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

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

引言

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

流式调用的概念

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

Java后端的流式调用实现

在Java中,流式调用主要依赖于InputStream和OutputStream类,它们允许数据以流的形式读取和写入。结合Hutool这样的工具库,我们可以更加优雅地处理HTTP请求和响应流。

引入依赖

首先,确保你的项目中引入了Hutool库。在Maven项目中,你可以在pom.xml文件中添加以下依赖:

xml 复制代码
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.3</version>
</dependency>

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

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

发起流式请求

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

java 复制代码
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后端中采用流式处理技术,我们可以实现实时响应和资源的有效管理,这对于提升用户体验和系统性能具有重要意义。希望本文能帮助你更好地理解和实现大模型的流式调用。

相关推荐
代码代码快快显灵1 小时前
java之异常处理
java·开发语言
sp_fyf_20241 小时前
【大语言模型-论文精读】谷歌-BERT:用于语言理解的预训练深度双向Transformers
人工智能·语言模型·bert
茶馆大橘1 小时前
Spring Validation —— 参数校验框架
java·后端·学习·spring
算家云2 小时前
PhotoMaker部署文档
人工智能·aigc·conda·图像生成·comfyui·工作流·文本转图像
Kalika0-02 小时前
温度转换-C语言
c语言·开发语言·数据结构·算法
小猪包3333 小时前
ai论文写作软件哪个好?分享5款ai论文题目生成器
人工智能·深度学习·计算机视觉·ai写作
阿望要努力上研究生3 小时前
若依项目搭建(黑马经验)
java·redis·node.js·maven·管理系统
一只脑洞君3 小时前
Kubernetes(K8s)的简介
java·容器·kubernetes
zygswo3 小时前
程序猿成长之路之设计模式篇——设计模式简介
java·设计模式
云翼时代科技4 小时前
【探索艺术新纪元:Midjourney中文版,让创意无界!】
人工智能