feat: AI 控制台会话化 + 视觉优化——①多轮对话连续性(后端 history 持久化 12 轮,Agent 注入历史上下文,DeepSeek 式会话:新建会话才清空);②聊天区改浅色(DeepSeek 风格,图片文字清晰);③截图点击放大查看

This commit is contained in:
2026-09-04 13:18:36 +08:00
parent e24458a085
commit ce4e5464b9
4 changed files with 99 additions and 27 deletions
+27 -4
View File
@@ -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}")