LangChain-检索系统 (Retrieval)
检索系统 (Retrieval)
检索系统是LangChain的核心组件之一,它提供了从各种数据源获取相关信息的能力,是构建知识增强型应用的基础。本文档详细介绍LangChain检索系统的组件、工作原理和最佳实践。
概述
检索系统解决了大型语言模型知识有限和过时的问题,允许模型访问外部信息源。LangChain的检索框架包括以下主要组成部分:
- 文档加载:从各种来源加载文本数据
- 文档处理:分割、清理和预处理文档
- 嵌入和索引:将文本转换为向量并建立索引
- 检索:搜索并获取相关文档
- 上下文增强:将检索到的信息整合到模型输入中
文档加载器
LangChain提供了100多种文档加载器,用于从不同数据源获取文档。
常见文档加载器
from langchain_community.document_loaders import (TextLoader, PyPDFLoader, CSVLoader, WebBaseLoader, YouTubeLoader, DirectoryLoader, GitLoader
)# 加载文本文件
text_loader = TextLoader("path/to/document.txt")
text_docs = text_loader.load()# 加载PDF文件
pdf_loader = PyPDFLoader("path/to/document.pdf")
pdf_docs = pdf_loader.load()# 加载CSV文件
csv_loader = CSVLoader("path/to/data.csv")
csv_docs = csv_loader.load()# 加载网页内容
web_loader = WebBaseLoader(["https://www.example.com/page"])
web_docs = web_loader.load()# 加载YouTube视频
youtube_loader = YouTubeLoader.from_youtube_url("https://www.youtube.com/watch?v=example",add_video_info=True,language=["zh-cn"]
)
youtube_docs = youtube_loader.load()# 加载整个目录
dir_loader = DirectoryLoader("./documents/", glob="**/*.pdf")
dir_docs = dir_loader.load()# 加载Git仓库
git_loader = GitLoader(clone_url="https://github.com/username/repo",repo_path="./repos/example_repo",branch="main"
)
git_docs = git_loader.load()
文档结构
加载的文档通常包含以下属性:
from langchain_core.documents import Documentdoc = Document(page_content="文档内容",metadata={"source": "example.txt", "page": 1, "author": "张三"}
)
文档处理
文本分割
将长文档分割成小块,以适应模型的上下文窗口:
from langchain_text_splitters import (RecursiveCharacterTextSplitter,CharacterTextSplitter,TokenTextSplitter,SentenceTransformersTokenTextSplitter
)# 基于字符的递归分割(推荐)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, # 每块最大字符数chunk_overlap=200, # 块之间的重叠字符数separators=["\n\n", "\n", "。", ",", " ", ""] # 尝试优先在这些分隔符处拆分
)# 基于令牌的分割(更精确控制token数量)
token_splitter = TokenTextSplitter(chunk_size=500, # 每块最大token数chunk_overlap=50 # 块之间的重叠token数
)# 中文分割优化(基于句子变换器的分词)
chinese_splitter = SentenceTransformersTokenTextSplitter(chunk_size=256,chunk_overlap=20
)# 分割文档
doc = text_loader.load()[0] # 假设已经加载了文档
chunks = text_splitter.split_documents([doc])
print(f"文档被分割成{len(chunks)}个块")
嵌入与向量存储
嵌入模型
将文本转换为向量表示:
from langchain_openai import OpenAIEmbeddings
from langchain_community.embeddings import HuggingFaceEmbeddings, ModelScopeEmbeddings# OpenAI嵌入(高质量但需付费)
openai_embeddings = OpenAIEmbeddings()# 开源嵌入选项(本地或免费)
huggingface_embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2" # 多语言模型
)# 使用中文模型(ModelScope)
chinese_embeddings = ModelScopeEmbeddings(model_id="iic/nlp_lawbert_text-embedding-chinese_base"
)# 生成文本嵌入
text = "这是一段示例文本"
embedding = openai_embeddings.embed_query(text)
向量存储
存储和检索文档嵌入:
from langchain_community.vectorstores import FAISS, Chroma, Milvus# 准备文档
docs = text_splitter.split_documents(text_loader.load())# 使用FAISS(高效的开源向量库,适合本地使用)
faiss_db = FAISS.from_documents(docs, openai_embeddings)# 使用Chroma(开源向量数据库,支持元数据过滤)
chroma_db = Chroma.from_documents(docs, openai_embeddings,persist_directory="./chroma_db" # 持久化存储路径
)# 保存Chroma数据库
chroma_db.persist()# 使用Milvus(分布式向量数据库,适合大规模部署)
milvus_db = Milvus.from_documents(docs,openai_embeddings,connection_args={"host": "localhost", "port": "19530"}
)
检索器
基本检索
从向量存储中检索文档:
# 将向量存储转换为检索器
retriever = chroma_db.as_retriever()# 自定义检索参数
custom_retriever = chroma_db.as_retriever(search_type="similarity", # 相似度搜索search_kwargs={"k": 5} # 返回前5个最相关文档
)# 执行检索
query = "人工智能的应用场景有哪些?"
relevant_docs = retriever.get_relevant_documents(query)# 显示检索结果
for i, doc in enumerate(relevant_docs):print(f"结果 {i+1}: {doc.page_content[:100]}...")print(f"来源: {doc.metadata.get('source', '未知')}\n")
检索增强生成 (RAG)
基础RAG实现
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI# 创建检索链
def format_docs(docs):return "\n\n".join([doc.page_content for doc in docs])# 创建RAG提示模板
template = """请根据以下上下文回答问题。如果上下文中没有提供足够的信息,就说你不知道。上下文:
{context}问题:{question}回答:"""prompt = ChatPromptTemplate.from_template(template)# 创建RAG链
rag_chain = {"context": retriever | format_docs,"question": RunnablePassthrough()
} | prompt | ChatOpenAI(temperature=0) | StrOutputParser()# 执行RAG查询
result = rag_chain.invoke("深度学习和机器学习有什么区别?")
print(result)
高级RAG模式
对话RAG
from langchain_core.prompts import MessagesPlaceholder
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory# 创建带对话历史的RAG提示
conversational_rag_prompt = ChatPromptTemplate.from_messages([("system", "你是一个基于上下文的问答助手。使用提供的上下文回答用户问题。"),MessagesPlaceholder(variable_name="chat_history"),("human", "{question}"),("system", "上下文信息:\n{context}")
])# 创建对话历史
chat_history = ChatMessageHistory()# 对话RAG链
conversational_rag_chain = {"context": retriever | format_docs,"question": RunnablePassthrough(),"chat_history": lambda _: chat_history.messages
} | conversational_rag_prompt | ChatOpenAI() | StrOutputParser()
最佳实践
-
文档分割策略:根据文档类型选择适当的分割方法
- 通用文本:使用
RecursiveCharacterTextSplitter - 代码:使用专用代码分割器
- 结构化文档:使用专用分割器如
MarkdownHeaderTextSplitter
- 通用文本:使用
-
选择合适的块大小
- 太大:检索精度低,但可能包含更完整信息
- 太小:检索精度高,但可能缺乏上下文
- 推荐:普通文本500-1000 tokens,技术文档300-500 tokens
-
中文检索优化
- 使用专为中文优化的嵌入模型
- 使用中文分词进行文本分割
- 考虑检索更多文档以提高召回率
-
检索系统部署考虑
- 小规模/本地测试:FAISS、Chroma
- 中等规模/生产:Weaviate、Pinecone
- 大规模/企业级:Milvus、Elasticsearch with vector search
总结
检索系统是LangChain中连接大语言模型与外部知识的关键组件。通过文档加载、文本处理、向量嵌入和检索,可以构建强大的知识增强型应用。RAG架构将检索系统与生成模型结合,创建了一种既有知识深度又能保持对话灵活性的AI应用框架。
后续学习
- 模型输入输出 - 了解如何与语言模型交互
- 链 - 学习如何将检索系统集成到复杂流程中
- 智能体|后续更新 - 探索将检索系统与自主智能体结合
相关文章:
LangChain-检索系统 (Retrieval)
检索系统 (Retrieval) 检索系统是LangChain的核心组件之一,它提供了从各种数据源获取相关信息的能力,是构建知识增强型应用的基础。本文档详细介绍LangChain检索系统的组件、工作原理和最佳实践。 概述 检索系统解决了大型语言模型知识有限和过时的问…...
Fast网络速度测试工具
目录 网站简介 功能特点 测试过程 为什么使用Fast 如果网络速度不达标 网站简介 Fast是一个由Netflix提供的网络速度测试工具,主要用来测试用户的互联网下载速度。它以其简洁的界面和快速的测试过程而受到用户的欢迎。 功能特点 下载速度测试:这是…...
ubuntu20.04在mid360部署direct_lidar_odometry(DLO)
editor:1034Robotics-yy time:2025.4.10 1.下载DLO,mid360需要的一些...: 1.1 在工作空间/src下 下载DLO: git clone https://github.com/vectr-ucla/direct_lidar_odometry 1.2 在工作空间/src下 下载livox_ros_driver2&…...
制造企业数据治理体系搭建与业务赋能实践
当下制造企业正面临着前所未有的机遇与挑战,从多环节业务协同的复杂性,到海量数据资源的沉睡与孤岛化;从个性化定制需求的爆发,到供应链效率优化的迫切性——如何通过数据治理将“数据包袱”转化为“数据资产”,已成为…...
java基础多态------面试八股文
是什么是多态 类引用指向子类对象,并调用子类重写的方法,实现不同的行为 例子 class Animal {void sound() {System.out.println("动物发出声音");} }class Dog extends Animal {Overridevoid sound() {System.out.println("狗叫&…...
【LunarVim】解决which-key 自定义键位注册不成功问题
问题描述 LunarVim将which-key设置放在一个keymaps.lua中,然后config.lua调用reload “user.keymaps”,键位没用注册成功,而直接写在config.lua中,就注册成功 这暴露了LunarVim 插件和配置加载顺序的一些细节坑,下面解…...
开源推荐#5:CloudFlare-ImgBed — 基于 CloudFlare Pages 的开源免费文件托管解决方案
大家好,我是 jonssonyan。 寻找一个稳定、快速、还最好是免费或成本极低的图床服务,一直是许多开发者、博主和内容创作者的痛点。公共图床可能说关就关,付费服务又增加成本。现在,一个名为 CloudFlare-ImgBed 的开源项目…...
算法训练之动态规划(三)
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
xv6-labs-2024 lab2
lab-2 0. 前置 课程记录 操作系统的隔离性,举例说明就是,当我们的shell,或者qq挂掉了,我们不希望因为他,去影响其他的进程,所以在不同的应用程序之间,需要有隔离性,并且࿰…...
LangChain-模型输入输出 (Model I/O)
模型输入输出是LangChain的核心组件,负责处理与各种语言模型的交互。本文档详细介绍了这些组件的功能和使用方法。 概述 模型输入输出组件负责: 连接各种语言模型:统一不同提供商的模型接口格式化输入:将原始输入转换为模型可理…...
基于FPGA实现BPSK 调制
目录 一、 任务介绍二、基本原理三、基于FPGA实现BPSK 调制四、源码 一、 任务介绍 BPSK 调制在数字通信系统中是一种极重要的调制方式,它的抗干扰噪声性能及通频带的利用率均优先于 ASK 移幅键控和 FSK 移频键控。因此,PSK 技术在中、高速数据传输中得…...
深入理解 ResponseBodyAdvice 及其应用
ResponseBodyAdvice 是 Spring MVC 提供的一个强大接口,允许你在响应体被写入 HTTP 响应之前对其进行全局处理。 下面我将全面介绍它的工作原理、使用场景和最佳实践。 基本概念 接口定义 public interface ResponseBodyAdvice<T> {boolean supports(Metho…...
Java 基础 - 反射(1)
文章目录 引入类加载过程1. 通过 new 创建对象2. 通过反射创建对象2.1 触发加载但不初始化2.2 按需触发初始化2.3 选择性初始化控制 核心用法示例1. 通过无参构造函数创建实例对象2. 通过有参构造函数创建实例对象3. 反射通过私有构造函数创建对象, 破坏单例模式4. …...
Spring Boot中Spring MVC相关配置的详细描述及表格总结
以下是Spring Boot中Spring MVC相关配置的详细描述及表格总结: Spring MVC 配置项详解 1. 异步请求配置 spring.mvc.async.request-timeout 描述:设置异步请求的超时时间(单位:毫秒)。默认值:未设置&…...
flink Shuffle的总结
关于 ** 5 种 Shuffle 类型** 的区别、使用场景及 Flink 版本支持的总结: * 注意:下面是问AI具体细节与整理学习 1. 核心区别 Shuffle 类型核心特点使用场景Flink 版本支持Pipelined Shuffle流式调度,纯内存交换,低延迟(毫秒级…...
在排序数组中查找元素的第一个和最后一个位置 --- 二分查找
目录 一:题目 二:算法原理分析 三:代码实现 一:题目 题目链接: 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode) 二:算法原理分析 三:代码实现 c…...
631SJBH中小型企业的网络管理模式的方案设计
1.1、研究现状 我国很多企业信息化水平一直还处在非常初级的阶段,有关统计表明,真正实现了计算机较高应用的企业在全国1000多万中小企业中所占的比例还不足10%幢3。大多数企业还停留在利用互联网进行网上查询(72.9%)、…...
NO.85十六届蓝桥杯备战|动态规划-经典线性DP|最长上升子序列|合唱队形|最长公共子序列|编辑距离(C++)
经典线性dp问题有两个:最⻓上升⼦序列(简称:LIS)以及最⻓公共⼦序列(简称:LCS),这两道题⽬的很多⽅⾯都是可以作为经验,运⽤到别的题⽬中。⽐如:解题思路&…...
0410 | 软考高项笔记:项目管理概述
以下是不同组织结构中项目经理的角色、工作特点以及快速记忆的方法: 不同组织结构中项目经理的角色和工作特点 组织结构项目经理的角色工作特点职能型组织项目协调者、辅助管理者权力有限,主要负责协调部门间的工作,项目成员向部门经理汇报…...
Vue3的Composition API与React Hooks有什么异同?
Vue3的一个重大更新点就是支持Composition API,而且也被业界称为hooks,那么Vue3的“Hooks”与React的Hooks有这么区别呢? 一、核心相似点 1. 逻辑复用与代码组织 都解决了传统类组件或选项式 API 中逻辑分散的问题,允许将相关逻…...
LangChain4j(1):初步认识Java 集成 LLM 的技术架构
LangChain 作为构建具备 LLM 能力应用的框架,虽在 Python 领域大放异彩,但 Java 开发者却只能望洋兴叹。LangChain4j 正是为解决这一困境而诞生,它旨在借助 LLM 的强大效能,增强 Java 应用,简化 LLM 功能在Java应用中的…...
JDK 21 的新特性有哪些?带你全面解读 Java 的未来
引言:从 JDK 21 看 Java 的进化之路 Java 是一门历久弥新的语言,每一次版本更新都在强化它的生态体系。2023 年发布的 JDK 21,作为长期支持版本(LTS),带来了许多令人兴奋的新特性。不论你是开发者、架构师…...
【C++算法】53.链表_重排链表
文章目录 题目链接:题目描述:解法C 算法代码: 题目链接: 143. 重排链表 题目描述: 解法 模拟 找到链表的中间节点 快慢双指针 把后面的部分逆序 双指针,三指针,头插法 合并两个链表 合并两个有…...
多卡分布式训练:torchrun --nproc_per_node=5
多卡分布式训练:torchrun --nproc_per_node=5 1. torchrun 实现规则 torchrun 是 PyTorch 提供的用于启动分布式训练作业的实用工具,它基于 torch.distributed 包,核心目标是简化多进程分布式训练的启动和管理。以下是其主要实现规则: 进程启动 多进程创建:torchrun 会…...
系统架构设计师之系统设计模块笔记
一、系统设计概述 定义与目标 系统设计是根据系统分析结果,制定系统构建蓝图的过程,核心目标是合理分配功能需求、优化资源使用、确保系统高内聚低耦合,并满足性能、安全、可扩展等非功能需求。主要内容 概要设计:将功能需求分配…...
Elasticsearch:加快 HNSW 图的合并速度
作者:来自 Elastic Thomas Veasey 及 Mayya Sharipova 过去,我们曾讨论过搜索多个 HNSW 图时所面临的一些挑战,以及我们是如何缓解这些问题的。当时,我们也提到了一些计划中的改进措施。本文正是这项工作的成果汇总。 你可能会问…...
图片中文字无法正确显示的解决方案
图片中文字无法正确显示的解决方案 问题描述 在 Linux 系统中生成图片时,图片中的文字(如中文)未能正确显示,可能表现为乱码或空白。这通常是由于系统缺少对应的字体文件(如宋体/SimSun),或者…...
数据结构:通俗解释AOE 网中事件的最早发生时间和最迟发生时间
1. 事件的最早发生时间 在 AOE 网(Activity On Edge Network,边表示活动的网络)中,事件的最早发生时间指从源点(起点)到该事件结点的最长路径长度(即所需时间)。它决定了所有以该事…...
C# 看门狗策略实现
using System; using System.Threading;public class Watchdog {private Timer _timer;private volatile bool _isTaskAlive;private readonly object _lock new object();private const int CheckInterval 5000; // 5秒检测一次private const int TimeoutThreshold 10000; …...
在 openEuler 24.03 (LTS) 操作系统上添加 ollama 作为系统服务的步骤
以下是在 openEuler 操作系统上添加 ollama 作为系统服务的步骤: 创建 systemd 服务文件 sudo vi /etc/systemd/system/ollama.service将以下内容写入服务文件(按需修改参数): [Unit] DescriptionOllama Service Afternetwork.…...
