流式 LangChain
流式对于使基于法学硕士的应用程序能够响应最终用户至关重要。
LLM、解析器、提示器、检索器和代理等重要的 LangChain 原函数实现了 LangChain Runnable Interface。
该接口提供了两种流内容的通用方法:
- 同步流和异步astream:流式传输的默认实现,用于流式传输链中的最终输出。
- async astream_events 和 async astream_log:它们提供了一种从链中传输中间步骤和最终输出的方法。
让我们来看看这两种方法,并尝试理解如何使用它们。
使用流式
所有 Runnable 对象都实现一个称为 Stream 的同步方法和一个称为 astream 的异步变体。
这些方法旨在以块的形式传输最终输出,一旦每个块可用就生成它。
仅当程序中的所有步骤都知道如何处理输入流时,流式传输才可能实现;即,一次处理一个输入块,并产生相应的输出块。
此处理的复杂性可能会有所不同,从简单的任务(例如由 LLM 生成的令牌)到更具挑战性的任务(例如在整个 JSON 完成之前流式传输 JSON 结果的部分)。
开始探索流媒体的最佳位置是法学硕士应用程序中最重要的一个组件——法学硕士本身!
LLMs 和 聊天模型
大型语言模型及其聊天变体是基于 LLM 的应用程序的主要瓶颈。
大型语言模型可能需要几秒钟才能生成对查询的完整响应。这远远慢于应用程序对最终用户的响应速度约为 200-300 毫秒的阈值。
让应用程序感觉响应更快的关键策略是显示中间进度;即,按令牌流式传输模型令牌的输出。
我们将展示使用 Anthropic 的聊天模型进行流式传输的示例。要使用该模型,您需要安装 langchain-anthropic 包。您可以使用以下命令来执行此操作:
pip install -qU langchain-anthropic
# Showing the example using anthropic, but you can use
# your favorite chat model!
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic()
chunks = []
async for chunk in model.astream("hello. tell me something about yourself"):
chunks.append(chunk)
print(chunk.content, end="|", flush=True)
Hello|!| My| name| is| Claude|.| I|'m| an| AI| assistant| created| by| An|throp|ic| to| be| helpful|,| harmless|,| and| honest|.||
让我们检查其中一个块
chunks[0]
AIMessageChunk(content=' Hello')
我们得到了一个叫做 AIMessageChunk 的东西。该块代表 AIMessage 的一部分。
消息块在设计上是可加的——人们可以简单地将它们相加以获得迄今为止的响应状态!
chunks[0] + chunks[1] + chunks[2] + chunks[3] + chunks[4]
AIMessageChunk(content=' Hello! My name is')
Chains
实际上,所有 LLM 申请都涉及更多步骤,而不仅仅是调用语言模型。
让我们使用 LangChain 表达式语言(LCEL)构建一个简单的链,它结合了提示、模型和解析器,并验证流式传输是否有效。
我们将使用 StrOutputParser 来解析模型的输出。这是一个简单的解析器,它从 AIMessageChunk 中提取内容字段,为我们提供模型返回的Token。
::: tip 提示 LCEL 是一种通过将不同的 LangChain 原语链接在一起来指定“程序”的声明方式。使用 LCEL 创建的链受益于 Stream 和 astream 的自动实现,允许流式传输最终输出。事实上,用 LCEL 创建的链实现了整个标准 Runnable 接口。 :::
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
parser = StrOutputParser()
chain = prompt | model | parser
async for chunk in chain.astream({"topic": "parrot"}):
print(chunk, end="|", flush=True)
Here|'s| a| silly| joke| about| a| par|rot|:|
What| kind| of| teacher| gives| good| advice|?| An| ap|-|parent| (|app|arent|)| one|!||
::: info 注意 您不必使用 LangChain 表达式语言来使用 LangChain,而是可以依靠标准的命令式编程方法,通过单独调用每个组件上的调用、批处理或流,将结果分配给变量,然后在您认为合适的情况下在下游使用它们。
如果这满足您的需求,那么我们没问题👌! :::