术语问题的两种形态:检索不到与检索错
领域术语对 RAG 系统的破坏有两种形态,症状和解法完全不同,先分清是哪一种(或两种都有),再动手建设施。
形态一:OOV 术语导致双通道齐失灵
新药代号、法规编号、内部项目代号这类词,对检索系统是真正的生词。生成侧的症状是模型自信地瞎编(把内部代号"启明计划"解释成一个不存在的开源项目);检索侧的症状更隐蔽:embedding 和 BM25 会同时失灵。BM25 失灵的原因是分词——"无因管理"被切成"无因"和"管理",字面倒排索引里根本不存在这个词条;embedding 失灵的原因是稀疏性——生词在训练分布里几乎没有上下文,向量质量不可信。双通道同时失灵意味着混合检索也救不了,必须有一个显式的术语层来补。
形态二:一词多义导致检索错
第二种形态更伤人:术语没有生僻到检索不到,但同一个词形在不同语境下指向完全不同的内容。"利率"在债券交易文档和存款产品文档里是两回事,"缓存"在 CPU 文档和 Redis 运维手册里是两个概念,"发布"在软件工程文档和营销物料里含义迥异。多义术语的症状是检索回来的文档词面高度相关但领域错位——用户是存款业务的人,检索回来一堆债券研报,每一段都提到"利率",没有一段能回答问题。这种错位还会污染生成:上下文里塞满错误领域的"相关"内容,模型会基于错误语境作答。
术语表的设计与治理
最小字段集与状态机
术语表不需要一开始就做成庞大的本体系统,最小可用字段集是六个:规范名(canonical term)、别名列表(缩写、口语、历史曾用名、中英映射)、定义(一到两句话的领域内权威解释)、所属域(domain,金融/医疗/内部系统 A……)、状态(生效/废弃/被取代)、关联术语(上下位与易混淆项)。状态字段尤其重要:企业术语有生命周期,被废弃的项目代号要能标记出来——查询提到废弃术语时,检索需要能同时覆盖"它当年指什么"和"它的接替者是谁",没有状态字段就无从做起。
治理流程决定术语表能不能活过第一年。可持续的模式是"LLM 提案 + SME 审核 + 变更留痕":LLM 从新进文档里自动挖掘候选术语(高频未登录词、括号缩写展开、加粗定义句都是高置信信号),生成提案进入领域专家(SME)审核队列,批准后入库并记录来源。全自动无审核的术语表,半年内就会被抽取噪声污染到没人信;纯人工维护的术语表,则会因为维护成本被悄悄放弃。术语表是活的基础设施,它的治理成本必须设计进系统,而不是当成一次性数据工程。
候选术语挖掘的具体信号
LLM 提案之外,统计信号能为候选池提供可靠的补充。高价值的挖掘信号有四类:括号缩写展开(正则匹配"全称(缩写)""全称(英文缩写)"模式,直接给出别名对,是置信度最高的信号);加粗与定义句(Markdown 加粗术语、"是指""所谓""即"引导的定义句式);高频未登录 n-gram(领域语料的片段频次统计中,通用词表未收录、但领域内频次显著高于通用分布的片段——领域特异性打分高的进入候选);检索失败聚类的共同词(零结果查询里反复出现的词,多半是索引侧缺收录的术语)。四类信号合流进同一个审核队列,SME 的批准历史本身又是训练样本——把审核记录喂给判别模型,逐步提高自动通过比例,让治理成本随时间递减。
三个入口:索引侧、查询侧、生成侧
术语表喂给 RAG 系统有三个入口,作用机制完全不同,分别解决不同的问题:
flowchart LR
G[领域术语表<br/>规范名/别名/定义/域/状态] -->|入口一| I[索引侧<br/>别名归一 + 同义词扩展]
G -->|入口二| Q[查询侧<br/>术语检测 + 规范化扩展]
G -->|入口三| P[生成侧<br/>术语卡片注入]
I --> V[(向量 + BM25 索引)]
Q --> R[检索执行]
V --> R
R --> C[上下文组装]
P --> C
C --> L[LLM 生成<br/>术语有据可依]
索引侧:别名扩展与方向性陷阱
索引侧的做法是把术语别名写入检索引擎的同义词机制(Elasticsearch 的 synonym filter 是典型实现),入库文本经过分析器时别名与规范名建立等价关系。这里有一个必踩的坑值得专门展开:同义词的方向性。双向同义词(X 等价 Y)意味着 X 和 Y 在任何查询里互通,这对"室早 ⇄ 室性早搏"是安全的;但对多义术语是灾难——"苹果"和"苹果公司"双向等价后,水果食谱文档会因为包含"苹果"而被"苹果公司财报"查询召回,因为索引里的"苹果"已经被扩展成两个意思的并集。规则很明确:单向扩展用于上位到下位的归一(别名→规范名),双向等价只用于真正的纯别名;多义术语根本不进同义词表,改走查询侧消歧。
第二个坑是分词与位置对齐:同义词 filter 在分词之后应用,如果别名的分词结果与文档原文不一致("3C 认证"分词成"3C"和"认证"),扩展就错位失效。企业术语要作为整词进入自定义词典(IK 分词器的自定义词库等机制),先保证"术语是一个完整 token",再谈扩展。这两个坑叠加起来解释了一个常见现象:同义词配置了但线上没效果——多数时候不是配置没生效,而是术语没作为整词进词典,扩展点根本没命中。
查询侧:术语检测、规范化与歧义处理
Aho-Corasick 多模匹配与最长匹配
查询侧管线分三步。第一步术语检测:用 Aho-Corasick 自动机对查询做多模式匹配,一次扫描找出全部术语提及,最长匹配优先("企业年金"优先于"年金"命中);匹配延迟在微秒级,可以放进同步查询路径。第二步规范化与扩展:命中的别名替换成规范名,形成"原词 + 规范词"的双路查询(原词保留是给字面通道的,规范词给语义通道和过滤通道)。第三步消歧决策:多义术语按上下文判域(下一节展开),歧义无法解决时选择多路并行或澄清提问。
检测出术语之后除了扩展,还应该驱动过滤:术语带所属域信息,查询规范成规范名后可以直接给检索加域过滤器——用户问"年金",规范化成"企业年金"后,检索范围直接锁定企业年金文档集合,排序压力骤减。这比扩展词更彻底:扩展词是在排序里竞争,过滤器是直接缩小战场。
生成侧:术语卡片注入防幻觉
第三个入口最容易被漏掉,但对答案质量影响直接:检索命中的内容涉及术语时,把术语定义(术语卡片)附在上下文里。动机很朴素:模型对一个生僻术语的解释能力不可信,与其让它自由发挥,不如把库里维护的权威定义直接给它。这和 Generated Knowledge Prompting(Liu 等人 2022)的思路一致——生成前注入相关知识,比指望参数化知识更可控。术语卡片的注入格式建议是固定引导语加短定义:"【术语】室性早搏:心室提早出现的搏动,心电图表现为……",并在系统提示里要求答案引用术语含义时以卡片为准。另一个配套措施:答案中术语首次出现时自动附注(渲染层做),用户不认识缩写也不用追问一轮——这属于答案可读性的最后一公里,成本极低。
消歧:上下文判域
多义术语的消歧依据按可靠性排序有三层。第一层是邻近术语投票:查询窗口内其他已识别术语的所属域投票——"存款利率上限"里"存款"属于负债业务域,"利率"随之判到存款语境;这个特征最可靠,因为它直接来自术语表的结构化信息。第二层是用户画像先验:用户所属业务线、历史会话讨论的域分布,作为投票的平票判据或弱权重补充;注意画像先验只能做平票,不能做主判据——用户偶尔跨域提问时,画像会把整条检索带偏。第三层是显式澄清:前两层都判不出且查询本身歧义度高的场景,宁可问一句"您问的是 A 业务还是 B 业务的利率?"也不要掷硬币。消歧失败的高成本处理(检索错域 + 生成基于错误语境作答)远高于一次澄清的交互成本,这个不对称性决定了阈值应该偏向澄清。
术语表的评测:覆盖率与误伤率
术语表自己也要有指标。覆盖率:抽样真实查询,统计术语检测的命中比例(目标随领域密度定,专业库通常三到六成查询含术语);误伤率:被错误当作术语处理的普通词比例——误伤会把正常词强行扩展,直接污染查询。两个指标用人工标注一百条查询就能测出来,随版本演进定期回归。术语表是高频变更的基础设施,没有回归指标,一次糟糕的批量导入就能让检索质量无声劣化,而且排查方向会先被引向检索算法而不是数据源。
跨语言场景再加一条:中英混排的企业(文档一半中文一半英文)需要术语表的跨语言对齐——中文规范名挂英文规范名,查询"PL 的算法"能把 PL 链到英文实体再双语检索。对齐关系由 LLM 批量提案加人工抽检维护,错误对齐的伤害与错误实体链接同级,抽检比例不能省。
小结
术语层是 RAG 系统里杠杆率最高的基础设施之一:数据量小(几百到几千条)、维护成本低(LLM 提案加 SME 审核)、但对检索和生成的改善立竿见影。设计要点按三个入口展开:索引侧用别名归一打通字面通道,但必须守住方向性(纯别名才双向等价,多义术语不进同义词表)和整词进词典(先保证术语是完整 token 再扩展),这两个坑解释了大多数"同义词配了没效果"的现象;查询侧用 Aho-Corasick 做微秒级术语检测,规范化后双路检索,并让术语的域信息直接驱动过滤器缩小战场;生成侧注入术语卡片,把模型对生僻术语的自由发挥换成库里维护的权威定义。消歧用邻近术语投票、画像平票、显式澄清三层递进,阈值偏向澄清——因为检索错域的代价远高于多问一句。最后强调治理:术语表是带状态机(生效/废弃/被取代)的活基础设施,它的价值曲线取决于第一年是否有人持续维护——把治理流程设计进系统,比把术语数据灌进系统重要得多。
读者留言
COMMENTS 暂无还没有留言,来说第一句?