首页 > 教程攻略 > ai资讯 >搭建RAG系统就这么简单:LangChain|RAG是什么?

搭建RAG系统就这么简单:LangChain|RAG是什么?

来源:互联网 时间:2026-08-17 14:22:23

RAG是什么

“RAG”(Retrieval-Augmented Generation)这个词,说白了就是“检索+生成”的组合拳。大模型虽然能说会道,但总有点“记忆力不好、信息过时”的毛病。RAG恰好能补上这块短板——它让模型在回答之前,先去外部知识库里翻一翻资料。那么,具体能带来哪些好处?

  • 知识更丰富:

    模型不再是闭卷考试,而是开卷查资料,答案自然更准、更深。
  • 信息够实时:

    大模型训练的数据可能是一两年前的,但RAG可以实时拉取最新内容,永远不过时。
  • 减少偏见与错误:

    检索的是可靠源,相当于给模型请了个“质检员”,胡说八道的概率大大降低。
  • 泛化能力更强:

    遇到没见过的问题,RAG也能临时翻书找答案,而不是瞎编。
  • 长尾问题有救:

    那些冷门、低频的问题,通过检索也能给出靠谱回复,不再指望训练数据里恰好覆盖到。

简而言之,RAG让大模型更聪明、更靠谱,而且随着技术演进,它的应用场景只会越来越广。

一个基础的RAG任务,大致包含这几个模块:数据读取与处理、索引构建、检索、prompt拼接、大模型推理。下面这幅图能帮你快速建立整体印象(图片位置同上,不再重复)。

环境搭建

动手之前,先把需要的工具装上。这里我们用到的包都在下面了,直接一行命令搞定:

pip install langchain_community tiktoken langchain-openai langchainhub chromadb langchain

数据读取

数据从哪来?这里用 WebBaseLoader,它本质上是urllib拉取网页HTML,再丢给BeautifulSoup解析出正文。设置好三个东方财富研报的URL,指定只保留标题和正文部分的class,就能把干净文本提取出来:

import bs4
from langchain_community.document_loaders import WebBaseLoader

loader = WebBaseLoader(
    web_paths=(
        "https://data.eastmoney.com/report/zw_stock.jshtml?encodeUrl=35LdZWW1ERIe7AWLlyVZFHptPNDUH2qN4gEfzUIhYsc=",
        "https://data.eastmoney.com/report/zw_stock.jshtml?encodeUrl=OPw8X34UDWQq6g0u70KgHW6e5Ad8C5kc3TYV6t9BZsw=",
        "https://data.eastmoney.com/report/zw_stock.jshtml?encodeUrl=OPw8X34UDWQq6g0u70KgHbx8/qX6gdD4f6j3/4IEWIA=",
    ),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(class_=("detail-header", "newsContent"))
    ),
)
blog_docs = loader.load()

文本切块

文档太长没法直接喂给模型,得切成小段。这里用 RecursiveCharacterTextSplitter,它很聪明——会按着换行符、句号这些自然分隔点递归切分,直到每块大小合适。我们设每块512字符,块之间重叠128字符。重叠的好处是:前后文的逻辑能被保留下来,不会丢三落四。

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=512, chunk_overlap=128
)
splits = text_splitter.split_documents(blog_docs)

创建索引(Indexing)

切好的文本得转成向量才能被快速检索。这里先用OpenAI的Embeddings模型(你当然可以换成别的,后续会聊怎么选),然后存进Chroma向量数据库:

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

vectorstore = Chroma.from_documents(
    documents=splits,
    embedding=OpenAIEmbeddings()
)

创建检索器

索引建好了,我们还需要一个检索器来实际“翻箱倒柜”。这里用余弦相似度搜索,每次返回最相关的6个片段。注意:检索召回的质量直接决定了整个系统的上限,这一环非常关键。

retriever = vectorstore.as_retriever(
    search_type="similarity", search_kwargs={"k": 6}
)

# 测试一下:看看检索到的片段合不合格
retrieved_docs = retriever.invoke("东方财富营收是多少")
len(retrieved_docs)

创建模型

两块东西要准备好:一个是prompt模板,一个是大模型本身。prompt模板我们可以从LangChain Hub里直接拉一个经典的RAG模板,当然你也可以根据任务手写定制。大模型这里用gpt-3.5-turbo,温度设0.01让回答更稳定——如果你要换其他模型,参考之前的文章即可。

from langchain import hub
from langchain_openai import ChatOpenAI

prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.01)

RAG生成流程

前面砖都码好了,现在把它们串成一个完整的链条。先把检索出来的文档片段合并成一段文字(用换行隔开),然后和用户问题一起塞进prompt,再喂给大模型,最后把输出解析成字符串。整个过程用LangChain的表达式语言写出来非常清晰:

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

def format_docs(docs):
    return "

".join(doc.page_content for doc in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

for chunk in rag_chain.stream("东方财富的营收是多少"):
    print(chunk, end="", flush=True)

到这里,一个简单的RAG系统就搭好了。你只需要换换prompt,就能让这个系统做问答、写总结,甚至搞创作——有了知识库的辅助,大模型输出的准确性会远超裸模型。别小看这个基础框架,后续的优化(高级检索策略、多模态、路由等等)都是在这个骨架上长出来的。先从跑通第一个demo开始吧。