恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
VeapAI 自然语言操作实战|第 03 篇:附件知识加工——一份文档如何变成一条条知识条目
首页
资讯中心
/
VeapAI 自然语言操作实战|第 03 篇:附件知识加工——一份文档如何变成一条条知识条目
VeapAI 自然语言操作实战|第 03 篇:附件知识加工——一份文档如何变成一条条知识条目
发布时间:2026/10/15 4:00:13
系列VeapAI 自然语言操作实战全体系架构专题 本文要点两阶段加工 · 两套策略注册 · 确定性合并五步 · 溯源不变式## 从能读到能查中间隔着一次拆条附件解析完文件是能读了。但用户要的不是能读——用户要问第三十条怎么规定的系统得答得上来。一份 87 页的规章制度人工整理成条目要两三天。难点不在工作量而在一致性同样一条规定两个人整理出的编号、正文、字段可能都不一样。附件知识加工平台里的 mod 叫 kbBuild要解决的就是把拆条变成一条可复用的管线。它的核心设计只有一句话模型出草稿代码定稿。## 两个阶段一条管线![附件知识加工管线输入准备、整体元数据、知识点拆分、保存与稳定契约五个环节]整个加工被拆成两个 stage- stage.docMetadata资料整体元数据从正文里提取这份资料的身份证——标题、编码、标准、元数据、语义内容外加一份拆分提示 splitHints- stage.entrySplit资料分知识点输出按处理策略把正文拆成一条条知识条目。在两个 stage 里模型只负责读内容和写草稿。校验、合并、落库全部由确定性代码完成。这是整条管线最重要的设计原则。## 第一步先给资料办一张身份证docMetadata 的输出是一长串固定键包括- 主题信息title、code、standardCode、taskCode- 内容信息metadata、semanticContent、splitHints 等。所有键都在白名单里一个不多、一个不少。校验器做两件事。第一输出里不允许出现未定义的键。第二metadata 里的字段必须与内容元数据标准逐一核对缺必填字段直接报用户可修复错误。为什么要这么严因为这一步的产物会写进知识主题。模型在这里自由发挥一次后面的所有条目都会继承错误。![第一步整体元数据模型提取身份证校验器逐键核对]## 第二步拆分两套策略各管一段进入 entrySplit 之前先要选两套策略。第一套是处理策略处理模式决定怎么看待这份资料- chapterSplit章节拆分适用于有成文编号的规章、制度、办法- fixedLengthEntry固定长度拆分单知识点提交适用于没有编号结构的说明书、手册。第二套是切分策略分片方式决定正文怎么切成模型能一次读完的分片。取值三种- fixed固定长度加重叠窗口- hierarchy按标题层级切分- semantic按语义聚合切分。配置存在附件资料表的 split_config 字段里管线启动时读取。长文档按重叠窗口分片相邻分片必然带一部分重复内容——这是预期行为不是缺陷。想靠关闭重叠来规避重复是一种偷懒会把跨片的完整条目一起裁掉。去重是合并层的职责。模型逐片输出条目草稿每条含 code、title、content、metadata。接下来是这条管线里最较真的部分合并。![第二步拆分与条目条目的最终形态由合并算法与附件原文共同决定]## 合并五步确定性算法![分片合并契约五个步骤从带重叠的分片输出走到唯一确定的知识条目清单]合并算法entrySplitMerge.js一共五步全部是确定性规则1. 按 code 分组——同一个编号的条目先聚到一起2. 组内折叠——完全一致的去重互相包含的取长的互不包含的保留3. 条型 code 冲突——两个候选互不包含且编号形如第X条时去附件原文找该编号的完整段落用原文覆盖4. 跨 code 去重——不同编号但正文完全一致的条目合并5. 重编号——确认是编号碰撞的比如生成式编号段落1跨片撞号全部保留并重编号为 段落1#2、段落1#3。第三步的裁决来源只有一处附件原文。原文里恰好出现一次才能裁决出现零次或多次直接报用户可修复错误。不猜、不取最长、不静默兜底。三类情形的意义在示例里最清楚- 第十一条在分片 1 和分片 2 各出现一次正文有空白差异 → 折叠成一个条目- 第三十条两个候选互不包含完整版与截断版→ 按附件原文 span 取完整版- 生成式编号段落1跨片撞号 → 两个条目都保留重编号为段落1与段落1#2。## 保存与溯源不变式合并后的条目清单先过保存前校验再走保存入口。接口是 POST /ai/knowledgeTopic/saveForAiBuild采用 Patch 白名单null 表示不更新。保存侧有两个稳定约束。一是 insert 与 update 两个分支的字段必须对称——同一份数据更新分支漏写一个字段展示端就会读到旧值。二是溯源不变式每条条目必须带 sourceRefs引用的是解析片段的 segment_id且这个 ID 在文档资产内唯一。还有一个小而关键的细节正文进入管线前会过滤定位信息——目录页的点线行、孤立页码行、第 N 页共 M 页这类行会被整行删除。这些行混进分片会污染条目正文还会干扰附件原文的裁决定位。而溯源用的片段数据不过滤从哪里引用来就还能回到哪里。## 源码走读- 加工注册veap-ui/src/components/AiConsole/mods/kbBuild/index.js——注册处理策略、切分器、stage 输出校验器与命令- 输出校验stageOutputs/docMetadata.js、stageOutputs/entrySplit.js——输出键白名单与标准字段核对- 合并算法utils/entrySplitMerge.js——五步确定性合并- 策略注册中心utils/processingStrategy.js处理策略、utils/documentSplitter.js切分策略- 保存端点veap-cloud/veap-modules/veap-ai 的 AiKnowledgeTopicController#saveForAiBuild- 切分配置ai_file_datas.split_configJSONstrategyCode params。一个历史包袱的处理方式值得提一句。早期版本靠提示词 bizCode 后缀推断处理模式后来改成显式枚举 processingStrategyCode写入点收敛为一条命令。历史会话缺少这个值时只在会话恢复hydrate时按下线口径推导一次并写回运行期禁止再做推断。## 较真编号碰撞不是错误是常态这套合并算法经历过三轮返工每一轮的起点都是同一类报错entry code conflict。第一轮章节拆分下的第十一条报冲突。根因是重叠窗口让相邻分片带上了同一章节模型的两次输出只差几个空白字符。修法是去掉全部空白再比较按包含关系折叠。第二轮同样的第十一条又来了这次两段互不包含。我们补齐了附件 span 裁决——以原文为准。第三轮报错对象变成了段落1。这类生成式编号本来就不是条文编号跨片撞号是常态硬按同 code 必同条文去裁决附件里根本找不到。最终决策编号碰撞全部保留、重编号只有条型编号才做附件裁决。三轮下来我们对确定性的理解更深了一层确定性不是所有情况都能算出唯一答案而是每种情况都有唯一、可复现的处置规则。算不出来的那种要报错而不是猜。## 复现与验证1. 上传一份带章节编号的文档比如一份管理办法在加工面板完成第一步与第二步2. 保存后查库SELECT code, title, LEFT(content, 40) FROM ai_knowledge_entry WHERE topic_id 主题id ORDER BY id LIMIT 20;核对条目编号与正文3. 想验证合并算法可以把同一份文档分两次跑确认两次结果一致——确定性算法对相同输入产生相同输出。这条管线的边界也说清楚它只负责从附件到条目。条目的发布态、向量化与召回是后面几篇的事。有一件事它明确不做——正文过滤只管整行的定位信息页眉重复行这类边界情形不启用过滤。规则宁少勿滥每一条都要能解释。附件侧的知识有了一条管线系统数据还差一条。下一个问题同样具体表结构、字典、接口这些系统自己的事实怎么变成知识。