| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- """
- 主流程脚本:串联 Step1 和 Step2
- 执行完整的灵感分析流程:
- 1. Step1: 灵感与人设匹配(调用 step1 main,自动保存结果)
- 2. Step2: 增量词在人设中的匹配(调用 step2 main,自动保存结果)
- 3. 生成流程汇总文件
- """
- import os
- import sys
- import json
- import asyncio
- from agents import trace
- from lib.my_trace import set_trace_smith as set_trace
- from lib.data_loader import load_inspiration_list, select_inspiration
- from lib.utils import read_json
- # 导入 step1 和 step2 的 main 函数
- import step1_inspiration_match
- import step2_incremental_match
- def find_step1_output(persona_dir: str, inspiration: str, max_tasks: int = None) -> str:
- """查找 step1 输出文件
- Args:
- persona_dir: 人设目录
- inspiration: 灵感点名称
- max_tasks: 任务数限制
- Returns:
- step1 文件路径
- """
- from pathlib import Path
- step1_dir = os.path.join(persona_dir, "how", "灵感点", inspiration)
- scope_prefix = f"top{max_tasks}" if max_tasks is not None else "all"
- step1_pattern = f"{scope_prefix}_step1_*.json"
- step1_files = list(Path(step1_dir).glob(step1_pattern))
- if not step1_files:
- raise FileNotFoundError(f"找不到 step1 输出文件: {step1_dir}/{step1_pattern}")
- return str(step1_files[0])
- def find_step2_output(persona_dir: str, inspiration: str, max_tasks: int = None) -> str:
- """查找 step2 输出文件
- Args:
- persona_dir: 人设目录
- inspiration: 灵感点名称
- max_tasks: 任务数限制
- Returns:
- step2 文件路径
- """
- from pathlib import Path
- step2_dir = os.path.join(persona_dir, "how", "灵感点", inspiration)
- scope_prefix = f"top{max_tasks}" if max_tasks is not None else "all"
- step2_pattern = f"{scope_prefix}_step2_*.json"
- step2_files = list(Path(step2_dir).glob(step2_pattern))
- if not step2_files:
- raise FileNotFoundError(f"找不到 step2 输出文件: {step2_dir}/{step2_pattern}")
- return str(step2_files[0])
- async def run_full_analysis(
- persona_dir: str,
- inspiration: str,
- max_tasks: int = None,
- current_time: str = None,
- log_url: str = None
- ) -> dict:
- """执行完整的灵感分析流程(Step1 + Step2)
- Args:
- persona_dir: 人设目录路径
- inspiration: 灵感点文本
- max_tasks: step1 最大任务数(None 表示不限制)
- current_time: 当前时间戳
- log_url: 日志链接
- Returns:
- 包含文件路径和状态的字典
- """
- print(f"\n{'=' * 80}")
- print(f"开始完整分析流程: {inspiration}")
- print(f"{'=' * 80}\n")
- # ========== Step1: 灵感与人设匹配 ==========
- print(f"{'─' * 80}")
- print(f"Step1: 灵感与人设匹配")
- print(f"{'─' * 80}\n")
- # 临时修改 sys.argv 来传递参数给 step1
- original_argv = sys.argv.copy()
- sys.argv = [
- "step1_inspiration_match.py",
- persona_dir,
- inspiration,
- str(max_tasks) if max_tasks is not None else "all"
- ]
- try:
- # 调用 step1 的 main 函数
- await step1_inspiration_match.main(current_time, log_url)
- finally:
- # 恢复原始参数
- sys.argv = original_argv
- # 查找 step1 输出文件
- step1_file = find_step1_output(persona_dir, inspiration, max_tasks)
- print(f"✓ Step1 完成,结果文件: {step1_file}\n")
- # 读取 step1 结果
- step1_data = read_json(step1_file)
- step1_results = step1_data.get("匹配结果列表", [])
- if not step1_results:
- print("⚠️ Step1 结果为空,终止流程")
- return {
- "step1_file": step1_file,
- "step2_file": None,
- "summary_file": None,
- "status": "step1_empty"
- }
- step1_top1 = step1_results[0]
- step1_score = step1_top1.get('匹配结果', {}).get('score', 0)
- step1_element = step1_top1.get("业务信息", {}).get("匹配要素", "")
- print(f"Top1 匹配要素: {step1_element}, score: {step1_score:.2f}")
- # ========== Step2: 增量词匹配 ==========
- print(f"\n{'─' * 80}")
- print(f"Step2: 增量词在人设中的匹配")
- print(f"{'─' * 80}\n")
- # 临时修改 sys.argv 来传递参数给 step2
- sys.argv = [
- "step2_incremental_match.py",
- persona_dir,
- inspiration
- ]
- try:
- # 调用 step2 的 main 函数
- await step2_incremental_match.main(current_time, log_url)
- finally:
- # 恢复原始参数
- sys.argv = original_argv
- # 查找 step2 输出文件
- step2_file = find_step2_output(persona_dir, inspiration, max_tasks)
- print(f"✓ Step2 完成,结果文件: {step2_file}\n")
- # 读取 step2 结果
- step2_data = read_json(step2_file)
- step2_score = step2_data.get("匹配结果", {}).get("score", 0)
- step2_b_content = step2_data.get("输入信息", {}).get("B", "")
- step2_word_count = len(step2_b_content.split("\n")) if step2_b_content else 0
- # ========== 保存流程汇总 ==========
- output_dir = os.path.join(persona_dir, "how", "灵感点", inspiration)
- scope_prefix = f"top{max_tasks}" if max_tasks is not None else "all"
- # 从 step1 文件名提取模型名称
- step1_filename = os.path.basename(step1_file)
- model_short = step1_filename.split("_")[-1].replace(".json", "")
- summary_filename = f"{scope_prefix}_summary_完整流程_{model_short}.json"
- summary_file = os.path.join(output_dir, summary_filename)
- summary = {
- "元数据": {
- "current_time": current_time,
- "log_url": log_url,
- "流程": "Step1 + Step2 完整分析",
- "step1_model": step1_data.get("元数据", {}).get("model", ""),
- "step2_model": step2_data.get("元数据", {}).get("model", "")
- },
- "灵感": inspiration,
- "文件路径": {
- "step1": step1_file,
- "step2": step2_file
- },
- "关键指标": {
- "step1_top1_score": step1_score,
- "step1_top1_匹配要素": step1_element,
- "step2_增量词数量": step2_word_count,
- "step2_score": step2_score
- }
- }
- with open(summary_file, 'w', encoding='utf-8') as f:
- json.dump(summary, f, ensure_ascii=False, indent=2)
- print(f"{'=' * 80}")
- print(f"完整流程执行完成")
- print(f"{'=' * 80}")
- print(f"\n结果文件:")
- print(f" Step1: {step1_file}")
- print(f" Step2: {step2_file}")
- print(f" 汇总: {summary_file}\n")
- return {
- "step1_file": step1_file,
- "step2_file": step2_file,
- "summary_file": summary_file,
- "status": "success"
- }
- async def main(current_time: str, log_url: str):
- """主函数"""
- # 解析命令行参数
- persona_dir = sys.argv[1] if len(sys.argv) > 1 else "data/阿里多多酱/out/人设_1110"
- # 第二个参数:灵感数量限制,默认为 1(处理第一个灵感)
- # 可以是数字(如 1, 5, 10)或 "all"(所有灵感)
- inspiration_count_arg = sys.argv[2] if len(sys.argv) > 2 else "1"
- # 第三个参数:step1 任务数限制,默认为 None(所有任务)
- max_tasks = None if len(sys.argv) > 3 and sys.argv[3] == "all" else (
- int(sys.argv[3]) if len(sys.argv) > 3 else None
- )
- print(f"{'=' * 80}")
- print(f"灵感分析主流程 (Step1 + Step2)")
- print(f"{'=' * 80}")
- print(f"人设目录: {persona_dir}")
- # 加载灵感列表
- inspiration_list = load_inspiration_list(persona_dir)
- # 确定要处理的灵感数量
- if inspiration_count_arg == "all":
- inspiration_count = len(inspiration_list)
- print(f"处理灵感: 全部 ({inspiration_count} 个)")
- else:
- inspiration_count = int(inspiration_count_arg)
- print(f"处理灵感: 前 {inspiration_count} 个")
- if max_tasks:
- print(f"Step1 任务数限制: {max_tasks}")
- # 选择要处理的灵感列表
- inspirations_to_process = inspiration_list[:inspiration_count]
- print(f"\n将处理以下灵感:")
- for i, insp in enumerate(inspirations_to_process, 1):
- print(f" {i}. {insp}")
- # 批量执行流程
- results = []
- for i, inspiration in enumerate(inspirations_to_process, 1):
- print(f"\n{'#' * 80}")
- print(f"处理第 {i}/{len(inspirations_to_process)} 个灵感")
- print(f"{'#' * 80}")
- result = await run_full_analysis(
- persona_dir=persona_dir,
- inspiration=inspiration,
- max_tasks=max_tasks,
- current_time=current_time,
- log_url=log_url
- )
- results.append(result)
- # 输出最终汇总
- print(f"\n{'=' * 80}")
- print(f"批量处理完成")
- print(f"{'=' * 80}")
- success_count = sum(1 for r in results if r["status"] == "success")
- print(f"\n成功: {success_count}/{len(results)}")
- for i, (insp, result) in enumerate(zip(inspirations_to_process, results), 1):
- status_icon = "✓" if result["status"] == "success" else "✗"
- print(f" {status_icon} [{i}] {insp}")
- if log_url:
- print(f"\nTrace: {log_url}")
- if __name__ == "__main__":
- # 设置 trace
- current_time, log_url = set_trace()
- # 使用 trace 上下文包裹整个执行流程
- with trace("灵感分析完整流程 (Step1+Step2)"):
- asyncio.run(main(current_time, log_url))
|