尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
LangChain MultiVectorRetriever:一个文档存多个向量
个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录LangChain MultiVectorRetriever一个文档存多个向量一、核心思路二、用法一小块检索返回大块三、用法二用摘要做向量四、用法三用假设问题做向量强烈推荐五、用法四混合多种表示六、持久化别用 InMemoryStore七、什么时候用它什么时候用 ParentDocument八、常见坑九、小结LangChain MultiVectorRetriever一个文档存多个向量切分有个绕不开的矛盾小块检索准但缺上下文大块上下文全但检索不准。父子文档检索前面讲过是一种解法MultiVectorRetriever 是另一种更灵活的——同一个文档存多种向量表示。这篇讲它的四种用法以及什么时候它比父子文档更合适。一、核心思路传统做法一个 chunk → 一个向量。MultiVector 的做法一个文档 → 多个向量都指向它。原始文档 D完整内容存在 docstore ↑ ↑ ↑ 向量1 向量2 向量3 摘要 子块A 假设问题检索时用任意一种向量去匹配命中哪个都算数但返回的始终是原始文档 D的完整内容。这就同时拿到了精准匹配和完整上下文。二、用法一小块检索返回大块这是最常用、也最直观的一种。fromlangchain.retrievers.multi_vectorimportMultiVectorRetrieverfromlangchain_community.vectorstoresimportChromafromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain.storageimportInMemoryStorefromlangchain_core.documentsimportDocumentimportuuid# 原始文档docs[Document(page_content第三章 差旅报销……2000 字的完整章节,metadata{source:handbook.md,chapter:3}),]# 1. 给每个文档分配 iddoc_ids[str(uuid.uuid4())for_indocs]# 2. 把每个文档切成小块这些小块用来做向量child_splitterRecursiveCharacterTextSplitter(chunk_size200)sub_docs[]fori,docinenumerate(docs):forchunkinchild_splitter.split_text(doc.page_content):sub_docs.append(Document(page_contentchunk,metadata{doc_id:doc_ids[i]},# 关键指回父文档))# 3. 向量库存小块vectorstoreChroma(collection_namemulti,embedding_functionOpenAIEmbeddings())vectorstore.add_documents(sub_docs)# 4. docstore 存完整文档storeInMemoryStore()store.mset([(doc_ids[i],docs[i])foriinrange(len(docs))])# 5. 组装retrieverMultiVectorRetriever(vectorstorevectorstore,docstorestore,id_keydoc_id,)resultsretriever.invoke(住宿费标准上浮条件是什么)print(len(results[0].page_content))# 完整的 2000 字章节和 ParentDocumentRetriever 的区别ParentDocumentRetrieverMultiVectorRetriever父子关系自动维护手动用 id 关联每个父文档的向量一组同粒度子块可以是多组、不同粒度/不同表示去重自动默认不去重可能返回重复所以要手动去重defdedup(docs):seen,outset(),[]fordindocs:keyd.metadata.get(doc_id)ord.page_content[:80]ifkeynotinseen:seen.add(key)out.append(d)returnout resultsdedup(retriever.invoke(问题))三、用法二用摘要做向量有些文档很长很啰嗦直接用原文向量化效果不好。先让 LLM 生成一段摘要用摘要做向量。fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParser summary_chain(ChatPromptTemplate.from_template(用 100 字概括下面文档的核心内容\n{doc})|ChatOpenAI(modelgpt-4o-mini,temperature0)|StrOutputParser())summariessummary_chain.batch([{doc:d.page_content}fordindocs],config{max_concurrency:5})summary_docs[Document(page_contents,metadata{doc_id:doc_ids[i]})fori,sinenumerate(summaries)]vectorstore.add_documents(summary_docs)为什么有用摘要去掉了细节噪声向量更能代表这篇文档在讲什么。对于这篇文档是讲什么的这类宽泛提问效果特别好。代价建索引时要对每篇文档调一次 LLM。1000 篇文档就是 1000 次调用——用便宜模型批量跑。四、用法三用假设问题做向量强烈推荐这是我最喜欢的一种。思路是让 LLM 反过来生成这篇文档能回答哪些问题用这些问题做向量。QUESTION_PROMPTChatPromptTemplate.from_template( 下面是文档的一段内容。请生成 3 个「这段内容能够回答的问题」。 要求问题要具体、用词接近真实用户的提问方式。每行一个不要编号。 文档内容 {doc} )question_chain(QUESTION_PROMPT|ChatOpenAI(modelgpt-4o-mini,temperature0)|StrOutputParser())defbuild_question_vectors(docs,doc_ids):out[]fori,docinenumerate(docs):rawquestion_chain.invoke({doc:doc.page_content[:2000]})forqinraw.strip().split(\n):qq.strip(- ).strip()ifq:out.append(Document(page_contentq,metadata{doc_id:doc_ids[i]}))returnout question_docsbuild_question_vectors(docs,doc_ids)vectorstore.add_documents(question_docs)为什么效果好因为检索本质是用问题匹配文档但问题和文档的表述方式天然不同——用户问咋报销文档写费用报销流程。用假设问题做向量后检索变成了用户问题 vs 假设问题的匹配两边都是问题表述空间一致了匹配准确率明显提升。这在 FAQ、制度文档、产品手册上效果非常显著。五、用法四混合多种表示最强的做法是几种向量都存让它们互相补# 1. 小块向量针对细节问题vectorstore.add_documents(sub_docs)# 2. 摘要向量针对宽泛问题vectorstore.add_documents(summary_docs)# 3. 假设问题向量针对口语化提问vectorstore.add_documents(question_docs)三者指向同一个doc_id任何一路命中都会返回完整原文。代价是向量库体积变成 3 倍。我的建议排序预算选哪种只能选一种假设问题提升最明显能选两种假设问题 小块不差钱三种全上六、持久化别用 InMemoryStore和父子文档那篇一样InMemoryStore重启就丢会导致命中了向量却取不到原文。fromlangchain_community.storageimportRedisStore storeRedisStore(redis_urlredis://localhost:6379)# 或自己实现基于数据库/文件的 BaseStore七、什么时候用它什么时候用 ParentDocument场景推荐只需小块检索 大块返回ParentDocumentRetriever代码少自动去重想用摘要/假设问题做向量MultiVectorRetriever想同时存多种表示MultiVectorRetriever文档很短、不需要切分MultiVector直接存原文 假设问题一句话要多种表示就用 MultiVector只是检索小、返回大用 ParentDocument 更省事。八、常见坑现象原因解法返回了重复的文档MultiVector 不去重按doc_id手动去重报找不到 docdocstore里没有对应 id检查mset是否都写进去了重启后取不到原文用了InMemoryStore换 Redis / 数据库向量库巨大存了太多种表示优先保留假设问题建索引很慢逐篇调 LLM 生成摘要/问题batchmax_concurrency 便宜模型九、小结MultiVector 的核心一个文档多个向量命中任一都返回完整原文四种表示子块细节、摘要宽泛、假设问题口语化效果最好、混合假设问题解决了问题和文档表述空间不一致的根本问题性价比最高和 ParentDocument 的区别它不去重、需手动关联 id但支持任意多种表示必须用持久化的 docstoreRedis/数据库InMemoryStore重启即丢建索引的 LLM 调用要批量 并发 便宜模型。下一篇讲 SelfQueryRetriever——让模型自己把自然语言转成结构化查询。
RELATED

相关推荐

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

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

个人主页&#xff1a;> for_ever_love__ <&#xff08;欢迎各位大佬莅临&#x1f60a;&#xff09; 其他栏目: > 大模型开发从0到1 < 其他栏目: > iOS项目总结大全 < 其他栏目: > 我想学python了 < 其他栏目: > iOS UI < 文章目录LangChain Self…

📅 2026/10/12 6:02:43
Scratch图形化四级真题拆解:从执行思维到算法思维的分水岭

Scratch图形化四级真题拆解:从执行思维到算法思维的分水岭

考完Scratch图形化四级&#xff0c;我带的几个孩子出来以后表情都很微妙——不是难到崩溃&#xff0c;而是“感觉都会&#xff0c;但有一两题心里没底”。这种状态其实比“完全不会”更值得警惕&#xff0c;因为它说明四级开始真正考察算法思维&#xff0c;而不是单纯的操作熟练…

📅 2026/10/12 5:57:42
VS Code 集成 Claude API 的工程实践:代理模式与本地网关

VS Code 集成 Claude API 的工程实践:代理模式与本地网关

1. 项目概述&#xff1a;这不是“装个插件就完事”的配置&#xff0c;而是打通本地开发环境与大模型能力的工程实践你有没有过这种体验&#xff1a;在 VS Code 里写代码写到一半&#xff0c;突然想让 Claude 帮你解释一段晦涩的 Rust 生命周期报错&#xff1b;或者正在调试一个…

📅 2026/10/12 5:57:42
MORE NEWS

更多资讯

📰

DB2 V11.1下载安装避坑指南:老版本为何仍是运维必选项

简介&#xff1a;DB2 V11.1 是 IBM 推出的企业级关系型数据库管理系统&#xff0c;这份 Linux 版安装压缩包专为需要稳定、安全数据存储环境的中大型企业及系统管理员、DBA 设计&#xff0c;可用于生产或测试环境的快速部署。包内共 405 个文件&#xff0c;包含 174 个 cat 消息…

📰

“氛围编程”陷阱:程序员如何靠产出而非人设提升竞争力

知道“氛围编程”这个词&#xff0c;还是年初的事。一个做技术管理的朋友跟我八卦&#xff0c;说他组里那个公认的“气氛担当”被优化了&#xff0c;头一天还在张罗周五的狼人杀局&#xff0c;第二天就被HR约谈&#xff0c;工位干净得像从没坐过人。那哥们儿走的时候&#xff0…

📰

SpringBoot+Vue文学创作社交论坛毕设项目完整解析

这个标题看起来就像是一个典型的毕设资源包&#xff0c;“SpringBootVue 文学创作社交论坛”加上“完整项目源码SQL脚本接口文档”这几个关键词&#xff0c;基本已经把这套东西的家底全亮出来了。作为过来人&#xff0c;我第一反应是&#xff1a;这不仅仅是一套代码&#xff0c…

📰

ORB-SLAM2跑自己的图片序列:数据准备、配置与避坑全指南

简介&#xff1a;视觉SLAM&#xff08;Visual SLAM&#xff09;是机器人自主定位与建图的核心技术&#xff0c;而ORB-SLAM2作为经典开源方案&#xff0c;被广泛用于单目相机运动轨迹恢复。要让它准确运行&#xff0c;输入数据的规范性比算法调参更关键——图片序列必须时序连续…

📰

用自己的图片序列跑通ORB SLAM2:从数据准备到轨迹输出的完整指南

简介&#xff1a;面向视觉SLAM初学者与机器人开发者&#xff0c;解决如何利用ORB SLAM2处理自采图片序列完成定位与建图的问题。资源以ORB SLAM2为切入点&#xff0c;覆盖从视频逐帧提取图像、生成带时间戳的rgb.txt、编写辅助脚本到修改配置文件并运行数据集的完整流程&#x…

📰

DLL接口逆向:从二进制DLL生成C头文件与导入库

简介&#xff1a;本资源是一个面向C/C开发者、逆向工程师及Windows底层学习者的DLL反编译工具集&#xff0c;核心解决源码丢失或需逆向分析DLL时的C语言级代码还原问题。压缩包共78个文件&#xff0c;涵盖10个cpp与11个h头文件&#xff08;含LongJump、DebugTools等关键模块&am…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬