1. 流程模拟的效率瓶颈:Aspen Plus操作场景的重复劳动
干流程模拟的工程师心里都有本账:一个稍微像样的模拟案例,真正花在“思考工艺方案”上的时间可能只占三成,剩下七成全都耗在了软件操作上。改一个进料温度,鼠标要点五六下;换一种物性方法,要把整个流程从头到尾检查一遍;跑完一次模拟,还得逐条把结果复制到Excel里做对比。日复一日,全是机械劳动。
这种重复感在炼油、化工、医药中间体的工艺设计阶段尤其明显。你手里拿着的可能是一个成熟的苯-甲苯精馏模型,或者一套天然气脱酸吸收塔流程,工艺本身早就跑通过了,但每次换原料组成、调产品指标,都得重新打开Aspen Plus,把几十个参数重复填一遍。更麻烦的是,Aspen Plus的界面交互逻辑和Office完全不一样,它不开放批处理脚本,常规的UI自动化工具拿它没太多办法,录制宏又只能处理最简单的操作路径。
我一直觉得这个场景是该被自动化“治一治”的。Aspen Plus虽然老,但它提供了完整的COM接口,理论上所有界面操作都能在后台调用;再加上AI Agent现在具备了理解和执行自然语言指令的能力,把这两者结合起来,就成了一套可以“用大白话指挥Aspen Plus干活”的自动化方案。这次我基于WorkBuddy把整套流程封装成了Skill并正式发布,就是想验证一件事:流程模拟的日常操作,到底能省下多少人力。
所谓WorkBuddy的Skill,简单理解就是给Agent配置的一组“能力包”:告诉它什么时候该调用什么工具、工具的参数怎么解析、拿到结果之后怎么处理。举个例子,你对它说“把苯-甲苯塔的回流比从2.5调到3.0,重新运行并对比塔顶产品纯度”,Skill里的意图识别模块会先判断这是“参数修改+运行+结果对比”的复合任务,再把回流比修改指令翻译成COM调用,最后把新老结果整理成对比表格返回给你。整个过程不需要手写一行模拟代码,也不需要你去Aspen Plus界面里找输入框。
这个Skill对三类人最有用。第一类是天天和Aspen Plus打交道的工艺工程师,能把调参、跑模拟、导数据这类重复操作压缩到一句话;第二类是流程模拟的初学者,可以用自然语言快速搭出基础模型,再对照生成的参数反查Aspen Plus里的具体设置;第三类是像我一样负责工艺包开发或模拟平台维护的人,需要批量验证不同工况下的模拟表现,逐个人工操作根本不现实。
2. WorkBuddy Skill架构:把模拟能力拆成可编排的模块
2.1 Skill在WorkBuddy里的定位
接触过Agent开发的朋友应该熟悉,目前这类工具普遍采用“模型+技能+工具”三层结构。模型负责理解和生成,技能负责把复杂任务分解成步骤,工具负责真正执行某个具体动作。WorkBuddy的Skill就处在中间这一层,它本身不直接操作软件,而是告诉模型“你可以使用哪些工具、按什么顺序用、用的时候注意什么”。
第一次接触Skill这个概念时,容易把它理解成“预先写好的Prompt模板”。这个理解不算错,但太窄了。一个成熟的Skill至少包含三个部分:触发条件(什么时候该用它)、工作流定义(怎么拆解任务、按什么顺序执行)、工具集绑定(每个步骤调用哪个工具、参数怎么传、异常怎么兜底)。Prompt只是工作流定义里的一小段,真正让Skill“能干成事”的,是背后的工具层。
给Aspen Plus做自动化Skill,工具层就是COM调用的封装,这部分是整个Skill能否成功的关键。Agent再聪明,如果工具层不稳定,执行到一半模拟软件崩溃了,一切白搭。
2.2 我设计的三个Skill及边界划分
一开始我犯过一个错:想着做一个大而全的Skill,同时管建模、改参、运行、取数、生成报告。结果开发到一半就发现,Skill的逻辑复杂度直线上升,模型意图一旦判断错,整个链路全军覆没。后来借鉴了微服务的思路,把一个大Skill拆成了三个职责单一的Skill:
| Skill名称 | 核心职责 | 典型输入 | 输出 |
|---|---|---|---|
| ParameterSetter | 修改模拟参数 | “把进料温度改成85度”“回流比设为2.5” | 修改确认、当前值回显 |
| SimulationRunner | 运行与收敛控制 | “重新运行”“继续计算” | 运行状态、收敛提示 |
| ResultExtractor | 结果提取与报告 | “对比塔顶组成”“导出物料平衡表” | 结构化数据、对比报告 |
这种拆法的好处是,每个Skill的意图空间都很窄,模型不容易误判。比如用户说“把压力降到1.2公斤”,进入ParameterSetter就只会去找压力相关参数,不会跑去改塔板数或热负荷。同时每个Skill内部可以单独做异常处理,比如SimulationRunner发现不收敛,可以自己走一遍“读取警告、调整迭代次数、重新运行”的兜底逻辑,不影响其他Skill的状态。
2.3 交互模式:指令、工具、反馈三层闭环
三个Skill之间不是孤立的,用户最终要的是一个连贯的交互体验。以“改参-运行-看结果”这个高频链路为例,整个交互过程是这样闭环的:
- 用户用自然语言下达指令,WorkBuddy先判断是哪种Skill的触发条件。
- 进入ParameterSetter,模型从指令中提取“参数名-新值-作用对象”三元组,调用COM接口完成修改,同时返回修改后的确认值。
- 用户继续要求“运行一下”,SimulationRunner接管,启动模拟引擎,监控计算状态,直到收敛完成或报错。
- 用户再问“产品纯度多少”,ResultExtractor把Result表里的关键流股数据抽取出来,格式化为表格或文字答案。
这个闭环之所以可行,前提是Aspen Plus的状态在每一步之后都能被准确读取。COM接口的问题在于,它不是天然“有状态”的,你得自己维护当前打开了哪个模拟文件、当前模拟是否已经运行过、上次计算结果是否存在。我在Skill里专门加了一个状态管理模块,用工作目录下的临时状态文件记录这些信息,否则模型对当前工况的理解就是瞎蒙。
3. Skill核心开发过程:从COM接口到自然语言闭环
3.1 基础工具层:用COM把Aspen Plus“打开、改参、运行、取数”串起来
现在聊干货。Aspen Plus在Windows环境下通过COM接口对外开放,常用语言是VBA或Python。我用的是Python的pywin32库,安装好之后直接调用,核心代码逻辑不算复杂,但细节繁多。
先看最基础的四步操作。
打开模拟文件:
import win32com.client # 启动Aspen Plus进程(使用已注册的ProgID) aspen = win32com.client.Dispatch("Apwn.Document") # 打开指定的模拟文件(.bkp或.apw) file_path = r"D:\cases\benzene_toluene.bkp" aspen.InitFromFile2(file_path) # 等待加载完成 aspen.Visible = False这里有个关键点:InitFromFile2是异步的,文件越大加载越慢,必须做等待处理。我封装了一个wait_until_ready函数,不断查询引擎状态直到Engine.Ready为真,再开始后续操作。这个坑后面细说。
修改参数:
Aspen Plus的COM接口里,改参数要通过Tree对象操作整个模拟数据库。
def set_parameter(aspen, path, value): node = aspen.Tree.FindNode(path) if node is None: raise ValueError(f"参数路径不存在: {path}") node.Value = value return node.Value参数路径与Aspen Pluss界面里的层级树一一对应。比如改“苯-甲苯塔”的回流比,路径通常是:
\Data\Blocks\B1\Input\BASIS\MIXED\RR这个路径不是在界面上能直接看到的,需要摸索。最笨但最有效的办法是先用“Edit->Copy”复制某个单元格,能拿到它在Tree里的唯一路径;或者直接在Python里遍历Tree节点。等摸熟了常用路径,就能做成一个参数路径映射表。
运行模拟:
def run_simulation(aspen, time_out=600): engine = aspen.Engine engine.Run2(1) # 1表示运行整个流程 # 等待计算结束 deadline = time.time() + time_out while time.time() < deadline: if engine.IsSimulationStopped: break time.sleep(2) return engine.IsCalcOKRun2触发后台计算,界面会更新。计算完以后通过IsSimulationStopped判断是否结束,IsCalcOK判断有没有收敛。这里要注意,Aspen Plus遇到不收敛时计算也会停,但IsCalcOK是False,所以不能只看是否停止,必须检查收敛状态。
提取结果:
def get_stream_value(aspen, stream_name, prop): path = f"\\Data\\Streams\\{stream_name}\\Output\\TOTAL_MIXED\\{prop}" node = aspen.Tree.FindNode(path) return node.Value比如塔顶产品苯的摩尔分数,路径在\Data\Streams\S1\Output\TOTAL_MIXED\MASSFRAC\BENZENE。这类路径的规律性比较强,但具体字段名随版本不同会有差异,需要针对每个版本的Aspen Plus单独验证一遍。
3.2 意图解析层:把中文指令翻译成结构化的模拟任务
工具层通了之后,接下来的问题就是:怎么让模型理解“改成85度”里的85是进料温度,而不是塔压或产品纯度。
我的做法是用一个结构化的Function Call方案,把参数识别交给WorkBuddy里的模型去判断。定义一个工具函数modify_case_parameter,参数包括:
param_path:Aspen Plus Tree路径param_value:新值unit:单位(C、bar、kg/hr等)
模型看到用户输入“把进料温度改成85度”时,会思考这个指令对应哪个路径、哪个值、哪个单位,然后以JSON格式调用工具函数。这比硬编码规则要灵活得多,用户说“进料温度”还是“原料油温度”,模型都能理解成同一个概念。
不过模型自己判断路径有一个风险:它会生成不存在的路径。解决办法是多加一个“路径校正”步骤,在模型生成param_path之后,先去Aspen Plus的Tree里查这个路径是否存在,不存在就返回错误提示和可选的相近路径列表,让模型重新选择。
3.3 结果处理层:收敛性判断、数据提取与报告生成
结果提取和报告生成,是容易被忽视但实际使用频率最高的部分。
在Aspen Plus里读取结果,核心是搞清楚Output节点下有哪些字段。常见的结果包括:
- 流股的物性汇总(温度、压力、流量、组成)
- 塔模块的载荷(回流比、塔顶/塔底温度、冷凝器/再沸器热负荷)
- 换热器的热负荷和换热面积
我的ResultExtractor Skill会把“用户想要什么”分成几类,每一类对应一组固定的Tree路径:
| 用户意图 | 提取的目标 | 返回形式 |
|---|---|---|
| 看某股流组成 | 流股中各组分摩尔分数 | 字典或表格 |
| 看塔操作参数 | 塔模块关键负荷参数 | 字段列表+数值 |
| 对比多工况 | 多组工况下的关键指标 | 对比表 |
| 导出完整结果 | 所有物流的T/P/F/组成 | CSV文件 |
3.4 与WorkBuddy的对接配置
开发完上面这些逻辑,最后一步是把它们配置为WorkBuddy的Skill。我用的方式是在WorkBuddy的Skill目录下手写一个描述文件,文件名就是Skill名字,内容包括:Skill的职责说明、触发场景示例、暴露的工具函数及参数说明。
举个例子,ParameterSetter Skill的描述文件核心内容大致是:
# Skill: ParameterSetter 用途: 修改Aspen Plus模拟案例中的工艺参数 触发场景: - 用户要求修改温度、压力、流量、回流比等参数时 - 用户要求调整进料组成或产品规格时 工具: - modify_case_parameter 参数: param_path: Aspen Plus内部参数路径 param_value: 新数值 unit: 单位 使用约束: - 修改参数前必须确认案例文件已加载 - 修改后必须返回更新后的当前值配置好之后,在WorkBuddy里加载Skill,就能直接对话使用了。我实际测试下来,模型能准确理解Skill描述文件里的自然语言说明,不需要额外训练。
4. 实测案例:一个苯-甲苯精馏塔简捷设计的全自动流程
4.1 任务描述和需求拆解
为了验证这套Skill的真实可用程度,我设计了一套和实际工作高度相关的测试任务:用简捷法(DSTWU)设计一个苯-甲苯常压精馏塔。整个任务分成六个环节:
- 建立新的模拟流程,选择DSTWU模块。
- 设置进料流股:苯/甲苯各50 mol%,进料温度25°C,压力1 bar,流量100 kmol/hr。
- 指定塔顶产品组成(苯回收率99%)和塔底产品组成(甲苯回收率98%)。
- 设定塔压降和冷凝器压力。
- 运行模型,得到最小回流比、最小理论塔板数等参数。
- 根据结果,把DSTWU切换成严格塔RadFrac,设置实际回流比1.3倍最小回流比,再运行一次并对比。
这个任务覆盖了建模型、改参、运行、取数、模型替换五个高频操作,基本算是一个完整的中型模拟场景缩略版。
4.2 自然的交互过程
整个操作过程中,我没有手动打开过Aspen Plus界面,所有操作都是通过WorkBuddy对话完成的。下面摘录几段真实对话(经过精简):
对话1:建立模型
用户:新建一个精馏塔模拟,用DSTWU,处理苯和甲苯的混合物
Skill执行:创建新模拟文件,添加DSTWU模块,连接到物流拓扑,设置组分列表为BENZENE和TOLUENE。
这一句指令背后做了很多事:初始化新的Aspen Plus文档、进入模拟设置界面、添加组分、选择物性方法(这里用的NRTL-RK,适用于常压芳烃体系)、创建物料流股和模块连接。
对话2:设置进料和塔参数
用户:进料是100 kmol/hr,苯甲苯各一半,25度,1 bar
Skill执行:调用modify_case_parameter,分别设置物料流股的四个属性:温度、压力、总流量、组成。
这一步要注意,Aspen Plus的流股组成设置不是单一路径能搞定的,需要同时设置每个组分的分率或摩尔流量。我的工具层做了封装,传入一个字典就能一次设置完成。
对话3:运行并读取DSTWU结果
用户:跑一下,告诉我最小回流比和最小塔板数
Skill执行:运行模拟,等待收敛,读取Results Summary里的RRmin和Nmin,返回: “模拟已收敛。按当前设计规范,最小回流比为1.81,最小理论塔板数为14.6层(不含再沸器)。塔顶苯回收率为99.1%,塔底甲苯回收率为98.2%,满足设定指标。”
对话4:切换到严格塔模型
用户:换成RadFrac严格塔,回流比取最小回流比的1.3倍
Skill执行:新建RadFrac模块B2,把物流连接关系迁移过去,设置塔板数20层、进料板第12层、回流比2.35,运行并对比结果。
这一条语句涉及的操作量最大,因为模型替换不只是把模块类型改掉,还要重新指定塔的构造参数。我的Skill里预设了一套映射关系:DSTWU算出的Nmin和RRmin作为RadFrac初始塔板数和回流比,再按用户指令做系数放缩。
4.3 结果校验与人工介入点
这套流程跑下来,最关键的问题是:自动化出来的结果能信吗?我的答案是,能信,但有边界。
DSTWU简捷法到RadFrac严格法的切换,涉及一个工程判断:简捷法算出的塔板数直接乘以某个系数,得到的严格塔模型往往不是最优的,可能需要进一步用Design Specs反推实际回流比或产品纯度。我在Skill里内置了这个提醒逻辑,当结果出现产品纯度与设计指标偏差较大时,会提示用户“当前严格塔模型与设计规范有偏差,建议使用Design Specs重新校验”。
这其实也界定了自动化的边界:它能省去你在界面上的重复点击,但不能替你做工程判断。不过好消息是,把重复劳动消灭掉之后,你有更多时间去处理真正需要专业判断的部分。
5. 踩坑记录:开发过程中最花时间的几个问题
5.1 不同版本Aspen Plus的COM接口行为差异
这是最先遇到的坑。Aspen Plus不同版本(V10、V11、V12)的COM接口在几个关键方法上的行为不完全一致,尤其是InitFromFile2和Engine.Run2。
在我用的V12版本上,Run2的参数含义是运行方式,传1代表运行整个流程,传2代表运行到当前模块为止。但在V10里,Run2传2甚至不一定会停止在指定模块,有时候会直接运行整个流程。这一类差异不会报错,只会让结果不符合预期,非常隐蔽。
建议:做一个接口适配层,把所有与版本相关的调用统一封装,在配置文件里声明版本号,运行时按版本号选择不同的调用方式。
5.2 收敛失败后的状态恢复
模拟软件的常态是“不收敛”。Aspen Plus不收敛时界面会弹提示,引擎状态落在IsCalcOK == False,但进程不会崩。这时候如果直接对模型做参数修改再运行,很可能得到的是上一次失败计算的部分结果,甚至会让模拟引擎进入一种“半锁死”状态。
我的处理方法是:在SimulationRunner里加入失败状态机的处理逻辑,判断IsCalcOK=False后,依次尝试三步修复:
- 重新运行一次(有时候是数值抖动,重跑能过)。
- 检查是否有警告信息(特别是物性计算精度警告),根据警告类型调整容差参数。
- 保存当前状态并关闭引擎,重新打开文件再加载一次。
第三步治标不治本,但能保证长跑流程不中断。等你发现同一个模型反复在第三步“恢复”,那就该回头检查物性方法选型了,这属于工程问题,不是自动化脚本能兜住的。
5.3 长耗时任务下Agent上下文的管理
Aspen Plus的模拟,复杂流程算一次可能需要几分钟到几十分钟。Agent在执行长任务时有一个问题:上下文窗口有限,任务完成后,关键信息容易“淹没”在中间步骤的日志里。
我的做法是在ResultExtractor里设置一个“汇总缓冲”,当某个任务链路执行完毕,自动生成一段精简结果摘要,并把完整结果写入工作目录下的JSON文件。这样后续对话里,用户问“刚才那个工况的回流比是多少”,WorkBuddy可以直接读取摘要文件回答,不需要翻历史记录。
5.4 文件格式:bkp还是apw
Aspen Plus老版本用的是.bkp文件格式,新版本默认是.apw工程文件格式。两者在COM接口调用上的差别很大,.bkp是纯文本格式,COM打开速度慢但稳定;.apw是数据库格式,打开快,但需要有配套的.apw工程文件结构。
如果要在自动化链路里频繁保存和恢复状态,建议统一用.bkp格式,它在后台运行时的崩溃概率明显更低。不过要注意,新版Aspen Plus打开.bkp文件后另存为.apw时,部分老模型的物性计算设置可能会被替换,需要人工复核一次。
6. 自动化的边界和下一步扩展方向
6.1 目前做到什么程度
这次发布的Skill,我已经在三个实际案例上做了完整验证:
一是上面提到的苯-甲苯精馏塔简捷设计全流程,从新建模型到切换严格塔,全程无人工干预,耗时约19分钟(模拟计算本身占了绝大部分时间),手工操作通常需要40到50分钟。二是天然气三甘醇脱水流程的参数敏感性分析,批量跑了16组工况,手动导出结果后自动生成对比曲线,整个过程一键完成。三是炼油装置常压塔进料变化的快速复核,需要把原油进料替换成“虚拟组分”表示的新油品,这类操作原来要手工改好几处物性参数,现在也可以靠参数映射一次性处理掉。
从效率角度看,省时效果最明显的是批量工况验证场景。手工跑一组工况,包括改参数、等收敛、抄数据,最少需要5分钟,一天最多跑80组左右就非常吃力了。现在把这个过程压缩到一句指令,真正的时间瓶颈变成了Aspen Plus单工况的计算速度本身,链路吞吐率提升了一个数量级。
从稳定性角度看,只要不遇到“模拟不收敛”这个老问题,自动化的操作成功率在九成以上。遇到不收敛时,Skill的兜底逻辑能处理大约一半情况,剩下的需要人工介入做工程诊断,这个比例我觉得是可以接受的。
6.2 接下来想继续做的方向
第一,把参数路径映射表做成半自动生成。目前这些路径还是靠人工整理的,Aspen Plus每个版本的内部结构都有小幅调整,路径变了就得重新梳理。打算写一个Tree遍历脚本,在打开模拟文件后自动扫描常用模块和物流的参数路径,输出成一个JSON映射表,让维护成本大幅下降。
第二,增加“多案例批量对比”的编排能力。现在每次只支持一个模拟文件的状态管理,以后想支持给一组文件批量改参、批量运行、批量收集结果,输出成统一的工况对比报告。这需要把单一文件的Skill状态管理重构成多实例管理,工作量主要集中在并发控制和资源清理上。
第三,把物性方法选型和热力学模型经验知识做成一个独立的“推荐Skill”。物料体系一变,物性方法选错了,后面的模拟全是无用功。如果能把“这个体系该用NRTL还是UNIQUAC还是SRK”这类隐性经验固化成推荐规则,对初学者的帮助会比自动化操作本身更大。
最后说一点个人使用体会。Skill这类东西,最忌讳的就是想一口气吃掉所有场景。我在开发过程中最大的教训就是第一次试图做一个“全流程万能Skill”,结果逻辑复杂到连自己都不想用。拆成小Skill之后,每个都在特定场景里做到稳定,反而整体效果大幅提升。你们如果打算在WorkBuddy上规划自己的自动化Skill,建议从最频繁、最机械的那一个操作开始,先跑通闭环,再慢慢加场景。自动化这件事最大的成就感,不在于让工具学会多少新技能,而是你发现原来可以把手从那些耗神耗力的重复操作里彻底抽出来。