RAG检索

  |   0 评论   |   0 浏览

你将学会: 文档切块 → 放入向量库 → 检索 → 交给模型回答。
前置: L01、L02。

模型训练截止日期之后的公司文档,它不会「知道」。RAG = 回答前先检索你提供的文本。

检索工作台

管道

先跑假向量把管道跑通(不需要百炼 key)。语义真正准,再换成 embedding API。

1. 只切分(不需要 API key)

from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter

raw = """LangChain 的入口是 create_agent,负责模型加工具循环。
LangGraph 用 StateGraph 编排节点和边,支持 checkpoint。
Deep Agents 预装虚拟文件系统和子代理,适合长任务。
"""
docs = [Document(page_content=raw, metadata={"source": "notes.txt"})]
splitter = RecursiveCharacterTextSplitter(chunk_size=40, chunk_overlap=8, add_start_index=True)
for i, c in enumerate(splitter.split_documents(docs)):
    print(i, c.metadata.get("start_index"), repr(c.page_content))

2. 检索 + 生成(需要 DeepSeek)

FakeEmbeddings 不是语义检索,只验证形状。问「checkpoint」不一定命中 LangGraph 那句。换真 embedding 后才会按意思找。

from dotenv import load_dotenv

load_dotenv()

from langchain.chat_models import init_chat_model
from langchain_core.documents import Document
from langchain_core.embeddings import FakeEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_text_splitters import RecursiveCharacterTextSplitter

model = init_chat_model(
    "deepseek:deepseek-chat",
    temperature=0.5,
    max_tokens=2500,
    timeout=300,
    max_retries=6,
)

docs = [
    Document(page_content="请假流程:提前在 OA 提交,直属领导审批,HR 备案。"),
    Document(page_content="报销需要电子发票,金额超过 1000 元要总监加签。"),
    Document(page_content="笔记本电脑每 3 年可申请更换,找 IT 工单。"),
]
chunks = RecursiveCharacterTextSplitter(chunk_size=80, chunk_overlap=0).split_documents(docs)
store = InMemoryVectorStore(embedding=FakeEmbeddings(size=64))
store.add_documents(chunks)

question = "报销一千块以上要找谁?"
hits = store.similarity_search(question, k=2)
context = "\n".join(h.page_content for h in hits)
print("检索到 =>", [h.page_content for h in hits])
print("回答 =>", model.invoke(
    f"只根据资料回答,资料没有就说不知道。\n资料:\n{context}\n\n问题:{question}"
).content)

真语义搜索:仓库 05-RAG与检索/Document-pipeline文档管道.pyBAILIAN_API_KEY)。

上面是 2-Step RAG:你规定「先检索再生成」。生产里更常见的是 Agentic RAG:把检索做成工具,让 agent 自己决定何时查。

3. 检索挂成工具(需要 DeepSeek)

from dotenv import load_dotenv

load_dotenv()

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool
from langchain_core.documents import Document
from langchain_core.embeddings import FakeEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore

model = init_chat_model(
    "deepseek:deepseek-chat",
    temperature=0.5,
    max_tokens=2500,
    timeout=300,
    max_retries=6,
)

store = InMemoryVectorStore(embedding=FakeEmbeddings(size=64))
store.add_documents([
    Document(page_content="请假流程:提前在 OA 提交,直属领导审批,HR 备案。"),
    Document(page_content="报销需要电子发票,金额超过 1000 元要总监加签。"),
    Document(page_content="笔记本电脑每 3 年可申请更换,找 IT 工单。"),
])


@tool
def search_notes(query: str) -> str:
    """在公司制度里检索。问请假、报销、换电脑时必须调用。"""
    print(f"[检索] {query}", flush=True)
    hits = store.similarity_search(query, k=3)
    return "\n".join(h.page_content for h in hits) or "没有检索到。"


agent = create_agent(
    model=model,
    tools=[search_notes],
    system_prompt="制度问题必须先 search_notes。资料没有就说不知道。不要编造。",
)
print(agent.invoke({
    "messages": [{"role": "user", "content": "报销超过一千要找谁?"}]
})["messages"][-1].content)

终端应出现 [检索] ...。L13 综合项目就是在这一段上加记忆和测试。

练习

  1. 把三句资料改成你自己的笔记,问一个只有笔记里才有的问题。
  2. 问一个资料里没有的问题,确认模型按提示说「不知道」(系统提示已经写了)。

本章验收

  •  能画出 Loader → Splitter → Embedding → VectorStore → LLM
  •  亲手跑通「检索到的片段进 prompt」
  •  能把检索挂成 @tool,并在日志里看到它被调用
  •  知道 FakeEmbeddings 不能当生产检索

对照仓库:05-RAG与检索/Retrieval检索.pyDocument-pipeline文档管道.py

下一课:中间件与护栏


标题:RAG检索
作者:llp
地址:https://llinp.cn/articles/2026/08/23/1787492918339.html