feat: capture reasoning content from thinking models, improve thinking UI
- Backend: intercept reasoning_content from DeepSeek-R1/QwQ streaming chunks and emit as thinking events (stage=reasoning) - RAG chain: show retrieved document titles/previews in thinking steps - Conversation chain: directly stream from LLM to capture reasoning - Frontend: collapsible thinking panel with reasoning section, document details, and time summary - Replace relative time with HH:mm format for message timestamps Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -80,24 +80,41 @@ class ConversationChain:
|
||||
}
|
||||
|
||||
async def astream_with_thinking(self, question: str, chat_history: List[Dict] = None):
|
||||
"""流式调用(包含思考过程)"""
|
||||
"""流式调用(包含思考过程,捕获推理模型的真实推理内容)"""
|
||||
import time
|
||||
|
||||
|
||||
# 思考阶段
|
||||
start_time = time.time()
|
||||
yield {"type": "thinking", "stage": "understanding", "message": "正在理解问题..."}
|
||||
|
||||
|
||||
# 准备历史
|
||||
history_messages = self._format_history(chat_history or [])
|
||||
|
||||
history_count = len([m for m in (chat_history or []) if m["role"] == "user"])
|
||||
yield {"type": "thinking", "stage": "preparing", "message": f"加载对话上下文({history_count} 轮历史)..." if history_count > 0 else "准备生成回答..."}
|
||||
|
||||
yield {"type": "thinking", "stage": "generating", "message": "正在生成回答..."}
|
||||
|
||||
# 流式生成
|
||||
async for chunk in self.chain.astream({
|
||||
|
||||
# 直接流式调用 LLM 以捕获推理内容
|
||||
prompt_messages = await self.prompt.ainvoke({
|
||||
"question": question,
|
||||
"chat_history": history_messages
|
||||
}):
|
||||
yield {"type": "chunk", "content": chunk}
|
||||
})
|
||||
|
||||
content_started = False
|
||||
async for chunk in self.llm.astream(prompt_messages):
|
||||
# 捕获推理内容(DeepSeek-R1/QwQ 等推理模型)
|
||||
if hasattr(chunk, 'additional_kwargs') and 'reasoning_content' in chunk.additional_kwargs:
|
||||
reasoning_text = chunk.additional_kwargs['reasoning_content']
|
||||
if reasoning_text:
|
||||
yield {"type": "thinking", "stage": "reasoning", "message": reasoning_text}
|
||||
elif hasattr(chunk, 'reasoning_content') and chunk.reasoning_content:
|
||||
yield {"type": "thinking", "stage": "reasoning", "message": chunk.reasoning_content}
|
||||
|
||||
content = chunk.content if hasattr(chunk, 'content') else str(chunk)
|
||||
if content:
|
||||
if not content_started:
|
||||
content_started = True
|
||||
yield {"type": "chunk", "content": content}
|
||||
|
||||
# 完成
|
||||
total_time = time.time() - start_time
|
||||
|
||||
Reference in New Issue
Block a user