课程摘要
上一节,我们将自然语言需求整理成经过校验的仿真任务书。本节继续完成智能体工作流:如何按顺序调用工具、区分“工具调用成功”与“求解成功”,以及在许可证故障、结果缺失和物理量异常时停止流程。通过一个不连接 Abaqus 的模拟程序,学习者可以先掌握可观察、可中止的仿真闭环,再将其接入真实求解器。
一、从“任务书”走向“工具调用”
第四十九节留下了一个已明确参数的案例:长 \(1000\ \mathrm{mm}\)、截面 \(100\ \mathrm{mm^2}\)、弹性模量 \(210000\ \mathrm{MPa}\) 的杆件,右端受 \(10000\ \mathrm N\) 拉力。
如果现在让智能体继续工作,它不应直接说“计算完成”。它需要依次回答:
- 输入是否仍然符合已支持的模型?
- 使用者是否批准提交真实作业?
- 求解器是否成功完成?
- 结果文件能否读取、所需变量是否齐全?
- 位移、应力和反力是否与基本力学规律相符?
由此得到本节的流程:
\[ \boxed{ \text{校验任务} \rightarrow \text{确认提交} \rightarrow \text{调用求解器} \rightarrow \text{读取状态} \rightarrow \text{提取结果} \rightarrow \text{物理核查} \rightarrow \text{报告} } \]
任何一步失败,都不能直接跳到“报告成功”。
二、先分清三种“成功”
仿真智能体最容易犯的错误,是把不同层次的成功混为一谈。
| 看到的现象 | 实际说明 | 还要检查什么 |
|---|---|---|
| 工具调用返回正常 | 命令或接口被成功调用 | 作业是否真正完成 |
作业状态为COMPLETED | 求解过程已结束 | ODB 是否可读、目标变量是否存在 |
| 得到了位移和应力数字 | 提取程序读到了数据 | 单位、边界条件、力平衡及理论量级是否合理 |
Abaqus 的作业对象区分SUBMITTED、RUNNING、ABORTED、TERMINATED、COMPLETED等状态;waitForCompletion()返回本身并不等于作业成功,之后仍需检查状态。Abaqus Job 对象文档
同样,.sta、.msg、.dat等文件有助于诊断求解过程,但不能仅凭某个文件存在就认定结果可信。Abaqus 作业监控说明
三、把工具设计成有限的操作,而不是“任意执行代码”
一个适合本课程案例的工具清单可以很短:
| 工具 | 输入 | 输出 |
|---|---|---|
validate_task | 结构化任务书 | 校验结果、解析参考值 |
submit_approved_job | 已批准的案例编号 | 作业编号、提交状态 |
get_job_status | 作业编号 | 当前状态、错误摘要 |
extract_bar_results | 已完成的作业编号 | \(u_3\)、\(\sigma\)、左端反力 |
check_physics | 提取结果与参考值 | 通过或停止,以及原因 |
关键是:submit_approved_job应根据已批准的任务记录生成并运行固定模板,而不是接收一段由大模型自由生成的 Python 或系统命令。
这些操作将来可以封装成 MCP 工具。MCP 为工具提供名称、输入结构与调用结果,并区分协议错误和工具执行错误;规范同时强调输入校验、访问控制、超时及敏感操作的人类确认。MCP 工具规范
本节先不搭建 MCP 服务,而是把最重要的调用顺序与停止规则讲清楚。
四、实操:用模拟求解器测试智能体流程
下面的程序复用第四十九节的validate(),但以mock_submit()模拟求解器。它不会启动 Abaqus,也不会生成真实 ODB。这样,没有 Abaqus 许可证的学员仍能练习完整的状态判断逻辑。
程序提供四种情形:
success:模拟作业完成且结果通过检查;license_error:模拟许可证不可用;missing_data:模拟作业完成,但没有拿到结果数据;bad_stress:模拟作业完成,但应力偏离参考值 20%。
其中,结果核查的核心代码是:
def assess(job, expected, force): if job.get("status") != "COMPLETED": return f"STOP_SOLVER: {job.get('reason', 'UNKNOWN')}" data = job.get("data") if not isinstance(data, dict): return "STOP_OUTPUT: MISSING_DATA" targets = { "u3_mm": expected[1], "stress_MPa": expected[2], "reaction_N": -force, } for key, target in targets.items(): value = data.get(key) if ( isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value) ): return f"STOP_OUTPUT: INVALID_{key}" if not math.isclose( value, target, rel_tol=0.01, abs_tol=1e-9 ): return ( f"STOP_PHYSICS: {key} differs " "by more than 1%" ) return "VERIFIED_MOCK_RESULT"这里的检查顺序很重要:先看作业状态,再看数据是否存在,最后看物理量。不能在ABORTED状态下拿部分输出继续写“仿真成功”。
代码中的 1% 仅是本教学案例的演示阈值,不是所有工程问题的通用验收标准。非线性、接触、断裂或网格敏感问题,应另行制定核查指标。
五、运行程序并观察预期输出
在 PowerShell 中进入第五十节材料目录后运行:
python lesson50_tool_loop.py --self-test python lesson50_tool_loop.py success预期输出:
SELF_TEST_OK INPUT_VALID: bar_demo_001 APPROVAL: simulation only; no real job submitted MOCK_JOB_STATUS: COMPLETED ASSESSMENT: VERIFIED_MOCK_RESULT再模拟许可证故障:
python lesson50_tool_loop.py license_error预期输出:
INPUT_VALID: bar_demo_001 APPROVAL: simulation only; no real job submitted MOCK_JOB_STATUS: ABORTED ASSESSMENT: STOP_SOLVER: LICENSE_UNAVAILABLE模拟“作业完成,但结果缺失”:
python lesson50_tool_loop.py missing_data预期结尾:
MOCK_JOB_STATUS: COMPLETED ASSESSMENT: STOP_OUTPUT: MISSING_DATA模拟应力异常:
python lesson50_tool_loop.py bad_stress预期结尾:
MOCK_JOB_STATUS: COMPLETED ASSESSMENT: STOP_PHYSICS: stress_MPa differs by more than 1%失败情形会返回非零退出码,便于上层自动化流程识别“不能继续”。
六、失败之后,智能体应该怎样做?
不是每一种失败都适合“自动修一下,再跑一次”。
| 失败类型 | 合理处理 | 不应做的事 |
|---|---|---|
| 许可证不可用 | 保留原任务,报告环境故障;待许可证恢复后再提交 | 擅自修改材料、载荷或网格 |
| 输入文件错误 | 定位模板或参数问题,记录错误,修正后重新校验 | 反复提交同一份错误输入 |
| 求解不收敛 | 查看状态和诊断文件,提出可核查的原因 | 无依据地增大载荷步数直到“跑通” |
| 结果变量缺失 | 核对输出请求及提取位置 | 用解析值冒充 ODB 结果 |
| 物理量异常 | 回查单位、边界条件、截面和节点编号 | 只挑选“看起来正确”的结果报告 |
智能体可以帮助提出诊断假设,但改变材料模型、边界条件或收敛设置,可能改变原本要解的问题。此类修改必须被明确记录,并视情况重新征得工程师确认。
七、接入真实 Abaqus 时,还缺哪一步?
本节程序故意停在模拟层。真正接入 Abaqus 时,需要把mock_submit()换成经过审核的适配器:由批准后的任务生成.inp,提交作业,等待结束,检查job.status,再调用前面课程已经编写的 ODB 提取程序。Abaqus 官方支持从输入文件提交分析,也提供作业状态和结果数据库相关接口。Abaqus 执行过程、Job 对象文档
真实适配器还必须记录案例编号、输入文件、求解器版本、状态、错误摘要和结果文件位置。这样当智能体说“应力核查失败”时,工程师能追溯它究竟检查了哪一次计算。
本节思考题
为什么bad_stress情形中的作业已经是COMPLETED,智能体仍必须停止?答案是:COMPLETED只说明求解过程结束;应力与已知解析参考值明显不符,可能暴露单位、截面、边界条件、提取位置或模型设置错误。能算出数字,不等于算对了问题。