| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- Stage 7 独立运行脚本
- 从 Stage 6 结果开始,进行深度解构分析
- 支持指定 feature 和数量限制
- """
- import os
- import json
- import logging
- import argparse
- from stage7_analyzer import Stage7DeconstructionAnalyzer
- # 配置日志
- logging.basicConfig(
- level=logging.INFO,
- format='%(asctime)s - %(levelname)s - %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S',
- handlers=[
- logging.FileHandler('stage7_standalone.log', encoding='utf-8'),
- logging.StreamHandler()
- ]
- )
- logger = logging.getLogger(__name__)
- def main():
- """主函数"""
- parser = argparse.ArgumentParser(
- description='Stage 7 深度解构分析(独立运行)',
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog='''
- 示例用法:
- # 只处理"墨镜"特征的前10个高分帖子
- python3 run_stage7.py --feature "墨镜" --max-notes 10
- # 处理"墨镜"和"耳环"两个特征,每个最多5个
- python3 run_stage7.py --feature "墨镜" "耳环" --max-notes 5
- # 处理所有特征,按时间排序,前20个
- python3 run_stage7.py --sort-by time --max-notes 20
- # 只处理"墨镜",按互动量排序,跳过前3个
- python3 run_stage7.py --feature "墨镜" --sort-by engagement --skip 3
- # 降低分数阈值,处理更多帖子
- python3 run_stage7.py --feature "墨镜" --min-score 6.0 --max-notes 30
- # 使用配置文件
- python3 run_stage7.py --config stage7_config.json
- '''
- )
- # 输入输出配置
- parser.add_argument(
- '--input',
- default='output_v2/stage6_with_evaluations.json',
- help='Stage 6 结果文件路径(默认: output_v2/stage6_with_evaluations.json)'
- )
- parser.add_argument(
- '--output',
- default='output_v2/stage7_with_deconstruction.json',
- help='Stage 7 输出文件路径(默认: output_v2/stage7_with_deconstruction.json)'
- )
- # Feature 过滤(新增)
- parser.add_argument(
- '--feature',
- nargs='+',
- default=None,
- help='指定要处理的原始特征名称(可指定多个),如: --feature "墨镜" "耳环"。不指定则处理所有特征'
- )
- # 过滤参数
- parser.add_argument(
- '--min-score',
- type=float,
- default=8.0,
- help='最低分数阈值,只处理 >= 此分数的帖子(默认: 8.0)'
- )
- parser.add_argument(
- '--skip',
- type=int,
- default=0,
- help='跳过前 N 个帖子(默认: 0)'
- )
- parser.add_argument(
- '--max-notes',
- type=int,
- default=None,
- help='最多处理多少个帖子(默认: None 不限制)'
- )
- parser.add_argument(
- '--sort-by',
- choices=['score', 'time', 'engagement'],
- default='score',
- help='排序方式: score(评分), time(时间), engagement(互动量)(默认: score)'
- )
- # API 配置
- parser.add_argument(
- '--api-url',
- default='http://192.168.245.150:7000/what/analysis/single',
- help='解构 API 地址(默认: http://192.168.245.150:7000/what/analysis/single)'
- )
- parser.add_argument(
- '--timeout',
- type=int,
- default=30,
- help='API 超时时间(秒)(默认: 30)'
- )
- parser.add_argument(
- '--max-retries',
- type=int,
- default=3,
- help='API 最大重试次数(默认: 3)'
- )
- # 并发配置
- parser.add_argument(
- '--max-workers',
- type=int,
- default=5,
- help='并发处理数(默认: 5)'
- )
- # 从配置文件加载
- parser.add_argument(
- '--config',
- default=None,
- help='从 JSON 配置文件加载参数'
- )
- args = parser.parse_args()
- # 如果提供了配置文件,加载配置
- if args.config:
- logger.info(f"从配置文件加载参数: {args.config}")
- with open(args.config, 'r', encoding='utf-8') as f:
- config = json.load(f)
- # 配置文件中的参数会覆盖命令行参数
- for key, value in config.items():
- setattr(args, key.replace('-', '_'), value)
- # 检查输入文件是否存在
- if not os.path.exists(args.input):
- logger.error(f"输入文件不存在: {args.input}")
- return
- # 加载 Stage 6 结果
- logger.info(f"加载 Stage 6 结果: {args.input}")
- with open(args.input, 'r', encoding='utf-8') as f:
- stage6_results = json.load(f)
- # 打印配置
- logger.info("=" * 60)
- logger.info("运行配置:")
- logger.info(f" 输入文件: {args.input}")
- logger.info(f" 输出文件: {args.output}")
- if args.feature:
- logger.info(f" 指定特征: {', '.join(args.feature)}")
- else:
- logger.info(f" 指定特征: 全部")
- logger.info(f" API 地址: {args.api_url}")
- logger.info(f" 最低分数阈值: {args.min_score}")
- logger.info(f" 跳过前 N 个: {args.skip}")
- logger.info(f" 最多处理数: {args.max_notes if args.max_notes else '不限制'}")
- logger.info(f" 排序方式: {args.sort_by}")
- logger.info(f" 并发数: {args.max_workers}")
- logger.info(f" API 超时: {args.timeout}秒")
- logger.info(f" 最大重试: {args.max_retries}次")
- logger.info("=" * 60)
- # 创建分析器
- analyzer = Stage7DeconstructionAnalyzer(
- api_url=args.api_url,
- max_workers=args.max_workers,
- max_notes=args.max_notes,
- min_score=args.min_score,
- skip_count=args.skip,
- sort_by=args.sort_by,
- timeout=args.timeout,
- max_retries=args.max_retries,
- output_dir=os.path.dirname(args.output) or 'output_v2',
- target_features=args.feature # 传递 feature 过滤参数
- )
- # 运行分析
- try:
- stage7_results = analyzer.run(
- stage6_results=stage6_results,
- output_path=args.output
- )
- # 打印结果摘要
- logger.info("\n" + "=" * 60)
- logger.info("执行完成!")
- logger.info(f" 总匹配帖子数: {stage7_results['metadata']['total_matched_notes']}")
- logger.info(f" 实际处理数: {stage7_results['metadata']['processed_notes']}")
- logger.info(f" 成功: {stage7_results['metadata']['success_count']}")
- logger.info(f" 失败: {stage7_results['metadata']['failed_count']}")
- logger.info(f" 总耗时: {stage7_results['metadata']['processing_time_seconds']}秒")
- logger.info(f" 结果已保存: {args.output}")
- logger.info("=" * 60)
- except Exception as e:
- logger.error(f"执行失败: {e}", exc_info=True)
- raise
- if __name__ == '__main__':
- main()
|