个人主页秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 系列专栏https://blog.csdn.net/qinjh_/category_13137010.html目录检索器Retrievers相关概念检索系统检索器使用向量数据库作为检索器基本使用使用 chain 创建“检索器”RAG 案例前言 hello! 各位铁子们大家好哇。今日更新了LangChain相关内容 欢迎大家关注点赞收藏⭐️留言检索器Retrievers相关概念检索系统检索系统Information Retrieval System, IR System是一个为了满足用户信息需求从大规模、非 结构化的数据集合中自动、高效地查找、排序并返回相关信息的计算机系统。它的核心任务是在正确的时间以正确的方式将正确的信息传递给正确的人。最常见的例子就 是搜索引擎如Google、百度。随着大型语言模型的流行检索系统已成为人工智能应用例如 RAG的重要组成部分。且存在多种 【不同类型】的检索系统包括关系数据库关系数据库是许多应用程序中使用的结构化数据存储的基本类型。数据存储在行记录和列属 性中可以通过 SQL结构化查询语言进行高效的查询和作。关系数据库擅长维护数据完整性、 支持复杂查询以及处理不同数据实体之间的关系。词法搜索索引许多搜索引擎基于将查询中的单词与每个文档中的单词进行匹配这种方法称为词法检索。即一个单 词经常出现在用户的查询和特定文档中那么这个文档可能是一个很好的匹配。这通常使用【倒排索 引】实现。向量数据库向量存储不使用字频而是使用【嵌入模型】将文档转换为高维向量表示。这允许使用余弦相似度等 数学运算对嵌入向量进行有效的相似性搜索。检索器检索器是检索系统中的一个核心组件它接收来自用户接口的查询Query检索出包含查询关键词 的候选文档集合。我们可以使用上面提到的任何检索系统实现方式创建检索器如关系数据库、向量数据库等。由于其 重要性和多样性LangChain 提供了一个统一的接口来与不同类型的检索系统进行交互。LangChain 的检索器接口非常简单输入查询字符串输出文档列表标准化的 LangChain 文档对象 Document例如使用关系数据库的检索系统检索器可以将问题转换为 SQL 语句并执行查询最后将查询结 果响应用户。下面我们来演示如何使用向量存储作为检索器。使用向量数据库作为检索器基本使用向量存储是索引和检索非结构化数据的一种强大而有效的方法。可以通过调用向量数据库的 as_retriever 方法将向量存储用作检索器。在这里我们使用 Redis 向量存储。# 嵌入模型 embeddings OpenAIEmbeddings(modeltext-embedding-3-large) # Redis 配置 config RedisConfig( index_nameqa, # 定义索引名 redis_urlredis://192.168.100.238:6379, metadata_schema[ {name: category, type: tag}, # 添加索引字段分类 {name: num, type: numeric}, # 添加索引字段编号 ] ) # 初始化 Redis 向量存储实例建立了索引结构 vector_store RedisVectorStore( embeddingsembeddings, configconfig, ) # 检索器依赖向量库(Runnable) retriever vector_store.as_retriever() search_docs retriever.invoke(项目介绍) for doc in search_docs: print(* * 30) print(doc.page_content)LangChain 检索器是一个 Runnable 的对象 它是 LangChain 组件的标准接口。这意味着它有一些常 用方法包括 invoke 用于与其交互。默认情况下向量存储检索器使用相似性搜索。as_retriever 方法也支持我们传递相关参数修改搜索结果如search_type 设置相似算法包括 “similarity” 默 认、 “mmr” 或 “similarity_score_threshold” 相似性分数阈值search_kwargs k 限制检索器返回的文档 k 数量。retriever vector_store.as_retriever(search_kwargs{k: 2})fetch_k 要传递给 MMR 算法的文档量。retriever vector_store.as_retriever( search_typemmr, search_kwargs{ k: 2, fetch_k: 10 } )要注意的是 Retrievers 检索器虽然是 Runnable 对象但其不提供任何流式处理因为它本身 通常是同步的、阻塞的操作。如下所示chunks [] for chunk in retriever.stream(数据库表怎么设计的): chunks.append(chunk) print(chunk, end|, flushTrue)调用可以发现它是一次性返回与 invoke 调用无异。使用 chain 创建“检索器”除了使用 as_retriever 方法我们还可以自行创建一个“检索器”。回想一下检索器的特点LangChain 检索器是一个 Runnable 的对象LangChain 检索器输入为查询字符串输出为文档列表标准化的 LangChain 文档对象 Document综上所述我们可以# 使用chain定义检索器函数当作具有Runnable的检索器使用 chain def retriever(query: str) - List[Document]: return vector_store.similarity_search(queryquery ,k2) search_docs retriever.invoke(项目介绍) for doc in search_docs: print(* * 30) print(doc.page_content)上面定义了一个函数使用 chain 修饰该修饰可以使其成为 Runnable 函数且满足检索器输入 输出的要求。在函数中我们依旧使用向量数据库的相似性搜索方法这样灵活性也更高想要进行 元数据筛选也更方便。注意这并不是真正的检索器检索器是一个 Runnable 对象而我们定义的只是一个函数具备其 特点罢了。RAG 案例RAG 是当前大语言模型应用的核心模式。当用户向 LLM 提问时系统首先使用嵌入模型在知识库中进 行语义搜索找到最相关的内容然后将这些内容和问题一起交给 LLM 来生成答案。这极大地提高了 答案的准确性和时效性。由于 LangChain 检索器是一个 Runnable 的对象我们便可以方便的使用 链 完成相关的调用。下面 我们来完成一个最简单的 RAG 案例将会完成根据 Query 搜索最相关的 4 篇文档。将相关的文档转换为字符串以便后续发送给聊天模型。将 Query 与文档字符串发送给聊天模型。聊天模型依据输出解析器格式输出内容。from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_redis import RedisConfig, RedisVectorStore # 构建链完成RAG能力 # 定义组件构建链 # 嵌入模型 embeddings OpenAIEmbeddings(modeltext-embedding-3-large) # 聊天模型 model ChatOpenAI(modelgpt-4o-mini) # 1. 先从知识库中检索 # Redis 配置 config RedisConfig( index_nameqa, # 定义索引名 redis_urlredis://192.168.100.238:6379, metadata_schema[ {name: category, type: tag}, # 添加索引字段分类 {name: num, type: numeric}, # 添加索引字段编号 ] ) # Redis 向量库 vector_store RedisVectorStore( embeddingsembeddings, configconfig, ) # 检索器 retriever vector_store.as_retriever() # 2. 将检索结果查询语句 构建为提示词提示词模板 # 提示词模板 prompt ChatPromptTemplate.from_messages( [ ( human, 你是负责回答问题的助手。使用一下检索到的上下文片段来回答问题。如果你不知道答案就说不知道答案。最多回复三句话的结果回答要简明扼要 Question:{question} Context:{context} Answer: ) ] ) # 将检索出来的文档转换成文本传递给提示词模板 def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) # 3. 将消息发送给 LLM实例化消息交由链完成 # 定义链执行时需要 question # 检索器 format_docs question 同时传递 # prompt # model # 输出解析器 chain ( # 检索器 format_docs 分支1 # question 分支2: RunnablePassthrough() 在链中透传输入数据保持原始问题不变直接传递给后续步骤 {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | model | StrOutputParser() # 输出解析器 ) # 执行流 # 输入问题项目介绍 # 并行执行两个分支提高效率 # 输出结果 # { # context:xxxx # question:项目介绍 # } # 4. 打印字符串结果 流式 while True: # 获取用户输入 question input(\n请输入您的问题输入退出或quit结束程序: ).strip() # 检查是否退出 if question.lower() in [退出, quit]: print(程序已结束再见) break # 检查输入是否为空 if not question: print(问题不能为空请重新输入。) continue # 执行链流式输出 print(回答: , end, flushTrue) for chunk in chain.stream(question): print(chunk, end, flushTrue) print() # 换行上述代码中 RunnablePassthrough 我们之前还没有见过简单来说 RunnablePassthrough 是一个“伪”Runnable它的主要作用是在链Chain中透明地传递 输入数据而不做任何修改。当我们需要将原始输入和另一个处理过程的输出一起传递给下一个步骤时就需要 RunnablePassthrough 。就例如代码中我们需要将【Query】与【通过检索出来的文档转换的 字符串】同时发送给提示词模板。上面讲过检索器不提供任何流式处理。但这里可以使用流式输出。我们可以把像 RAG 这样的链的执行 过程想象成两个阶段阶段一准备阶段同步、阻塞接收输入、检索文档、构建提示阶段二生成阶段可流式调用LLM流式输出的是最终答案而非中间过程。
【LangChain核心组件】检索器
发布时间:2026/7/15 6:40:39
个人主页秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 系列专栏https://blog.csdn.net/qinjh_/category_13137010.html目录检索器Retrievers相关概念检索系统检索器使用向量数据库作为检索器基本使用使用 chain 创建“检索器”RAG 案例前言 hello! 各位铁子们大家好哇。今日更新了LangChain相关内容 欢迎大家关注点赞收藏⭐️留言检索器Retrievers相关概念检索系统检索系统Information Retrieval System, IR System是一个为了满足用户信息需求从大规模、非 结构化的数据集合中自动、高效地查找、排序并返回相关信息的计算机系统。它的核心任务是在正确的时间以正确的方式将正确的信息传递给正确的人。最常见的例子就 是搜索引擎如Google、百度。随着大型语言模型的流行检索系统已成为人工智能应用例如 RAG的重要组成部分。且存在多种 【不同类型】的检索系统包括关系数据库关系数据库是许多应用程序中使用的结构化数据存储的基本类型。数据存储在行记录和列属 性中可以通过 SQL结构化查询语言进行高效的查询和作。关系数据库擅长维护数据完整性、 支持复杂查询以及处理不同数据实体之间的关系。词法搜索索引许多搜索引擎基于将查询中的单词与每个文档中的单词进行匹配这种方法称为词法检索。即一个单 词经常出现在用户的查询和特定文档中那么这个文档可能是一个很好的匹配。这通常使用【倒排索 引】实现。向量数据库向量存储不使用字频而是使用【嵌入模型】将文档转换为高维向量表示。这允许使用余弦相似度等 数学运算对嵌入向量进行有效的相似性搜索。检索器检索器是检索系统中的一个核心组件它接收来自用户接口的查询Query检索出包含查询关键词 的候选文档集合。我们可以使用上面提到的任何检索系统实现方式创建检索器如关系数据库、向量数据库等。由于其 重要性和多样性LangChain 提供了一个统一的接口来与不同类型的检索系统进行交互。LangChain 的检索器接口非常简单输入查询字符串输出文档列表标准化的 LangChain 文档对象 Document例如使用关系数据库的检索系统检索器可以将问题转换为 SQL 语句并执行查询最后将查询结 果响应用户。下面我们来演示如何使用向量存储作为检索器。使用向量数据库作为检索器基本使用向量存储是索引和检索非结构化数据的一种强大而有效的方法。可以通过调用向量数据库的 as_retriever 方法将向量存储用作检索器。在这里我们使用 Redis 向量存储。# 嵌入模型 embeddings OpenAIEmbeddings(modeltext-embedding-3-large) # Redis 配置 config RedisConfig( index_nameqa, # 定义索引名 redis_urlredis://192.168.100.238:6379, metadata_schema[ {name: category, type: tag}, # 添加索引字段分类 {name: num, type: numeric}, # 添加索引字段编号 ] ) # 初始化 Redis 向量存储实例建立了索引结构 vector_store RedisVectorStore( embeddingsembeddings, configconfig, ) # 检索器依赖向量库(Runnable) retriever vector_store.as_retriever() search_docs retriever.invoke(项目介绍) for doc in search_docs: print(* * 30) print(doc.page_content)LangChain 检索器是一个 Runnable 的对象 它是 LangChain 组件的标准接口。这意味着它有一些常 用方法包括 invoke 用于与其交互。默认情况下向量存储检索器使用相似性搜索。as_retriever 方法也支持我们传递相关参数修改搜索结果如search_type 设置相似算法包括 “similarity” 默 认、 “mmr” 或 “similarity_score_threshold” 相似性分数阈值search_kwargs k 限制检索器返回的文档 k 数量。retriever vector_store.as_retriever(search_kwargs{k: 2})fetch_k 要传递给 MMR 算法的文档量。retriever vector_store.as_retriever( search_typemmr, search_kwargs{ k: 2, fetch_k: 10 } )要注意的是 Retrievers 检索器虽然是 Runnable 对象但其不提供任何流式处理因为它本身 通常是同步的、阻塞的操作。如下所示chunks [] for chunk in retriever.stream(数据库表怎么设计的): chunks.append(chunk) print(chunk, end|, flushTrue)调用可以发现它是一次性返回与 invoke 调用无异。使用 chain 创建“检索器”除了使用 as_retriever 方法我们还可以自行创建一个“检索器”。回想一下检索器的特点LangChain 检索器是一个 Runnable 的对象LangChain 检索器输入为查询字符串输出为文档列表标准化的 LangChain 文档对象 Document综上所述我们可以# 使用chain定义检索器函数当作具有Runnable的检索器使用 chain def retriever(query: str) - List[Document]: return vector_store.similarity_search(queryquery ,k2) search_docs retriever.invoke(项目介绍) for doc in search_docs: print(* * 30) print(doc.page_content)上面定义了一个函数使用 chain 修饰该修饰可以使其成为 Runnable 函数且满足检索器输入 输出的要求。在函数中我们依旧使用向量数据库的相似性搜索方法这样灵活性也更高想要进行 元数据筛选也更方便。注意这并不是真正的检索器检索器是一个 Runnable 对象而我们定义的只是一个函数具备其 特点罢了。RAG 案例RAG 是当前大语言模型应用的核心模式。当用户向 LLM 提问时系统首先使用嵌入模型在知识库中进 行语义搜索找到最相关的内容然后将这些内容和问题一起交给 LLM 来生成答案。这极大地提高了 答案的准确性和时效性。由于 LangChain 检索器是一个 Runnable 的对象我们便可以方便的使用 链 完成相关的调用。下面 我们来完成一个最简单的 RAG 案例将会完成根据 Query 搜索最相关的 4 篇文档。将相关的文档转换为字符串以便后续发送给聊天模型。将 Query 与文档字符串发送给聊天模型。聊天模型依据输出解析器格式输出内容。from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_redis import RedisConfig, RedisVectorStore # 构建链完成RAG能力 # 定义组件构建链 # 嵌入模型 embeddings OpenAIEmbeddings(modeltext-embedding-3-large) # 聊天模型 model ChatOpenAI(modelgpt-4o-mini) # 1. 先从知识库中检索 # Redis 配置 config RedisConfig( index_nameqa, # 定义索引名 redis_urlredis://192.168.100.238:6379, metadata_schema[ {name: category, type: tag}, # 添加索引字段分类 {name: num, type: numeric}, # 添加索引字段编号 ] ) # Redis 向量库 vector_store RedisVectorStore( embeddingsembeddings, configconfig, ) # 检索器 retriever vector_store.as_retriever() # 2. 将检索结果查询语句 构建为提示词提示词模板 # 提示词模板 prompt ChatPromptTemplate.from_messages( [ ( human, 你是负责回答问题的助手。使用一下检索到的上下文片段来回答问题。如果你不知道答案就说不知道答案。最多回复三句话的结果回答要简明扼要 Question:{question} Context:{context} Answer: ) ] ) # 将检索出来的文档转换成文本传递给提示词模板 def format_docs(docs): return \n\n.join(doc.page_content for doc in docs) # 3. 将消息发送给 LLM实例化消息交由链完成 # 定义链执行时需要 question # 检索器 format_docs question 同时传递 # prompt # model # 输出解析器 chain ( # 检索器 format_docs 分支1 # question 分支2: RunnablePassthrough() 在链中透传输入数据保持原始问题不变直接传递给后续步骤 {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | model | StrOutputParser() # 输出解析器 ) # 执行流 # 输入问题项目介绍 # 并行执行两个分支提高效率 # 输出结果 # { # context:xxxx # question:项目介绍 # } # 4. 打印字符串结果 流式 while True: # 获取用户输入 question input(\n请输入您的问题输入退出或quit结束程序: ).strip() # 检查是否退出 if question.lower() in [退出, quit]: print(程序已结束再见) break # 检查输入是否为空 if not question: print(问题不能为空请重新输入。) continue # 执行链流式输出 print(回答: , end, flushTrue) for chunk in chain.stream(question): print(chunk, end, flushTrue) print() # 换行上述代码中 RunnablePassthrough 我们之前还没有见过简单来说 RunnablePassthrough 是一个“伪”Runnable它的主要作用是在链Chain中透明地传递 输入数据而不做任何修改。当我们需要将原始输入和另一个处理过程的输出一起传递给下一个步骤时就需要 RunnablePassthrough 。就例如代码中我们需要将【Query】与【通过检索出来的文档转换的 字符串】同时发送给提示词模板。上面讲过检索器不提供任何流式处理。但这里可以使用流式输出。我们可以把像 RAG 这样的链的执行 过程想象成两个阶段阶段一准备阶段同步、阻塞接收输入、检索文档、构建提示阶段二生成阶段可流式调用LLM流式输出的是最终答案而非中间过程。