LCEL是专门为方便开发LLM应用而设计的编程语言,它提供了一系列直观、好用的功能和语法。

本篇我们来学习提升LLM应用体验的一个功能——stream流式输出。

image-20231227115947187

1. LCEL流式输出接口-stream

(1)为什么要用流式输出

在使用LLM应用时,用户总是期望立即得到答案,不管他的问题有多么复杂,或者让LLM生成的文本有多么长。

流式输出“这时就派上用场了,它能够使LLM在生成文本时逐步提供结果,而不是等到整个文本生成完成后再一次性返回给用户。

流式输出的方式有以下几个优点:

  1. 实时性:不用等待整个文本生成完毕再返回结果,减少响应时间,用户获得实时响应体验。
  2. 交互性:生成结果逐步提供,可匹配用户阅读速度,增强交互感。
  3. 节省资源和带宽:逐步返回生成的结果可以减少对网络带宽的需求。
  4. 支持长文本生成:生成长文本时无需担心超出内存限制。

总之,流式输出可以让用户得到更好的体验,让用户觉得你的LLM程序”性能“很棒。

(2)流式输出接口的使用

LangChain在Runnable协议中定义了流式输出方法stream,以及它的异步方法astream

LangChain的很多组件都是遵循Runnable的对象,可以直接调用stream/astream方法。以之前专栏多次构建过的链chain为例:

  • chain.stream()

  • chain.astream()

2.快速上手

以让LLM生成一首诗为例,对比下直接输出、流式输出的差异效果。

任务链的构建不再赘述,如下代码,我们构建了名为chain的链,它的功能是根据输入的主题生成一首诗。

image-20231227125844993

(1)使用invoke方法直接调用

  • 调用语法:chain.invoke(“犀牛”)
  • 执行效果:任务启动后,没有立即得到响应;大概6秒后,生成结果一次性闪现。

invoke

(2)使用stream方法流式输出

  • 调用语法:chain.stream(“犀牛”)
    • 注意:由于stream()是迭代输出,因此用for语句来循环遍历输出结果。
  • 执行效果:任务启动后,立即得到响应,以一定的字频逐行输出结果。

stream

  • 如果想用异步方式astream,则调用语法如下:

image-20231227145757283

(3) 对比总结 Invoke vs Stream

对于一个交互式的LLM应用程序,stream流式输出的响应实时性和交互体验都更好。

在 Python 中,没有名为"stream” 的内置方法,但是有类似于流式操作的机制,比如生成器(yield)、迭代器(iterator)。所以,如果没有LCEL提供的stream方法,而是要我们自己来实现的话,将是一件费脑筋的事。

如下是不使用LCEL实现流式输出的示例代码,可以跟上面简单的一行方法调用对比下:

image-20231227124359421

LangChain的大牛们用python实现了与Java “Stream API"类似的流式处理方法,极大的方便了开发人员。

某种意义上来说,LangChain不仅仅是定义了一套Runnable协议,也是对Python语法的重构,构建了自己的语法——LCEL。

3.小结

本文解读了LangChain LCEL语法中提升性能的一种方法——stream流式输出。关键要点如下:

  • 流式输出接口

    • “流式输出"使LLM在生成文本时逐步提供结果,提升LLM应用程序的性能,让用户得到更好的体验。
    • LangChain的Runnable对象可以直接调用stream/astream方法。
  • 实例演示

    • 对比invoke直接输出和stream流式输出的效果差异。

参考文档:翻译的LangChain官方文档

  • 翻译链接:https://jherculesqz.gitbook.io/langchain-guan-fang-wen-dang