优化工具调用格式解析与后端工具调用日志保存逻辑,同时增强列表工具的返回内容展示
All checks were successful
Deploy Noval to K3s / deploy (push) Successful in 52s
All checks were successful
Deploy Noval to K3s / deploy (push) Successful in 52s
This commit is contained in:
@@ -115,19 +115,23 @@ def _sse(data: dict) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _save_assistant_message(novel_id: int | None, full_response: str, tool_call_logs: list[str]):
|
def _save_assistant_message(novel_id: int | None, full_response: str, tool_call_logs: list[str]):
|
||||||
"""保存 AI 回复到 DB(含工具调用摘要)。在 finally 中调用,确保断连也能保存。"""
|
"""保存 AI 回复到 DB。工具调用日志和回复文本分别存为独立记录。"""
|
||||||
save_content = full_response
|
with Session(engine) as s:
|
||||||
|
# 工具调用日志作为单独一条记录
|
||||||
if tool_call_logs:
|
if tool_call_logs:
|
||||||
tool_summary = "\n".join(tool_call_logs)
|
tool_summary = "\n".join(tool_call_logs)
|
||||||
save_content = f"[以下操作已执行]\n{tool_summary}\n\n{full_response}"
|
s.add(ChatMessage(
|
||||||
if save_content.strip():
|
|
||||||
with Session(engine) as s:
|
|
||||||
ai_msg = ChatMessage(
|
|
||||||
novel_id=novel_id,
|
novel_id=novel_id,
|
||||||
role="assistant",
|
role="assistant",
|
||||||
content=save_content,
|
content=f"[以下操作已执行]\n{tool_summary}",
|
||||||
)
|
))
|
||||||
s.add(ai_msg)
|
# AI 回复文本作为单独一条记录
|
||||||
|
if full_response.strip():
|
||||||
|
s.add(ChatMessage(
|
||||||
|
novel_id=novel_id,
|
||||||
|
role="assistant",
|
||||||
|
content=full_response,
|
||||||
|
))
|
||||||
s.commit()
|
s.commit()
|
||||||
|
|
||||||
|
|
||||||
@@ -225,15 +229,23 @@ def _summarize_result(tool_name: str, result_json: str) -> str:
|
|||||||
if "error" in data:
|
if "error" in data:
|
||||||
return f"错误: {data['error']}"
|
return f"错误: {data['error']}"
|
||||||
|
|
||||||
# 列表类工具 → 仅显示数量
|
# 列表类工具 → 显示数量 + 各条目 ID 和标题
|
||||||
if tool_name == "list_outlines":
|
if tool_name == "list_outlines":
|
||||||
return f"{data.get('total', 0)}条大纲"
|
items = data.get("outlines", [])
|
||||||
|
brief = ", ".join(f"#{o['id']}{o.get('summary', '')[:15]}" for o in items[:10])
|
||||||
|
return f"{data.get('total', 0)}条大纲: {brief}" if brief else f"{data.get('total', 0)}条大纲"
|
||||||
if tool_name == "list_characters":
|
if tool_name == "list_characters":
|
||||||
return f"{data.get('total', 0)}个角色"
|
items = data.get("characters", [])
|
||||||
|
brief = ", ".join(f"#{c['id']}{c.get('name', '')}" for c in items[:15])
|
||||||
|
return f"{data.get('total', 0)}个角色: {brief}" if brief else f"{data.get('total', 0)}个角色"
|
||||||
if tool_name == "list_chapters":
|
if tool_name == "list_chapters":
|
||||||
return f"{data.get('total', 0)}个章节"
|
items = data.get("chapters", [])
|
||||||
|
brief = ", ".join(f"#{c['id']}{c.get('title', '')[:15]}" for c in items[:10])
|
||||||
|
return f"{data.get('total', 0)}个章节: {brief}" if brief else f"{data.get('total', 0)}个章节"
|
||||||
if tool_name == "list_files":
|
if tool_name == "list_files":
|
||||||
return f"{data.get('total', 0)}个文件"
|
items = data.get("files", [])
|
||||||
|
brief = ", ".join(f"#{f['id']}{f.get('filename', '')}" for f in items[:5])
|
||||||
|
return f"{data.get('total', 0)}个文件: {brief}" if brief else f"{data.get('total', 0)}个文件"
|
||||||
|
|
||||||
# 创建类 → ID + 标题
|
# 创建类 → ID + 标题
|
||||||
if tool_name == "create_outline":
|
if tool_name == "create_outline":
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ function parseHistoryMessage(msg: ChatMessage): ChatEntry[] {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试匹配普通工具调用格式
|
// 尝试匹配普通工具调用格式(兼容 "→ 结果: xxx" 和 "→ xxx" 两种格式)
|
||||||
const toolMatch = line.match(/^\[工具调用: (.+?)\] 参数: (.+?) → 结果: (.+)$/)
|
const toolMatch = line.match(/^\[工具调用: (.+?)\] 参数: (.+?) → (?:结果: )?(.+)$/)
|
||||||
if (toolMatch) {
|
if (toolMatch) {
|
||||||
const label = toolMatch[1]
|
const label = toolMatch[1]
|
||||||
const name = LABEL_TO_TOOL_NAME[label] || label
|
const name = LABEL_TO_TOOL_NAME[label] || label
|
||||||
|
|||||||
Reference in New Issue
Block a user