小工具知识网

当前位置: 首页 > 行业知识 > LLM(大语言模型)——Springboot集成文心一言、讯飞星火、通义千问、智谱清言

行业知识

LLM(大语言模型)——Springboot集成文心一言、讯飞星火、通义千问、智谱清言

2026-10-31 12:37:48 来源:互联网转载

目录

引言

代码完整地址

入参

 出参

Controller

Service

Service实现类

 模型Service

 入参转换类

文心一言实现类

讯飞星火实现类

 通义千问实现类

智谱清言实现类


引言

本文将介绍如何使用Java语言,结合Spring Boot框架,集成国内热门大模型API,包括文心一言、讯飞星火、通义千问、智谱清言。

在开始前,请确保您已经按照各模型官网的指引,完成了相应的资源申请和配置。这些资源是调用大模型API的必要凭证,务必妥善保管。接下来,我们将通过具体的代码示例和步骤说明,引导您完成Spring Boot项目和大模型API集成。

代码完整地址

https://github.com/wangsilingwsl/model-integrate.git

入参

package com.wsl.model.llm.api.dto;import com.alibaba.fastjson.JSONObject;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import javax.validation.constraints.NotNull;import java.io.Serializable;import java.util.List;/** * 聊天请求 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class ChatRequestDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "聊天上下文信息", notes = "(1)最后一个message为当前请求的信息,前面的message为历史对话信息\n" +            "(2)成员数目必须为奇数\n" +            "(3)示例中message中的role值分别为user、assistant;奇数位message中的role值为user;偶数位值为assistant",            example = "[{\"role\":\"user\",\"content\":\"你好\"},{\"role\":\"assistant\",\"content\":\"需要什么帮助\"},{\"role\":\"user\",\"content\":\"自我介绍下\"}]")    @NotNull(message = "聊天上下文信息不能为空")    private List messages;    @ApiModelProperty(value = "模型人设", notes = "主要用于人设设定,例如,你是xxx公司制作的AI助手,最大20000字符", example = "你是一名天气助手,需要提供天气查询服务")    private String system;    @ApiModelProperty(value = "请求参数", notes = "请求参数", example = "{\"key\":\"value\"}")    private JSONObject params;}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import java.io.Serializable;/** * 消息 DTO * * @author wsl * @date 2024/2/20 */@Data@AllArgsConstructorpublic class MessageDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "角色", notes = "说明: user-用户, assistant-助手", example = "user")    private String role;    @ApiModelProperty(value = "消息内容", notes = "说明: 消息内容", example = "你好")    private String content;}

 出参

package com.wsl.model.llm.api.vo;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.io.Serializable;/** * 聊天响应 VO * * @author wsl * @date 2024/2/20 */@Datapublic class ChatResponseVO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "结果", notes = "结果")    private String result;}

Controller

package com.wsl.model.llm.api.controller;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.service.IAiAppService;import com.wsl.model.llm.api.vo.ChatResponseVO;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;/** * AI应用Controller * * @author wsl * @date 2024/02/19 */@Slf4j@RestController@Api(tags = "AI应用")@RequestMapping("/llm/middle")public class AiAppController {    @Autowired    private IAiAppService service;    @PostMapping("/chat-message")    @ApiOperation("向大模型发起对话请求")    public ChatResponseVO chatMessage(            @ApiParam(value = "模型类型(ErnieBot/SparkDesk/ChatGlm/QianWen)", required = true) @RequestParam String modelType,            @ApiParam(value = "消息参数", required = true) @RequestBody ChatRequestDTO dto) {        try {            return service.chatMessage(modelType, dto);        } catch (Exception e) {            throw new RuntimeException(e);        }    }}

Service

package com.wsl.model.llm.api.service;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.vo.ChatResponseVO;/** * AI应用Service * * @author wsl * @date 2024/02/19 */public interface IAiAppService {    /**     * 向大模型发起对话请求-根据模型编码、用户ID     *     * @param modelType 模型类型     * @param dto       消息参数     * @return ChatResponseVO     * @throws Exception 异常     */    ChatResponseVO chatMessage(String modelType, ChatRequestDTO dto) throws Exception;}

Service实现类

package com.wsl.model.llm.api.service.impl;import cn.hutool.core.collection.CollUtil;import cn.hutool.core.util.StrUtil;import cn.hutool.extra.spring.SpringUtil;import com.wsl.model.llm.api.constant.enums.ModelTypeEnum;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.dto.MessageDTO;import com.wsl.model.llm.api.service.IAiAppService;import com.wsl.model.llm.api.service.ModelService;import com.wsl.model.llm.api.vo.ChatResponseVO;import org.springframework.stereotype.Service;import java.util.List;/** * AI应用ServiceImpl * * @author wsl * @date 2024/02/19 */@Service("aiAppService")public class AiAppServiceImpl implements IAiAppService {    @Override    public ChatResponseVO chatMessage(String modelType, ChatRequestDTO dto) throws Exception {        this.checkMessages(dto.getMessages());        // 根据枚举类ModelTypeEnum中的枚举值判断模型类型,并调用对应的模型实现类的方法        ModelService modelService = getModelService(modelType);        return modelService.chatMessage(dto);    }    /**     * 检查消息参数是否符合规范     *     * @param messages 消息参数     */    private void checkMessages(List messages) {        if (CollUtil.isNotEmpty(messages)) {            // messages参数个数必须为奇数并且奇数个数的消息role必须为user,偶数个数的消息role必须为assistant            if (messages.size() % 2 == 0) {                throw new RuntimeException("messages参数个数必须为奇数");            }            for (int i = 0; i  

 模型Service

package com.wsl.model.llm.api.service;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.vo.ChatResponseVO;/** * 模型服务 * * @author wsl * @date 2024/2/19 */public interface ModelService {    /**     * 发起请求     *     * @param dto 请求参数     * @return 返回值     * @throws Exception 异常     */    ChatResponseVO chatMessage(ChatRequestDTO dto) throws Exception;}

 入参转换类

package com.wsl.model.llm.api.convert;import cn.hutool.core.bean.BeanUtil;import cn.hutool.core.collection.CollUtil;import cn.hutool.core.util.StrUtil;import com.alibaba.fastjson.JSONObject;import com.wsl.model.llm.api.dto.*;import org.mapstruct.Mapper;import org.mapstruct.factory.Mappers;import java.util.ArrayList;import java.util.List;/** * 聊天请求转换器 * * @author wsl * @date 2024/2/22 */@Mapperpublic interface ChatRequestConvert {    ChatRequestConvert INSTANCE = Mappers.getMapper(ChatRequestConvert.class);    /**     * 通用请求转换为文心一言请求     *     * @param dto 通用请求     * @return 文心一言请求     */    default JSONObject convertErnieBot(ChatRequestDTO dto) {        ErnieBotDTO ernieBotDTO = new ErnieBotDTO();        ernieBotDTO.setMessages(dto.getMessages());        ernieBotDTO.setSystem(dto.getSystem());        JSONObject jsonObject = new JSONObject();        BeanUtil.copyProperties(ernieBotDTO, jsonObject);        BeanUtil.copyProperties(dto.getParams(), jsonObject);        return jsonObject;    }    /**     * 通用请求转换为通义千问请求     *     * @param dto 通用请求     * @return 通义千问请求     */    default QianWenDTO convertQianwen(ChatRequestDTO dto) {        QianWenDTO qianWenDTO = new QianWenDTO();        qianWenDTO.setModel("qwen-turbo");        QianWenInputDTO input = new QianWenInputDTO();        String system = dto.getSystem();        if (StrUtil.isNotBlank(system)) {            MessageDTO messageDTO = new MessageDTO("system", system);            dto.getMessages().add(0, messageDTO);        }        input.setMessages(dto.getMessages());        JSONObject parametersJsonObject = new JSONObject();        BeanUtil.copyProperties(dto.getParams(), parametersJsonObject);        qianWenDTO.setInput(input);        qianWenDTO.setParameters(parametersJsonObject);        return qianWenDTO;    }    /**     * 通用请求转换为智谱清言请求     *     * @param dto 通用请求     * @return 智谱清言请求     */    default JSONObject convertChatGlm(ChatRequestDTO dto) {        ChatGlmDTO chatGlmDTO = new ChatGlmDTO();        String system = dto.getSystem();        if (StrUtil.isNotBlank(system)) {            MessageDTO messageDTO = new MessageDTO("system", system);            dto.getMessages().add(0, messageDTO);        }        chatGlmDTO.setMessages(dto.getMessages());        chatGlmDTO.setModel("glm-4");        JSONObject jsonObject = new JSONObject();        BeanUtil.copyProperties(chatGlmDTO, jsonObject);        BeanUtil.copyProperties(dto.getParams(), jsonObject);        return jsonObject;    }    /**     * 通用请求转换为讯飞星火请求     *     * @param dto 通用请求     * @return 讯飞星火请求     */    default SparkDeskDTO convertSparkDesk(ChatRequestDTO dto) {        SparkDeskDTO sparkDeskDTO = new SparkDeskDTO();        SparkDeskPayloadDTO payload = new SparkDeskPayloadDTO();        SparkDeskPayloadMessageDTO payloadMessage = new SparkDeskPayloadMessageDTO();        String system = dto.getSystem();        if (StrUtil.isNotBlank(system)) {            MessageDTO messageDTO = new MessageDTO("system", system);            dto.getMessages().add(0, messageDTO);        }        payloadMessage.setText(dto.getMessages());        payload.setMessage(payloadMessage);        SparkDeskParameterChatDTO parameterChat = new SparkDeskParameterChatDTO();        parameterChat.setDomain("generalv3.5");        JSONObject parameterChatJsonObject = new JSONObject();        BeanUtil.copyProperties(parameterChat, parameterChatJsonObject);        BeanUtil.copyProperties(dto.getParams(), parameterChatJsonObject);        SparkDeskParameterDTO parameter = new SparkDeskParameterDTO();        parameter.setChat(parameterChatJsonObject);        sparkDeskDTO.setPayload(payload);        sparkDeskDTO.setParameter(parameter);        return sparkDeskDTO;    }    /**     * 通用请求转换为通义千问请求     *     * @param dto 通用请求     * @return 通义千问请求     */    default FaRuiDTO convertFaRui(ChatRequestDTO dto) {        FaRuiDTO faRuiDTO = new FaRuiDTO();        List messages = dto.getMessages();        String prompt = messages.get(messages.size() - 1).getContent();        FaRuiInputDTO input = new FaRuiInputDTO();        if (messages.size() == 1) {            messages = new ArrayList();        }        if (CollUtil.isNotEmpty(messages)) {            messages.remove(messages.size() - 1);            List history = convertFaRuiHistory(messages);            input.setHistory(history);        }        input.setPrompt(prompt);        faRuiDTO.setParameters(dto.getParams());        faRuiDTO.setInput(input);        return faRuiDTO;    }    /**     * 通用消息转换为通义法睿历史消息     *     * @param messages 通用消息     * @return 通义法睿历史消息     */    default List convertFaRuiHistory(List messages) {        List history = new ArrayList();        int size = messages.size();        for (int i = 0; i  

文心一言实现类

package com.wsl.model.llm.api.service.impl;import cn.hutool.http.HttpRequest;import cn.hutool.http.HttpResponse;import cn.hutool.http.HttpUtil;import cn.hutool.json.JSONUtil;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.wsl.model.llm.api.convert.ChatRequestConvert;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.service.ModelService;import com.wsl.model.llm.api.vo.ChatResponseVO;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;/** * 文心一言 大模型服务 * * @author wsl * @link https://console.bce.baidu.com/tools/?_=1708497709522&u=qfdc#/api?product=AI&project=%E5%8D%83%E5%B8%86%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%B9%B3%E5%8F%B0&parent=ERNIE-Bot&api=rpc%2F2.0%2Fai_custom%2Fv1%2Fwenxinworkshop%2Fchat%2Fcompletions&method=post * @date 2024/2/19 */@Service("ErnieBotService")@Slf4jpublic class ErnieBotServiceImpl implements ModelService {    private String appSecret = "?";    private String apiKey = "?";    private static final String TOKEN_URL_TEMPLATE = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s";    private static final String CHAT_URL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=%s";    @Override    public ChatResponseVO chatMessage(ChatRequestDTO dto) {        JSONObject ernieBot = ChatRequestConvert.INSTANCE.convertErnieBot(dto);        String requestBody = JSONUtil.toJsonStr(ernieBot);        log.info("文心一言请求参数 ernieBot request:{}", requestBody);        HttpResponse response = HttpUtil.createPost(String.format(CHAT_URL, getAccessToken(apiKey, appSecret)))                .body(requestBody)                .header("Content-Type", "application/json")                .execute();        if (response == null) {            throw new RuntimeException("HTTP response is null");        }        log.info("文心一言返回结果 ernieBot response:{}", response.body());        if (response.body() == null || response.body().trim().isEmpty()) {            throw new RuntimeException("HTTP response body is null or empty");        }        JSONObject jsonObject = JSON.parseObject(response.body());        if (!jsonObject.containsKey("result")) {            throw new RuntimeException(JSONObject.toJSONString(jsonObject));        }        ChatResponseVO vo = new ChatResponseVO();        vo.setResult(jsonObject.getString("result"));        return vo;    }    /**     * 从用户的AK,SK生成鉴权签名(Access Token)     *     * @param appId     应用ID     * @param appSecret 应用密钥     * @return token     */    public String getAccessToken(String appId, String appSecret) {        String url = String.format(TOKEN_URL_TEMPLATE, apiKey, appSecret);        try (HttpResponse response = HttpRequest.post(url)                .header("Content-Type", "application/json")                .header("Accept", "application/json")                .execute()) {            JSONObject jsonObject = JSON.parseObject(response.body());            String accessToken = jsonObject.getString("access_token");            return accessToken;        }    }}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import javax.validation.constraints.NotNull;import java.io.Serializable;import java.util.List;/** * 文心一言 请求 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class ErnieBotDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "聊天上下文信息", notes = "说明:\n" +            "(1)messages成员不能为空,1个成员表示单轮对话,多个成员表示多轮对话;例如:\n" +            "· 1个成员示例,\"messages\": [ {\"role\": \"user\",\"content\": \"你好\"}]\n" +            "· 3个成员示例,\"messages\": [ {\"role\": \"user\",\"content\": \"你好\"},{\"role\":\"assistant\",\"content\":\"需要什么帮助\"},{\"role\":\"user\",\"content\":\"自我介绍下\"}]\n" +            "(2)最后一个message为当前请求的信息,前面的message为历史对话信息\n" +            "(3)成员数目必须为奇数,成员中message的role值说明如下:奇数位messsage的role值必须为user或function,偶数位message的role值为assistant,第一个message的role不能是function。例如:\n" +            "示例中message中的role值分别为user、assistant、user、assistant、user;奇数位(红框)message中的role值为user,即第1、3、5个message中的role值为user;偶数位(蓝框)值为assistant,即第2、4个message中的role值为assistant",            example = "[{\"role\":\"system\",\"content\":\"您好,我是智谱清言,我可以帮您查询天气,您可以输入:查询{{destination}}的天气,查询{{destination}}未来{{num_day}}天的天气\"},{\"role\":\"user\",\"content\":\"查询三亚未来5天的天气\"},{\"role\":\"assistant\",\"content\":\"正在查询三亚未来5天的天气\"},{\"role\":\"assistant\",\"content\":\"三亚未来5天的天气是晴天\"}]")    @NotNull(message = "聊天上下文信息不能为空")    private List messages;    @ApiModelProperty(value = "模型人设", notes = "主要用于人设设定,例如,你是xxx公司制作的AI助手,最大20000字符", example = "qwen-turbo")    private String system;    @ApiModelProperty(value = "温度", notes = "较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。默认0.8,范围 [0, 1.0],不能为0", example = "0.8")    private Float temperature;}

讯飞星火实现类

package com.wsl.model.llm.api.service.impl;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONException;import com.alibaba.fastjson.JSONObject;import com.wsl.model.llm.api.convert.ChatRequestConvert;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.dto.SparkDeskDTO;import com.wsl.model.llm.api.dto.SparkDeskHeaderDTO;import com.wsl.model.llm.api.service.ModelService;import com.wsl.model.llm.api.vo.ChatResponseVO;import lombok.extern.slf4j.Slf4j;import okhttp3.*;import org.springframework.stereotype.Service;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.*;import java.util.concurrent.CompletableFuture;import java.util.concurrent.TimeUnit;/** * 讯飞星火 大模型服务 * * @author wsl * @link https://www.xfyun.cn/doc/spark/Web.html * @date 2024/2/19 */@Service("SparkDeskService")@Slf4jpublic class SparkDeskServiceImpl implements ModelService {    private String appId = "?";    private String appSecret = "?";    private String appKey = "?";    public static final String HOST_URL = "https://spark-api.xf-yun.com/v3.5/chat";    @Override    public ChatResponseVO chatMessage(ChatRequestDTO dto) throws Exception {        ChatResponseVO vo = new ChatResponseVO();        SparkDeskDTO sparkDeskDTO = ChatRequestConvert.INSTANCE.convertSparkDesk(dto);        sparkDeskDTO.setHeader(new SparkDeskHeaderDTO(appId));        String authUrl = getAuthUrl(HOST_URL, appKey, appSecret).replace("http://", "ws://").replace("https://", "wss://");        Request request = new Request.Builder().url(authUrl).build();        OkHttpClient client = new OkHttpClient.Builder().build();        StringBuilder sb = new StringBuilder();        CompletableFuture messageReceived = new CompletableFuture();        String body = JSON.toJSONString(sparkDeskDTO);        WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {            @Override            public void onOpen(WebSocket webSocket, Response response) {                //发送消息                log.info("讯飞星火请求参数 sparkDesk request:{}", body);                webSocket.send(body);            }            @Override            public void onMessage(WebSocket webSocket, String text) {                try {                    JSONObject obj = JSON.parseObject(text);                    // 使用Optional来避免空指针异常,并在内容不存在时抛出异常                    Optional contentOptional = Optional.ofNullable(obj)                            .map(jsonObject -> jsonObject.getJSONObject("payload"))                            .map(payload -> payload.getJSONObject("choices"))                            .map(choices -> choices.getJSONArray("text"))                            .map(jsonArray -> jsonArray.getJSONObject(0))                            .map(jsonObject -> jsonObject.getString("content"));                    String str = contentOptional.orElseThrow(() -> new RuntimeException(JSONObject.toJSONString(obj)));                    sb.append(str);                    // 检查header和status字段                    Optional statusOptional = Optional.ofNullable(obj)                            .map(jsonObject -> jsonObject.getJSONObject("header"))                            .map(header -> header.getLong("status"));                    // 如果status为2,则关闭WebSocket并完成CompletableFuture                    if (statusOptional.isPresent() && statusOptional.get() == 2) {                        webSocket.close(1000, "Closing WebSocket connection");                        messageReceived.complete(text);                    }                } catch (JSONException e) {                    throw new RuntimeException(e);                }            }        });        messageReceived.get(60, TimeUnit.SECONDS);        webSocket.close(1000, "Closing WebSocket connection");        log.info("讯飞星火返回结果 sparkDesk response:{}", sb);        vo.setResult(sb.toString());        return vo;    }    /**     * 鉴权方法     *     * @param hostUrl   服务地址     * @param apiKey    apiKey     * @param apiSecret apiSecret     * @return 返回鉴权url     * @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";        // 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);        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();        return httpUrl.toString();    }}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.io.Serializable;/** * 讯飞星火 请求 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class SparkDeskDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "头部", notes = "头部")    private SparkDeskHeaderDTO header;    @ApiModelProperty(value = "参数", notes = "参数")    private SparkDeskParameterDTO parameter;    @ApiModelProperty(value = "有效载荷", notes = "有效载荷")    private SparkDeskPayloadDTO payload;}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/** * 讯飞星火 Header DTO * * @author wsl * @date 2024/2/20 */@Data@NoArgsConstructor@AllArgsConstructorpublic class SparkDeskHeaderDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "应用appid", notes = "从开放平台控制台创建的应用中获取")    private String app_id;}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.io.Serializable;/** * 讯飞星火 聊天 参数 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class SparkDeskParameterChatDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "指定访问的领域", notes = "generalv3指向V3版本;generalv3.5指向V3.5版本")    private String domain;    @ApiModelProperty(value = "温度", notes = "较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。默认0.8,范围 [0, 2.0],不能为0", example = "0.8")    private Float temperature;    @ApiModelProperty(value = "最大标记", notes = "模型回答的tokens的最大长度;取值范围[1,8192],默认为2048", example = "2048")    private Integer max_tokens;}
package com.wsl.model.llm.api.dto;import com.alibaba.fastjson.JSONObject;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.io.Serializable;/** * 讯飞星火 参数 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class SparkDeskParameterDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "聊天参数", notes = "聊天参数")    private JSONObject chat;}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.io.Serializable;/** * 讯飞星火 有效载荷 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class SparkDeskPayloadDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "消息", notes = "消息")    private SparkDeskPayloadMessageDTO message;}
package com.wsl.model.llm.api.dto;import lombok.Data;import javax.validation.constraints.NotNull;import java.io.Serializable;import java.util.List;/** * 讯飞星火 有效载荷 消息 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class SparkDeskPayloadMessageDTO implements Serializable {    private static final long serialVersionUID = 1L;    @NotNull(message = "聊天上下文信息不能为空")    private List text;}

 通义千问实现类

package com.wsl.model.llm.api.service.impl;import cn.hutool.http.HttpRequest;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.wsl.model.llm.api.convert.ChatRequestConvert;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.dto.QianWenDTO;import com.wsl.model.llm.api.service.ModelService;import com.wsl.model.llm.api.vo.ChatResponseVO;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;import java.util.Optional;/** * 通义千问 大模型服务 * * @author wsl * @link https://help.aliyun.com/zh/dashscope/developer-reference/api-details?spm=a2c4g.11186623.0.0.6922140bTYj6qJ#602895ef3dtl1 * @date 2024/2/19 */@Slf4j@Service("QianWenService")public class QianWenServiceImpl implements ModelService {    private String apiKey = "?";    @Override    public ChatResponseVO chatMessage(ChatRequestDTO dto) {        QianWenDTO qianwen = ChatRequestConvert.INSTANCE.convertQianwen(dto);        String url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";        String json = JSON.toJSONString(qianwen);        log.info("通义千问请求参数 qianwen request:{}", json);        String result = HttpRequest.post(url)                .header("Authorization", "Bearer " + apiKey)                .header("Content-Type", "application/json")                .body(json)                .execute().body();        log.info("通义千问返回结果 qianwen response:{}", result);        ChatResponseVO vo = new ChatResponseVO();        JSONObject jsonObject = JSON.parseObject(result);        Optional textOptional = Optional.ofNullable(jsonObject.getJSONObject("output"))                .map(output -> output.getString("text"));        if (!textOptional.isPresent()) {            throw new RuntimeException(JSONObject.toJSONString(jsonObject));        }        vo.setResult(textOptional.get());        return vo;    }}
package com.wsl.model.llm.api.dto;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import javax.validation.constraints.NotNull;import java.io.Serializable;import java.util.List;/** * 通义千问 输入 DTO * * @author wsl * @date 2024/2/20 */@Datapublic class QianWenInputDTO implements Serializable {    private static final long serialVersionUID = 1L;    @ApiModelProperty(value = "聊天上下文信息", notes = "说明:\n" +            "(1)messages成员不能为空,1个成员表示单轮对话,多个成员表示多轮对话;例如:\n" +            "· 1个成员示例,\"messages\": [ {\"role\": \"user\",\"content\": \"你好\"}]\n" +            "· 3个成员示例,\"messages\": [ {\"role\": \"user\",\"content\": \"你好\"},{\"role\":\"assistant\",\"content\":\"需要什么帮助\"},{\"role\":\"user\",\"content\":\"自我介绍下\"}]\n" +            "(2)最后一个message为当前请求的信息,前面的message为历史对话信息\n" +            "(3)成员数目必须为奇数,成员中message的role值说明如下:奇数位messsage的role值必须为user或function,偶数位message的role值为assistant,第一个message的role不能是function。例如:\n" +            "示例中message中的role值分别为user、assistant、user、assistant、user;奇数位(红框)message中的role值为user,即第1、3、5个message中的role值为user;偶数位(蓝框)值为assistant,即第2、4个message中的role值为assistant",            example = "[{\"role\":\"system\",\"content\":\"您好,我是智谱清言,我可以帮您查询天气,您可以输入:查询{{destination}}的天气,查询{{destination}}未来{{num_day}}天的天气\"},{\"role\":\"user\",\"content\":\"查询三亚未来5天的天气\"},{\"role\":\"assistant\",\"content\":\"正在查询三亚未来5天的天气\"},{\"role\":\"assistant\",\"content\":\"三亚未来5天的天气是晴天\"}]")    @NotNull(message = "聊天上下文信息不能为空")    private List messages;}

智谱清言实现类

package com.wsl.model.llm.api.service.impl;import cn.hutool.http.HttpResponse;import cn.hutool.http.HttpUtil;import cn.hutool.json.JSONUtil;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.auth0.jwt.JWT;import com.auth0.jwt.algorithms.Algorithm;import com.wsl.model.llm.api.convert.ChatRequestConvert;import com.wsl.model.llm.api.dto.ChatRequestDTO;import com.wsl.model.llm.api.service.ModelService;import com.wsl.model.llm.api.vo.ChatResponseVO;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Optional;/** * 智谱清言 大模型服务 * * @author wsl * @link https://open.bigmodel.cn/dev/api#glm-4 * @date 2024/2/19 */@Slf4j@Service("ChatGlmService")public class ChatGlmServiceImpl implements ModelService {    private String apiKey = "?";    @Override    public ChatResponseVO chatMessage(ChatRequestDTO dto) throws Exception {        JSONObject chatGlm = ChatRequestConvert.INSTANCE.convertChatGlm(dto);        String url = "https://open.bigmodel.cn/api/paas/v4/chat/completions";        String requestBody = JSONUtil.toJsonStr(chatGlm);        log.info("智谱清言请求参数 chatGlm request:{}", requestBody);        HttpResponse response = HttpUtil.createPost(url).body(requestBody).header("Content-Type", "application/json").header("Authorization", "Bearer " + generateToken(apiKey, 3600)).execute();        log.info("智谱清言返回结果 chatGlm response:{}", Optional.ofNullable(response).map(HttpResponse::body).orElse(""));        ChatResponseVO vo = new ChatResponseVO();        Optional jsonObject = Optional.ofNullable(JSON.parseObject(response.body()));        jsonObject.ifPresent(json -> {            Optional choices = Optional.ofNullable(json.getJSONArray("choices"));            choices.ifPresent(choiceArray -> {                if (!choiceArray.isEmpty()) {                    Optional firstChoiceMessage = Optional.ofNullable(choiceArray.getJSONObject(0).getJSONObject("message"));                    firstChoiceMessage.ifPresent(message -> {                        String content = message.getString("content");                        if (content != null) {                            vo.setResult(content);                        } else {                            throw new RuntimeException(response.body());                        }                    });                }            });            throw new RuntimeException(response.body());        });        return vo;    }    /**     * 生成token     *     * @param apikey     apikey     * @param expSeconds 过期时间     * @return token     * @throws Exception 异常     */    public static String generateToken(String apikey, int expSeconds) throws Exception {        String[] parts = apikey.split("\.");        if (parts.length != 2) {            throw new Exception("Invalid apikey");        }        String id = parts[0];        String secret = parts[1];        Map payload = new HashMap(16);        payload.put("api_key", id);        payload.put("exp", new Date(System.currentTimeMillis() + expSeconds * 1000));        payload.put("timestamp", new Date(System.currentTimeMillis()));        Algorithm algorithm = Algorithm.HMAC256(secret);        return JWT.create().withHeader(new HashMap(16) {{            put("alg", "HS256");            put("sign_type", "SIGN");        }}).withPayload(payload).sign(algorithm);    }}

上一篇:服务器怎么修改创建线程数?

下一篇:服务器数怎么计算?