开完项目会,录音躺在文件夹里,群里已经开始有人问“纪要呢”,这类场面你可能比我更熟。以前我的做法是把录音拖进播放器,边听边敲键盘,一小时的会至少搭进去两小时整理,最后列出来的待办还总是漏项,等项目复盘时被问“当时不是说了要跟进吗”,只能尴尬翻录音。后来我把 Octo-ASR 接进 OCTO 工作流,让语音转写自动跑完,再由工作流里的 LLM 节点把口语化的流水账整理成结构化会议纪要,最后把待办拆出来直接派发给对应的 Agent,整条链路跑通之后,会一开完,任务清单基本就在工作台上排好了。这篇文章就把这套用法完整拆一遍,包括我接入时调过的参数、测试过的模型组合、踩过的一些坑,以及最后的可扩展方向。如果你也在做 agent 相关开发,尤其是想把“会上说的事”变成“系统里能执行的任务”,这套流程应该能给你不少可落地的参考。
1. 先想清楚转写、纪要与派单分别解决什么问题
很多人在搭这类系统时容易犯一个错误:以为把 ASR 的结果丢给大模型,直接就能输出纪要并派单。我最初也这么干过,结果发现中间省略了太多关键环节。Octo-ASR 输出的是一段带时间戳和说话人标签的文本,它并不理解“谁该对这件事负责”;OCTO 工作流里的 LLM 节点虽然能做归纳和判断,但如果输入的文本太原始,模型也会被口语中的冗余信息带偏。所以第一步不是写代码,而是把整条流程拆清楚。
1.1 Octo-ASR只负责“转写”,不负责“理解”
Octo-ASR 这类开源 ASR 工具的核心价值是“把声音变成文字”。它做得好的地方在于语音识别准确率、说话人分离(diarization)和较长音频的批量处理能力。但它有一个严格的工作边界:它不会判断哪些内容是闲聊、哪句话是真正的决策、谁在分配任务。这些语义层面的工作,Octo-ASR 完全不参与。
我之前在测试时遇到过一种尴尬情况:把会议录音转写出来后,文本里出现了“小刘,你回头跟客户确认一下时间”这样的句子。ASR 能准确识别出每个字,也能标出这是“发言者 A”说的,但它不会告诉你“这是一个待办任务”。如果要让系统自动把这条语句变成一条派发给小刘的待办,需要下游的 LLM 节点结合上下文去推断:这句话包含一个明确的动作(确认时间)、一个明确的负责人(小刘),因此符合待办条件。
所以,Octo-ASR 在整条链路中的角色是一个“高质量原材料提供者”,而不是最终的决策者。只要转写文本足够干净、说话人区分足够准确,后续的 LLM 节点才能有饭吃。这也是我后来在接入 OCTO 工作流时最强调的一点:先把转写质量做扎实,再谈智能化。
1.2 从转写文本到会议纪要:OCTO工作流里真正干活的是LLM节点
OCTO 工作流的定位是一个流程编排平台,它可以把多个节点串联起来:ASR 转写节点、文本增强节点、LLM 摘要节点、待办提取节点、Agent 派发节点等。每个节点之间通过 JSON 传递数据,节点各自处理一个独立任务。
以我的实现为例,OCTO 工作流里跑的主要是三步:
- ASR 节点把录音文件转成带时间戳和说话人的纯文本;
- LLM 节点拿到这段纯文本,用固定的提示词模板做信息抽取和摘要,输出一个结构化的 JSON,里面包含会议主题、关键决议、行动项、负责人和截止时间;
- 路由节点根据 JSON 里的负责人字段,把每一个行动项派发给对应的 Agent 实例,Agent 再去做后续的日程提醒、消息推送或任务创建。
这个架构看起来不复杂,但每一步都有很多细节。尤其是第二步的 LLM 节点,它的输出格式如果不做严格的 JSON Schema 约束,就会出现字段名不统一、待办和风险项互相混淆的问题。我前面说“直接丢给大模型”不够用,原因也在这里:大模型需要的是结构化任务的拆分,而不是一次性自由发挥。
所以在设计 OCTO 工作流时,我建议把“纪要整理”和“待办提取”拆成两个节点,而不是让一个提示词既做摘要又做任务分解。拆分的好处是每一段的任务更单纯,模型的表现也更稳定。纪要整理节点负责把口语转成有条理的会议概要;待办提取节点再基于概要,找出所有包含责任人、动作和时限的句子,形成待办清单。这样即使纪要节点出一个字段错误,也不会拖垮待办提取节点。
2. Octo-ASR接入前的准备:模型选型、音频预处理与输出格式
接入 Octo-ASR 之前需要做三件事:选模型、搞音频、定输出格式。这三件事看起来基础,但它们决定了后面所有环节的地基。
2.1 模型选型先想好:离线还是在线,实时还是非实时
Octo-ASR 有不同规格的模型可用,大模型和小模型的识别准确率差异明显,但也要看你具体的使用场景。
- 离线批量转写:如果会议已经录制完,不要求实时字幕,就用大模型。它的中文长音频识别能力更强,对专有名词的容错率也更高。我这边跑一小时会议录音,离线批量模式大概用 5 到 8 分钟左右完成转写,具体耗时看 GPU 配置。
- 在线实时转写:如果要做直播字幕或实时纪要,就得用轻量级模型配合流式接口。轻量模型在安静环境下满足日常使用,但会议场景里的多人重叠发言容易乱,需要额外做 VAD(语音活动检测)和降噪处理。
有一点容易忽略:Octo-ASR 的模型对中文口语表达的优化程度并不均衡。有些版本对英文表现很好,但中文语速快、口音重时识别错误率会明显上升。我在接入前专门拿了三场真实会议录音做对比测试,最后选了中文适配更好的模型底座,把热词表加上之后,人名和项目代号基本都能正确识别了。
建议在接入之前,先拿你所在团队的真实会议录音做一个基准测试,而不是直接用默认模型上生产。因为每个团队的专有名词不同,直接上线大概率会遇到识别率低的问题。
2.2 音频预处理:采样率、降噪和切分不能省
Octo-ASR 对输入音频有一定要求,常见的是 16kHz 单声道 WAV。很多会议录音原始文件是 48kHz 双声道,直接喂给 ASR 虽然不会报错,但会造成特征提取不一致,影响识别准确率。我在实测中遇到过一次:同一段录音,用原文件转写和用先转成 16kHz 单声道再转写,错误率能差 2 到 4 个百分点。
预处理步骤大致是这样:
- 用 ffmpeg 把音频统一转成 16kHz 单声道 WAV;
- 做简单的降噪处理,去掉空调声和风扇声;
- 如果整段录音很长,先做 VAD 切分,再分段转写。
VAD 切分有一个实际意义:它能把“无人说话”的空档去掉,避免 ASR 在静音段产生幻觉文本。我遇到过最离谱的情况是,一整段静音被转写成了“会议开始”,后面还带了几句编造的内容。后来我在转写前加了 VAD 过滤,这类幻觉基本消失。
关于切分的粒度,我建议分段控制在 30 秒到 60 秒之间。太短会导致上下文丢失,太长则容易在多人说话时互相串扰。Octo-ASR 本身支持长音频,但内部还是会做分块处理,你切分的边界和它内部的边界错位时,可能出现句子被拦腰截断的问题。加了上下文重叠之后,转写质量会更稳。
2.3 输出格式直接影响下游解析成本
Octo-ASR 的输出一般支持纯文本、SRT 字幕和带完整元信息的 JSON。如果你只是自己听录音,SRT 就够了;但如果要接 OCTO 工作流,一定要用 JSON 格式。
一个好的 JSON 输出至少包含这些信息:
| 字段 | 说明 | 用途 |
|---|---|---|
| start | 句子开始时间(秒) | 便于回溯定位 |
| end | 句子结束时间(秒) | 便于回溯定位 |
| speaker | 说话人编号或名称 | 角色指代识别 |
| text | 转写文本 | 供 LLM 分析 |
| confidence | 置信度分数 | 用于过滤低质量转写 |
低置信度的句子建议单独标记出来,不要让它们混入正常的纪要素材。我之前试过把置信度 0.3 以下的句子也喂给 LLM,结果模型把一段“嗯嗯嗯好的好”也总结成了“与会者表示同意”,非常误导。
接入 OCTO 工作流时,ASR 节点的输出 JSON 会直接作为下一个节点的输入。用 JSON 的好处是字段清晰,后续的 LLM 节点提示词里可以直接引用text和speaker,不需要做额外的文本解析。
3. OCTO工作流里的“会议纪要整理”节点
转写文本到手之后,下一步是把口语化的内容整理成会议纪要。这一步是整个流程中最容易被低估的环节。很多人以为只要把文本丢给大模型,说一句“帮我整理会议纪要”就行,但真实场景里,模型会被各种干扰信息带偏。
3.1 提示词模板要从“流水账”中提取“五要素”
我给纪要节点设计的提示词不是简单的“总结一下”,而是要求模型从文本中提取五类核心信息:
- 会议主题与目标;
- 关键议题与讨论过程;
- 最终决议;
- 行动项(谁在什么时间前做什么);
- 遗留问题与风险。
实践下来,效果比开放式总结稳定得多。模型不需要发挥,只需要做信息抽取和归类,漏内容的概率大幅下降。
我的提示词模板大概长这样:
你是会议纪要助手。下面是一段会议转写文本,包含说话人标签和时间戳。 请提取以下五类信息: 1. 会议主题 2. 关键议题及结论 3. 明确决议 4. 行动项:必须包含负责人、动作、时间限制(如果有) 5. 遗留问题与风险 要求: - 只基于文本中确有依据的信息,不要补充原文没有的内容。 - 行动项必须使用如下格式输出:负责人 | 动作 | 截止时间 | 原句摘录。 - 如果某类信息为空,请输出 "无"。 - 输出为 JSON,不要使用 Markdown 表格。 转写文本: {asr_text}注意最后两条要求很重要。很多第一次写提示词的人会忽略“输出为 JSON”和“不要使用 Markdown 表格”,结果模型返回一段富文本,下游就傻眼了。我在 OCTO 工作流里给 LLM 节点配置了 Response Format 强制 JSON,但提示词里再写一遍会更保险,模型输出更稳定。
3.2 说话人角色归一化:避免“小刘”“刘工”指代混乱
真实会议里,一个人可能有多种称呼。上一句叫“小刘”,下一句叫“刘工”,再后来说“小刘总”。如果直接把说话人标签带入待办提取,会出现同一个人被拆成多个负责人的情况。
解决办法是在纪要节点里增加一步角色归一化:
- 先让 ASR 输出每个说话人的编号,比如
speaker_0、speaker_1; - 上一步之后,用一个单独的 LLM 节点,根据上下文把每个说话人编号映射到实际姓名或角色;
- 在提示词里指定一个已知团队名单(名称列表),让模型在名单里选择最可能的对应人。
例如,转写文本里出现“让我们部门确认一下排期”,而团队名单里有“王明(后端负责人)”,纪要节点就应该把这句话挂到王明的名下。这一步如果没有做,待办派发时会出现“负责人:小刘”这种让下游 Agent 无法识别的名称。
我建议把团队成员名单做成一个静态配置文件,放在工作流里作为上下文注入。名单字段不需要很复杂,维护一个“常用称呼到正式姓名”的映射表就够了。团队不大时,用字典映射最直接;团队很大时,可以让模型根据历史纪要学习称呼归属。
3.3 纪要去噪:哪些内容可以丢,哪些必须留
会议录音里的废话比例通常不低。我在测试时发现,一段 60 分钟的会议录音,去掉寒暄、点外卖、闲聊和口头禅之后,有效内容常常不到 40 分钟。如果这些干扰信息全部留给后面的待办提取节点,误判概率会显著上升。
我的去噪策略分两层:
第一层在 ASR 输出阶段,把置信度低的句子标记为low_confidence,纪要节点直接忽略这些句子,不参与总结。
第二层在 LLM 提示词中明确告诉模型哪些内容不属于纪要范围。比如:
以下内容应被忽略: - 寒暄与闲聊(如"今天天气不错") - 口头禅与重复语句(如"嗯嗯""就是说") - 与会议主题无关的日常事务(如"中午吃什么") - 单纯的附和(如"对""是的")这听起来很基础,但真的能明显减少纪要的篇幅和质量问题。模型在提取信息时会更有目标性,不会把“下午三点前把方案发我”这种句子丢掉,因为它在任务语句里。
去噪还有一层深意:它不是把信息丢掉,而是把信息从“所有人说的一堆话”中分离出来。一个合格纪要的产出,应该让读者只看纪要就能了解会议全貌,而不用翻回原始转写文本。这是我在实际使用中体会最深的一点。
4. 待办提取与Agent派发:最难也最容易出错的一段
纪要整理出来之后,最核心的环节就是待办提取与派发。这一步之所以难,是因为它要求系统不仅能识别“这是一件待办”,还要能判断“这件待办该给谁、什么时候要做完、优先级高不高”。
4.1 待办字段设计:负责人、时限、优先级、原句摘录缺一不可
我先设计了一个待办的 JSON 结构,后来在真实项目里不断调整,最终稳定成了这样:
{ "id": "todo-20250115-001", "action": "确认客户新版接口的接入时间", "assignee": "王明", "due_date": "2025-01-20", "priority": "high", "source_text": "这个接口的时间,王明你去跟客户确认一下,下周要定下来。", "timestamp_start": 1523.4, "timestamp_end": 1528.7, "status": "pending" }字段看起来多,但每一个都有实际用途:
source_text用于追溯:派发给 Agent 后,如果 Agent 执行时需要看上下文,可以随时跳回原始会议文本,甚至跳回录音时间点。timestamp_start和timestamp_end用于对齐录音:团队中有争议时,可以直接定位到会议上说的那一句话,省去翻录音的麻烦。due_date是提取出来的“软时限”。如果原文说“下周之前”,模型应该把它转成具体的2025-01-20,这样 Agent 才能在排期里生成任务。
在提示词里,我要求模型对每一条待办都必须给出source_text。不给没关系,模型很容易编造出原文没有的任务。加上原句摘录之后,每一条待办都能在纪要里找到证据,这是一个非常强的约束。
4.2 从负责人到Agent实例的路由设计
待办提取完成之后,剩下的问题就是“怎么把待办交给正确的 Agent”。这里又分两种思路。
第一种是静态路由:在 OCTO 工作流里配置一个负责人到 Agent 实例的映射表。比如“王明”对应一个负责项目跟进的 Agent,“李婷”对应一个负责日程管理的 Agent。待办 JSON 的assignee字段直接查表,找到对应的 Agent API 就把待办推送过去。
第二种是动态路由:不配置固定映射,而是让一个调度 Agent 根据待办的内容判断该交给谁。这种方式更灵活,适合 Agent 数量多、职责边界不清晰的场景,但会多一层推理开销。
我建议第一天先做静态路由,等到跑通了,团队也确实需要更复杂的分发逻辑时再上动态路由。原因很简单:动态路由一旦出错,你很难判断是待办提取的问题还是调度 Agent 的问题。而静态路由逻辑透明,任何一条派发失误都可以直接看路由映射表排查。
路由消息本身也有讲究。不要把整个待办 JSON 全部塞给 Agent,应该按目标 Agent 的接收能力做裁剪。比如有的 Agent 是通过 Webhook 接收消息,它只关心action和due_date,那source_text可以放到附注里。如果 Agent 对接的是 IM 机器人,可能还需要把待办格式化成自然语言:
提醒:你有一个待办任务 内容:确认客户新版接口的接入时间 截止时间:2025-01-20 优先级:高 来源会议:2025-01-15 项目评审会这一步看似琐碎,但直接决定了 Agent 拿到消息之后能不能正确处理。我之前踩过坑,把完整 JSON 发给一个只接受文本指令的 Agent,结果它把所有 JSON 内容当作一条指令执行,闹了笑话。
4.3 派发确认与失败重试:没有回执的派发等于白派
待办派发之后,工作流不能就此结束,否则很容易出现“系统显示已派发,但 Agent 根本没收到”的情况。我给派发环节加了三层保障:
- ACK/NACK 回执:每个 Agent 在接收待办后必须返回一个确认信号。收到 ACK 代表任务已经进入 Agent 自己的队列;收到 NACK 或超时未响应,则触发重试。
- 有限重试:重试次数我设置为 3 次,间隔 1 分钟、5 分钟、15 分钟递增。重试超过 3 次后,把待办转到一个“人工补发队列”,由运维人员或项目助理手动处理。
- 对齐兜底:定期用待办列表与 Agent 内的任务列表做比对,发现 Agent 侧缺失任务就重新推送。这一步适合对系统性可靠性要求高的团队。
有了这三层保障,派发才算闭环。第一次实现时我没有加回执,结果有一场重要会议的 12 条待办里,有 4 条 Agent 根本没收到,没有人知道。后来检查日志才发现是 Agent 服务重启时把队列弄丢了。加入 ACK 回执后,这类问题在 1 分钟内就能被暴露。
5. 实测中的坑与调整:从1小时录音到全员收到任务
流程搭好后,我找了一场真实会议做了完整测试:一场一小时左右的线上项目评审会,参会 6 人,最后转写文本约 7000 字。下面说说实测结果、参数调整以及几个容易忽略的坑。
5.1 实测数据:转写、纪要与派发各用了多长时间
这次实测的完整流程耗时如下:
| 环节 | 耗时 | 说明 |
|---|---|---|
| 音频预处理(转 16kHz + VAD 切分) | 约 20 秒 | 用 ffmpeg 自动完成 |
| Octo-ASR 转写 | 约 6 分钟 | 使用离线大模型,GPU 环境下 |
| 纪要去噪与整理 | 约 40 秒 | LLM 节点处理 7000 字文本 |
| 待办提取 | 约 10 秒 | 独立 LLM 节点 |
| Agent 派发 | 约 5 秒 | 静态路由 + ACK 回执 |
整个过程接近 8 分钟。会议结束后,我泡了杯茶回来,Team 群里已经收到了任务提醒。这个速度当然不是“实时”,但对于会议场景已经能接受。如果希望更快,可以换成轻量模型加并行处理,转写时间能压到 2 分钟左右,代价是识别准确率略有下降。
最终这场会议提取出 10 条待办,对照人工整理的原始录音逐条核对,准确检出 8 条,漏掉 1 条(因为原句表述太模糊“那个事再跟进一下”,没有明确负责人和时限),多提取 1 条(把一句“要是没事的话就可以先这样”误判成了结束时间确认,后来靠低置信度过滤和二次校验拦住了)。
5.2 多人同时说话时转写错乱,用 VAD 和声纹分离缓解
线上会议最常见的坑是多人同时开麦,ASR 对重叠语音处理得很吃力。Octo-ASR 的说话人分离是基于声纹特征做的,同一声源若被压缩得太厉害,会频繁切换说话人标签。
我实测中遇到过一个案例:两位同事同时讲话,转写结果被 ASR 识别成 5 个不同的说话人,同一人在一句内来回切换身份标签,标签之间没有逻辑关联。
我的处理方案是:
- 在转写前做更细粒度的 VAD 切分,只保留能量较高的语音段,让重叠部分尽量各自独立;
- 若实在无法区分,在 ASR 输出中标记为
overlap,并在纪要节点中让模型忽略这些片段,避免它们对纪要产生干扰。
这个方案能一定程度缓解问题,但要彻底解决还是得从硬件出发。有条件的话,给会议室装一个全向麦配合每个座位的独立麦克风阵列,转写质量会上一个台阶,但成本也高。预算有限就先在软件层做过滤。
5.3 “回头再说”“之后同步”被误判成待办,阈值和二次校验双重控制
ASR 转写后的文本里,“回头再说”“之后再同步给你”这类模糊语句出现频率极高。LLM 提取待办时很容易把它们当成行动项,产生大量无效待办。
我加了两个控制手段。
第一个手段是置信度阈值,在待办提取节点中要求模型输出的待办必须满足“明确负责人 + 明确动作”两个条件,模糊语句直接跳过。没有通过这两个条件的一律不输出。
第二个手段是二次校验,新增一个校验节点,用独立的提示词重新审视待办列表:
以下是提取出的待办清单。对于每一条待办,请检查: 1. 原句中是否真的包含负责人? 2. 原句中的动作是否明确?(“回头再说”不算明确动作) 3. 如果只有负责人的称谓但对任务描述模糊,请标记为“需要人工确认”。二次校验比直接提取的准确率提升很多,因为它相当于用另一个视角重新审了一遍,本质上是“多重采样一致性”的简化版。之前没有加校验时,误判率达到 15% 左右;加上之后,降到了 4% 以内。
5.4 模型幻觉出的假任务:最小校验链路必须要有
大模型在处理长文本时偶尔会“脑补”。我在测试中遇到过一条不存在的待办,模型把“如果方案的接口不稳定,我们再想备选方案”提取成了“备选方案需要评估”,但实际原文是讨论假设情况,并不是安排任务。还有一次,模型凭空造了一个负责人名字,原文根本没有这个人出场。
应对幻觉任务,我总结出三个做法:
- 用
source_text强制绑定每一条待办,没有原句摘录的待办直接丢弃; - 在提示词里明确写“只基于原文,不要补充任何原文没有的信息”;
- 对置信度低的句子,在待办提取之前就过滤掉,防止模型基于低质量文本进行推断。
这三个做法单独拿出来效果有限,但叠加起来能有效降低幻觉概率。我还是那句话:尽量不给模型自由发挥的空间,让它做抽取,而不是做创作。
6. 这套流程还能往哪些方向扩展
如果这套会议纪要和待办派发的链路你已经跑通了,可以先别急着收工。我接下来打算把 OCTO 工作流往周边场景延伸,这里一并分享三个阶段。
6.1 第一阶段:把会议纪要同步到知识库和项目空间
会议纪要生成后,可以直接推给企业的知识库系统,自动归类到对应项目目录下。这样后期查找信息时,不用在 IM 聊天记录里翻找,直接去知识库搜索就行。同时,纪要和待办可以关联到项目管理工具里,让每条待办自带“会议来源”属性,方便项目复盘时回溯决策过程。
这个阶段的核心仍然是把数据格式整理干净。所以前面设计的 JSON 结构,在扩展时能直接复用。
6.2 第二阶段:让Agent带着记忆执行待办
如果把待办只发给 Agent 就算完,那是比较浅的用法。更有意思的是让 Agent 具备记忆能力,在多次会议之间积累上下文。比如这次会议提到“客户接口尚未确认”,下一次会议又提到“接口确认了”,Agent 如果能读取历史记忆,就会知道这个待办已经闭环,不必再次提醒。
关于 Agent 的记忆体系,短期记忆(当前会议)、中期记忆(最近几周的待办)、长期记忆(项目历史决策记录)是可以拆开做的。短期记忆直接存在工作流上下文里;中期记忆存成任务列表;长期记忆则可以让 Agent 定期把历史纪要里的重要结论写入向量库。这样 Agent 在接到新待办时,可以通过语义检索找到以前的关联决策,执行起来更准。
6.3 第三阶段:多Agent协作时把路由升级为动态调度
当 Agent 数量增多,静态路由的映射表会变得很难维护。此时可以考虑引入一个调度 Agent,它读取待办内容,结合所有 Agent 的能力描述,决定由谁执行,甚至可以把一条大任务拆成多个子任务分派给不同 Agent。这其实就是吴恩达在多 Agent 课程里讲的“三明治架构”在具体场景里的实践。
不过我还是那个建议:先静态、后动态。第一版系统不需要追求花哨,稳定性是最重要的。等到你手里有三个月以上的真实数据,知道各类待办实际会被哪些 Agent 正确处理了,再做调度决策才有依据。
最后说一个我个人的体会:会议纪要自动整理这件事,技术难点不在 ASR,也不在 LLM,而在流程设计与提示词约束。你要让模型在明确边界内做抽取,而不是给它无限的自由度;要让每一步输出都可追溯,而不是黑盒一锅焖。先把 Octo-ASR 的转写质量调到能接受的水平,再把 OCTO 工作流里的节点拆细、提示词写严,最后的派发环节加上回执和重试,这套流程在大部分团队里都是可以落地的。如果时间有限,建议先只做“转写 + 待办提取”,不要一上来就追求全套自动化。我见过很多项目是因为步子迈得太大,最后卡在 Agent 派发的可靠性上,连基础的前两步都没用起来。一步步来,比什么都快。