Spring Boot 整合讯飞星火3.5通过接口Api接口实现聊天功能(首发)复制粘贴即可使用,后续更新WebSocket实现聊天功能

程序员必备网站:

天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/

1.pom.xml

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.72</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>
           <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>13.0</version>
            <scope>compile</scope>
        </dependency>

spark:
  ai:
    hostUrl: https://spark-api.xf-yun.com/v3.5/chat
    appId: ####
    apiSecret: #####
    apiKey: ######

2.实体类

import cn.hutool.json.JSONObject;
import lombok.Data;

@Data
public class SparkDto {
    private JSONObject payload;
    private JSONObject parameter;
    private JSONObject header;
}

@Data
public class SparkParamDto {
    private String content;
}

3.Tool工具类

import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.example.springbootServiceNetwork.demos.web.Config.JwtInfo;
import com.example.springbootServiceNetwork.demos.web.Dto.SparkDto;
import com.example.springbootServiceNetwork.demos.web.Dto.SparkParamDto;
import okhttp3.HttpUrl;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 讯飞星火工具类
 */
public class SparkUtil {

    /**
     * 构建 鉴权方法
     * @param hostUrl
     * @param apiKey
     * @param apiSecret
     * @return
     * @throws Exception
     */
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    };

    /**
     * 构建请求参数
     * @param jwtInfo
     * @param appId
     * @param sparkParam
     * @return
     * @throws Exception
     */
    public static String getSparkJson(JwtInfo jwtInfo, String appId, SparkParamDto sparkParam) throws Exception {
        SparkDto sprarkDto = new SparkDto();
        //----------------payload-----------------
        JSONObject payload=new JSONObject();
          JSONObject message=new JSONObject();
            JSONArray text=new JSONArray();
              JSONObject textObj=new JSONObject();
              textObj.put("role","user");
              textObj.put("content",sparkParam.getContent());
            text.add(textObj);
          message.put("text",text);
        payload.put("message",message);
        sprarkDto.setPayload(payload);

        //----------------parameter-----------------

        JSONObject parameter=new JSONObject(); // parameter参数
        JSONObject chat=new JSONObject();
        chat.put("domain","generalv2");
        chat.put("temperature",0.5);
        chat.put("max_tokens",2000);
        parameter.put("chat",chat);
        sprarkDto.setParameter(parameter);

        //----------------header-----------------

        JSONObject header = new JSONObject();
        header.put("app_id", appId);
        header.put("uid", jwtInfo.getUserId());
        sprarkDto.setHeader(header);
        return JSON.toJSONString(sprarkDto);
    }


}

4.业务层

图片解析

import com.example.springbootServiceNetwork.demos.web.Config.JwtInfo;
import com.example.springbootServiceNetwork.demos.web.Config.Result;
import com.example.springbootServiceNetwork.demos.web.Dto.SparkParamDto;

public interface SparkService {
    Result SparkChat(SparkParamDto sparkParam, JwtInfo jwtInfo);
}

@Service
public class SparkServiceImpl implements SparkService {
    @Value("${spark.ai.hostUrl}")
    private  String  hostUrl;
    @Value("${spark.ai.appId}")
    private  String appId;
    @Value("${spark.ai.apiSecret}")
    private  String apiSecret;
    @Value("${spark.ai.apiKey}")
    private  String apiKey;

    @Override
    public Result SparkChat(SparkParamDto sparkParamDto, JwtInfo jwtInfo) {
            Result result = new Result();
            try {
                // 构建鉴权url
                String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
                OkHttpClient client = new OkHttpClient.Builder().build();
                String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
                Request request = new Request.Builder().url(url).build();
                String body = getSparkJson(jwtInfo,appId,sparkParamDto);

                StringBuilder builderSb =new StringBuilder();
                CompletableFuture<String> messageReceived = new CompletableFuture<>();

                WebSocket webSocket = client.newWebSocket(request, new WebSocketListener(){

                    @Override
                    public void onOpen(WebSocket webSocket, Response response) {
                        webSocket.send(body);
                    }
                    @Override
                    public void onMessage(WebSocket webSocket, String res) {
                        JSONObject obj = JSON.parseObject(res);
                        String str= obj.getJSONObject("payload").getJSONObject("choices").getJSONArray("text").getJSONObject(0).getString("content");
                        builderSb.append(str);
                        if(obj.getJSONObject("header").getLong("status")==2){
                            webSocket.close(1000, "Closing WebSocket connection");
                            messageReceived.complete(res); // 将收到的消息传递给 CompletableFuture
                        }
                    }

                });
                String resItem = messageReceived.get(30, TimeUnit.SECONDS);; // 阻塞等待消息返回
                webSocket.close(1000, "Closing WebSocket connection");
                result.setData(builderSb.toString());
                result.setCode(200);
                result.setMsg("天梦星");
            }catch (Exception e){
                e.printStackTrace();
            }
        return result;
    }


}

5.控制层

import com.example.springbootServiceNetwork.demos.web.Config.JwtInfo;
import com.example.springbootServiceNetwork.demos.web.Config.Result;
import com.example.springbootServiceNetwork.demos.web.Dto.SparkParamDto;
import com.example.springbootServiceNetwork.demos.web.Service.JwtRedistService;
import com.example.springbootServiceNetwork.demos.web.Service.SparkService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;



@RestController
@RequestMapping("/Spark")
public class SparkController {
    @Resource
    private SparkService sparkService;
    @Resource
    private JwtRedistService jwtRedistService;

    @PostMapping("/chat")
    public Result SparkChatApi(@RequestBody SparkParamDto sparkParam, @RequestHeader("token") String token){
        JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);
        if(jwtInfo.getPass()){
            return sparkService.SparkChat(sparkParam,jwtInfo);
        }else {
            return jwtInfo.getResult();
        }
    }
}

6.测试

http://localhost:8082/Spark/chat

{
    "content":"帮我写一份本地js模糊查询"
}


{
	"code": 200,
	"msg": "天梦星",
	"data": "以下是一个简单的本地 JavaScript 模糊查询的示例代码:\n\n```javascript\n// 假设有一个数据列表,包含商品的名称和价格\nconst products = [\n  { name: \"苹果\", price: 1.99 },\n  { name: \"香蕉\", price: 0.99 },\n  { name: \"橙子\", price: 2.49 },\n  { name: \"草莓\", price: 3.99 },\n];\n\n// 实现模糊查询函数\nfunction searchProducts(keyword) {\n  // 将关键字转换为小写,以忽略大小写的差异\n  const lowerCaseKeyword = keyword.toLowerCase();\n\n  // 使用数组的 filter 方法进行模糊查询\n  const results = products.filter((product) => {\n    // 将商品名称转换为小写,并使用 includes 方法检查是否包含关键字\n    return product.name.toLowerCase().includes(lowerCaseKeyword);\n  });\n\n  return results;\n}\n\n// 测试模糊查询函数\nconst keyword = \"果\"; // 输入要查询的关键字\nconst searchResults = searchProducts(keyword);\nconsole.log(searchResults);\n```\n\n上述代码中,我们首先定义了一个包含商品名称和价格的数据列表 `products`。然后实现了一个 `searchProducts` 函数,该函数接受一个关键字作为参数,并返回包含该关键字的商品列表。在函数内部,我们将关键字转换为小写,并使用数组的 `filter` 方法对商品列表进行模糊查询。最后,我们通过调用 `searchProducts` 函数并打印结果来进行测试。"
}

备注:这步骤是我的业务流程,你可以省略不写

JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);

返回数据格式,已有忽略

@Data
public class Result {
    private Integer code;//状态码
    private Object msg;//状态信息或者报错信息
    private Object data;//返回数据
    private Integer count;//总条数
}

已经三天没吃饭了,大佬行行好

相关推荐
V+zmm1013429 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
搬码后生仔1 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
迷糊的『迷』1 小时前
vue-axios+springboot实现文件流下载
vue.js·spring boot
凡人的AI工具箱1 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
J不A秃V头A2 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
Lx3522 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas