Appearance
LangChain基础
LangChain是一个强大的框架,用于构建基于大语言模型的应用程序,特别适合实现RAG系统。本章节将详细介绍LangChain 1.2版本的核心概念、组件和使用方法,帮助你快速上手构建RAG应用。
1. LangChain核心概念
组件(Components)
- LLMs:大语言模型,如OpenAI GPT、Claude等
- Embeddings:嵌入模型,用于将文本转换为向量
- Document Loaders:文档加载器,用于从各种源加载文档
- Text Splitters:文本分割器,用于将长文本分割成小块
- Vector Stores:向量存储,用于存储和检索向量
- Retrievers:检索器,用于从向量存储中检索相关文档
- Chains:链,用于组合多个组件
- Agents:代理,用于基于用户输入做出决策
工作流(Workflows)
- 数据加载:使用Document Loaders加载文档
- 文本分割:使用Text Splitters分割文本
- 向量存储:使用Embeddings将文本转换为向量并存储
- 检索:使用Retrievers检索相关文档
- 生成:使用LLMs基于检索结果生成回答
2. 安装与配置
安装LangChain
bash
pip install langchain==1.2.0安装依赖
bash
# 安装OpenAI依赖(如果使用OpenAI模型)
pip install openai
# 安装Hugging Face依赖(如果使用Hugging Face模型)
pip install transformers sentence-transformers
# 安装向量数据库依赖(根据选择)
pip install chromadb # 轻量级向量数据库
# 或 pip install pinecone-client # 托管向量数据库
# 安装文档加载器依赖
pip install pypdf python-docx
# 安装环境变量管理
pip install python-dotenv配置API密钥
python
from dotenv import load_dotenv
import os
# 加载.env文件
load_dotenv()
# 设置API密钥
os.environ["OPENAI_API_KEY"] = "your-api-key"3. 文档处理
加载文档
python
from langchain.document_loaders import TextLoader, PyPDFLoader, DirectoryLoader
# 加载文本文件
loader = TextLoader("document.txt")
documents = loader.load()
# 加载PDF文件
pdf_loader = PyPDFLoader("document.pdf")
pdf_documents = pdf_loader.load()
# 加载整个目录
dir_loader = DirectoryLoader(
"./docs",
glob="**/*.txt",
loader_cls=TextLoader
)
dir_documents = dir_loader.load()分割文档
python
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 创建文本分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 每个块的大小
chunk_overlap=200, # 重叠大小
length_function=len,
)
# 分割文档
chunks = text_splitter.split_documents(documents)
print(f"分割成 {len(chunks)} 个块")4. 向量存储与检索
创建向量存储
python
from langchain.embeddings import OpenAIEmbeddings, HuggingFaceEmbeddings
from langchain.vectorstores import Chroma, FAISS
# 选择嵌入模型
# embeddings = OpenAIEmbeddings()
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 创建Chroma向量存储
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 或使用FAISS
# vectorstore = FAISS.from_documents(documents=chunks, embedding=embeddings)相似度搜索
python
# 直接搜索
results = vectorstore.similarity_search("什么是RAG?", k=3)
for doc in results:
print(doc.page_content)
print("---")
# 带分数的搜索
results_with_scores = vectorstore.similarity_search_with_score("什么是RAG?", k=3)
for doc, score in results_with_scores:
print(f"分数: {score}")
print(doc.page_content)
print("---")5. 构建RAG链
基础RAG链
python
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 创建RAG链
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
# 执行查询
result = qa_chain({"query": "什么是RAG技术?"})
print(result["result"])
print("\n来源文档:")
for doc in result["source_documents"]:
print(f"- {doc.metadata.get('source', 'Unknown')}")自定义提示模板
python
from langchain.prompts import PromptTemplate
# 创建自定义提示模板
custom_prompt = PromptTemplate(
template="""基于以下上下文回答问题。如果无法从上下文中找到答案,请说"我不知道"。
上下文:
{context}
问题:{question}
请提供详细且准确的回答:""",
input_variables=["context", "question"]
)
# 使用自定义提示创建链
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": custom_prompt}
)6. 高级链类型
Map-Reduce链
适用于大量文档的场景:
python
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="map_reduce",
retriever=retriever
)Refine链
迭代优化回答:
python
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="refine",
retriever=retriever
)7. 完整示例
python
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
class RAGSystem:
def __init__(self):
self.embeddings = HuggingFaceEmbeddings()
self.vectorstore = None
self.qa_chain = None
def load_documents(self, file_path):
"""加载文档"""
loader = TextLoader(file_path)
documents = loader.load()
# 分割文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
chunks = text_splitter.split_documents(documents)
# 创建向量存储
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings
)
# 创建RAG链
retriever = self.vectorstore.as_retriever(search_kwargs={"k": 3})
self.qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
print(f"已加载 {len(chunks)} 个文档块")
def query(self, question):
"""查询"""
if not self.qa_chain:
raise ValueError("请先加载文档")
result = self.qa_chain({"query": question})
return {
"answer": result["result"],
"sources": [doc.metadata.get('source', 'Unknown')
for doc in result["source_documents"]]
}
# 使用示例
rag = RAGSystem()
rag.load_documents("knowledge_base.txt")
response = rag.query("什么是RAG技术?")
print(response["answer"])8. 调试与监控
查看检索结果
python
# 启用详细输出
qa_chain.verbose = True
# 或者手动检查检索结果
retriever = vectorstore.as_retriever()
retrieved_docs = retriever.get_relevant_documents("查询")
for i, doc in enumerate(retrieved_docs):
print(f"文档 {i+1}:")
print(doc.page_content[:200])
print("---")回调函数
python
from langchain.callbacks import StdOutCallbackHandler
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="stuff",
retriever=retriever,
callbacks=[StdOutCallbackHandler()]
)