当前位置: 首页 > news >正文

LLM应用开发与落地:流式响应

图片

一、背景

最近智能客服产品给到一个游戏客户那边,客户那边的客服负责人体验后认为我们产品回答的准确率是还是比较高的。同时,他反馈了几个需要改进的地方,其中一个就是机器人回复慢。机器人回复慢有很多原因,也有优化方式,其中一个就是流式响应。

二、原理

我们在微信需要发送比较长一段文字的时候,我们需要花比较长的时间去写,跟你聊天的人那边的感触就是要有一段时间的等待。如果我们每写好一句话就先发送过去,对方的等待的感觉就会弱一点。推到极致就是,我们每写一个字就发送过去,这样对方的等待感是最弱的。当然,人不可能这么做 ,因为我们要检查和改动我们写的内容。但是LLM可以,因为LLM也是一个一个token生成,而且不需要检查和改动。

LLM应用要实现流式响应,其实需要三个点都支持流式响应。

首先,LLM生成响应的时候,每生成一部分要先提前返回。百度的ernie-bot-4 是支持流式响应的,只需要请求body中带上参数 stream=True。

其次,应用服务器跟LLM服务器间的数据通道需要支持流式响应,一般http接口的封装都有这个参数,比如python request包的post方法的stream参数。

最后,应用服务器返回给前端的数据通道,以及前端展示要支持流式响应。gradio的chatbot也是支持流式响应的。

三、实践

万事俱备,就等coding。

LLM和数据通道这块都只是加个参数,这个改动不大。我们来看下gradio的流式怎么实现。

如果我们要用gradio实现一个回显的demo(就是我们发送什么,服务器就返回什么),我们会这么实现

import random
import gradio as grdef echo_response(message, history):return "你输入:" + messagegr.ChatInterface(echo_response).launch()

输出效果如下:

图片

实现一个流式响应的也很简单,区别就是把响应函数变成一个生成器,每次返回最新的消息:


import time
import gradio as grdef echo_response(message, history):for i in range(len(message)):time.sleep(0.3)yield "你输入: " + message[: i+1]gr.ChatInterface(echo_response).launch()

为了看到回显消息一个字一个字出来,故意每增加输出一个字延迟0.3秒。看的的效果就是“你输入:”后边的字一个一个显示出来。

接下来就是把LLM的流式响应参数和http通道的流式响应的参数设置为True,然后把gradio的响应函数改成生成器即可。

使用百度 ernie-bot 和 gradio 写了个demo,把全流程串起来验证了下,log中可以看到ernie-bot的分批返回:


{'id': 'as-gxfvpsrx35', 'object': 'chat.completion', 'created': 1707351331, 'sentence_id': 0, 'is_end': False, 'is_truncated': False, 'result': '我是百度公司', 'need_clear_history': False, 'finish_reason': 'normal', 'usage': {'prompt_tokens': 2, 'completion_tokens': 0, 'total_tokens': 2}}
stream result:我是百度公司
{'id': 'as-gxfvpsrx35', 'object': 'chat.completion', 'created': 1707351334, 'sentence_id': 1, 'is_end': False, 'is_truncated': False, 'result': '开发的人工智能语言模型,我的中文名是文心一言,英文名是ERNIE Bot,我可以为人类提供信息解决问题,比如回答问题,提供定义、解释', 'need_clear_history': False, 'finish_reason': 'normal', 'usage': {'prompt_tokens': 2, 'completion_tokens': 0, 'total_tokens': 2}}
stream result:开发的人工智能语言模型,我的中文名是文心一言,英文名是ERNIE Bot,我可以为人类提供信息解决问题,比如回答问题,提供定义、解释
{'id': 'as-gxfvpsrx35', 'object': 'chat.completion', 'created': 1707351336, 'sentence_id': 2, 'is_end': False, 'is_truncated': False, 'result': '和建议,也可以辅助人类进行创作产生新的内容,如文本生成与创作、文本改写等。', 'need_clear_history': False, 'finish_reason': 'normal', 'usage': {'prompt_tokens': 2, 'completion_tokens': 0, 'total_tokens': 2}}
stream result:和建议,也可以辅助人类进行创作产生新的内容,如文本生成与创作、文本改写等。
{'id': 'as-gxfvpsrx35', 'object': 'chat.completion', 'created': 1707351337, 'sentence_id': 3, 'is_end': False, 'is_truncated': False, 'result': '如果您有任何问题,请随时向我提问。', 'need_clear_history': False, 'finish_reason': 'normal', 'usage': {'prompt_tokens': 2, 'completion_tokens': 0, 'total_tokens': 2}}
stream result:如果您有任何问题,请随时向我提问。
{'id': 'as-gxfvpsrx35', 'object': 'chat.completion', 'created': 1707351337, 'sentence_id': 4, 'is_end': True, 'is_truncated': False, 'result': '', 'need_clear_history': False, 'finish_reason': 'normal', 'usage': {'prompt_tokens': 2, 'completion_tokens': 62, 'total_tokens': 64}}
stream result:

文章的最后有demo代码,感兴趣的可以自己验证下。

四、感悟

demo好写,但是发现在智能机器人项目支持这个还是有点改动,从agent framework 到具体agent的实现,整个返回的线路都要改成生成器模式。

最近感悟就是,简单的RAG也好,让人惊喜的AGI也好,都非常容易实现,但是真正要落地到企业中,非常多的坑和需要探索解决的东西,无论是准确率、响应速度、成本,以及使用人的接受度等等。这也是很大一部分人短暂接触LLM后放弃的原因。

最近跟一些在做LLM应用的人聊,大家其实真的还是需要信仰去支持调prompt,去探索新的方法。毕竟,这真的是没有现成的技术方案可以参考,就跟20年前怎么实现服务器高并发一样。那时候,C10K 问题都是会专门讨论的(C10K problem: http://www.kegel.com/c10k.html)。要做开拓者,先行者,这些都是必然会遇到的。

我正在开发一款基于自研的LLM agent framework 的智能客服产品,它具有私有知识问答,意图引导、信息收集、情绪安抚、内部系统融合、LUI与GUI 融合、人工接管、数据分析与洞察、异常监控等功能。

欢迎对prompt编写、LLM应用开发与落地、智能客服产品等等感兴趣的朋友加我微信,一起交流,共同前行。

今天是2024年的除夕了,在这里顺祝大家新年快乐!2023年大环境不好,很多人不容易,但是要相信这都是暂时的,只要保持前行,总有希望!


# LLM 流式响应demo
import gradio as gr
import random
import time
import requests
import json
from extension.llm import llm_baidu
API_KEY = "your_ai_key"
SECRET_KEY = "your_secret_key"def baidu_llm_respond():url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=" + get_access_token()playload_obj = llm_baidu.LlmBaiduMsg(role="user", content="你是谁?").__dict__msgs = [playload_obj]payload = json.dumps({"messages": msgs,"temperature": 0.99,# "system": "this is system","disable_search": False,"enable_citation": False,"stream": True,})print(payload)headers = {'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload, stream=True)obj_list = fetch_stream(response)for obj in obj_list:print(obj)print(f'stream result:{obj["result"]}')yield obj["result"]def fetch_stream(response):for line in response.iter_lines():if not line.startswith(b"data: "):continuejson_data = line[6:] # 只要jsondict_obj = json.loads(json_data)yield dict_objdef get_access_token():url = "https://aip.baidubce.com/oauth/2.0/token"params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}return str(requests.post(url, params=params).json().get("access_token"))with gr.Blocks() as demo:chatbot = gr.Chatbot()msg = gr.Textbox()clear = gr.Button("Clear")def user_input_handler(user_message, history):print(f"user() user_message:{user_message}")return "", history + [[user_message, None]]def respond(history):print(f"bot() history={history}")bot_message_list = baidu_llm_respond()history[-1][1] = ""for msg in bot_message_list:for character in msg:history[-1][1] += charactertime.sleep(0.2)yield historymsg.submit(user_input_handler, [msg, chatbot], [msg, chatbot], queue=False).then(respond, chatbot, chatbot)clear.click(lambda: None, None, chatbot, queue=False)demo.queue()
demo.launch()

相关文章:

LLM应用开发与落地:流式响应

一、背景 最近智能客服产品给到一个游戏客户那边,客户那边的客服负责人体验后认为我们产品回答的准确率是还是比较高的。同时,他反馈了几个需要改进的地方,其中一个就是机器人回复慢。机器人回复慢有很多原因,也有优化方式&#…...

神经网络 | 基于 CNN 模型实现土壤湿度预测

Hi,大家好,我是半亩花海。在现代农业和环境监测中,了解土壤湿度的变化对于作物生长和水资源管理至关重要。通过深度学习技术,特别是卷积神经网络,我们可以利用过去的土壤湿度数据来预测未来的湿度趋势。本文将使用 Pad…...

江科大STM32 终

目录 SPI协议10.1 SPI简介W25Q64简介10.3 SPI软件读写W25Q6410.4 SPI硬件外设读写W25Q64 BKP备份寄存器、PER电源控制器、RTC实时时钟11.0 Unix时间戳代码示例:读写备份寄存器BKP11.2 RTC实时时钟 十二、PWR电源控制12.1 PWR简介代码示例:修改主频12.3 串…...

《MySQL 简易速速上手小册》第10章:未来趋势和进阶资源(2024 最新版)

文章目录 10.1 MySQL 在云计算和容器化中的应用10.1.1 基础知识10.1.2 重点案例:使用 Python 部署 MySQL 到 Kubernetes10.1.3 拓展案例 1:在 AWS RDS 上部署 MySQL 实例10.1.4 拓展案例 2:使用 Docker 部署 MySQL 10.2 MySQL 和 NoSQL 的整合…...

Stable Diffusion 模型下载:GhostMix(幽灵混合)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 GhostMix 是绝对让你惊艳的模型,也是自己认为现在最强的2.5D模型。我认为模型的更新应该是基于现有的画面整体不大变的前提下,提高模型的成…...

django解决Table ‘xx‘ already exists的方法

1,首先看已存在的这个库表结构是什么样的,先让对应的model.py恢复到和他一样的字段 2,删除对应app下的migrations目录里面除__init__.py文件的其他所有文件 3,回到manage.py所在目录执行python manage.py makemigrations 4&#x…...

qt学习:arm摄像头+c调用v412框架驱动+qt调用v412框架驱动 显示摄像头画面

目录 跟内核进行数据通信的函数 编程步骤 c代码 头文件 打开摄像头文件 /dev/videox 获取当前主机上(开发板)摄像头列表信息 设置当前摄像头的画面格式 比如说 设置 采集图像的宽度为640 高度 480 在内核空间中,申请一个缓冲区队列…...

Linux 36.2@Jetson Orin Nano基础环境构建

Linux 36.2Jetson Orin Nano基础环境构建 1. 源由2. 步骤2.1 安装NVIDIA Jetson Linux 36.2系统2.2 必备软件安装2.3 基本远程环境2.3.1 远程ssh登录2.3.2 samba局域网2.3.3 VNC远程登录 2.4 开发环境安装 3. 总结 1. 源由 现在流行什么,也跟风来么一个一篇。当然&…...

牛客网SQL264:查询每个日期新用户的次日留存率

官网链接: 牛客每个人最近的登录日期(五)_牛客题霸_牛客网牛客每天有很多人登录,请你统计一下牛客每个日期新用户的次日留存率。 有一个登录(login。题目来自【牛客题霸】https://www.nowcoder.com/practice/ea0c56cd700344b590182aad03cc61b8?tpId82 …...

echarts 曲线图自定义提示框

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>曲线图</title><!-- 引入 ECharts 库 -->…...

幻兽帕鲁服务器怎么搭建?Palworld多人联机教程

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…...

DAY39: 动态规划不同路径问题62

Leetcode: 62 不同路径 机器人从(0 , 0) 位置出发&#xff0c;到(m - 1, n - 1)终点。 基本思路 1、确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条…...

idea开发工具的简单使用与常见问题

1、配置git 选择左上角目录file->setting 打开&#xff0c;Version Control 目录下Git&#xff0c;选择git安装目录下的git.exe文件&#xff1b; 点击test&#xff0c;出现git版本&#xff0c;则表示git识别成功&#xff0c;点击右下角确认即可生效。 2、配置node.js 选…...

使用 WMI 查询安全软件信息

在这篇文章中&#xff0c;我们将详细介绍如何使用 Windows Management Instrumentation (WMI) API 来查询当前计算机上安装的安全软件的基本信息。我们将分析代码的各个部分&#xff0c;并解释每个步骤所涉及的技术和原理。 一、什么是 WMI&#xff1f; WMI 是 Windows Manag…...

创建TextMeshPro字体文件

相比于Unity的Text组件&#xff0c;TextMesh Pro提供了更强大的文本格式和布局控制&#xff0c;更高级的文本渲染技术&#xff0c;更灵活的文本样式和纹理支持&#xff0c;更好的性能以及更易于使用的优点。但unity自带TextMeshPro字体不支持中文。这里使用普通字体文件生成Tex…...

信创ARM架构QT应用开发环境搭建

Linux ARM架构QT应用开发环境搭建 前言交叉工具链Ubuntu上安装 32 位 ARM 交叉工具链Ubuntu上安装 64 位 ARM 交叉工具链 交叉编译 QT 库下载 QT 源码交叉编译 QT 源码 Qt Creator交叉编译配置配置 Qt Creator Kits创建一个测试项目 小结 前言 有没有碰到过这种情况&#xff1…...

使用SPM_batch进行批量跑脚本(matlab.m)

软件&#xff1a;spm8matlab2023bwin11 数据格式&#xff1a; F:\ASL\HC\CBF\HC_caishaoqing\CBF.nii F:\ASL\HC\CBF\HC_caishaoqing\T1.nii F:\ASL\HC\CBF\HC_wangdonga\CBF.nii F:\ASL\HC\CBF\HC_wangdonga\T1.nii clear spmdirD:\AnalysisApps\spm8; datadirF:\ASL\HC\CBF…...

力扣0124——二叉树的最大路径和

二叉树的最大路径和 难度&#xff1a;困难 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点…...

c# 字符串帮助类

public class StringHelper { #region 全角半角互相转换 /// <summary> /// 转全角的函数(SBC case) /// </summary> /// <param name"str">任意字符串</param> /// <returns>全…...

LabVIEW双光子荧光显微成像系统开发

双光子显微成像是一种高级荧光显微技术&#xff0c;广泛用于生物学和医学研究&#xff0c;尤其是用于活体组织的深层成像。在双光子成像过程中&#xff0c;振镜&#xff08;Galvo镜&#xff09;扮演了非常关键的角色&#xff0c;它负责精确控制激光束在样本上的扫描路径。以下是…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

Appium下载安装配置保姆教程(图文详解)

目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...

【R语言编程——数据调用】

这里写自定义目录标题 可用库及数据集外部数据导入方法查看数据集信息 在R语言中&#xff0c;有多个库支持调用内置数据集或外部数据&#xff0c;包括studentdata等教学或示例数据集。以下是常见的库和方法&#xff1a; 可用库及数据集 openintro库 该库包含多个教学数据集&a…...