|
@@ -450,12 +450,13 @@ def find_qualified_queries(evaluation_results: list[dict], min_relevance_score:
|
|
|
# 主流程
|
|
# 主流程
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
|
|
|
|
|
-async def progressive_exploration(context: RunContext, max_levels: int = 4) -> dict:
|
|
|
|
|
|
|
+async def progressive_exploration(context: RunContext, logger, max_levels: int = 4) -> dict:
|
|
|
"""
|
|
"""
|
|
|
渐进式广度探索流程
|
|
渐进式广度探索流程
|
|
|
|
|
|
|
|
Args:
|
|
Args:
|
|
|
context: 运行上下文
|
|
context: 运行上下文
|
|
|
|
|
+ logger: 结构化日志记录器
|
|
|
max_levels: 最大探索层数,默认4
|
|
max_levels: 最大探索层数,默认4
|
|
|
|
|
|
|
|
返回格式:
|
|
返回格式:
|
|
@@ -467,24 +468,103 @@ async def progressive_exploration(context: RunContext, max_levels: int = 4) -> d
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
# 阶段1:提取关键词(从原始问题提取)
|
|
# 阶段1:提取关键词(从原始问题提取)
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name="提取关键词",
|
|
|
|
|
+ step_type="extraction",
|
|
|
|
|
+ description="从原始问题提取关键词",
|
|
|
|
|
+ input_data={"q": context.q}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
keyword_result = await extract_keywords(context.q)
|
|
keyword_result = await extract_keywords(context.q)
|
|
|
context.keywords = keyword_result.keywords
|
|
context.keywords = keyword_result.keywords
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="keywords",
|
|
|
|
|
+ artifact_data=keyword_result.model_dump()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={"keywords": keyword_result.keywords, "reasoning": keyword_result.reasoning}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
# 阶段2:渐进式探索
|
|
# 阶段2:渐进式探索
|
|
|
current_level = 1
|
|
current_level = 1
|
|
|
|
|
|
|
|
# Level 1:单个关键词
|
|
# Level 1:单个关键词
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name="探索Level 1",
|
|
|
|
|
+ step_type="exploration",
|
|
|
|
|
+ description=f"探索 Level 1:{len(context.keywords[:7])} 个单关键词",
|
|
|
|
|
+ input_data={"queries": context.keywords[:7]}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
level_1_queries = context.keywords[:7] # 限制最多7个关键词
|
|
level_1_queries = context.keywords[:7] # 限制最多7个关键词
|
|
|
level_1_data = await explore_level(level_1_queries, current_level, context)
|
|
level_1_data = await explore_level(level_1_queries, current_level, context)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="level_1_results",
|
|
|
|
|
+ artifact_data=level_1_data
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={"level": 1, "queries_count": len(level_1_queries)}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
# 分析Level 1
|
|
# 分析Level 1
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name="分析Level 1",
|
|
|
|
|
+ step_type="analysis",
|
|
|
|
|
+ description="分析 Level 1 探索结果",
|
|
|
|
|
+ input_data={"level": 1, "queries_count": len(level_1_queries)}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
analysis_1 = await analyze_level(level_1_data, context.exploration_levels, context.q, context)
|
|
analysis_1 = await analyze_level(level_1_data, context.exploration_levels, context.q, context)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="analysis_result",
|
|
|
|
|
+ artifact_data=analysis_1.model_dump()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={
|
|
|
|
|
+ "should_evaluate_now": analysis_1.should_evaluate_now,
|
|
|
|
|
+ "candidates_to_evaluate": analysis_1.candidates_to_evaluate if analysis_1.should_evaluate_now else [],
|
|
|
|
|
+ "next_combinations": analysis_1.next_combinations,
|
|
|
|
|
+ "key_findings": analysis_1.key_findings,
|
|
|
|
|
+ "reasoning": analysis_1.reasoning,
|
|
|
|
|
+ "promising_signals": [s.model_dump() for s in analysis_1.promising_signals]
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
if analysis_1.should_evaluate_now:
|
|
if analysis_1.should_evaluate_now:
|
|
|
# 直接评估
|
|
# 直接评估
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name="评估Level 1候选",
|
|
|
|
|
+ step_type="evaluation",
|
|
|
|
|
+ description=f"评估 Level 1 的 {len(analysis_1.candidates_to_evaluate)} 个候选query",
|
|
|
|
|
+ input_data={"candidates": analysis_1.candidates_to_evaluate}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
eval_results = await evaluate_candidates(analysis_1.candidates_to_evaluate, context.q, context)
|
|
eval_results = await evaluate_candidates(analysis_1.candidates_to_evaluate, context.q, context)
|
|
|
qualified = find_qualified_queries(eval_results, min_relevance_score=0.7)
|
|
qualified = find_qualified_queries(eval_results, min_relevance_score=0.7)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="evaluation_results",
|
|
|
|
|
+ artifact_data=eval_results
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={"qualified_count": len(qualified), "qualified": qualified}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
if qualified:
|
|
if qualified:
|
|
|
return {
|
|
return {
|
|
|
"success": True,
|
|
"success": True,
|
|
@@ -503,16 +583,77 @@ async def progressive_exploration(context: RunContext, max_levels: int = 4) -> d
|
|
|
break
|
|
break
|
|
|
|
|
|
|
|
# 探索当前层
|
|
# 探索当前层
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name=f"探索Level {level_num}",
|
|
|
|
|
+ step_type="exploration",
|
|
|
|
|
+ description=f"探索 Level {level_num}:{len(prev_analysis.next_combinations)} 个组合query",
|
|
|
|
|
+ input_data={"queries": prev_analysis.next_combinations}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
level_data = await explore_level(prev_analysis.next_combinations, level_num, context)
|
|
level_data = await explore_level(prev_analysis.next_combinations, level_num, context)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name=f"level_{level_num}_results",
|
|
|
|
|
+ artifact_data=level_data
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={"level": level_num, "queries_count": len(prev_analysis.next_combinations)}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
# 分析当前层
|
|
# 分析当前层
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name=f"分析Level {level_num}",
|
|
|
|
|
+ step_type="analysis",
|
|
|
|
|
+ description=f"分析 Level {level_num} 探索结果",
|
|
|
|
|
+ input_data={"level": level_num}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
analysis = await analyze_level(level_data, context.exploration_levels, context.q, context)
|
|
analysis = await analyze_level(level_data, context.exploration_levels, context.q, context)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="analysis_result",
|
|
|
|
|
+ artifact_data=analysis.model_dump()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={
|
|
|
|
|
+ "should_evaluate_now": analysis.should_evaluate_now,
|
|
|
|
|
+ "candidates_to_evaluate": analysis.candidates_to_evaluate if analysis.should_evaluate_now else [],
|
|
|
|
|
+ "next_combinations": analysis.next_combinations,
|
|
|
|
|
+ "key_findings": analysis.key_findings,
|
|
|
|
|
+ "reasoning": analysis.reasoning,
|
|
|
|
|
+ "promising_signals": [s.model_dump() for s in analysis.promising_signals]
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
if analysis.should_evaluate_now:
|
|
if analysis.should_evaluate_now:
|
|
|
# 评估候选
|
|
# 评估候选
|
|
|
|
|
+ step_id = logger.start_step(
|
|
|
|
|
+ step_name=f"评估Level {level_num}候选",
|
|
|
|
|
+ step_type="evaluation",
|
|
|
|
|
+ description=f"评估 Level {level_num} 的 {len(analysis.candidates_to_evaluate)} 个候选query",
|
|
|
|
|
+ input_data={"candidates": analysis.candidates_to_evaluate}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
eval_results = await evaluate_candidates(analysis.candidates_to_evaluate, context.q, context)
|
|
eval_results = await evaluate_candidates(analysis.candidates_to_evaluate, context.q, context)
|
|
|
qualified = find_qualified_queries(eval_results, min_relevance_score=0.7)
|
|
qualified = find_qualified_queries(eval_results, min_relevance_score=0.7)
|
|
|
|
|
|
|
|
|
|
+ logger.log_artifact(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ artifact_name="evaluation_results",
|
|
|
|
|
+ artifact_data=eval_results
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ logger.end_step(
|
|
|
|
|
+ step_id=step_id,
|
|
|
|
|
+ output_data={"qualified_count": len(qualified), "qualified": qualified}
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
if qualified:
|
|
if qualified:
|
|
|
return {
|
|
return {
|
|
|
"success": True,
|
|
"success": True,
|
|
@@ -615,26 +756,53 @@ async def main(input_dir: str, max_levels: int = 4):
|
|
|
log_url=log_url,
|
|
log_url=log_url,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- # 执行渐进式探索
|
|
|
|
|
- optimization_result = await progressive_exploration(run_context, max_levels=max_levels)
|
|
|
|
|
-
|
|
|
|
|
- # 格式化输出
|
|
|
|
|
- final_output = format_output(optimization_result, run_context)
|
|
|
|
|
- print(f"\n{'='*60}")
|
|
|
|
|
- print("最终结果")
|
|
|
|
|
- print(f"{'='*60}")
|
|
|
|
|
- print(final_output)
|
|
|
|
|
-
|
|
|
|
|
- # 保存结果
|
|
|
|
|
- run_context.optimization_result = optimization_result
|
|
|
|
|
- run_context.final_output = final_output
|
|
|
|
|
-
|
|
|
|
|
- # 保存 RunContext 到 log_dir
|
|
|
|
|
- os.makedirs(run_context.log_dir, exist_ok=True)
|
|
|
|
|
- context_file_path = os.path.join(run_context.log_dir, "run_context.json")
|
|
|
|
|
- with open(context_file_path, "w", encoding="utf-8") as f:
|
|
|
|
|
- json.dump(run_context.model_dump(), f, ensure_ascii=False, indent=2)
|
|
|
|
|
- print(f"\nRunContext saved to: {context_file_path}")
|
|
|
|
|
|
|
+ # === 初始化结构化日志系统 ===
|
|
|
|
|
+ from lib.structured_logger import StructuredLogger
|
|
|
|
|
+ from sug_v6_1_2_visualizer import visualize_log
|
|
|
|
|
+
|
|
|
|
|
+ logger = StructuredLogger(log_dir=log_dir, run_id=current_time)
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ # 执行渐进式探索
|
|
|
|
|
+ optimization_result = await progressive_exploration(run_context, logger, max_levels=max_levels)
|
|
|
|
|
+
|
|
|
|
|
+ # 格式化输出
|
|
|
|
|
+ final_output = format_output(optimization_result, run_context)
|
|
|
|
|
+ print(f"\n{'='*60}")
|
|
|
|
|
+ print("最终结果")
|
|
|
|
|
+ print(f"{'='*60}")
|
|
|
|
|
+ print(final_output)
|
|
|
|
|
+
|
|
|
|
|
+ # 保存结果
|
|
|
|
|
+ run_context.optimization_result = optimization_result
|
|
|
|
|
+ run_context.final_output = final_output
|
|
|
|
|
+
|
|
|
|
|
+ # 保存 RunContext 到 log_dir(旧版兼容)
|
|
|
|
|
+ os.makedirs(run_context.log_dir, exist_ok=True)
|
|
|
|
|
+ context_file_path = os.path.join(run_context.log_dir, "run_context.json")
|
|
|
|
|
+ with open(context_file_path, "w", encoding="utf-8") as f:
|
|
|
|
|
+ json.dump(run_context.model_dump(), f, ensure_ascii=False, indent=2)
|
|
|
|
|
+ print(f"\nRunContext saved to: {context_file_path}")
|
|
|
|
|
+
|
|
|
|
|
+ # === 完成结构化日志 ===
|
|
|
|
|
+ logger.finalize(
|
|
|
|
|
+ final_status="success",
|
|
|
|
|
+ final_output=optimization_result
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ # === 生成可视化页面 ===
|
|
|
|
|
+ print("\n生成可视化页面...")
|
|
|
|
|
+ visualization_path = visualize_log(logger.log_dir)
|
|
|
|
|
+ print(f"🎨 可视化页面已生成: {visualization_path}")
|
|
|
|
|
+ print(f" 在浏览器中打开查看详细信息")
|
|
|
|
|
+
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ # 出错时也要完成日志记录
|
|
|
|
|
+ logger.finalize(
|
|
|
|
|
+ final_status="error",
|
|
|
|
|
+ final_output={"error": str(e)}
|
|
|
|
|
+ )
|
|
|
|
|
+ raise
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if __name__ == "__main__":
|