首页 > 编程语言 >Langchain语言模型提问请求,提问使用非标准的sse请求获取流式数据,java后台版解决方式

Langchain语言模型提问请求,提问使用非标准的sse请求获取流式数据,java后台版解决方式

时间:2023-10-26 19:34:11浏览次数:40  
标签:java 请求 流式 source str sse new 提问

问题描述:请求后接收的数据流,不走EventSourceListener的onEvent事件,但onOpen onClosed都是正常走的。

 

问题原因:默认的接口返回是StreamingResponse不是EventSourceResponse,无法走标准sse协议的onEvent()方法

 

目标需求:在不改动模型方面接口的情况下,接收到流式数据并通过sse协议转发前端。

 

网上现成方案:

可以使用SSE协议
1、 pip install sse_starlette.sse
2、引入依赖: from sse_starlette.sse import EventSourceResponse
3、将StreamingResponse改为EventSourceResponse

前端使用EventSource进行请求,因原生EventSource支持get请求,可以使用Fetch请求或者微软的 @microsoft/fetch-event-source进行请求

 

最终解决方式:因为不能修改模型api的基础上,不能够使用标准sse来获取数据流,所以最终自己实现实时读取流式数据。故使用OkHttp包,请求链接,并把返回的请求生成一个缓冲区,通过逐字读取,匹配到两个会话之间断点的标志(“}{”)来实现分割,并把分割的数据进行转发。

 

参考code

public void sendQuery(ChatGlmDto chatGlmDto) {

    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(1, TimeUnit.DAYS)
            .readTimeout(1, TimeUnit.DAYS)
            .build();
    okhttp3.RequestBody formBody = okhttp3.RequestBody.create(JSON.toJSONString(chatGlmDto), MediaType.parse("application/json; charset=utf-8"));
    Request.Builder requestBuilder = new Request.Builder();
    Request request = requestBuilder.url(apiUrl).post(formBody).build();
    try (Response response = client.newCall(request).execute()) {
        ResponseBody responseBody = response.body();
        if (responseBody == null) {
            // 处理响应体为空的情况
            return;
        }

        try (BufferedSource source = responseBody.source()) {
            // 将源缓冲区包装成一个流式输入流
            InputStream inputStream = source.inputStream();

            // 此处需要将编码格式设置为UTF_8,解决 InputStream 流读取时的中文乱码问题
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            int byteRead;
            int preRead = 0;

            String str = "";

            while ((byteRead = reader.read()) != -1) {

                char nowStr = (char) byteRead;
                char preStr = (char) preRead;
                if (preStr == '}' && nowStr == '{' ){
                    // 转发给客户端
                    log.info("Received message: " + str);
                    callback.send(str);
                    str = "";
                }
                str = str + nowStr;
                preRead = byteRead;
            }
            //最后一个为关联文档,
            log.info("Received message: " + str);
            callback.send(str);

        }
    } catch (IOException e) {
        log.error("获取失败",e);
    }
}

 

标签:java,请求,流式,source,str,sse,new,提问
From: https://www.cnblogs.com/goodscoding/p/17790195.html

相关文章

  • java复习
    java中成员变量和局部变量的区别是什么?作用域不同,局部变量的作用域仅限于定义它的方法,在该方法外无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它,如果访问权限允许,还可以在类外部使用成员变量;初始值不同,对于成员变量,如果在类定义中没有给它赋予初......
  • javaweb--mysql数据模型
    关系型数据库由多张可以相互连接的二维表组成的数据库frm表文件myd数据文件注释/**/多行注释--和#单行注释四类语法DDL数据定义语言DML数据操作语言DQL数据查询语言DCL数据控制语言原始数据库information_schema存储数据库的基本信息,存储的库名表名列名等mysql存......
  • Java基本语法_04类型转换
    1.自动类型转换 ......
  • Java map详解 - 用法、遍历、排序、常用API等
    java.util中的集合类包含Java中某些最常用的类。最常用的集合类是List和Map。Map提供了一个更通用的元素存储方法。Map集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。本文主要介绍javamap的初始化、用法、map的四种常用的遍历方式、map的排序以及常用ap......
  • Ajax请求--Ajax的使用与案例
    浏览器向网站发送请求时:以URL和表单的形式提交GETPOST特点:提交时页面会刷新除此之外,也可以基于Ajax向后台发送请求(页面不会刷新,只局部更新)依赖jQuery编写Ajax代码$.ajax({ url:"发送的地址", type:"get", data:{ n1:123, n2:456 }, success:function(res){......
  • java如何从Content-Disposition获取文件名的正则表达式
    一,主要是关于:post请求下载文件,如何从Content-Disposition获取文件名的正则表达式记录:HttpResponsehttpResponse=httpRequest.execute();byte[]bytes=httpResponse.bodyBytes();Stringheader=httpResponse.header("Content-Disposition")......
  • Java SimpleDateFormat的使用方法
    JavaSimpleDateFormat的使用方法使用Date直接输出日期时,是使用系统默认的格式输出,所以需要使用SimpleDateFormat来格式化日期。那么SimpleDateFormat类怎么使用呢,我们需要先了解此类的格式化符号y:代表年份M:代表月份d:代表月份中的那一天,也就是日H:代表小时m:代表分钟s:代表秒......
  • java中 int (double、float、long等等) 与 String 之间的相互转换
    int转String(double、float、long等同理)方法1 inti=28; Strings=i+"";此方法在将i转换成s时,会额外产生一个""常量对象存放在常量池中方法2 inti=28; Strings=String.valueOf(i);方法3 inti=28; Strings=Integer.toString(i);String转in......
  • Java 多表联查
    Java多表联查前提:由于我当前页面显示的数据是在其他两个表中只有ID可以使用1、分别对两个表进行操作,将List转为Map对象//查询项目表List<BudgetProjectInfo>budgetProjectInfoList=budgetProjectInfoService.list();Map<String,BudgetProjectInfo>schemMap=budgetPro......
  • Java中 List和数组之间的常见转换方法
    List转数组1、使用for循环//要转换的list集合List<String>list=newArrayList<>();list.add("aa");list.add("bb");list.add("cc");//初始化需要得到的数组String[]array=newString[list.size()];//使用fo......