run_stage7.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Stage 7 独立运行脚本
  5. 从 Stage 6 结果开始,进行深度解构分析
  6. 支持指定 feature 和数量限制
  7. """
  8. import os
  9. import json
  10. import logging
  11. import argparse
  12. from stage7_analyzer import Stage7DeconstructionAnalyzer
  13. # 配置日志
  14. logging.basicConfig(
  15. level=logging.INFO,
  16. format='%(asctime)s - %(levelname)s - %(message)s',
  17. datefmt='%Y-%m-%d %H:%M:%S',
  18. handlers=[
  19. logging.FileHandler('stage7_standalone.log', encoding='utf-8'),
  20. logging.StreamHandler()
  21. ]
  22. )
  23. logger = logging.getLogger(__name__)
  24. def main():
  25. """主函数"""
  26. parser = argparse.ArgumentParser(
  27. description='Stage 7 深度解构分析(独立运行)',
  28. formatter_class=argparse.RawDescriptionHelpFormatter,
  29. epilog='''
  30. 示例用法:
  31. # 只处理"墨镜"特征的前10个高分帖子
  32. python3 run_stage7.py --feature "墨镜" --max-notes 10
  33. # 处理"墨镜"和"耳环"两个特征,每个最多5个
  34. python3 run_stage7.py --feature "墨镜" "耳环" --max-notes 5
  35. # 处理所有特征,按时间排序,前20个
  36. python3 run_stage7.py --sort-by time --max-notes 20
  37. # 只处理"墨镜",按互动量排序,跳过前3个
  38. python3 run_stage7.py --feature "墨镜" --sort-by engagement --skip 3
  39. # 降低分数阈值,处理更多帖子
  40. python3 run_stage7.py --feature "墨镜" --min-score 6.0 --max-notes 30
  41. # 使用配置文件
  42. python3 run_stage7.py --config stage7_config.json
  43. '''
  44. )
  45. # 输入输出配置
  46. parser.add_argument(
  47. '--input',
  48. default='output_v2/stage6_with_evaluations.json',
  49. help='Stage 6 结果文件路径(默认: output_v2/stage6_with_evaluations.json)'
  50. )
  51. parser.add_argument(
  52. '--output',
  53. default='output_v2/stage7_with_deconstruction.json',
  54. help='Stage 7 输出文件路径(默认: output_v2/stage7_with_deconstruction.json)'
  55. )
  56. # Feature 过滤(新增)
  57. parser.add_argument(
  58. '--feature',
  59. nargs='+',
  60. default=None,
  61. help='指定要处理的原始特征名称(可指定多个),如: --feature "墨镜" "耳环"。不指定则处理所有特征'
  62. )
  63. # 过滤参数
  64. parser.add_argument(
  65. '--min-score',
  66. type=float,
  67. default=8.0,
  68. help='最低分数阈值,只处理 >= 此分数的帖子(默认: 8.0)'
  69. )
  70. parser.add_argument(
  71. '--skip',
  72. type=int,
  73. default=0,
  74. help='跳过前 N 个帖子(默认: 0)'
  75. )
  76. parser.add_argument(
  77. '--max-notes',
  78. type=int,
  79. default=None,
  80. help='最多处理多少个帖子(默认: None 不限制)'
  81. )
  82. parser.add_argument(
  83. '--sort-by',
  84. choices=['score', 'time', 'engagement'],
  85. default='score',
  86. help='排序方式: score(评分), time(时间), engagement(互动量)(默认: score)'
  87. )
  88. # API 配置
  89. parser.add_argument(
  90. '--api-url',
  91. default='http://192.168.245.150:7000/what/analysis/single',
  92. help='解构 API 地址(默认: http://192.168.245.150:7000/what/analysis/single)'
  93. )
  94. parser.add_argument(
  95. '--timeout',
  96. type=int,
  97. default=30,
  98. help='API 超时时间(秒)(默认: 30)'
  99. )
  100. parser.add_argument(
  101. '--max-retries',
  102. type=int,
  103. default=3,
  104. help='API 最大重试次数(默认: 3)'
  105. )
  106. # 并发配置
  107. parser.add_argument(
  108. '--max-workers',
  109. type=int,
  110. default=5,
  111. help='并发处理数(默认: 5)'
  112. )
  113. # 从配置文件加载
  114. parser.add_argument(
  115. '--config',
  116. default=None,
  117. help='从 JSON 配置文件加载参数'
  118. )
  119. args = parser.parse_args()
  120. # 如果提供了配置文件,加载配置
  121. if args.config:
  122. logger.info(f"从配置文件加载参数: {args.config}")
  123. with open(args.config, 'r', encoding='utf-8') as f:
  124. config = json.load(f)
  125. # 配置文件中的参数会覆盖命令行参数
  126. for key, value in config.items():
  127. setattr(args, key.replace('-', '_'), value)
  128. # 检查输入文件是否存在
  129. if not os.path.exists(args.input):
  130. logger.error(f"输入文件不存在: {args.input}")
  131. return
  132. # 加载 Stage 6 结果
  133. logger.info(f"加载 Stage 6 结果: {args.input}")
  134. with open(args.input, 'r', encoding='utf-8') as f:
  135. stage6_results = json.load(f)
  136. # 打印配置
  137. logger.info("=" * 60)
  138. logger.info("运行配置:")
  139. logger.info(f" 输入文件: {args.input}")
  140. logger.info(f" 输出文件: {args.output}")
  141. if args.feature:
  142. logger.info(f" 指定特征: {', '.join(args.feature)}")
  143. else:
  144. logger.info(f" 指定特征: 全部")
  145. logger.info(f" API 地址: {args.api_url}")
  146. logger.info(f" 最低分数阈值: {args.min_score}")
  147. logger.info(f" 跳过前 N 个: {args.skip}")
  148. logger.info(f" 最多处理数: {args.max_notes if args.max_notes else '不限制'}")
  149. logger.info(f" 排序方式: {args.sort_by}")
  150. logger.info(f" 并发数: {args.max_workers}")
  151. logger.info(f" API 超时: {args.timeout}秒")
  152. logger.info(f" 最大重试: {args.max_retries}次")
  153. logger.info("=" * 60)
  154. # 创建分析器
  155. analyzer = Stage7DeconstructionAnalyzer(
  156. api_url=args.api_url,
  157. max_workers=args.max_workers,
  158. max_notes=args.max_notes,
  159. min_score=args.min_score,
  160. skip_count=args.skip,
  161. sort_by=args.sort_by,
  162. timeout=args.timeout,
  163. max_retries=args.max_retries,
  164. output_dir=os.path.dirname(args.output) or 'output_v2',
  165. target_features=args.feature # 传递 feature 过滤参数
  166. )
  167. # 运行分析
  168. try:
  169. stage7_results = analyzer.run(
  170. stage6_results=stage6_results,
  171. output_path=args.output
  172. )
  173. # 打印结果摘要
  174. logger.info("\n" + "=" * 60)
  175. logger.info("执行完成!")
  176. logger.info(f" 总匹配帖子数: {stage7_results['metadata']['total_matched_notes']}")
  177. logger.info(f" 实际处理数: {stage7_results['metadata']['processed_notes']}")
  178. logger.info(f" 成功: {stage7_results['metadata']['success_count']}")
  179. logger.info(f" 失败: {stage7_results['metadata']['failed_count']}")
  180. logger.info(f" 总耗时: {stage7_results['metadata']['processing_time_seconds']}秒")
  181. logger.info(f" 结果已保存: {args.output}")
  182. logger.info("=" * 60)
  183. except Exception as e:
  184. logger.error(f"执行失败: {e}", exc_info=True)
  185. raise
  186. if __name__ == '__main__':
  187. main()