QQPilot 系列机器人的简化版聊天引擎:一个 OpenAI 兼容的中转站,
内部跑完整流水线,QQPilot无需改动,把 server_url 指向本服务即可接入。
QQPilot (C#) ──POST /v1/chat/completions──▶ entry.py(Flask 中转站,端口 7749)
▲ │
│ 需要回复:getAnswer() 走流水线 │
└─────────── OpenAI 格式响应 ◀──────────────┘
流水线(对应 config.xml 的 4 个模型组):
| 阶段 | 模块 | 作用 |
|---|---|---|
| 1 | EcoReasoning |
判断是否需要回复(双通道:模型支持工具则调用 decide_should_reply 工具;否则提示词引导输出 {"reply": true/false},引擎内部解析,失败保守回复);不需要 → 拖到 QQPilot 超时(默认 300s) |
| 2 | clumsyImitation |
基于 system 字段 + 机器人历史发言,生成更贴风格的 system 提示词 |
| 3 | forgetfulMem |
回复前从 SQLite 提取相关记忆注入 system;回复后写入本轮对话 |
| 4 | Xreply |
正式回复(vision 模型支持图片输入,data: URL / 本地路径均可) |
判断是否需要回复的提示词与工具定义都集中在
defaultPattern.py(patternEcoSystem/patternEcoUser/ecoReasoningTool)。 模型配置<tools>True</tools>时启用工具通道;不支持工具的模型/端点会自动回退到文本引导。
思考型模型(qwen3.5 等)的 thinking 只能通过 Ollama 原生 API(/api/chat) 的 think:false 关闭——
OpenAI 兼容端点(/v1/chat/completions)该参数无效,模型会先输出 reasoning,慢且占 max_tokens。
引擎按 <url> 自动选择调用方式(也可用 <api> 显式指定):
<url> |
默认 API | 说明 |
|---|---|---|
ollama |
native(/api/chat) |
think:false 生效,速度快 |
http(s)://... |
openai(/v1/chat/completions) |
兼容任意 OpenAI 端点 |
示例(显式指定走原生 API 并关闭思考):
<model>
<url>ollama</url>
<name>qwen3.5:0.8b</name>
<api>native</api>
</model>config.py—— 解析config.xml(4 模型组 + 通用设置,Sequntial/random选模型)chatContent.py——ChatContent数据类(消息文本格式与 QQPilot4 一致)extract.py—— 把聊天日志(用户名: MM-dd HH:mm:ss+ 内容 +<img src>)解析为ChatContentanswer.py—— 核心流水线:getAnswer(text: List[ChatContent], systemPrompt='auto') -> Optional[str]memory.py—— SQLite 记忆存取(forgetfulMem)entry.py—— Flask 中转站(OpenAI 兼容端点/v1/chat/completions)defaultPattern.py—— 消息输入/输出格式模板test.py/test.json—— 测试
git clone https://github.com/QQPilotOrganization/SimplifiedChatEngine.git
cd SimplifiedChatEngine
#确保你安装了python.
pip install -r requirements.txt
python entry.py在 QQPilot 的 config.ini 中设置:
server_url = http://localhost:7749/v1
api_key = 任意值from answer import getAnswer
from chatContent import ChatContent
contents = [ChatContent("User1", [], "你好", "08-10 17:19:57", False)]
reply = getAnswer(contents, systemPrompt="你的名字是 neko,只输出发言内容")
# reply: 回复文本;None 表示判定无需回复日志解析:
from extract import extract
contents = extract(chat_log_str, character_name="neko") # character_name 用于识别自己的消息<general><timeout>:判定无需回复时的等待秒数(对应 QQPilotremote_server_timeout,默认 300)<general><maxImageCount>:单次回复最多携带图片数(默认 12)<general><apiKey>:远程端点的 API Key(本地 Ollama 不用填)<general><memoryDb>:SQLite 记忆库路径(默认memories.db)- 每个模型组:
<select>(Sequntial顺序轮询 /random随机)、多个<model>(url为ollama或 http base_url,name模型名,tools/vision开关)、<inject>额外请求字段(如{"think": false})
python entry.py # 终端 1:启动引擎
python test.py # 终端 2:发送 test.json(含图片对话)
python test.py "现在几点了" # 或发送一条简单消息