惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Help Net Security
Help Net Security
P
Privacy International News Feed
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
AWS News Blog
AWS News Blog
K
Kaspersky official blog
A
Arctic Wolf
Latest news
Latest news
T
Threat Research - Cisco Blogs
L
LINUX DO - 最新话题
P
Privacy & Cybersecurity Law Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
月光博客
月光博客
N
News and Events Feed by Topic
Jina AI
Jina AI
博客园 - 司徒正美
WordPress大学
WordPress大学
罗磊的独立博客
雷峰网
雷峰网
AI
AI
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Security @ Cisco Blogs
博客园 - 三生石上(FineUI控件)
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cisco Blogs
博客园 - 【当耐特】
The Hacker News
The Hacker News
有赞技术团队
有赞技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Schneier on Security
Schneier on Security
博客园 - Franky
S
SegmentFault 最新的问题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Cloudbric
Cloudbric
爱范儿
爱范儿
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
Last Week in AI
Last Week in AI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
LangChain框架-数据检索
yuyuyui · 2026-04-30 · via 博客园_首页

4. LangChain的数据检索

RAG基础里面,我们已经或多或少知道了大模型存在的缺陷,数据不实时,缺少垂直领域数据和私域数据等。解决这些缺陷的主要方法是通过检索增强生成(RAG)。首先检索外部数据,然后在执行生成步骤时将其传递给LLM。LangChain 为RAG应用程序提供了从简单到复杂的所有构建块,数据检索(Retrieval)模块包括与检索步骤相关的所有内容,例如数据的获取、切分、向量化、向量存储、向量检索等模块。

image

1.Document loaders 文档加载模块

在上面的图中已经清晰的知道,第一步是必须有数据源,第二步就是读取数据源,LangChain为开发者封装了很多文档加载模块,例如 pdf、csv、json、word、md格式文件,我们先看一下如何加载

1.加载本地pdf、word文件

LangChain中加载pdf使用的是pypdf,需要先安装一下,我们在前面其实也读取过pdf,不过用的是原生的方式,如果要做那种可以更精细化的处理,例如读取pdf中的表格,行,用原生的比较好

pip install pypdf

pdf加载

from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader('物理知识点.pdf')

print(loader)
page = loader.load()
print(page[0].page_content)

word加载



from langchain_community.document_loaders import UnstructuredWordDocumentLoader

# 指定要加载的Word文档路径
loader = UnstructuredWordDocumentLoader("语文.docx")
print(loader)

# 加载文档并分割成段落或元素
documents = loader.load()
print(documents)
# 输出加载的内容
for doc in documents:
    print(doc.page_content)

2.文档切分模块

上一步我们已经对已有的数据源进行加载,当然也不局限于本地文件其实数据源可以来源于很多途径,数据库查询接口获取,甚至用于直接通过接口调用写入的,都归属于数据加载这一环节,那么文档切分模块,就是对已经加载的数据源进行切分,然后向量化,那么为什么要切分呢?

简单说分割就是为了 检索精度和信息完整性 之间找一个平衡点,如果不进行分割,直接把所有数据作为检索单元,会存在一些问题:

1.把整个源数据作为转换为向量,那么整个向量的语义就会非常宽泛

2.大语言模型的上下文窗口是有限的,处理太长的文本会增加计算成本

3.将整个数据作为上下文,相当于把答案藏在大海,模型需要从里面筛选信息,无异于大海捞针,而且容易被一些不相关的噪声干扰,导致质量下降

当然分割也不是越细越好,如果仅仅按照固定字符强行切断,很容易破坏数据完整性,例如:

1.上下文丢失:例如原文是,“我是小余。我喜欢吃西瓜”,如果被切分成“我是小余”和 ”我喜欢吃西瓜“2个块,当用户问“小余喜欢吃什么“的时候或者包含”我喜欢吃西瓜”的时候可能就检索不到。

2.破坏结构:对于表格、列表、操作步骤这一些结构化的的内容,分割不好会将他们拆散,导致查出来的信息,缺胳膊少腿,用都没法用。

所以一些做的比较好的检索,会采用一些更智能的分割方法,例如:

按语义分割:

在段落、章节这些自然的边界上进行切分,保证从语义上相对完整。什么是语义?,简单来说就是归类,例如当一辆无人驾驶的汽车,通过摄像头看到前方的景像,有汽车,道路、行人、建筑,语义分割就是

所有道路的像素都被标记为灰色。

所有汽车的像素都被标记为蓝色。

所有行人的像素都被标记为红色。

所有建筑的像素都被标记为紫色

这样,汽车就不再是看一张复杂的图片,而是得到了一张清晰的指令图:灰色区域可以行驶,红色区域必须避让,同理文档也是一样,核心就是分类。

重叠分割:

在相邻的块之间保留一部分重叠,来让上下文衔接,增加连贯性,这也是用的比较多的一种,直接上图。

image

在LangChain中,框架也提供了许多不同类型的文本切分器

分割器类型 核心逻辑 适用场景 爽点 坑点
CharacterTextSplitter 数着字数切
不管内容啥意思,凑够指定字数就咔嚓一刀。
简单的纯文本,或者对语义没啥要求的场景。 快,不需要加载任何模型,简单直接。 傻,很容易把一句完整的话从中间切断,导致上下文不连贯。
RecursiveCharacterTextSplitter 层层递进地切
先试着按段落切,切不开再按换行切,再切不开按句号切...直到切小为止。
最推荐。适合绝大多数长文档、文章、书籍。 聪明,尽量保证不把句子切断,保留了语义完整性。 需要稍微花点心思调整分隔符的优先级。
TokenTextSplitter 按模型“词汇量”切
按 Token 数量切,而不是按字数。因为大模型是按 Token 收费和计数的。
需要严格控制成本,或者怕超出模型上下文限制(比如 4K/8K 限制)时。 精准,能完美匹配大模型的输入限制,不会超支。 计算稍微复杂一点点(其实也就是一瞬间的事)。
Language 专属分割器 按代码语法切
懂编程语言的逻辑,按函数、类来切,而不是瞎切。
处理源代码(Python, JS, Java 等)。 专业,能把完整的函数或类打包在一起,不会把代码切碎。 挑食,只支持特定的编程语言,普通文本用不了。
SemanticChunker 按意思切
利用 AI 模型判断两句话“像不像”,意思变了就切一刀。
对检索质量要求极高的场景,比如复杂的知识库问答。 高质量,切出来的每一段都是一个完整的意思,检索效果最好。 贵且慢,因为要调用 AI 模型去理解全文,费钱又费时。
MarkdownHeaderTextSplitter 按标题切
专门识别 Markdown 的 # 号,把每个章节单独切出来。
结构化文档,比如 GitHub 的 README 文件、技术文档。 有结构,能保留文档的层级关系,知道这段话属于哪个标题。 挑食,只认 Markdown 格式,普通文本用不了。

首选万金油方案就是使用RecursiveCharacterTextSplitter 是LangChain默认推荐的,因为它在速度和语义之间取得了平衡。建议配置:chunk_size=1000, chunk_overlap=200 不过具体数值视模型上下文而定。如果还有比较特殊格式处理,像代码库问答那必须用 Language作为分割器.例如我用cursor写c#,他就是基于Tree-sitter来进行语法分

块,然后向量化,当用户询问某个函数的逻辑,他会把匹配的分块结果自行交给大模型推导语义无需 Roslyn 这类重型的编译器介入,不过这里不要误解Tree-sitter号称支持50+语言的语法分析。

这里再扩展一下,语义和语法的区别,这个之前学习roslyn时里面提到过,会解析语法树,好多api的意思,之前我也有点懵逼,现在搞清白了,语法就是长什么样,而语义就是代表“代码实际在做什么”

下面来用RecursiveCharacterTextSplitter 来进行分档分割,他有几个重点参数

1.chunk_size每个切块的token数量

2.chunk_overlap相邻2个块重复的token数,就是重叠分割的意思,重叠几个字符,看上面的图就能明白,假设一个数字一个token 。

# 导入 PDF 加载器模块
from langchain_community.document_loaders import PyPDFLoader

# 导入递归字符文本分割器模块
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1. 加载 PDF 文档
# 使用 PyPDFLoader 初始化加载器,指定文件路径为 '财务管理文档.pdf'
loader = PyPDFLoader('葵花宝典完整版.pdf')

# 调用 load_and_split() 方法加载文档并按页进行初步分割,返回一个包含 Document 对象的列表
pages = loader.load_and_split()

# 2. 初始化文本分割器
# 创建 RecursiveCharacterTextSplitter 实例,用于将长文本切分成小块
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,      # 每个文本块的最大字符数设置为 200
    chunk_overlap=100,   # 文本块之间的重叠字符数设置为 100,以保持上下文连贯
    length_function=len  # 使用内置的 len 函数来计算文本长度(按字符数计算)
)

# 3. 数据清洗与提取
# 遍历 pages 列表,提取每页的 page_content 内容,并使用 replace 方法去除所有的换行符(\n)和空格
# 如果 pages 不为空则执行列表推导式,否则 data 被赋值为空列表 []
data = [page.page_content.replace('\n','').replace(' ','') for page in pages ] if pages else []

# 4. 执行文本切分
# 使用 text_splitter 将清洗后的纯文本列表 (data) 转换为 Document 对象列表
result = text_splitter.create_documents(data)

# 5. 打印结果
print(result) # 打印整个 result 列表,查看对象概览

# 6. 遍历并输出每个文本块的详细信息
for page in result:
    # 打印每个文本块的具体内容和其对应的字符长度
    print(page.page_content, len(page.page_content))

这个网站可以可视化展示文本如何分割

image

3.文本向量化模型封装

我们已经介绍了对源数据进行切割,那么这一环就是对我们已经切割的文档进行向量化,LangChain对文本向量化模型的接口做了封装,OpenAI, Cohere, Hugging Face等。

向量化模型的封装提供了两种接口,一种针对文档的向量化embed_documents,一种针对句子的向量化embed_query。我们还是用听得懂的来理解 抽象了一个接口2个方法,多态OpenAI, Cohere, Hugging Face

至于使用哪一种,就需要自己来选型了,学习演示就使用百炼的和Huggingface,如果不熟悉Huggingface的,这里说一下,你就理解为大模型界的github就可以了。

百炼向量模型和本地bge-large-zh-v1.5

import os
from dotenv import load_dotenv
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_huggingface import HuggingFaceEmbeddings


data =[
        "元旦:1月1日(周四)至3日(周六)放假调休,共3天。1月4日(周日)上班。",
        "春节:2月15日(农历腊月二十八、周日)至23日(农历正月初七、周一)放假调休,共9天。2月14日(周六)、2月28日(周六)上班",
        "清明节:4月4日(周六)至6日(周一)放假,共3天。",
        "劳动节:5月1日(周五)至5日(周二)放假调休,共5天。5月9日(周六)上班。",
        "端午节:6月19日(周五)至21日(周日)放假,共3天。"
    ]

# 加载 .env 文件中的环境变量到系统环境中,从环境变量中获取名为 "QW_KEY" 的 API 密钥
load_dotenv()
api_key = os.getenv("QW_KEY")
# 初始化 DashScope 的 Embeddings 模型,传入 API 密钥并指定模型为 "text-embedding-v3"
bl_embeddings_model = DashScopeEmbeddings(dashscope_api_key=api_key, model="text-embedding-v3")

# 调用模型的 embed_documents 方法,将一组文档(字符串列表)批量转换为向量(Embeddings)
bl_embeddings = bl_.embed_documents(data)

# 打印向量列表的总长度
print(len(bl_embeddings ), len(bl_embeddings [0]), len(bl_embeddings [1]))

# 将用户的提问(Query)也转换为相同维度的向量,以便进行相似度匹配。
bl_query_text = "劳动节放假几天?"
bl_query_embedding = bl_embeddings_model .embed_query(query_text)


#-------------------------------------------------------
#本地bge-large-zh-v1.5
#-------------------------------------------------------

指定本地 HuggingFace 模型的路径,配置编码参数:将生成的嵌入向量进行归一化处理,归一化后的向量在计算余弦相似度时会更准确、更高效
model_name = '/Users/yuxl/3.Resources/Demo/llm/embdding/bge-large-zhv15/BAAI/bge-large-zh-v1___5'
encode_kwargs = {'normalize_embeddings': True}
hf_embeddings_model = HuggingFaceEmbeddings(
    model_name=model_name,
    encode_kwargs=encode_kwargs
)
hf_embeddings = hf_embeddings_model .embed_documents(data)

# 将用户的提问(Query)也转换为相同维度的向量,以便进行相似度匹配。
hf_query_text = "劳动节放假几天?"
hf_query_embedding = hf_embeddings_model .embed_query(query_text)

4.向量存储

文档加载、切割、向量化已经完成,那么接下来就需要把向量存起来了,如何存储呢?

使用向量数据库,常用的向量数据库有Chroma、Milvus、FAISS、Qdrant,在本地练习使用Chroma,甚至如果你是中小规模 RAG 应用、个人项目都可以使用它,因为Chroma 的设计非常符合 Python的开发习惯,支持内存模式和持久化模式,几行代码即可完成向量存储与检索,参考下面的例子

import os
from dotenv import load_dotenv

from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1.加载 .env 文件中的环境变量
load_dotenv()
# 1. 加载并拆分 PDF 文档
loader = PyPDFLoader('葵花宝典.pdf')
pages = loader.load_and_split()

# 2. 初始化文本分割器(设置块大小与重叠字符数)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=100,
    length_function=len,
    add_start_index=True
)

# 清洗文本数据:去除换行符和空格,并分割为独立的段落文档
data = [page.page_content.replace('\n', '').replace(' ', '') for page in pages] if pages else []
paragraphs = text_splitter.create_documents(data)

# 3. 初始化阿里云 DashScope 向量嵌入模型
embeddings = DashScopeEmbeddings(dashscope_api_key=os.getenv("QW_KEY"), model='text-embedding-v2')
# 将处理好的段落转化为向量并存入 Chroma 本地向量数据库
db = Chroma.from_documents(paragraphs, embeddings)

# 4. 定义查询问题,并在向量库中进行相似度检索
query = "欲练此功的下一句是什么?"
docs = db.similarity_search(query,k =2)

# 打印检索到的相关文档内容
for doc in docs:
    print(doc)

5.Retrievers 检索器

先看下面这一段代码,上面的就是直接在向量数据库查询,但是需要把问题向量化,再去搜索,但是用检索器这里语法上就不一样,然后也不需要写代码把问题向量化


# 定义查询问题,并在向量库中进行相似度检索
query = "欲练此功的下一句是什么?"
docs = db.similarity_search(query,k =2)

#实例化一个检索器
retriever = db.as_retriever(search_kwargs={"k": 1})
docs = retriever.get_relevant_documents("欲练此功的下一句是什么?")

其实乍一看还是很懵的,什么是检索器?他和直接向量查询有什么关系?后面看了些资料,用自己理解的大白话来搞明白检索器(Retriever)和直接查询向量数据库(Vector Store)到底有什么区别?

1.向量数据库(Vector Store) 就像一个巨大的仓库。里面堆满了各种零件 = 数据向量,它只负责把零件存好,而且能精准地告诉你某个零件在哪个货架上哪个柜子里头。

2.检索器(Retriever) 就像这个仓库里的管理员。我们不需要知道零件在哪个货架,只需要把的需求(我想组装一台电脑)告诉他,他就会跑进仓库,帮你把最合适的零件挑出来,打包好直接交出来。

可以看出核心区别就是职责不同,一个是仓库,一个是仓库管理员,向量数据库它的核心能力就是存向量和做相似度计算。它只能搜自己库里有的东西。但是检索器非常通用,不仅仅限于向量数据库。除了到向量库里头捞数据,还可以去维基百科搜、去谷歌搜、甚至去公司的 SQL 数据库里查表格。还有就是数据库通常是给多少拿多少。你设了找5条,它就很死板

地把最像的5条给你,但是检索器如果加上一些策略,他会帮你筛选掉重复的,挑出比较代表性内容多样的文档。

生产中的主流检索器类型

1.向量检索器 (Vector Retriever / Semantic Search)

基于语义相似度。它不纠结字面是否完全一样,而是理解意思。比如你搜么样修电脑,它能找到计算机故障排除说明书

2.关键词检索器 (Keyword / Sparse Retriever)

基于传统的文本匹配。严格匹配你输入的词是否在文档中出现过。特点就是非常精准,特别适合查找专有名词、产品型号、订单号或特定的术语,但理解不了语义。

3.混合检索器 (Hybrid Retriever)

这种就是目前企业生产中的标准。它将向量检索和关键词检索结合起来,取长补短。一般会配合一个重排序器(Reranker),先把两路搜到的结果汇总,再按相关性重新打分排序。既能听懂人话,又能精准匹配关键词,准确率最高。

4.多文档/代理检索器 (Multi-Query / Agent Retriever)

当你问的问题比较麻烦复杂时,它会自动把问题拆解或改写成多个不同角度的问题,分别拿去检索,最后把结果合并去重。特别适合处理复杂、宽泛的查询,能搜出更多维度的信息。

向量检索负责听懂意图,关键词检索负责精准确认结果,所以生产系统混合检索(向量+关键词) 是目前解决既要精准又要智能的最好的方法。