Langchain 流式输出到前端(真正解决方法,附最佳实践的完整代码)

这篇具有很好参考价值的文章主要介绍了Langchain 流式输出到前端(真正解决方法,附最佳实践的完整代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Langchain 流式输出

当我们深入使用Langchain时,我们都会考虑如何进行流式输出。尽管官方网站提供了一些流式输出的示例,但这些示例只能在控制台中输出,并不能获取我们所需的生成器。而网上的许多教程也只是伪流式输出,即先完全生成结束,再进行流式输出。

以下是我为大家提供的真正的流式输出示例代码:

这里是2023/12/08 最新补充的方法,简单快捷,好理解,强烈推荐。

最新的流式输出方式(LCEL语法的特性) 推荐指数 : ※ ※ ※ ※ ※ ※※※※※:

from dotenv import load_dotenv
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

load_dotenv()


llm = ChatOpenAI(model="chatglm3",streaming=True,max_tokens=2048)


prompt = ChatPromptTemplate.from_messages(
    [("system", "你是一个专业的AI助手。"), ("human", "{query}")]
)

# llm_chain = prompt | llm.bind(model="chatglm3")  # bin的用法
llm_chain = prompt | llm

ret = llm_chain.stream({"query": "你是谁?"})
for token in ret:
    print(token.content,end="",flush=True)
print()

方法一 推荐指数 : ※ ※ ※ ※ ※ :

本方法是开辟新的线程的方法(当然也可以是新的进程的方式) ,然后结合 langchain的callback方法

为什么推荐使用 线程的方法,而不是 方法二中的异步操作,因为在实际使用过程中,很多外部的方法是不支持异步操作的,要想让程序run起来,必须把一些方法(比如 langchain中的 某些检索器,官方代码只帮你写了 同步的方法,而没有实现异步的方法) 重写为异步方法,而在 重写的过程中会遇到很多 的 问题,令人头疼,而所有的代码都是支持同步的,所以开辟新线程的方式是好的方法。

注: 此方法就是我在 使用方法二的异步方式的过程,遇到了难以解决的问题(本人小白)才找到了此种方式。

缺点: 开辟线程要比 协程 更加耗费计算机资源,因此未来的实现 尽可能还是使用 方法二,但是对于不会异步编程的人来说方法一更加简单。

但是如果对异步操作非常熟悉,那么方法二 是最能提升性能的方式。

代码实现不解释了,手疼,需要的人自然可以看得懂。

至于 ChatOpenAI 所需要的 key,需要自己想办法。

import os
from dotenv import load_dotenv
from langchain.chat_models import ChatOpenAI
from langchain.callbacks import StreamingStdOutCallbackHandler
from fastapi import FastAPI
from sse_starlette.sse import EventSourceResponse
from typing import Generator
import threading
import uvicorn

os.system('clear')
app = FastAPI()
load_dotenv()


class My_StreamingStdOutCallbackHandler(StreamingStdOutCallbackHandler):
    # def __init__(self):
    tokens = []
    # 记得结束后这里置true
    finish = False

    def on_llm_new_token(self, token: str, **kwargs) -> None:
        self.tokens.append(token)

    def on_llm_end(self, response, **kwargs) -> None:
        self.finish = True

    def on_llm_error(self, error: Exception, **kwargs) -> None:
        self.tokens.append(str(error))

    def generate_tokens(self) -> Generator:
        while not self.finish:  # or self.tokens:
            if self.tokens:
                token = self.tokens.pop(0)
                yield {'data': token}
            else:
                pass
                # time.sleep(0.02)  # wait for a new token

# 用于在另一个 线程中运行的方法
def f(llm, query):
    llm.predict(query)


@app.post('/qa')
def test(query='你好'):
    callback = My_StreamingStdOutCallbackHandler()
    llm = ChatOpenAI(model='chatglm3',
                     streaming=True,
                     callbacks=[callback],
                     max_tokens=1024)
    thread = threading.Thread(target=f, args=(llm, query))
    thread.start()

    return EventSourceResponse(callback.generate_tokens(), media_type="text/event-stream")


if __name__ == '__main__':
    uvicorn.run(app=app, host='0.0.0.0')


方法二: 基于 python 异步机制实现 推荐指数 : ※ ※ ※ ※

为了方便展示,我直接使用gradio写一个小webUI,因为流式输出的场景就是用于Web的展示。直接进行python输出也是可以的。
值得注意的是 方法 一定要加上 async ,这里对于小白可能看不懂, 因为这里涉及到,异步协程等概念。

import gradio as gr
import asyncio
from langchain.chat_models import ChatOpenAI
#使用 异步的 Callback   AsyncIteratorCallbackHandler
from langchain.callbacks import AsyncIteratorCallbackHandler

async def f():
   callback = AsyncIteratorCallbackHandler()
   llm = ChatOpenAI(engine='GPT-35',streaming=True,callbacks=[callback])
   coro = llm.apredict("写一个1000字的修仙小说")  # 这里如果是 LLMChain的话 可以 换成  chain.acall()
   asyncio.create_task(coro)
   text = ""
   async for token in callback.aiter():
       text = text+token
       yield gr.TextArea.update(value=text)

with gr.Blocks() as demo:
    with gr.Column():
         摘要汇总 = gr.TextArea(value="",label="摘要总结",)
         bn = gr.Button("触发", variant="primary")
    bn.click(f,[],[摘要汇总])

demo.queue().launch(share=False, inbrowser=False, server_name="0.0.0.0", server_port=8001)

方法来之不易,如果您有所收获,请点赞,收藏,关注文章来源地址https://www.toymoban.com/news/detail-753120.html

到了这里,关于Langchain 流式输出到前端(真正解决方法,附最佳实践的完整代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端开发中的最佳实践

    部分数据来源: ChatGPT 引言         前端开发是一个繁忙而庞杂的领域,其中充满了技术和工具。因此,始终保持最佳实践是确保您的项目顺利完成并高效运行的关键。本文将讨论前端开发的一些最佳实践,以帮助您最大化生产力并确保项目成功。 1. 版本控制       

    2024年02月08日
    浏览(31)
  • 【区块链 | 前端】前端开发人员入门区块链的最佳实践

    前端开发人员入门区块链的最佳实践 从技术入门一个行业通常是漫无目的,个人认为正确的入行区块链的方式是去了解他的背景,是去建立自己信仰的,尤其身处一个刚起步就被扼杀的行业,我们每个人都是领头人,我们需要坚信这个行业是有未来的,当然我们不能去神话他

    2023年04月09日
    浏览(43)
  • 前端数据请求的10种方式与最佳实践

    在前端开发中,数据请求是经常遇到的一个问题。本文将介绍前端常见的10种数据请求方式,并给出每个方式的代码示例与使用场景,以帮助开发者更好的选择和使用。 Fetch API 是浏览器内置的一个用于网络请求的全局接口,可以使用它来发送HTTP请求并获取响应数据。 Fetch API 使用

    2024年02月11日
    浏览(23)
  • Gerrit常见命令及最佳实践,学习前端开发经验

    git clone ssh://tusi@xx.xx.cn:29428/project-name 如果使用了 Git 代理,请将 xx.xx.cn:29428 换成代理后的 ip:port git clone ssh://tusi@ip:port/project-name 创建develop分支 ============================================================================== 一般我们不会将代码直接提交到 master 分支,而是会选择在 develop 分支进

    2024年04月28日
    浏览(20)
  • Vue前端压缩图片后上传,拍照上传最佳实践

    最近有一个需求,通过手机拍照后上传图片到服务器,大家应该都知道,现在的手机像素实在是太高了,随便拍一张都是 10M 以上,直接上传到服务器一方面是浪费存储空间,另外就是特别浪费流量,如果网络不好还很慢。所以想寻求一种前端压缩图片的方案。 在网上找了很

    2024年02月10日
    浏览(53)
  • 最佳实践:基于vite3的monorepo前端工程搭建

    ▪选择理由1:多个应用(可以按业务线产品粒度划分)在同一个repo管理,便于统一管理代码规范、共享工作流 ▪选择理由2:解决跨项目/应用之间物理层面的代码复用,不用通过发布/安装npm包解决共享问题 ▪选择理由1:通过软/硬链接方式,最大程度节省磁盘空间 ▪选择理

    2024年02月06日
    浏览(33)
  • 探秘前端单元测试的秘密:让代码快速稳定的最佳实践!

    一说到单元测试,可能对于业务一线同学来说,心理立马就会无形中有一种压迫感,心想 “业务都做不完了,写个球的单元测试,先保证功能完备,赶紧上线才是王道”,这句话的核心是以业务为重,没任何问题,但是,业务在任何时候都是重要的,除了业务,其实还有效率

    2024年02月05日
    浏览(32)
  • 什么是前端安全性(front-end security)?列举一些前端安全性的最佳实践

    聚沙成塔·每天进步一点点 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一个系统而

    2024年02月05日
    浏览(38)
  • 变量和方法命名的最佳实践

    在每个代码范围内使用足够短和足够长的名称:例如循环计算器用一个字符就可以了,如i;条件和循环变量用一个单词,方法名1-2个单词,类名2-3个单词,全局变量3-4个单词组成 为变量指定一些专门名称,不要使用例如 \\\"value\\\", \\\"equals\\\", \\\"data\\\" 这样的变量名 变量名要使用有意义

    2024年02月11日
    浏览(18)
  • Vue 3, TypeScript 和 Element UI Plus:前端开发的高级技巧与最佳实践

    Vue 3、TypeScript 和 Element UI Plus 结合使用时,可以提供一个强大且灵活的前端开发环境。以下是一些高级用法和技巧,帮助你更有效地使用这些技术: Composition API 使用 setup 函数: Vue 3 引入了 Composition API,允许你在 setup 函数中组织逻辑代码。 响应式引用 (ref 和 reactive): 使用

    2024年03月12日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包