从ConversationalRetrievalChain到LCEL:掌握更清晰的检索增强生成

从 ConversationalRetrievalChain 到 LCEL:掌握更清晰的检索增强生成

在当今快速发展的人工智能和自然语言处理领域,检索增强生成(Retrieval-Augmented Generation, RAG)已成为一项核心技术,能够显著提高模型的回答质量。过去,我们依赖 ConversationalRetrievalChain 来结合检索增强生成和聊天历史,实现文档互动。如今,LCEL(LangChain Execution Layer)提供了更精细的控制和额外特性,如异步操作与流式方法支持。本文将深入探讨迁移到 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()  # 请勿在代码中明文存储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("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())

# 使用 OpenAI 的聊天模型
llm = ChatOpenAI()

# 创建用于重构问题的系统提示
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)

这个示例展示了如何从 ConversationalRetrievalChain 迁移到 LCEL,并详细解释每个步骤。使用 LCEL,我们不仅得到了更清晰的结构,还支持异步和流式操作,这在实现大规模商业应用时至关重要。

常见问题和解决方案

  1. 访问限制问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务以提高访问的稳定性。

  2. 性能优化:向量存储的选择对于性能至关重要,建议在实现中使用适合自己数据规模和类型的方案。

  3. 兼容性问题:在迁移过程中,注意检查新旧系统中的 API 版本兼容性,确保 API 调用和模型参数的一致性。

总结与进一步学习资源

LCEL 提供了一个更强大、更灵活的框架来实现检索增强生成,使得与文档的互动更加高效。在实践中,我们应根据具体需求,灵活应用 LCEL 的特性。更多学习资源和示例代码,可以参考以下链接:

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

—END—

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值