feat(open-chat): 新增 /api/open/chat 开放问答接口

- 无需登录(/api/open/ 加入 auth 白名单 + CSRF 豁免),供外部系统直接调用本项目智能体做问答
- 可指定模型(model_name)与智能体(agent_name 中文名称,扫描 agents/*/config.yaml 解析为运行 id);GET /api/open/agents 列出可选名称
- 只返回最终结果(answer = 最后一段 markdown),不含中间过程/工具调用
- 可靠关闭思考:thinking_enabled=false 时下发 thinking_force_disabled,经 create_chat_model(force_disable_thinking=True) 强制注入 enable_thinking=false(及 GLM thinking.type=disabled),覆盖只声明 supports_thinking 的内网 vLLM/Qwen 模型(与生成标题关思考一致)
- 一次性问答设 is_scheduled_run 跳过自动起标题

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-22 11:21:56 +08:00
1 parent 593daa91ec
commit 2b6424b3ff
9 files changed
+337 -4

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
"""开放问答接口 /api/open/chat 测试脚本(Jupyter 版)。
接口只返回「最终结果」:智能体把调研 / 工具调用全部跑完后,只把最后那段
文本(markdown)放在 answer 字段里返回 —— 不含中间过程、工具调用、思考。
用法:在 Jupyter 里把下面几段按顺序运行即可。
- 「配置」段:改成你要的模型 / 智能体 / 问题 / 是否思考
- 「调用」段:运行后 answer 变量就是最终 md 文本
无第三方依赖(纯标准库 urllib)。
"""
import json
import time
import urllib.error
import urllib.request
# ====================== 配置(按需修改这里) ======================
BASE_URL = "http://47.94.209.59:2026" # 后端地址(走 nginx 用 :2026,Gateway 直连用 :8001)
MESSAGE = "帮我调研一下 XXX,输出 markdown 报告。" # 要问的问题
MODEL_NAME = None # 模型名(config.yaml models[].name);None=默认模型
AGENT_NAME = None # 智能体中文名称;None=默认 lead agent。不确定填啥就先跑下面的「列出智能体」
THINKING_ENABLED = False # False=关闭思考(内网模型也会被强制关闭);True=开启
TIMEOUT = 600 # 请求超时(秒)
# ===============================================================
def open_chat(message, model_name=None, agent_name=None, thinking_enabled=False,
base_url=BASE_URL, timeout=TIMEOUT):
"""调用 /api/open/chat,返回最终 md 文本(只要结果,不要过程)。"""
url = base_url.rstrip("/") + "/api/open/chat"
payload = {
"message": message,
"model_name": model_name,
"agent_name": agent_name, # 按中文名称选智能体
"thinking_enabled": thinking_enabled,
}
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(
url,
data=data,
headers={"Content-Type": "application/json; charset=utf-8"},
method="POST",
)
with urllib.request.urlopen(req, timeout=timeout) as resp:
result = json.loads(resp.read().decode("utf-8"))
return result["answer"] # 只返回最终结果
# ====================== (可选)列出可用智能体名称 ======================
# 不知道 AGENT_NAME 填什么时,先跑这段看有哪些中文名:
# import urllib.request, json
# with urllib.request.urlopen(BASE_URL.rstrip("/") + "/api/open/agents", timeout=30) as r:
# for a in json.loads(r.read().decode("utf-8"))["agents"]:
# print(a["name"])
# ====================== 调用 ======================
_t0 = time.time()
answer = open_chat(MESSAGE, MODEL_NAME, AGENT_NAME, THINKING_ENABLED)
print(f"(耗时 {time.time() - _t0:.1f}s)\n")
print(answer) # answer 就是最终 markdown 文本
# ====================== (可选)在 Jupyter 里渲染成 markdown ======================
# from IPython.display import Markdown, display
# display(Markdown(answer))
# ====================== (可选)存成 .md 文件 ======================
# with open("result.md", "w", encoding="utf-8") as f:
# f.write(answer)