generate_questions.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #!/usr/bin/env python3
  2. """
  3. Step 1: Generate 200 test questions from maritime documents
  4. Uses document titles + sampled content to create diverse questions
  5. """
  6. import json
  7. import os
  8. import random
  9. import re
  10. from pathlib import Path
  11. PROCESSED_DIR = Path('/home/67/knowledge/maritime/processed')
  12. OUTPUT = Path('/home/67/knowledge/maritime/test_200_questions.json')
  13. # Collect all document files with their content
  14. docs = []
  15. for f in sorted(PROCESSED_DIR.glob('*.txt')):
  16. text = f.read_text(encoding='utf-8')
  17. if '[scan PDF' in text or len(text) < 100:
  18. continue
  19. docs.append({'name': f.stem, 'text': text, 'length': len(text)})
  20. print(f"Total docs with content: {len(docs)}")
  21. # Categorize documents by type from filename patterns
  22. categories = {
  23. 'crew': [], # ship crew related
  24. 'safety': [], # maritime safety
  25. 'pollution': [], # environmental protection
  26. 'vessel': [], # vessel management
  27. 'port': [], # port management
  28. 'law': [], # laws and regulations
  29. 'policy': [], # policy documents
  30. 'report': [], # development reports
  31. 'certificate': [], # certificates and licenses
  32. 'other': [],
  33. }
  34. for d in docs:
  35. name = d['name'].lower()
  36. if any(k in name for k in ['船员', '海员', '适任', '培训']):
  37. categories['crew'].append(d)
  38. elif any(k in name for k in ['安全', '事故', '救助', '搜救']):
  39. categories['safety'].append(d)
  40. elif any(k in name for k in ['污染', '环保', '排放', '防治']):
  41. categories['pollution'].append(d)
  42. elif any(k in name for k in ['船舶', '船', '航行']):
  43. categories['vessel'].append(d)
  44. elif any(k in name for k in ['港口', '港', '码头', '锚地']):
  45. categories['port'].append(d)
  46. elif any(k in name for k in ['法', '条例', '规定', '办法', '规则']):
  47. categories['law'].append(d)
  48. elif any(k in name for k in ['通知', '意见', '方案', '公告']):
  49. categories['policy'].append(d)
  50. elif any(k in name for k in ['报告', '统计', '发展']):
  51. categories['report'].append(d)
  52. elif any(k in name for k in ['证书', '许可', '资质', '审批']):
  53. categories['certificate'].append(d)
  54. else:
  55. categories['other'].append(d)
  56. for cat, ds in categories.items():
  57. print(f" {cat}: {len(ds)} docs")
  58. # Question templates for different types
  59. FACT_TEMPLATES = [
  60. "根据{doc},{topic}的主要内容是什么?",
  61. "{doc}中规定的{topic}有哪些要求?",
  62. "请说明{doc}中关于{topic}的具体规定。",
  63. "{topic}的法律依据是什么?",
  64. "{doc}的施行日期和适用范围是什么?",
  65. "{doc}中对{topic}是如何定义的?",
  66. "根据相关文件,{topic}需要满足哪些条件?",
  67. "{topic}的申请流程是怎样的?",
  68. "{doc}对违反{topic}的行为如何处罚?",
  69. "请列举{doc}中提到的{topic}的分类。",
  70. ]
  71. REASONING_TEMPLATES = [
  72. "对比{doc1}和{doc2}在{topic}方面的异同。",
  73. "{topic}在近年来有什么变化趋势?",
  74. "从法律层级角度分析{topic}的规范体系。",
  75. "{topic}对航运企业有哪些实际影响?",
  76. "请综合分析{topic}存在的问题和改进建议。",
  77. "不同地区在{topic}方面的实施情况有何差异?",
  78. "{topic}与国际公约的要求有何对比?",
  79. "请评估{topic}的执行效果和存在的挑战。",
  80. ]
  81. MULTI_DOC_TEMPLATES = [
  82. "请综合多个文件说明{topic}的完整法规框架。",
  83. "关于{topic},不同层级的法规分别有哪些要求?",
  84. "请梳理{topic}的政策演变过程。",
  85. "请总结所有涉及{topic}的文件的核心要点。",
  86. ]
  87. # Extract topics from document names
  88. def extract_topics(doc_name):
  89. topics = []
  90. # Remove common prefixes like numbering and dates
  91. clean = re.sub(r'^[\d\.\-]+', '', doc_name)
  92. clean = re.sub(r'\d{4}年\d+月\d+日起施行', '', clean)
  93. clean = re.sub(r'(全国人大|国务院|交通运输部|海事局|部海事局).*?--', '', clean)
  94. clean = re.sub(r'--+', '', clean)
  95. clean = clean.strip()
  96. # Key maritime topics to search for
  97. topic_keywords = [
  98. '船员管理', '船舶检验', '船舶登记', '船舶安全', '海上交通',
  99. '港口管理', '航道管理', '海洋环保', '防污染', '船员培训',
  100. '适任证书', '船舶进出港', '定线制', '报告制', '引航',
  101. '危险货物', '防台', '搜救', '海事调查', '船舶安全检查',
  102. '通航安全', '水上交通', '海员', '船长', '轮机',
  103. ]
  104. for kw in topic_keywords:
  105. if kw in doc_name or kw in clean:
  106. topics.append(kw)
  107. if not topics and clean:
  108. # Use the cleaned name as topic
  109. if len(clean) > 5:
  110. topics.append(clean[:30])
  111. return topics
  112. # Generate questions
  113. questions = []
  114. qid = 0
  115. # 1. Fact questions from each category (120 questions)
  116. for cat_name, cat_docs in categories.items():
  117. if not cat_docs:
  118. continue
  119. # Sample docs from this category
  120. sample_size = min(len(cat_docs), max(3, 120 // len([c for c in categories.values() if c])))
  121. sampled = random.sample(cat_docs, min(sample_size, len(cat_docs)))
  122. for doc in sampled:
  123. topics = extract_topics(doc['name'])
  124. if not topics:
  125. topics = [cat_name]
  126. topic = random.choice(topics)
  127. template = random.choice(FACT_TEMPLATES)
  128. q = template.format(doc=doc['name'][:60], topic=topic)
  129. qid += 1
  130. questions.append({
  131. 'id': qid,
  132. 'type': 'fact',
  133. 'difficulty': random.choice(['easy', 'medium']),
  134. 'category': cat_name,
  135. 'question': q,
  136. 'source_doc': doc['name'],
  137. })
  138. # 2. Reasoning questions (50 questions)
  139. all_topics = ['船员管理', '船舶安全', '海洋环境保护', '港口管理', '航道安全',
  140. '危险货物运输', '船舶检验', '海事调查', '引航管理', '船员培训',
  141. '船舶登记', '海上搜救', '通航安全', '防台风', '船舶防污染',
  142. '水上交通事故', '船员适任', '船舶技术', '航运市场', '海事执法']
  143. for i in range(50):
  144. topic = random.choice(all_topics)
  145. if random.random() < 0.4 and len(docs) > 1:
  146. # Cross-document comparison
  147. d1, d2 = random.sample(docs[:200], 2)
  148. template = random.choice(REASONING_TEMPLATES[:2])
  149. q = template.format(doc1=d1['name'][:40], doc2=d2['name'][:40], topic=topic)
  150. else:
  151. template = random.choice(REASONING_TEMPLATES)
  152. q = template.format(topic=topic, doc1='', doc2='')
  153. q = q.replace('和在', '在').replace(' ', ' ')
  154. qid += 1
  155. questions.append({
  156. 'id': qid,
  157. 'type': 'reasoning',
  158. 'difficulty': random.choice(['medium', 'hard']),
  159. 'category': 'cross-doc',
  160. 'question': q,
  161. })
  162. # 3. Multi-doc synthesis questions (30 questions)
  163. synthesis_topics = ['船员权益保障', '船舶安全管理体系', '海事行政处罚',
  164. '船舶污染防治', '港口危险货物管理', '海上应急救援',
  165. '船员职业发展', '内河航运管理', '国际航行船舶管理',
  166. '海事信息化建设', '船舶技术标准', '海上通信安全',
  167. '船舶保险制度', '航运企业安全管理', '海事法律体系']
  168. for i in range(30):
  169. topic = random.choice(synthesis_topics)
  170. template = random.choice(MULTI_DOC_TEMPLATES)
  171. q = template.format(topic=topic)
  172. qid += 1
  173. questions.append({
  174. 'id': qid,
  175. 'type': 'synthesis',
  176. 'difficulty': 'hard',
  177. 'category': 'synthesis',
  178. 'question': q,
  179. })
  180. # Shuffle and trim to 200
  181. random.shuffle(questions)
  182. questions = questions[:200]
  183. # Re-number
  184. for i, q in enumerate(questions):
  185. q['id'] = i + 1
  186. # Save
  187. with open(OUTPUT, 'w', encoding='utf-8') as f:
  188. json.dump({
  189. 'description': 'Maritime QA benchmark - 200 questions',
  190. 'generated_at': __import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  191. 'stats': {
  192. 'total': len(questions),
  193. 'fact': sum(1 for q in questions if q['type'] == 'fact'),
  194. 'reasoning': sum(1 for q in questions if q['type'] == 'reasoning'),
  195. 'synthesis': sum(1 for q in questions if q['type'] == 'synthesis'),
  196. },
  197. 'questions': questions,
  198. }, f, ensure_ascii=False, indent=2)
  199. print(f"\nGenerated {len(questions)} questions:")
  200. print(f" Fact: {sum(1 for q in questions if q['type'] == 'fact')}")
  201. print(f" Reasoning: {sum(1 for q in questions if q['type'] == 'reasoning')}")
  202. print(f" Synthesis: {sum(1 for q in questions if q['type'] == 'synthesis')}")
  203. print(f"\nSaved to: {OUTPUT}")
  204. print(f"\nSample questions:")
  205. for q in questions[:5]:
  206. print(f" [{q['type']}/{q['difficulty']}] {q['question']}")