feat: AI 控制台会话化 + 视觉优化——①多轮对话连续性(后端 history 持久化 12 轮,Agent 注入历史上下文,DeepSeek 式会话:新建会话才清空);②聊天区改浅色(DeepSeek 风格,图片文字清晰);③截图点击放大查看
This commit is contained in:
+27
-4
@@ -38,7 +38,8 @@ _CFG_KEYS = {"api_base": "agent_api_base",
|
||||
|
||||
# ---------- 运行状态(单实例 + 事件队列) ----------
|
||||
_run = {"id": None, "state": "idle", "prompt": "", "serial": "",
|
||||
"answer": "", "error": ""}
|
||||
"answer": "", "error": "",
|
||||
"history": []} # 多轮对话历史 [{role: user|assistant, content}]
|
||||
_queues = {} # run_id -> queue.Queue(SSE 消费者读取)
|
||||
_lock = threading.Lock()
|
||||
|
||||
@@ -91,6 +92,7 @@ def agent_run():
|
||||
prompt = (data.get("prompt") or "").strip()
|
||||
if not prompt:
|
||||
return jsonify({"ok": False, "error": "请输入指令"}), 400
|
||||
serial = (data.get("serial") or "").strip()
|
||||
cfg = _read_cfg()
|
||||
if not cfg.get("api_key"):
|
||||
return jsonify({"ok": False, "error": "请先在配置区填写 API Key"}), 400
|
||||
@@ -103,9 +105,11 @@ def agent_run():
|
||||
_run.update(id=run_id, state="running", prompt=prompt,
|
||||
serial=(data.get("serial") or "").strip(),
|
||||
answer="", error="")
|
||||
# history 保留(同会话多轮对话),由前端「清空对话」调用 clear 重置
|
||||
_queues[run_id] = queue.Queue()
|
||||
_log.info(f"Agent 启动: {prompt[:60]}")
|
||||
threading.Thread(target=_agent_thread, args=(run_id, prompt, cfg),
|
||||
threading.Thread(target=_agent_thread,
|
||||
args=(run_id, prompt, serial, cfg),
|
||||
daemon=True).start()
|
||||
return jsonify({"ok": True, "run_id": run_id})
|
||||
|
||||
@@ -139,6 +143,15 @@ def agent_stream():
|
||||
"X-Accel-Buffering": "no"})
|
||||
|
||||
|
||||
@bp.route("/api/agent/clear", methods=["POST"])
|
||||
@admin_required
|
||||
def agent_clear():
|
||||
"""清空对话历史。"""
|
||||
with _lock:
|
||||
_run["history"] = []
|
||||
return jsonify({"ok": True, "msg": "已清空"})
|
||||
|
||||
|
||||
def _shrink_image(b64, width=220, quality=50):
|
||||
"""截图降采样(SSE step 事件用,控制传输体积)。失败原样返回。"""
|
||||
try:
|
||||
@@ -153,7 +166,7 @@ def _shrink_image(b64, width=220, quality=50):
|
||||
return b64
|
||||
|
||||
|
||||
def _agent_thread(run_id, prompt, cfg):
|
||||
def _agent_thread(run_id, prompt, serial, cfg):
|
||||
"""后台线程:Agent 流式执行,事件推入队列供 SSE 消费。"""
|
||||
q = _queues.get(run_id)
|
||||
try:
|
||||
@@ -177,9 +190,14 @@ def _agent_thread(run_id, prompt, cfg):
|
||||
agent.s.api_key = cfg.get("api_key") or agent.s.api_key
|
||||
agent.s.default_serial = cfg.get("default_serial") or agent.s.default_serial
|
||||
|
||||
with _lock:
|
||||
history = list(_run.get("history") or [])
|
||||
target = serial or cfg.get("default_serial") or ""
|
||||
|
||||
async def _execute():
|
||||
await agent._load_tools()
|
||||
return await agent.run_stream(prompt, cfg.get("default_serial") or "",
|
||||
return await agent.run_stream(prompt, target,
|
||||
history=history,
|
||||
on_delta=on_delta, on_tool=on_tool)
|
||||
|
||||
# 整体超时保护:卡死时结束,释放单实例
|
||||
@@ -187,6 +205,11 @@ def _agent_thread(run_id, prompt, cfg):
|
||||
with _lock:
|
||||
_run["state"] = "done"
|
||||
_run["answer"] = answer
|
||||
# 追加本轮进历史(多轮连续性;上限 12 轮防 token 膨胀)
|
||||
hist = _run.setdefault("history", [])
|
||||
hist.append({"role": "user", "content": prompt[:2000]})
|
||||
hist.append({"role": "assistant", "content": (answer or "")[:4000]})
|
||||
_run["history"] = hist[-24:]
|
||||
q.put(("done", {"answer": answer}))
|
||||
except Exception as e:
|
||||
_log.warning(f"Agent 运行异常: {e}")
|
||||
|
||||
Reference in New Issue
Block a user