ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Instructor CitationMixin 引文提取与校验实战:用上下文引用杜绝 LLM 幻觉

Instructor CitationMixin 引文提取与校验实战:用上下文引用杜绝 LLM 幻觉 Instructor CitationMixin 引文提取与校验实战用上下文引用杜绝 LLM 幻觉【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor本篇技术指南深入讲解 Instructor 项目中CitationMixin的核心能力它作为一个 Pydantic mixin为你的响应模型自动注入substring_quotes字段并在模型校验阶段将 LLM 生成的引文与用户提供的源文本做模糊匹配、校正为源文本中的精确片段。读完本文你将掌握如何为提取任务、RAG 问答系统接入带引文的结构化输出确保模型产出的每一个事实都能回溯到原文从机制层面抑制幻觉。什么是 CitationMixinCitationMixin是 Instructor 内置的一个 Pydantic mixin用来为你的数据模型添加引文校验能力。当你在自定义模型上继承它之后模型会自动获得一个substring_quotes字段——该字段存放从源文本中截取的引文。mixin 会自动校验这些引文是否真实存在于源文本中并将其纠正为与原文精确匹配的片段。它的核心价值在于LLM 在生成结构化数据时常常会脑补内容而 CitationMixin 强制要求模型在输出数据的同时给出支撑该数据的原文引用并在校验阶段核验引文的真实性从而有效防止幻觉。从源码结构看CitationMixin定义在 instructor/v2/dsl/citation.py并经由 instructor/dsl/citation.py 的兼容层对外导出因此你可以在项目顶层通过from instructor import CitationMixin直接导入参见 instructor/v2/dsl/init.py 与 instructor/init.py 的导出列表。基本用法让模型输出带引文的结构化数据继承CitationMixin即可为你的模型加上引文支持from pydantic import BaseModel, Field from instructor import CitationMixin import instructor class User(CitationMixin, BaseModel): name: str Field(descriptionThe name of the person) age: int Field(descriptionThe age of the person) role: str Field(descriptionThe role of the person) client instructor.from_provider(openai/gpt-4o-mini) context Betty was a student. Jason was a student. Jason is 20 years old user client.create( response_modelUser, messages[ { role: user, content: fExtract information about Jason from: {context}, }, ], context{context: context}, ) # Verify quotes exist in context for quote in user.substring_quotes: assert quote in context print(user.model_dump()) # { # name: Jason, # age: 20, # role: student, # substring_quotes: [ # Jason was a student, # Jason is 20 years old, # ] # }几个值得注意的细节substring_quotes字段的官方描述是 List of unique and specific substrings of the quote that was used to answer the question.用于回答问题的、独特且具体的引文子串列表定义见 instructor/v2/dsl/citation.py。提示词中应引导 LLM 给出足够长、足够具体的原文片段以便后续核验。源文本通过context{context: context}传入client.create()这一步触发了引文校验逻辑详见下文验证上下文传递一节。从源码看from_provider(openai/gpt-4o-mini)会基于当前模型自动选择匹配的 provider 与模式你也可以沿用instructor.from_openai(...)等既有方式创建客户端参见 examples/citation_with_extraction/citation_fuzzy_match.py 中的等价写法。它是如何工作的三步机制与源码解析CitationMixin 的引文校验分为三个步骤提取ExtractionLLM 在生成结构化数据的同时将支撑性引文写入substring_quotes字段校验Validationmixin 用模糊匹配检查每条引文是否能在源文本中找到纠正Correction将引文替换为源文本中的精确片段即按匹配到的起止 span 切片原文。当你在create()调用中传入context{context: source_text}时上述校验会自动发生。底层实现位于 instructor/v2/dsl/citation.py 的validate_sources方法它是一个model_validator(modeafter)校验器model_validator(modeafter) def validate_sources(self, info: ValidationInfo) - CitationMixin: if info.context is None: return self # Get the context from the info text_chunks info.context.get(context, None) if text_chunks is None: return self # Get the spans of the substring_phrase in the context spans list(self.get_spans(text_chunks)) # Replace the substring_phrase with the actual substring self.substring_quotes [text_chunks[span[0] : span[1]] for span in spans] return self这段代码揭示了几个重要的工程行为上下文缺失时安全降级如果调用时未传入contextinfo.context is None或传入的 context 字典中没有context键mixin 会直接返回self保留 LLM 输出的原始引文而不做任何修改。这意味着引文校验是可选增强不会因配置缺失而让整个调用失败。对应的测试 tests/v2/test_citation.py 中test_no_context_leaves_quotes_untouched明确验证了这一点。span 切片纠正校验的核心动作是用匹配到的起止位置对源文本做切片text_chunks[span[0]:span[1]]从而把模型给出的、可能略有偏差的引文拉回到与源文本完全一致的原文。无匹配则删除如果某条引文在源文本中完全找不到get_spans不会为它产出 span最终它会被从substring_quotes中移除见测试test_non_matching_quote_is_dropped。验证上下文的传递context 参数的两种用法CitationMixin 依赖 Pydantic 的**验证上下文validation context**机制来获取源文本。传入方式是create()方法中的context参数但键名需要与校验器读取的保持一致。在 v2 的CitationMixin实现中校验器读取的是info.context.get(context, None)因此标准写法是context{context: source_text}这一点与原文档 docs/concepts/citation.md 中所有示例的用法一致。注意如果你参考的是仓库里更早期的示例如 examples/citation_with_extraction/citation_fuzzy_match.py那里使用的是validation_context{text_chunk: context}并且校验器读取info.context.get(text_chunk, None)——这是自定义校验器的写法与内置CitationMixin的键名不同两者不要混用。client.create()的context参数会透传给 Pydantic 的ValidationInfo因此任何model_validator或字段级校验器都能通过info.context读取它。这种机制同样服务于 reask_validation.md 中介绍的基于上下文的动态校验场景——引文校验正是这一能力最有代表性的应用。模糊匹配容忍小差异拒绝大偏差引文校验的关键难点在于LLM 输出引文时往往不会与原文逐字一致可能存在多余空格、轻微措辞变化或标点差异。CitationMixin 使用**模糊匹配fuzzy matching**来处理这类问题。其实现位于 instructor/v2/dsl/citation.py 的_get_span方法def _get_span( self, quote: str, context: str, errs: int 5 ) - Generator[tuple[int, int], None, None]: import regex # Escape the quote so regex metacharacters in LLM-generated text # (e.g. unbalanced parentheses or brackets) are matched literally # instead of crashing the fuzzy search with a regex compile error. minor regex.escape(quote) major context errs_ 0 s regex.search(f({minor}){{e{errs_}}}, major) while s is None and errs_ errs: errs_ 1 s regex.search(f({minor}){{e{errs_}}}, major) if s is not None: yield from s.spans()关键点有三默认容错 5 个字符错误errs: int 5是默认参数匹配从 0 个错误开始逐步放宽最多允许 5 次编辑错误errs_从 0 递增到 5。这能覆盖 LLM 轻微的改写但对大幅偏离原文的内容依然会判为不匹配。正则元字符转义LLM 生成的引文可能包含不平衡的括号、方括号、量词或反斜杠等正则元字符。在把引文拼进模糊匹配模式前先用regex.escape(quote)转义确保这些字符被按字面匹配而不是导致正则编译崩溃。测试 tests/v2/test_citation.py 的test_quote_with_regex_metacharacters_does_not_crash与test_various_metacharacter_quotes_resolve覆盖了50% (approx、cost [USD]、ab*c、path\\to\\file、who? (maybe)等场景。转义不影响模糊能力转义只改变正则语义字面匹配并不会关闭编辑距离容错——测试test_fuzzy_matching_still_works_after_escaping验证了50% (aprox)能匹配到50% (approx)test_quote_within_error_tolerance_matches与test_quote_beyond_error_tolerance_is_dropped则从正反两面确认了 5 字符容错边界。模糊匹配使用regex库注意不是标准库re通过{eN}的近似匹配语法控制允许的错误数这也是该方法需要延迟import regex的原因。进阶示例带精确引文的问答系统将CitationMixin与嵌套模型结合可以构建每个事实都带出处的问答系统——这也是原文档演示的典型用法。下面示例来自 docs/concepts/citation.mdfrom typing import List from pydantic import BaseModel, Field from instructor import CitationMixin import instructor class Fact(CitationMixin, BaseModel): statement: str Field(descriptionA factual statement) class Answer(CitationMixin, BaseModel): question: str facts: List[Fact] Field(descriptionList of facts that answer the question) client instructor.from_provider(openai/gpt-4o-mini) source_text Jason Liu grew up in Toronto, Canada but was born in China. He went to an arts high school but studied Computational Mathematics and Physics in university. He worked at Stitchfix and Facebook as part of coop programs. He started the Data Science club at the University of Waterloo and was president for 2 years. answer client.create( response_modelAnswer, messages[ { role: system, content: Answer questions with exact citations from the source text., }, { role: user, content: fSource: {source_text}\n\nQuestion: What did Jason do during college?, }, ], context{context: source_text}, ) # Verify all citations exist for fact in answer.facts: for quote in fact.substring_quotes: assert quote in source_text print(fVerified: {quote})这一模式的关键在于递归校验Answer本身继承CitationMixin而它内部的每个Fact也继承CitationMixin因此嵌套模型中的每一层都会独立执行引文校验形成一个自底向上的引文核验树。如果你的诉求是更细粒度地控制例如自定义无引文即剔除该事实的过滤逻辑可以参考 docs/examples/exact_citations.md 与 examples/citation_with_extraction/citation_fuzzy_match.py 中的手动写法用model_validator(modeafter)自己实现get_spans/_get_span并用QuestionAnswer级别的校验器把没有任何引文支撑的Fact从答案列表中移除。该示例还展示了如何结合 loguru 输出Found 1 span(s) for from 1 citation(s).之类的调试日志便于观察每条引文的匹配情况。何时使用 CitationMixin适合使用它的典型场景需要核验提取的信息确实来自源文本例如从合同、报告、新闻中抽取结构化字段时要求每条字段都有原文支撑构建 RAG检索增强生成系统检索到的文档片段作为context传入模型输出必须引用这些片段形成检索—生成—核验的闭环需要预防幻觉通过强制引文存在性校验把无中生有的内容挡在输出之外需要精确引文片段用于高亮或展示由于引文会被纠正为源文本的精确 span你可以直接用它们做原文高亮、脚注或来源标记。已知限制使用CitationMixin时需要注意以下边界必须显式传入源文本校验依赖context{context: ...}参数若未传入引文将原样保留、不做任何校验安全降级而非报错模糊匹配不能覆盖所有改写默认 5 字符错误容错对轻微偏差有效但大幅改写、同义替换或长句重组仍可能漏检或误判只校验引文、不校验事实mixin 保证引文存在于原文但无法保证事实判断正确——模型仍可能从原文中摘出与问题无关或结论错误的片段。相关资源Validation —— Instructor 中的模型校验机制概览Context-Based Validation —— 基于验证上下文的动态校验引文校验正是其典型应用Citation Examples —— 更完整的自定义引文校验示例含正则 span 定位与无效事实过滤RAG Patterns —— 使用 Instructor 构建 RAG 系统的模式探讨源码实现instructor/v2/dsl/citation.py、兼容导出层 instructor/dsl/citation.py单元测试tests/v2/test_citation.py —— 覆盖正则元字符转义、模糊匹配容错、无上下文降级等关键行为【免费下载链接】instructorstructured outputs for llms项目地址: https://gitcode.com/GitHub_Trending/in/instructor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表