analyze_specific_feature.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. """
  2. 分析特定原始特征的搜索执行情况
  3. """
  4. import json
  5. import sys
  6. from typing import Dict, Any, List
  7. def analyze_feature_searches(stage4_path: str, stage6_path: str, feature_name: str):
  8. """分析指定原始特征的搜索情况"""
  9. # 加载数据
  10. with open(stage4_path, 'r', encoding='utf-8') as f:
  11. stage4_data = json.load(f)
  12. with open(stage6_path, 'r', encoding='utf-8') as f:
  13. stage6_data = json.load(f)
  14. # 找到指定特征
  15. stage4_feature = None
  16. stage6_feature = None
  17. for item in stage4_data:
  18. if item['原始特征名称'] == feature_name:
  19. stage4_feature = item
  20. break
  21. for item in stage6_data:
  22. if item['原始特征名称'] == feature_name:
  23. stage6_feature = item
  24. break
  25. if not stage4_feature:
  26. print(f"❌ 在 Stage4 中未找到特征: {feature_name}")
  27. return
  28. if not stage6_feature:
  29. print(f"❌ 在 Stage6 中未找到特征: {feature_name}")
  30. return
  31. print("=" * 80)
  32. print(f"原始特征: {feature_name}")
  33. print("=" * 80)
  34. # 收集 Stage4 的所有搜索词
  35. stage4_search_words = []
  36. for association in stage4_feature.get('找到的关联', []):
  37. assoc_name = association.get('分类名称', '')
  38. for feature in association.get('特征列表', []):
  39. search_word = feature.get('search_word')
  40. llm_eval = feature.get('llm_evaluation', {})
  41. if search_word:
  42. stage4_search_words.append({
  43. 'search_word': search_word,
  44. 'association': assoc_name,
  45. 'feature_name': feature.get('特征名称', ''),
  46. 'llm_score': llm_eval.get('score'),
  47. 'llm_rank': llm_eval.get('rank'),
  48. 'reasoning': llm_eval.get('reasoning', '')
  49. })
  50. # 收集 Stage6 的所有搜索词及其执行状态
  51. stage6_search_words = []
  52. for association in stage6_feature.get('找到的关联', []):
  53. assoc_name = association.get('分类名称', '')
  54. for feature in association.get('特征列表', []):
  55. search_word = feature.get('search_word')
  56. search_result = feature.get('search_result')
  57. search_metadata = feature.get('search_metadata', {})
  58. llm_eval = feature.get('llm_evaluation', {})
  59. if search_word:
  60. stage6_search_words.append({
  61. 'search_word': search_word,
  62. 'association': assoc_name,
  63. 'feature_name': feature.get('特征名称', ''),
  64. 'llm_score': llm_eval.get('score'),
  65. 'llm_rank': llm_eval.get('rank'),
  66. 'has_result': search_result is not None,
  67. 'status': search_metadata.get('status', 'not_searched'),
  68. 'note_count': search_metadata.get('note_count', 0)
  69. })
  70. # 统计
  71. total_stage4 = len(stage4_search_words)
  72. total_stage6 = len(stage6_search_words)
  73. searched = sum(1 for w in stage6_search_words if w['has_result'])
  74. not_searched = total_stage6 - searched
  75. print(f"\n📊 统计信息:")
  76. print(f" Stage4 生成的搜索词数: {total_stage4}")
  77. print(f" Stage6 保留的搜索词数: {total_stage6}")
  78. print(f" 已执行搜索: {searched} 个")
  79. print(f" 未执行搜索: {not_searched} 个")
  80. print(f" 搜索执行率: {searched/total_stage6*100:.1f}%")
  81. # 按 rank 排序并展示
  82. stage6_sorted = sorted(stage6_search_words, key=lambda x: x['llm_rank'] if x['llm_rank'] else 999)
  83. print(f"\n📋 详细搜索词列表 (按 LLM Rank 排序):")
  84. print(f"{'Rank':<6} {'评分':<6} {'搜索状态':<12} {'帖子数':<8} 搜索词")
  85. print("-" * 80)
  86. for idx, word in enumerate(stage6_sorted, 1):
  87. rank = word['llm_rank'] if word['llm_rank'] else 'N/A'
  88. score = f"{word['llm_score']:.2f}" if word['llm_score'] else 'N/A'
  89. status = '✅ 已搜索' if word['has_result'] else '⏸️ 未搜索'
  90. note_count = word['note_count'] if word['has_result'] else '-'
  91. print(f"{rank:<6} {score:<6} {status:<12} {note_count:<8} {word['search_word']}")
  92. # 展示已搜索的搜索词详情
  93. searched_words = [w for w in stage6_sorted if w['has_result']]
  94. if searched_words:
  95. print(f"\n✅ 已执行搜索的 {len(searched_words)} 个搜索词:")
  96. for idx, word in enumerate(searched_words, 1):
  97. print(f"\n 【{idx}】 {word['search_word']}")
  98. print(f" 关联: {word['association']}")
  99. print(f" 特征: {word['feature_name']}")
  100. print(f" 评分: {word['llm_score']:.2f}, 排名: #{word['llm_rank']}")
  101. print(f" 结果: {word['note_count']} 个帖子")
  102. # 展示未搜索的搜索词
  103. not_searched_words = [w for w in stage6_sorted if not w['has_result']]
  104. if not_searched_words:
  105. print(f"\n⏸️ 未执行搜索的 {len(not_searched_words)} 个搜索词:")
  106. for idx, word in enumerate(not_searched_words, 1):
  107. print(f"\n 【{idx}】 {word['search_word']}")
  108. print(f" 关联: {word['association']}")
  109. print(f" 特征: {word['feature_name']}")
  110. print(f" 评分: {word['llm_score']:.2f}, 排名: #{word['llm_rank']}")
  111. # 分析为什么只搜索了部分
  112. print(f"\n🔍 搜索策略分析:")
  113. if searched == 10:
  114. print(f" 系统使用了 Top-10 策略")
  115. top_10_ranks = sorted([w['llm_rank'] for w in searched_words if w['llm_rank']])
  116. print(f" 实际搜索的 Rank 范围: {top_10_ranks}")
  117. # 检查是否严格按 rank 取的 top-10
  118. expected_top_10_ranks = sorted([w['llm_rank'] for w in stage6_sorted[:10] if w['llm_rank']])
  119. if top_10_ranks == expected_top_10_ranks:
  120. print(f" ✓ 严格按照 LLM Rank 取了 Top-10")
  121. else:
  122. print(f" ⚠️ 不是严格的 Top-10 (期望: {expected_top_10_ranks})")
  123. elif searched > 0:
  124. print(f" 系统执行了 {searched} 个搜索")
  125. else:
  126. print(f" 该特征的搜索尚未执行")
  127. print("\n" + "=" * 80)
  128. if __name__ == '__main__':
  129. stage4_path = 'output_v2/stage4_with_llm_scores.json'
  130. stage6_path = 'output_v2/stage6_with_evaluations.json'
  131. feature_name = '墨镜'
  132. if len(sys.argv) > 1:
  133. feature_name = sys.argv[1]
  134. if len(sys.argv) > 2:
  135. stage4_path = sys.argv[2]
  136. if len(sys.argv) > 3:
  137. stage6_path = sys.argv[3]
  138. analyze_feature_searches(stage4_path, stage6_path, feature_name)