【agent篇】RAG 知识库构建避坑指南

组件 作用 常用选择
Document Loader 加载原始文档 MinerU, Docling
Text Splitter 切分文档为 chunk RecursiveCharacterTextSplitter
Embeddings 文本转向量 DashScopeEmbeddings, BGE-M3, qwen3-embedding:0.6b
Vector Store 存储和检索向量 InMemory(开发), Chroma(中小), Milvus(大规模)
Retriever 标准检索接口 vectorstore.as_retriever()

一.文档加载(Document Loaders)

1.1 工作目录有示例文件却无法解析

python 复制代码
#原代码


Document_loaders/sample.txt      #--- 相对路径,依赖工作目录

相对路径 Document_loaders/sample.txt 解析的起点是当前工作目录(cwd),不是脚本所在目录。

实际解析:D:\python\project\Rag\Document_loaders\sample.txt ← 这个目录不存在

python 复制代码
#修改
# 基于脚本所在目录构建路径,避免工作目录不同导致 FileNotFoundError


BASE_DIR = Path(__file__).parent
SAMPLE_PATH = BASE_DIR / "sample.txt"

langchain-community 正在被废弃,LangChain 官方不再维护它,正在把各功能拆成独立的包。

1.2 为什么执行CSVLoader的时候应输出内容不是sample.txt,而是新创建了SAMPLE_PATH?

python 复制代码
#原代码


with open("SAMPLE_PATH","w",...)   # ← 传的是字符串 "SAMPLE_PATH",不是变量 SAMPLE_PATH
loader = CSVLoader(file_path="SAMPLE_PATH", ...)  # ← 同样的错误

给 SAMPLE_PATH 加了引号,所以 Python 把它当成一个字面量文件名字符串 "SAMPLE_PATH",而不是第 7 行定义的 Path 变量 SAMPLE_PATH(指向 sample.txt)。

python 复制代码
#修改后


with open(SAMPLE_PATH,"w",...)   
loader = CSVLoader(file_path=str(SAMPLE_PATH), ...) 

1.3 Flash和Precision对比

本质区别

两种模式的根本差异在于服务端处理深度:

Flash 是轻量同步接口------直接抽取文本,公式/表格用正则快速识别,不做版面分析和图片提取,所以秒级返回但只产出纯 Markdown

Precision 是异步任务接口------提交后进入队列,服务端用 VLM 模型做完整版面分析(标题层级、阅读顺序、图片定位、公式 LaTeX 化、表格 HTML 化),轮询完成后返回全量结果

1.4 SDK,langchain,OCR对比

MinerU注册地址https://mineru.net/

.env中格式:MINERU_TOKEN = 你的密钥。

注:MinerU不收费

二.文本切分(Text Splitters)

2.1 结构感知切分类名搞混

|----|---------------------------------------------------------------|----------------------------------------|
| 类 | MarkdownTextSplitter | MarkdownHeaderTextSplitter |
| 作用 | 按字符数切分(和 RecursiveCharacterTextSplitter 类似,只是自带 Markdown 分隔符) | 按 Markdown 标题层级切分,将标题信息写入 metadata |
| 参数 | 不接收 headers_to_split_on | 接收 headers_to_split_on=(关键字参数) |

2.2 五种常用 LangChain 文本切分方式对比

方法 切分单位 分隔符策略 保留结构 适用场景
CharacterTextSplitter 字符数 单一分隔符(如 \n) 在分隔符处切分 简单文本,行边界明确
RecursiveCharacterTextSplitter 字符数 多级分隔符依次尝试 \n\n → \n → . → 空格 通用文本,RAG 首选
.from_tiktoken_encoder() Token 数 先按分隔符尝试 再按 token 计数对齐 需精确控制 LLM token 用量
MarkdownHeaderTextSplitter 文档结构 按标题层级切分 # / ## / ### Markdown / 技术文档
代码切分 .from_language() 字符数 按语言语法切分 函数/类边界 部分 代码库文档

三. 向量化(Embeddings)

3.1 Ollama和DashScope对比

四. 向量库(Vector Stores)

4.1 md内容过少导致输出结果与想象的不一样

python 复制代码
recursive_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
)
4.1.1 相似度检索只查询第一页为什么两页内容同时输出

md 全文才 8 行、不到 400 字符,而 chunk_size=1000,所以 RecursiveCharacterTextSplitter 把整个文档切成1 个 chunk

解决:

  1. 减小 chunk_size,让两页分开。

  2. 换更有区分度的查询词。

4.1.2 基于metadatafilter 查的是 doc_2无任何数据输出

chunk_size=1000 只切出 1 个 chunkdoc_1)。你 filter 查的是 doc_2,库里根本不存在,所以空结果。

解决:缩小 chunk_size 让文档切成多块

4.2 similarity_search_with_relevance_scores检索成功后无分数

similarity_search_with_relevance_scores 是 LangChain VectorStore 的通用方法,Chroma 底层对 relevance score 的计算支持不稳定。

解决:换成 Chroma 原生的 similarity_search_with_score,直接返回原始距离分数

区别:

  • similarity_search_with_relevance_scores:LangChain 通用方法,底层依赖各 VectorStore 实现 _relevance_score 归一化函数,Chroma 对此支持不稳定,可能不返回分数
  • similarity_search_with_score:Chroma 原生方法,直接返回 L2 距离,一定有分数

Chroma 返回的是 L2 距离,值越小越相似

五.检索器(Retriever)

相关推荐
jimidou15 分钟前
子 Agent 能并行,却不能互相说话:Claude Code 里哪些活不该委派
agent·ai编程
DeepAgent16 分钟前
AI Agent 项目赏析:DeerFlow 2.0 —— 一个真正“长跑“的 SuperAgent 是怎么设计出来的?
github·agent
wuyk55526 分钟前
12.归并排序:分治思想的稳定排序算法
开发语言·数据结构·算法·排序算法
吴声子夜歌30 分钟前
ApacheCommons——commons-text(模板替换与文本算法)
java·开发语言·算法·apache
Haooog43 分钟前
Agent 开发中的 Memory:State、短期记忆、长期记忆与 Memory Retrieval
java·agent·memory
2601_9622946144 分钟前
Python接口自动化测试实战:使用requests库
python·接口自动化测试·异常处理·requests库·api测试
砚底藏山河1 小时前
【量化纯GET实战 #23】多股票相关性:用收益率看板块联动
java·数据库·python·金融·数据分析
阿童木写作1 小时前
跨境电商翻译工具推荐:批量图片翻译+视频字幕实时翻译
人工智能·python·音视频
晶捷软件1 小时前
晶捷智能:集团型制造企业ERP如何实现多工厂统一管控
大数据·人工智能·python·制造
oyguyteggytrrwwwrt1 小时前
闵可夫斯基差演示
python