ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent Harness 实战:从 LLM 输出到可验收办公产物的工程化封装

Agent Harness 实战:从 LLM 输出到可验收办公产物的工程化封装 办公场景里让大模型干活最尴尬的不是它不会干而是它干完了你不敢用。让它整理一份周报它给你一段洋洋洒洒的文字你还得手动复制到文档里让它汇总表格数据它输出一段 Markdown 表格粘到 Excel 里格式全乱让它生成一份会议纪要它把关键结论埋在第三段中间你还得逐字校对。问题的根子不在模型能力而在于从模型输出到可交付产物之间缺了一层工程化的封装。OpenWorkBuddy 这个项目有意思的地方就在这——它把自己定位成一个 Agent Harness核心目标是把 LLM 调用变成可验收的办公产物。这篇文章我会从 Harness 这个概念本身拆起讲清楚它和 Agent 的区别、它怎么组织工具调用、怎么定义验收、以及如果你想自己搭一套类似的办公 Agent 系统哪些坑是绕不过去的。1. 先把 Harness 和 Agent 的区别说透1.1 为什么这个词最近被反复提起Agent 这个词已经被用烂了。你打开任何一个技术社区Agent 框架、Agent 开发、Agent 架构这些词铺天盖地但真正落地到办公场景的时候很多人会发现一个尴尬的事实大部分所谓的 Agent 项目本质上就是一个带工具调用的对话循环。它能调 API、能读文件、能搜索但你让它连续完成一个稍微复杂的办公任务比如把这三份 PDF 里的数据提取出来合并成一张表再生成一份带图表的汇总报告它大概率会在第三步开始跑偏。Harness 这个词的出现本质上是对这种混乱的一次纠偏。它的原意是马具或者安全带在工程语境里指的是包裹在核心能力外面的一层控制结构。Agent Harness 就是包裹在 LLM 外面的那层工程框架它不负责智能它负责约束、编排、验证和交付。你可以把 LLM 想象成一个能力很强但不太靠谱的实习生Agent 是他手里的工具箱而 Harness 是那个盯着他干活、检查他每一步产出、最后帮他把成果整理成正式文档的带教老师。这个区分非常关键。Agent 关注的是能不能做Harness 关注的是做得对不对、能不能用。办公场景恰恰是后者比前者重要得多的地方因为办公产物的验收标准是明确的格式要对、数据要准、结论要能直接引用。一个能聊天但输出不可控的 Agent在办公场景里价值有限。1.2 从调用链角度看两者的分工我用一个具体的调用链来说明这个分工。假设用户输入是帮我把上个月的销售数据整理成月报。纯 Agent 的做法通常是这样的LLM 收到指令决定调用数据查询工具拿到原始数据然后直接生成一段文字回复。整个过程是一个思考-行动-输出的循环中间没有强制的检查点。Agent Harness 的做法会多出好几层首先它会做意图解析把整理成月报拆解成明确的子任务清单——数据获取、数据清洗、指标计算、图表生成、文档组装。然后每个子任务都有独立的执行器和验证器。数据获取完成后Harness 会检查返回的数据结构是否符合预期 schema指标计算完成后会做一次数值合理性校验比如环比增长超过 500% 就触发告警文档组装完成后会按照预设的模板做格式校验。只有全部通过才把最终产物交付给用户。这个差异带来的直接后果是Agent 的输出是一段文本Harness 的输出是一个文件。前者需要人再加工后者可以直接用。这就是标题里可验收的办公产物的含义——产物是有明确验收标准的不是一段模棱两可的回复。1.3 办公场景对 Harness 的特殊要求不是所有场景都需要 Harness。你在做一个创意写作助手Harness 的价值就没那么大因为创意本身没有硬性验收标准。但办公场景不一样它有几个非常鲜明的特征决定了 Harness 几乎是必需品。第一是产物格式的刚性。办公产物有明确的格式要求Word 文档要有标题层级和页眉页脚Excel 要有表头和数据类型PPT 要有版式和配色。LLM 直接输出的 Markdown 或者纯文本离这些格式还差着十万八千里中间必须有格式转换和校验层。第二是数据的可追溯性。办公场景里一个数字错了可能导致整个决策跑偏。所以 Harness 必须记录每个数据的来源、计算过程和中间状态出了问题能回溯到具体哪一步。这跟纯对话场景完全不是一个要求。第三是任务的幂等性。同一份数据今天跑和明天跑结果应该是一致的除非数据本身变了。纯 Agent 因为依赖 LLM 的随机性同样的输入可能给出不同的输出这在办公场景里是不可接受的。Harness 需要通过固定流程、缓存中间结果、锁定关键参数来保证幂等。第四是失败的可恢复性。办公任务往往步骤多、耗时长中间某一步失败了不能从头再来。Harness 需要支持断点续跑把已经完成的步骤结果持久化失败后从断点继续。理解了这四点你就能明白为什么 OpenWorkBuddy 要把自己定位成 Harness 而不是 Agent。它解决的不是能不能调用 LLM的问题而是调用了之后怎么保证产物可用的问题。2. OpenWorkBuddy 的任务编排层是怎么设计的2.1 从自然语言指令到结构化任务图OpenWorkBuddy 最核心的一层是任务编排。用户输入的是一句自然语言但系统内部处理的是一张任务图Task Graph。这个转换过程是整个 Harness 的地基做不好后面全塌。具体来说它分三步走。第一步是意图识别用 LLM 把用户指令分类到预定义的任务类型里比如数据汇总类文档生成类信息提取类。这一步不需要太精确因为后面还有细化。第二步是任务分解把任务类型展开成子任务列表每个子任务有明确的输入输出定义。第三步是依赖分析确定子任务之间的执行顺序哪些可以并行、哪些必须串行。这里有个设计上的取舍值得说。很多项目喜欢让 LLM 自由发挥直接生成一个执行计划。但 OpenWorkBuddy 的做法是半开放的——任务类型和子任务模板是预定义的LLM 只负责把用户指令映射到这些模板上以及在模板允许的范围内做参数填充。这样做的好处是可控性大幅提升坏处是灵活性受限。对于办公场景来说这个取舍是对的因为办公任务的模式其实很固定无非就是取数、算数、写文档这几类没必要让 LLM 每次都重新发明轮子。我实测过一个类似的对比让纯 Agent 处理把销售数据做成月报它每次生成的执行步骤都不一样有时候先算环比有时候先算同比导致最终报告的结构不稳定。而用模板化的任务图每次都是固定的五步流程输出结构完全一致。对于需要定期生成的办公产物来说这种稳定性比灵活性重要得多。2.2 子任务执行器的隔离与复用任务图定下来之后每个节点需要一个执行器来干活。OpenWorkBuddy 在这块的设计思路是执行器隔离每个子任务类型对应一个独立的执行器执行器之间不共享状态只通过明确定义的输入输出接口通信。这个设计的好处我在实际排查问题时体会特别深。有一次数据汇总的结果不对我顺着任务图往回查发现是数据清洗那一步的日期格式解析出了问题。因为执行器是隔离的我可以单独把数据清洗这个执行器拿出来喂给它原始数据复现问题修复再放回去。如果所有逻辑都揉在一个大函数里这种定位会痛苦得多。执行器的复用也是同理。数据清洗这个执行器在月报任务里用在季度汇总任务里也能用在临时的数据核对任务里还能用。只要输入输出的 schema 定义清楚执行器就是可插拔的积木。这也是 Harness 相比一次性脚本的核心优势——它把办公任务里重复出现的环节沉淀成了可复用的组件。不过这里有个坑要注意执行器的输入输出 schema 一定要严格定义不能图省事用宽松的类型。我见过有项目把执行器的输入定义成一个字典结果上游传什么全凭运气下游拿到什么全靠猜调试的时候简直是灾难。正确的做法是每个执行器都定义明确的 schema字段名、类型、是否必填、默认值全部写清楚上游传错了直接报错而不是让它带着错误数据往下跑。2.3 并行与串行的调度策略任务图里的节点不是都要串行执行的。比如读取三份数据源这三个子任务完全可以并行计算各项指标在数据齐了之后也可以并行。OpenWorkBuddy 的调度器会根据依赖关系自动决定哪些节点可以并行。并行的价值在办公场景里很实在。假设一个任务要处理 20 个部门的报表串行处理每个部门要 30 秒总共就是 10 分钟并行处理的话如果并发度开到 5理论上 2 分钟就能跑完。对于需要定期批量处理的任务这个时间差是决定性的。但并行也带来新的问题主要是资源竞争和错误传播。资源竞争方面如果多个执行器同时调用同一个外部 API可能触发限流同时写同一个文件可能产生冲突。OpenWorkBuddy 的做法是给执行器加上资源锁需要访问共享资源的执行器排队执行。错误传播方面并行任务里如果有一个失败了其他正在跑的任务要不要中断这里的策略是快速失败——一旦有节点失败立即通知所有正在执行的节点停止避免浪费资源。提示并行度不是越高越好。我实测下来对于调用外部 API 的任务并发度控制在 3 到 5 之间比较稳再高就容易触发限流或者超时。对于纯本地计算的任务可以适当提高但也要考虑机器的 CPU 和内存。2.4 中间状态的持久化设计办公任务往往不是秒级完成的有的要跑几分钟甚至更久。这期间如果进程崩了、机器重启了任务就白跑了。所以中间状态的持久化是 Harness 的必备能力。OpenWorkBuddy 把每个子任务的执行结果都持久化下来包括输入参数、输出结果、执行时间、状态标记。这样任务失败后重新启动时可以从最后一个成功的节点继续不用从头再来。这个能力在调试阶段特别有用你可以反复重跑失败的那一步而不用每次都把前面的步骤重新执行一遍。持久化的存储选型也有讲究。轻量场景用 SQLite 就够了单文件、零配置、支持事务。数据量大或者需要多机共享的话得上 PostgreSQL 或者 Redis。我个人的经验是如果任务执行时间在 5 分钟以内、并发不高SQLite 完全够用没必要上重型数据库。但要注意 SQLite 的并发写限制多个执行器同时写会锁表这时候要么加写队列要么换数据库。3. 工具调用与 MCP 在办公产物生成中的角色3.1 MCP 到底解决了什么问题MCP 这个词最近热度很高但很多人对它的理解停留在又一个工具调用协议的层面。实际上 MCP 解决的是一个很具体的问题工具的定义和调用标准化。在没有 MCP 之前每个 Agent 框架都有自己的工具定义方式。你要接一个文件系统工具得按框架 A 的规范写一遍换个框架又得按框架 B 的规范重写。工具和框架强耦合复用性极差。MCP 做的事情是把工具的定义抽象成一个标准协议工具提供方按 MCP 规范实现一次任何支持 MCP 的客户端都能调用。对于 OpenWorkBuddy 这类办公 Harness 来说MCP 的价值在于它能把办公场景里常用的工具——文件读写、表格处理、文档生成、数据查询——都标准化成 MCP 服务。Harness 本身不需要关心这些工具怎么实现只需要按 MCP 协议调用就行。这样 Harness 的核心逻辑就能保持干净工具生态可以独立演进。我实际用下来MCP 最实用的地方是文件系统操作和数据库查询这两类。文件系统 MCP 让 Agent 能直接读写本地文件不用把内容塞进 prompt 里数据库 MCP 让 Agent 能直接查数据不用先导出成 CSV 再处理。这两个能力一加上办公自动化的可行性就上了一个台阶。3.2 办公场景常用工具的接入清单基于我自己的实践办公 Harness 需要接入的工具大概分这么几类我列个表方便对照。工具类别典型能力接入优先级注意事项文件系统读写本地文件、目录遍历高注意路径权限和文件锁表格处理Excel/CSV 读写、公式计算高注意数据类型转换和空值处理文档生成Word/PDF 生成、模板填充高注意模板引擎的转义规则数据查询SQL 查询、API 调用中注意查询超时和结果集大小图表生成柱状图、折线图、饼图中注意中文字体和配色方案邮件发送邮件组装、附件添加低注意发送频率限制这个清单不是绝对的具体接哪些要看你的实际场景。但有个原则是通用的优先接入那些能减少 LLM 直接处理数据量的工具。比如表格处理如果让 LLM 直接读一个几千行的 CSVtoken 消耗巨大且容易出错用表格工具先做筛选和聚合只把汇总结果给 LLM效率和准确率都会好很多。3.3 工具调用的错误处理与重试工具调用不可能每次都成功。网络抖动、API 限流、文件被占用各种意外都会发生。Harness 必须有一套健壮的错误处理和重试机制。OpenWorkBuddy 的重试策略是分级的。对于瞬时错误比如网络超时直接重试最多三次每次间隔指数退避。对于限流错误等待更长时间再重试或者切换到备用通道。对于参数错误这类不可恢复的错误直接失败并记录详细日志不浪费时间重试。这里有个经验值得分享重试一定要幂等。如果一个工具调用不是幂等的重试可能导致重复操作。比如发送邮件这个操作重试可能发出两封邮件。对于这类操作要么在工具层面做幂等保证比如用唯一 ID 去重要么在 Harness 层面记录已执行的操作重试前先检查。还有一个坑是错误信息的传递。工具调用失败时返回的错误信息往往很技术化比如HTTP 500或者connection reset。这些信息直接给 LLM 看它也不知道怎么处理。好的做法是在 Harness 层面把错误信息翻译成 LLM 能理解的描述比如数据源暂时不可用建议稍后重试这样 LLM 才能做出合理的决策。3.4 工具输出的结构化约束工具返回的结果格式必须可控。如果工具返回的是一段自由文本LLM 解析起来就很容易出错。所以 OpenWorkBuddy 要求所有工具的输出都必须是结构化的通常是 JSON 格式并且有明确的 schema。这个约束看起来简单实际执行起来需要花不少功夫。很多现成的工具返回的是人类可读的文本要把它转成结构化数据中间得加一层解析。比如一个查询数据库的工具原生返回的是表格形式的文本Harness 需要把它解析成 JSON 数组每个元素是一个对象字段名对应列名。我踩过的一个坑是工具返回的 JSON 里数字字段有时候是字符串类型有时候是数字类型取决于数据源。LLM 拿到这种不一致的数据计算的时候就会出错。解决办法是在工具层面做类型强制转换或者在 Harness 层面加一层 schema 校验类型不对就报错。宁可报错也不要让它带着错误类型往下跑因为后面的错误会更难定位。4. 可验收这三个字背后的验收机制4.1 验收标准的定义方式可验收是 OpenWorkBuddy 的核心卖点但验收标准怎么定义是个需要认真设计的问题。验收标准不能太松太松了产物质量没保证也不能太严太严了动不动就失败可用性差。我的经验是把验收标准分成三个层次。第一层是格式验收检查产物的结构是否符合预期比如 Word 文档有没有标题、Excel 有没有表头、图表有没有坐标轴标签。这一层是硬性的不通过直接失败。第二层是数据验收检查关键数值是否在合理范围内比如销售额不能是负数、增长率不能超过某个阈值。这一层是软性的不通过触发告警但可以继续。第三层是语义验收用 LLM 检查产物的内容是否切题、逻辑是否通顺。这一层是辅助性的结果供人工参考。这三层验收的组合既保证了产物的基本可用性又不会因为过于严苛导致大量失败。实际用下来格式验收能拦住大部分低级错误数据验收能拦住大部分逻辑错误语义验收主要用来发现一些微妙的问题。4.2 格式校验的具体实现格式校验是验收机制里最实在的一环。办公产物的格式要求很具体校验起来也有章可循。以 Word 文档为例校验项包括文档是否有标题且标题层级正确、段落样式是否统一、页眉页脚是否存在、表格是否有表头、图片是否有题注。这些校验用 python-docx 这类库都能实现。Excel 的校验项包括是否有表头行、列的数据类型是否一致、是否有空值、公式是否正确。PDF 的校验相对麻烦一些主要靠文本提取后做结构分析。这里有个实操技巧把格式校验做成可配置的规则集而不是硬编码在代码里。因为不同任务对格式的要求不一样月报要求有页眉页脚周报可能就不需要。做成配置的话改需求的时候改配置就行不用动代码。规则集可以用 YAML 或者 JSON 描述每条规则包含校验项、期望值、失败处理方式。4.3 数据合理性校验的边界设定数据校验比格式校验难因为合理的边界不好定。销售额是正数这个好判断但增长率超过 50% 就不合理这种判断就得看具体业务了。OpenWorkBuddy 的做法是让用户配置校验规则而不是系统预设。系统提供一些通用的校验器比如范围校验、非空校验、类型校验、唯一性校验用户根据业务需求组合使用。这样既保证了灵活性又不用系统去猜业务逻辑。我自己的经验是数据校验的阈值设定要留有余地。比如你设定日销售额不超过 100 万结果某天搞活动卖了 120 万校验就误报了。所以阈值最好是动态的基于历史数据算出来而不是拍脑袋定死。比如用过去 30 天的均值加减三倍标准差作为合理范围超出这个范围才告警。4.4 验收失败后的处理路径验收失败之后怎么办这个流程设计得好不好直接决定了系统的可用性。OpenWorkBuddy 的处理路径是分级的。格式验收失败直接回退到上一个成功的节点重新执行。数据验收失败记录告警但继续执行把问题标记在最终产物里让人工决定是否采纳。语义验收失败记录日志不影响交付。这个分级处理的逻辑是格式问题通常是技术性的重跑一遍大概率能解决数据问题可能是业务性的重跑也没用得人来判断语义问题是最主观的系统不该替人做决定。注意验收失败的回退不能无限循环。我见过有系统因为格式校验一直失败反复重跑同一个节点把资源耗光了。正确的做法是设置最大重试次数超过就标记为失败转人工处理。5. 从 LLM 输出到办公产物的转换链路5.1 为什么不能直接让 LLM 输出最终格式很多人会想既然 LLM 能生成 Markdown那让它直接生成 Word 的 XML 或者 Excel 的公式不就行了理论上可以实际上不可行。原因有三个。第一LLM 对复杂格式的生成能力有限。让它生成一个带样式、带页眉页脚、带目录的 Word 文档它生成的 XML 大概率是错的而且错在哪很难定位。第二格式和内容耦合在一起修改起来很麻烦。你想调整一下文档的样式得重新生成整个文档内容和格式一起变不可控。第三不同格式之间的转换逻辑差异很大让 LLM 同时掌握所有格式的生成规则prompt 会变得极其复杂。所以正确的做法是内容和格式分离。LLM 只负责生成内容内容用结构化的中间格式表示比如 JSON 或者 Markdown。然后由专门的格式转换器把中间格式转成目标格式。这样 LLM 的职责单一格式转换的职责也单一两边都好维护。5.2 中间表示格式的选择中间表示格式的选择直接影响到后续转换的灵活性和可靠性。我对比过几种方案。Markdown 是最常用的优点是 LLM 生成起来最自然可读性好缺点是表达能力有限复杂的表格、嵌套结构、样式信息都表达不了。JSON 的表达能力最强什么结构都能描述缺点是 LLM 生成 JSON 容易出错尤其是嵌套深的时候。HTML 介于两者之间表达能力比 Markdown 强LLM 也还算熟悉但生成的 HTML 往往带一堆没用的标签。OpenWorkBuddy 的选择是 Markdown 为主、JSON 为辅。文档类的内容用 Markdown表格和结构化数据用 JSON。这个组合覆盖了大部分办公场景而且两种格式的转换器都很成熟。我自己的实践也印证了这个选择。纯用 JSON 的话LLM 生成长文档时经常漏字段或者字段名写错调试起来很痛苦。纯用 Markdown 的话遇到复杂表格就抓瞎。两者结合各取所长是目前比较务实的方案。5.3 格式转换器的实现要点格式转换器是 Harness 里最脏的活因为办公格式的细节太多了。我列几个实现时的关键点。Word 转换方面python-docx 是主流选择。要注意的是样式继承——如果你在模板里定义了标题样式生成的时候要确保段落应用了正确的样式而不是手动设置字体大小。手动设置的话后续改模板就改不动了。表格转换要注意合并单元格的处理Markdown 表格不支持合并单元格遇到这种情况得用 HTML 表格作为中间格式。Excel 转换方面openpyxl 用得最多。要注意的是数据类型——数字要写成数字类型日期要写成日期类型不要都写成字符串否则 Excel 里的公式和排序都用不了。公式的生成要小心openpyxl 写公式是写字符串Excel 打开时才计算如果公式有错打开的时候才会发现。PDF 转换是最麻烦的通常的做法是先生成 Word 或者 HTML再用转换工具转 PDF。中文字体是个大坑很多转换工具默认字体不支持中文生成出来是乱码。解决办法是显式指定中文字体或者把字体嵌入到文档里。5.4 模板引擎在产物生成中的应用模板引擎是提升产物一致性的利器。与其让 LLM 每次从零生成文档结构不如预定义好模板LLM 只负责填充内容。OpenWorkBuddy 用的是 Jinja2 风格的模板。模板里定义好文档的骨架比如标题、章节、表格的位置用占位符标记需要填充的地方。LLM 生成的内容填充到占位符里生成最终文档。这样做的好处是文档结构完全可控LLM 只需要关注内容质量。模板的设计有个原则模板要足够灵活能适应不同的内容量。比如一个章节有时候内容多有时候内容少模板要能自动处理而不是内容多了就溢出、内容少了就留白。Jinja2 的循环和条件语句能处理大部分情况复杂的排版需求可能得写自定义的模板函数。我踩过的一个坑是模板里的特殊字符转义。LLM 生成的内容里可能包含{{、}}这类字符如果不转义模板引擎会把它当成占位符解析导致报错。解决办法是在填充前对内容做转义处理把特殊字符替换掉。6. 搭建同类办公 Harness 的实操建议6.1 从最小可用版本开始如果你看完上面的内容想自己搭一个类似的系统我的第一个建议是别一上来就追求大而全。先做一个能跑通的最小版本哪怕只支持一种任务类型、一种产物格式。最小版本应该包含什么一个任务定义比如把 CSV 数据转成 Excel 报表、一个执行器读 CSV、算汇总、写 Excel、一个验收规则检查 Excel 有没有表头和汇总行。就这三样跑通了再往上加。为什么要这样因为 Harness 的复杂度主要来自组件之间的交互而不是单个组件本身。你先跑通一条链路把交互模式定下来后面加组件就是复制这个模式。如果一上来就设计一个支持十种任务、五种格式的架构大概率会过度设计而且调试起来无从下手。6.2 日志和可观测性的重要性办公 Harness 的调试难度比普通程序高因为中间涉及 LLM 调用不确定性大。所以日志和可观测性必须从第一天就做好。我建议记录这几类信息每次 LLM 调用的完整 prompt 和 response、每个执行器的输入输出、每个验收规则的检查结果、整个任务的执行时间线。这些信息在排查问题时都是关键线索。日志的格式要结构化方便后续查询和分析。用 JSON 格式记录每个字段有明确含义。日志的级别要分明DEBUG 级别记录详细数据INFO 级别记录关键节点ERROR 级别记录异常。生产环境默认 INFO 级别排查问题时临时调到 DEBUG。可观测性方面如果条件允许接一个追踪系统会很有帮助。每个任务一个 trace每个子任务一个 span能直观看到时间花在哪里、哪一步最慢。对于优化性能很有价值。6.3 成本控制的几个抓手LLM 调用是有成本的办公场景如果批量处理成本会累积得很快。控制成本有几个抓手。第一是减少不必要的 LLM 调用。能用规则处理的就别用 LLM比如数据格式转换、简单的数值计算这些用代码实现又快又准又便宜。LLM 只用在真正需要理解语义的地方比如意图识别、内容生成。第二是控制 prompt 长度。prompt 越长token 消耗越大。把不必要的历史对话、冗余的上下文去掉能省不少。对于长文档处理先做摘要或者分段处理不要一股脑全塞进去。第三是缓存重复的调用。同样的输入如果之前调用过直接返回缓存结果。办公场景里重复调用其实不少比如同一份数据被多个任务引用缓存能省很多。第四是选择合适的模型。不是所有任务都需要最强的模型。意图识别、格式检查这类任务用轻量模型就够了内容生成、复杂推理才需要强模型。分级使用成本能降不少。6.4 安全边界与权限控制办公 Harness 能访问文件系统、能查数据库、能发邮件权限很大安全边界必须划清楚。最基本的是最小权限原则。Harness 只应该访问它完成任务必需的文件和数据库不应该有全盘访问权限。文件操作限制在指定的工作目录内数据库操作限制在指定的表和字段上。其次是操作审计。所有敏感操作都要记录日志谁在什么时候执行了什么操作结果如何。出了问题能追溯到具体操作。还有输入校验。用户输入的自然语言指令不能直接拼接到系统命令或者 SQL 里必须经过解析和校验。虽然 LLM 本身有一定的防护能力但不能完全依赖它Harness 层面必须有自己的校验。提示如果 Harness 要处理来自外部的数据比如用户上传的文件一定要做格式和内容的校验。恶意构造的文件可能触发解析器的漏洞或者包含注入攻击的 payload。6.5 迭代方向与扩展思路系统跑起来之后往哪个方向迭代我分享几个我认为有价值的方向。一是增加任务类型的覆盖。从最初的单一任务逐步扩展到报告生成、数据核对、文档转换、邮件处理等更多办公场景。每增加一种任务类型系统的适用范围就扩大一圈。二是提升验收的智能化程度。目前的验收主要靠规则未来可以引入 LLM 做更智能的验收比如检查报告的逻辑是否自洽、结论是否有数据支撑。这需要设计好的验收 prompt以及处理 LLM 验收结果的不确定性。三是支持人机协作。不是所有任务都能全自动完成有些环节需要人工确认。Harness 可以支持在关键节点暂停等待人工审核后再继续。这样既保证了质量又不会因为全自动而失控。四是积累任务模板库。把常用的办公任务沉淀成模板用户直接选用不用每次从零描述需求。模板库越丰富系统的易用性越高。五是优化性能和成本。随着任务量增加性能和成本会成为瓶颈。通过并行优化、缓存策略、模型分级等手段持续优化。这些方向不是都要做根据你的实际场景选择优先级高的先做。我的建议是先做任务类型覆盖和人机协作这两个对可用性的提升最直接。7. 几个容易踩的坑和我的应对经验7.1 LLM 输出的不确定性怎么收敛LLM 的输出有随机性同样的输入可能给出不同的输出。这在办公场景里是个大问题因为办公产物要求一致性。收敛不确定性的手段有几个。最直接的是降低 temperature把温度调到 0 或者接近 0让输出尽可能确定。但要注意temperature 调到 0 也不能保证完全确定因为底层还有并行计算带来的浮点误差。更可靠的手段是约束输出格式。用 JSON schema 约束 LLM 的输出结构让它只能按指定的格式输出。现在很多模型都支持结构化输出能大幅提升格式的稳定性。还有一个手段是多次生成取最优。同一个任务生成多次用验收规则打分选分数最高的。这个手段成本高适合对质量要求极高的场景。我自己的经验是temperature 调到 0.1 到 0.3 之间配合结构化输出约束大部分办公场景的稳定性就够了。追求极致稳定的话再加一层结果缓存同样的输入直接返回缓存结果。7.2 长文档处理的分段策略办公场景经常要处理长文档比如几十页的报告、几百行的表格。直接把长文档塞给 LLMtoken 消耗大且效果差。分段处理是必然选择。但怎么分段有讲究。按固定长度分段最简单但可能把一句话或者一个表格切断导致语义不完整。按语义分段效果好但需要额外的处理逻辑。我的做法是按结构分段。文档通常有天然的结构比如章节、段落、表格。按这些结构分段每段语义完整处理起来也方便。对于表格按行分段每段处理若干行最后合并结果。分段处理还要注意上下文传递。处理后面段落的时候可能需要前面段落的上下文。解决办法是在每段的 prompt 里带上必要的上下文摘要而不是完整的上文。摘要可以用 LLM 生成也可以用规则提取关键信息。7.3 中文办公文档的特殊处理中文办公文档有一些特殊之处处理的时候要特别注意。字体方面中文文档对字体要求高宋体、黑体、仿宋各有用途。生成文档时要显式指定字体不能依赖默认字体否则可能显示成乱码或者不好看的字体。排版方面中文的段落缩进、行距、标点符号都有约定俗成的规范。比如中文段落首行缩进两个字符中文标点占一个字符宽度。这些细节不注意生成的文档看起来就不专业。日期和数字格式方面中文习惯用2024年1月1日而不是2024-01-01用一万而不是10,000。这些格式转换要在生成阶段处理好。表格方面中文表格的表头通常居中内容左对齐或居中这些样式要在生成时设置。这些细节看起来琐碎但正是这些细节决定了产物是否可验收。一个字体不对、缩进不对的文档即使内容再好也算不上合格的办公产物。7.4 任务失败时的用户沟通任务失败是难免的关键是失败时怎么跟用户沟通。糟糕的沟通会让用户对整个系统失去信任。我的原则是透明且有用。透明是指如实告诉用户哪一步失败了、失败的原因是什么不要含糊其辞。有用是指给出可操作的建议比如数据源连接失败请检查网络后重试或者第 3 步的数据格式不符合预期请确认输入文件。避免两种极端。一种是过度技术化把堆栈信息直接抛给用户用户看不懂。另一种是过度简化只说任务失败用户不知道该怎么办。好的沟通是在两者之间找到平衡用用户能理解的语言说明问题同时给出足够的信息让用户能采取行动。还有一点是保留中间产物。任务失败了但前面步骤的产物可能是有效的。把这些产物保留下来用户可以手动处理不用从头再来。这也是 Harness 相比一次性脚本的优势——它的中间状态是持久化的失败不会导致所有工作白费。7.5 版本升级时的兼容性处理Harness 是要持续迭代的升级的时候怎么保证兼容性是个容易被忽视的问题。兼容性问题主要出在几个地方。任务定义的 schema 变了老的任务定义可能解析不了。执行器的接口变了老的调用可能失败。验收规则变了老的产物可能通不过验收。处理兼容性的原则是向后兼容优先。新版本要能处理老版本的数据和定义。如果实在做不到要提供迁移工具把老格式转成新格式。迁移工具要经过充分测试确保转换后的结果和预期一致。版本管理方面给每个任务定义和执行器都加上版本号。执行的时候根据版本号选择对应的处理逻辑。这样新老版本可以共存逐步迁移不用一刀切。我踩过的一个坑是升级了验收规则结果之前能通过的任务现在通不过了导致大量任务失败。教训是验收规则的变更要谨慎新规则先以告警模式运行一段时间观察影响范围确认没问题再切换成强制模式。8. 写在最后的一点个人体会搭这套东西的过程中我最大的体会是办公自动化的难点从来不在 AI而在工程。LLM 的能力已经足够强了真正卡住落地的是那些琐碎的工程问题——格式转换、错误处理、状态管理、验收规则。这些问题不性感但它们是决定系统能不能用的关键。OpenWorkBuddy 这个项目的价值不在于它用了多先进的模型而在于它把 Harness 这层工程结构做扎实了。它把 LLM 调用包装成了可验收的办公产物这个定位本身就抓住了办公场景的核心需求。如果你也在做类似的事情我的建议是把精力放在工程细节上而不是追逐最新的模型。模型会不断迭代但工程结构是相对稳定的。把任务编排、执行器隔离、验收机制、格式转换这些基础打牢换什么模型都能跑。反过来如果工程结构一团糟再强的模型也救不了。最后分享一个小技巧在开发阶段把每个执行器的输入输出都存成文件方便对比和调试。我习惯在每个执行器的目录下建一个samples文件夹存几组典型的输入输出样例。写测试用例的时候直接用这些样例排查问题的时候也能快速复现。这个习惯帮我省了很多时间推荐你也试试。
返回列表