feat(i18n): replace all user-visible Chinese in report_agent.py
Covers ReportLogger message fields and logger messages shown via ConsoleLogger.
This commit is contained in:
@@ -106,7 +106,7 @@ class ReportLogger:
|
||||
"simulation_id": simulation_id,
|
||||
"graph_id": graph_id,
|
||||
"simulation_requirement": simulation_requirement,
|
||||
"message": "报告生成任务开始"
|
||||
"message": t('report.taskStarted')
|
||||
}
|
||||
)
|
||||
|
||||
@@ -115,7 +115,7 @@ class ReportLogger:
|
||||
self.log(
|
||||
action="planning_start",
|
||||
stage="planning",
|
||||
details={"message": "开始规划报告大纲"}
|
||||
details={"message": t('report.planningStart')}
|
||||
)
|
||||
|
||||
def log_planning_context(self, context: Dict[str, Any]):
|
||||
@@ -124,7 +124,7 @@ class ReportLogger:
|
||||
action="planning_context",
|
||||
stage="planning",
|
||||
details={
|
||||
"message": "获取模拟上下文信息",
|
||||
"message": t('report.fetchSimContext'),
|
||||
"context": context
|
||||
}
|
||||
)
|
||||
@@ -135,7 +135,7 @@ class ReportLogger:
|
||||
action="planning_complete",
|
||||
stage="planning",
|
||||
details={
|
||||
"message": "大纲规划完成",
|
||||
"message": t('report.planningComplete'),
|
||||
"outline": outline_dict
|
||||
}
|
||||
)
|
||||
@@ -147,7 +147,7 @@ class ReportLogger:
|
||||
stage="generating",
|
||||
section_title=section_title,
|
||||
section_index=section_index,
|
||||
details={"message": f"开始生成章节: {section_title}"}
|
||||
details={"message": t('report.sectionStart', title=section_title)}
|
||||
)
|
||||
|
||||
def log_react_thought(self, section_title: str, section_index: int, iteration: int, thought: str):
|
||||
@@ -160,7 +160,7 @@ class ReportLogger:
|
||||
details={
|
||||
"iteration": iteration,
|
||||
"thought": thought,
|
||||
"message": f"ReACT 第{iteration}轮思考"
|
||||
"message": t('report.reactThought', iteration=iteration)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -182,7 +182,7 @@ class ReportLogger:
|
||||
"iteration": iteration,
|
||||
"tool_name": tool_name,
|
||||
"parameters": parameters,
|
||||
"message": f"调用工具: {tool_name}"
|
||||
"message": t('report.toolCall', toolName=tool_name)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -205,7 +205,7 @@ class ReportLogger:
|
||||
"tool_name": tool_name,
|
||||
"result": result, # 完整结果,不截断
|
||||
"result_length": len(result),
|
||||
"message": f"工具 {tool_name} 返回结果"
|
||||
"message": t('report.toolResult', toolName=tool_name)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -230,7 +230,7 @@ class ReportLogger:
|
||||
"response_length": len(response),
|
||||
"has_tool_calls": has_tool_calls,
|
||||
"has_final_answer": has_final_answer,
|
||||
"message": f"LLM 响应 (工具调用: {has_tool_calls}, 最终答案: {has_final_answer})"
|
||||
"message": t('report.llmResponse', hasToolCalls=has_tool_calls, hasFinalAnswer=has_final_answer)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -251,7 +251,7 @@ class ReportLogger:
|
||||
"content": content, # 完整内容,不截断
|
||||
"content_length": len(content),
|
||||
"tool_calls_count": tool_calls_count,
|
||||
"message": f"章节 {section_title} 内容生成完成"
|
||||
"message": t('report.sectionContentDone', title=section_title)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -274,7 +274,7 @@ class ReportLogger:
|
||||
details={
|
||||
"content": full_content,
|
||||
"content_length": len(full_content),
|
||||
"message": f"章节 {section_title} 生成完成"
|
||||
"message": t('report.sectionComplete', title=section_title)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -286,7 +286,7 @@ class ReportLogger:
|
||||
details={
|
||||
"total_sections": total_sections,
|
||||
"total_time_seconds": round(total_time_seconds, 2),
|
||||
"message": "报告生成完成"
|
||||
"message": t('report.reportComplete')
|
||||
}
|
||||
)
|
||||
|
||||
@@ -299,7 +299,7 @@ class ReportLogger:
|
||||
section_index=None,
|
||||
details={
|
||||
"error": error_message,
|
||||
"message": f"发生错误: {error_message}"
|
||||
"message": t('report.errorOccurred', error=error_message)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -914,7 +914,7 @@ class ReportAgent:
|
||||
# 控制台日志记录器(在 generate_report 中初始化)
|
||||
self.console_logger: Optional[ReportConsoleLogger] = None
|
||||
|
||||
logger.info(f"ReportAgent 初始化完成: graph_id={graph_id}, simulation_id={simulation_id}")
|
||||
logger.info(t('report.agentInitDone', graphId=graph_id, simulationId=simulation_id))
|
||||
|
||||
def _define_tools(self) -> Dict[str, Dict[str, Any]]:
|
||||
"""定义可用工具"""
|
||||
@@ -965,7 +965,7 @@ class ReportAgent:
|
||||
Returns:
|
||||
工具执行结果(文本格式)
|
||||
"""
|
||||
logger.info(f"执行工具: {tool_name}, 参数: {parameters}")
|
||||
logger.info(t('report.executingTool', toolName=tool_name, params=parameters))
|
||||
|
||||
try:
|
||||
if tool_name == "insight_forge":
|
||||
@@ -1024,7 +1024,7 @@ class ReportAgent:
|
||||
|
||||
elif tool_name == "search_graph":
|
||||
# 重定向到 quick_search
|
||||
logger.info("search_graph 已重定向到 quick_search")
|
||||
logger.info(t('report.redirectToQuickSearch'))
|
||||
return self._execute_tool("quick_search", parameters, report_context)
|
||||
|
||||
elif tool_name == "get_graph_statistics":
|
||||
@@ -1041,7 +1041,7 @@ class ReportAgent:
|
||||
|
||||
elif tool_name == "get_simulation_context":
|
||||
# 重定向到 insight_forge,因为它更强大
|
||||
logger.info("get_simulation_context 已重定向到 insight_forge")
|
||||
logger.info(t('report.redirectToInsightForge'))
|
||||
query = parameters.get("query", self.simulation_requirement)
|
||||
return self._execute_tool("insight_forge", {"query": query}, report_context)
|
||||
|
||||
@@ -1058,7 +1058,7 @@ class ReportAgent:
|
||||
return f"未知工具: {tool_name}。请使用以下工具之一: insight_forge, panorama_search, quick_search"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"工具执行失败: {tool_name}, 错误: {str(e)}")
|
||||
logger.error(t('report.toolExecFailed', toolName=tool_name, error=str(e)))
|
||||
return f"工具执行失败: {str(e)}"
|
||||
|
||||
# 合法的工具名称集合,用于裸 JSON 兜底解析时校验
|
||||
@@ -1149,7 +1149,7 @@ class ReportAgent:
|
||||
Returns:
|
||||
ReportOutline: 报告大纲
|
||||
"""
|
||||
logger.info("开始规划报告大纲...")
|
||||
logger.info(t('report.startPlanningOutline'))
|
||||
|
||||
if progress_callback:
|
||||
progress_callback("planning", 0, t('progress.analyzingRequirements'))
|
||||
@@ -1202,11 +1202,11 @@ class ReportAgent:
|
||||
if progress_callback:
|
||||
progress_callback("planning", 100, t('progress.outlinePlanComplete'))
|
||||
|
||||
logger.info(f"大纲规划完成: {len(sections)} 个章节")
|
||||
logger.info(t('report.outlinePlanDone', count=len(sections)))
|
||||
return outline
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"大纲规划失败: {str(e)}")
|
||||
logger.error(t('report.outlinePlanFailed', error=str(e)))
|
||||
# 返回默认大纲(3个章节,作为fallback)
|
||||
return ReportOutline(
|
||||
title="未来预测报告",
|
||||
@@ -1246,7 +1246,7 @@ class ReportAgent:
|
||||
Returns:
|
||||
章节内容(Markdown格式)
|
||||
"""
|
||||
logger.info(f"ReACT生成章节: {section.title}")
|
||||
logger.info(t('report.reactGenerateSection', title=section.title))
|
||||
|
||||
# 记录章节开始日志
|
||||
if self.report_logger:
|
||||
@@ -1310,7 +1310,7 @@ class ReportAgent:
|
||||
|
||||
# 检查 LLM 返回是否为 None(API 异常或内容为空)
|
||||
if response is None:
|
||||
logger.warning(f"章节 {section.title} 第 {iteration + 1} 次迭代: LLM 返回 None")
|
||||
logger.warning(t('report.sectionIterNone', title=section.title, iteration=iteration + 1))
|
||||
# 如果还有迭代次数,添加消息并重试
|
||||
if iteration < max_iterations - 1:
|
||||
messages.append({"role": "assistant", "content": "(响应为空)"})
|
||||
@@ -1330,8 +1330,7 @@ class ReportAgent:
|
||||
if has_tool_calls and has_final_answer:
|
||||
conflict_retries += 1
|
||||
logger.warning(
|
||||
f"章节 {section.title} 第 {iteration+1} 轮: "
|
||||
f"LLM 同时输出工具调用和 Final Answer(第 {conflict_retries} 次冲突)"
|
||||
t('report.sectionConflict', title=section.title, iteration=iteration+1, conflictCount=conflict_retries)
|
||||
)
|
||||
|
||||
if conflict_retries <= 2:
|
||||
@@ -1351,8 +1350,7 @@ class ReportAgent:
|
||||
else:
|
||||
# 第三次:降级处理,截断到第一个工具调用,强制执行
|
||||
logger.warning(
|
||||
f"章节 {section.title}: 连续 {conflict_retries} 次冲突,"
|
||||
"降级为截断执行第一个工具调用"
|
||||
t('report.sectionConflictDowngrade', title=section.title, conflictCount=conflict_retries)
|
||||
)
|
||||
first_tool_end = response.find('</tool_call>')
|
||||
if first_tool_end != -1:
|
||||
@@ -1392,7 +1390,7 @@ class ReportAgent:
|
||||
|
||||
# 正常结束
|
||||
final_answer = response.split("Final Answer:")[-1].strip()
|
||||
logger.info(f"章节 {section.title} 生成完成(工具调用: {tool_calls_count}次)")
|
||||
logger.info(t('report.sectionGenDone', title=section.title, count=tool_calls_count))
|
||||
|
||||
if self.report_logger:
|
||||
self.report_logger.log_section_content(
|
||||
@@ -1420,7 +1418,7 @@ class ReportAgent:
|
||||
# 只执行第一个工具调用
|
||||
call = tool_calls[0]
|
||||
if len(tool_calls) > 1:
|
||||
logger.info(f"LLM 尝试调用 {len(tool_calls)} 个工具,只执行第一个: {call['name']}")
|
||||
logger.info(t('report.multiToolOnlyFirst', total=len(tool_calls), toolName=call['name']))
|
||||
|
||||
if self.report_logger:
|
||||
self.report_logger.log_tool_call(
|
||||
@@ -1489,7 +1487,7 @@ class ReportAgent:
|
||||
|
||||
# 工具调用已足够,LLM 输出了内容但没带 "Final Answer:" 前缀
|
||||
# 直接将这段内容作为最终答案,不再空转
|
||||
logger.info(f"章节 {section.title} 未检测到 'Final Answer:' 前缀,直接采纳LLM输出作为最终内容(工具调用: {tool_calls_count}次)")
|
||||
logger.info(t('report.sectionNoPrefix', title=section.title, count=tool_calls_count))
|
||||
final_answer = response.strip()
|
||||
|
||||
if self.report_logger:
|
||||
@@ -1502,7 +1500,7 @@ class ReportAgent:
|
||||
return final_answer
|
||||
|
||||
# 达到最大迭代次数,强制生成内容
|
||||
logger.warning(f"章节 {section.title} 达到最大迭代次数,强制生成")
|
||||
logger.warning(t('report.sectionMaxIter', title=section.title))
|
||||
messages.append({"role": "user", "content": REACT_FORCE_FINAL_MSG})
|
||||
|
||||
response = self.llm.chat(
|
||||
@@ -1513,8 +1511,8 @@ class ReportAgent:
|
||||
|
||||
# 检查强制收尾时 LLM 返回是否为 None
|
||||
if response is None:
|
||||
logger.error(f"章节 {section.title} 强制收尾时 LLM 返回 None,使用默认错误提示")
|
||||
final_answer = f"(本章节生成失败:LLM 返回空响应,请稍后重试)"
|
||||
logger.error(t('report.sectionForceFailed', title=section.title))
|
||||
final_answer = t('report.sectionGenFailedContent')
|
||||
elif "Final Answer:" in response:
|
||||
final_answer = response.split("Final Answer:")[-1].strip()
|
||||
else:
|
||||
@@ -1627,7 +1625,7 @@ class ReportAgent:
|
||||
)
|
||||
ReportManager.save_report(report)
|
||||
|
||||
logger.info(f"大纲已保存到文件: {report_id}/outline.json")
|
||||
logger.info(t('report.outlineSavedToFile', reportId=report_id))
|
||||
|
||||
# 阶段2: 逐章节生成(分章节保存)
|
||||
report.status = ReportStatus.GENERATING
|
||||
@@ -1685,7 +1683,7 @@ class ReportAgent:
|
||||
full_content=full_section_content.strip()
|
||||
)
|
||||
|
||||
logger.info(f"章节已保存: {report_id}/section_{section_num:02d}.md")
|
||||
logger.info(t('report.sectionSaved', reportId=report_id, sectionNum=f"{section_num:02d}"))
|
||||
|
||||
# 更新进度
|
||||
ReportManager.update_progress(
|
||||
@@ -1730,7 +1728,7 @@ class ReportAgent:
|
||||
if progress_callback:
|
||||
progress_callback("completed", 100, t('progress.reportComplete'))
|
||||
|
||||
logger.info(f"报告生成完成: {report_id}")
|
||||
logger.info(t('report.reportGenDone', reportId=report_id))
|
||||
|
||||
# 关闭控制台日志记录器
|
||||
if self.console_logger:
|
||||
@@ -1740,7 +1738,7 @@ class ReportAgent:
|
||||
return report
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"报告生成失败: {str(e)}")
|
||||
logger.error(t('report.reportGenFailed', error=str(e)))
|
||||
report.status = ReportStatus.FAILED
|
||||
report.error = str(e)
|
||||
|
||||
@@ -1786,7 +1784,7 @@ class ReportAgent:
|
||||
"sources": [信息来源]
|
||||
}
|
||||
"""
|
||||
logger.info(f"Report Agent对话: {message[:50]}...")
|
||||
logger.info(t('report.agentChat', message=message[:50]))
|
||||
|
||||
chat_history = chat_history or []
|
||||
|
||||
@@ -1800,7 +1798,7 @@ class ReportAgent:
|
||||
if len(report.markdown_content) > 15000:
|
||||
report_content += "\n\n... [报告内容已截断] ..."
|
||||
except Exception as e:
|
||||
logger.warning(f"获取报告内容失败: {e}")
|
||||
logger.warning(t('report.fetchReportFailed', error=e))
|
||||
|
||||
system_prompt = CHAT_SYSTEM_PROMPT_TEMPLATE.format(
|
||||
simulation_requirement=self.simulation_requirement,
|
||||
@@ -2091,7 +2089,7 @@ class ReportManager:
|
||||
with open(cls._get_outline_path(report_id), 'w', encoding='utf-8') as f:
|
||||
json.dump(outline.to_dict(), f, ensure_ascii=False, indent=2)
|
||||
|
||||
logger.info(f"大纲已保存: {report_id}")
|
||||
logger.info(t('report.outlineSaved', reportId=report_id))
|
||||
|
||||
@classmethod
|
||||
def save_section(
|
||||
@@ -2127,7 +2125,7 @@ class ReportManager:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(md_content)
|
||||
|
||||
logger.info(f"章节已保存: {report_id}/{file_suffix}")
|
||||
logger.info(t('report.sectionFileSaved', reportId=report_id, fileSuffix=file_suffix))
|
||||
return file_path
|
||||
|
||||
@classmethod
|
||||
@@ -2296,7 +2294,7 @@ class ReportManager:
|
||||
with open(full_path, 'w', encoding='utf-8') as f:
|
||||
f.write(md_content)
|
||||
|
||||
logger.info(f"完整报告已组装: {report_id}")
|
||||
logger.info(t('report.fullReportAssembled', reportId=report_id))
|
||||
return md_content
|
||||
|
||||
@classmethod
|
||||
@@ -2443,7 +2441,7 @@ class ReportManager:
|
||||
with open(cls._get_report_markdown_path(report.report_id), 'w', encoding='utf-8') as f:
|
||||
f.write(report.markdown_content)
|
||||
|
||||
logger.info(f"报告已保存: {report.report_id}")
|
||||
logger.info(t('report.reportSaved', reportId=report.report_id))
|
||||
|
||||
@classmethod
|
||||
def get_report(cls, report_id: str) -> Optional[Report]:
|
||||
@@ -2556,7 +2554,7 @@ class ReportManager:
|
||||
# 新格式:删除整个文件夹
|
||||
if os.path.exists(folder_path) and os.path.isdir(folder_path):
|
||||
shutil.rmtree(folder_path)
|
||||
logger.info(f"报告文件夹已删除: {report_id}")
|
||||
logger.info(t('report.reportFolderDeleted', reportId=report_id))
|
||||
return True
|
||||
|
||||
# 兼容旧格式:删除单独的文件
|
||||
|
||||
Reference in New Issue
Block a user