|
|
@@ -41,9 +41,72 @@ class FunctionKnowledge:
|
|
|
self.prompt_dir = os.path.join(current_dir, "prompt")
|
|
|
self.use_cache = use_cache
|
|
|
self.cache = CacheManager() if use_cache else None
|
|
|
+
|
|
|
+ # 执行详情收集
|
|
|
+ self.execution_detail = {
|
|
|
+ "generate_query": {},
|
|
|
+ "select_tool": {},
|
|
|
+ "extract_params": {},
|
|
|
+ "execution_time": 0,
|
|
|
+ "cache_hits": []
|
|
|
+ }
|
|
|
+
|
|
|
logger.info(f"缓存状态: {'启用' if use_cache else '禁用'}")
|
|
|
logger.info("=" * 80)
|
|
|
|
|
|
+ def _save_execution_detail(self, cache_key: str):
|
|
|
+ """保存执行详情到缓存(支持合并旧记录)"""
|
|
|
+ if not self.use_cache or not self.cache:
|
|
|
+ return
|
|
|
+
|
|
|
+ try:
|
|
|
+ import hashlib
|
|
|
+ question_hash = hashlib.md5(cache_key.encode('utf-8')).hexdigest()[:12]
|
|
|
+ detail_dir = os.path.join(
|
|
|
+ self.cache.base_cache_dir,
|
|
|
+ question_hash,
|
|
|
+ 'function_knowledge'
|
|
|
+ )
|
|
|
+ os.makedirs(detail_dir, exist_ok=True)
|
|
|
+
|
|
|
+ detail_file = os.path.join(detail_dir, 'execution_detail.json')
|
|
|
+
|
|
|
+ # 准备最终要保存的数据,默认为当前内存中的数据
|
|
|
+ final_detail = self.execution_detail.copy()
|
|
|
+
|
|
|
+ # 尝试读取旧文件进行合并
|
|
|
+ if os.path.exists(detail_file):
|
|
|
+ try:
|
|
|
+ with open(detail_file, 'r', encoding='utf-8') as f:
|
|
|
+ old_detail = json.load(f)
|
|
|
+
|
|
|
+ # 智能合并逻辑:保留更有价值的历史信息
|
|
|
+ for key, new_val in self.execution_detail.items():
|
|
|
+ # 跳过非字典字段或旧文件中不存在的字段
|
|
|
+ if not isinstance(new_val, dict) or key not in old_detail:
|
|
|
+ continue
|
|
|
+
|
|
|
+ old_val = old_detail[key]
|
|
|
+ if not isinstance(old_val, dict):
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 核心逻辑:如果新记录是缓存命中(cached=True),而旧记录包含prompt(说明是当初生成的)
|
|
|
+ # 则保留旧记录,防止被简略信息覆盖
|
|
|
+ if new_val.get("cached", False) is True and "prompt" in old_val:
|
|
|
+ # logger.debug(f" 保留 {key} 的历史详细记录")
|
|
|
+ final_detail[key] = old_val
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ logger.warning(f" ⚠ 读取旧详情失败,将使用新记录: {e}")
|
|
|
+
|
|
|
+ with open(detail_file, 'w', encoding='utf-8') as f:
|
|
|
+ json.dump(final_detail, f, ensure_ascii=False, indent=2)
|
|
|
+
|
|
|
+ logger.info(f"✓ 执行详情已保存: {detail_file}")
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"✗ 保存执行详情失败: {e}")
|
|
|
+
|
|
|
def _load_prompt(self, filename: str) -> str:
|
|
|
"""加载prompt文件内容"""
|
|
|
prompt_path = os.path.join(self.prompt_dir, filename)
|
|
|
@@ -52,29 +115,26 @@ class FunctionKnowledge:
|
|
|
with open(prompt_path, 'r', encoding='utf-8') as f:
|
|
|
return f.read().strip()
|
|
|
|
|
|
- def generate_query(self, question: str, post_info: str, persona_info: str) -> tuple:
|
|
|
+ def generate_query(self, question: str, post_info: str, persona_info: str) -> str:
|
|
|
"""
|
|
|
生成查询语句
|
|
|
|
|
|
Returns:
|
|
|
- tuple: (query, detail_info)
|
|
|
- - query: 生成的查询语句
|
|
|
- - detail_info: 详细信息dict,包含prompt和response
|
|
|
+ str: 生成的查询语句
|
|
|
"""
|
|
|
logger.info(f"[步骤1] 生成Query...")
|
|
|
|
|
|
# 组合问题的唯一标识
|
|
|
combined_question = f"{question}||{post_info}||{persona_info}"
|
|
|
|
|
|
- detail_info = {"cached": False, "prompt": None, "response": None}
|
|
|
-
|
|
|
# 尝试从缓存读取
|
|
|
if self.use_cache:
|
|
|
cached_query = self.cache.get(combined_question, 'function_knowledge', 'generated_query.txt')
|
|
|
if cached_query:
|
|
|
logger.info(f"✓ 使用缓存的Query: {cached_query}")
|
|
|
- detail_info["cached"] = True
|
|
|
- return cached_query, detail_info
|
|
|
+ # 记录缓存命中
|
|
|
+ self.execution_detail["generate_query"].update({"cached": True, "query": cached_query})
|
|
|
+ return cached_query
|
|
|
|
|
|
try:
|
|
|
prompt_template = self._load_prompt("function_generate_query_prompt.md")
|
|
|
@@ -84,53 +144,57 @@ class FunctionKnowledge:
|
|
|
persona_info=persona_info
|
|
|
)
|
|
|
|
|
|
- detail_info["prompt"] = prompt
|
|
|
-
|
|
|
logger.info("→ 调用Gemini生成Query...")
|
|
|
query = generate_text(prompt=prompt)
|
|
|
query = query.strip()
|
|
|
|
|
|
- detail_info["response"] = query
|
|
|
-
|
|
|
logger.info(f"✓ 生成Query: {query}")
|
|
|
|
|
|
# 写入缓存
|
|
|
if self.use_cache:
|
|
|
self.cache.set(combined_question, 'function_knowledge', 'generated_query.txt', query)
|
|
|
|
|
|
- return query, detail_info
|
|
|
+ # 记录详情
|
|
|
+ self.execution_detail["generate_query"] = {
|
|
|
+ "cached": False,
|
|
|
+ "prompt": prompt,
|
|
|
+ "response": query,
|
|
|
+ "query": query
|
|
|
+ }
|
|
|
+
|
|
|
+ return query
|
|
|
except Exception as e:
|
|
|
logger.error(f"✗ 生成Query失败: {e}")
|
|
|
- detail_info["error"] = str(e)
|
|
|
- return question, detail_info # 降级使用原问题
|
|
|
+ return question # 降级使用原问题
|
|
|
|
|
|
- def select_tool(self, combined_question: str, query: str) -> tuple:
|
|
|
+ def select_tool(self, combined_question: str, query: str) -> str:
|
|
|
"""
|
|
|
选择合适的工具
|
|
|
|
|
|
Returns:
|
|
|
- tuple: (tool_name, detail_info)
|
|
|
+ str: 工具名称,如果没有合适的工具则返回"None"
|
|
|
"""
|
|
|
logger.info(f"[步骤2] 选择工具...")
|
|
|
|
|
|
- detail_info = {"cached": False, "prompt": None, "response": None, "available_tools_count": 0}
|
|
|
-
|
|
|
# 尝试从缓存读取
|
|
|
if self.use_cache:
|
|
|
cached_tool = self.cache.get(combined_question, 'function_knowledge', 'selected_tool.txt')
|
|
|
if cached_tool:
|
|
|
logger.info(f"✓ 使用缓存的工具: {cached_tool}")
|
|
|
- detail_info["cached"] = True
|
|
|
- return cached_tool, detail_info
|
|
|
+ # 记录缓存命中
|
|
|
+ self.execution_detail["select_tool"].update({
|
|
|
+ "cached": True,
|
|
|
+ "tool_name": cached_tool
|
|
|
+ })
|
|
|
+ return cached_tool
|
|
|
|
|
|
try:
|
|
|
all_tool_infos = get_all_tool_infos()
|
|
|
if not all_tool_infos:
|
|
|
logger.info(" 工具库为空,无可用工具")
|
|
|
- return "None", detail_info
|
|
|
+ return "None"
|
|
|
|
|
|
tool_count = len(all_tool_infos.split('--- Tool:')) - 1
|
|
|
- detail_info["available_tools_count"] = tool_count
|
|
|
logger.info(f" 当前可用工具数: {tool_count}")
|
|
|
|
|
|
prompt_template = self._load_prompt("function_knowledge_select_tools_prompt.md")
|
|
|
@@ -139,28 +203,31 @@ class FunctionKnowledge:
|
|
|
tool_infos=all_tool_infos
|
|
|
)
|
|
|
|
|
|
- detail_info["prompt"] = prompt
|
|
|
- detail_info["tool_infos"] = all_tool_infos
|
|
|
-
|
|
|
logger.info("→ 调用Gemini选择工具...")
|
|
|
tool_name = generate_text(prompt=prompt)
|
|
|
tool_name = tool_name.strip()
|
|
|
|
|
|
- detail_info["response"] = tool_name
|
|
|
-
|
|
|
logger.info(f"✓ 选择结果: {tool_name}")
|
|
|
|
|
|
# 写入缓存
|
|
|
if self.use_cache:
|
|
|
self.cache.set(combined_question, 'function_knowledge', 'selected_tool.txt', tool_name)
|
|
|
|
|
|
- return tool_name, detail_info
|
|
|
+ # 记录详情
|
|
|
+ self.execution_detail["select_tool"] = {
|
|
|
+ "cached": False,
|
|
|
+ "prompt": prompt,
|
|
|
+ "response": tool_name,
|
|
|
+ "tool_name": tool_name,
|
|
|
+ "available_tools_count": tool_count
|
|
|
+ }
|
|
|
+
|
|
|
+ return tool_name
|
|
|
except Exception as e:
|
|
|
logger.error(f"✗ 选择工具失败: {e}")
|
|
|
- detail_info["error"] = str(e)
|
|
|
- return "None", detail_info
|
|
|
+ return "None"
|
|
|
|
|
|
- def extract_tool_params(self, combined_question: str, tool_name: str, query: str) -> tuple:
|
|
|
+ def extract_tool_params(self, combined_question: str, tool_name: str, query: str) -> dict:
|
|
|
"""
|
|
|
根据工具信息和查询提取调用参数
|
|
|
|
|
|
@@ -170,32 +237,29 @@ class FunctionKnowledge:
|
|
|
query: 查询内容
|
|
|
|
|
|
Returns:
|
|
|
- tuple: (params, detail_info)
|
|
|
+ dict: 提取的参数字典
|
|
|
"""
|
|
|
logger.info(f"[步骤3] 提取工具参数...")
|
|
|
|
|
|
- # 初始化detail_info
|
|
|
- detail_info = {"cached": False, "prompt": None, "response": None, "tool_info": None}
|
|
|
-
|
|
|
# 尝试从缓存读取
|
|
|
if self.use_cache:
|
|
|
cached_params = self.cache.get(combined_question, 'function_knowledge', 'tool_params.json')
|
|
|
if cached_params:
|
|
|
logger.info(f"✓ 使用缓存的参数: {cached_params}")
|
|
|
- detail_info["cached"] = True
|
|
|
- return cached_params, detail_info
|
|
|
+ # 记录缓存命中
|
|
|
+ self.execution_detail["extract_params"].update({
|
|
|
+ "cached": True,
|
|
|
+ "params": cached_params
|
|
|
+ })
|
|
|
+ return cached_params
|
|
|
|
|
|
try:
|
|
|
# 获取工具信息
|
|
|
tool_info = get_tool_info(tool_name)
|
|
|
if not tool_info:
|
|
|
logger.warning(f" ⚠ 未找到工具 {tool_name} 的信息,使用默认参数")
|
|
|
- # 降级:使用query作为keyword
|
|
|
- default_params = {"keyword": query}
|
|
|
- detail_info["fallback"] = "tool_info_not_found"
|
|
|
- return default_params, detail_info
|
|
|
+ return {"keyword": query}
|
|
|
|
|
|
- detail_info["tool_info"] = tool_info
|
|
|
logger.info(f" 工具 {tool_name} 信息长度: {len(tool_info)}")
|
|
|
|
|
|
# 加载prompt
|
|
|
@@ -205,12 +269,9 @@ class FunctionKnowledge:
|
|
|
tool_info=tool_info
|
|
|
)
|
|
|
|
|
|
- detail_info["prompt"] = prompt
|
|
|
-
|
|
|
# 调用LLM提取参数
|
|
|
logger.info(" → 调用Gemini提取参数...")
|
|
|
response_text = generate_text(prompt=prompt)
|
|
|
- detail_info["response"] = response_text
|
|
|
|
|
|
# 解析JSON
|
|
|
logger.info(" → 解析参数JSON...")
|
|
|
@@ -233,7 +294,15 @@ class FunctionKnowledge:
|
|
|
if self.use_cache:
|
|
|
self.cache.set(combined_question, 'function_knowledge', 'tool_params.json', params)
|
|
|
|
|
|
- return params, detail_info
|
|
|
+ # 记录详情
|
|
|
+ self.execution_detail["extract_params"].update({
|
|
|
+ "cached": False,
|
|
|
+ "prompt": prompt,
|
|
|
+ "response": response_text,
|
|
|
+ "params": params
|
|
|
+ })
|
|
|
+
|
|
|
+ return params
|
|
|
|
|
|
except json.JSONDecodeError as e:
|
|
|
logger.error(f" ✗ 解析JSON失败: {e}")
|
|
|
@@ -241,16 +310,12 @@ class FunctionKnowledge:
|
|
|
# 降级:使用query作为keyword
|
|
|
default_params = {"keyword": query}
|
|
|
logger.warning(f" 使用默认参数: {default_params}")
|
|
|
- detail_info["fallback"] = "json_decode_error"
|
|
|
- return default_params, detail_info
|
|
|
+ return default_params
|
|
|
|
|
|
except Exception as e:
|
|
|
logger.error(f"✗ 提取工具参数失败: {e}")
|
|
|
# 降级:使用query作为keyword
|
|
|
- default_params = {"keyword": query}
|
|
|
- detail_info["error"] = str(e)
|
|
|
- detail_info["fallback"] = "exception"
|
|
|
- return default_params, detail_info
|
|
|
+ return {"keyword": query}
|
|
|
|
|
|
def save_knowledge_to_file(self, knowledge: str, combined_question: str):
|
|
|
"""保存获取到的知识到文件"""
|
|
|
@@ -282,20 +347,14 @@ class FunctionKnowledge:
|
|
|
|
|
|
def get_knowledge(self, question: str, post_info: str, persona_info: str) -> dict:
|
|
|
"""
|
|
|
- 获取方法知识的主流程
|
|
|
+ 获取方法知识的主流程(重构后)
|
|
|
|
|
|
Returns:
|
|
|
- dict: 包含完整执行信息的字典
|
|
|
- {
|
|
|
- "input": {...}, # 原始输入
|
|
|
- "execution": {...}, # 执行过程信息
|
|
|
- "result": {...}, # 最终结果
|
|
|
- "metadata": {...} # 元数据
|
|
|
- }
|
|
|
+ dict: 完整的执行记录
|
|
|
"""
|
|
|
import time
|
|
|
- start_time = time.time()
|
|
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ start_time = time.time()
|
|
|
|
|
|
logger.info("=" * 80)
|
|
|
logger.info(f"Function Knowledge - 开始处理")
|
|
|
@@ -307,86 +366,17 @@ class FunctionKnowledge:
|
|
|
# 组合问题的唯一标识
|
|
|
combined_question = f"{question}||{post_info}||{persona_info}"
|
|
|
|
|
|
- # 初始化执行记录
|
|
|
- execution_record = {
|
|
|
- "input": {
|
|
|
- "question": question,
|
|
|
- "post_info": post_info,
|
|
|
- "persona_info": persona_info,
|
|
|
- "timestamp": timestamp
|
|
|
- },
|
|
|
- "execution": {
|
|
|
- "steps": [],
|
|
|
- "tool_info": None,
|
|
|
- "knowledge_search_info": None
|
|
|
- },
|
|
|
- "result": {
|
|
|
- "type": None, # "tool" 或 "knowledge"
|
|
|
- "content": None,
|
|
|
- "raw_data": None
|
|
|
- },
|
|
|
- "metadata": {
|
|
|
- "execution_time": None,
|
|
|
- "cache_hits": [],
|
|
|
- "errors": []
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- # 检查最终结果缓存
|
|
|
- if self.use_cache:
|
|
|
- cached_final = self.cache.get(combined_question, 'function_knowledge', 'final_result.json')
|
|
|
- if cached_final:
|
|
|
- logger.info(f"✓ 使用缓存的最终结果")
|
|
|
- logger.info("=" * 80 + "\n")
|
|
|
- # 如果是完整的执行记录,直接返回
|
|
|
- if isinstance(cached_final, dict) and "execution" in cached_final:
|
|
|
- return cached_final
|
|
|
- # 否则构造一个简单的返回
|
|
|
- return {
|
|
|
- "input": execution_record["input"],
|
|
|
- "execution": {"cached": True},
|
|
|
- "result": {"type": "cached", "content": cached_final},
|
|
|
- "metadata": {"cache_hit": True}
|
|
|
- }
|
|
|
-
|
|
|
try:
|
|
|
# 步骤1: 生成Query
|
|
|
- step1_start = time.time()
|
|
|
- query, query_detail = self.generate_query(question, post_info, persona_info)
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 1,
|
|
|
- "name": "generate_query",
|
|
|
- "duration": time.time() - step1_start,
|
|
|
- "output": query,
|
|
|
- "detail": query_detail # 包含prompt和response
|
|
|
- })
|
|
|
+ query = self.generate_query(question, post_info, persona_info)
|
|
|
|
|
|
# 步骤2: 选择工具
|
|
|
- step2_start = time.time()
|
|
|
- tool_name, tool_select_detail = self.select_tool(combined_question, query)
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 2,
|
|
|
- "name": "select_tool",
|
|
|
- "duration": time.time() - step2_start,
|
|
|
- "output": tool_name,
|
|
|
- "detail": tool_select_detail # 包含prompt、response和可用工具列表
|
|
|
- })
|
|
|
+ tool_name = self.select_tool(combined_question, query)
|
|
|
|
|
|
- result_content = None
|
|
|
if tool_name and tool_name != "None":
|
|
|
# 路径A: 使用工具
|
|
|
- execution_record["result"]["type"] = "tool"
|
|
|
-
|
|
|
# 步骤3: 提取参数
|
|
|
- step3_start = time.time()
|
|
|
- arguments, params_detail = self.extract_tool_params(combined_question, tool_name, query)
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 3,
|
|
|
- "name": "extract_tool_params",
|
|
|
- "duration": time.time() - step3_start,
|
|
|
- "output": arguments,
|
|
|
- "detail": params_detail # 包含prompt、response和工具信息
|
|
|
- })
|
|
|
+ arguments = self.extract_tool_params(combined_question, tool_name, query)
|
|
|
|
|
|
# 步骤4: 调用工具
|
|
|
logger.info(f"[步骤4] 调用工具: {tool_name}")
|
|
|
@@ -396,102 +386,52 @@ class FunctionKnowledge:
|
|
|
cached_tool_result = self.cache.get(combined_question, 'function_knowledge', 'tool_result.json')
|
|
|
if cached_tool_result:
|
|
|
logger.info(f"✓ 使用缓存的工具调用结果")
|
|
|
- execution_record["metadata"]["cache_hits"].append("tool_result")
|
|
|
tool_result = cached_tool_result
|
|
|
else:
|
|
|
- step4_start = time.time()
|
|
|
logger.info(f" → 调用工具,参数: {arguments}")
|
|
|
tool_result = call_tool(tool_name, arguments)
|
|
|
-
|
|
|
# 缓存工具调用结果
|
|
|
self.cache.set(combined_question, 'function_knowledge', 'tool_result.json', tool_result)
|
|
|
-
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 4,
|
|
|
- "name": "call_tool",
|
|
|
- "duration": time.time() - step4_start,
|
|
|
- "output": "success"
|
|
|
- })
|
|
|
else:
|
|
|
- step4_start = time.time()
|
|
|
logger.info(f" → 调用工具,参数: {arguments}")
|
|
|
tool_result = call_tool(tool_name, arguments)
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 4,
|
|
|
- "name": "call_tool",
|
|
|
- "duration": time.time() - step4_start,
|
|
|
- "output": "success"
|
|
|
- })
|
|
|
-
|
|
|
- # 记录工具调用信息
|
|
|
- execution_record["execution"]["tool_info"] = {
|
|
|
- "tool_name": tool_name,
|
|
|
- "parameters": arguments,
|
|
|
- "result": tool_result
|
|
|
- }
|
|
|
-
|
|
|
- result_content = f"工具 {tool_name} 执行结果: {json.dumps(tool_result, ensure_ascii=False)}"
|
|
|
- execution_record["result"]["content"] = result_content
|
|
|
- execution_record["result"]["raw_data"] = tool_result
|
|
|
|
|
|
logger.info(f"✓ 工具调用完成")
|
|
|
|
|
|
else:
|
|
|
# 路径B: 知识搜索
|
|
|
- execution_record["result"]["type"] = "knowledge_search"
|
|
|
-
|
|
|
logger.info("[步骤4] 未找到合适工具,调用 MultiSearch...")
|
|
|
|
|
|
- step4_start = time.time()
|
|
|
knowledge = get_multi_search_knowledge(query, cache_key=combined_question)
|
|
|
|
|
|
- execution_record["execution"]["steps"].append({
|
|
|
- "step": 4,
|
|
|
- "name": "multi_search_knowledge",
|
|
|
- "duration": time.time() - step4_start,
|
|
|
- "output": f"knowledge_length: {len(knowledge)}"
|
|
|
- })
|
|
|
-
|
|
|
- # 记录知识搜索信息
|
|
|
- execution_record["execution"]["knowledge_search_info"] = {
|
|
|
- "query": query,
|
|
|
- "knowledge_length": len(knowledge),
|
|
|
- "source": "multi_search"
|
|
|
- }
|
|
|
-
|
|
|
- result_content = knowledge
|
|
|
- execution_record["result"]["content"] = knowledge
|
|
|
- execution_record["result"]["raw_data"] = {"knowledge": knowledge, "query": query}
|
|
|
-
|
|
|
- # 异步生成新工具
|
|
|
- logger.info("[后台任务] 启动新工具生成线程...")
|
|
|
+ # 异步保存知识到文件
|
|
|
+ logger.info("[后台任务] 保存知识到文件...")
|
|
|
threading.Thread(target=self.save_knowledge_to_file, args=(knowledge, combined_question)).start()
|
|
|
- # 计算总执行时间
|
|
|
- execution_record["metadata"]["execution_time"] = time.time() - start_time
|
|
|
|
|
|
- # 保存完整的执行记录到JSON文件
|
|
|
- if self.use_cache:
|
|
|
- self.cache.set(combined_question, 'function_knowledge', 'final_result.json', execution_record)
|
|
|
-
|
|
|
- # 同时保存一个格式化的JSON文件供人类阅读
|
|
|
- from knowledge_v2.cache_manager import CacheManager
|
|
|
- cache = CacheManager()
|
|
|
- import hashlib
|
|
|
- question_hash = hashlib.md5(combined_question.encode('utf-8')).hexdigest()[:12]
|
|
|
- output_file = os.path.join(cache.base_cache_dir, question_hash, 'execution_record.json')
|
|
|
-
|
|
|
- try:
|
|
|
- with open(output_file, 'w', encoding='utf-8') as f:
|
|
|
- json.dump(execution_record, f, ensure_ascii=False, indent=2)
|
|
|
- logger.info(f"✓ 完整执行记录已保存: {output_file}")
|
|
|
- except Exception as e:
|
|
|
- logger.error(f"保存执行记录失败: {e}")
|
|
|
+ # 计算执行时间并保存详情
|
|
|
+ self.execution_detail["execution_time"] = time.time() - start_time
|
|
|
+ self._save_execution_detail(combined_question)
|
|
|
+
|
|
|
+ # 收集所有执行记录
|
|
|
+ logger.info("=" * 80)
|
|
|
+ logger.info("收集执行记录...")
|
|
|
+ logger.info("=" * 80)
|
|
|
+
|
|
|
+ from knowledge_v2.execution_collector import collect_and_save_execution_record
|
|
|
+
|
|
|
+ execution_record = collect_and_save_execution_record(
|
|
|
+ combined_question,
|
|
|
+ {
|
|
|
+ "question": question,
|
|
|
+ "post_info": post_info,
|
|
|
+ "persona_info": persona_info,
|
|
|
+ "timestamp": timestamp
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
logger.info("=" * 80)
|
|
|
logger.info(f"✓ Function Knowledge 完成")
|
|
|
- logger.info(f" 类型: {execution_record['result']['type']}")
|
|
|
- logger.info(f" 结果长度: {len(result_content) if result_content else 0}")
|
|
|
- logger.info(f" 执行时间: {execution_record['metadata']['execution_time']:.2f}秒")
|
|
|
+ logger.info(f" 执行时间: {execution_record.get('metadata', {}).get('execution_time', 0):.2f}秒")
|
|
|
logger.info("=" * 80 + "\n")
|
|
|
|
|
|
return execution_record
|
|
|
@@ -499,27 +439,42 @@ class FunctionKnowledge:
|
|
|
except Exception as e:
|
|
|
logger.error(f"✗ 执行失败: {e}")
|
|
|
import traceback
|
|
|
- error_trace = traceback.format_exc()
|
|
|
-
|
|
|
- execution_record["metadata"]["errors"].append({
|
|
|
- "error": str(e),
|
|
|
- "traceback": error_trace
|
|
|
- })
|
|
|
- execution_record["result"]["type"] = "error"
|
|
|
- execution_record["result"]["content"] = f"执行失败: {str(e)}"
|
|
|
- execution_record["metadata"]["execution_time"] = time.time() - start_time
|
|
|
+ logger.error(traceback.format_exc())
|
|
|
|
|
|
- return execution_record
|
|
|
-
|
|
|
-def get_knowledge(question: str, post_info: str, persona_info: str) -> dict:
|
|
|
- """
|
|
|
- 便捷调用函数
|
|
|
-
|
|
|
- Returns:
|
|
|
- dict: 完整的执行记录,包含输入、执行过程、结果和元数据
|
|
|
- """
|
|
|
- agent = FunctionKnowledge()
|
|
|
- return agent.get_knowledge(question, post_info, persona_info)
|
|
|
+ # 即使失败也尝试保存详情和收集记录
|
|
|
+ try:
|
|
|
+ self.execution_detail["execution_time"] = time.time() - start_time
|
|
|
+ self._save_execution_detail(combined_question)
|
|
|
+
|
|
|
+ from knowledge_v2.execution_collector import collect_and_save_execution_record
|
|
|
+ execution_record = collect_and_save_execution_record(
|
|
|
+ combined_question,
|
|
|
+ {
|
|
|
+ "question": question,
|
|
|
+ "post_info": post_info,
|
|
|
+ "persona_info": persona_info,
|
|
|
+ "timestamp": timestamp
|
|
|
+ }
|
|
|
+ )
|
|
|
+ return execution_record
|
|
|
+ except Exception as collect_error:
|
|
|
+ logger.error(f"收集执行记录也失败: {collect_error}")
|
|
|
+ # 返回基本错误信息
|
|
|
+ return {
|
|
|
+ "input": {
|
|
|
+ "question": question,
|
|
|
+ "post_info": post_info,
|
|
|
+ "persona_info": persona_info,
|
|
|
+ "timestamp": timestamp
|
|
|
+ },
|
|
|
+ "result": {
|
|
|
+ "type": "error",
|
|
|
+ "content": f"执行失败: {str(e)}"
|
|
|
+ },
|
|
|
+ "metadata": {
|
|
|
+ "errors": [str(e)]
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
# 测试代码
|
|
|
@@ -533,9 +488,7 @@ if __name__ == "__main__":
|
|
|
print("=" * 50)
|
|
|
print("执行结果:")
|
|
|
print("=" * 50)
|
|
|
- print(f"类型: {execution_result['result']['type']}")
|
|
|
- print(f"内容预览: {execution_result['result']['content'][:200]}...")
|
|
|
- print(f"执行时间: {execution_result['metadata']['execution_time']:.2f}秒")
|
|
|
+ print(json.dumps(execution_result, ensure_ascii=False, indent=2))
|
|
|
print(f"\n完整JSON已保存到缓存目录")
|
|
|
except Exception as e:
|
|
|
logger.error(f"测试失败: {e}")
|