ventilation_plan_parser.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. from langchain_openai import ChatOpenAI
  2. from langchain_core.prompts import ChatPromptTemplate
  3. from typing import List, Dict, Any
  4. import json
  5. from config.settings import LLM_MODEL, LLM_API_KEY, LLM_BASE_URL, LLM_TIMEOUT
  6. from parser.base_parser import BaseParser
  7. class VentilationPlanParser(BaseParser):
  8. def __init__(self):
  9. super().__init__()
  10. self.llm = ChatOpenAI(
  11. model=LLM_MODEL,
  12. api_key=LLM_API_KEY,
  13. base_url=LLM_BASE_URL,
  14. temperature=0,
  15. timeout=LLM_TIMEOUT
  16. )
  17. def parse(self, file_path: str) -> Dict[str, Any]:
  18. """
  19. ✅ 优化点:
  20. 1. 只加载一次PDF
  21. 2. 只调用一次大模型
  22. 3. 一次性返回所有结构
  23. """
  24. # 1. 加载并清洗文本(只做一次)
  25. documents = self.load_pdf(file_path)
  26. full_text = "\n".join([doc.page_content for doc in documents])
  27. # 2. ✅ 只调用一次大模型,解析全部内容
  28. return self._parse_all_in_one(full_text)
  29. # 3. 解析成模型对象
  30. def _parse_all_in_one(self, text: str) -> Dict[str, Any]:
  31. prompt = ChatPromptTemplate.from_messages([
  32. ("system", """你是专业煤矿配风计划解析助手。
  33. 请从文档中提取**煤矿配风计划**全部数据,严格仅输出标准JSON,禁止输出任何多余文字、解释、前言后语。
  34. 如果文档内容与配风计划无关,必须100%回复{{"error_message":"非配风计划文档,后续大模型请勿继续操作!"}}
  35. 固定JSON字段(下划线英文简写,严格使用,不可修改):
  36. mine_info 矿井基本信息对象
  37. mine_name: 矿井名称
  38. mine_level: 矿井瓦斯等级
  39. total_air_volume: 矿井总需风量 m³/min
  40. return_well_count: 回风井数量
  41. preparation_date: 编制日期 YYYY-MM-DD
  42. vent_date: 配风计划月份 YYYY-MM
  43. reviewer: 编制人
  44. ventilation_chief: 通风科长
  45. ventilation_deputy: 通风副总
  46. chief_engineer: 总工程师
  47. list_all_vent_place: 结合文档整体分析是否列出所有用风地点,true OR false
  48. return_well_zone_calc: 结合文档整体分析多个回风井是否按承担区域分别计算需风量 true OR false
  49. coal_faces 采煤工作面列表(数组)
  50. face_name: 工作面名称
  51. is_standby: 是否为备用工作面
  52. standby_base: 假如是备用工作面,选择哪个工作面的作为依据,非备用工作面则为空
  53. vcf: 采煤工作面的风速 m/s
  54. scf: 采煤工作面的平均有效断面积
  55. kch: 采煤工作面采高调整系数
  56. kcl: 采煤工作面长度调整系数
  57. qcg: 采煤工作面回风巷风流中平均绝对瓦斯涌出量 m³/min
  58. kcg: 采煤工作面瓦斯涌出不均匀的备用风量系数
  59. Acf: 采煤工作面一次爆破所用的最大炸药量 kg
  60. Qcfg: 按瓦斯涌出量计算风量
  61. Qcfc: 按二氧化碳涌出量计算风量
  62. Qcfa: 按炸药量计算风量
  63. Qcfn: 按工作人员数量计算的风量
  64. Qcte: 按气象条件计算的风量
  65. Ncfi: 采煤工作面同时工作的最多人数
  66. qcc: 采煤工作面回风巷风流中平均绝对二氧化碳涌出量
  67. kcc: 采煤工作面二氧化碳涌出不均匀的备用风量系数
  68. is_working_face_min_air_check_pass: 回采工作面能否通过最低风量验算 true OR false
  69. is_working_face_max_air_check_pass: 回采工作面能否通过最大风量验算 true OR false
  70. is_wheeled_vehicle_air_check_pass: 能否通过胶轮车风量验算 true OR false
  71. q_max: 实际需风量,取最大值
  72. max_control_distance: 最大控顶距 m
  73. min_control_distance: 最小控顶距 m
  74. face_length: 工作面长度 m
  75. average_mining_height: 平均采高 m
  76. average_temperature: 工作面平均温度 ℃
  77. coal_face_calculated_separately: 检查每个采煤工作面实际需要风量,是否按工作面气象条件、瓦斯涌出量、二氧化碳涌出量、工作人员和爆破后的有害气体产生量等规定分别进行计算,然后取其中最大值 true OR false
  78. has_calc_check_process: 结合该地点分析是否有风量计算核验过程 true OR false
  79. tunneling_faces 掘进工作面列表(数组)
  80. face_name: 工作面名称
  81. Qhfg: 按瓦斯涌出量计算的需风量
  82. Qhfc: 按二氧化碳涌出量计算的需风量
  83. Qhfl: 按局部通风机实际吸风量计算
  84. Qcfn: 按工作人员数量计算的风量
  85. q_max: 实际需风量,取最大值
  86. qhg: 掘进工作面回风流中平均绝对瓦斯涌出量
  87. khg: 掘进工作面瓦斯涌出不均匀的备用风量系数
  88. qhc: 掘进工作面回风流中平均绝对二氧化碳涌出量
  89. khc: 掘进工作面二氧化碳涌出不均匀的备用风量系数
  90. has_min_air_by_leak_rate: 检查有无根据百米漏风率确定最小吸风量的过程,true OR false
  91. eQaf: 掘进工作面同时运转的局部通风机实际吸风量的总和
  92. is_gas_emission_tunnel: 是否有瓦斯涌出(半煤岩巷会有瓦斯涌出)
  93. Shdi: 局部通风机安装地点到回风口间的巷道最大断面积,m²
  94. Nhf: 掘进工作面同时工作的最多人数
  95. Shf: 掘进工作面巷道的净断面积
  96. Ndl: 掘进工作面最多运行防爆柴油动力装置机车的台数
  97. Pdl: 煤矿用防爆柴油动力装置机车的功率,kW
  98. has_calc_check_process: 结合该地点分析是否有风量计算核验过程 true OR false
  99. chambers 硐室列表(数组)
  100. name: 硐室名称
  101. type: 硐室类型:爆炸物品库/充电硐室/机电硐室/其他
  102. V: 硐室体积 m³
  103. qhy: 充电时氢气产生量 m³/min
  104. ρ: 空气密度
  105. CP: 空气的定压比热
  106. s: 机电硐室发热系数
  107. dt: 机电硐室的进、回风流的温度差
  108. W: 机电硐室中运转的电动机(或变压器)总功率(按全年中最大值计算),kW
  109. qd: 实际需风量
  110. has_calc_check_process: 结合该地点分析是否有风量计算核验过程 true OR false
  111. other_points 其他用风地点列表(数组)
  112. name: 地点名称
  113. Qrlg: 按瓦斯涌出量计算风量
  114. qrg: 其他用风巷道平均绝对瓦斯涌出量
  115. krg: 其他用风巷道瓦斯涌出不均匀的备用风量系数
  116. Src: 一般用风巷道净断面积
  117. Sre: 架线电机车用风巷道净断面积
  118. Qrlv: 按煤矿用防爆柴油动力装置机车需要风量
  119. Qo: 实际需风量
  120. Ndl: 其他用风巷道最多运行防爆柴油动力装置机车的台数
  121. Pdl: 煤矿用防爆柴油动力装置机车的功率,kW
  122. has_calc_check_process: 结合该地点分析是否有风量计算核验过程 true OR false
  123. 填充规则:
  124. 1. 无数据时:填null
  125. 2. 数字自动剔除单位,只保留数值
  126. 3. test_points 里绝对不要输出 id 字段
  127. 4. 严格按给定字段输出,不新增、不减少、不改名
  128. 5. 只输出纯净JSON,无任何其他内容
  129. """),
  130. ("human", "请解析以下煤矿测风报表文档内容:\n{text}")])
  131. # 调用大模型(唯一一次)
  132. chain = prompt | self.llm
  133. response = chain.invoke({"text": text}) # 控制在安全长度内
  134. # 安全解析
  135. return json.loads(response.content)
  136. if __name__ == '__main__':
  137. parser = VentilationPlanParser()
  138. result = parser.parse("D:\workspace\py\\vent_agent\\vent_plan.pdf")
  139. print(json.dumps(result, ensure_ascii=False, indent=2))