外观
llm-chat-server
面向电话对话的统一服务。它既提供基于 profile 的无状态流式 Chat,也提供与 Chat 节点完全独立的确定性 conversation strategy。
默认监听 9931,接口如下:
GET /healthGET /api/v1/chat/capabilitiesPOST /api/v1/chat/stream,以 SSE 返回delta、complete、errorGET /api/v1/conversation/capabilitiesPOST /api/v1/conversation,返回统一 JSON 结果
除健康检查外,配置了 server.authToken 时需发送 X-Callout-Internal-Token。 未注册的路径或错误 HTTP 方法不执行鉴权,统一返回 404 与 { "ok": false, "error": "接口不存在" }。
Conversation strategy
策略注册表位于 src/conversation-registry.ts。当前注册 kb-mock,它不注册为 chat profile、不进入 Chat 节点、不保存会话状态,也不调用 Ollama 或 TTS。
初始化请求:
json
{ "strategy": "kb-mock", "action": "start", "sessionId": "call-uuid" }响应中的固定话术为:
json
{
"ok": true,
"data": {
"openingPrompt": "您好,请问有什么可以帮您?",
"errorPrompt": "抱歉,系统暂时没有找到相关内容,请您换个说法再试试。"
}
}查询请求:
json
{ "strategy": "kb-mock", "action": "query", "sessionId": "call-uuid", "text": " 你好 " }响应严格回显去除首尾空白后的用户原话,且不会主动挂机:
json
{ "ok": true, "data": { "answerText": "知识库模拟回答:你好", "hangup": false } }非法 JSON、未知策略/action、空 sessionId 或空查询文本返回 HTTP 400;鉴权失败 返回 401。GET /api/v1/conversation/capabilities 只暴露策略 key、名称和说明。
运行
在仓库根目录运行:
bash
bun run dev:llm-chat或进入本目录运行 bun run dev、bun run start、bun run typecheck、bun run build、bun run build:all。
配置
开发态默认读取当前工作目录下的 config.json;独立可执行文件优先读取可执行文件同目录的 config.json。也可通过 LLM_CHAT_CONFIG_PATH 显式指定配置文件。
json
{
"server": {
"host": "0.0.0.0",
"port": 9931,
"authToken": ["chat-token"]
},
"llm": {
"ollamaUrl": "http://127.0.0.1:11434/api/chat",
"model": "qwen3.5:2b",
"timeoutMs": 30000
},
"logging": {
"dir": "logs",
"level": "info",
"maxSize": "20m",
"maxFiles": "14d",
"detailedContentEnabled": true
}
}环境变量优先于配置文件:
| 环境变量 | 覆盖字段 |
|---|---|
LLM_CHAT_CONFIG_PATH | 配置文件路径 |
LLM_CHAT_HOST / LLM_CHAT_PORT | server.host / server.port |
LLM_CHAT_AUTH_TOKEN | server.authToken,支持逗号分隔多个 token |
LLM_CHAT_OLLAMA_URL / LLM_CHAT_MODEL / LLM_CHAT_TIMEOUT_MS | Ollama 地址、模型与单轮总超时 |
LLM_CHAT_LOG_DIR / LLM_CHAT_LOG_LEVEL | 日志目录与级别 |
LLM_CHAT_LOG_MAX_SIZE / LLM_CHAT_LOG_MAX_FILES | 滚动文件大小与保留周期 |
LLM_CHAT_DETAILED_CONTENT_LOG_ENABLED | logging.detailedContentEnabled;支持 true/false、1/0、yes/no、on/off |
日志
服务向控制台和 logs/application-YYYY-MM-DD.log 写入单行结构化日志,文件按日滚动。每个 POST /api/v1/chat/stream 都会生成内部 requestId,用于关联以下事件:
| 事件 | 主要字段 |
|---|---|
request | requestId、method、path、status、durationMs、profile、turn、messageCount、branchCount、finalEventType |
ollama-request | requestId、phase、model;详细模式增加完整 payload |
ollama-response | requestId、phase、model、status、durationMs;回复生成阶段包含 usage,出口判断阶段包含 outcome / exitKey 摘要 |
ollama-error | requestId、phase、model、status、durationMs、type、message;错误类型区分 timeout、client-abort、http、network、parse、validation |
phase 为 reply-generation 或 exit-judgment。前者记录流式 Ollama NDJSON、拼接后的回复和 token 统计;后者记录原始响应 body、模型 content 与出口判断摘要。request.durationMs 覆盖完整 SSE 生命周期,finalEventType 标记最终的 complete、error 或 client-abort;详细模式还记录请求 body 和最终 complete / error 数据。
默认开启详细内容日志(logging.detailedContentEnabled=true)。它会记录客户对话、服务端 system prompt、流程分支说明及模型输出,生产环境应根据隐私和数据保留要求评估;如不允许这些内容落盘,可设置:
bash
LLM_CHAT_DETAILED_CONTENT_LOG_ENABLED=false关闭后不会记录 messages、prompt、客户话术、reply、原始响应或完整 payload,但仍保留关联 ID、阶段、模型、HTTP 状态、耗时、错误分类、usage 以及 outcome / exitKey 等排障摘要。任何模式都不记录请求头、鉴权 token 或 URL 查询参数。logger 或文件 transport 写入失败不会改变 SSE 输出和客户端取消逻辑。
本服务不收集 NLU 的 JSONL 微调数据;上述内容只进入常规滚动运行日志。
conversation 请求的摘要日志只记录 strategy 与 action。请求中的 sessionId、 用户文本和响应正文仅在 logging.detailedContentEnabled=true 时记录。