下面代码是一个可用的 LangChain + 阿里云通义千问 RAG 最小示例。其逻辑非常清晰,就是:加载 → 切分 → 向量化 → 检索 → QA。
https://item.jd.com/15261772.html
# -*- coding: utf-8 -*- """ Created on Thu Jul 24 21:03:45 2025 @author: liguo """ from langchain_community.document_loaders import TextLoader from langchain_community.indexes import VectorstoreIndexCreator from langchain_text_splitters import CharacterTextSplitter from langchain_community.embeddings import DashScopeEmbeddings # 👈 替换 QwenEmbeddings from langchain_community.vectorstores import Chroma from langchain.chains import RetrievalQA from langchain_community.llms import Tongyi # Qwen import os # 设置阿里云 DashScope API Key(必须) api_key=os.getenv("DASHSCOPE_API_KEY") # 👈 替换为你自己的 API Key def basic_rag_flow(): # 1. 加载文档 —— 修复编码问题 loader = TextLoader("example.txt", encoding='utf-8') documents = loader.load() # 2. 分割文档 text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) texts = text_splitter.split_documents(documents) # 3. 创建嵌入和向量存储(使用通义千问的 Embedding 模型) embeddings = DashScopeEmbeddings( model="text-embedding-v1", # 阿里云提供的嵌入模型 dashscope_api_key=os.environ["DASHSCOPE_API_KEY"] ) vectorstore = Chroma.from_documents(texts, embeddings) # 4. 构建检索器 retriever = vectorstore.as_retriever() # 5. 创建RAG链(使用通义千问大模型) llm = Tongyi( model_name="qwen-max", # 也可以用 "qwen-plus", "qwen-turbo" 等 api_key=api_key, temperature=0.1 ) qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=retriever, return_source_documents=True # 可选:返回参考文档 ) # 6. 执行查询并输出结果 query = "请总结文档的主要内容" result = qa_chain.invoke({"query": query}) # 👈 注意:新版推荐用 invoke print("问题:", query) print("回答:", result["result"]) # 可选:打印参考文档 # for doc in result["source_documents"]: # print("参考文档片段:", doc.page_content[:200], "...") return qa_chain # 调用函数以执行流程 if __name__ == "__main__": basic_rag_flow()下面我按模块 + 按流程对你给出的代码做一次完整解析,并明确说明:
👉这个示例到底在演示什么?
👉每一步解决了什么问题?
一、这个示例整体在演示什么?
✅这是一个“最小可运行的 RAG(检索增强生成)示例”
它演示了如何用LangChain + 阿里云通义千问(Qwen) 完成:
“基于本地文档内容回答问题”
也就是:
📄 本地文本文件
⬇
🔍 向量检索
⬇
🤖 大模型生成答案
这正是RAG 的核心流程。
二、RAG 的核心思想(先看这个)
RAG =Retrieval-Augmented Generation
用户问题 ↓ 从文档中检索相关内容 ↓ 把相关内容交给大模型 ↓ 生成基于事实的回答✅ 目的:
减少大模型幻觉
利用私有数据
不依赖模型训练
三、代码结构总览
basic_rag_flow() ├─ 1. 加载文档 ├─ 2. 切分文档 ├─ 3. 向量化 + 存入向量库 ├─ 4. 构建检索器 ├─ 5. 构建 RAG 问答链 └─ 6. 执行查询四、逐段代码解析
✅ 1️⃣ 导入依赖(基础设施)
from langchain_community.document_loaders import TextLoader from langchain_community.indexes import VectorstoreIndexCreator from langchain_text_splitters import CharacterTextSplitter from langchain_community.embeddings import DashScopeEmbeddings from langchain_community.vectorstores import Chroma from langchain.chains import RetrievalQA from langchain_community.llms import Tongyi📌 这些模块分别对应:
模块 | 作用 |
|---|---|
TextLoader | 读取本地文本 |
CharacterTextSplitter | 文本切分成块 |
DashScopeEmbeddings | 阿里云向量模型 |
Chroma | 向量数据库 |
RetrievalQA | RAG 问答链 |
Tongyi | 通义千问 LLM |
✅ 2️⃣ 加载文档(数据来源)
loader = TextLoader("example.txt", encoding='utf-8') documents = loader.load()📌 这一步在做什么?
从本地加载
example.txt返回一个
Document对象列表每个 Document 包含:
page_content = 文本内容 metadata = {"source": "example.txt"}
✅ 这是RAG 的数据入口
✅ 3️⃣ 文本切分(非常关键)
text_splitter = CharacterTextSplitter( chunk_size=1000, chunk_overlap=0 ) texts = text_splitter.split_documents(documents)📌 为什么一定要切分?
Embedding 模型有长度限制
向量检索更适合“小块语义”
LLM 上下文有限
📌 切分后变成:
texts = [ Document(...), Document(...), Document(...) ]每一段都是一个可独立检索的语义单元
✅ 4️⃣ 向量化 & 向量库(检索基础)
embeddings = DashScopeEmbeddings( model="text-embedding-v1", dashscope_api_key=os.environ["DASHSCOPE_API_KEY"] )📌 这一步在做什么?
把文本 → 向量(数字)
使用的是阿里云的
text-embedding-v1
vectorstore = Chroma.from_documents(texts, embeddings)📌 Chroma 做了什么?
把所有文本块存成向量
建立索引
支持相似度搜索
✅ 到这里,你已经拥有了一个“可检索的知识库”
✅ 5️⃣ 构建检索器(Retriever)
retriever = vectorstore.as_retriever()📌 Retriever 的作用:
给定一个问题 → 返回最相关的文档片段
等价于:
问题 → 向量化 → 相似度匹配 → Top-K 文档✅ 6️⃣ 构建 RAG 问答链(核心)
llm = Tongyi( model_name="qwen-max", api_key=api_key, temperature=0.1 )📌 LLM 负责:
理解问题
阅读检索到的文档
生成最终答案
qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=retriever, return_source_documents=True )📌RetrievalQA做了什么?
自动完成这个流程:
用户输入问题 ↓ Retriever 找相关文档 ↓ 把问题和文档拼在一起 ↓ LLM 生成答案📌chain_type="stuff"的含义:
把所有检索到的文档直接塞进 prompt
简单、直观
适合文档不太长的场景
✅ 7️⃣ 执行查询
query = "请总结文档的主要内容" result = qa_chain.invoke({"query": query})📌 实际发生了什么?
问题 → embedding
去 Chroma 里找相关内容
拼接成类似这样的 prompt:
根据以下内容回答问题: [文档片段1] [文档片段2] 问题:请总结文档的主要内容Qwen 生成答案
五、这个示例“演示了什么能力”?
✅ 它不是一个玩具,而是一个标准 RAG 模板,展示了:
能力 | 是否演示 |
|---|---|
私有数据接入 | ✅ |
文本向量化 | ✅ |
向量检索 | ✅ |
大模型增强生成 | ✅ |
LangChain 标准用法 | ✅ |
阿里云通义千问集成 | ✅ |
六、一句话总结
这个示例演示了:如何使用 LangChain + 阿里云 DashScope,构建一个基于本地文档的检索增强生成(RAG)问答系统。