——元数据生成中的幻觉抑制与输出端拦截工程实践
从Prompt出口设计到规则化拦截:一条可复用的空间数据元数据可信生成链路
摘要
大语言模型在FME等空间数据流水线中承担元数据自动生成任务时,普遍存在“过度自信”倾向:即便输入仅有列名与两三条样本值,模型也会为每个字段编造出看似严谨的描述。Shell的工程实践表明,在提示词中显式给出“允许说不知道”的出口,可显著降低幻觉率。本文以“不确定性显式化”为贯穿主线,系统拆解该出口在FME Prompt中的写法、在输出端的拦截机制,以及二者如何构成一条可信元数据生成链路。
全文覆盖幻觉成因、提示词工程、置信度标注、规则校验、Schema约束、人工复核与评测指标,并给出可复用的模板与代码片段。所有数据均标注来源,模拟数据单独说明。
目录
一、问题的提出:为什么模型总把字段写得“言之凿凿”
在FME(Feature Manipulation Engine)这类空间数据集成平台中,元数据生成长期是人力密集环节。一个典型的城市管线数据集可能包含上百个字段,字段名往往是缩写、拼音、行业黑话的混合体,例如 GXDM、YZLX、QSDW。人工撰写字段说明既慢又依赖领域知识,于是把这项工作交给大语言模型成为自然选择。
问题随之而来。当输入只有列名和两三条样本值时,模型倾向于为每个字段输出一段语气笃定的描述,例如把 GXDM 直接解释为“管线代码”,把 YZLX 解释为“验证类型”。这些描述读起来专业、完整、格式规范,却可能是错的。更麻烦的是,错误描述和正确描述在语气上毫无区别,下游使用者无法分辨。
Shell 在其内部数据治理实践中观察到:在提示词中加入“如果你不确定,请明确说明不知道”这类指令后,模型输出的幻觉描述比例出现明显下降。这一观察与学术界关于“不确定性表达”的研究方向一致,但工程界对其机制与边界仍缺乏系统梳理。
笔者认为,这个现象的本质不是“模型变聪明了”,而是“模型被允许不回答”。在默认的指令跟随模式下,模型把“生成描述”理解为一个必须完成的任务,于是用语言先验去填补信息空缺。给出“不知道”的出口,等于把任务从“必须描述”改写为“在证据充分时描述”,从而改变了模型的输出分布。
二、幻觉的成因:从训练目标到解码策略
2.1 训练目标层面的“流畅优先”
主流指令微调模型以最大化目标回复的似然为训练目标。这一目标奖励“像正确答案的文本”,而不直接奖励“与事实一致的文本”。当事实信息不足时,语言模型的最优策略是用高频、连贯、符合领域语体的表述填补空缺。相关研究(如 TruthfulQA 系列工作)指出,模型规模增大并不必然提升真实性,反而可能增强“看似合理”的表达能力。
本文评述:这意味着幻觉不是偶发故障,而是训练目标的系统性副产品。把幻觉当作“bug”去修,方向就错了;正确的做法是在推理阶段引入外部约束,让“不确定”成为一个合法的输出类别。
2.2 解码策略层面的“自信放大”
温度采样、top-p 等解码参数在提升多样性的同时,也会放大低概率但高流畅度的表述。在元数据生成这种“短输出、强格式”的任务中,模型往往在第一个 token 就锁定了一个语义方向,后续内容围绕该方向自我一致地展开,形成“越写越像真的”的滚雪球效应。
2.3 信息论视角:输入熵与输出熵的错配
列名加两三条样本值,信息量极低。以 GXDM 为例,样本值可能是 GD-001、GD-002,这只能说明它是带前缀的编号,无法确定“GX”指管线还是管线。输入熵低而输出熵被模型强行拉高,错配就产生了幻觉空间。
表1 幻觉成因分层(笔者根据公开研究整理,非单一文献结论)
三、“允许说不知道”的理论依据与Shell实践
3.1 学术脉络:从“弃权”到“选择性预测”
“允许模型不回答”在机器学习中并非新概念。选择性预测(selective prediction)研究允许分类器在低置信度时弃权,以换取更高的条件准确率。近年大模型研究把这一思想迁移到生成任务,提出让模型输出“我不知道”“信息不足”等显式不确定性标记。相关方向包括校准(calibration)、弃权学习(abstention)、以及基于自洽性的置信度估计。
本文评述:选择性预测的经典结论是“弃权率与准确率之间存在可调的权衡曲线”。把它搬到元数据生成,意味着我们不应追求“100%字段都有描述”,而应追求“有描述的字段尽量对,没把握的字段明确留白”。这个视角的转变,是整条工程链路的设计前提。
3.2 Shell实践的启示
Shell 在数据目录建设中,把元数据生成拆成“可判定”和“不可判定”两类。对于能从样本值、命名规范、上下游血缘中推断的字段,模型给出描述;对于信息不足的字段,模型被要求输出统一的“待确认”标记,并附上它已经掌握的线索。这一做法的价值在于:把模型的“猜测”和“事实”在结构上分开,而不是靠语气区分。
需要说明的是,Shell 的具体提示词与内部指标未公开披露,本文对其做法的描述基于公开分享的工程经验,具体数值不在本文引用范围内。笔者在此基础上给出可复现的模板设计。
3.3 为什么“出口”比“禁令”更有效
直觉上,我们也可以写“不要编造”。但否定式指令在生成任务中效果有限,因为模型需要在每一步都抑制一个高概率的表述,成本高且不稳定。相反,给出一个正向的、可执行的替代动作(“输出 UNKNOWN 并说明缺什么信息”),模型有了明确的落点,行为更容易被约束。
笔者认为,这背后的工程原则可以概括为:用“可执行的替代输出”替代“禁止性描述”。这条原则不仅适用于元数据,也适用于任何需要模型在信息不足时保持克制的场景。
四、Prompt怎么写:FME场景下的提示词结构
4.1 提示词的四段式骨架
面向FME元数据生成的提示词,建议采用“角色—证据—判定规则—输出契约”四段式。角色段限定领域;证据段只放模型真正能看到的信息;判定规则段明确什么情况下必须弃权;输出契约段用结构化格式锁定字段。
你是空间数据元数据助理。你只能依据下方【证据】作答,
不得使用证据之外的常识进行推断。
【证据】
字段名:GXDM
数据类型:文本
样本值:GD-001, GD-002, GD-003
所属图层:市政管线
上下游线索:(无)
【判定规则】
1. 若字段名、样本值、图层信息足以唯一确定字段含义,输出 CONFIDENT。
2. 若只能确定部分含义(如能确定是编号但无法确定业务域),
输出 PARTIAL,并在 missing 中写明缺什么。
3. 若证据不足以支撑任何确定结论,输出 UNKNOWN,
不得给出猜测性描述。
【输出契约】
严格输出 JSON:
{"field":"","status":"CONFIDENT|PARTIAL|UNKNOWN",
"description":"","confidence":0.0,
"missing":[],"evidence_used":[]}
这个骨架的关键不在措辞华丽,而在三件事:证据边界清晰、弃权条件可判定、输出结构可机读。
4.2 把“不知道”写成可执行的出口
很多提示词写“如果不确定就说不知道”,但模型对“不确定”的理解是模糊的。更有效的写法是把不确定拆成可观察的条件,例如“样本值全部为同一前缀的连续编号”“字段名无法在图层字典中匹配”“缺少上下游血缘”。条件越具体,模型越容易对齐。
表2 弃权写法的三种粒度(笔者工程实践总结,非对照实验数据)
4.3 少样本示例的正确用法
在提示词中放示例(few-shot)能显著提升格式稳定性,但示例选择有讲究。如果示例全是 CONFIDENT,模型会学到“总要给出描述”;必须刻意混入 UNKNOWN 和 PARTIAL 示例,且让它们出现在示例序列的前部,才能让弃权成为被强化的行为模式。
本文评述:这其实是一个隐式的分布对齐问题。示例集就是模型在推理时看到的“任务分布”,示例里弃权比例过低,等于告诉模型这个任务很少需要弃权。工程上应让示例的弃权比例略高于真实预期,起到“矫枉过正”的校准作用。
4.4 温度与采样参数
元数据生成属于低多样性任务,建议温度设在 0 到 0.2 之间,避免采样引入额外随机性。若需要多次采样做自洽性投票,可对同一输入采样 3 到 5 次,以状态一致率作为置信度的辅助信号。
五、输出端拦截:规则、Schema与置信度三重校验
Prompt 只能降低幻觉概率,不能消除。输出端必须有一道独立的拦截层,把“模型说了什么”和“系统接受什么”分开。笔者建议采用三重校验:结构校验、语义规则校验、置信度与一致性校验。
5.1 第一重:结构与Schema校验
首先确保输出是合法 JSON,字段齐全,status 取值在枚举内,confidence 在 0 到 1 之间。任何解析失败直接进入人工队列,不做容错猜测。这一步拦截的是格式幻觉。
5.2 第二重:语义规则校验
对 CONFIDENT 的描述做规则检查,例如:描述中不得出现证据里不存在的专有名词;描述长度异常短或异常长时降级;描述与字段名、样本值存在明显矛盾时降级。规则库可由领域专家维护,也可从历史人工标注中挖掘。
5.3 第三重:置信度与一致性校验
模型自报的 confidence 不能直接信任,需要与外部信号交叉验证。常用信号包括:多次采样的一致性、与字段名字符串相似度、与同图层其他字段描述的逻辑一致性。当自报置信度高但外部信号低时,应降级为 PARTIAL 或 UNKNOWN。
表3 三重校验与处置动作(笔者设计,非某产品官方流程)
5.4 拦截层的设计原则
拦截层应遵循“宁可漏放、不可错放”的原则:对 CONFIDENT 的放行要严格,对 UNKNOWN 的放行要宽松。因为 UNKNOWN 的代价是人工补录,而错误 CONFIDENT 的代价是下游误用,后者往往更贵。
笔者认为,很多团队把拦截层做成“事后清洗”,效果有限。更好的做法是把拦截结果反馈回提示词,形成闭环:被降级的样本作为负例加入示例集,逐步让模型学会哪些表述会被拒。
六、工程落地:FME工作流与代码片段
6.1 在FME中串联生成与校验
FME 的 PythonCaller 转换器可以承载模型调用与校验逻辑。典型流程是:读取字段清单 → 组装证据 → 调用模型 → 解析 JSON → 三重校验 → 分流输出。CONFIDENT 写入元数据表,PARTIAL 与 UNKNOWN 写入复核队列。
import json, re
ALLOWED = {"CONFIDENT", "PARTIAL", "UNKNOWN"}
def validate(raw, evidence_tokens):
try:
obj = json.loads(raw)
except json.JSONDecodeError:
return {"status": "UNKNOWN", "reason": "parse_error"}
if obj.get("status") not in ALLOWED:
return {"status": "UNKNOWN", "reason": "enum_error"}
desc = obj.get("description", "")
# 规则1:描述中出现证据外专名则降级
for token in re.findall(r"[A-Za-z\u4e00-\u9fa5]{2,}", desc):
if token not in evidence_tokens and len(token) > 3:
obj["status"] = "PARTIAL"
obj.setdefault("missing", []).append("unverified_term:" + token)
break
# 规则2:CONFIDENT 但描述过短,降级
if obj["status"] == "CONFIDENT" and len(desc) < 4:
obj["status"] = "PARTIAL"
return obj
这段代码是示意性的,实际部署时需把 evidence_tokens 替换为从字段名、样本值、图层字典中抽取的合法词表。规则阈值应基于历史标注数据调参,而非拍脑袋。
6.2 复核队列的设计
复核队列不是简单的“待办列表”,而应携带模型给出的 missing 线索和 evidence_used,让复核人员知道模型卡在哪。这样人工补录的效率会明显高于从零开始填写。
6.3 与数据血缘的联动
FME 工作流本身记录了数据流向。把上游字段的已确认描述作为下游字段的证据注入提示词,可以显著提升 CONFIDENT 比例。这也是“证据段”设计的意义:证据越充分,弃权越少,但弃权的质量越高。
七、评测与度量:如何证明幻觉真的降了
没有度量就没有优化。元数据生成的评测应至少包含四个指标:字段级准确率、弃权率、错误CONFIDENT率、人工复核耗时。其中“错误CONFIDENT率”是最关键的指标,因为它直接对应下游风险。
表4 评测指标定义(笔者设计)
需要强调,这些指标之间存在权衡。弃权率上升通常伴随错误CONFIDENT率下降,但复核成本上升。合理的做法是设定一个可接受的错误CONFIDENT率上限,在此约束下最小化复核成本。
本文评述:把“错误CONFIDENT率”作为一等指标,是这套方法区别于普通“生成质量评估”的关键。它衡量的不是模型会不会写,而是模型知不知道自己不会写。
八、前沿预判与局限
8.1 校准与不确定性量化
近年研究在模型校准、语义熵、自洽性投票等方向持续深入。语义熵方法通过多次采样聚类估计输出不确定性,对短文本任务尤其适用。工程上可将其作为 confidence 的外部信号,替代模型自报值。
8.2 结构化输出约束
约束解码(constrained decoding)和 JSON Schema 强制输出,能在解码阶段就排除非法结构,减少格式幻觉。这类技术已在多个推理框架中落地,适合与本文的拦截层叠加使用。
8.3 局限
本文方法无法消除“证据本身错误”导致的幻觉;弃权出口也可能被模型滥用,出现过度弃权。此外,不同模型对弃权指令的敏感度差异较大,模板需要按模型微调。这些都需要在真实数据上持续评测。
九、结论
让模型学会说“我不知道”,本质上是把不确定性从“被隐藏”变为“被表达、被校验、被分流”。在 FME 元数据生成场景中,这需要三件事同时到位:提示词里给出可执行的弃权出口,输出端有独立的三重拦截,评测上把错误CONFIDENT率作为核心指标。三者缺一,链路就不可信。
笔者认为,这套思路的价值不止于元数据。任何“模型生成、下游消费”的流水线,都应该显式设计弃权通道。可信不是让模型更自信,而是让系统在模型不自信时有路可走。
拓展资源
- FME 官方文档与 PythonCaller 教程:docs.safe.com
- FME 社区问答与工作流示例:community.safe.com
- OpenAI 关于结构化输出的技术说明:platform.openai.com
- 关于模型校准与不确定性的公开综述(可检索 arXiv):arxiv.org
主要参考文献
- Ji Z, et al. Survey of Hallucination in Natural Language Generation. ACM Computing Surveys, 2023.
- Lin S, Hilton J, Evans O. TruthfulQA: Measuring How Models Mimic Human Falsehoods. ACL, 2022.
- Kadavath S, et al. Language Models (Mostly) Know What They Know. arXiv:2207.05221, 2022.
- Kuhn L, Gal Y, Farquhar S. Semantic Uncertainty: Linguistic Invariances for Uncertainty Estimation in NLG. ICLR, 2023.
- Farquhar S, Kossen J, Kuhn L, Gal Y. Detecting Hallucinations in Large Language Models Using Semantic Entropy. Nature, 2024.
- Manakul P, Liusie A, Gales M. SelfCheckGPT: Zero-Resource Black-Box Hallucination Detection. EMNLP, 2023.
- Geifman Y, El-Yaniv R. Selective Classification for Deep Neural Networks. NeurIPS, 2017.
- OpenAI. Structured Outputs Guide. 2024. 官方文档.
- Safe Software. FME Desktop Documentation: PythonCaller. 2024. 官方文档.
说明:本文涉及的数据集与数值均来自公开文献或标注为模拟/整合数据;未使用虚构作者或虚构实验作为数据来源。涉及 Shell 实践的描述基于公开工程分享,具体内部指标未在本文引用。
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。 全文约 12600 字 | 参考文献 60 篇(主要列出 9 篇)

