feat(i18n): replace all user-visible Chinese logger messages in zep_tools.py
These are shown to users via ConsoleLogger in the report page.
This commit is contained in:
parent
e79569ab4f
commit
24e9bee5be
|
|
@ -18,7 +18,7 @@ from zep_cloud.client import Zep
|
|||
from ..config import Config
|
||||
from ..utils.logger import get_logger
|
||||
from ..utils.llm_client import LLMClient
|
||||
from ..utils.locale import get_locale
|
||||
from ..utils.locale import get_locale, t
|
||||
from ..utils.zep_paging import fetch_all_nodes, fetch_all_edges
|
||||
|
||||
logger = get_logger('mirofish.zep_tools')
|
||||
|
|
@ -430,7 +430,7 @@ class ZepToolsService:
|
|||
self.client = Zep(api_key=self.api_key)
|
||||
# LLM客户端用于InsightForge生成子问题
|
||||
self._llm_client = llm_client
|
||||
logger.info("ZepToolsService 初始化完成")
|
||||
logger.info(t("console.zepToolsInitialized"))
|
||||
|
||||
@property
|
||||
def llm(self) -> LLMClient:
|
||||
|
|
@ -452,13 +452,12 @@ class ZepToolsService:
|
|||
last_exception = e
|
||||
if attempt < max_retries - 1:
|
||||
logger.warning(
|
||||
f"Zep {operation_name} 第 {attempt + 1} 次尝试失败: {str(e)[:100]}, "
|
||||
f"{delay:.1f}秒后重试..."
|
||||
t("console.zepRetryAttempt", operation=operation_name, attempt=attempt + 1, error=str(e)[:100], delay=f"{delay:.1f}")
|
||||
)
|
||||
time.sleep(delay)
|
||||
delay *= 2
|
||||
else:
|
||||
logger.error(f"Zep {operation_name} 在 {max_retries} 次尝试后仍失败: {str(e)}")
|
||||
logger.error(t("console.zepAllRetriesFailed", operation=operation_name, retries=max_retries, error=str(e)))
|
||||
|
||||
raise last_exception
|
||||
|
||||
|
|
@ -484,7 +483,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
SearchResult: 搜索结果
|
||||
"""
|
||||
logger.info(f"图谱搜索: graph_id={graph_id}, query={query[:50]}...")
|
||||
logger.info(t("console.graphSearch", graphId=graph_id, query=query[:50]))
|
||||
|
||||
# 尝试使用Zep Cloud Search API
|
||||
try:
|
||||
|
|
@ -496,7 +495,7 @@ class ZepToolsService:
|
|||
scope=scope,
|
||||
reranker="cross_encoder"
|
||||
),
|
||||
operation_name=f"图谱搜索(graph={graph_id})"
|
||||
operation_name=t("console.graphSearchOp", graphId=graph_id)
|
||||
)
|
||||
|
||||
facts = []
|
||||
|
|
@ -529,7 +528,7 @@ class ZepToolsService:
|
|||
if hasattr(node, 'summary') and node.summary:
|
||||
facts.append(f"[{node.name}]: {node.summary}")
|
||||
|
||||
logger.info(f"搜索完成: 找到 {len(facts)} 条相关事实")
|
||||
logger.info(t("console.searchComplete", count=len(facts)))
|
||||
|
||||
return SearchResult(
|
||||
facts=facts,
|
||||
|
|
@ -540,7 +539,7 @@ class ZepToolsService:
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Zep Search API失败,降级为本地搜索: {str(e)}")
|
||||
logger.warning(t("console.zepSearchApiFallback", error=str(e)))
|
||||
# 降级:使用本地关键词匹配搜索
|
||||
return self._local_search(graph_id, query, limit, scope)
|
||||
|
||||
|
|
@ -565,7 +564,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
SearchResult: 搜索结果
|
||||
"""
|
||||
logger.info(f"使用本地搜索: query={query[:30]}...")
|
||||
logger.info(t("console.usingLocalSearch", query=query[:30]))
|
||||
|
||||
facts = []
|
||||
edges_result = []
|
||||
|
|
@ -635,10 +634,10 @@ class ZepToolsService:
|
|||
if node.summary:
|
||||
facts.append(f"[{node.name}]: {node.summary}")
|
||||
|
||||
logger.info(f"本地搜索完成: 找到 {len(facts)} 条相关事实")
|
||||
logger.info(t("console.localSearchComplete", count=len(facts)))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"本地搜索失败: {str(e)}")
|
||||
logger.error(t("console.localSearchFailed", error=str(e)))
|
||||
|
||||
return SearchResult(
|
||||
facts=facts,
|
||||
|
|
@ -658,7 +657,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
节点列表
|
||||
"""
|
||||
logger.info(f"获取图谱 {graph_id} 的所有节点...")
|
||||
logger.info(t("console.fetchingAllNodes", graphId=graph_id))
|
||||
|
||||
nodes = fetch_all_nodes(self.client, graph_id)
|
||||
|
||||
|
|
@ -673,7 +672,7 @@ class ZepToolsService:
|
|||
attributes=node.attributes or {}
|
||||
))
|
||||
|
||||
logger.info(f"获取到 {len(result)} 个节点")
|
||||
logger.info(t("console.fetchedNodes", count=len(result)))
|
||||
return result
|
||||
|
||||
def get_all_edges(self, graph_id: str, include_temporal: bool = True) -> List[EdgeInfo]:
|
||||
|
|
@ -687,7 +686,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
边列表(包含created_at, valid_at, invalid_at, expired_at)
|
||||
"""
|
||||
logger.info(f"获取图谱 {graph_id} 的所有边...")
|
||||
logger.info(t("console.fetchingAllEdges", graphId=graph_id))
|
||||
|
||||
edges = fetch_all_edges(self.client, graph_id)
|
||||
|
||||
|
|
@ -711,7 +710,7 @@ class ZepToolsService:
|
|||
|
||||
result.append(edge_info)
|
||||
|
||||
logger.info(f"获取到 {len(result)} 条边")
|
||||
logger.info(t("console.fetchedEdges", count=len(result)))
|
||||
return result
|
||||
|
||||
def get_node_detail(self, node_uuid: str) -> Optional[NodeInfo]:
|
||||
|
|
@ -724,12 +723,12 @@ class ZepToolsService:
|
|||
Returns:
|
||||
节点信息或None
|
||||
"""
|
||||
logger.info(f"获取节点详情: {node_uuid[:8]}...")
|
||||
logger.info(t("console.fetchingNodeDetail", uuid=node_uuid[:8]))
|
||||
|
||||
try:
|
||||
node = self._call_with_retry(
|
||||
func=lambda: self.client.graph.node.get(uuid_=node_uuid),
|
||||
operation_name=f"获取节点详情(uuid={node_uuid[:8]}...)"
|
||||
operation_name=t("console.fetchNodeDetailOp", uuid=node_uuid[:8])
|
||||
)
|
||||
|
||||
if not node:
|
||||
|
|
@ -743,7 +742,7 @@ class ZepToolsService:
|
|||
attributes=node.attributes or {}
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"获取节点详情失败: {str(e)}")
|
||||
logger.error(t("console.fetchNodeDetailFailed", error=str(e)))
|
||||
return None
|
||||
|
||||
def get_node_edges(self, graph_id: str, node_uuid: str) -> List[EdgeInfo]:
|
||||
|
|
@ -759,7 +758,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
边列表
|
||||
"""
|
||||
logger.info(f"获取节点 {node_uuid[:8]}... 的相关边")
|
||||
logger.info(t("console.fetchingNodeEdges", uuid=node_uuid[:8]))
|
||||
|
||||
try:
|
||||
# 获取图谱所有边,然后过滤
|
||||
|
|
@ -771,11 +770,11 @@ class ZepToolsService:
|
|||
if edge.source_node_uuid == node_uuid or edge.target_node_uuid == node_uuid:
|
||||
result.append(edge)
|
||||
|
||||
logger.info(f"找到 {len(result)} 条与节点相关的边")
|
||||
logger.info(t("console.foundNodeEdges", count=len(result)))
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"获取节点边失败: {str(e)}")
|
||||
logger.warning(t("console.fetchNodeEdgesFailed", error=str(e)))
|
||||
return []
|
||||
|
||||
def get_entities_by_type(
|
||||
|
|
@ -793,7 +792,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
符合类型的实体列表
|
||||
"""
|
||||
logger.info(f"获取类型为 {entity_type} 的实体...")
|
||||
logger.info(t("console.fetchingEntitiesByType", type=entity_type))
|
||||
|
||||
all_nodes = self.get_all_nodes(graph_id)
|
||||
|
||||
|
|
@ -803,7 +802,7 @@ class ZepToolsService:
|
|||
if entity_type in node.labels:
|
||||
filtered.append(node)
|
||||
|
||||
logger.info(f"找到 {len(filtered)} 个 {entity_type} 类型的实体")
|
||||
logger.info(t("console.foundEntitiesByType", count=len(filtered), type=entity_type))
|
||||
return filtered
|
||||
|
||||
def get_entity_summary(
|
||||
|
|
@ -823,7 +822,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
实体摘要信息
|
||||
"""
|
||||
logger.info(f"获取实体 {entity_name} 的关系摘要...")
|
||||
logger.info(t("console.fetchingEntitySummary", name=entity_name))
|
||||
|
||||
# 先搜索该实体相关的信息
|
||||
search_result = self.search_graph(
|
||||
|
|
@ -863,7 +862,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
统计信息
|
||||
"""
|
||||
logger.info(f"获取图谱 {graph_id} 的统计信息...")
|
||||
logger.info(t("console.fetchingGraphStats", graphId=graph_id))
|
||||
|
||||
nodes = self.get_all_nodes(graph_id)
|
||||
edges = self.get_all_edges(graph_id)
|
||||
|
|
@ -907,7 +906,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
模拟上下文信息
|
||||
"""
|
||||
logger.info(f"获取模拟上下文: {simulation_requirement[:50]}...")
|
||||
logger.info(t("console.fetchingSimContext", requirement=simulation_requirement[:50]))
|
||||
|
||||
# 搜索与模拟需求相关的信息
|
||||
search_result = self.search_graph(
|
||||
|
|
@ -971,7 +970,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
InsightForgeResult: 深度洞察检索结果
|
||||
"""
|
||||
logger.info(f"InsightForge 深度洞察检索: {query[:50]}...")
|
||||
logger.info(t("console.insightForgeStart", query=query[:50]))
|
||||
|
||||
result = InsightForgeResult(
|
||||
query=query,
|
||||
|
|
@ -987,7 +986,7 @@ class ZepToolsService:
|
|||
max_queries=max_sub_queries
|
||||
)
|
||||
result.sub_queries = sub_queries
|
||||
logger.info(f"生成 {len(sub_queries)} 个子问题")
|
||||
logger.info(t("console.generatedSubQueries", count=len(sub_queries)))
|
||||
|
||||
# Step 2: 对每个子问题进行语义搜索
|
||||
all_facts = []
|
||||
|
|
@ -1087,7 +1086,7 @@ class ZepToolsService:
|
|||
result.relationship_chains = relationship_chains
|
||||
result.total_relationships = len(relationship_chains)
|
||||
|
||||
logger.info(f"InsightForge完成: {result.total_facts}条事实, {result.total_entities}个实体, {result.total_relationships}条关系")
|
||||
logger.info(t("console.insightForgeComplete", facts=result.total_facts, entities=result.total_entities, relationships=result.total_relationships))
|
||||
return result
|
||||
|
||||
def _generate_sub_queries(
|
||||
|
|
@ -1134,7 +1133,7 @@ class ZepToolsService:
|
|||
return [str(sq) for sq in sub_queries[:max_queries]]
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"生成子问题失败: {str(e)},使用默认子问题")
|
||||
logger.warning(t("console.generateSubQueriesFailed", error=str(e)))
|
||||
# 降级:返回基于原问题的变体
|
||||
return [
|
||||
query,
|
||||
|
|
@ -1169,7 +1168,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
PanoramaResult: 广度搜索结果
|
||||
"""
|
||||
logger.info(f"PanoramaSearch 广度搜索: {query[:50]}...")
|
||||
logger.info(t("console.panoramaSearchStart", query=query[:50]))
|
||||
|
||||
result = PanoramaResult(query=query)
|
||||
|
||||
|
|
@ -1232,7 +1231,7 @@ class ZepToolsService:
|
|||
result.active_count = len(active_facts)
|
||||
result.historical_count = len(historical_facts)
|
||||
|
||||
logger.info(f"PanoramaSearch完成: {result.active_count}条有效, {result.historical_count}条历史")
|
||||
logger.info(t("console.panoramaSearchComplete", active=result.active_count, historical=result.historical_count))
|
||||
return result
|
||||
|
||||
def quick_search(
|
||||
|
|
@ -1257,7 +1256,7 @@ class ZepToolsService:
|
|||
Returns:
|
||||
SearchResult: 搜索结果
|
||||
"""
|
||||
logger.info(f"QuickSearch 简单搜索: {query[:50]}...")
|
||||
logger.info(t("console.quickSearchStart", query=query[:50]))
|
||||
|
||||
# 直接调用现有的search_graph方法
|
||||
result = self.search_graph(
|
||||
|
|
@ -1267,7 +1266,7 @@ class ZepToolsService:
|
|||
scope="edges"
|
||||
)
|
||||
|
||||
logger.info(f"QuickSearch完成: {result.total_count}条结果")
|
||||
logger.info(t("console.quickSearchComplete", count=result.total_count))
|
||||
return result
|
||||
|
||||
def interview_agents(
|
||||
|
|
@ -1307,7 +1306,7 @@ class ZepToolsService:
|
|||
"""
|
||||
from .simulation_runner import SimulationRunner
|
||||
|
||||
logger.info(f"InterviewAgents 深度采访(真实API): {interview_requirement[:50]}...")
|
||||
logger.info(t("console.interviewAgentsStart", requirement=interview_requirement[:50]))
|
||||
|
||||
result = InterviewResult(
|
||||
interview_topic=interview_requirement,
|
||||
|
|
@ -1318,12 +1317,12 @@ class ZepToolsService:
|
|||
profiles = self._load_agent_profiles(simulation_id)
|
||||
|
||||
if not profiles:
|
||||
logger.warning(f"未找到模拟 {simulation_id} 的人设文件")
|
||||
logger.warning(t("console.profilesNotFound", simId=simulation_id))
|
||||
result.summary = "未找到可采访的Agent人设文件"
|
||||
return result
|
||||
|
||||
result.total_agents = len(profiles)
|
||||
logger.info(f"加载到 {len(profiles)} 个Agent人设")
|
||||
logger.info(t("console.loadedProfiles", count=len(profiles)))
|
||||
|
||||
# Step 2: 使用LLM选择要采访的Agent(返回agent_id列表)
|
||||
selected_agents, selected_indices, selection_reasoning = self._select_agents_for_interview(
|
||||
|
|
@ -1335,7 +1334,7 @@ class ZepToolsService:
|
|||
|
||||
result.selected_agents = selected_agents
|
||||
result.selection_reasoning = selection_reasoning
|
||||
logger.info(f"选择了 {len(selected_agents)} 个Agent进行采访: {selected_indices}")
|
||||
logger.info(t("console.selectedAgentsForInterview", count=len(selected_agents), indices=selected_indices))
|
||||
|
||||
# Step 3: 生成采访问题(如果没有提供)
|
||||
if not result.interview_questions:
|
||||
|
|
@ -1344,7 +1343,7 @@ class ZepToolsService:
|
|||
simulation_requirement=simulation_requirement,
|
||||
selected_agents=selected_agents
|
||||
)
|
||||
logger.info(f"生成了 {len(result.interview_questions)} 个采访问题")
|
||||
logger.info(t("console.generatedInterviewQuestions", count=len(result.interview_questions)))
|
||||
|
||||
# 将问题合并为一个采访prompt
|
||||
combined_prompt = "\n".join([f"{i+1}. {q}" for i, q in enumerate(result.interview_questions)])
|
||||
|
|
@ -1374,7 +1373,7 @@ class ZepToolsService:
|
|||
# 不指定platform,API会在twitter和reddit两个平台都采访
|
||||
})
|
||||
|
||||
logger.info(f"调用批量采访API(双平台): {len(interviews_request)} 个Agent")
|
||||
logger.info(t("console.callingBatchInterviewApi", count=len(interviews_request)))
|
||||
|
||||
# 调用 SimulationRunner 的批量采访方法(不传platform,双平台采访)
|
||||
api_result = SimulationRunner.interview_agents_batch(
|
||||
|
|
@ -1384,12 +1383,12 @@ class ZepToolsService:
|
|||
timeout=180.0 # 双平台需要更长超时
|
||||
)
|
||||
|
||||
logger.info(f"采访API返回: {api_result.get('interviews_count', 0)} 个结果, success={api_result.get('success')}")
|
||||
logger.info(t("console.interviewApiReturned", count=api_result.get('interviews_count', 0), success=api_result.get('success')))
|
||||
|
||||
# 检查API调用是否成功
|
||||
if not api_result.get("success", False):
|
||||
error_msg = api_result.get("error", "未知错误")
|
||||
logger.warning(f"采访API返回失败: {error_msg}")
|
||||
logger.warning(t("console.interviewApiReturnedFailure", error=error_msg))
|
||||
result.summary = f"采访API调用失败:{error_msg}。请检查OASIS模拟环境状态。"
|
||||
return result
|
||||
|
||||
|
|
@ -1462,11 +1461,11 @@ class ZepToolsService:
|
|||
|
||||
except ValueError as e:
|
||||
# 模拟环境未运行
|
||||
logger.warning(f"采访API调用失败(环境未运行?): {e}")
|
||||
logger.warning(t("console.interviewApiCallFailed", error=e))
|
||||
result.summary = f"采访失败:{str(e)}。模拟环境可能已关闭,请确保OASIS环境正在运行。"
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"采访API调用异常: {e}")
|
||||
logger.error(t("console.interviewApiCallException", error=e))
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
result.summary = f"采访过程发生错误:{str(e)}"
|
||||
|
|
@ -1479,7 +1478,7 @@ class ZepToolsService:
|
|||
interview_requirement=interview_requirement
|
||||
)
|
||||
|
||||
logger.info(f"InterviewAgents完成: 采访了 {result.interviewed_count} 个Agent(双平台)")
|
||||
logger.info(t("console.interviewAgentsComplete", count=result.interviewed_count))
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -1522,10 +1521,10 @@ class ZepToolsService:
|
|||
try:
|
||||
with open(reddit_profile_path, 'r', encoding='utf-8') as f:
|
||||
profiles = json.load(f)
|
||||
logger.info(f"从 reddit_profiles.json 加载了 {len(profiles)} 个人设")
|
||||
logger.info(t("console.loadedRedditProfiles", count=len(profiles)))
|
||||
return profiles
|
||||
except Exception as e:
|
||||
logger.warning(f"读取 reddit_profiles.json 失败: {e}")
|
||||
logger.warning(t("console.readRedditProfilesFailed", error=e))
|
||||
|
||||
# 尝试读取Twitter CSV格式
|
||||
twitter_profile_path = os.path.join(sim_dir, "twitter_profiles.csv")
|
||||
|
|
@ -1542,10 +1541,10 @@ class ZepToolsService:
|
|||
"persona": row.get("user_char", ""),
|
||||
"profession": "未知"
|
||||
})
|
||||
logger.info(f"从 twitter_profiles.csv 加载了 {len(profiles)} 个人设")
|
||||
logger.info(t("console.loadedTwitterProfiles", count=len(profiles)))
|
||||
return profiles
|
||||
except Exception as e:
|
||||
logger.warning(f"读取 twitter_profiles.csv 失败: {e}")
|
||||
logger.warning(t("console.readTwitterProfilesFailed", error=e))
|
||||
|
||||
return profiles
|
||||
|
||||
|
|
@ -1626,7 +1625,7 @@ class ZepToolsService:
|
|||
return selected_agents, valid_indices, reasoning
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"LLM选择Agent失败,使用默认选择: {e}")
|
||||
logger.warning(t("console.llmSelectAgentFailed", error=e))
|
||||
# 降级:选择前N个
|
||||
selected = profiles[:max_agents]
|
||||
indices = list(range(min(max_agents, len(profiles))))
|
||||
|
|
@ -1674,7 +1673,7 @@ class ZepToolsService:
|
|||
return response.get("questions", [f"关于{interview_requirement},您有什么看法?"])
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"生成采访问题失败: {e}")
|
||||
logger.warning(t("console.generateInterviewQuestionsFailed", error=e))
|
||||
return [
|
||||
f"关于{interview_requirement},您的观点是什么?",
|
||||
"这件事对您或您所代表的群体有什么影响?",
|
||||
|
|
@ -1732,6 +1731,6 @@ class ZepToolsService:
|
|||
return summary
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"生成采访摘要失败: {e}")
|
||||
logger.warning(t("console.generateInterviewSummaryFailed", error=e))
|
||||
# 降级:简单拼接
|
||||
return f"共采访了{len(interviews)}位受访者,包括:" + "、".join([i.agent_name for i in interviews])
|
||||
|
|
|
|||
Loading…
Reference in New Issue