【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)

相关推荐
新知图书1 小时前
8.1 智能体的心跳执行模式:以定时器为核心(智能体工程)
人工智能·agent·ai agent·智能体
墨心@1 小时前
阶段 4:事件总线
人工智能·语言模型·大语言模型·agent·codex·harness
前端开发江鸟1 小时前
学完 Agent 开发基础后,我准备把它真正用在文字创作里
agent
Smoothcloud_润云1 小时前
从“模型服务”到“Agent 调度”:AI 推理基础设施为什么正在重构?
llm·agent·gpu
安逸sgr2 小时前
卷积神经网络 CNN 是什么?为什么适合处理图像?
人工智能·ai·大模型·agent·智能体
ShallJason2 小时前
Java与Python MCP跨语言调用中的时间序列化问题:根因剖析与完整解决方案
agent
墨雨晨曦882 小时前
2026/08/16 AI学习笔记
笔记·学习
心再无旁骛2 小时前
anywhere-labs/deepseek-harness-desktop 如何围绕上游演进:Submodule、版本溯源与非 Fork 架构
agent
用户3126874877202 小时前
一条 Prompt 就能劫持你的 Agent!OWASP Agentic Top 10 与零信任防御实战
agent