[从ConversationalRetrievalChain迁移到LCEL的全面指南]

115 阅读3分钟
# 从ConversationalRetrievalChain迁移到LCEL的全面指南

## 引言

在现代对话系统中,`ConversationalRetrievalChain`一直被视为一种强大的工具,它结合了检索增强生成和聊天记录,提供了与文档进行“对话”的能力。但随着技术的进步,切换到LCEL(LangChain Enhanced Learning)实现会带来更清晰的内部结构、更好的文档返回以及流媒体和异步操作等支持。在这篇文章中,我们将探讨迁移的过程、必要的步骤以及相关的代码示例。

## 主要内容

### 为什么选择LCEL?

1. **清晰的内部结构**`ConversationalRetrievalChain`包含一个隐藏的重新措辞步骤,而LCEL则提供了更加透明的实现。
2. **更容易返回源文档**:通过LCEL,开发者可以更容易地追溯和返回源文档。
3. **支持流媒体和异步操作**:这是现代应用程序中非常重要的功能,LCEL对此有良好的支持。

### 准备工作

在开始之前,你需要安装一些Python库:

```bash
%pip install --upgrade --quiet langchain-community langchain langchain-openai faiss-cpu

你还需要确保你有一个有效的OpenAI API密钥。

import os
from getpass import getpass

os.environ["OPENAI_API_KEY"] = getpass()  # 获取API密钥

加载和处理文档

使用langchain的库,我们可以加载和处理文档:

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 = ChatOpenAI()

代码示例

以下是如何使用LCEL重建对话检索链的代码示例:

from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain

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['answer'])

# 使用API代理服务提高访问稳定性

常见问题和解决方案

  • API访问问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务来提高访问稳定性。
  • 模型响应时间:确保使用异步方法来减少延迟,特别是在高并发场景下。

总结和进一步学习资源

迁移到LCEL提供了许多优势,包括更清晰的内部结构和更强大的功能支持。有关LCEL的更多信息,可以参阅LangChain官方文档.

参考资料

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


---END---