| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- #!/usr/bin/env python3
- """默认验证真实 Agent 的沙箱文档解析与报告交付;旧服务须显式选择。"""
- import argparse
- import asyncio
- import hashlib
- import json
- import os
- from pathlib import Path
- import shutil
- import sys
- import uuid
- ROOT = Path(__file__).resolve().parents[1]
- sys.path.insert(0, str(ROOT))
- async def run(args, output):
- from agents.workspace import session_root
- from db import chat_store
- from runtime.environment import RuntimeEnvironment
- from extensions.main_fan.service import analyze
- from runtime.execution import execute
- source = args.document.resolve()
- source_hash = hashlib.sha256(source.read_bytes()).hexdigest()
- async with RuntimeEnvironment(prewarm=False, billing_retry=False):
- user = "main-fan-live-document"
- session = chat_store.create_session(user, "full", "原件自动识别实测")
- root = session_root(user, session["id"])
- target = root / "workspace" / "uploads" / source.name
- target.parent.mkdir(parents=True, exist_ok=True)
- shutil.copyfile(source, target)
- def progress(value):
- print(json.dumps(value, ensure_ascii=False), flush=True)
- data = {"mine_code": args.mine_code, "mine_name": args.mine_name,
- "fan_name": args.fan_name, "fan_id": args.fan_name,
- "document_cache_policy": args.cache_policy,
- "materials": [{"path": "/workspace/uploads/"+source.name}]}
- if args.input_json:
- raw = json.loads(args.input_json.read_text(encoding='utf-8'))
- data = {**raw, **data, 'materials': [*raw.get('materials', []), *data['materials']]}
- data['fan_id'] = args.fan_id or raw.get('fan_id', args.fan_name)
- elif args.fan_id:
- data['fan_id'] = args.fan_id
- if args.agent:
- execution = await execute(agent_name="main_fan", user_name=user, session_id=session["id"],
- message="请读取业务 Skill,在沙箱自行编写文档解析、计算和报告生成代码,核对后提交真实脚本输出。完整输入已注入任务配置。",
- graph_config={"configurable": {"business_task_input": data,
- "document_audit_dir": str(output / "document")}})
- if execution.status != "success" or not execution.structured_output:
- raise RuntimeError("实际智能体执行失败:"+execution.error)
- result = execution.structured_output
- audit = result.get('assessment', {}).get('exploration', {}).get('python_runs', [])
- if not audit or result['assessment'].get('mode') != 'sandbox_exploration':
- raise RuntimeError('没有本轮成功沙箱交付记录,不能把旧固定服务作为自主探索实测')
- else:
- result = await analyze(data, user, session["id"], document_audit_dir=output / "document", document_progress=progress)
- audit = result["analysis"]["document_audits"]
- if not audit:
- raise RuntimeError("没有完整自动识别记录,详情见文档调用原始响应")
- if any(a.get("transcript_seed_loaded") or a.get("cache_used") for a in audit) and args.cache_policy != "auto":
- raise RuntimeError("刷新实测不可使用已有缓存或转录")
- if hashlib.sha256(source.read_bytes()).hexdigest() != source_hash:
- raise RuntimeError("原件在实测过程中发生变化")
- summary = {"mode": "live_agent_sandbox" if args.agent else "legacy_model_document_recognition",
- "source": str(source), "source_sha256": source_hash,
- "session_id": session['id'], "workspace": str(root / 'workspace'),
- "transcript_seed_loaded": False, "cache_policy": args.cache_policy,
- "mine_code_note": "本地测试编码,未假定陕西局正式编码", "result": result}
- (output / "result.json").write_text(json.dumps(summary, ensure_ascii=False, indent=2)+"\n", encoding="utf-8")
- print("真实模型研判完成:", output / "result.json", flush=True)
- if args.agent:
- print('成功沙箱交付', len(audit), '结论', result['platform_payload']['judgment']['resultCode'], flush=True)
- else:
- print("完成页数",sum(len(a["pages"]) for a in audit),"模型调用",sum(len(a["calls"]) for a in audit),
- "计算复核",len(result["analysis"]["calculations"]), flush=True)
- def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--document", type=Path, required=True)
- parser.add_argument("--mine-code", default="live-test-unassigned")
- parser.add_argument("--mine-name", required=True, help="任务目标矿井身份,不作为文档模型的预填数据")
- parser.add_argument("--fan-name", required=True)
- parser.add_argument("--fan-id", help="可选的明确设备ID,默认沿用输入JSON中的fan_id")
- parser.add_argument("--output", type=Path)
- parser.add_argument("--input-json", type=Path, help="可选的原始任务JSON,提供时序等明确数据;不注入文档转录结果")
- parser.add_argument("--cache-policy", choices=["refresh", "off", "auto"], default="refresh")
- parser.add_argument("--vision-model", help="仅旧固定服务:覆盖视觉模型;自主模式由主Agent直接看图")
- parser.add_argument("--agent", action="store_true", default=True, help="默认通过真实 Agent 的沙箱自主执行")
- parser.add_argument("--legacy-service", action="store_false", dest="agent", help="显式验证旧固定服务,不验证沙箱自主探索")
- args = parser.parse_args()
- output = (args.output or ROOT/"data"/"main_fan_live"/uuid.uuid4().hex[:12]).resolve()
- output.mkdir(parents=True, exist_ok=True)
- if (output/"business.sqlite").exists():
- raise ValueError("实测目录已有数据库,请使用新目录保留独立识别记录")
- # 沿用项目模型凭证,仅隔离运行数据与网关;不加载任何测试转录 JSON。
- os.environ.update({"DEEP_AGENT_ENV_PRIORITY": "process", "DB_DIALECT": "sqlite",
- "DB_SQLITE_PATH": str(output/"business.sqlite"), "CHECKPOINTER": "sqlite",
- "CHECKPOINT_DB_PATH": str(output/"checkpoints.sqlite"), "SHANXI_GATEWAY_ENABLED": "0",
- "MAIN_FAN_ALLOW_MANUAL_CACHE": "0", "RESULT_PLATFORM_ENABLED": "0", "MAIN_FAN_AUTO_PUBLISH": "0",
- "MAIN_FAN_TARGETS_FILE": "", "LOG_LEVEL": "WARNING"})
- if args.vision_model:
- os.environ["MAIN_FAN_VISION_MODEL"] = args.vision_model
- try:
- asyncio.run(run(args, output))
- except Exception as exc:
- (output/"failure.json").write_text(json.dumps({"type":type(exc).__name__,"message":str(exc),
- "transcript_seed_loaded":False},ensure_ascii=False,indent=2),encoding="utf-8")
- raise
- if __name__ == "__main__":
- main()
|