feat(aibox): add DeepSeek reasoning mode support with tool calling on deepseek-v4-flash
- Add api.reasoning_enabled config (default false) to enable thinking mode - Uses deepseek-v4-flash native thinking capability (thinking param), supports tool calls while reasoning - Real-time reasoning content streaming via reasoning_start/reasoning/reasoning_end WS messages - Frontend shows reasoning in gray italic area, auto-folds long reasoning (>2000 chars) - Dynamic reasoning detection: shows reasoning even if model returns it without explicit config - Increase default API timeout to 120s for longer reasoning responses - Remove duplicate _add_assistant_message_with_reasoning method - Update docs: config example, message types table, v2.5 changelog
This commit is contained in:
1 parent
81ae84851d
commit
b79044d631
5 files changed
+125
-33
No files matched your search
+4
-2
@@ -60,7 +60,9 @@ BotOps/
|
|||||||
- 发送:`{"type":"message","content":...}` / `{"type":"command","command":"/..."}` / `{"type":"interrupt",...}`
|
- 发送:`{"type":"message","content":...}` / `{"type":"command","command":"/..."}` / `{"type":"interrupt",...}`
|
||||||
- 接收:
|
- 接收:
|
||||||
- `chunk`(**增量片段**):服务端 `chunk_buffer` 发送后即清零,前端直接 `append_ai` 拼接,为内容权威来源
|
- `chunk`(**增量片段**):服务端 `chunk_buffer` 发送后即清零,前端直接 `append_ai` 拼接,为内容权威来源
|
||||||
|
- `reasoning_start`(**思考开始**):创建灰色斜体思考区域,实时展示 AI 思考过程
|
||||||
|
- `reasoning`(**思考流**):思考内容增量片段,追加到思考区域(超长自动折叠显示最后 2000 字符)
|
||||||
|
- `reasoning_end`(**思考结束**):思考结束,切换到正式回答
|
||||||
- `complete`(**收尾信号**):chunk 流式已完整渲染,complete 仅用于收尾;仅在完全丢帧(未收到任何 chunk)时用 full_text 补建消息,**不再做全文替换对齐**(避免服务端递归调用工具后 complete 只含最后一轮内容导致重复渲染)
|
- `complete`(**收尾信号**):chunk 流式已完整渲染,complete 仅用于收尾;仅在完全丢帧(未收到任何 chunk)时用 full_text 补建消息,**不再做全文替换对齐**(避免服务端递归调用工具后 complete 只含最后一轮内容导致重复渲染)
|
||||||
- `line`(过程行):🔧 工具调用提示、工具输出、💬 助手前缀,路由到任务侧栏;助手前缀/思考提示在聊天区已由 AI 消息框承载,不重复展示
|
- `line`(过程行):🔧 工具调用提示、工具输出,路由到任务侧栏;助手前缀/思考提示在聊天区已由对应区域承载,不重复展示
|
||||||
- `reasoning`(思考流):仅服务端 debug_level≥3 发送,记入任务侧栏
|
|
||||||
- `dialogue_ended` / `dialogue_reset` / `task_added` / `task_process` / `task_status` / `task_error` / `interrupt_ack` / `error` / `info` / `command_result` / `connection_ack` / `notification` / `pong`
|
- `dialogue_ended` / `dialogue_reset` / `task_added` / `task_process` / `task_status` / `task_error` / `interrupt_ack` / `error` / `info` / `command_result` / `connection_ack` / `notification` / `pong`
|
||||||
+20
-7
@@ -58,6 +58,13 @@ class BotOpsApp(App):
|
|||||||
color: yellow;
|
color: yellow;
|
||||||
padding: 0 1;
|
padding: 0 1;
|
||||||
}
|
}
|
||||||
|
.msg-reasoning {
|
||||||
|
color: $text-muted;
|
||||||
|
background: $surface;
|
||||||
|
padding: 0 1;
|
||||||
|
margin: 0 1;
|
||||||
|
text-style: italic;
|
||||||
|
}
|
||||||
#status {
|
#status {
|
||||||
height: 1;
|
height: 1;
|
||||||
}
|
}
|
||||||
@@ -163,21 +170,27 @@ class BotOpsApp(App):
|
|||||||
if t == "chunk":
|
if t == "chunk":
|
||||||
# 服务端 chunk 为增量片段(发送后即清零),直接拼接
|
# 服务端 chunk 为增量片段(发送后即清零),直接拼接
|
||||||
await self.chat.append_ai(content)
|
await self.chat.append_ai(content)
|
||||||
|
elif t == "reasoning_start":
|
||||||
|
# 开始深度思考,创建思考区域
|
||||||
|
await self.chat.start_reasoning(content or "🤔 深度思考中...")
|
||||||
|
elif t == "reasoning":
|
||||||
|
# 思考内容增量
|
||||||
|
stripped = content
|
||||||
|
if stripped:
|
||||||
|
await self.chat.append_reasoning(stripped)
|
||||||
|
elif t == "reasoning_end":
|
||||||
|
# 思考结束
|
||||||
|
await self.chat.end_reasoning()
|
||||||
elif t == "line":
|
elif t == "line":
|
||||||
# 过程行(服务端 output_callback 原样透传):工具调用提示 / 工具输出 / 前缀
|
# 过程行(服务端 output_callback 原样透传):工具调用提示 / 工具输出 / 前缀
|
||||||
stripped = content.strip()
|
stripped = content.strip()
|
||||||
if not stripped:
|
if not stripped:
|
||||||
pass
|
pass
|
||||||
elif stripped.startswith(("💬 助手", "💬 Assistant", "🤔 思考中", "🤔 Thinking")):
|
elif stripped.startswith(("💬 助手", "💬 Assistant", "🤔 思考中", "🤔 Thinking", "🤔 深度思考中")):
|
||||||
pass # 助手前缀 / 思考提示:聊天区已有 AI 消息框,无需展示
|
pass # 助手前缀 / 思考提示:聊天区已有对应区域,无需展示
|
||||||
else:
|
else:
|
||||||
# 🔧 调用工具 / 工具输出 / 🤔 分析工具结果 等 → 任务侧栏
|
# 🔧 调用工具 / 工具输出 / 🤔 分析工具结果 等 → 任务侧栏
|
||||||
self.tasks.write(stripped)
|
self.tasks.write(stripped)
|
||||||
elif t == "reasoning":
|
|
||||||
# 思考流(服务端 debug_level>=3 才发送),记入任务侧栏
|
|
||||||
stripped = content.strip()
|
|
||||||
if stripped:
|
|
||||||
self.tasks.write(f"💭 {stripped[-200:]}")
|
|
||||||
elif t == "complete":
|
elif t == "complete":
|
||||||
# complete 携带完整全文,用于对齐已显示内容
|
# complete 携带完整全文,用于对齐已显示内容
|
||||||
await self.chat.finish_ai(content)
|
await self.chat.finish_ai(content)
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
"""聊天视图:用户/AI/系统消息 + AI 回复流式 Markdown 渲染。
|
"""聊天视图:用户/AI/系统消息 + AI 回复流式 Markdown 渲染。
|
||||||
|
|
||||||
服务端协议(aibox/aibox.py output_callback 原样透传 msg_type):
|
服务端协议(aibox/aibox.py output_callback 原样透传 msg_type):
|
||||||
- chunk 增量片段(服务端 chunk_buffer 发送后即清零),直接 append
|
- chunk 增量片段(正式回答内容),直接 append 到 AI 消息
|
||||||
|
- reasoning_start 思考开始信号,创建思考区域
|
||||||
|
- reasoning 思考内容增量片段,追加到思考区域
|
||||||
|
- reasoning_end 思考结束信号
|
||||||
- complete 收尾信号:chunk 流式是内容权威来源,complete 仅用于收尾;
|
- complete 收尾信号:chunk 流式是内容权威来源,complete 仅用于收尾;
|
||||||
仅当流式完全丢帧(未建 widget 且无内容)时,用 full_text 补建
|
仅当流式完全丢帧(未建 widget 且无内容)时,用 full_text 补建
|
||||||
"""
|
"""
|
||||||
@@ -20,7 +23,9 @@ class ChatView(VerticalScroll):
|
|||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._ai_widget: Markdown | None = None
|
self._ai_widget: Markdown | None = None
|
||||||
|
self._reasoning_widget: Static | None = None
|
||||||
self._ai_text = ""
|
self._ai_text = ""
|
||||||
|
self._reasoning_text = ""
|
||||||
self._ai_finalized = True # 初始无活跃 AI 消息
|
self._ai_finalized = True # 初始无活跃 AI 消息
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -49,6 +54,39 @@ class ChatView(VerticalScroll):
|
|||||||
await self.mount(self._ai_widget)
|
await self.mount(self._ai_widget)
|
||||||
self._anchor_bottom()
|
self._anchor_bottom()
|
||||||
|
|
||||||
|
async def start_reasoning(self, hint: str = "🤔 思考中..."):
|
||||||
|
"""开始展示思考过程区域。"""
|
||||||
|
if self._reasoning_widget is not None:
|
||||||
|
return
|
||||||
|
self._reasoning_text = ""
|
||||||
|
self._reasoning_widget = Static(hint + "\n", classes="msg-reasoning", markup=False)
|
||||||
|
await self.mount(self._reasoning_widget)
|
||||||
|
self._anchor_bottom()
|
||||||
|
|
||||||
|
async def append_reasoning(self, delta: str):
|
||||||
|
"""追加思考内容增量。"""
|
||||||
|
if not delta:
|
||||||
|
return
|
||||||
|
if self._reasoning_widget is None:
|
||||||
|
await self.start_reasoning()
|
||||||
|
self._reasoning_text += delta
|
||||||
|
# 限制思考内容显示长度(最多显示最后 2000 字符,避免思考过长占满屏幕)
|
||||||
|
display = self._reasoning_text
|
||||||
|
if len(display) > 2000:
|
||||||
|
display = "...(前略)\n" + display[-2000:]
|
||||||
|
self._reasoning_widget.update(f"💭 思考中...\n{display}")
|
||||||
|
self.call_after_refresh(self.scroll_end, animate=False)
|
||||||
|
|
||||||
|
async def end_reasoning(self):
|
||||||
|
"""结束思考区域,更新提示文字。"""
|
||||||
|
if self._reasoning_widget is not None and self._reasoning_text:
|
||||||
|
# 思考结束后保持展示,但更新标签
|
||||||
|
display = self._reasoning_text
|
||||||
|
if len(display) > 2000:
|
||||||
|
display = "...(前略)\n" + display[-2000:]
|
||||||
|
self._reasoning_widget.update(f"💭 思考过程({len(self._reasoning_text)}字符)\n{display}\n{'─' * 30}")
|
||||||
|
# 思考区域保留显示,不删除
|
||||||
|
|
||||||
async def append_ai(self, delta: str):
|
async def append_ai(self, delta: str):
|
||||||
"""追加增量片段(服务端 chunk 为增量语义,直接拼接)。"""
|
"""追加增量片段(服务端 chunk 为增量语义,直接拼接)。"""
|
||||||
if not delta:
|
if not delta:
|
||||||
@@ -97,12 +135,16 @@ class ChatView(VerticalScroll):
|
|||||||
self._anchor_bottom()
|
self._anchor_bottom()
|
||||||
|
|
||||||
self._ai_text = ""
|
self._ai_text = ""
|
||||||
|
self._reasoning_widget = None
|
||||||
|
self._reasoning_text = ""
|
||||||
self._ai_finalized = True
|
self._ai_finalized = True
|
||||||
self.call_after_refresh(self.scroll_end, animate=False)
|
self.call_after_refresh(self.scroll_end, animate=False)
|
||||||
|
|
||||||
async def reset(self):
|
async def reset(self):
|
||||||
"""清空聊天区(/clear)。"""
|
"""清空聊天区(/clear)。"""
|
||||||
self._ai_widget = None
|
self._ai_widget = None
|
||||||
|
self._reasoning_widget = None
|
||||||
self._ai_text = ""
|
self._ai_text = ""
|
||||||
|
self._reasoning_text = ""
|
||||||
self._ai_finalized = True
|
self._ai_finalized = True
|
||||||
await self.remove_children()
|
await self.remove_children()
|
||||||
+19
-4
@@ -215,9 +215,11 @@ const ws = new WebSocket('ws://localhost:8765');
|
|||||||
| 类型 | 说明 |
|
| 类型 | 说明 |
|
||||||
|-----|------|
|
|-----|------|
|
||||||
| `chunk` | AI 响应的**增量片段**(流式输出,chunk_buffer 发送后即清零,为内容权威来源) |
|
| `chunk` | AI 响应的**增量片段**(流式输出,chunk_buffer 发送后即清零,为内容权威来源) |
|
||||||
|
| `reasoning_start` | AI 开始思考信号(思考模式,创建思考区域展示) |
|
||||||
|
| `reasoning` | AI 思考过程增量片段(流式输出,灰色/斜体样式) |
|
||||||
|
| `reasoning_end` | AI 思考结束信号(切换到正式回答) |
|
||||||
| `complete` | AI 响应**收尾信号**(chunk 流式是内容权威来源,complete 仅用于收尾;完全丢帧时可用 full_text 补建) |
|
| `complete` | AI 响应**收尾信号**(chunk 流式是内容权威来源,complete 仅用于收尾;完全丢帧时可用 full_text 补建) |
|
||||||
| `line` | 过程行(🔧 工具调用提示、工具输出、💬 助手前缀、思考提示等,供任务侧栏/终端显示) |
|
| `line` | 过程行(🔧 工具调用提示、工具输出、💬 助手前缀等,供任务侧栏/终端显示) |
|
||||||
| `reasoning` | AI 思考过程(思考模式,仅 debug_level≥3 发送) |
|
|
||||||
| `error` | 错误信息(API 请求失败、解析失败等;服务端自动回滚本轮消息防止对话历史被污染) |
|
| `error` | 错误信息(API 请求失败、解析失败等;服务端自动回滚本轮消息防止对话历史被污染) |
|
||||||
| `command_result` | 命令执行结果 |
|
| `command_result` | 命令执行结果 |
|
||||||
| `task_status` | 任务状态更新(executing/complete/failed) |
|
| `task_status` | 任务状态更新(executing/complete/failed) |
|
||||||
@@ -427,8 +429,9 @@ AI 可以通过 `update_soul` 工具动态更新 `99_SOUL.md`,通过 `update_i
|
|||||||
"api": {
|
"api": {
|
||||||
"deepseek_api_url": "https://api.deepseek.com/chat/completions",
|
"deepseek_api_url": "https://api.deepseek.com/chat/completions",
|
||||||
"deepseek_model": "deepseek-v4-flash",
|
"deepseek_model": "deepseek-v4-flash",
|
||||||
|
"reasoning_enabled": false,
|
||||||
"api_key_env": "DEEPSEEK_API_KEY",
|
"api_key_env": "DEEPSEEK_API_KEY",
|
||||||
"timeout": 30,
|
"timeout": 120,
|
||||||
"temperature": 0.7
|
"temperature": 0.7
|
||||||
},
|
},
|
||||||
"context": {
|
"context": {
|
||||||
@@ -492,7 +495,9 @@ AI 可以通过 `update_soul` 工具动态更新 `99_SOUL.md`,通过 `update_i
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 默认模型为 `deepseek-v4-flash`(通过 `api.deepseek_model` 修改)。API Key 从环境变量 `DEEPSEEK_API_KEY` 读取(亦支持 `~/.cert/deepseek.key` 文件)。
|
> 默认模型为 `deepseek-v4-flash`(通过 `api.deepseek_model` 修改)。设置 `api.reasoning_enabled: true` 可启用思考模式,此时会在请求中添加 `thinking: {type: "enabled"}` 参数,模型会先进行思考再回答,实时展示思考过程(灰色斜体区域),回答质量更高且**支持工具调用**(文件操作、命令执行、记忆搜索等工具均可在思考模式下正常使用)。
|
||||||
|
>
|
||||||
|
> API Key 从环境变量 `DEEPSEEK_API_KEY` 读取(亦支持 `~/.cert/deepseek.key` 文件)。
|
||||||
|
|
||||||
## 🛠️ 命令行参数
|
## 🛠️ 命令行参数
|
||||||
|
|
||||||
@@ -701,6 +706,16 @@ elif command == "/mycommand":
|
|||||||
|
|
||||||
## 📄 更新日志
|
## 📄 更新日志
|
||||||
|
|
||||||
|
### v2.5
|
||||||
|
- ✅ **新增 DeepSeek 思考模式支持**(Reasoning Mode):
|
||||||
|
- 新增 `api.reasoning_enabled` 配置项(默认 `false`),启用后在请求中添加 `thinking: {type: "enabled"}` 参数
|
||||||
|
- 使用 `deepseek-v4-flash` 模型原生思考能力,**思考模式下完整支持工具调用**(文件操作、命令执行、记忆搜索等均可正常使用)
|
||||||
|
- 实时展示 AI 思考过程:新增 `reasoning_start`/`reasoning`/`reasoning_end` WebSocket 消息类型
|
||||||
|
- 思考内容在前端以灰色斜体区域独立展示,超长思考自动折叠显示最后 2000 字符
|
||||||
|
- 即使未启用思考模式,若模型返回 `reasoning_content` 也会自动实时展示
|
||||||
|
- API 超时默认从 30s 提高到 120s,适配思考模式更长的响应时间
|
||||||
|
- ✅ 删除重复定义的 `_add_assistant_message_with_reasoning` 方法
|
||||||
|
|
||||||
### v2.4
|
### v2.4
|
||||||
- ✅ **新增专用工作目录规范**:
|
- ✅ **新增专用工作目录规范**:
|
||||||
- AI 主动创建的临时文件、脚本、数据文件默认写入 `~/.aibox/workspace/`,避免污染系统其他目录
|
- AI 主动创建的临时文件、脚本、数据文件默认写入 `~/.aibox/workspace/`,避免污染系统其他目录
|
||||||
|
|||||||
+39
-19
@@ -1168,8 +1168,9 @@ class ConfigManager:
|
|||||||
"api": {
|
"api": {
|
||||||
"deepseek_api_url": "https://api.deepseek.com/chat/completions",
|
"deepseek_api_url": "https://api.deepseek.com/chat/completions",
|
||||||
"deepseek_model": "deepseek-v4-flash",
|
"deepseek_model": "deepseek-v4-flash",
|
||||||
|
"reasoning_enabled": false,
|
||||||
"api_key_env": "DEEPSEEK_API_KEY",
|
"api_key_env": "DEEPSEEK_API_KEY",
|
||||||
"timeout": 30,
|
"timeout": 120,
|
||||||
"temperature": 0.7
|
"temperature": 0.7
|
||||||
},
|
},
|
||||||
"context": {
|
"context": {
|
||||||
@@ -1356,7 +1357,11 @@ class Constants:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def DEEPSEEK_MODEL(cls):
|
def DEEPSEEK_MODEL(cls):
|
||||||
return cls._get_config().get("api.deepseek_model")
|
return cls._get_config().get("api.deepseek_model", "deepseek-v4-flash")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def REASONING_ENABLED(cls):
|
||||||
|
return cls._get_config().get("api.reasoning_enabled", False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def DEFAULT_TIMEOUT(cls):
|
def DEFAULT_TIMEOUT(cls):
|
||||||
@@ -7169,11 +7174,13 @@ class DeepSeekChat:
|
|||||||
"stream": True
|
"stream": True
|
||||||
}
|
}
|
||||||
|
|
||||||
# 可选:添加 thinking 模式配置(如果有)
|
# 思考模式:启用 thinking 参数
|
||||||
|
if constants.REASONING_ENABLED:
|
||||||
payload["thinking"] = {
|
payload["thinking"] = {
|
||||||
"type": "enabled"
|
"type": "enabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 工具调用(v4-flash 支持思考+工具调用)
|
||||||
tools = self.tool_registry.get_tools_schemas()
|
tools = self.tool_registry.get_tools_schemas()
|
||||||
if tools:
|
if tools:
|
||||||
payload["tools"] = tools
|
payload["tools"] = tools
|
||||||
@@ -7182,10 +7189,16 @@ class DeepSeekChat:
|
|||||||
current_time = datetime.now().strftime("%H:%M:%S")
|
current_time = datetime.now().strftime("%H:%M:%S")
|
||||||
if output_callback:
|
if output_callback:
|
||||||
output_callback("line", f"\n{i18n.get('thinking', current_time)}\n")
|
output_callback("line", f"\n{i18n.get('thinking', current_time)}\n")
|
||||||
|
if constants.REASONING_ENABLED:
|
||||||
|
output_callback("reasoning_start", "🤔 思考中...")
|
||||||
|
else:
|
||||||
|
# 普通模式先显示助手前缀
|
||||||
output_callback("line", i18n.get('assistant_prefix'))
|
output_callback("line", i18n.get('assistant_prefix'))
|
||||||
|
|
||||||
full_response = ""
|
full_response = ""
|
||||||
full_reasoning = "" # 存储思考内容
|
full_reasoning = "" # 存储思考内容
|
||||||
|
reasoning_started = False
|
||||||
|
reasoning_ended = False
|
||||||
tool_calls_buffer = []
|
tool_calls_buffer = []
|
||||||
current_tool_calls = {}
|
current_tool_calls = {}
|
||||||
|
|
||||||
@@ -7236,10 +7249,25 @@ class DeepSeekChat:
|
|||||||
if 'reasoning_content' in delta and delta['reasoning_content']:
|
if 'reasoning_content' in delta and delta['reasoning_content']:
|
||||||
reasoning = delta['reasoning_content']
|
reasoning = delta['reasoning_content']
|
||||||
full_reasoning += reasoning
|
full_reasoning += reasoning
|
||||||
# 可选:将思考内容也发送给前端(可以单独处理)
|
|
||||||
if output_callback and self.debug_level >= 3:
|
# 发送思考开始信号(仅第一次,且未提前发送过)
|
||||||
|
if not reasoning_started and output_callback:
|
||||||
|
if not constants.REASONING_ENABLED:
|
||||||
|
# 非显式思考模式但模型返回了思考内容,动态发送开始信号
|
||||||
|
output_callback("reasoning_start", "🤔 思考中...")
|
||||||
|
reasoning_started = True
|
||||||
|
|
||||||
|
# 实时发送思考内容给前端(无需debug_level限制)
|
||||||
|
if output_callback:
|
||||||
output_callback("reasoning", reasoning)
|
output_callback("reasoning", reasoning)
|
||||||
|
|
||||||
|
# 思考结束:当开始收到content且之前有reasoning时,发送结束信号
|
||||||
|
if 'content' in delta and delta['content'] and reasoning_started and not reasoning_ended:
|
||||||
|
reasoning_ended = True
|
||||||
|
if output_callback:
|
||||||
|
output_callback("reasoning_end", "")
|
||||||
|
output_callback("line", i18n.get('assistant_prefix'))
|
||||||
|
|
||||||
# 处理正常内容
|
# 处理正常内容
|
||||||
if 'content' in delta and delta['content']:
|
if 'content' in delta and delta['content']:
|
||||||
content = delta['content']
|
content = delta['content']
|
||||||
@@ -7290,7 +7318,12 @@ class DeepSeekChat:
|
|||||||
# 处理工具调用
|
# 处理工具调用
|
||||||
if current_tool_calls:
|
if current_tool_calls:
|
||||||
tool_calls_buffer = list(current_tool_calls.values())
|
tool_calls_buffer = list(current_tool_calls.values())
|
||||||
if output_callback:
|
|
||||||
|
# 如果之前在思考,先结束思考状态
|
||||||
|
if reasoning_started and not reasoning_ended and output_callback:
|
||||||
|
output_callback("reasoning_end", "")
|
||||||
|
output_callback("line", i18n.get('calling_tools') + "\n")
|
||||||
|
elif output_callback:
|
||||||
output_callback("line", i18n.get('calling_tools') + "\n")
|
output_callback("line", i18n.get('calling_tools') + "\n")
|
||||||
|
|
||||||
# 【关键修复1】先添加助手消息,包含 tool_calls
|
# 【关键修复1】先添加助手消息,包含 tool_calls
|
||||||
@@ -7388,19 +7421,6 @@ class DeepSeekChat:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"消息回滚失败: {e}")
|
self.logger.error(f"消息回滚失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def _add_assistant_message_with_reasoning(self, content: str, reasoning_content: str = None, tool_calls: List = None):
|
|
||||||
"""添加助手消息,包含 reasoning_content"""
|
|
||||||
msg = {"role": "assistant"}
|
|
||||||
if content:
|
|
||||||
msg["content"] = content
|
|
||||||
if reasoning_content:
|
|
||||||
msg["reasoning_content"] = reasoning_content
|
|
||||||
if tool_calls:
|
|
||||||
msg["tool_calls"] = tool_calls
|
|
||||||
msg["content"] = None
|
|
||||||
self.messages.append(msg)
|
|
||||||
|
|
||||||
def reset_conversation(self, reload_prompts: bool = True):
|
def reset_conversation(self, reload_prompts: bool = True):
|
||||||
"""
|
"""
|
||||||
重置对话状态 - 清除所有对话记忆,可选择是否重新加载系统提示词
|
重置对话状态 - 清除所有对话记忆,可选择是否重新加载系统提示词
|
||||||
|
|||||||
Reference in new issue
Block a user