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

浅谈人工智能之大模型的流式调用:Java 后端实践

浅谈人工智能之大模型的流式调用:Java 后端实践

引言

在现代AI应用中,大模型(如阿里云的Qwen、百度的ERNIE等)因其强大的语义理解和生成能力而备受关注。然而,这些模型往往伴随着庞大的计算资源消耗,尤其是对于长时间的对话或大规模文本生成任务。为了解决这一问题,流式调用技术应运而生,它允许开发者以流的方式与模型交互,从而实现实时响应和高效资源管理。本文将详细介绍如何在Java后端中实现大模型的流式调用。

流式调用的概念

流式调用是一种数据传输模式,其中数据不是一次性传输,而是分块或按需传输。在大模型的上下文中,这意味着模型的输出可以被逐步接收和处理,而不是等待整个响应完成后再进行处理。这种模式特别适用于实时应用,如聊天机器人、语音转文字、自动翻译等,同时也减少了对服务器内存的占用。

Java后端的流式调用实现

在Java中,流式调用主要依赖于InputStream和OutputStream类,它们允许数据以流的形式读取和写入。结合Hutool这样的工具库,我们可以更加优雅地处理HTTP请求和响应流。
引入依赖
首先,确保你的项目中引入了Hutool库。在Maven项目中,你可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.3</version>
</dependency>

其次,我们需要处理json格式,所以我们再引入如下依赖包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

发起流式请求
使用Hutool的HttpRequest类发起POST请求,同时指定接收响应的流式处理方式并且进行输出:

import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class QwenSteam {

    private final Logger log = LoggerFactory.getLogger(this.getClass());


    public  void OpenAI (String prompt){
        String baseUrl = "http://XX.XX.XX.XX:8889/v1/chat/completions";
        String model = "QWen";
                String requestBody = "{\n" +
                "  \"model\": \"" + model + "\",\n" +
                "  \"messages\": [\n" +
                "    {\"role\": \"system\", \"content\": \"你是一个老中医,对咳嗽治疗尤其厉害。\"},\n" +
                "    {\"role\": \"user\", \"content\": \"" + prompt + "\"}\n" +
                "  ],\n" +
                "  \"stream\": \"" + true + "\",\n" +
                "  \"temperature\": 0.7,\n" +
                "  \"top_p\": 0.8,\n" +
                "  \"repetition_penalty\": 1.05,\n" +
                "  \"max_tokens\": 512\n" +
                "}";
        System.out.println(requestBody);
        InputStream execute = HttpRequest.post(baseUrl)
                .header("Content-Type", "application/json")
                .body(requestBody).execute().bodyStream();

        try(BufferedReader reader = new BufferedReader(new InputStreamReader(execute))){
            String line;
            String finalContent="";
            while ((line = reader.readLine()) != null) {
                if (!line.trim().isEmpty() && !"data: [DONE]".equals(line)) {
                    line = line.replace("data: ", "");
                    try {
                        JSONObject reqJson = JSONObject.parseObject(line);
                        JSONArray choicesArray = reqJson.getJSONArray("choices");
                        JSONObject firstChoice = choicesArray.getJSONObject(0);
                        JSONObject delta = firstChoice.getJSONObject("delta");
                        if (delta.size()!=0){
                            if(delta.containsKey("content")){
                                String content = delta.getString("content");
                                if(!content.equals(null)){
                                    finalContent = finalContent + content;
//                            processPartialResponse(content);
                                    System.out.println(finalContent);
                                }
                            }
                        }
                    } catch (Exception e) {
                        System.err.println("Failed to parse JSON: " + line);
                        e.printStackTrace();
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        // 关闭输入流
        IoUtil.close(execute);
    }

    public static void main(String[] args) {
        QwenSteam qwen = new QwenSteam();
        qwen.OpenAI("我有点咳嗽");

    }

}

注意事项

● 编码问题:确保在整个数据处理流程中使用一致的字符编码,通常推荐使用UTF-8。
● 流的关闭:在读取完流之后,记得关闭InputStream,以释放系统资源。
● 错误处理:在网络通信中,错误处理至关重要。确保你的代码能够妥善处理各种异常情况,如网络中断、服务器错误等。
● 性能优化:流式调用虽然可以减少内存占用,但对于高并发场景,你可能需要考虑线程池和异步处理机制,以进一步提升性能。

结论

流式调用是现代AI应用中处理大模型输出的一种高效方式。通过在Java后端中采用流式处理技术,我们可以实现实时响应和资源的有效管理,这对于提升用户体验和系统性能具有重要意义。希望本文能帮助你更好地理解和实现大模型的流式调用。


http://www.kler.cn/news/337697.html

相关文章:

  • 台球助教小程序开发搭建/桌球助教到店软件
  • Axios 快速入门
  • 本地访问autodl的jupyter notebook
  • 架构师必须多维度理解架构:视点、视角、视图(附PPT:华为企业架构数据、应用、技术架构设计方法论)
  • MySQL存储过程原理、实现及优化
  • Thinkphp/Laravel基于WEB技术的试卷生成在线考试系统 Vscode毕业设计成品源码_9hcr7
  • qemu-system-aarch64开启user用户模式网络连接
  • 旋转位置编码Rope
  • leetcode经典算法题总结
  • SpringBoot整合异步任务执行
  • micropython中断处理程序设计-临界区
  • 区间覆盖(贪心)
  • <Rust>iced库(0.13.1)学习之部件(三十一):picklist部件的使用及可变style设置
  • 自动驾驶传感器系列—自动驾驶中的“眼睛”:摄像头技术详解
  • springboot整合seata
  • 【代码配置】Orienting Point Clouds with Dipole Propagation
  • Redis 中热 Key 的判定及其解决方案
  • 传热学一些“数”和意义
  • 停车位识别数据集 图片数量12416张YOLO,xml和txt标签都有; 2类类别:space-empty,space-occupied;
  • 如何解决Lenovo笔记本电脑很快就自动休眠,自动锁屏,需要密码登录的问题