写点什么

Springboot --- 使用国内的 AI 大模型 对话

  • 2024-10-14
    福建
  • 本文字数:6032 字

    阅读完需:约 20 分钟

尝试使用 国内给出的 AI 大模型做出一个 可以和 AI 对话的 网站出来


  • 使用 智普 AI 只能 在控制台中输出 对应的信息 不如就做一个 maven 的 项目调用对应的 API



    <dependency>        <groupId>cn.bigmodel.openapi</groupId>        <artifactId>oapi-java-sdk</artifactId>        <version>release-V4-2.0.0</version>    </dependency>
复制代码


  • 使用 普通的 java -- Maven 项目 只能在控制台 查看结果 也就是 说没有办法在其他平台使用制作出来的 AI ChatRobot

  • 思来想去 不如 将这个东西写成 QQ 机器人

  • 但是因为我找到的 那个 不更新了 或者 腾讯不支持了 让我放弃了 写成 QQ 机器人的想法

  • 于是我就尝试将这个写成一个本地的 AI 对话机器人 但是 在翻看 官方给出的 Demo 我偶然发现了一个方法 他的 输出似乎是一个 json 转换成的 String

  • 这个方法并没有将这个 String 返回出来 而是 直接在控制台打印


package com.codervibe.utils; import com.alibaba.fastjson.JSON;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.PropertyNamingStrategy;import com.zhipu.oapi.ClientV4;import com.zhipu.oapi.Constants;import com.zhipu.oapi.service.v4.image.CreateImageRequest;import com.zhipu.oapi.service.v4.image.ImageApiResponse;import com.zhipu.oapi.service.v4.model.*;import io.reactivex.Flowable; import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.atomic.AtomicBoolean; public class ChatAPIUtils {    private static final String API_KEY = "cb11ad7f3b68ce03ed9be6e13573aa19";     private static final String API_SECRET = "nG7UQrrXqsXtqD1S";     private static final ClientV4 client = new ClientV4.Builder(API_KEY, API_SECRET).build();     private static final ObjectMapper mapper = defaultObjectMapper();      public static ObjectMapper defaultObjectMapper() {        ObjectMapper mapper = new ObjectMapper();        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);        mapper.addMixIn(ChatFunction.class, ChatFunctionMixIn.class);        mapper.addMixIn(ChatCompletionRequest.class, ChatCompletionRequestMixIn.class);        mapper.addMixIn(ChatFunctionCall.class, ChatFunctionCallMixIn.class);        return mapper;    }     // 请自定义自己的业务id    private static final String requestIdTemplate = "mycompany-%d";       /**     * 同步调用     */    public static String InvokeApi(String content) throws JsonProcessingException {        List<ChatMessage> messages = new ArrayList<>();        ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), content);        messages.add(chatMessage);        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());        // 函数调用参数构建部分        List<ChatTool> chatToolList = new ArrayList<>();        ChatTool chatTool = new ChatTool();        chatTool.setType(ChatToolType.FUNCTION.value());        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();        chatFunctionParameters.setType("object");        Map<String, Object> properties = new HashMap<>();        properties.put("location", new HashMap<String, Object>() {{            put("type", "string");            put("description", "城市,如:北京");        }});        properties.put("unit", new HashMap<String, Object>() {{            put("type", "string");            put("enum", new ArrayList<String>() {{                add("celsius");                add("fahrenheit");            }});        }});        chatFunctionParameters.setProperties(properties);        ChatFunction chatFunction = ChatFunction.builder()                .name("get_weather")                .description("Get the current weather of a location")                .parameters(chatFunctionParameters)                .build();        chatTool.setFunction(chatFunction);        chatToolList.add(chatTool);        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()                .model(Constants.ModelChatGLM4)                .stream(Boolean.FALSE)                .invokeMethod(Constants.invokeMethod)                .messages(messages)                .requestId(requestId)                .tools(chatToolList)                .toolChoice("auto")                .build();        ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest);        try {        // 这里返回出去是一个 json             return mapper.writeValueAsString(invokeModelApiResp);        } catch (JsonProcessingException e) {            e.printStackTrace();        }        return mapper.writeValueAsString(new ModelApiResponse());    }     public static void CreateImage(String content) {        CreateImageRequest createImageRequest = new CreateImageRequest();        createImageRequest.setModel(Constants.ModelCogView);        createImageRequest.setPrompt(content);        ImageApiResponse imageApiResponse = client.createImage(createImageRequest);        System.out.println("imageApiResponse:" + JSON.toJSONString(imageApiResponse));    } }
复制代码


  • 工具类中 InvokeApi 方法 最后获得的是一个 ModelApiResponse 类 这个类有点类似于 统一返回类型 但是我在这里 只需要里面的具体方法 请求状态和 信息 并不需要 (有另外一个统一返回类型定义 ) 所以在 后面我将这个方法 修改 改为 将我需要的数据返回给 controller

  • 实际上这是不应该直接返回给 controller 的 而是 应该 通过 service 的 因为 service 中才是真正的业务代码

  • 修改后的方法 代码如下


    /**     * 同步调用     */    public static ModelData InvokeApi(String content) throwsJsonProcessingException{        List<ChatMessage> messages = new ArrayList<>();        ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), content);        messages.add(chatMessage);        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());        // 函数调用参数构建部分        List<ChatTool> chatToolList = new ArrayList<>();        ChatTool chatTool = new ChatTool();        chatTool.setType(ChatToolType.FUNCTION.value());        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();        chatFunctionParameters.setType("object");        Map<String, Object> properties = new HashMap<>();        properties.put("location", new HashMap<String, Object>() {{            put("type", "string");            put("description", "城市,如:北京");        }});        properties.put("unit", new HashMap<String, Object>() {{            put("type", "string");            put("enum", new ArrayList<String>() {{                add("celsius");                add("fahrenheit");            }});        }});        chatFunctionParameters.setProperties(properties);        ChatFunction chatFunction = ChatFunction.builder()                .name("get_weather")                .description("Get the current weather of a location")                .parameters(chatFunctionParameters)                .build();        chatTool.setFunction(chatFunction);        chatToolList.add(chatTool);        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()                .model(Constants.ModelChatGLM4)                .stream(Boolean.FALSE)                .invokeMethod(Constants.invokeMethod)                .messages(messages)                .requestId(requestId)                .tools(chatToolList)                .toolChoice("auto")                .build();        ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest);        ModelData data = invokeModelApiResp.getData();        return data;
复制代码


  • 而这里的信息实际上是一层层 抽丝剥茧 剥离出来的


    List<Choice> choices = data.getChoices();    System.out.println("choices.toString() = " + choices.toString());    for (Choice choice : choices) {        ChatMessage message = choice.getMessage();        System.out.println("message.getContent() = " + message.getContent());        //本来这里想返回具体的信息类但是发现 上面的的那个ModelApiResponse类 也是一个 统一返回类型 也包含这 请求状态码 之类的定义        return message;    }    return new ChatMessage();    try {        return mapper.writeValueAsString(invokeModelApiResp);    } catch (JsonProcessingException e) {            e.printStackTrace();    }    return mapper.writeValueAsString(new ModelApiResponse());    
复制代码


  • 可以看到我的这段代码 有多个 return 所以这实际上是一段假 代码

  • 每一个 return 实际上官方都 对应的 model 或者说 resoponse

  • controller 代码


    @PostMapping("/chat")    public R chat(@RequestParam("content") String content) throws JsonProcessingException {        /**         * data 中的 choices 是一个 List<Choice> 类型但是实际上只有一个所以索性直接获取数组下标0的对象         */        logger.info(ChatAPIUtils.InvokeApi(content).getChoices().get(0).getMessage().getContent().toString());        return R.ok().data("content", ChatAPIUtils.InvokeApi(content));    }
复制代码


  • 修改 由 service 层 调用 工具类

  • service 代码

  • service 接口


package com.codervibe.server.service; import com.zhipu.oapi.service.v4.image.ImageResult;import com.zhipu.oapi.service.v4.model.ModelData; public interface ChatService {    /**     * AI 对话     */    ModelData AIdialogue(String content);     /**     * AI  画图     */    ImageResult AIcreateimage(String content);}
复制代码


  • service 接口实现


 package com.codervibe.server.Impl; import com.codervibe.server.service.ChatService;import com.codervibe.utils.ChatAPIUtils;import com.fasterxml.jackson.core.JsonProcessingException;import com.zhipu.oapi.service.v4.image.ImageResult;import com.zhipu.oapi.service.v4.model.ModelData;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service; @Service("chatService")public class ChatServiceImpl implements ChatService {    Logger logger = LoggerFactory.getLogger(ChatServiceImpl.class);    /**     * AI 对话     * @param content     */    @Override    public ModelData AIdialogue(String content) {        logger.info(ChatAPIUtils.InvokeApi(content).getChoices().get(0).getMessage().getContent().toString());        return ChatAPIUtils.InvokeApi(content);    }     /**     * AI  画图     *     * @param content     */    @Override    public ImageResult AIcreateimage(String content) {        logger.info(ChatAPIUtils.CreateImage(content).getData().get(0).getUrl());        return ChatAPIUtils.CreateImage(content);    }}
复制代码


  • controller 层调用 service


****package com.codervibe.web.controller; import com.codervibe.server.service.ChatService;import com.codervibe.utils.ChatAPIUtils;import com.codervibe.web.common.response.R;import com.fasterxml.jackson.core.JsonProcessingException;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.slf4j.Logger;import org.slf4j.LoggerFactory; import javax.annotation.Resource; @RestController@RequestMapping("/chat")public class ChatController {    Logger logger = LoggerFactory.getLogger(ChatController.class);    @Resource    private ChatService chatService;    @PostMapping("/content")    public R chat(@RequestParam("content") String content) {        return R.ok().data("content", chatService.AIdialogue(content));    }    @PostMapping("/AIcreateimage")    public R AIcreateimage(@RequestParam("content") String content){        return R.ok().data("image",chatService.AIcreateimage(content));    }}
复制代码


  • 现在 虽然可以 和 AI 进行对话 但是 数据返回的速度实在是太慢 所以我打算 将 常见的问题和答案 存储在本地的数据库中以提升 数据返回的速度 这只是一个初步的想法

  • 最后的想法 还未实现 先这样


文章转载自:codervibe

原文链接:https://www.cnblogs.com/codervibe/p/18460483

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Springboot --- 使用国内的 AI 大模型 对话_Python_快乐非自愿限量之名_InfoQ写作社区