资讯详情

资讯详情

LangChain SelfQueryRetriever:让模型自己写过滤条件

个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录LangChain SelfQueryRetriever让模型自己写过滤条件一、问题长什么样二、上手三、metadata 描述怎么写最重要3.1 description 的三个要点3.2 字段名必须和 metadata 一致四、支持的查询类型五、看看它生成了什么调试必备六、向量库的支持程度七、成本与延迟八、什么时候用九、常见坑十、小结LangChain SelfQueryRetriever让模型自己写过滤条件用户问2024 年技术部发布的制度有哪些——这句话里既有语义制度又有结构化条件year2024, dept技术部。纯向量检索会把2024技术部也当成语义去匹配效果很差。SelfQueryRetriever 让模型先把这句话拆成语义查询 过滤条件再分别执行。一、问题长什么样先看纯向量检索的失败案例vectorstore.similarity_search(2024 年技术部发布的制度,k4)问题在于2024“技术部这些词在向量空间里和制度”流程很近结果召回了2022 年的制度因为都是制度市场部的文件因为都提到部门2024 年的预算表因为都有2024。用户要的且关系向量检索做不到。正确做法是把它拆成语义查询交给向量制度 流程规范 过滤条件交给数据库year 2024 AND dept 技术部SelfQueryRetriever 就是自动做这个拆分的。二、上手fromlangchain.chains.query_constructor.baseimportAttributeInfofromlangchain.retrievers.self_query.baseimportSelfQueryRetrieverfromlangchain_openaiimportChatOpenAI# 1. 声明 metadata 字段关键metadata_field_info[AttributeInfo(nameyear,description文档发布年份整数如 2022 / 2023 / 2024,typeinteger,),AttributeInfo(namedept,description发布部门如 技术部 / 市场部 / 人力资源部,typestring,),AttributeInfo(namedoc_type,description文档类型制度 / 通知 / 手册,typestring,),]document_content_description公司内部制度与通知文档llmChatOpenAI(modelgpt-4o-mini,temperature0)retrieverSelfQueryRetriever.from_llm(llm,vectorstore,document_content_description,metadata_field_info,enable_limitTrue,# 支持前 N 条这类表达)resultsretriever.invoke(2024 年技术部发布的制度有哪些)模型内部会生成类似这样的结构化查询query制度 流程规范 filterAND(eq(year, 2024), eq(dept, 技术部)) limitNone然后向量库先按 filter 过滤再在结果里做语义检索。三、metadata 描述怎么写最重要这一步决定了 SelfQuery 能不能用对。AttributeInfo的三个字段都要认真写AttributeInfo(nameyear,# 必须和 metadata 里的 key 完全一致description...,# 给模型看的说明typeinteger,# string / integer / float / boolean)3.1 description 的三个要点① 说清楚取值范围# ❌ 太模糊description部门# ✅ 枚举出来description发布部门。可选值技术部、市场部、人力资源部、财务部LLM 不知道你的部门有哪些你不告诉它它只能猜猜错就过滤出空结果。② 说清楚类型和格式AttributeInfo(nameyear,description发布年份,typeinteger)# ✅ 明确是整数模型才会生成 eq(year, 2024) 而不是 eq(year, 2024年)③ 说清楚这个字段的用途AttributeInfo(nameis_active,description该制度是否仍然有效。true现行有效false已废止。当用户问现行有效最新时应过滤 true,typeboolean,)把用户说什么话时该用这个字段写进描述模型判断会更准。3.2 字段名必须和 metadata 一致# 入库时Document(page_content...,metadata{publish_year:2024})# 声明时AttributeInfo(namepublish_year,...)# ✅ 必须叫 publish_yearAttributeInfo(nameyear,...)# ❌ 对不上过滤失效这是最常见的低级错误而且不会报错只是过滤没生效很难发现。四、支持的查询类型SelfQuery 能生成的过滤器不止等于类型例子等于eq(dept, 技术部)不等于ne(dept, 技术部)大于/小于gt(year, 2023)、lt(amount, 1000)大于等于/小于等于gte(year, 2023)介于gte(year, 2022) AND lte(year, 2024)包含in([制度, 通知])且/或AND(...)、OR(...)对应的自然语言用户说生成的过滤“2024 年的”eq(year, 2024)“2023 年之后的”gt(year, 2023)“2022 到 2024 年的”gte(year, 2022) AND lte(year, 2024)“技术部和市场部的”in([技术部, 市场部])“不是技术部的”ne(dept, 技术部)五、看看它生成了什么调试必备fromlangchain.chains.query_constructor.baseimport(StructuredQueryOutputParser,get_query_constructor_prompt,)promptget_query_constructor_prompt(document_content_description,metadata_field_info,)output_parserStructuredQueryOutputParser.from_components()query_constructorprompt|llm|output_parser resultquery_constructor.invoke({query:2024 年技术部的制度})print(语义:,result.query)print(过滤:,result.filter)print(限制:,result.limit)调试 SelfQuery 一定要先看这一步的输出——如果过滤条件生成错了后面再怎么调都没用问题一定出在AttributeInfo的描述上。六、向量库的支持程度不是所有向量库都支持 SelfQuery。它需要一个StructuredQuery翻译器。向量库支持备注Chroma✅开箱可用PGVector✅生产推荐Elasticsearch✅过滤器能力强Pinecone / Weaviate / Qdrant✅各有 translatorFAISS❌不支持原生无 metadata 过滤如果用 FAISSSelfQuery 用不了——这是很多人踩的坑。要么换 Chroma/PGVector要么自己在检索后手动过滤defmanual_filter(query:str,filters:dict,k4):docsvectorstore.similarity_search(query,kk*10)out[]fordindocs:ifall(d.metadata.get(key)valforkey,valinfilters.items()):out.append(d)iflen(out)k:breakreturnout七、成本与延迟SelfQuery每次检索都要多一次 LLM 调用生成结构化查询。方案额外成本额外延迟普通向量检索——SelfQuery1 次 LLM 调用0.5~1.5 秒优化办法缓存结构化查询。fromfunctoolsimportlru_cachelru_cache(maxsize200)defparse_query(question:str):returnquery_constructor.invoke({query:question})相似问题会命中缓存省掉这次调用。八、什么时候用场景用不用文档有明确的 metadata年份、部门、类型、状态强烈推荐用户提问经常带限定词“2024 年的”“技术部的”强烈推荐metadata 只有 source 一个字段没必要用户提问都很模糊收益有限用 FAISS用不了前提条件你的 metadata 得有价值。如果入库时只存了sourceSelfQuery 无从发挥——回到前面讲过的那句metadata 要在加载阶段就埋好。九、常见坑现象原因解法过滤没生效字段名和 metadata 不一致逐个核对过滤出空结果描述里没说取值范围模型猜错枚举可选值年份比较出错type 写成 string改typeintegerFAISS 报错不支持结构化查询换 Chroma/PGVector每次都很慢多了 LLM 调用缓存结构化查询模型不用过滤描述太简单说明用户说什么时该用它十、小结SelfQuery 解决语义 结构化条件的混合查询纯向量检索做不好2024 年技术部这类且关系核心是AttributeInfo字段名要和 metadata 完全一致描述要枚举取值范围、说清类型、说明什么时候用支持 eq / ne / gt / lt / gte / lte / in / AND / OR调试时先打印生成的结构化查询问题多半在描述上⚠️FAISS 不支持无原生 metadata 过滤要用就换 Chroma 或 PGVector每次检索多一次 LLM 调用用缓存省掉重复解析。下一篇讲时间加权检索——让最近的记忆更容易被想起。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →