From cb47e9859c783b85cbd030b8374a82351afdced5 Mon Sep 17 00:00:00 2001
From: 666ghj <670939375@qq.com>
Date: Tue, 16 Dec 2025 17:59:34 +0800
Subject: [PATCH] Update ReportAgent to enhance report retrieval and streamline
tool call process
- Reduced maximum tool calls per chat from 5 to 2 for improved efficiency.
- Simplified system prompt to focus on concise responses and report content.
- Implemented report content retrieval with length limitation to prevent context overflow.
- Adjusted tool call execution to limit to one call per iteration, enhancing clarity in responses.
- Updated user message prompts to encourage concise answers based on retrieved data.
---
backend/app/services/report_agent.py | 123 +++++++++------------------
1 file changed, 41 insertions(+), 82 deletions(-)
diff --git a/backend/app/services/report_agent.py b/backend/app/services/report_agent.py
index d5756be..dbb447d 100644
--- a/backend/app/services/report_agent.py
+++ b/backend/app/services/report_agent.py
@@ -499,7 +499,7 @@ class ReportAgent:
MAX_REFLECTION_ROUNDS = 3
# 对话中的最大工具调用次数
- MAX_TOOL_CALLS_PER_CHAT = 5
+ MAX_TOOL_CALLS_PER_CHAT = 2
def __init__(
self,
@@ -1656,62 +1656,45 @@ class ReportAgent:
chat_history = chat_history or []
- system_prompt = f"""你是一个拥有「上帝视角」的未来预测助手,负责回答关于模拟预测结果的问题。
+ # 获取已生成的报告内容
+ report_content = ""
+ try:
+ report = ReportManager.get_report_by_simulation(self.simulation_id)
+ if report and report.markdown_content:
+ # 限制报告长度,避免上下文过长
+ report_content = report.markdown_content[:15000]
+ if len(report.markdown_content) > 15000:
+ report_content += "\n\n... [报告内容已截断] ..."
+ except Exception as e:
+ logger.warning(f"获取报告内容失败: {e}")
+
+ # 构建系统提示
+ system_prompt = f"""你是一个简洁高效的模拟预测助手。
-═══════════════════════════════════════════════════════════════
-【预测场景背景】
-═══════════════════════════════════════════════════════════════
-预测条件(模拟需求): {self.simulation_requirement}
-模拟世界ID: {self.graph_id}
+【背景】
+预测条件: {self.simulation_requirement}
-模拟世界是对未来的预演。你的任务是帮助用户理解:在设定条件下,未来会发生什么?各类人群会如何反应?
+【已生成的分析报告】
+{report_content if report_content else "(暂无报告)"}
-═══════════════════════════════════════════════════════════════
-【最重要的规则 - 必须遵守】
-═══════════════════════════════════════════════════════════════
-
-1. 【必须调用工具获取预测数据】
- - 你的回答必须基于模拟世界中的预测结果
- - 禁止使用你自己的知识来回答问题
- - 每次回答前至少调用1次工具获取预测数据
-
-2. 【必须引用Agent的原始言行】
- - Agent的发言和行为是对未来人群行为的预测
- - 在回答中使用引用格式展示这些预测,例如:
- > "某类人群会表示:原文内容..."
- - 这些引用是预测的核心证据
-
-3. 【忠实呈现预测结果】
- - 回答必须反映模拟世界中的预测结果
- - 不要添加模拟中不存在的信息
- - 如果某方面信息不足,如实说明
-
-═══════════════════════════════════════════════════════════════
-【可用检索工具】(最多调用3次)
-═══════════════════════════════════════════════════════════════
+【规则】
+1. 优先基于上述报告内容回答问题
+2. 直接回答问题,避免冗长的思考论述
+3. 仅在报告内容不足以回答时,才调用工具检索更多数据
+4. 回答要简洁、清晰、有条理
+【可用工具】(仅在需要时使用,最多调用1-2次)
{self._get_tools_description()}
-【工具使用建议】
-- insight_forge: 用于深度分析,会自动分解问题并多维度检索
-- panorama_search: 用于了解全貌和演变过程
-- quick_search: 用于快速验证某个具体信息
-- interview_agents: 用于采访模拟Agent,获取不同角色的真实观点和看法
-
【工具调用格式】
{{"name": "工具名称", "parameters": {{"参数名": "参数值"}}}}
-═══════════════════════════════════════════════════════════════
-【回答要求】
-═══════════════════════════════════════════════════════════════
-
-1. 先调用工具获取模拟数据,再回答问题
-2. 大量引用检索到的原文
-3. 使用 > 格式引用重要内容
-4. 如果信息不足,如实说明限制
-5. 保持专业和客观"""
+【回答风格】
+- 简洁直接,不要长篇大论
+- 使用 > 格式引用关键内容
+- 优先给出结论,再解释原因"""
# 构建消息
messages = [{"role": "system", "content": system_prompt}]
@@ -1720,48 +1703,27 @@ class ReportAgent:
for h in chat_history[-10:]: # 限制历史长度
messages.append(h)
- # 添加用户消息,强调需要先检索
+ # 添加用户消息
messages.append({
"role": "user",
- "content": f"""{message}
-
-【提醒】请先调用工具获取模拟数据,再回答问题。推荐使用 insight_forge 进行深度检索。"""
+ "content": message
})
- # ReACT循环
+ # ReACT循环(简化版)
tool_calls_made = []
- max_iterations = 5 # 最大迭代轮数
- min_tool_calls = 1 # 最少工具调用次数
+ max_iterations = 2 # 减少迭代轮数
for iteration in range(max_iterations):
response = self.llm.chat(
messages=messages,
- temperature=0.5,
- max_tokens=2048
+ temperature=0.5
)
# 解析工具调用
tool_calls = self._parse_tool_calls(response)
if not tool_calls:
- # 没有工具调用
- if len(tool_calls_made) < min_tool_calls and iteration < 2:
- # 还没有调用过工具,强烈提示需要先检索
- messages.append({"role": "assistant", "content": response})
- messages.append({
- "role": "user",
- "content": f"""【重要】你还没有调用工具获取模拟数据!
-
-请先调用工具检索相关信息:
-
-{{"name": "insight_forge", "parameters": {{"query": "{message[:100]}"}}}}
-
-
-【记住】回答必须基于模拟结果,不能使用你自己的知识!"""
- })
- continue
-
- # 已有工具调用,清理响应并返回
+ # 没有工具调用,直接返回响应
clean_response = re.sub(r'.*?', '', response, flags=re.DOTALL)
clean_response = re.sub(r'\[TOOL_CALL\].*?\)', '', clean_response)
@@ -1771,33 +1733,30 @@ class ReportAgent:
"sources": [tc.get("parameters", {}).get("query", "") for tc in tool_calls_made]
}
- # 执行工具调用
+ # 执行工具调用(限制数量)
tool_results = []
- for call in tool_calls:
+ for call in tool_calls[:1]: # 每轮最多执行1次工具调用
if len(tool_calls_made) >= self.MAX_TOOL_CALLS_PER_CHAT:
break
result = self._execute_tool(call["name"], call.get("parameters", {}))
tool_results.append({
"tool": call["name"],
- "result": result[:2000] # 增加结果长度限制
+ "result": result[:1500] # 限制结果长度
})
tool_calls_made.append(call)
# 将结果添加到消息
messages.append({"role": "assistant", "content": response})
- observation = "═══ 检索结果 ═══\n" + "\n\n".join([
- f"【{r['tool']}】\n{r['result']}" for r in tool_results
- ])
+ observation = "\n".join([f"[{r['tool']}结果]\n{r['result']}" for r in tool_results])
messages.append({
"role": "user",
- "content": observation + "\n\n请基于以上模拟数据回答问题。\n【重要】请在回答中引用检索到的原文,使用 > 格式。"
+ "content": observation + "\n\n请简洁回答问题。"
})
# 达到最大迭代,获取最终响应
final_response = self.llm.chat(
messages=messages,
- temperature=0.5,
- max_tokens=2048
+ temperature=0.5
)
# 清理响应