Springboot --- 使用国内的 AI 大模型 对话
code-vibe 2024-06-24 14:01:08 阅读 54
实在是不知道标题写什么了 可以在评论区给个建议哈哈哈哈 先用这个作为标题吧
尝试使用 国内给出的 AI 大模型做出一个 可以和 AI 对话的 网站出来
使用 智普AI 只能 在控制台中输出 对应的信息 不如就做一个 maven 的 项目调用对应的APIhttps://open.bigmodel.cn/dev/api#glm-4
<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 或者说 resoponsecontroller 代码
@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 进行对话 但是 数据返回的速度实在是太慢 所以我打算 将 常见的问题和答案 存储在本地的数据库中以提升 数据返回的速度 这只是一个初步的想法最后的想法 还未实现 先这样粉丝群 企鹅 179469398
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。