重算操作手册_v0.1.md 9.9 KB

观澜 · 如东 v2 重算操作手册 (v0.1, 2026-09-11)

给谁看: 要手工把 data\raw 下的原始数据算成系统能显示的东西的人。 前提: 已经跑过 install.bat(有 .venv)、.venv\Scripts\python.exe 存在。 所有命令都在安装根目录下敲(F:\temp\guanlan-rudong-v2_0.2.0\) —— 脚本按自身位置解析路径, 但相对路径参数 (如 --src)会按当前目录解释, 站在根目录最省事。

一句话原理: 页面的数来自 outputs\rudong\ 里的产物; 产物由 data\raw\ 下的原始件算出来; data\raw\ 的下一级目录名就是场站名称(扫描辨识, 不写死)。所以流程永远是: 放数据 → 算 → 重启服务 → 看页面。


0. 先摸清现状(三条只读命令, 不改任何东西)

.venv\Scripts\python.exe scripts\scan_stations.py              :: 系统认到哪个场站、四类源各多少件、有没有"缺"
.venv\Scripts\python.exe scripts\rebuild_from_raw.py --dry-run  :: 重算会做哪几步(不写盘)
.venv\Scripts\python.exe scripts\products_state.py --status     :: 产物在位还是被挪走

scan_stations.py 的期望输出(当前这台机器):

扫描到 1 个场站目录:
  如东  (631 件)  ...\data\raw\如东    ← 就绪
      scada_10min        38 件
      scada_1min         38 件
      故障报警              16 件
      风机故障记录           135 件
      油样报告             404 件
辨识结论 : how=raw_station   ← 目录名与场配置 raw_station 完全相同

1. 放数据(现场包 → 约定目录)

现场给的通常是几个 GBK 名的大压缩包。不要手工拖拽, 用映射表脚本落位(可复核、可反复跑):

:: 先看要落什么
.venv\Scripts\python.exe scripts\place_raw_data.py --src F:\temp\如东风场数据 --scope full --dry-run
:: 真落位
.venv\Scripts\python.exe scripts\place_raw_data.py --src F:\temp\如东风场数据 --scope full
范围 落什么
--scope a2 四项数据层: scada_10min / 故障报警 / 风机故障记录 / 油样报告
--scope mech 机理层源件 data\raw\西门子4.0技术资料\(含那份对译表) + <场站>\scada_1min\
--scope full 两组一起(从零重算要用的全集)

同尺寸文件会自动跳过, 所以重复跑很便宜(不用怕重抄十几 GB)。--src 不给会去找 data\_incoming\(默认)。

放数据的四条硬规矩

  1. 下一级目录名 = 场站名称, 且要与 configs\ 场配置里的 raw_station 一致(当前 如东)。
  2. 四个(加可选 1min 共五个)子目录名固定: scada_10min / scada_1min / 故障报警 / 风机故障记录 / 油样报告。
  3. scada_10min 必须是逐台平铺的 WTG01.csv…WTG38.csv 本身 —— 不能是压缩包、不能再套一层目录。
  4. 机理层资料放 data\raw\西门子4.0技术资料\(不在场站目录下)。

2. 重算

:: ① 三门台账(报警/工单/油样): 秒级~分钟级
.venv\Scripts\python.exe scripts\rebuild_from_raw.py

:: ② SCADA 侧 10 个构建器(逐台读 38 个 ~380MB CSV, **约 15 分钟**, 建议放后台或别关窗口)
.venv\Scripts\python.exe scripts\rebuild_from_raw.py --scada

②跑的 10 步(顺序 = 依赖顺序): 功率曲线 → 可用率与损失 → 七镜头曲线 / 控制策略件 / 停机事件 → 温度 NBM / 偏航 / 液压蓄能 / 热链 / 系统辅助。

期望结果(本机实测):

产物 行数
alarms.parquet 39,211
workorders.parquet 5,876
oil_samples_index.parquet 404(见 §7 的 102 行说明)
loss_monthly.parquet 3,729
temp_bins.parquet 24,624
curve_lenses.parquet 7,676
stop_events.parquet 2,318
powercurve_bins.parquet 912
curve_liveness / control_schedule 304
yaw_daily / hydraulic_accum / thermal_chain / system_aux / control_profile / powercurve_dev 各 38(逐台一行)

没换 SCADA 数据就不用跑 ②(① 是吃台账表的, 现场按月给表时跑 ① 就够)。

3. 本体层(机理资料那一层, 前提是技术资料已放好)

:: 对象库(技术资料 + 故障处理手册 + 码表 + 工单/报警) → objects.json
.venv\Scripts\python.exe -m src.ontology.kb_ingest

:: 检索索引(BM25 词法索引; 向量那半要 Ollama 的 bge-m3, 本机没模型时会跳过, 纯词法仍可用)
.venv\Scripts\python.exe -c "from src.ontology import retrieval as R; R.build(use_vec=False)"

:: 实机参数表(1706 条整定值, 源件是技术资料里的 Turbine+Parameters.*.xlsx)
.venv\Scripts\python.exe -c "from src.ontology.maintenance import refresh_params as f; print(f())"

:: 决策链进度入图谱(需要 windscada 服务已在跑, 从 /api/fleet 取)
.venv\Scripts\python.exe -m src.ontology.chain_ingest

期望: kb_ingest 打印 {'AlarmCode': 555, 'WorkInstruction': 559, 'FailureMode': 150, 'MaintTask': 559, 'Doc': 303, 'Component': 8, ...} (本机实测数字; 技术资料不在时它会打印 ⚠ 源缺失 并降级 —— 不静默)。

跑不通的两个(不是操作错, 是缺别的产物, 见 §7): python -m src.ontology.populate 与 python -m src.ontology.audit 都会因 outputs\rudong\pitch\pitch_daily.parquet 不存在而退出 1。

4. 等价验收(可选, 但强烈建议做一次)

--verify 拿随包基线逐键逐值比对重算件, 把差异分成"旧链已知缺陷 / 本链新增覆盖 / 无法归类"三类, 只有第三类才算不通过(退出码 4)。

基线不参与运行, 平时是单独存着的(_products_off\_baseline_kept\), 验收时临时放回:

:: ① 临时放回基线(3 件 1.1 MB)
xcopy /E /I /Y "_products_off\_baseline_kept\_pre_rebuild_20260911" "outputs\rudong\windscada\_pre_rebuild_20260911"

:: ② 验收(只比不算)
.venv\Scripts\python.exe scripts\rebuild_from_raw.py --verify

:: ③ 验完撤走, 让产物仓只留重算出来的东西
rmdir /S /Q "outputs\rudong\windscada\_pre_rebuild_20260911"

期望结论: alarms 39211/39211 逐值完全一致; workorders 8 行差异全部可归类(旧链的时间解析缺陷)

  • 69 行本链新增覆盖; 1 处"需人工看" = 油样 506→404(那 102 行的源件不在包里)。

5. 重启服务(必做)

产物换了必须重启: CMS 等模块是启动时加载数据的, 不重启页面还是旧数; 反过来, 产物被挪走期间起的 那次 CMS 会直接崩(表现为 /cms/ 503)。

.venv\Scripts\python.exe guanlan.py stop
.venv\Scripts\python.exe guanlan.py serve

期望: 状态 degraded offline 模块 5/7 ok, 并列出 DOWN 的项。

6. 怎么看"数据真的进去了"

命令行(不开浏览器):

.venv\Scripts\python.exe -m src.ontology.maintenance        :: 数据层+机理层逐行: 覆盖/条数/末次更新/摄入命令
.venv\Scripts\python.exe guanlan.py status                  :: 各服务端口与进程
.venv\Scripts\python.exe guanlan.py check                   :: 自检(依赖/产物/发布件/模型)

浏览器: http://127.0.0.1:28084/detail/ → 维护页「数据层 + 机理层」那两屏 —— 每行都写着它自己的摄入命令, 以后忘了敲什么直接看页面。

回归尺子(与出厂基线比对 10 个端点):

.venv\Scripts\python.exe scripts\page_fingerprint.py --save F:\temp\fp_now.json
.venv\Scripts\python.exe scripts\page_fingerprint.py --diff F:\temp\fp_before.json

7. 会遇到的"算不出来"(都不是操作错)

现象 原因 怎么办
/cms/ 503 CMS 的源是振动线 handoff(测点索引), 现场包里只有成品牌报告 PDF 找振动线要测点导出件
`/detail/api/query turbine fleet回err=no_products`
油样只有 404 行(出厂 506) 差的那 102 行来自一份合并报告, 该 PDF 不在现场包里 把该批报告放进 油样报告\ 后重跑 ①
门户没有"契约结论段"、/api/facts 503 契约要 sop\findings.json + paradigm_r1 底稿, 两者本身没有生成端 找研发要
populate / audit 退出 1 卡在 pitch\pitch_daily.parquet(变桨产物无生成端) 同上
/local-ai/ 503 本机 Ollama 未运行或没有模型(环境项, 与数据无关) ollama pull 见 configs\models.json

8. 两个必须知道的坑

  1. products_state.py --on 会删掉重算产物。它按清单把随包产物挪回来, 且目标目录存在就先 rmtree (scripts\products_state.py 第 110-112 行)。当前清单覆盖 outputs\rudong\{ontology, windscada, …} —— 也就是说: 想让"原始重算"的结果留着, 就不要跑 --on。要拿随包产物就先备份自己的重算结果。 只想取验收基线 → 用 §4 的 xcopy, 别用 --on。
  2. 顺序永远是: 停服务 → 挪/放数据与产物 → 算 → 起服务。挪产物期间起的服务会带着"没有数据"的 状态跑起来(CMS 直接崩), 表现为页面 503, 而数据其实是好的。

一页速记(最短路径)

:: 现状
.venv\Scripts\python.exe scripts\scan_stations.py

:: 放数据(现场包还在 F:\temp\如东风场数据)
.venv\Scripts\python.exe scripts\place_raw_data.py --src F:\temp\如东风场数据 --scope full

:: 算
.venv\Scripts\python.exe scripts\rebuild_from_raw.py
.venv\Scripts\python.exe scripts\rebuild_from_raw.py --scada        :: 约 15 分钟
.venv\Scripts\python.exe -m src.ontology.kb_ingest

:: 重启
.venv\Scripts\python.exe guanlan.py stop
.venv\Scripts\python.exe guanlan.py serve

:: 看
.venv\Scripts\python.exe -m src.ontology.maintenance
:: 浏览器 http://127.0.0.1:28084/detail/  → 维护页「数据层」

相关文档: docs\数据目录结构与落位约定_v0.2.md(§2 落位 · §4 重算边界表) · docs\重算缺口与补件清单_v0.1.md(缺什么找谁补) · _修复记录_20260911\README.md(踩过的坑)