LangChain RAG RAG(Retrieval-Augmented Generation,检索增强生成)让 AI 能够基于你的私有文档回答问题,不需要微调模型,只需将文档向量化存储,Agent 就能检索相关内容来回答。普通的大模型智能回答训练数据中有的内容,如果你的文档是私有的(公司内部文档、个人笔记),模型就不知道。RAG 解决了这个问题,其工作流程如下:
离线阶段:将文档切分成小块 -> 用 Embedding 模型转换为向量 -> 存入向量数据库。
在线阶段:用户提问 -> 将问题转为向量 -> 在向量数据库中搜索最相似内容 -> 将检索到的内容作为上下文发给模型 -> 模型基于检索内容回答
环境准备,打开终端输入如下命令
1 pip install langchain-deepseek langchain-chroma chromadb
接入 Embedding 模型 我们使用百炼的 API,初始化代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 from dotenv import load_dotenvimport osfrom langchain_community.embeddings import DashScopeEmbeddingsload_dotenv() def embedding_init (): api_key = os.getenv("BAILIAN_API_KEY" ) embeddings = DashScopeEmbeddings( model="qwen3.7-text-embedding" , dashscope_api_key=api_key, ) return embeddings
在主文件中写下如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from model_init import embedding_initembeddings = embedding_init() text = "菜鸟教程 RUNOOB 是一个编程学习平台" input = {"input" :f"{text} " }vector = embeddings.embed_query(text) print (f"文本: {text} " )print (f"向量维度: {len (vector)} " )print (f"向量前 5 个值: {vector[:5 ]} " )
使用 ChromaDB 创建持久化存储 示例代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from model_init import embedding_initfrom langchain_chroma import Chromaembeddings = embedding_init() vector_store = Chroma( collection_name="runoob_docs" , embedding_function=embeddings, persist_directory="./chroma_db" ) texts = [ "菜鸟教程(RUNOOB)是一个免费的编程学习网站,提供 HTML、CSS、JavaScript、Python 等教程。" , "Python3 基础教程共 30 章,适合零基础入门,包含环境搭建、语法基础、面向对象等内容。" , "HTML 基础教程共 25 章,覆盖 HTML 标签、表单、多媒体等基础知识。" , ] vector_store.add_texts(texts) print (f"已添加 {len (texts)} 个文档到向量存储" )
语义检索 使用 similarity_search 进行语义相近搜索:
1 2 3 4 results = vector_store.similarity_search( "我想学 Python,有什么教程推荐?" , k=2 , )
创建 Retriever 检索器 Retriever 是 Vector Store 的标准化接口:
1 2 3 4 5 6 7 8 9 10 retriever = vector_store.as_retriever( search_type="similarity" , search_kwargs={"k" : 3 }, ) docs = retriever.invoke("Python 学习路线" ) for doc in docs: print (f"- {doc.page_content[:60 ]} ..." )
LangChain 文本加载与切分 LangChain 提供了多种文档加载器,覆盖了常见的文件格式,如下:
Loader
来源
安装包
TextLoader
.txt
langchain
PyPDFLoader
PDF 文件
langchain-community + pypdf
WebBase
网页 URL
langchain-community + beautifulsoup4
CSVLoader
CSV 文件
langchain-community
UnstructuredMarkdownLoader
Markdown 文件
langchain-community + unstructured
示例代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from langchain_community.document_loaders import TextLoaderloader = TextLoader("knowledge.txt" , encoding="utf-8" ) docs = loader.load() print (f"加载了 {len (docs)} 个文档" )print (f"内容预览: {docs[0 ].page_content[:150 ]} ..." )from langchain_community.document_loaders import WebBaseLoaderloader = WebBaseLoader("https://www.runoob.com/python/python-tutorial.html" ) docs = loader.load() print (f"\n网页内容: {docs[0 ].page_content[:150 ]} ..." )
文档通常太长,需要切分成小块(chunk)才能有效检索。切分策略将直接影响 RAG 效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from langchain_text_splitters import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter( chunk_size=500 , chunk_overlap=50 , separators=["\n\n" , "\n" , "。" , "!" , "?" , ";" , "," , " " , "" ], ) long_text = """菜鸟教程(RUNOOB)是一个免费的编程学习平台。 平台提供了丰富的编程语言教程,包括但不限于: - Python 教程:从基础语法到数据分析 - Java 教程:面向对象编程到 Spring 框架 - 前端教程:HTML、CSS、JavaScript 及其框架 所有教程都配有详细的代码示例和在线运行环境。 学习者可以通过边学边练的方式快速掌握编程技能。""" chunks = text_splitter.split_text(long_text) print (f"原文长度: {len (long_text)} 字" )print (f"切分后: {len (chunks)} 块\n" )for i, chunk in enumerate (chunks): print (f"--- 块 {i+1 } ({len (chunk)} 字) ---" ) print (chunk) print ()
chunk_overlap 很重要。如果块之间没有重叠,一个完整的句子可能被切成两半,导致检索时遗漏关键信息。50-100 字符的重叠是常见的设置。
LangSmith LangSmith 是 LangChain 官方的可观测性平台,可以帮我我们追踪 Agent 的执行过程、监控性能以及调试问题。当 Agent 在后台运行时,我们看不到它内部发生了什么 ———— 调用了哪些模型、执行了哪些工具、每一步消耗了多少 Token。LangSmith 解决了这个”黑盒”问题。我们现在 .env 中写下如下内容:
1 2 3 4 # .env 文件 LANGCHAIN_TRACING_V2=true LANGCHAIN_API_KEY=lsv2_pt_your_key_here LANGCHAIN_PROJECT=my-agent-project
示例代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from dotenv import load_dotenvload_dotenv() from langchain.agents import create_agentfrom langchain.chat_models import init_chat_modelfrom langchain.messages import HumanMessagefrom langchain.tools import tool@tool def search_course (keyword: str ) -> str : """搜索课程""" return f"搜索结果:{keyword} 相关课程" model = init_chat_model("deepseek:deepseek-v4-flash" , temperature=0 ) agent = create_agent( model=model, tools=[search_course], system_prompt="你是菜鸟教程 RUNOOB 的助手。" , ) result = agent.invoke({ "messages" : [HumanMessage(content="搜索 Python 课程" )] }) print ("已完成,请到 LangSmith 控制台查看追踪详情" )
运行完成后,我们在 LangSmith 控制台中,可以看到每次 Agent 执行的完整轨迹:
执行时间线:模型调用 → 工具调用 → 模型再调用的完整时间线
输入/输出:每一步的输入消息和模型返回结果
Token 用量:每次模型调用的 Token 消耗和费用估算
延迟分析:每一步的耗时分布
错误信息:如果某步出错,可以看到完整的错误堆栈
如下图所示
图 1 层级图及追踪效果