Compare commits

..

7 Commits

Author SHA1 Message Date
26a76b030d feat: UI重构 - 历史对话列表页 + 新建按钮顶部右侧 + 删除功能 2026-04-26 10:15:51 +08:00
daccc625c3 revert: 撤回错误的修改,恢复原版本
用户指出SiliconFlow平台确实支持标准tool消息类型,之前的修改是错误的

版本: v3.0.7
2026-04-15 10:01:59 +08:00
a2a7fd46c3 chore: 版本号更新到v3.0.6 2026-04-15 09:52:31 +08:00
baf5913bfb fix: SiliconFlow平台Function Calling第二轮调用兼容
问题:SiliconFlow平台不支持标准tool消息类型,第二轮调用返回参数无效

修复:将tool消息转换为user消息格式
- 收集所有tool消息的内容
- 合并为一个用户消息发送给模型
- 添加明确的提示让模型直接根据结果回答

版本: v3.0.6
2026-04-15 09:52:19 +08:00
ae08e01e55 fix: Kimi模型伪工具调用格式过滤
修复Kimi-K2.5模型在第二轮调用时输出伪工具调用格式的问题:
- 添加系统提示告诉模型直接根据工具结果回答
- 过滤 <|tool_calls_section_begin|> 等内部格式标记
- 清理多余空行

版本: v3.0.1
2026-04-15 09:45:08 +08:00
9048d94e33 fix: 添加详细日志诊断工具调用消息格式 2026-04-15 02:25:05 +08:00
291de733a4 fix: chat_with_tool_results不重复添加tool结果,修正消息格式 2026-04-15 01:03:10 +08:00
3 changed files with 464 additions and 489 deletions

View File

@@ -647,17 +647,19 @@ async def get_conversations(db: Session = Depends(get_db)):
user = conv_service.get_or_create_user(MAIN_USER_ID, display_name="主用户", user_type='web')
conversations = conv_service.get_user_conversations(user.id)
return {
"conversations": [
{
"id": c.conversation_id,
"title": c.title or "新对话",
"created_at": c.created_at.isoformat(),
"updated_at": c.updated_at.isoformat()
}
for c in conversations
]
}
# 为每个对话计算消息数量
result = []
for c in conversations:
msg_count = db.query(Message).filter(Message.conversation_id == c.id).count()
result.append({
"id": c.conversation_id,
"title": c.title or "新对话",
"created_at": c.created_at.isoformat(),
"updated_at": c.updated_at.isoformat(),
"message_count": msg_count
})
return {"conversations": result}
@app.get("/api/conversations/latest")
@@ -693,6 +695,26 @@ async def create_conversation(db: Session = Depends(get_db)):
}
@app.get("/api/conversations/{conversation_id}")
async def get_conversation(conversation_id: str, db: Session = Depends(get_db)):
"""获取单个对话详情"""
conv_service = ConversationService(db)
conversation = conv_service.get_conversation(conversation_id)
if not conversation:
raise HTTPException(status_code=404, detail="会话不存在")
msg_count = db.query(Message).filter(Message.conversation_id == conversation.id).count()
return {
"id": conversation.conversation_id,
"title": conversation.title or "新对话",
"created_at": conversation.created_at.isoformat(),
"updated_at": conversation.updated_at.isoformat(),
"message_count": msg_count
}
@app.get("/api/conversations/{conversation_id}/messages")
async def get_messages(conversation_id: str, db: Session = Depends(get_db)):
"""获取会话消息"""
@@ -1121,7 +1143,6 @@ async def websocket_endpoint(websocket: WebSocket, user_id: str):
messages=history_with_tools,
provider_config=agent_config['provider'],
agent_config=agent_config['agent'],
tool_results=tool_results,
enable_thinking=enable_thinking
)

View File

@@ -514,17 +514,15 @@ class LLMService:
messages: List[Dict],
provider_config: dict,
agent_config: dict,
tool_results: List[Dict],
enable_thinking: bool = True
) -> Tuple[str, Optional[str]]:
"""
第二阶段调用:将工具执行结果返回给LLM
第二阶段调用:使用包含工具调用和结果的完整消息历史
Args:
messages: 对话历史(包含工具调用和结果)
messages: 已包含assistant tool_calls和tool结果的完整消息历史
provider_config: LLM Provider配置
agent_config: Agent配置
tool_results: 工具执行结果 [{"tool_call_id": "xxx", "content": "..."}]
Returns:
Tuple[str, Optional[str]]: (回复内容, 思考过程)
@@ -535,14 +533,8 @@ class LLMService:
max_tokens = provider_config.get('max_tokens', 4096)
temperature = agent_config.get('temperature_override') or provider_config.get('temperature', 0.7)
# 将工具结果添加到消息历史
# 消息历史已经包含了assistant的tool_calls和tool结果直接使用
final_messages = messages.copy()
for result in tool_results:
final_messages.append({
"role": "tool",
"tool_call_id": result['tool_call_id'],
"content": result['content']
})
# 调用LLM生成最终回复
url = f"{api_base.rstrip('/')}/chat/completions"
@@ -557,14 +549,14 @@ class LLMService:
"max_tokens": max_tokens
}
logger.info(f"工具结果返回LLM: url={url}, model={model}")
logger.info(f"工具结果返回LLM: url={url}, model={model}, 消息数={len(final_messages)}")
try:
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(url, headers=headers, json=payload)
if response.status_code != 200:
logger.error(f"API返回错误: status={response.status_code}")
logger.error(f"API返回错误: status={response.status_code}, body={response.text[:500]}")
response.raise_for_status()
data = response.json()

File diff suppressed because it is too large Load Diff