MAIN_FAN_WORKFLOW.md 17 KB

主通风机批次固定工作流

当前启动批次、月度批次、批次 API 和 scripts/run_main_fan_batch.py 共用本工作流,执行版本为 main-fan-workflow-v5。自由对话的 Skill/沙箱入口保留为原有交互能力;它不参与当前批次研判。

执行顺序

  1. 沿用固定煤矿筛选、测点分页、40 天历史查询和预处理。安全监控提供开停,重大设备提供风量。给模型的开停区间过滤起止相差不超过 5 秒(含 5 秒)的记录,适用于“开”和“停”;原始状态观测继续留档。按实际开停变化配对切出、切入风机并计算停启间隔估算及采样上下界,可配对的停启允许跨观测组连接,超过 10 分钟的间隔也会进入候选。前后各 1 小时附近单点风量及变化百分比沿用原方法。
  2. 按每份原 PDF 的物理页顺序提取全文。可用文本层由宿主 Python/PDFium 直接读取;空文本、只有水印或包含较大扫描图片的混合页渲染后发送 GLM OCR。页眉可读但表格是图片时也走 OCR,避免只读到页眉便声称全页完成。空白页单独记录。GLM 超时、HTTP 错误、空输出、输出截断或明显循环重复时,同一张页面图片再交给 Qwen3.5 识别一次。两者都失败则保留失败页及具体错误。PDFium 文本页使用显式 close() 释放,不作为上下文管理器。PDF 全部提取失败也继续使用已有开停和风量研判,正文记录提取受限,不写成用户未提供报告。
  3. 提取后按页首标题过滤明确无关的声明、机构资质、检测仪器清单和确定的空白页;出现性能、风量、功率、频率、叶片、铭牌、风机身份等关键词时保守保留。封面、性能表、相关说明、失败页及用途不确定的页面保留,不重新编号,不建立工况索引,也不自动把表格重排配对。筛选只影响送模副本,原 PDF、完整逐页文字和每页识别记录继续归档。将筛选后的 PDF 页和完整的风量、开停和切换整理结果合并为一个 JSON。原预览超过 20 条的区间/候选由程序展开完整结果。保留 0、null、缺测、原件身份和模拟来源。
  4. 使用配置的 Qwen3.5 发起一次非流式 chat/completions 生成请求,通过 response_format.type=json_schema 提交完整字段约束。保留最高思考配置。结构化解码能否在思考模式下实际生效还取决于模型服务的 parser 和 structured outputs 配置;客户端仍严格验证响应。不提供工具,不带检查点消息、历史聊天或旧研判,不再让模型写脚本、规划取数或调用提交工具。OPENAI_MAX_RETRIES 只影响原 Agent/SDK,工作流的唯一生成请求没有自动重试。
  5. 用严格 schema 校验 Qwen 的研判对象、资料说明和 judgment。存在完整业务内容但 JSON 语法或字段结构错误时,只发送待修复 JSON、目标 Schema 和校验错误,请 Qwen 修复格式,最多额外 3 次。没有 PDF、监测输入或旧会话随修复请求发送,也不重跑研判。修复不得改结论、数值和正文;能解析的原业务字符串逐字段核对,语法损坏的原件保守核对结论编码、数值和中文字是否变化。缺少 evidenceLink 可按固定契约补空字符串;空回复、没有业务内容的空对象、正文截断不能通过修复器编造结果。修复上限耗尽报 qwen_json_repair_exhausted。通过后由宿主绑定矿井身份、智能体身份、任务 ID 和完成时刻,组装并校验 PlatformResultPayload,再保存数据库和本地文件。

“一次”指一次业务研判生成;OCR 补识别和格式修复是独立调用,分别计数。扫描页默认最多 2 路并发,GLM 每页失败后最多一次 Qwen 补识别。HTTP 客户端没有隐藏的自动重试,首次业务请求的 HTTP 错误不触发 JSON 修复。所有原始响应、筛选记录和修复请求/响应均保存,成功修复不会覆盖首次研判的错误原文。页面筛选不裁剪监测数据,不把报告压成未经核对的摘要;上游上下文不足时保留错误,供服务器调整真实上下文配置后重跑。

JSON 语法错误 qwen_invalid_json 记录行、列和偏移;可解析但字段不符合契约时使用 qwen_schema_validation 并记录字段位置。详细诊断同时写入 failure.json 和日志。

v5 将监测阈值判定交给固定代码:不重新选参考点或改变比例,按有效的现成变化率和可靠间隔下界计算监测告警。一般阈值采用“超过”,配置的严重阈值采用“达到”;严重间隔阈值为空时不会自行新增。输入新增 monitoring_assessment,记录每个候选的原数值、固定判定及最低综合等级,请求 Schema 同步限制编码。模型不能降低监测告警等级;有效风量从正数降至0形成100%变化,在本轮15%严重阈值下必须为 ABNORMAL。

模型仍只进行一次辅助研判。格式修复继续只修改格式、保留原业务内容;随后统一合并固定监测结论。存在固定监测告警且模型未给出更高等级时,正式报文的编码、摘要、正文和资料说明统一使用固定证据生成,避免“编码异常、正文正常”的矛盾。模型有更高级别的性能异常结论时保留该等级,并附上固定监测证据。首次响应、格式修复后的响应及模型原判定均保留;监测规则判定.json 和 最终结论核对.json 记录原值、阈值、模型编码、最终编码及采用的正文。本轮未形成明确监测告警时,保留原有的性能辅助研判和资料可用性口径。

停启间隔按本次净切换中,切出风机各参与测点最后一次“开→停”、切入风机各参与测点最后一次“停→开”计算。多级测点取各方最后完成变化的新状态观测时刻,启动抖动不使用第一次短暂启动。duration_seconds=max(0, 启动观测时间-停机观测时间),duration_minutes=duration_seconds/60,状态为 estimated;先启后停时另存 overlap_seconds。from_stopped_at、to_started_at 是采用的观测时间,duration_sources 保留逐点依据;它们不宣称准确整机动作时刻。各变化的前一旧状态与首次新状态形成采样边界,据此计算 duration_bounds_minutes.lower/upper;跨未知或长缺测的变化标记 duration_has_gaps=true。仅下界也超限且不跨未知/缺测时据间隔告警。整个候选的 time_range 不当作停启间隔。

安全监控的明确开关标签兼容“开/停”和“开/关”,“关”统一为派生状态“停”,原始 value_label 保留在采样证据中;故障、报警等异常状态仍保持未知,不按数值 0/1 猜测开停。v4 修正了旧版把“关”误记未知的问题,重新研判时从原始采样重新归一化,旧版已完成的结论不能直接复用为本版结果。

给Agent的数据.json 和 给Qwen的数据.json 都包含上述计算结果。复用旧原始详情时也会从其中保留的实际状态变化重新派生间隔;只有缺少可配对的变化时间时才保留 duration_minutes=null、duration_status=unknown。本轮间隔数值是固定代码计算,模型直接采用,不重新推算。正文使用业务表述,不把内部字段名或 null/unknown 直接写给业务人员。

GLM 使用 Text Recognition: 提取全页内容;Qwen 补识别只转录原页文字与表格,不负责业务判定。复杂表头、上下标和数值仍可能识别错误;性能比较优先采用同角度、同频率、相近风量、相同口径的清晰原值。最终 schema 校验及格式修复不代替业务正确性核对。

研判口径

本轮策略为 main-fan-precision-first-v2-monitoring-rules,以告警准确率优先,接受漏报;但已经满足冻结阈值的有效监测超限不能被模型忽略。它同时写入提示词与 给Qwen的数据.json 的 judgment_policy,不沿用自由对话 Skill 中“关键项资料不齐就无法综合判定”的旧口径。

  • 开停、风量沿用冻结规则和固定程序的实际数值。有效风量变化比例按 switch.flow_deviation_percent 与 severity.abnormal_flow_deviation_percent 判断;停启间隔使用现成估算及其采样上下界,按对应间隔阈值判断。不添加稳定窗口、完整率或 CV 门槛,不把整个候选采样范围当作实际切换耗时。缺少 PDF 不影响有效监测超限形成告警。
  • 性能部分做粗略辅助核对,不再要求逐工况精算、插值、所有指标及工况配齐。只有清晰、可比且确凿超限的原件证据才告警;识别不清、工况不明、粗估接近阈值、缺页或点数不足只保留限制,不认为已证实性能异常。
  • 有确凿异常且达到已配置严重条件为 ABNORMAL;一般超限为 WARNING。没有配置的严重线不自行新增,资料缺失本身不告警。
  • 任一类有可用数据且未发现确凿异常为 NORMAL,含义是“现有数据未发现确凿异常”。尚未核实的性能、间隔或时段须说明,不能表述为已确认同等能力或全时段合格。
  • 仅报告、开停、风量三类均无可用数据时为 UNDETERMINED。宿主统计可读真实报告页、已识别开停区间、明确间隔、有效风量采样及参考值,保留零值;模拟 PDF 不作为本矿真实证据。统计写入输入和诊断中的 data_availability,并与固定监测等级一起收窄请求 Schema 的结论编码;合并固定告警后本地再次验证可用性口径,矛盾编码报 workflow_result_policy。监测结论的合并过程有独立原始/最终记录。

配置

保留既有网关、报告服务、只读原件目录及模型地址/凭证。下面只列本工作流相关项:

DEEPAGENT_MODEL=Qwen/Qwen3.5-35B-A3B-FP8
DEEPAGENT_THINKING=highest
# OPENAI_BASE_URL / OPENAI_API_KEY 沿用服务器当前的 Qwen 配置

MAIN_FAN_OCR_BASE_URL=http://10.244.3.155:10803/v1
MAIN_FAN_OCR_MODEL=glm-ocr
MAIN_FAN_OCR_API_KEY=
MAIN_FAN_OCR_TIMEOUT_SECONDS=120
MAIN_FAN_OCR_MAX_TOKENS=4096
MAIN_FAN_OCR_CONCURRENCY=2
MAIN_FAN_QWEN_OCR_TIMEOUT_SECONDS=240
MAIN_FAN_QWEN_OCR_MAX_TOKENS=8192
MAIN_FAN_PDF_DPI=150
MAIN_FAN_PDF_MAX_SIDE=2200
MAIN_FAN_PDF_CACHE_POLICY=auto

MAIN_FAN_WORKFLOW_MAX_TOKENS=16384
MAIN_FAN_WORKFLOW_TIMEOUT_SECONDS=600
MAIN_FAN_JSON_REPAIR_MAX_ATTEMPTS=3

# 本地测试保持关闭;不仅阻止本轮入队,也阻止后台结果推送服务启动。
RESULT_PLATFORM_ENABLED=False
MAIN_FAN_WORKFLOW_PUBLISH_ENABLED=False

Qwen 沿用 DEEPAGENT_THINKING;highest 对当前 vLLM/Qwen 接口发送 chat_template_kwargs.enable_thinking=true,没有另外的最高深度档。MAIN_FAN_WORKFLOW_MAX_TOKENS 同时给思考及正文留输出额度,实际总上下文仍由模型服务决定。

GLM 鉴权独立配置,空密钥时不发送 Authorization,不把 Qwen 密钥送给 GLM。Qwen 补识别复用现有模型、地址、密钥和思考配置。格式修复次数配置仅允许 0~3,0 表示关闭。请求、响应和输入落盘文件不保存鉴权头。

提取成功的原始 PDF 文字按原件 SHA256、提取版本、GLM/Qwen 服务及模型、思考开关和图片参数缓存。仅复用原始提取内容,本轮矿井绑定、监测输入、页面筛选和研判始终重新生成;旧 Agent 的提取事实档案或历史结论不会作为工作流 PDF 正文。存在失败页的提取不进入成功缓存。MAIN_FAN_PDF_CACHE_POLICY=refresh 强制重新提取并更新缓存,off 则不读写缓存。

新工作流默认禁止入推送队列,即使旧环境打开了 RESULT_PLATFORM_ENABLED 也不自动上报。以后需要工作流上报时,须同时显式开启 MAIN_FAN_WORKFLOW_PUBLISH_ENABLED 与总开关,并配置结果平台;本次不执行该步骤。总开关还控制其他业务任务及历史队列,所以服务器本地测试务必保留 RESULT_PLATFORM_ENABLED=False。

服务器本地运行

仅把代码放到服务器还不会让现有容器加载新代码;需要使用包含新代码的环境或重新构建镜像。镜像构建只交付程序,不表示服务器已部署或真实研判已经通过。

在服务器项目根目录,使用安装了项目依赖的 Python:

python scripts/run_main_fan_batch.py \
  --dept-id 1045 \
  --output outputs/main_fan_workflow/local-1045

不传 --mock-pdf 就使用当前真实报告采集服务和配置的原件目录。脚本独立创建业务/检查点数据库,固定关闭自动批次和所有结果推送,不影响现有应用的业务数据库;会实际访问网关、报告服务、OCR 和 Qwen。默认最多两个矿。若要测试指定合成原件,才额外传 --mock-pdf /path/to/report.pdf,结果必须保留模拟来源,不能替代目标矿井正式结论。

同目录可恢复未完成项;--reassess 保留旧结果版本后重新研判,复用符合条件的监测原件和成功 PDF 提取。不同执行版本不能直接当成当前版本的已完成批次,建议本地测试使用新的输出目录;跨版本 reassess 会重新发现测点,避免沿用旧版本错误的风机编号。风机识别支持“1号主扇二级”等名称,一级/二级不会作为风机编号。

已有批次 API 和启动/月度调度入口不用改 URL。测试时也可关掉启动批次和 cron,再从批次 API 显式选择单矿:MAIN_FAN_BATCH_RUN_ON_STARTUP=False、MAIN_FAN_BATCH_CRON=。

全矿研判可用 MAIN_FAN_BATCH_CRON=0 2 1 * *、MAIN_FAN_BATCH_SPREAD_DAYS=20、MAIN_FAN_BATCH_RUN_ON_STARTUP=False:每月1日02:00冻结清单,尽量平均分成20份,每天同一时刻处理一份,份内串行。重启复用原计划和当日批次;漏掉的份额顺延,每天最多一份,失败记录不阻塞下一份。详见分日部署说明。

启动批次可通过 MAIN_FAN_BATCH_STARTUP_EXCLUDE_DEPT_IDS 配置部门排除列表,值为 JSON 数组,默认 [];数字和数字字符串均支持,重复项自动去重,不在候选清单中的排除项忽略。过滤发生在按 MAIN_FAN_BATCH_STARTUP_MAX_MINES 和保护上限取前 N 矿之前,保留原顺序并继续向后补选;剩余不足 N 矿时只处理剩余矿,全部排除时跳过启动批次。月度与手动批次继续使用各自原有范围。日志 batch.startup.filtered 记录实际排除的部门,batch.startup.queued.selected_dept_ids 记录最终入选项。

例如在 docker run 的镜像名前加上,排除部门 1045、1106:

-e MAIN_FAN_BATCH_STARTUP_EXCLUDE_DEPT_IDS='[1045,1106]' \

修改配置后重新创建容器生效;需要使用包含这段筛选代码的新镜像。

本地输出

每个通风井目录包含:

文件 内容
待审阅报文.json 通过平台 schema 校验的标准推送 JSON;本地保存不等于已推送
结果.json / 报告.md 内部归档结果及由同一研判内容生成的可读报告
给Qwen的数据.json 一次业务研判的三类输入,PDF 为筛选后的页面,监测数据保持完整
PDF提取结果.json 全部 PDF 的物理页、提取方法、正文、失败原因和缓存记录
PDF筛选记录.json 每份原件保留页数、排除的原物理页码和原因
Qwen原始响应.json 首次业务研判原始响应,格式不合格时也不被覆盖
Qwen最终响应.json 格式校验后的模型响应,可能来自一次格式修复;正式结论还要合并固定监测告警
JSON格式修复记录.json 每次修复的请求/响应路径、次数、状态及失败原因
监测规则判定.json 固定阈值、逐候选监测判定和最低综合告警等级
最终结论核对.json 模型原判定、固定监测等级、最终采用的编码和正文
给Agent的数据.json 兼容保留的监测预处理预览,不再是完整研判上下文
研判数据.zip / 数据清单.json 原 PDF、监测证据、逐页文字/图片、OCR 响应、完整 Qwen 请求/响应和 SHA256
推送记录.json 默认 local_only

失败任务尚无正式报文,但矿级 workspace/exploration/<workflow_id>/workflow/ 下仍保存已完成提取、qwen-input.json、实际 qwen-request.json、收到的 qwen-response.json 和 failure.json(仅在执行到对应步骤时存在)。补识别文件为 pdf-N/page-NNNN.qwen.request.json、.qwen.response.json;GLM 文件继续保留。格式修复文件为 qwen-repair-N-request.json、qwen-repair-N-response.json,全部进入数据归档。

矿级 execution-<shaftId>.json 的诊断包含:judgment_calls(业务研判最多 1)、qwen_ocr_calls(失败页补识别)、json_repair_calls(格式修复最多 3)、qwen_calls(前三项合计),以及原页数、保留页数、排除页数、最终失败页数、研判策略版本和 data_availability。各类调用用量累计记账,不把补识别或修复算成新一轮业务研判。

标准平台报文仍为 agentCode、agentName、taskId、checkedAt、mineCode、mineName、objectDetail、dataDetail、judgment。其中 judgment 含 resultCode、result、reason、evidenceLink;编码仍为 NORMAL/WARNING/ABNORMAL/UNDETERMINED,含义按上述告警优先策略执行。