RAG(Retrieval-Augmented Generation)技术已经成为当前大语言模型应用中的关键架构模式。作为一名长期从事AI应用开发的工程师,我在多个实际项目中验证了RAG方案的有效性。本文将基于LangChain 0.3.28框架,详细拆解RAG的核心实现流程,并通过完整案例演示如何构建一个可落地的Web内容问答系统。
注意:本文使用的LangChain版本为0.3.28,新版本中部分API路径已发生变化。建议通过
pip install langchain==0.3.28指定版本安装。
典型的RAG系统包含以下核心组件:
mermaid复制graph TD
A[原始文档] --> B[文档加载]
B --> C[文本分割]
C --> D[向量嵌入]
D --> E[向量存储]
E --> F[用户查询]
F --> G[向量检索]
G --> H[提示工程]
H --> I[LLM生成]
LangChain提供了多种文档加载器,针对网页内容我们选择WebBaseLoader。其核心优势在于:
python复制loader = WebBaseLoader(
web_paths=("https://example.com",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("main-content", "article-body")
)
)
)
文本分割需要考虑以下因素:
python复制text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", " ", ""]
)
嵌入模型的选择直接影响检索质量。我们选用阿里云的text-embedding-v1模型,因其:
python复制embeddings = DashScopeEmbeddings(
model="text-embedding-v1",
dashscope_api_key=os.getenv("DASHCOPE_API_KEY")
)
首先安装必要的依赖包:
bash复制pip install langchain==0.3.28
pip install chromadb==1.5.5
pip install beautifulsoup4
pip install langchain-community==0.4.1
pip install dashscope==1.25.14
python复制# 初始化文档加载器
loader = WebBaseLoader(
web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("post-content", "post-title", "post-header")
)
)
)
# 加载并分割文档
docs = loader.load()
splits = text_splitter.split_documents(docs)
print(f"原始文档数:{len(docs)},分割后片段数:{len(splits)}")
使用ChromaDB作为本地向量数据库:
python复制vector_store = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db"
)
vector_store.persist()
# 检索示例
retrieved_docs = vector_store.similarity_search("什么是ReAct范式?", k=3)
for doc in retrieved_docs:
print(doc.metadata["source"], doc.page_content[:100] + "...")
构建一个完整的问答Agent需要:
python复制# 定义检索工具
@tool(description="从向量库检索相关文档片段")
def retrieve_docs(query: str):
docs = vector_store.similarity_search(query, k=2)
return "\n\n".join(f"来源:{doc.metadata}\n内容:{doc.page_content}" for doc in docs)
# 初始化LLM
llm = ChatOpenAI(
model="qwen-plus",
temperature=0.1,
api_key=os.getenv("DASHCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 创建Agent
agent = initialize_agent(
tools=[retrieve_docs],
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
# 执行问答
response = agent.run("在LLM驱动的自治agent系统中,除了作为大脑的LLM,还需要哪些组件?")
print(response)
分块策略优化:
元数据增强:
python复制for i, chunk in enumerate(splits):
chunk.metadata.update({
"chunk_id": i,
"doc_type": "technical_article",
"timestamp": datetime.now().isoformat()
})
检索结果不相关:
生成答案质量差:
python复制# 改进的检索函数
def enhanced_retrieve(query: str):
docs = vector_store.similarity_search_with_relevance_scores(query, k=5)
filtered = [doc for doc, score in docs if score > 0.7]
return filtered[:3] if filtered else "未找到相关文档"
结合图像和文本的混合检索:
python复制from langchain_community.document_loaders import ImageCaptionLoader
image_loader = ImageCaptionLoader(
image_paths=["image1.jpg", "image2.png"],
model="blip-image-captioning-base"
)
image_docs = image_loader.load()
实现增量索引更新策略:
python复制def update_index(new_urls: list):
new_docs = loader.load(new_urls)
new_splits = text_splitter.split_documents(new_docs)
vector_store.add_documents(new_splits)
vector_store.persist()
在实际项目中,我发现RAG系统的效果高度依赖三个关键因素:文档预处理质量、嵌入模型的选择和提示工程设计。建议在正式部署前,针对每个环节进行充分的AB测试。例如,我们曾通过调整分块重叠从100增加到200,使检索准确率提升了15%。