@@ -474,387 +474,386 @@ class Report:
# ── 工具描述 ──
# ── 工具描述 ──
TOOL_DESC_INSIGHT_FORGE = """ \
TOOL_DESC_INSIGHT_FORGE = """ \
【深度洞察检索 - 强大的检索工具】
[Deep Insight Retrieval - Powerful Analysis Tool]
这是我们强大的检索函数,专为深度分析设计。它会:
This is our powerful retrieval function designed for deep analysis. It will:
1. 自动将你的问题分解为多个子问题
1. Automatically decompose your question into multiple sub-questions
2. 从多个维度检索模拟图谱中的信息
2. Retrieve information from multiple dimensions in the simulation graph
3. 整合语义搜索、实体分析、关系链追踪的结果
3. Integrate results from semantic search, entity analysis, and relationship chain tracking
4. 返回最全面、最深度的检索内容
4. Return the most comprehensive and in-depth retrieval content
【使用场景】
[Use Cases]
- 需要深入分析某个话题
- Deep analysis of a specific topic
- 需要了解事件的多个方面
- Understanding multiple aspects of an event
- 需要获取支撑报告章节的丰富素材
- Gathering rich material to support report sections
【返回内容】
[Returned Content]
- 相关事实原文(可直接引用)
- Relevant original facts (can be directly quoted)
- 核心实体洞察
- Core entity insights
- 关系链分析 """
- Relationship chain analysis """
TOOL_DESC_PANORAMA_SEARCH = """ \
TOOL_DESC_PANORAMA_SEARCH = """ \
【广度搜索 - 获取全貌视图】
[Panorama Search - Get the Full Picture]
这个工具用于获取模拟结果的完整全貌,特别适合了解事件演变过程。它会:
This tool retrieves the complete picture of simulation results, especially useful for understanding event evolution. It will:
1. 获取所有相关节点和关系
1. Retrieve all related nodes and relationships
2. 区分当前有效的事实和历史/过期的事实
2. Distinguish between currently valid facts and historical/expired facts
3. 帮助你了解舆情是如何演变的
3. Help you understand how public sentiment evolved
【使用场景】
[Use Cases]
- 需要了解事件的完整发展脉络
- Understanding the full development timeline of an event
- 需要对比不同阶段的舆情变化
- Comparing sentiment changes across different stages
- 需要获取全面的实体和关系信息
- Getting comprehensive entity and relationship information
【返回内容】
[Returned Content]
- 当前有效事实(模拟最新结果)
- Currently valid facts (latest simulation results)
- 历史/过期事实(演变记录)
- Historical/expired facts (evolution records)
- 所有涉及的实体 """
- All involved entities """
TOOL_DESC_QUICK_SEARCH = """ \
TOOL_DESC_QUICK_SEARCH = """ \
【简单搜索 - 快速检索】
[Quick Search - Fast Retrieval]
轻量级的快速检索工具,适合简单、直接的信息查询。
A lightweight fast retrieval tool suitable for simple, direct information queries.
【使用场景】
[Use Cases]
- 需要快速查找某个具体信息
- Quickly finding specific information
- 需要验证某个事实
- Verifying a fact
- 简单的信息检索
- Simple information retrieval
【返回内容】
[Returned Content]
- 与查询最相关的事实列表 """
- List of facts most relevant to the query """
TOOL_DESC_INTERVIEW_AGENTS = """ \
TOOL_DESC_INTERVIEW_AGENTS = """ \
【深度采访 - 真实Agent采访( 双平台) 】
[Deep Interview - Real Agent Interview (Dual Platform)]
调用OASIS模拟环境的采访API, 对正在运行的模拟Agent进行真实采访!
Calls the OASIS simulation environment ' s interview API to conduct real interviews with running simulation agents!
这不是LLM模拟, 而是调用真实的采访接口获取模拟Agent的原始回答。
This is NOT LLM simulation - it calls the real interview API to get original responses from simulation agents.
默认在 Twitter和 Reddit两个平台同时采访,获取更全面的观点。
By default, interviews are conducted simultaneously on both Twitter and Reddit platforms for more comprehensive perspectives.
功能流程:
Workflow:
1. 自动读取人设文件, 了解所有模拟A gent
1. Automatically reads persona files to understand all simulation a gents
2. 智能选择与采访主题最相关的Agent( 如学生、媒体、官方等)
2. Intelligently selects agents most relevant to the interview topic (e.g., students, media, officials)
3. 自动生成采访问题
3. Automatically generates interview questions
4. 调用 /api/simulation/interview/batch 接口在双平台进行真实采访
4. Calls the /api/simulation/interview/batch endpoint for real interviews on both platforms
5. 整合所有采访结果,提供多视角分析
5. Consolidates all interview results and provides multi-perspective analysis
【使用场景】
[Use Cases]
- 需要从不同角色视角了解事件看法(学生怎么看?媒体怎么看?官方怎么说?)
- Understanding event perspectives from different role viewpoints (What do students think? What about media? What do officials say?)
- 需要收集多方意见和立场
- Collecting opinions and positions from multiple parties
- 需要获取模拟Agent的真实回答( 来自OASIS模拟环境)
- Getting real responses from simulation agents (from OASIS simulation environment)
- 想让报告更生动,包含 " 采访实录 "
- Making reports more vivid with " interview transcripts "
【返回内容】
[Returned Content]
- 被采访Agent的身份信息
- Identity information of interviewed agents
- 各Agent在 Twitter和 Reddit两个平台的采访回答
- Interview responses from each agent on both Twitter and Reddit platforms
- 关键引言(可直接引用)
- Key quotes (can be directly quoted)
- 采访摘要和观点对比
- Interview summary and perspective comparison
【重要】需要OASIS模拟环境正在运行才能使用此功能! """
[Important] Requires the OASIS simulation environment to be running! """
# ── 大纲规划 prompt ──
# ── 大纲规划 prompt ──
PLAN_SYSTEM_PROMPT = """ \
PLAN_SYSTEM_PROMPT = """ \
你是一个「未来预测报告」的撰写专家, 拥有对模拟世界的「上帝视角」——你可以洞察模拟中每一位Agent的行为、言论和互动。
You are a " Future Prediction Report " writing expert with a " God ' s-eye view " of the simulation world — you can observe the behavior, speech, and interactions of every Agent in the simulation.
【核心理念】
[Core Philosophy]
我们构建了一个模拟世界,并向其中注入了特定的「模拟需求」作为变量。模拟世界的演化结果,就是对未来可能发生情况的预测。你正在观察的不是 " 实验数据 " ,而是 " 未来的预演 " 。
We have built a simulation world and injected a specific " simulation requirement " as a variable. The evolution of the simulation world represents a prediction of what may happen in the future. What you are observing is not " experimental data " but a " rehearsal of the future. "
【你的任务】
[Your Task]
撰写一份「未来预测报告」,回答:
Write a " Future Prediction Report " that answers:
1. 在我们设定的条件下,未来发生了什么?
1. Under the conditions we set, what happened in the future?
2. 各类Agent( 人群) 是如何反应和行动?
2. How did various groups of Agents (people) react and act?
3. 这个模拟揭示了哪些值得关注的未来趋势和风险?
3. What noteworthy future trends and risks does this simulation reveal?
【报告定位】
[Report Positioning]
- ✅ 这是一份基于模拟的未来预测报告,揭示 " 如果这样,未来会怎样 "
- ✅ This is a simulation-based future prediction report, revealing " if this, then what happens in the future "
- ✅ 聚焦于预测结果:事件走向、群体反应、涌现现象、潜在风险
- ✅ Focus on prediction outcomes: event trajectory, group reactions, emergent phenomena, potential risks
- ✅ 模拟世界中的Agent言行就是对未来人群行为的预测
- ✅ Agent behavior and speech in the simulation world represent predictions of future crowd behavior
- ❌ 不是对现实世界现状的分析
- ❌ NOT an analysis of the current state of the real world
- ❌ 不是泛泛而谈的舆情综述
- ❌ NOT a generic public sentiment overview
【章节数量限制】
[Chapter Count Limits]
- 最少2个章节, 最多5个章节
- Minimum 2 chapters, maximum 5 chapters
- 不需要子章节,每个章节直接撰写完整内容
- No sub-chapters needed; each chapter should directly write complete content
- 内容要精炼,聚焦于核心预测发现
- Content should be concise, focused on core prediction findings
- 章节结构由你根据预测结果自主设计
- Chapter structure should be designed by you based on prediction results
请输出JSON格式的报告大纲, 格式如下:
Please output the report outline in JSON format as follows:
{
{
" title " : " 报告标题 " ,
" title " : " Report Title " ,
" summary " : " 报告摘要(一句话概括核心预测发现) " ,
" summary " : " Report Summary (one sentence summarizing core prediction findings) " ,
" sections " : [
" sections " : [
{
{
" title " : " 章节标题 " ,
" title " : " Section Title " ,
" description " : " 章节内容描述 "
" description " : " Section Content Description "
}
}
]
]
}
}
注意: sections数组最少2个, 最多5个元素! """
Note: The sections array must have a minimum of 2 and maximum of 5 elements! """
PLAN_USER_PROMPT_TEMPLATE = """ \
PLAN_USER_PROMPT_TEMPLATE = """ \
【预测场景设定】
[Prediction Scenario Setup]
我们向模拟世界注入的变量(模拟需求): {simulation_requirement}
The variable (simulation requirement) we injected into the simulation world: {simulation_requirement}
【模拟世界规模】
[Simulation World Scale]
- 参与模拟的实体数量 : {total_nodes}
- Number of entities participating in simulation : {total_nodes}
- 实体间产生的关系数量 : {total_edges}
- Number of relationships generated between entities : {total_edges}
- 实体类型分布 : {entity_types}
- Entity type distribution : {entity_types}
- 活跃 Agent数量 : {total_entities}
- Number of active Agents : {total_entities}
【模拟预测到的部分未来事实样本】
[Sample of Predicted Future Facts from the Simulation]
{related_facts_json}
{related_facts_json}
请以「上帝视角」审视这个未来预演:
Please examine this future rehearsal from a " God ' s-eye view " :
1. 在我们设定的条件下,未来呈现出了什么样的状态?
1. Under the conditions we set, what state has the future taken on?
2. 各类人群( Agent) 是如何反应和行动的?
2. How are various groups of people (Agents) reacting and acting?
3. 这个模拟揭示了哪些值得关注的未来趋势?
3. What noteworthy future trends does this simulation reveal?
根据预测结果,设计最合适的报告章节结构。
Design the most appropriate report section structure based on the prediction results.
【再次提醒】报告章节数量: 最少2个, 最多5个, 内容要精炼聚焦于核心预测发现。 """
[Reminder] Report chapter count: minimum 2, maximum 5. Content should be concise and focused on core prediction findings. """
# ── 章节生成 prompt ──
# ── 章节生成 prompt ──
SECTION_SYSTEM_PROMPT_TEMPLATE = """ \
SECTION_SYSTEM_PROMPT_TEMPLATE = """ \
你是一个「未来预测报告」的撰写专家,正在撰写报告的一个章节。
You are a " Future Prediction Report " writing expert, currently writing a section of the report.
报告标题 : {report_title}
Report Title : {report_title}
报告摘要 : {report_summary}
Report Summary : {report_summary}
预测场景(模拟需求) : {simulation_requirement}
Prediction Scenario (Simulation Requirement) : {simulation_requirement}
当前要撰写的章节 : {section_title}
Section currently being written : {section_title}
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【核心理念】
[Core Philosophy]
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
模拟世界是对未来的预演。我们向模拟世界注入了特定条件(模拟需求),
The simulation world is a rehearsal of the future. We injected specific conditions (simulation requirement) into the simulation world. The behavior and interactions of Agents in the simulation represent predictions of future crowd behavior.
模拟中Agent的行为和互动, 就是对未来人群行为的预测。
你的任务是:
Your task is to:
- 揭示在设定条件下,未来发生了什么
- Reveal what happened in the future under the set conditions
- 预测各类人群( Agent) 是如何反应和行动的
- Predict how various groups of people (Agents) react and act
- 发现值得关注的未来趋势、风险和机会
- Discover noteworthy future trends, risks, and opportunities
❌ 不要写成对现实世界现状的分析
❌ Do NOT write this as an analysis of the current state of the real world
✅ 要聚焦于 " 未来会怎样 " ——模拟结果就是预测的未来
✅ Focus on " what will happen in the future " — the simulation results ARE the predicted future
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【最重要的规则 - 必须遵守】
[Most Important Rules - Must Be Followed]
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
1. 【必须调用工具观察模拟世界】
1. [Must Call Tools to Observe the Simulation World]
- 你正在以「上帝视角」观察未来的预演
- You are observing the future rehearsal from a " God ' s-eye view "
- 所有内容必须来自模拟世界中发生的事件和Agent言行
- All content must come from events and Agent behavior occurring in the simulation world
- 禁止使用你自己的知识来编写报告内容
- Do NOT use your own knowledge to write report content
- 每个章节至少调用3次工具( 最多5次) 来观察模拟的世界, 它代表了未来
- Each section must call tools at least 3 times (maximum 5) to observe the simulated world, which represents the future
2. 【必须引用Agent的原始言行】
2. [Must Quote Agent ' s Original Words and Actions]
- Agent的发言和行为是对未来人群行为的预测
- Agent speech and behavior are predictions of future crowd behavior
- 在报告中使用引用格式展示这些预测,例如:
- Display these predictions using quote format in the report, for example:
> " 某类人群会表示:原文内容 ..."
> " A certain group of people would say: original content ..."
- 这些引用是模拟预测的核心证据
- These quotes are core evidence for simulation predictions
3. 【语言一致性 - 引用内容必须翻译为报告语言】
3. [Language Consistency - Quoted Content Must Be Translated to Report Language]
- 工具返回的内容可能包含与报告语言不同的表述
- Content returned by tools may contain expressions in a different language than the report
- 报告必须全部使用与用户指定语言一致的语言撰写
- The entire report must be written in the language specified by the user
- 当你引用工具返回的其他语言内容时,必须将其翻译为报告语言后再写入
- When quoting content returned by tools in other languages, you must translate it into the report language before including it
- 翻译时保持原意不变,确保表述自然通顺
- Maintain the original meaning during translation and ensure natural expression
- 这一规则同时适用于正文和引用块(> 格式)中的内容
- This rule applies to both body text and quote blocks (> format)
4. 【忠实呈现预测结果】
4. [Faithfully Present Prediction Results]
- 报告内容必须反映模拟世界中的代表未来的模拟结果
- Report content must reflect the simulation results representing the future in the simulation world
- 不要添加模拟中不存在的信息
- Do not add information that does not exist in the simulation
- 如果某方面信息不足,如实说明
- If information on a certain aspect is insufficient, state so honestly
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【 ⚠️ 格式规范 - 极其重要!】
[ ⚠️ Format Requirements - Extremely Important!]
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【一个章节 = 最小内容单位】
[One Section = Minimum Content Unit]
- 每个章节是报告的最小分块单位
- Each section is the minimum chunk unit of the report
- ❌ 禁止在章节内使用任何 Markdown 标题(#、##、 ###、 #### 等)
- ❌ Do NOT use any Markdown headings (#, ##, ###, #### etc.) within a section
- ❌ 禁止在内容开头添加章节主标题
- ❌ Do NOT add the section main title at the beginning of the content
- ✅ 章节标题由系统自动添加,你只需撰写纯正文内容
- ✅ Section titles are automatically added by the system; you only need to write plain body content
- ✅ 使用**粗体**、段落分隔、引用、列表来组织内容,但不要用标题
- ✅ Use **bold text**, paragraph breaks, quotes, and lists to organize content, but do NOT use headings
【正确示例】
[Correct Example]
```
```
本章节分析了事件的舆论传播态势。通过对模拟数据的深入分析,我们发现 ...
This section analyzes the public sentiment propagation dynamics of the event. Through in-depth analysis of simulation data, we found ...
**首发引爆阶段 **
**Initial Ignition Phase **
微博作为舆情的第一现场,承担了信息首发的核心功能:
Platform A served as the first site of public sentiment, carrying the core function of information release:
> " 微博贡献了68 % 的首发声量 ..."
> " Platform A contributed 68 % o f the initial volume ..."
**情绪放大阶段 **
**Emotion Amplification Phase **
抖音平台进一步放大了事件影响力:
Platform B further amplified the event ' s impact:
- 视觉冲击力强
- Strong visual impact
- 情绪共鸣度高
- High emotional resonance
```
```
【错误示例】
[Incorrect Example]
```
```
## 执行摘要 ← 错误!不要添加任何标题
## Executive Summary ← WRONG! Do not add any headings
### 一、首发阶段 ← 错误!不要用###分小节
### Part 1: Initial Phase ← WRONG! Do not use ### for sub-sections
#### 1.1 详细分析 ← 错误!不要用####细分
#### 1.1 Detailed Analysis ← WRONG! Do not use #### for sub-divisions
本章节分析了 ...
This section analyzes ...
```
```
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【可用检索工具】( 每章节调用3-5次)
[Available Retrieval Tools] (Call 3-5 times per section)
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
{tools_description}
{tools_description}
【工具使用建议 - 请混合使用不同工具,不要只用一种】
[Tool Usage Tips - Please mix different tools, do not use only one]
- insight_forge: 深度洞察分析,自动分解问题并多维度检索事实和关系
- insight_forge: Deep insight analysis, automatically decomposes questions and retrieves facts and relationships from multiple dimensions
- panorama_search: 广角全景搜索,了解事件全貌、时间线和演变过程
- panorama_search: Panoramic search to understand event overview, timeline, and evolution process
- quick_search: 快速验证某个具体信息点
- quick_search: Quickly verify a specific piece of information
- interview_agents: 采访模拟Agent, 获取不同角色的第一人称观点和真实反应
- interview_agents: Interview simulation agents to get first-person perspectives and real reactions from different roles
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【工作流程】
[Workflow]
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
每次回复你只能做以下两件事之一(不可同时做):
Each response you can only do ONE of the following two things (NOT both):
选项A - 调用工具:
Option A - Call a tool:
输出你的思考,然后用以下格式调用一个工具:
Output your thoughts, then call a tool using the following format:
<tool_call>
<tool_call>
{{ " name " : " 工具名称 " , " parameters " : {{ " 参数名 " : " 参数值 " }}}}
{{ " name " : " tool_name " , " parameters " : {{ " param_name " : " param_value " }}}}
</tool_call>
</tool_call>
系统会执行工具并把结果返回给你。你不需要也不能自己编写工具返回结果。
The system will execute the tool and return the result to you. You do not need to and cannot write tool results yourself.
选项B - 输出最终内容:
Option B - Output final content:
当你已通过工具获取了足够信息,以 " Final Answer: " 开头输出章节内容。
When you have gathered enough information through tools, output the section content starting with " Final Answer: " .
⚠️ 严格禁止:
⚠️ Strictly prohibited:
- 禁止在一次回复中同时包含工具调用和 Final Answer
- Do NOT include both a tool call and Final Answer in the same response
- 禁止自己编造工具返回结果( Observation) , 所有工具结果由系统注入
- Do NOT fabricate tool results (Observation); all tool results are injected by the system
- 每次回复最多调用一个工具
- Each response can call at most one tool
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【章节内容要求】
[Section Content Requirements]
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
1. 内容必须基于工具检索到的模拟数据
1. Content must be based on simulation data retrieved by tools
2. 大量引用原文来展示模拟效果
2. Extensively quote original text to demonstrate simulation results
3. 使用 Markdown格式(但禁止使用标题):
3. Use Markdown format (but headings are prohibited):
- 使用 **粗体文字** 标记重点(代替子标题)
- Use **bold text** to highlight key points (replacing sub-headings)
- 使用列表(-或1.2.3.)组织要点
- Use lists (- or 1.2.3.) to organize key points
- 使用空行分隔不同段落
- Use blank lines to separate paragraphs
- ❌ 禁止使用 #、##、 ###、 #### 等任何标题语法
- ❌ Do NOT use #, ##, ###, #### or any heading syntax
4. 【引用格式规范 - 必须单独成段】
4. [Quote Format Requirements - Must Be Standalone Paragraphs]
引用必须独立成段,前后各有一个空行,不能混在段落中:
Quotes must be standalone paragraphs with blank lines before and after, not mixed into regular paragraphs:
✅ 正确格式:
✅ Correct format:
```
```
校方的回应被认为缺乏实质内容。
The institution ' s response was considered lacking in substance.
> " 校方的应对模式在瞬息万变的社交媒体环境中显得僵化和迟缓。 "
> " The institution ' s response mode appears rigid and slow in the rapidly changing social media environment. "
这一评价反映了公众的普遍不满。
This assessment reflects widespread public dissatisfaction.
```
```
❌ 错误格式:
❌ Incorrect format:
```
```
校方的回应被认为缺乏实质内容。> " 校方的应对模式... " 这一评价反映了 ...
The institution ' s response was considered lacking in substance.> " The institution ' s response mode... " This assessment reflects ...
```
```
5. 保持与其他章节的逻辑连贯性
5. Maintain logical coherence with other sections
6. 【避免重复】仔细阅读下方已完成的章节内容,不要重复描述相同的信息
6. [Avoid Repetition] Carefully read the content of completed sections below and do not repeat the same information
7. 【再次强调】不要添加任何标题!用**粗体**代替小节标题 """
7. [Emphasize Again] Do NOT add any headings! Use **bold text** instead of sub-section headings """
SECTION_USER_PROMPT_TEMPLATE = """ \
SECTION_USER_PROMPT_TEMPLATE = """ \
已完成的章节内容(请仔细阅读,避免重复):
Completed section content (please read carefully to avoid repetition):
{previous_content}
{previous_content}
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【当前任务】撰写章节 : {section_title}
[Current Task] Write Section : {section_title}
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
【重要提醒】
[Important Reminders]
1. 仔细阅读上方已完成的章节,避免重复相同的内容!
1. Carefully read the completed sections above to avoid repeating the same content!
2. 开始前必须先调用工具获取模拟数据
2. You must call tools to retrieve simulation data before starting
3. 请混合使用不同工具,不要只用一种
3. Please mix different tools, do not use only one
4. 报告内容必须来自检索结果,不要使用自己的知识
4. Report content must come from retrieval results, do not use your own knowledge
【 ⚠️ 格式警告 - 必须遵守】
[ ⚠️ Format Warning - Must Be Followed]
- ❌ 不要写任何标题(#、##、 ###、 ####都不行)
- ❌ Do not write any headings (#, ##, ###, #### are all prohibited)
- ❌ 不要写 " {section_title} " 作为开头
- ❌ Do not write " {section_title} " as the beginning
- ✅ 章节标题由系统自动添加
- ✅ Section titles are automatically added by the system
- ✅ 直接写正文,用**粗体**代替小节标题
- ✅ Write body text directly, use **bold text** instead of sub-section headings
请开始:
Please begin:
1. 首先思考( Thought) 这个章节需要什么信息
1. First think (Thought) about what information this section needs
2. 然后调用工具( Action) 获取模拟数据
2. Then call a tool (Action) to retrieve simulation data
3. 收集足够信息后输出 Final Answer( 纯正文, 无任何标题) """
3. After gathering enough information, output Final Answer (plain body text, no headings) """
# ── ReACT 循环内消息模板 ──
# ── ReACT 循环内消息模板 ──
REACT_OBSERVATION_TEMPLATE = """ \
REACT_OBSERVATION_TEMPLATE = """ \
Observation(检索结果) :
Observation (Retrieval Result) :
═══ 工具 {tool_name} 返回 ═══
═══ Tool {tool_name} Returned ═══
{result}
{result}
═══════════════════════════════════════════════════════════════
═══════════════════════════════════════════════════════════════
已调用工具 {tool_calls_count} / {max_tool_calls} 次(已用 : {used_tools_str} ) {unused_hint}
Called tools {tool_calls_count} / {max_tool_calls} times (used : {used_tools_str} ) {unused_hint}
- 如果信息充分:以 " Final Answer: " 开头输出章节内容(必须引用上述原文)
- If information is sufficient: output section content starting with " Final Answer: " (must quote the above original text)
- 如果需要更多信息:调用一个工具继续检索
- If more information is needed: call a tool to continue retrieving
═══════════════════════════════════════════════════════════════ """
═══════════════════════════════════════════════════════════════ """
REACT_INSUFFICIENT_TOOLS_MSG = (
REACT_INSUFFICIENT_TOOLS_MSG = (
" 【注意】你只调用了 {tool_calls_count} 次工具,至少需要 {min_tool_calls} 次。 "
" [Note] You have only called tools {tool_calls_count} time(s), at least {min_tool_calls} required. "
" 请再调用工具获取更多模拟数据,然后再输出 Final Answer。 {unused_hint} "
" Please call tools to get more simulation data before outputting Final Answer. {unused_hint} "
)
)
REACT_INSUFFICIENT_TOOLS_MSG_ALT = (
REACT_INSUFFICIENT_TOOLS_MSG_ALT = (
" 当前只调用了 {tool_calls_count} 次工具,至少需要 {min_tool_calls} 次。 "
" Currently only called tools {tool_calls_count} time(s), at least {min_tool_calls} required. "
" 请调用工具获取模拟数据。 {unused_hint} "
" Please call a tool to retrieve simulation data. {unused_hint} "
)
)
REACT_TOOL_LIMIT_MSG = (
REACT_TOOL_LIMIT_MSG = (
" 工具调用次数已达上限( {tool_calls_count} / {max_tool_calls} ),不能再调用工具。 "
" Tool call limit reached ( {tool_calls_count} / {max_tool_calls} ), no more tools can be called. "
' 请立即基于已获取的信息,以 " Final Answer: " 开头输出章节内容。 '
' Please immediately output section content starting with " Final Answer: " based on the information already gathered. '
)
)
REACT_UNUSED_TOOLS_HINT = " \n 💡 你还没有使用过: {unused_list} ,建议尝试不同工具获取多角度信息 "
REACT_UNUSED_TOOLS_HINT = " \n 💡 You haven ' t used: {unused_list} , try different tools for multi-angle information "
REACT_FORCE_FINAL_MSG = " 已达到工具调用限制,请直接输出 Final Answer: 并生成章节内容。 "
REACT_FORCE_FINAL_MSG = " Tool call limit reached. Please directly output Final Answer: and generate section content. "
# ── Chat prompt ──
# ── Chat prompt ──
CHAT_SYSTEM_PROMPT_TEMPLATE = """ \
CHAT_SYSTEM_PROMPT_TEMPLATE = """ \
你是一个简洁高效的模拟预测助手。
You are a concise and efficient simulation prediction assistant.
【背景】
[Background]
预测条件 : {simulation_requirement}
Prediction Condition : {simulation_requirement}
【已生成的分析报告】
[Generated Analysis Report]
{report_content}
{report_content}
【规则】
[Rules]
1. 优先基于上述报告内容回答问题
1. Prioritize answering questions based on the report content above
2. 直接回答问题,避免冗长的思考论述
2. Answer directly, avoid lengthy reasoning
3. 仅在报告内容不足以回答时,才调用工具检索更多数据
3. Only call tools to retrieve more data when the report content is insufficient to answer
4. 回答要简洁、清晰、有条理
4. Answers should be concise, clear, and well-organized
【可用工具】( 仅在需要时使用, 最多调用1-2次)
[Available Tools] (use only when needed, maximum 1-2 calls)
{tools_description}
{tools_description}
【工具调用格式】
[Tool Call Format]
<tool_call>
<tool_call>
{{ " name " : " 工具名称 " , " parameters " : {{ " 参数名 " : " 参数值 " }}}}
{{ " name " : " tool_name " , " parameters " : {{ " param_name " : " param_value " }}}}
</tool_call>
</tool_call>
【回答风格】
[Response Style]
- 简洁直接,不要长篇大论
- Concise and direct, avoid lengthy explanations
- 使用 > 格式引用关键内容
- Use > format to quote key content
- 优先给出结论,再解释原因 """
- Lead with conclusions, then explain reasoning """
CHAT_OBSERVATION_SUFFIX = " \n \n 请简洁回答问题。 "
CHAT_OBSERVATION_SUFFIX = " \n \n Please answer the question concisely. "
# ═══════════════════════════════════════════════════════════════
# ═══════════════════════════════════════════════════════════════
@@ -923,32 +922,32 @@ class ReportAgent:
" name " : " insight_forge " ,
" name " : " insight_forge " ,
" description " : TOOL_DESC_INSIGHT_FORGE ,
" description " : TOOL_DESC_INSIGHT_FORGE ,
" parameters " : {
" parameters " : {
" query " : " 你想深入分析的问题或话题 " ,
" query " : " The question or topic you want to analyze in depth " ,
" report_context " : " 当前报告章节的上下文(可选,有助于生成更精准的子问题) "
" report_context " : " Current report section context (optional, helps generate more precise sub-questions) "
}
}
} ,
} ,
" panorama_search " : {
" panorama_search " : {
" name " : " panorama_search " ,
" name " : " panorama_search " ,
" description " : TOOL_DESC_PANORAMA_SEARCH ,
" description " : TOOL_DESC_PANORAMA_SEARCH ,
" parameters " : {
" parameters " : {
" query " : " 搜索查询,用于相关性排序 " ,
" query " : " Search query, used for relevance ranking " ,
" include_expired " : " 是否包含过期/历史内容(默认 True) "
" include_expired " : " Whether to include expired/historical content (default True) "
}
}
} ,
} ,
" quick_search " : {
" quick_search " : {
" name " : " quick_search " ,
" name " : " quick_search " ,
" description " : TOOL_DESC_QUICK_SEARCH ,
" description " : TOOL_DESC_QUICK_SEARCH ,
" parameters " : {
" parameters " : {
" query " : " 搜索查询字符串 " ,
" query " : " Search query string " ,
" limit " : " 返回结果数量(可选,默认 10) "
" limit " : " Number of results to return (optional, default 10) "
}
}
} ,
} ,
" interview_agents " : {
" interview_agents " : {
" name " : " interview_agents " ,
" name " : " interview_agents " ,
" description " : TOOL_DESC_INTERVIEW_AGENTS ,
" description " : TOOL_DESC_INTERVIEW_AGENTS ,
" parameters " : {
" parameters " : {
" interview_topic " : " 采访主题或需求描述(如: ' 了解学生对宿舍甲醛事件的看法 ' ) " ,
" interview_topic " : " Interview topic or requirement description (e.g., ' understand student views on the dormitory incident ' ) " ,
" max_agents " : " 最多采访的Agent数量( 可选, 默认5, 最大 10) "
" max_agents " : " Maximum number of agents to interview (optional, default 5, max 10) "
}
}
}
}
}
}
@@ -1055,11 +1054,11 @@ class ReportAgent:
return json . dumps ( result , ensure_ascii = False , indent = 2 )
return json . dumps ( result , ensure_ascii = False , indent = 2 )
else :
else :
return f " 未知工具 : { tool_name } 。请使用以下工具之一 : insight_forge, panorama_search, quick_search"
return f " Unknown tool : { tool_name } . Please use one of the following tools : insight_forge, panorama_search, quick_search"
except Exception as e :
except Exception as e :
logger . error ( t ( ' report.toolExecFailed ' , toolName = tool_name , error = str ( e ) ) )
logger . error ( t ( ' report.toolExecFailed ' , toolName = tool_name , error = str ( e ) ) )
return f " 工具执行失败 : { str ( e ) } "
return f " Tool execution failed : { str ( e ) } "
# 合法的工具名称集合,用于裸 JSON 兜底解析时校验
# 合法的工具名称集合,用于裸 JSON 兜底解析时校验
VALID_TOOL_NAMES = { " insight_forge " , " panorama_search " , " quick_search " , " interview_agents " }
VALID_TOOL_NAMES = { " insight_forge " , " panorama_search " , " quick_search " , " interview_agents " }
@@ -1126,12 +1125,12 @@ class ReportAgent:
def _get_tools_description ( self ) - > str :
def _get_tools_description ( self ) - > str :
""" 生成工具描述文本 """
""" 生成工具描述文本 """
desc_parts = [ " 可用工具: " ]
desc_parts = [ " Available tools: " ]
for name , tool in self . tools . items ( ) :
for name , tool in self . tools . items ( ) :
params_desc = " , " . join ( [ f " { k } : { v } " for k , v in tool [ " parameters " ] . items ( ) ] )
params_desc = " , " . join ( [ f " { k } : { v } " for k , v in tool [ " parameters " ] . items ( ) ] )
desc_parts . append ( f " - { name } : { tool [ ' description ' ] } " )
desc_parts . append ( f " - { name } : { tool [ ' description ' ] } " )
if params_desc :
if params_desc :
desc_parts . append ( f " 参数 : { params_desc } " )
desc_parts . append ( f " Parameters : { params_desc } " )
return " \n " . join ( desc_parts )
return " \n " . join ( desc_parts )
def plan_outline (
def plan_outline (
@@ -1163,7 +1162,7 @@ class ReportAgent:
if progress_callback :
if progress_callback :
progress_callback ( " planning " , 30 , t ( ' progress.generatingOutline ' ) )
progress_callback ( " planning " , 30 , t ( ' progress.generatingOutline ' ) )
system_prompt = f " { PLAN_SYSTEM_PROMPT } \n \n { get_language_instruction( ) } "
system_prompt = f " { get_language_instruction ( )} \n \n { PLAN_SYSTEM_PROMPT } "
user_prompt = PLAN_USER_PROMPT_TEMPLATE . format (
user_prompt = PLAN_USER_PROMPT_TEMPLATE . format (
simulation_requirement = self . simulation_requirement ,
simulation_requirement = self . simulation_requirement ,
total_nodes = context . get ( ' graph_statistics ' , { } ) . get ( ' total_nodes ' , 0 ) ,
total_nodes = context . get ( ' graph_statistics ' , { } ) . get ( ' total_nodes ' , 0 ) ,
@@ -1209,12 +1208,12 @@ class ReportAgent:
logger . error ( t ( ' report.outlinePlanFailed ' , error = str ( e ) ) )
logger . error ( t ( ' report.outlinePlanFailed ' , error = str ( e ) ) )
# 返回默认大纲( 3个章节, 作为fallback)
# 返回默认大纲( 3个章节, 作为fallback)
return ReportOutline (
return ReportOutline (
title = " 未来预测报告 " ,
title = " Future Prediction Report " ,
summary = " 基于模拟预测的未来趋势与风险分析 " ,
summary = " Future trends and risk analysis based on simulation predictions " ,
sections = [
sections = [
ReportSection ( title = " 预测场景与核心发现 " ) ,
ReportSection ( title = " Prediction Scenario and Core Findings " ) ,
ReportSection ( title = " 人群行为预测分析 " ) ,
ReportSection ( title = " Crowd Behavior Prediction Analysis " ) ,
ReportSection ( title = " 趋势展望与风险提示 " )
ReportSection ( title = " Trend Outlook and Risk Warnings " )
]
]
)
)
@@ -1259,7 +1258,7 @@ class ReportAgent:
section_title = section . title ,
section_title = section . title ,
tools_description = self . _get_tools_description ( ) ,
tools_description = self . _get_tools_description ( ) ,
)
)
system_prompt = f " { system_prompt } \n \n { get_language_instruction( ) } "
system_prompt = f " { get_language_instruction ( ) } \n \n { system_prompt } "
# 构建用户prompt - 每个已完成章节各传入最大4000字
# 构建用户prompt - 每个已完成章节各传入最大4000字
if previous_sections :
if previous_sections :
@@ -1270,7 +1269,7 @@ class ReportAgent:
previous_parts . append ( truncated )
previous_parts . append ( truncated )
previous_content = " \n \n --- \n \n " . join ( previous_parts )
previous_content = " \n \n --- \n \n " . join ( previous_parts )
else :
else :
previous_content = " (这是第一个章节) "
previous_content = " (This is the first section) "
user_prompt = SECTION_USER_PROMPT_TEMPLATE . format (
user_prompt = SECTION_USER_PROMPT_TEMPLATE . format (
previous_content = previous_content ,
previous_content = previous_content ,
@@ -1314,7 +1313,7 @@ class ReportAgent:
# 如果还有迭代次数,添加消息并重试
# 如果还有迭代次数,添加消息并重试
if iteration < max_iterations - 1 :
if iteration < max_iterations - 1 :
messages . append ( { " role " : " assistant " , " content " : " (响应为空) " } )
messages . append ( { " role " : " assistant " , " content " : " (响应为空) " } )
messages . append ( { " role " : " user " , " content " : " 请继续生成内容。 " } )
messages . append ( { " role " : " user " , " content " : " Please continue generating content. " } )
continue
continue
# 最后一次迭代也返回 None, 跳出循环进入强制收尾
# 最后一次迭代也返回 None, 跳出循环进入强制收尾
break
break
@@ -1339,11 +1338,11 @@ class ReportAgent:
messages . append ( {
messages . append ( {
" role " : " user " ,
" role " : " user " ,
" content " : (
" content " : (
" 【格式错误】你在一次回复中同时包含了工具调用和 Final Answer, 这是不允许的。 \n "
" [Format Error] You included both a tool call and Final Answer in the same response, which is not allowed. \n "
" 每次回复只能做以下两件事之一: \n "
" Each response can only do ONE of the following two things: \n "
" - 调用一个工具(输出一个 <tool_call> 块,不要写 Final Answer) \n "
" - Call a tool (output a <tool_call> block, do not write Final Answer) \n "
" - 输出最终内容(以 ' Final Answer: ' 开头,不要包含 <tool_call>) \n "
" - Output final content (start with ' Final Answer: ' , do not include <tool_call>) \n "
" 请重新回复,只做其中一件事。 "
" Please reply again, doing only one of the two. "
) ,
) ,
} )
} )
continue
continue
@@ -1805,7 +1804,7 @@ class ReportAgent:
report_content = report_content if report_content else " (暂无报告) " ,
report_content = report_content if report_content else " (暂无报告) " ,
tools_description = self . _get_tools_description ( ) ,
tools_description = self . _get_tools_description ( ) ,
)
)
system_prompt = f " { system_prompt } \n \n { get_language_instruction( ) } "
system_prompt = f " { get_language_instruction ( ) } \n \n { system_prompt } "
# 构建消息
# 构建消息
messages = [ { " role " : " system " , " content " : system_prompt } ]
messages = [ { " role " : " system " , " content " : system_prompt } ]