当前位置: 代码网 > it编程>编程语言>Java > springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

2025年04月18日 Java 我要评论
1.开通阿里云百炼,获取到key官方文档地址https://bailian.console.aliyun.com/?tab=api#/api/?type=model&url=https%3a%

1.开通阿里云百炼,获取到key

官方文档地址
https://bailian.console.aliyun.com/?tab=api#/api/?type=model&url=https%3a%2f%2fhelp.aliyun.com%2fdocument_detail%2f2868565.html

2.新建springboot项目

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
         xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0</modelversion>
    <groupid>devicewx-ai</groupid>
    <artifactid>devicewx-ai</artifactid>
    <version>1.0-snapshot</version>
    <parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.5.15</version>
        <relativepath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <!--阿里云deepseek-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
        <dependency>
            <groupid>com.alibaba</groupid>
            <artifactid>dashscope-sdk-java</artifactid>
            <version>2.18.3</version>
        </dependency>
        <!-- 集成redis依赖  -->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-data-redis</artifactid>
        </dependency>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <version>1.18.16</version>
        </dependency>
    </dependencies>
</project>

3.工具类

import org.springframework.data.redis.core.redistemplate;
import org.springframework.stereotype.component;
import javax.annotation.resource;
import java.util.list;
import java.util.map;
import java.util.set;
import java.util.concurrent.timeunit;
/**
 * redis工具类
 * @author: albc
 * @date: 2024/07/17/15:31
 * @description: good good study,day day up
 */
@component
public class redisutil {
    @resource
    private redistemplate<string, object> redistemplate;
    // =============================common============================
    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     */
    public boolean expire(string key, long time) {
        try {
            if (time > 0) {
                redistemplate.expire(key, time, timeunit.seconds);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getexpire(string key) {
        return redistemplate.getexpire(key, timeunit.seconds);
    }
    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean haskey(string key) {
        try {
            return redistemplate.haskey(key);
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @suppresswarnings("unchecked")
    public void del(string... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redistemplate.delete(key[0]);
            } else {
                //redistemplate.delete(collectionutils.arraytolist(key));
            }
        }
    }
    // ============================string=============================
    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public object get(string key) {
        return key == null ? null : redistemplate.opsforvalue().get(key);
    }
    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(string key, object value) {
        try {
            redistemplate.opsforvalue().set(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(string key, object value, long time) {
        try {
            if (time > 0) {
                redistemplate.opsforvalue().set(key, value, time, timeunit.seconds);
            } else {
                set(key, value);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     */
    public long incr(string key, long delta) {
        if (delta < 0) {
            throw new runtimeexception("递增因子必须大于0");
        }
        return redistemplate.opsforvalue().increment(key, delta);
    }
    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     */
    public long decr(string key, long delta) {
        if (delta < 0) {
            throw new runtimeexception("递减因子必须大于0");
        }
        return redistemplate.opsforvalue().increment(key, -delta);
    }
    // ================================map=================================
    /**
     * hashget
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     */
    public object hget(string key, string item) {
        return redistemplate.opsforhash().get(key, item);
    }
    /**
     * 获取hashkey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public map<object, object> hmget(string key) {
        return redistemplate.opsforhash().entries(key);
    }
    /**
     * hashset
     *
     * @param key 键
     * @param map 对应多个键值
     */
    public boolean hmset(string key, map<string, object> map) {
        try {
            redistemplate.opsforhash().putall(key, map);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * hashset 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(string key, map<string, object> map, long time) {
        try {
            redistemplate.opsforhash().putall(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(string key, string item, object value) {
        try {
            redistemplate.opsforhash().put(key, item, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(string key, string item, object value, long time) {
        try {
            redistemplate.opsforhash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(string key, object... item) {
        redistemplate.opsforhash().delete(key, item);
    }
    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hhaskey(string key, string item) {
        return redistemplate.opsforhash().haskey(key, item);
    }
    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     */
    public double hincr(string key, string item, double by) {
        return redistemplate.opsforhash().increment(key, item, by);
    }
    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     */
    public double hdecr(string key, string item, double by) {
        return redistemplate.opsforhash().increment(key, item, -by);
    }
    // ============================set=============================
    /**
     * 根据key获取set中的所有值
     *
     * @param key 键
     */
    public set<object> sget(string key) {
        try {
            return redistemplate.opsforset().members(key);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }
    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean shaskey(string key, object value) {
        try {
            return redistemplate.opsforset().ismember(key, value);
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sset(string key, object... values) {
        try {
            return redistemplate.opsforset().add(key, values);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long ssetandtime(string key, long time, object... values) {
        try {
            long count = redistemplate.opsforset().add(key, values);
            if (time > 0) {
                expire(key, time);
            }
            return count;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    /**
     * 获取set缓存的长度
     *
     * @param key 键
     */
    public long sgetsetsize(string key) {
        try {
            return redistemplate.opsforset().size(key);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setremove(string key, object... values) {
        try {
            long count = redistemplate.opsforset().remove(key, values);
            return count;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    // ===============================list=================================
    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     */
    public list<object> lget(string key, long start, long end) {
        try {
            return redistemplate.opsforlist().range(key, start, end);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }
    /**
     * 获取第一个元素并弹出
     *
     * @param key key
     * @return 第一个元素
     */
    public object lpop(string key) {
        try {
            return redistemplate.opsforlist().leftpop(key);
        } catch (exception e) {
            return null;
        }
    }
    /**
     * 阻塞时间获取
     * @param key
     * @param timeout 秒
     * @return
     */
    public object lpop(string key,long timeout) {
        try {
            return redistemplate.opsforlist().leftpop(key,timeout,timeunit.seconds);
        } catch (exception e) {
            return null;
        }
    }
    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lgetlistsize(string key) {
        try {
            return redistemplate.opsforlist().size(key);
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     */
    public object lgetindex(string key, long index) {
        try {
            return redistemplate.opsforlist().index(key, index);
        } catch (exception e) {
            e.printstacktrace();
            return null;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     */
    public boolean lset(string key, object value) {
        try {
            redistemplate.opsforlist().rightpush(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     */
    public boolean lset(string key, object value, long time) {
        try {
            redistemplate.opsforlist().rightpush(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lset(string key, list<object> value) {
        try {
            redistemplate.opsforlist().rightpushall(key, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lset(string key, list<object> value, long time) {
        try {
            redistemplate.opsforlist().rightpushall(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lupdateindex(string key, long index, object value) {
        try {
            redistemplate.opsforlist().set(key, index, value);
            return true;
        } catch (exception e) {
            e.printstacktrace();
            return false;
        }
    }
    /**
     * 移除n个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lremove(string key, long count, object value) {
        try {
            long remove = redistemplate.opsforlist().remove(key, count, value);
            return remove;
        } catch (exception e) {
            e.printstacktrace();
            return 0;
        }
    }
}

4.启动类

import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
/**
 * @author: albc
 * @date: 2025/04/17/10:03
 * @description: good good study,day day up
 */
@springbootapplication
public class aiapplication {
    public static void main(string[] args) {
        springapplication.run(aiapplication.class,args);
        system.out.println("启动成功");
    }
}

5.测试类

import lombok.data;
/**
 * @author: albc
 * @date: 2025/04/17/10:12
 * @description: good good study,day day up
 */
@data
public class testdto {
    private string content;
}

6.测试方法

import com.alibaba.dashscope.aigc.generation.generation;
import com.alibaba.dashscope.aigc.generation.generationparam;
import com.alibaba.dashscope.aigc.generation.generationresult;
import com.alibaba.dashscope.common.message;
import com.alibaba.dashscope.common.role;
import com.alibaba.dashscope.exception.apiexception;
import com.alibaba.dashscope.exception.inputrequiredexception;
import com.alibaba.dashscope.exception.noapikeyexception;
import com.atkj.dto.testdto;
import com.atkj.util.redisutil;
import io.reactivex.flowable;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.httpservletresponse;
import java.io.ioexception;
import java.io.printwriter;
import java.text.simpledateformat;
import java.util.arrays;
import java.util.date;
/**
 * @author: albc
 * @date: 2025/04/17/10:02
 * @description: good good study,day day up
 */
@requestmapping("/test")
@restcontroller
public class testcontroller {
    /**
     * 问题分析
     */
    private static stringbuilder reasoningcontent = new stringbuilder();
    /**
     * 完整回复
     */
    private static stringbuilder finalcontent = new stringbuilder();
    private static boolean isfirstprint = true;
    @autowired
    private redisutil redisutil;
    @postmapping("/testrdislistset")
    public string testrdislist(){
        return "ai测试方法";
    }
    @postmapping("/testai")
    @responsebody
    public void testai(httpservletresponse httpservletresponse,@requestbody testdto testdto){
        //正式版本自定义线程池,禁止创建线程
        new thread(()->{try {
            string content = testdto.getcontent();
            generation gen = new generation();
            message usermsg = message.builder().role(role.user.getvalue()).content(content).build();
            streamcallwithmessage(gen, usermsg);
//             打印最终结果
//            if (reasoningcontent.length() > 0) {
//                system.out.println("\n====================完整回复====================");
//                system.out.println(finalcontent.tostring());
//            }
        } catch (apiexception | noapikeyexception | inputrequiredexception e) {
            system.out.println("an exception occurred:"+e.getmessage());
        }}).start();
        httpservletresponse.setcontenttype("text/event-stream");
        httpservletresponse.setcharacterencoding("utf-8");
        simpledateformat simpledateformat = new simpledateformat("yyyy-mm-dd hh:mm:ss");
        string s = "";
        while (true) {
            object deep = redisutil.lpop("deep",5);
            if (deep == null){
                break;
            }
            s = "data: " + deep + "\n\n";
            try {
                printwriter pw = httpservletresponse.getwriter();
                thread.sleep(10l);
                pw.write(s);
                pw.flush();
            } catch (ioexception | interruptedexception e) {
                e.printstacktrace();
            }
        }
    }
    private void handlegenerationresult(generationresult message) {
        string reasoning = message.getoutput().getchoices().get(0).getmessage().getreasoningcontent();
        string content = message.getoutput().getchoices().get(0).getmessage().getcontent();
        if (!reasoning.isempty()) {
           // reasoningcontent.append(reasoning);
            if (isfirstprint) {
                system.out.println("====================思考过程====================");
                isfirstprint = false;
            }
            redisutil.lset("deep", reasoning);
            system.out.print(reasoning);
        }
        if (!content.isempty()) {
            //finalcontent.append(content);
            if (!isfirstprint) {
                system.out.println("\n====================完整回复====================");
                isfirstprint = true;
            }
            redisutil.lset("deep", content);
            system.out.print(content);
        }
    }
    private static generationparam buildgenerationparam(message usermsg) {
        return generationparam.builder()
                // 若没有配置环境变量,请用百炼api key将下行替换为:.apikey("sk-xxx") //qwen-plus,deepseek-r1
                .apikey("sk-123123123123123123123123123123123")
                .model("deepseek-r1")
                .messages(arrays.aslist(usermsg))
                // 不可以设置为"text"
                .resultformat(generationparam.resultformat.message)
                .incrementaloutput(true)
                .build();
    }
    public void streamcallwithmessage(generation gen, message usermsg)
            throws noapikeyexception, apiexception, inputrequiredexception {
        generationparam param = buildgenerationparam(usermsg);
        flowable<generationresult> result = gen.streamcall(param);
        result.blockingforeach(message -> handlegenerationresult(message));
    }
}

7.配置文件

server:
  port: 18868
spring:
  redis:
    host: 192.168.11.198
    port: 7366
    password: 123321
    database: 0

8.测试结果

http://127.0.0.1:18868/test/testai

到此这篇关于springboot整合阿里云百炼deepseek实现sse流式打印的操作方法的文章就介绍到这了,更多相关springboot整合阿里云百炼deepseek内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com