AI会议纪要工具排行榜:MapReduce与RAG结构化输出对比
摘要
采用MapReduce与RAG技术生成AI会议纪要:将长字幕按时序切片,每片独立摘要后逐层合并,同
做会议系统相关的事情有一段时间了,但我们的会议模块里,一直缺一个自动生成会议纪要的完整能力。说起来,这个功能并不新鲜。钉钉、飞书、腾讯会议这些成熟产品,早在几年前就上线了 AI 会议纪要。我们去年也排过计划,但业务需求一直在迭代,手头的事情又多,就一直搁置着。最近一次发版后总算有了点空档,认真研究了一番。
目前已经初步跑通了一个 MVP,虽然和大厂的产品还有差距,但至少流程是通的。这篇文章主要记录从需求到实现的过程,效果图放在最后,结尾会聊聊后续的拓展方向。
技术栈: langchain4j + milvus + qwen 的 embedding 模型 + deepseek 的 chat 模型
需求
先说需求。
会议纪要究竟要解决什么问题?很简单:用户开完会(或者中途进会)不想翻几个小时的字幕和语音转写,需要一眼看到核心内容——摘要、结论要点、待办、风险点、发言统计等等。那么,这些信息的来源有哪些?
- 会议基本信息
- 语音转写、字幕
- 人员信息
- 会议描述(如果创建时填了说明,也要作为 AI 总结的上下文)
最核心的当然是语音转录内容。对话是会议最重要的资产,会议纪要就应该从这些对话中结构化地提炼出要点。
但直接拿字幕来做纪要,会面临两个现实问题:
- 内容可能很长——三四个小时的会议,字幕轻松上千条。
- 字幕是口语化的,插话、重复、停顿、上下文跳跃随处可见。
长会议没法把所有内容一次性送给大模型,得拆成多个 chunk。这时候,LangChain 里的 MapReduceDocument 思路就派上用场了。
MapReduce
MapReduce 这个词听起来像大数据里的概念,但用到 AI 会议纪要上,其实很好理解。
把一场长会议看作一篇超长文档。文档短,直接给大模型总结就行。但文档太长——比如会议持续一两个小时、字幕上千条——直接塞给大模型会出问题:
- 上下文长度可能不够。
- 单次请求 token 太多,响应时间很长。
- 请求失败后重试成本高。
- 模型容易关注后半段,遗漏中间议题。
- 就算模型能处理,也不一定能保证每个阶段的信息都被总结到。
所以,先把长会议拆成小片段,每个片段单独总结,最后再把所有片段的总结合并成一份完整纪要。这就是 MapReduce 的基本思路。
- Map:拆成多个 chunk,每个 chunk 单独生成摘要
- Reduce:把所有 chunk 的摘要合并,生成最终会议纪要
对应到会议纪要,流程如下:
没有直接照搬 LangChain 的 MapReduceDocumentsChain,但思路一致。LangChain 的 MapReduceDocumentsChain 本质上也是先对多个 document 分别执行 llm_chain,再把 map 结果交给 reduce chain 做最终汇总。官方描述说得很清楚:Combining documents by mapping a chain over them, then combining results.
对应到我们的场景:
LangChain 概念 → AI 会议纪要里的实现
Document → 一段会议字幕 chunk
map chain → 对单个 chunk 生成局部摘要
reduce chain → 汇总所有局部摘要生成最终纪要
recursive reduce → 超长会议时分层合并
metadata → 会议标题、成员、时间、字幕行号
有一点要特别留意:字幕切分不能只按字符数。会议是有时间线的,用户后面查看关联发言、章节时间线、任务来源时,都需要回到原始发言的时间点。所以更合理的做法是按时间窗口切——比如每 8 分钟作为一个 chunk,相邻 chunk 之间保留一点 overlap。
为什么要有 overlap?避免一句话被刚好切在两个 chunk 中间。举个例子:
00:07:58 张三:这个接口如果周五前还没联调完
00:08:02 李四:就会影响下周验收
如果严格按 8 分钟切,第一句在前一个 chunk,第二句在后一个 chunk,模型在总结单个 chunk 时可能理解不了完整语义。保留一小段重叠,上下文就不会断得太生硬。
第一版实现时的生成流程大致如下:
比如有 40 个 chunk,如果直接把 40 个摘要全部交给最终 Reduce,仍然可能太长。这时可以分层:每 8 个摘要先合并一次,得到 5 个中间摘要,再用这 5 个中间摘要生成最终纪要。
40 个 chunk
-> 40 个局部摘要
-> 每 8 个合并成 1 个中间摘要
-> 5 个中间摘要
-> 最终会议纪要
这样做的好处是每一步输入都在可控范围内,失败后可以只重试某一段,不用整场会议全部重来。
当然,MapReduce 也不是完美的。最大的问题是:Map 阶段做了一次压缩,压缩后很多细节可能丢失。比如原始字幕里有这几句话:
- 张三:这个接口现在还没有联调。
- 李四:如果周五前没有完成,会影响下周验收。
- 王五:那这个风险先记录下来,我来跟进。
Map 阶段可能总结成:讨论了接口联调延期可能影响验收的问题,并安排人员跟进。 这个摘要作为最终纪要的一部分是够用的,但如果用户想知道“是谁说的”“原话是什么”“风险是怎么得出来的”,尤其当第一个 chunk 的结论在第三个 chunk 里被推翻时,只靠摘要就不够了。这也是后面要引入 RAG 的原因。
引入 RAG
一开始并不想把会议纪要做得太重。引入向量库意味着复杂度上升、调用增多,会影响实时输出的等待时间。但仔细一想,会议的对话字幕作为核心资产,迟早要纳入向量库。干脆先做一部分 RAG,用来做证据补充。
引入向量库还有一个附加好处:把 RAG 召回的内容一起丢给大模型,能让输出的结论有据可依,一定程度上缓解模型的幻觉问题。
为什么不在 prompt 里直接要求模型引用原文?
这是个很自然的问题:既然想让结论有原文依据,直接在提示词里说“请指出对应结论的原文行”不就行了吗?
短会议确实可以——字幕能完整放进上下文,模型有机会一边总结一边引用原文。但会议一长,问题就来了。
- Reduce 阶段看不到原始字幕。 经过 MapReduce 后,Reduce 拿到的不是原始字幕,而是 Map 阶段生成的摘要。模型只能基于分片摘要生成最终结果。如果你要求它“给出原文”,它只能引用 Map 摘要里的内容,甚至可能凭印象补一段看起来像原文的话——那不是真正的原文,而是加工后的二手内容。
- 就算把原始字幕放进 prompt,模型也不一定能稳定引用准确行号。 模型擅长概括,不擅长严格的索引定位。字幕有几百上千条时,它可能引用错行、漏行,或者把多人的发言混在一起。而我们做溯源,要求准确度很高,不能依赖模型。
- 关联补充可能发生在生成之后。 第一个小时生成的结论,第二个小时可能有人做了补充。新的发言也应该关联到前面的结论中去。
会议纪要生成的数据流转
生成时机有两种:用户手动点击生成,或者会议结束后自动触发。后端收到触发后进入主链路。数据链路图如下(由 ChatGPT 生成):
按图一步步解释:
加锁
防止同一场会议被重复生成。比如用户连续点击多次,或自动任务和手动生成同时触发,没有锁就可能多个任务并行跑,最后互相覆盖结果。
上下文查询
拿到锁后,后端收集上下文,主要包括:
- 会议基础信息
- 会议成员
- 原始字幕
- 会议说明
- 已有的会议文档内容
最重要的还是原始字幕——AI 会议纪要的主要信息来源就是它。其他信息更多是辅助,帮模型了解会议背景。
上下文收集完成后,系统判断会议长度。短会议直接送模型;长会议进入 MapReduce。
切片
按时间切片,不按字符数。因为会议天然有时间线,后续章节时间线、关联发言定位都依赖字幕的时间信息。每个切片独立生成分片摘要,再进入 Reduce 生成最终纪要。如果切片特别多,可以继续做层级 Reduce:先把多个分片摘要合并成中间摘要,再用中间摘要生成最终纪要,避免 Reduce 阶段输入过长。
字幕清洗与去重
这里的清洗不是音频识别——后端拿到的已经是转写文本。清洗主要做文本规范化:空白处理、重复标点压缩、低价值短句过滤、显式噪音标记兼容清理。去重则是减少重复内容进入索引。
分块
清洗之后是分块。为什么不直接每一条字幕作为一个向量存进去?因为单条字幕通常太短,语义不完整。比如:
- 张三:这个接口现在还没联调。
- 李四:如果周五前没完成,会影响验收。
- 王五:那我这边先把风险记录下来。
单独看每一句,信息都不完整。更合理的做法是把相邻字幕组成一个 chunk,保留一段上下文。一个 chunk 可能长这样:
- [张三 10:05] 这个接口现在还没联调。
- [李四 10:08] 如果周五前没完成,会影响验收。
- [王五 10:12] 那我这边先把风险记录下来。
这样 embedding 时,模型看到的是完整上下文,而不是孤立的一句话。分块主要考虑几个因素:最大字符数、时间间隔(两句话隔太久可能话题已变)、语义转场(比如“接下来”“下面看下一个问题”)、overlap(避免上下文被切断)。这里的 overlap 和 MapReduce 的 overlap 类似,都是为了解决边界问题。
证据补充:一定程度上解决模型幻觉
注意:向量库并不是在最终结果生成后才补充关联数据!
在 Reduce 生成最终纪要之前,RAG 链路就可以先构建一个证据包。证据包里包含和会议重点相关的原始字幕片段,比如任务相关发言、风险相关发言、决策相关发言、未决问题相关发言、章节主题相关发言。然后这个证据包被放进 Reduce prompt 里。这样最终生成纪要时,模型看到的不仅是 Map 阶段压缩后的分片摘要,还有一部分原始证据。对于长会议,这很关键——Map 摘要是压缩过的,细节可能丢失,RAG 证据包能把关键原文重新补回 Reduce 阶段。
输出
最后 Reduce 阶段,把多个 chunk 的结论汇总,结合 RAG 证据包,总结出整场会议的纪要,并以流式输出。
结构化输出
后端输出的是 Markdown 格式的流式内容,前端用产品内部的文档库来承载。文档库本身支持把 Markdown 转成内部文档格式,所以前端可以先展示流式 Markdown,让用户看到内容正在生成;等生成完成后,再把摘要、任务、风险、关联发言等内容转换成自定义卡片,形成结构化的会议纪要。(页面是我自己验证时做的,设计和前端都是自己动手,有点粗糙,见谅。)
下一步计划
目前的效果只是基本可用,后续还有很多值得深挖的方向。
声纹识别
语音转写是纪要的核心数据,准确度和人员区分都还需要提升。目前用阿里云的百炼模型,准确度尚可,但多人同麦时无法区分人员。后续需要找到支持声纹识别的厂商或方案。
生成结果有待优化
目前的实现虽然结论有据可依,但每次生成的结果不稳定——有时将多个风险合并成一个,有时把一个任务拆成多个。如何约束输出格式,还需要进一步优化。
其他模块联动
相比其他产品,我直接设计了任务模块,可以在会议纪要页面创建任务。但联动性不足,比如能否结合此人的历史任务记录、未来的排期计划,来推算任务的截止时间、负责人和优先级?这些都是需要考虑的。
总结
在动手之前,RAG 相关的文章已经看了不少。但真正做一遍,才能深入理解很多概念。这篇文章没有事无巨细地展开(比如还用了召回和重排),更多是思路上的总结。这次做的 AI 会议纪要还比较粗糙,后续会不断优化。
来源:互联网
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。