1. 为什么我要从零搭一套资料汇编的编排架构
历史专题资料汇编这件事,做过的人都知道,它跟普通的文档整理完全是两码事。普通文档整理,你把文件按目录分好、改个名、写个索引就完事了。但历史专题资料汇编的核心难点在于:同一件事在不同来源里的表述可能互相矛盾,时间线需要交叉验证,人物关系需要反复比对,而且资料本身往往是碎片化的——一段摘录、一张表格、一份扫描件里的几行字。你拿到手的不是一篇完整的文章,而是几十上百条散落在各处的信息碎片,需要把它们拼成一条逻辑自洽的叙事线。
我最初接手这个任务的时候,想得很简单:不就是把资料收集起来、分类、然后按时间排一排吗?结果第一轮实操下来就发现,光是“分类”这一步就足够让人崩溃。同一份资料可能同时涉及政治、经济、文化三个维度,你把它放哪个文件夹都不对。更麻烦的是,很多资料之间存在隐含的关联——比如某份文件里提到的一个地名,在另一份资料里是作为背景出现的,如果你不把这两条信息关联起来,整个叙事就会出现断裂。
所以到了第二轮,我开始认真考虑用 AI Agent 来编排整个流程。注意,我这里说的“Agent 编排”不是指让一个大模型从头到尾包办所有事情,而是把资料汇编拆解成多个独立的子任务,每个子任务交给专门的 Agent 去处理,然后通过一个编排层来协调它们之间的数据流转和状态管理。这个思路的核心逻辑是:历史资料汇编的每个环节——采集、清洗、分类、关联、校验、成文——对能力的要求完全不同,用一个通用模型硬扛所有环节,效果远不如让每个环节用最适合它的处理方式。
举个例子,资料清洗环节需要的是极强的格式解析能力,你得能从 PDF、图片 OCR 结果、网页摘录、手写笔记照片里把文字准确提取出来;而关联分析环节需要的是推理能力,你得判断两条信息之间是因果关系、时间先后关系还是纯粹的并列关系。这两件事对模型的要求截然不同,前者更看重鲁棒性和容错率,后者更看重逻辑推理的深度。把它们拆开,各自用最合适的方案,整体效果会好很多。
这套架构我前后迭代了六轮,每一轮都是拿真实的历史专题资料跑完整流程,然后根据暴露出来的问题调整设计。下面我把这六轮复盘的核心内容整理出来,包括架构设计的思路、每个环节的具体实现、踩过的坑以及最终的稳定方案。如果你也在做类似的历史资料整理工作,或者正在考虑用 Agent 架构来处理复杂的文档编排任务,这些经验应该能帮你少走不少弯路。
2. 整体架构设计与六轮迭代思路拆解
2.1 核心设计原则:分而治之加状态可追溯
整套架构的设计原则说起来就两条,但每条背后都有血泪教训。
第一条是分而治之。历史资料汇编的流程天然可以拆成六个阶段:资料采集、格式清洗、内容分类、关联建网、交叉校验、汇编成文。每个阶段之间的输入输出边界非常清晰——采集阶段的输出是原始文件列表,清洗阶段的输出是结构化文本,分类阶段的输出是带标签的资料条目,关联阶段的输出是条目之间的关系图谱,校验阶段的输出是修正后的条目和关系,成文阶段的输出是最终文档。这种清晰的边界让每个阶段都可以独立优化,不会牵一发而动全身。
第二条是状态可追溯。这条是我在第三轮迭代时才真正重视起来的。当时遇到的问题是:某条资料在分类阶段被标成了“经济类”,但在关联阶段又被当成“文化类”去匹配关系,导致最终成文时出现了逻辑矛盾。排查了半天才发现,是分类 Agent 和关联 Agent 之间的状态传递出了问题——分类 Agent 更新了标签,但关联 Agent 读到的还是旧版本的数据。从那以后,我给每个资料条目都加了一个版本号字段,任何 Agent 修改了条目内容,版本号就递增,下游 Agent 必须读取最新版本才能开始工作。这个机制看起来简单,但它是保证多 Agent 协作不出乱子的基础。
2.2 六轮迭代分别解决了什么问题
第一轮的核心目标是跑通流程。我用最朴素的方式把六个阶段串起来,每个阶段就是一个独立的处理函数,中间用 JSON 文件传递数据。这一轮暴露的最大问题是:资料清洗阶段的准确率太低,PDF 里的表格提取出来全是乱码,图片 OCR 的错误率也高得离谱。但至少证明了整个流程是可行的。
第二轮的重点是提升清洗质量。我引入了多引擎并行的策略——同一份 PDF 同时用两种不同的解析方式处理,然后对比结果,不一致的地方标记出来人工复核。这个策略把清洗准确率从大概六成提升到了八成五左右。但代价是处理速度慢了一倍,而且人工复核的工作量还是不小。
第三轮解决的是状态一致性问题。就是前面提到的版本号机制。这一轮还顺带把数据存储从纯 JSON 文件换成了 SQLite,因为 JSON 文件在并发写入时经常出现数据覆盖的问题。SQLite 虽然简单,但事务机制能保证数据一致性,对于这种单机跑的任务来说完全够用。
第四轮优化的是关联分析的准确率。之前的关联 Agent 只会做简单的时间线匹配和关键词共现分析,经常把不相关的两条资料关联到一起。我给它加了一个“关联置信度”的评分机制,每条关联关系都要给出一个 0 到 1 之间的置信度分数,低于阈值的关联直接丢弃,高于阈值的关联进入人工抽检环节。这个改动让关联准确率有了明显提升。
第五轮做的是性能优化。前四轮跑一个中等规模的历史专题(大概两千条资料)需要将近四个小时,太慢了。我分析了各阶段的耗时分布,发现瓶颈主要在清洗阶段和关联阶段。清洗阶段的优化思路是引入缓存机制——同一份文件如果之前处理过,直接读缓存结果;关联阶段的优化思路是把全量两两比对改成基于倒排索引的候选集筛选,只对可能相关的资料对做深度分析。这两项优化把总耗时压缩到了一个小时以内。
第六轮是稳定性加固。这一轮没有加新功能,而是把之前六轮里遇到的所有异常情况都梳理了一遍,给每个阶段加了重试机制、超时控制和降级方案。比如清洗阶段如果某个文件解析失败,不会直接中断整个流程,而是把该文件标记为“待人工处理”,继续处理下一个文件。这一轮之后,整套架构才算真正达到了可以稳定跑真实任务的水平。
2.3 为什么选择多 Agent 而不是单体大模型
这个问题我被问过很多次。用一个大模型从头到尾处理所有环节,理论上不是不行,但实际跑下来有几个绕不过去的坎。
首先是上下文长度限制。历史专题资料汇编动辄涉及几百上千条资料,全部塞进一个模型的上下文里根本不现实。就算用支持超长上下文的模型,成本也会高到无法接受。而多 Agent 架构下,每个 Agent 只需要处理自己那一小部分数据,上下文压力小得多。
其次是错误传播问题。单体模型如果在前面的清洗环节出了错,这个错误会一路传播到最终的成文结果里,而且很难定位到底是哪一步出的问题。多 Agent 架构下,每个阶段的输出都要经过校验才能进入下一阶段,错误在早期就会被拦截。
最后是可替换性。多 Agent 架构下,如果我发现某个环节用另一种方案效果更好,只需要替换那一个 Agent 就行,其他部分完全不用动。单体模型要做到这一点,基本上等于重新训练一遍。
当然,多 Agent 架构也有它的代价——协调成本更高,调试更复杂,对状态管理的要求更严格。但这些代价相对于它带来的灵活性和可控性来说,是完全值得的。
3. 核心环节的实操要点与避坑指南
3.1 资料采集与清洗:多引擎并行加人工兜底
资料采集阶段的核心任务是把各种格式的原始文件统一转换成纯文本。历史资料的来源非常杂,有扫描版 PDF、有网页截图、有手写笔记的照片、有 Excel 表格、甚至还有录音转写的文字稿。每种格式的处理方式都不一样。
对于 PDF 文件,我的做法是同时用两种解析引擎处理。一种基于文本层提取,适合电子版 PDF;另一种基于版面分析加 OCR,适合扫描版 PDF。两种结果出来后做差异比对,如果差异率低于百分之五,就取文本层提取的结果;如果差异率高于百分之五,说明这份 PDF 可能是扫描版或者排版特别复杂,就取 OCR 的结果,同时标记为“需人工复核”。
对于图片资料,OCR 是绕不开的环节。我试过好几个 OCR 方案,最终选定的方案是在通用 OCR 基础上加了一个历史文献专用词典。这个词典里收录了历史资料中常见的人名、地名、机构名、年号等专有名词,OCR 引擎在识别时会优先匹配词典里的词条。这个改动把 OCR 的专有名词识别准确率提升了一大截。
实操心得:OCR 结果一定要做后处理。我遇到过好几次 OCR 把“己亥年”识别成“已亥年”的情况,这种错误如果不在清洗阶段修正,到了关联分析阶段就会导致时间线错乱。我的做法是维护一个常见错误映射表,OCR 结果出来后自动替换一遍。
清洗阶段还有一个容易被忽视的问题:表格数据的结构化提取。历史资料里有大量表格,比如人口统计表、赋税记录表、行政区划表等。这些表格如果只是提取成纯文本,后续根本没法用。我的做法是先用版面分析模型识别出表格区域,然后用表格结构识别模型提取行列信息,最后输出成结构化的 JSON 格式。这个过程准确率大概在八成左右,剩下的两成需要人工修正。
3.2 内容分类:多标签体系加置信度评分
分类环节是整个流程里最考验设计功力的地方。历史资料的一个特点是一条资料往往同时属于多个类别。比如一份关于某地水利工程的奏折,它既属于“经济”类别(涉及财政支出),又属于“技术”类别(涉及工程技术),还可能属于“人物”类别(涉及主持工程的官员)。
我的解决方案是采用多标签分类体系,每条资料可以同时打上多个标签,每个标签附带一个置信度分数。分类 Agent 的工作流程是:先对资料内容做主题抽取,得到若干候选主题;然后把候选主题映射到预设的标签体系上;最后对每个标签给出置信度评分。
标签体系的设计我改了三版。第一版太粗,只有“政治”“经济”“文化”三个大类,结果大部分资料都堆在“政治”下面,根本没法用。第二版太细,分了三十多个小类,结果分类 Agent 经常在几个相近的类别之间摇摆不定。第三版折中了一下,设了八个一级标签和二十个二级标签,一级标签用于粗筛,二级标签用于精确定位。这个粒度用下来比较顺手。
注意事项:分类 Agent 的提示词里一定要明确告诉它“宁可多打标签,不要漏打标签”。漏打标签会导致后续关联分析时丢失重要线索,而多打标签最多只是增加一点人工复核的工作量。两害相权取其轻。
3.3 关联建网:从关键词共现到语义推理
关联建网是整套架构里技术含量最高的环节。它的目标是把分散的资料条目按照时间、地点、人物、事件等维度关联起来,形成一张知识图谱。这张图谱的质量直接决定了最终成文的质量。
我最初的做法很简单:两条资料如果包含相同的关键词,就建立一条关联。这个方法的问题很明显——关键词相同不代表真的相关。比如两条资料都提到了“北京”,但一条讲的是建筑,一条讲的是科举考试,硬把它们关联起来毫无意义。
后来我改成了多维度关联评分。每条关联关系从四个维度打分:时间接近度(两条资料提到的时间是否接近)、地点重合度(是否涉及同一地点)、人物重合度(是否涉及同一人物)、语义相似度(用文本向量计算的内容相似程度)。四个维度的分数加权求和,得到最终的关联置信度。
权重的设定我调了好几次。最终确定的权重是:时间接近度占百分之三十,地点重合度占百分之二十,人物重合度占百分之三十,语义相似度占百分之二十。这个权重分配是基于历史资料的特点——人物和时间的关联性最强,地点次之,纯语义相似度最弱。
实操技巧:关联分析一定要做传递性校验。如果 A 和 B 有关联,B 和 C 有关联,但 A 和 C 之间没有直接关联,这时候需要判断 A 和 C 是否应该通过 B 间接关联。我的做法是设置一个传递阈值,只有当 A-B 和 B-C 的置信度都高于某个值时,才建立 A-C 的间接关联。
3.4 交叉校验:矛盾检测与自动修正
交叉校验环节的任务是发现资料之间的矛盾之处,并尝试修正。历史资料里矛盾太常见了——同一件事在不同来源里的记载可能完全不同,同一个人物的生卒年份可能有好几种说法,同一个地名的古今对照可能对不上。
我的校验 Agent 主要做三件事。第一是时间线校验,把所有资料里提到的时间点提取出来,按时间排序,检查是否存在逻辑矛盾。比如某条资料说某人在某年做了某件事,但另一条资料说这个人在这之前就已经去世了,这就是一个明显的时间线矛盾。
第二是数值校验,对于涉及数字的资料(人口数、赋税额度、军队人数等),检查同一指标在不同资料里的数值差异是否在合理范围内。如果差异超过阈值,就标记为“数值矛盾”,需要人工判断哪个数值更可靠。
第三是实体一致性校验,检查同一实体在不同资料里的名称是否一致。历史资料里同一个人可能有字号、别称、官职名等多种称呼,同一个地名可能有古今不同的写法。校验 Agent 会尝试把这些称呼归并到同一个实体上,如果归并过程中出现冲突,就标记出来人工处理。
避坑经验:校验 Agent 不要试图自动修正所有矛盾。有些矛盾是历史资料本身的特点,不同来源的记载就是不一样,强行统一反而会丢失信息。我的做法是只自动修正那些“明显是错误”的矛盾(比如错别字、明显的笔误),对于“可能各有道理”的矛盾,保留原始记录并标注出来,留给人工判断。
4. 完整实操流程与关键配置
4.1 环境准备与依赖安装
整套架构跑在 Python 环境下,核心依赖包括文档解析库、OCR 引擎、文本向量模型和数据库驱动。下面是我实际使用的依赖清单和版本说明。
# 创建虚拟环境 python -m venv history_agent_env source history_agent_env/bin/activate # 核心依赖安装 pip install pdfplumber==0.10.3 # PDF 文本层提取 pip install paddleocr==2.7.0 # OCR 引擎 pip install layoutparser==0.3.4 # 版面分析 pip install sentence-transformers==2.2.2 # 文本向量 pip install sqlalchemy==2.0.23 # 数据库 ORM pip install networkx==3.2.1 # 关系图谱 pip install jieba==0.42.1 # 中文分词数据库我用的是 SQLite,对于单机跑的任务来说足够用了。建表语句如下:
CREATE TABLE documents ( id INTEGER PRIMARY KEY AUTOINCREMENT, source_path TEXT NOT NULL, raw_text TEXT, clean_text TEXT, version INTEGER DEFAULT 1, status TEXT DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE tags ( id INTEGER PRIMARY KEY AUTOINCREMENT, document_id INTEGER, tag_name TEXT, confidence REAL, FOREIGN KEY (document_id) REFERENCES documents(id) ); CREATE TABLE relations ( id INTEGER PRIMARY KEY AUTOINCREMENT, doc_a_id INTEGER, doc_b_id INTEGER, relation_type TEXT, confidence REAL, FOREIGN KEY (doc_a_id) REFERENCES documents(id), FOREIGN KEY (doc_b_id) REFERENCES documents(id) );4.2 清洗 Agent 的核心实现
清洗 Agent 的输入是一个文件路径,输出是结构化文本。核心逻辑是先用文件扩展名判断类型,然后分派给对应的处理函数。
import pdfplumber from paddleocr import PaddleOCR class CleaningAgent: def __init__(self): self.ocr = PaddleOCR(use_angle_cls=True, lang='ch') self.error_map = self._load_error_map() def _load_error_map(self): # 加载常见 OCR 错误映射表 return { '已亥': '己亥', '戊戍': '戊戌', '辛丑年': '辛丑年', # ... 更多映射 } def process_pdf(self, path): # 双引擎并行处理 text_layer = self._extract_text_layer(path) ocr_result = self._extract_ocr(path) if self._diff_rate(text_layer, ocr_result) < 0.05: return self._post_process(text_layer) else: return self._post_process(ocr_result, need_review=True) def _post_process(self, text, need_review=False): # 错误映射替换 for wrong, right in self.error_map.items(): text = text.replace(wrong, right) return { 'text': text, 'need_review': need_review }这里的关键点是差异率计算。我的做法是把两段文本都做分词,然后计算词集合的 Jaccard 距离。距离小于 0.05 说明两个引擎的结果高度一致,可以信任文本层提取的结果;距离大于 0.05 说明存在较大分歧,需要走 OCR 结果并标记人工复核。
4.3 分类 Agent 的提示词设计
分类 Agent 的效果很大程度上取决于提示词的质量。我前后改了十几版提示词,最终稳定下来的版本核心结构是这样的:
CLASSIFICATION_PROMPT = """ 你是一个历史资料分类助手。请对以下资料进行多标签分类。 分类体系: 一级标签:政治、经济、文化、军事、社会、地理、人物、事件 二级标签:[每个一级标签下各有若干二级标签,此处省略具体列表] 要求: 1. 每条资料至少打一个一级标签,最多打三个。 2. 每个标签必须附带 0 到 1 之间的置信度分数。 3. 如果资料内容涉及多个维度,不要犹豫,全部打上标签。 4. 宁可多打标签,不要漏打标签。 资料内容: {content} 请以 JSON 格式输出,格式如下: { "tags": [ {"name": "政治", "confidence": 0.85}, {"name": "经济", "confidence": 0.72} ] } """实操心得:提示词里一定要给出具体的输出格式示例。我最初没给示例的时候,模型输出的格式五花八门,有的用列表有的用字典,解析起来特别麻烦。给了 JSON 示例之后,输出格式就稳定多了。
4.4 关联 Agent 的评分计算
关联 Agent 的核心是评分函数。下面是我实际使用的评分逻辑:
def calculate_relation_score(doc_a, doc_b): # 时间接近度 time_score = calc_time_proximity(doc_a.time, doc_b.time) # 地点重合度 place_score = calc_place_overlap(doc_a.places, doc_b.places) # 人物重合度 person_score = calc_person_overlap(doc_a.persons, doc_b.persons) # 语义相似度 semantic_score = calc_semantic_similarity(doc_a.embedding, doc_b.embedding) # 加权求和 weights = { 'time': 0.3, 'place': 0.2, 'person': 0.3, 'semantic': 0.2 } total = ( time_score * weights['time'] + place_score * weights['place'] + person_score * weights['person'] + semantic_score * weights['semantic'] ) return total时间接近度的计算方式是:如果两条资料提到的时间在同一年内,得 1 分;相差一到三年,得 0.7 分;相差三到五年,得 0.4 分;相差超过五年,得 0 分。这个梯度是根据历史资料的特点设定的——历史事件的影响通常在三到五年内最为集中。
人物重合度的计算方式是:两条资料涉及的人物集合的 Jaccard 相似度。如果两条资料都提到了同一个人物,而且这个人物在两条资料里都是核心角色,那么得分会更高。我额外加了一个“核心人物加权”的机制,如果重合的人物在资料中出现的频率排在前三位,权重乘以 1.5。
4.5 校验 Agent 的矛盾检测规则
校验 Agent 的规则库是我在六轮迭代中逐步积累起来的。下面列出最常用的几条检测规则:
| 规则名称 | 检测逻辑 | 处理方式 |
|---|---|---|
| 时间线矛盾 | 同一人物在两条资料中的活动时间存在逻辑冲突 | 标记为高优先级人工复核 |
| 数值差异 | 同一指标在不同资料中的数值差异超过 20% | 标记并保留两个数值 |
| 实体名称不一致 | 同一实体的名称在不同资料中写法不同 | 尝试归并,失败则标记 |
| 地理坐标冲突 | 同一地名在不同资料中对应的现代位置不同 | 标记为待考证 |
| 事件因果矛盾 | 两条资料对同一事件的因果关系描述相反 | 标记为高优先级人工复核 |
注意事项:校验规则不要设得太激进。我最初设了一条“同一事件在不同资料中的描述相似度低于 0.3 就标记为矛盾”的规则,结果误报率特别高——很多资料只是从不同角度描述同一件事,相似度天然就低。后来把阈值降到了 0.15,误报率才降下来。
5. 常见问题与排查技巧实录
5.1 清洗阶段典型问题速查
清洗阶段最常见的问题就是 OCR 识别错误。除了前面提到的专有名词错误,还有几类高频错误值得注意。
第一类是形近字混淆。比如“日”和“曰”、“未”和“末”、“土”和“士”,这些字在扫描件里如果清晰度不够,OCR 很容易搞混。我的应对方式是在后处理阶段加一个基于上下文的纠错模块——用一个小型的语言模型判断当前语境下哪个字更合理。
第二类是竖排文本识别错误。很多历史资料是竖排排版的,OCR 引擎如果按横排方式处理,出来的结果就是乱序的。我的做法是在版面分析阶段就检测文本方向,如果是竖排,先做旋转校正再送 OCR。
第三类是表格线干扰。扫描件里的表格线有时候会被 OCR 当成文字笔画,导致识别结果里混入大量横线竖线字符。我的处理方式是在 OCR 之前先做一轮表格线检测和去除,把表格线从图像里抹掉再识别文字。
5.2 关联分析中的误关联排查
误关联是关联分析阶段最头疼的问题。我总结了几种典型的误关联模式:
同名异实现象是最常见的。历史资料里同名的人物、地名非常多,如果不加区分地按名称匹配,就会把完全不相关的资料关联到一起。我的解决方案是给每个实体加上“上下文指纹”——除了名称之外,还记录该实体出现的时代、地域、相关事件等信息。匹配时不仅要比对名称,还要比对上下文指纹。
时间窗口设置不当也会导致误关联。我最初把时间窗口设得太宽,结果把相隔几十年的资料都关联起来了。后来改成动态时间窗口——对于政治事件,窗口设为三年;对于经济数据,窗口设为五年;对于文化现象,窗口设为十年。不同类型的资料用不同的时间窗口,误关联率明显下降。
语义相似度陷阱也值得警惕。有些资料用词很接近,但讲的是完全不同的事情。比如两份资料都大量使用了“改革”“调整”“变更”这类词,但一份讲的是税制改革,一份讲的是行政区划调整。纯靠语义相似度会把它们关联起来,但实际上是误关联。我的应对方式是语义相似度只作为辅助维度,权重控制在 0.2 以内,主要依赖时间、地点、人物这三个硬维度。
5.3 性能瓶颈的定位与优化
第五轮迭代时我做了一次完整的性能剖析,定位到了几个关键瓶颈。
清洗阶段的瓶颈主要在 OCR 调用上。每次调用 OCR 引擎都有固定的初始化开销,如果逐张图片调用,开销会累积得非常大。我的优化方案是批量处理——把多张图片攒在一起,一次性送入 OCR 引擎,这样初始化开销只付一次。
关联阶段的瓶颈在两两比对。两千条资料如果做全量两两比对,就是将近两百万次比较,每次比较都要计算语义相似度,耗时巨大。我的优化方案是倒排索引加候选集筛选——先根据时间、地点、人物三个维度建立倒排索引,然后只对至少在一个维度上有交集的资料对做深度比较。这样候选集通常只有几万对,计算量降了一个数量级。
数据库写入的瓶颈也不容忽视。最初我每处理完一条资料就写一次数据库,结果 IO 开销成了瓶颈。后来改成批量提交——每处理完一百条资料批量写入一次,写入耗时降到了原来的十分之一。
5.4 六轮迭代中的关键教训
回顾这六轮迭代,有几个教训是用真金白银的时间换来的。
教训一:不要试图一步到位。我第一轮就想设计一个完美的架构,结果花了大量时间在架构设计上,实际跑起来发现各种问题。后来改成每轮只解决一个核心问题,快速迭代,反而效率更高。
教训二:人工复核环节不能省。我一度想做到全自动,把所有环节都交给 Agent 处理。但实际跑下来发现,历史资料的特殊性决定了人工判断是不可替代的。最终的方案是 Agent 处理百分之八十的常规情况,剩下百分之二十的疑难情况交给人工,整体效率反而比追求全自动更高。
教训三:数据版本管理要趁早做。我是在第三轮才引入版本号机制的,前两轮因为数据覆盖问题浪费了大量时间排查。如果一开始就做好版本管理,能省下不少功夫。
教训四:日志要详细,但不要冗余。我最初把每个 Agent 的每一步操作都记了日志,结果日志文件膨胀到几个 G,排查问题时反而找不到关键信息。后来改成只记录关键决策点和异常情况,日志量降到了原来的百分之五,排查效率反而提高了。
最后分享一个实用技巧:给每个 Agent 加一个“干跑模式”。在这个模式下,Agent 只输出它打算做什么,不实际执行。这个模式在调试新规则时特别有用,可以快速验证逻辑是否正确,而不用等整个流程跑完。
6. 架构的扩展方向与个人体会
这套架构目前跑历史专题资料汇编已经比较稳定了,但它的适用范围远不止于此。我后来把它迁移到了几个类似的场景:一个是企业档案的整理,一个是学术文献的综述编排,还有一个是地方志的数字化整理。核心逻辑基本不用改,只需要调整分类体系和关联规则就行。
扩展的时候有几个点需要注意。分类体系要跟着领域走——历史资料的分类体系和企业档案的分类体系完全不同,不能直接套用。关联规则的权重也要调整——学术文献更看重语义相似度,时间维度的权重可以降低;企业档案更看重部门和项目关联,人物维度的权重需要提高。校验规则也要重新设计——不同领域的数据矛盾类型不一样,需要针对性地设计检测规则。
我个人在实际操作中的体会是,Agent 编排架构的核心价值不在于“自动化”,而在于“可拆解”和“可追溯”。它把一个大问题拆成若干个小问题,每个小问题都有明确的输入输出和验收标准,这样你才能清楚地知道哪个环节出了问题、该怎么改。如果用一个黑盒模型从头跑到尾,出了问题你根本无从下手。
另外,不要迷信“最新最强的模型”。我在选型时试过好几个当时最热门的方案,结果发现对于历史资料这种专业性很强的领域,一个经过针对性微调的小模型,效果往往比通用大模型更好。关键是要把领域知识注入进去——不管是通过提示词、微调还是后处理规则,领域知识才是决定最终效果的核心因素。
这套架构后续还可以往几个方向扩展。一个是多模态资料的深度整合——目前对图片和表格的处理还比较浅,后续可以加入图像内容理解和表格语义分析。另一个是增量更新机制——目前每次跑都是全量处理,后续可以做成增量式的,只处理新增资料,已处理过的资料直接复用之前的结果。还有一个是协作功能——目前人工复核环节是单机操作的,后续可以做成多人协作的,不同的人负责不同类别的复核任务。
这些扩展方向我还在陆续尝试,等跑出稳定结果了再整理出来分享。如果你也在做类似的事情,欢迎交流踩坑经验。