| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- #!/usr/bin/env python3
- """用已有单矿核验数据生成与生产工具同格式的Agent区间输入示例,不调用网关或模型。"""
- import argparse
- import hashlib
- import json
- from pathlib import Path
- import shutil
- import sqlite3
- import sys
- ROOT = Path(__file__).resolve().parents[1]
- sys.path.insert(0, str(ROOT))
- from extensions.main_fan import exploration, history_compaction
- def main():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument('--batch-dir', type=Path, required=True)
- args = parser.parse_args()
- output = args.batch_dir.resolve()
- state = json.loads((output / 'batch.json').read_text())
- verification = json.loads((output / 'verification/本地数据核验.json').read_text())
- if len(verification['mines']) != 1:
- parser.error('此示例命令仅回放已有单矿核验批次')
- mine = verification['mines'][0]
- chosen = next(item for item in state['mines'] if item['dept_id'] == mine['dept_id'])
- if len(chosen['shafts']) != 1:
- parser.error('此示例命令只回放当前已核验的单候选系统')
- shaft = chosen['shafts'][0]
- base = ROOT / 'data/workspaces' / hashlib.sha256(state['user_name'].encode()).hexdigest() / hashlib.sha256(mine['session_id'].encode()).hexdigest()
- connection = sqlite3.connect((output / 'runtime/business.sqlite').as_uri() + '?mode=ro', uri=True)
- try:
- context = json.loads(connection.execute('SELECT context_json FROM main_fan_workflows WHERE id=?',
- (mine['workflow_id'],)).fetchone()[0])
- finally:
- connection.close()
- original = context['history_manifest']
- prefix = '/workspace/exploration/' + mine['workflow_id'] + '/compacted-history-preview'
- resolve = lambda virtual: base / virtual.lstrip('/')
- records, _, _, storage = history_compaction.compact_evidence(original['segments'], prefix + '/history-evidence.zip', resolve)
- manifest = {**original, 'segments': records, 'storage': storage}
- with history_compaction.RecordReader(resolve) as reader:
- details = history_compaction.summarize(manifest, reader)
- details.update(storage=storage, mine={key: mine[key] for key in ('dept_id', 'mine_id', 'mine_name')},
- shaft={key: shaft[key] for key in ('shaft_id', 'shaft_name', 'identity_status')})
- view = history_compaction.agent_view(details, prefix + '/history-state-details.json')
- for name, value in (('history-agent.json', view), ('history-state-details.json', details), ('history-manifest.json', manifest)):
- exploration._write(resolve(prefix + '/' + name), value)
- destination = output / 'verification/agent-history'
- destination.mkdir(exist_ok=True)
- for name in ('history-agent.json', 'history-state-details.json', 'history-manifest.json', 'history-evidence.zip'):
- shutil.copyfile(resolve(prefix + '/' + name), destination / name)
- lines = ['# 给Agent的整理后数据示例', '', f"来源:{mine['mine_name']}(deptId={mine['dept_id']}),复用已归档40天数据;本次未调用模型或网关。", '',
- 'Agent先读history-agent.json;精细连续区间、异常和缺口见history-state-details.json;逐日完整证据在一个ZIP中。', '',
- '下表为同状态有效观测的大段摘要。有效观测段数大于1时,中间含未知或长缺测,不能把起止之间全部认定为持续开/停。实际变化只定位到前后两次采样之间。', '']
- for point in view['points']:
- lines += ['## ' + point['label'], '', 'nodeId:`' + point['node_id'] + '`。', '']
- if point['role'] == 'fan_state':
- lines += ['| 状态 | 首次有效观测 | 最后有效观测 | 有效观测分段数 |', '|---|---|---|---|']
- lines += [f"| {row['state']} | {row['first_observed_at']} | {row['last_observed_at']} | {row['observed_parts']} |" for row in point['state_periods']]
- lines += ['', f"精细分段{point['state_interval_count']}段,其中未知{point['unknown_interval_count']}段;状态变化{point['state_change_count']}次。", '']
- else:
- values = point['values']
- lines += [f"原始{point['quality']['raw_sample_count']}条,数值有效{values['numeric_sample_count']}条,0值{values['zero_count']}条;范围{values['minimum']}~{values['maximum']} {point['unit']}。未计算稳定窗口对比。", '']
- lines += ['## 文件体积', '', f"原始{storage['original_file_count']}份JSON共{storage['original_bytes']}字节,压缩证据包{storage['compressed_bytes']}字节;Agent入口JSON为{(destination / 'history-agent.json').stat().st_size}字节。", '',
- '此前联调原件与数据库未改写;后续取数工具将自动压缩归档并清理本轮逐日暂存JSON。', '']
- (destination / '整理后数据示例.md').write_text('\n'.join(lines), encoding='utf-8')
- print(json.dumps({'agent_input': str(destination / 'history-agent.json'), 'example': str(destination / '整理后数据示例.md'),
- 'agent_input_bytes': (destination / 'history-agent.json').stat().st_size, 'storage': storage,
- 'state_period_counts': {point['label']: point.get('state_period_count') for point in view['points']}}, ensure_ascii=False))
- if __name__ == '__main__':
- main()
|