| | |
| | | */ |
| | | @PostMapping("/send") |
| | | public SseEmitter send(@RequestBody @Valid ChatRequest chatRequest) { |
| | | |
| | | openAiStreamClient = chatConfig.getOpenAiStreamClient(); |
| | | SseEmitter sseEmitter = new SseEmitter(0L); |
| | | SSEEventSourceListener openAIEventSourceListener = new SSEEventSourceListener(sseEmitter); |
| | | |
| | | List<Message> messages = chatRequest.getMessages(); |
| | | String content = messages.get(messages.size() - 1).getContent().toString(); |
| | | List<String> nearestList; |
| | |
| | | } |
| | | Message userMessage = Message.builder().content(content + (nearestList.size() > 0 ? "\n\n注æï¼åçé®é¢æ¶ï¼é¡»ä¸¥æ ¼æ ¹æ®æç»ä½ çç³»ç»ä¸ä¸æå
容åæè¿è¡åçï¼è¯·ä¸è¦èªå·±åæ¥,åçæ¶ä¿æåæ¥ææ¬çæ®µè½å±çº§" : "") ).role(Message.Role.USER).build(); |
| | | messages.add(userMessage); |
| | | |
| | | |
| | | ChatCompletion completion = ChatCompletion |
| | | .builder() |
| | | .messages(messages) |
| | |
| | | return sseEmitter; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æ ¹æ®ç¨æ·ä¿¡æ¯æ¥è¯¢æ¬å°ç¥è¯åº |
| | | */ |
| | |
| | | bo.setUid(LoginHelper.getUserId()); |
| | | return knowledgeInfoService.queryPageList(bo, pageQuery); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * æ°å¢ç¥è¯åº |
| | |
| | | * å é¤ç¥è¯åºéä»¶ |
| | | * |
| | | */ |
| | | @PostMapping("attach/remove/{kid}") |
| | | public R<Void> removeAttach(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") |
| | | @PathVariable String kid) { |
| | | attachService.removeKnowledgeAttach(kid); |
| | | @PostMapping("attach/remove/{docId}") |
| | | public R<Void> removeAttach(@NotEmpty(message = "主é®ä¸è½ä¸ºç©º") @PathVariable String docId) { |
| | | attachService.removeKnowledgeAttach(docId); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>mysql</groupId> |
| | | <artifactId>mysql-connector-java</artifactId> |
| | | <version>8.0.33</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.azure</groupId> |
| | | <artifactId>azure-ai-openai</artifactId> |
| | | <version>1.0.0-beta.12</version> |
| | |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>junit</groupId> |
| | | <artifactId>junit</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>junit</groupId> |
| | | <artifactId>junit</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.bigmodel.openapi</groupId> |
| | | <artifactId>oapi-java-sdk</artifactId> |
| | | <version>release-V4-2.3.0</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.squareup.okhttp</groupId> |
| | | <artifactId>okhttp</artifactId> |
| | | <version>2.7.5</version> |
| | | <scope>compile</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.Response; |
| | | import okhttp3.ResponseBody; |
| | | import okhttp3.sse.EventSource; |
| | | import okhttp3.sse.EventSourceListener; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | |
| | | import java.util.Objects; |
| | | import java.util.concurrent.CountDownLatch; |
| | | |
| | | /** |
| | | * æè¿°ï¼ sse |
| | | * |
| | | * @author https:www.unfbx.com |
| | | * 2023-06-15 |
| | | */ |
| | | @Slf4j |
| | | public class ConsoleEventSourceListenerV2 extends EventSourceListener { |
| | | @Getter |
| | | String args = ""; |
| | | final CountDownLatch countDownLatch; |
| | | |
| | | public ConsoleEventSourceListenerV2(CountDownLatch countDownLatch) { |
| | | this.countDownLatch = countDownLatch; |
| | | } |
| | | |
| | | @Override |
| | | public void onOpen(EventSource eventSource, Response response) { |
| | | log.info("OpenAI建ç«sseè¿æ¥..."); |
| | | } |
| | | |
| | | @Override |
| | | public void onEvent(EventSource eventSource, String id, String type, String data) { |
| | | log.info("OpenAIè¿åæ°æ®ï¼{}", data); |
| | | if (data.equals("[DONE]")) { |
| | | log.info("OpenAIè¿åæ°æ®ç»æäº"); |
| | | countDownLatch.countDown(); |
| | | return; |
| | | } |
| | | ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(data, ChatCompletionResponse.class); |
| | | if(Objects.nonNull(chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall())){ |
| | | args += chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall().getArguments(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onClosed(EventSource eventSource) { |
| | | log.info("OpenAIå
³ésseè¿æ¥..."); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | @Override |
| | | public void onFailure(EventSource eventSource, Throwable t, Response response) { |
| | | if(Objects.isNull(response)){ |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸:{}", t); |
| | | eventSource.cancel(); |
| | | return; |
| | | } |
| | | ResponseBody body = response.body(); |
| | | if (Objects.nonNull(body)) { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", body.string(), t); |
| | | } else { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", response, t); |
| | | } |
| | | eventSource.cancel(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import lombok.Getter; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.Response; |
| | | import okhttp3.ResponseBody; |
| | | import okhttp3.sse.EventSource; |
| | | import okhttp3.sse.EventSourceListener; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | import org.ruoyi.common.chat.entity.chat.Message; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCallFunction; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCalls; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.concurrent.CountDownLatch; |
| | | |
| | | /** |
| | | * æè¿°ï¼ demoæµè¯å®ç°ç±»ï¼ä»
ä¾æè·¯åè |
| | | * |
| | | * @author https:www.unfbx.com |
| | | * 2023-11-12 |
| | | */ |
| | | @Slf4j |
| | | public class ConsoleEventSourceListenerV3 extends EventSourceListener { |
| | | @Getter |
| | | List<ToolCalls> choices = new ArrayList<>(); |
| | | @Getter |
| | | ToolCalls toolCalls = new ToolCalls(); |
| | | @Getter |
| | | ToolCallFunction toolCallFunction = ToolCallFunction.builder().name("").arguments("").build(); |
| | | final CountDownLatch countDownLatch; |
| | | |
| | | public ConsoleEventSourceListenerV3(CountDownLatch countDownLatch) { |
| | | this.countDownLatch = countDownLatch; |
| | | } |
| | | |
| | | @Override |
| | | public void onOpen(EventSource eventSource, Response response) { |
| | | log.info("OpenAI建ç«sseè¿æ¥..."); |
| | | } |
| | | |
| | | @Override |
| | | public void onEvent(EventSource eventSource, String id, String type, String data) { |
| | | log.info("OpenAIè¿åæ°æ®ï¼{}", data); |
| | | if (data.equals("[DONE]")) { |
| | | log.info("OpenAIè¿åæ°æ®ç»æäº"); |
| | | return; |
| | | } |
| | | ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(data, ChatCompletionResponse.class); |
| | | Message delta = chatCompletionResponse.getChoices().get(0).getDelta(); |
| | | if (CollectionUtil.isNotEmpty(delta.getToolCalls())) { |
| | | choices.addAll(delta.getToolCalls()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onClosed(EventSource eventSource) { |
| | | if(CollectionUtil.isNotEmpty(choices)){ |
| | | toolCalls.setId(choices.get(0).getId()); |
| | | toolCalls.setType(choices.get(0).getType()); |
| | | choices.forEach(e -> { |
| | | toolCallFunction.setName(e.getFunction().getName()); |
| | | toolCallFunction.setArguments(toolCallFunction.getArguments() + e.getFunction().getArguments()); |
| | | toolCalls.setFunction(toolCallFunction); |
| | | }); |
| | | } |
| | | log.info("OpenAIå
³ésseè¿æ¥..."); |
| | | countDownLatch.countDown(); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | @Override |
| | | public void onFailure(EventSource eventSource, Throwable t, Response response) { |
| | | if(Objects.isNull(response)){ |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸:{}", t); |
| | | eventSource.cancel(); |
| | | return; |
| | | } |
| | | ResponseBody body = response.body(); |
| | | if (Objects.nonNull(body)) { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", body.string(), t); |
| | | } else { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", response, t); |
| | | } |
| | | eventSource.cancel(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.OkHttpClient; |
| | | import okhttp3.logging.HttpLoggingInterceptor; |
| | | import org.junit.Before; |
| | | import org.junit.Test; |
| | | import org.ruoyi.common.chat.entity.chat.*; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCallFunction; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCalls; |
| | | import org.ruoyi.common.chat.entity.chat.tool.Tools; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolsFunction; |
| | | import org.ruoyi.common.chat.openai.OpenAiClient; |
| | | import org.ruoyi.common.chat.openai.OpenAiStreamClient; |
| | | import org.ruoyi.common.chat.openai.function.KeyRandomStrategy; |
| | | import org.ruoyi.common.chat.openai.interceptor.DynamicKeyOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAILogger; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAiResponseInterceptor; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | import org.ruoyi.common.chat.plugin.CmdPlugin; |
| | | import org.ruoyi.common.chat.plugin.CmdReq; |
| | | import org.ruoyi.common.chat.sse.ConsoleEventSourceListener; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.concurrent.CountDownLatch; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * æè¿°ï¼ |
| | | * |
| | | * @author ageerle@163.com |
| | | * date 2025/3/8 |
| | | */ |
| | | @Slf4j |
| | | public class PluginTest { |
| | | |
| | | private OpenAiClient openAiClient; |
| | | private OpenAiStreamClient openAiStreamClient; |
| | | |
| | | @Before |
| | | public void before() { |
| | | //å¯ä»¥ä¸ºnull |
| | | // Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890)); |
| | | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger()); |
| | | //ï¼ï¼ï¼ï¼åä¸å«åç产æè
æµè¯ç¯å¢æå¼BODYçº§å«æ¥å¿ï¼ï¼ï¼ï¼ |
| | | //ï¼ï¼ï¼ç产æè
æµè¯ç¯å¢å»ºè®®è®¾ç½®ä¸ºè¿ä¸ç§çº§å«ï¼NONE,BASIC,HEADERS,ï¼ï¼ï¼ |
| | | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); |
| | | OkHttpClient okHttpClient = new OkHttpClient |
| | | .Builder() |
| | | // .proxy(proxy) |
| | | .addInterceptor(httpLoggingInterceptor) |
| | | .addInterceptor(new OpenAiResponseInterceptor()) |
| | | .connectTimeout(10, TimeUnit.SECONDS) |
| | | .writeTimeout(30, TimeUnit.SECONDS) |
| | | .readTimeout(30, TimeUnit.SECONDS) |
| | | .build(); |
| | | openAiClient = OpenAiClient.builder() |
| | | //æ¯æå¤keyä¼ å
¥ï¼è¯·æ±æ¶åéæºéæ© |
| | | .apiKey(Arrays.asList("sk-xx")) |
| | | //èªå®ä¹keyçè·åçç¥ï¼é»è®¤KeyRandomStrategy |
| | | //.keyStrategy(new KeyRandomStrategy()) |
| | | .keyStrategy(new KeyRandomStrategy()) |
| | | .okHttpClient(okHttpClient) |
| | | //èªå·±åäºä»£çå°±ä¼ ä»£çå°åï¼æ²¡æå¯ä¸ä¸ä¼ ,(å
³æ³¨å
¬ä¼å·åå¤ï¼openai ï¼è·åå
è´¹çæµè¯ä»£çå°å) |
| | | .apiHost("https://api.pandarobot.chat/") |
| | | .build(); |
| | | |
| | | openAiStreamClient = OpenAiStreamClient.builder() |
| | | //æ¯æå¤keyä¼ å
¥ï¼è¯·æ±æ¶åéæºéæ© |
| | | .apiKey(Arrays.asList("sk-xx")) |
| | | //èªå®ä¹keyçè·åçç¥ï¼é»è®¤KeyRandomStrategy |
| | | .keyStrategy(new KeyRandomStrategy()) |
| | | .authInterceptor(new DynamicKeyOpenAiAuthInterceptor()) |
| | | .okHttpClient(okHttpClient) |
| | | //èªå·±åäºä»£çå°±ä¼ ä»£çå°åï¼æ²¡æå¯ä¸ä¸ä¼ ,(å
³æ³¨å
¬ä¼å·åå¤ï¼openai ï¼è·åå
è´¹çæµè¯ä»£çå°å) |
| | | .apiHost("https://api.pandarobot.chat/") |
| | | .build(); |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void chatFunction() { |
| | | //模åï¼GPT_3_5_TURBO_16K_0613 |
| | | Message message = Message.builder().role(Message.Role.USER).content("ç»æè¾åºä¸ä¸ªé¿åº¦ä¸º2ç䏿è¯è¯ï¼å¹¶è§£éä¸è¯è¯å¯¹åºç©åçç¨é").build(); |
| | | //屿§ä¸ |
| | | JSONObject wordLength = new JSONObject(); |
| | | wordLength.put("type", "number"); |
| | | wordLength.put("description", "è¯è¯çé¿åº¦"); |
| | | //屿§äº |
| | | JSONObject language = new JSONObject(); |
| | | language.put("type", "string"); |
| | | language.put("enum", Arrays.asList("zh", "en")); |
| | | language.put("description", "è¯è¨ç±»åï¼ä¾å¦ï¼zhä»£è¡¨ä¸æãen代表è±è¯"); |
| | | //åæ° |
| | | JSONObject properties = new JSONObject(); |
| | | properties.put("wordLength", wordLength); |
| | | properties.put("language", language); |
| | | |
| | | Parameters parameters = Parameters.builder() |
| | | .type("object") |
| | | .properties(properties) |
| | | .required(Collections.singletonList("wordLength")).build(); |
| | | Functions functions = Functions.builder() |
| | | .name("getOneWord") |
| | | .description("è·åä¸ä¸ªæå®é¿åº¦åè¯è¨ç±»åçè¯è¯") |
| | | .parameters(parameters) |
| | | .build(); |
| | | |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | .functions(Collections.singletonList(functions)) |
| | | .functionCall("auto") |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); |
| | | |
| | | ChatChoice chatChoice = chatCompletionResponse.getChoices().get(0); |
| | | log.info("æé çæ¹æ³å¼ï¼{}", chatChoice.getMessage().getFunctionCall()); |
| | | log.info("æé çæ¹æ³åç§°ï¼{}", chatChoice.getMessage().getFunctionCall().getName()); |
| | | log.info("æé çæ¹æ³åæ°ï¼{}", chatChoice.getMessage().getFunctionCall().getArguments()); |
| | | WordParam wordParam = JSONUtil.toBean(chatChoice.getMessage().getFunctionCall().getArguments(), WordParam.class); |
| | | String oneWord = getOneWord(wordParam); |
| | | |
| | | FunctionCall functionCall = FunctionCall.builder() |
| | | .arguments(chatChoice.getMessage().getFunctionCall().getArguments()) |
| | | .name("getOneWord") |
| | | .build(); |
| | | Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("æ¹æ³åæ°").functionCall(functionCall).build(); |
| | | String content |
| | | = "{ " + |
| | | "\"wordLength\": \"3\", " + |
| | | "\"language\": \"zh\", " + |
| | | "\"word\": \"" + oneWord + "\"," + |
| | | "\"ç¨é\": [\"ç´æ¥å\", \"åæ²æ\", \"å®å\"]" + |
| | | "}"; |
| | | Message message3 = Message.builder().role(Message.Role.FUNCTION).name("getOneWord").content(content).build(); |
| | | List<Message> messageList = Arrays.asList(message, message2, message3); |
| | | ChatCompletion chatCompletionV2 = ChatCompletion |
| | | .builder() |
| | | .messages(messageList) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponseV2 = openAiClient.chatCompletion(chatCompletionV2); |
| | | log.info("èªå®ä¹çæ¹æ³è¿åå¼ï¼{}",chatCompletionResponseV2.getChoices().get(0).getMessage().getContent()); |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void plugin() { |
| | | CmdPlugin plugin = new CmdPlugin(CmdReq.class); |
| | | // æä»¶åç§° |
| | | plugin.setName("å½ä»¤è¡å·¥å
·"); |
| | | // æ¹æ³åç§° |
| | | plugin.setFunction("openCmd"); |
| | | // æ¹æ³è¯´æ |
| | | plugin.setDescription("æä¾ä¸ä¸ªå½ä»¤è¡æä»¤,æ¯å¦<è®°äºæ¬>,æä»¤ä½¿ç¨ä¸æ,以functionè¿åç»æä¸ºå"); |
| | | |
| | | PluginAbstract.Arg arg = new PluginAbstract.Arg(); |
| | | // åæ°åç§° |
| | | arg.setName("cmd"); |
| | | // åæ°è¯´æ |
| | | arg.setDescription("å½ä»¤è¡æä»¤"); |
| | | // åæ°ç±»å |
| | | arg.setType("string"); |
| | | arg.setRequired(true); |
| | | plugin.setArgs(Collections.singletonList(arg)); |
| | | |
| | | Message message2 = Message.builder().role(Message.Role.USER).content("帮ææå¼è®¡ç®å¨,ç»åä¸ä¸æå¤ææä»¤æ¯å¦æ§è¡æå,åªç¨å夿åæè
失败").build(); |
| | | List<Message> messages = new ArrayList<>(); |
| | | messages.add(message2); |
| | | //æå个éè½½æ¹æ³ï¼é½å¯ä»¥ä½¿ç¨ |
| | | ChatCompletionResponse response = openAiClient.chatCompletionWithPlugin(messages,"gpt-4o-mini",plugin); |
| | | log.info("èªå®ä¹çæ¹æ³è¿åå¼ï¼{}", response.getChoices().get(0).getMessage().getContent()); |
| | | } |
| | | |
| | | /** |
| | | * èªå®ä¹è¿åæ°æ®æ ¼å¼ |
| | | */ |
| | | @Test |
| | | public void diyReturnDataModelChat() { |
| | | Message message = Message.builder().role(Message.Role.USER).content("éæºè¾åº10个åè¯ï¼ä½¿ç¨jsonè¾åº").build(); |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | .responseFormat(ResponseFormat.builder().type(ResponseFormat.Type.JSON_OBJECT.getName()).build()) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); |
| | | chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage())); |
| | | } |
| | | |
| | | @Test |
| | | public void streamPlugin() { |
| | | WeatherPlugin plugin = new WeatherPlugin(WeatherReq.class); |
| | | plugin.setName("ç¥å¿å¤©æ°"); |
| | | plugin.setFunction("getLocationWeather"); |
| | | plugin.setDescription("æä¾ä¸ä¸ªå°åï¼æ¹æ³å°ä¼è·å该å°åç天æ°ç宿¶æ¸©åº¦ä¿¡æ¯ã"); |
| | | PluginAbstract.Arg arg = new PluginAbstract.Arg(); |
| | | arg.setName("location"); |
| | | arg.setDescription("å°å"); |
| | | arg.setType("string"); |
| | | arg.setRequired(true); |
| | | plugin.setArgs(Collections.singletonList(arg)); |
| | | |
| | | // Message message1 = Message.builder().role(Message.Role.USER).content("秦å§çç»ä¸äºåªå
å½ã").build(); |
| | | Message message2 = Message.builder().role(Message.Role.USER).content("è·å䏿µ·å¸ç天æ°ç°å¨å¤å°åº¦ï¼ç¶ååç»åº3个æ¨èçæ·å¤è¿å¨ã").build(); |
| | | List<Message> messages = new ArrayList<>(); |
| | | // messages.add(message1); |
| | | messages.add(message2); |
| | | //é»è®¤æ¨¡åï¼GPT_3_5_TURBO_16K_0613 |
| | | //æå个éè½½æ¹æ³ï¼é½å¯ä»¥ä½¿ç¨ |
| | | openAiStreamClient.streamChatCompletionWithPlugin(messages, ChatCompletion.Model.GPT_4_1106_PREVIEW.getName(), new ConsoleEventSourceListener(), plugin); |
| | | CountDownLatch countDownLatch = new CountDownLatch(1); |
| | | try { |
| | | countDownLatch.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * tools使ç¨ç¤ºä¾ |
| | | */ |
| | | @Test |
| | | public void toolsChat() { |
| | | Message message = Message.builder().role(Message.Role.USER).content("ç»æè¾åºä¸ä¸ªé¿åº¦ä¸º2ç䏿è¯è¯ï¼å¹¶è§£éä¸è¯è¯å¯¹åºç©åçç¨é").build(); |
| | | //屿§ä¸ |
| | | JSONObject wordLength = new JSONObject(); |
| | | wordLength.put("type", "number"); |
| | | wordLength.put("description", "è¯è¯çé¿åº¦"); |
| | | //屿§äº |
| | | JSONObject language = new JSONObject(); |
| | | language.put("type", "string"); |
| | | language.put("enum", Arrays.asList("zh", "en")); |
| | | language.put("description", "è¯è¨ç±»åï¼ä¾å¦ï¼zhä»£è¡¨ä¸æãen代表è±è¯"); |
| | | //åæ° |
| | | JSONObject properties = new JSONObject(); |
| | | properties.put("wordLength", wordLength); |
| | | properties.put("language", language); |
| | | Parameters parameters = Parameters.builder() |
| | | .type("object") |
| | | .properties(properties) |
| | | .required(Collections.singletonList("wordLength")).build(); |
| | | Tools tools = Tools.builder() |
| | | .type(Tools.Type.FUNCTION.getName()) |
| | | .function(ToolsFunction.builder().name("getOneWord").description("è·åä¸ä¸ªæå®é¿åº¦åè¯è¨ç±»åçè¯è¯").parameters(parameters).build()) |
| | | .build(); |
| | | |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | .tools(Collections.singletonList(tools)) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); |
| | | |
| | | ChatChoice chatChoice = chatCompletionResponse.getChoices().get(0); |
| | | log.info("æé çæ¹æ³å¼ï¼{}", chatChoice.getMessage().getToolCalls()); |
| | | |
| | | ToolCalls openAiReturnToolCalls = chatChoice.getMessage().getToolCalls().get(0); |
| | | WordParam wordParam = JSONUtil.toBean(openAiReturnToolCalls.getFunction().getArguments(), WordParam.class); |
| | | String oneWord = getOneWord(wordParam); |
| | | |
| | | |
| | | ToolCallFunction tcf = ToolCallFunction.builder().name("getOneWord").arguments(openAiReturnToolCalls.getFunction().getArguments()).build(); |
| | | ToolCalls tc = ToolCalls.builder().id(openAiReturnToolCalls.getId()).type(ToolCalls.Type.FUNCTION.getName()).function(tcf).build(); |
| | | //æé tool call |
| | | Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("æ¹æ³åæ°").toolCalls(Collections.singletonList(tc)).build(); |
| | | String content |
| | | = "{ " + |
| | | "\"wordLength\": \"3\", " + |
| | | "\"language\": \"zh\", " + |
| | | "\"word\": \"" + oneWord + "\"," + |
| | | "\"ç¨é\": [\"ç´æ¥å\", \"åæ²æ\", \"å®å\"]" + |
| | | "}"; |
| | | Message message3 = Message.builder().toolCallId(openAiReturnToolCalls.getId()).role(Message.Role.TOOL).name("getOneWord").content(content).build(); |
| | | List<Message> messageList = Arrays.asList(message, message2, message3); |
| | | ChatCompletion chatCompletionV2 = ChatCompletion |
| | | .builder() |
| | | .messages(messageList) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponseV2 = openAiClient.chatCompletion(chatCompletionV2); |
| | | log.info("èªå®ä¹çæ¹æ³è¿åå¼ï¼{}", chatCompletionResponseV2.getChoices().get(0).getMessage().getContent()); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * toolsæµå¼è¾åºä½¿ç¨ç¤ºä¾ |
| | | */ |
| | | @Test |
| | | public void streamToolsChat() { |
| | | |
| | | CountDownLatch countDownLatch = new CountDownLatch(1); |
| | | ConsoleEventSourceListenerV3 eventSourceListener = new ConsoleEventSourceListenerV3(countDownLatch); |
| | | |
| | | Message message = Message.builder().role(Message.Role.USER).content("ç»æè¾åºä¸ä¸ªé¿åº¦ä¸º2ç䏿è¯è¯ï¼å¹¶è§£éä¸è¯è¯å¯¹åºç©åçç¨é").build(); |
| | | //屿§ä¸ |
| | | JSONObject wordLength = new JSONObject(); |
| | | wordLength.put("type", "number"); |
| | | wordLength.put("description", "è¯è¯çé¿åº¦"); |
| | | //屿§äº |
| | | JSONObject language = new JSONObject(); |
| | | language.put("type", "string"); |
| | | language.put("enum", Arrays.asList("zh", "en")); |
| | | language.put("description", "è¯è¨ç±»åï¼ä¾å¦ï¼zhä»£è¡¨ä¸æãen代表è±è¯"); |
| | | //åæ° |
| | | JSONObject properties = new JSONObject(); |
| | | properties.put("wordLength", wordLength); |
| | | properties.put("language", language); |
| | | Parameters parameters = Parameters.builder() |
| | | .type("object") |
| | | .properties(properties) |
| | | .required(Collections.singletonList("wordLength")).build(); |
| | | Tools tools = Tools.builder() |
| | | .type(Tools.Type.FUNCTION.getName()) |
| | | .function(ToolsFunction.builder().name("getOneWord").description("è·åä¸ä¸ªæå®é¿åº¦åè¯è¨ç±»åçè¯è¯").parameters(parameters).build()) |
| | | .build(); |
| | | |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | .tools(Collections.singletonList(tools)) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | openAiStreamClient.streamChatCompletion(chatCompletion, eventSourceListener); |
| | | |
| | | try { |
| | | countDownLatch.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | ToolCalls openAiReturnToolCalls = eventSourceListener.getToolCalls(); |
| | | WordParam wordParam = JSONUtil.toBean(openAiReturnToolCalls.getFunction().getArguments(), WordParam.class); |
| | | String oneWord = getOneWord(wordParam); |
| | | |
| | | |
| | | ToolCallFunction tcf = ToolCallFunction.builder().name("getOneWord").arguments(openAiReturnToolCalls.getFunction().getArguments()).build(); |
| | | ToolCalls tc = ToolCalls.builder().id(openAiReturnToolCalls.getId()).type(ToolCalls.Type.FUNCTION.getName()).function(tcf).build(); |
| | | //æé tool call |
| | | Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("æ¹æ³åæ°").toolCalls(Collections.singletonList(tc)).build(); |
| | | String content |
| | | = "{ " + |
| | | "\"wordLength\": \"3\", " + |
| | | "\"language\": \"zh\", " + |
| | | "\"word\": \"" + oneWord + "\"," + |
| | | "\"ç¨é\": [\"ç´æ¥å\", \"åæ²æ\", \"å®å\"]" + |
| | | "}"; |
| | | Message message3 = Message.builder().toolCallId(openAiReturnToolCalls.getId()).role(Message.Role.TOOL).name("getOneWord").content(content).build(); |
| | | List<Message> messageList = Arrays.asList(message, message2, message3); |
| | | ChatCompletion chatCompletionV2 = ChatCompletion |
| | | .builder() |
| | | .messages(messageList) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | |
| | | |
| | | CountDownLatch countDownLatch1 = new CountDownLatch(1); |
| | | openAiStreamClient.streamChatCompletion(chatCompletionV2, new ConsoleEventSourceListenerV3(countDownLatch)); |
| | | try { |
| | | countDownLatch1.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | try { |
| | | countDownLatch1.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | @Data |
| | | @Builder |
| | | static class WordParam { |
| | | private int wordLength; |
| | | @Builder.Default |
| | | private String language = "zh"; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åä¸ä¸ªè¯è¯(æ ¹æ®è¯è¨åå符é¿åº¦æ¥è¯¢) |
| | | * @param wordParam |
| | | * @return |
| | | */ |
| | | public String getOneWord(WordParam wordParam) { |
| | | |
| | | List<String> zh = Arrays.asList("大é¦è", "åå¯ç", "è¹æ"); |
| | | List<String> en = Arrays.asList("apple", "banana", "cantaloupe"); |
| | | if (wordParam.getLanguage().equals("zh")) { |
| | | for (String e : zh) { |
| | | if (e.length() == wordParam.getWordLength()) { |
| | | return e; |
| | | } |
| | | } |
| | | } |
| | | if (wordParam.getLanguage().equals("en")) { |
| | | for (String e : en) { |
| | | if (e.length() == wordParam.getWordLength()) { |
| | | return e; |
| | | } |
| | | } |
| | | } |
| | | return "西ç"; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | |
| | | public class WeatherPlugin extends PluginAbstract<WeatherReq, WeatherResp> { |
| | | |
| | | public WeatherPlugin(Class<?> r) { |
| | | super(r); |
| | | } |
| | | |
| | | @Override |
| | | public WeatherResp func(WeatherReq args) { |
| | | WeatherResp weatherResp = new WeatherResp(); |
| | | weatherResp.setTemp("25å°28ææ°åº¦"); |
| | | weatherResp.setLevel(3); |
| | | return weatherResp; |
| | | } |
| | | |
| | | @Override |
| | | public String content(WeatherResp weatherResp) { |
| | | return "å½åå¤©æ°æ¸©åº¦ï¼" + weatherResp.getTemp() + "ï¼é£åç级ï¼" + weatherResp.getLevel(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | |
| | | @Data |
| | | public class WeatherReq extends PluginParam { |
| | | /** |
| | | * åå¸ |
| | | */ |
| | | private String location; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class WeatherResp { |
| | | /** |
| | | * 温度 |
| | | */ |
| | | private String temp; |
| | | /** |
| | | * é£åç级 |
| | | */ |
| | | private Integer level; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo.zhipu; |
| | | |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | |
| | | import com.fasterxml.jackson.databind.node.ObjectNode; |
| | | import com.zhipu.oapi.ClientV4; |
| | | import com.zhipu.oapi.Constants; |
| | | import com.zhipu.oapi.service.v4.deserialize.MessageDeserializeFactory; |
| | | import com.zhipu.oapi.service.v4.model.*; |
| | | import io.reactivex.Flowable; |
| | | import org.junit.Test; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | |
| | | public class AllToolsTest { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(AllToolsTest.class); |
| | | private static final String API_SECRET_KEY = "28550a39d4cfaabbbf38df04dd3931f5.IUvfTThUf0xBF5l0"; |
| | | |
| | | private static final ClientV4 client = new ClientV4.Builder(API_SECRET_KEY) |
| | | .networkConfig(300, 100, 100, 100, TimeUnit.SECONDS) |
| | | .connectionPool(new okhttp3.ConnectionPool(8, 1, TimeUnit.SECONDS)) |
| | | .build(); |
| | | private static final ObjectMapper mapper = MessageDeserializeFactory.defaultObjectMapper(); |
| | | // 请èªå®ä¹èªå·±çä¸å¡id |
| | | private static final String requestIdTemplate = "mycompany-%d"; |
| | | |
| | | |
| | | @Test |
| | | public void test1() throws JsonProcessingException { |
| | | |
| | | |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "å¸®ææ¥è¯¢å京天æ°"); |
| | | messages.add(chatMessage); |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | // 彿°è°ç¨åæ°æå»ºé¨å |
| | | List<ChatTool> chatToolList = new ArrayList<>(); |
| | | ChatTool chatTool = new ChatTool(); |
| | | |
| | | chatTool.setType("code_interpreter"); |
| | | ObjectNode objectNode = mapper.createObjectNode(); |
| | | objectNode.put("code", "å京天æ°"); |
| | | // chatTool.set(chatFunction); |
| | | chatToolList.add(chatTool); |
| | | |
| | | |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model("glm-4-alltools") |
| | | .stream(Boolean.TRUE) |
| | | .invokeMethod(Constants.invokeMethod) |
| | | .messages(messages) |
| | | .tools(chatToolList) |
| | | .toolChoice("auto") |
| | | .requestId(requestId) |
| | | .build(); |
| | | ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | if (sseModelApiResp.isSuccess()) { |
| | | AtomicBoolean isFirst = new AtomicBoolean(true); |
| | | List<Choice> choices = new ArrayList<>(); |
| | | AtomicReference<ChatMessageAccumulator> lastAccumulator = new AtomicReference<>(); |
| | | |
| | | mapStreamToAccumulator(sseModelApiResp.getFlowable()) |
| | | .doOnNext(accumulator -> { |
| | | { |
| | | if (isFirst.getAndSet(false)) { |
| | | logger.info("Response: "); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { |
| | | String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); |
| | | logger.info("tool_calls: {}", jsonString); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { |
| | | logger.info(accumulator.getDelta().getContent()); |
| | | } |
| | | choices.add(accumulator.getChoice()); |
| | | lastAccumulator.set(accumulator); |
| | | |
| | | } |
| | | }) |
| | | .doOnComplete(() -> System.out.println("Stream completed.")) |
| | | .doOnError(throwable -> System.err.println("Error: " + throwable)) // Handle errors |
| | | .blockingSubscribe();// Use blockingSubscribe instead of blockingGet() |
| | | |
| | | ChatMessageAccumulator chatMessageAccumulator = lastAccumulator.get(); |
| | | ModelData data = new ModelData(); |
| | | data.setChoices(choices); |
| | | if (chatMessageAccumulator != null) { |
| | | data.setUsage(chatMessageAccumulator.getUsage()); |
| | | data.setId(chatMessageAccumulator.getId()); |
| | | data.setCreated(chatMessageAccumulator.getCreated()); |
| | | } |
| | | data.setRequestId(chatCompletionRequest.getRequestId()); |
| | | sseModelApiResp.setFlowable(null);// æå°å置空 |
| | | sseModelApiResp.setData(data); |
| | | } |
| | | logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp)); |
| | | client.getConfig().getHttpClient().dispatcher().executorService().shutdown(); |
| | | |
| | | client.getConfig().getHttpClient().connectionPool().evictAll(); |
| | | // List all active threads |
| | | for (Thread t : Thread.getAllStackTraces().keySet()) { |
| | | logger.info("Thread: " + t.getName() + " State: " + t.getState()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable) { |
| | | return flowable.map(chunk -> { |
| | | return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0), chunk.getUsage(), chunk.getCreated(), chunk.getId()); |
| | | }); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo.zhipu; |
| | | |
| | | 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.core.response.HttpxBinaryResponseContent; |
| | | import com.zhipu.oapi.service.v4.batchs.BatchCreateParams; |
| | | import com.zhipu.oapi.service.v4.batchs.BatchResponse; |
| | | import com.zhipu.oapi.service.v4.batchs.QueryBatchResponse; |
| | | import com.zhipu.oapi.service.v4.embedding.EmbeddingApiResponse; |
| | | import com.zhipu.oapi.service.v4.embedding.EmbeddingRequest; |
| | | import com.zhipu.oapi.service.v4.file.*; |
| | | import com.zhipu.oapi.service.v4.fine_turning.*; |
| | | 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 org.junit.Test; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | |
| | | public class V4Test { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(V4Test.class); |
| | | private static final String API_SECRET_KEY = "28550a39d4cfaabbbf38df04dd3931f5.IUvfTThUf0xBF5l0"; |
| | | |
| | | |
| | | private static final ClientV4 client = new ClientV4.Builder(API_SECRET_KEY) |
| | | .enableTokenCache() |
| | | .networkConfig(300, 100, 100, 100, TimeUnit.SECONDS) |
| | | .connectionPool(new okhttp3.ConnectionPool(8, 1, TimeUnit.SECONDS)) |
| | | .build(); |
| | | |
| | | // 请èªå®ä¹èªå·±çä¸å¡id |
| | | private static final String requestIdTemplate = "mycompany-%d"; |
| | | |
| | | private static final ObjectMapper mapper = new ObjectMapper(); |
| | | |
| | | |
| | | 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); |
| | | return mapper; |
| | | } |
| | | |
| | | @Test |
| | | public void test() { |
| | | |
| | | } |
| | | |
| | | /** |
| | | * sse-V4ï¼functionè°ç¨ |
| | | */ |
| | | @Test |
| | | public void testFunctionSSE() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "æé½å°å京è¦å¤ä¹
ï¼å¤©æ°å¦ä½"); |
| | | 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); |
| | | HashMap<String, Object> extraJson = new HashMap<>(); |
| | | extraJson.put("temperature", 0.5); |
| | | extraJson.put("max_tokens", 50); |
| | | |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model(Constants.ModelChatGLM4) |
| | | .stream(Boolean.TRUE) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .tools(chatToolList) |
| | | .toolChoice("auto") |
| | | .extraJson(extraJson) |
| | | .build(); |
| | | ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | if (sseModelApiResp.isSuccess()) { |
| | | AtomicBoolean isFirst = new AtomicBoolean(true); |
| | | List<Choice> choices = new ArrayList<>(); |
| | | ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) |
| | | .doOnNext(accumulator -> { |
| | | { |
| | | if (isFirst.getAndSet(false)) { |
| | | logger.info("Response: "); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { |
| | | String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); |
| | | logger.info("tool_calls: {}", jsonString); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { |
| | | logger.info(accumulator.getDelta().getContent()); |
| | | } |
| | | choices.add(accumulator.getChoice()); |
| | | } |
| | | }) |
| | | .doOnComplete(System.out::println) |
| | | .lastElement() |
| | | .blockingGet(); |
| | | |
| | | |
| | | ModelData data = new ModelData(); |
| | | data.setChoices(choices); |
| | | data.setUsage(chatMessageAccumulator.getUsage()); |
| | | data.setId(chatMessageAccumulator.getId()); |
| | | data.setCreated(chatMessageAccumulator.getCreated()); |
| | | data.setRequestId(chatCompletionRequest.getRequestId()); |
| | | sseModelApiResp.setFlowable(null);// æå°å置空 |
| | | sseModelApiResp.setData(data); |
| | | } |
| | | logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * sse-V4ï¼éfunctionè°ç¨ |
| | | */ |
| | | @Test |
| | | public void testNonFunctionSSE() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLMåä½ åªä¸ªæ´å¼ºå¤§"); |
| | | messages.add(chatMessage); |
| | | HashMap<String, Object> extraJson = new HashMap<>(); |
| | | extraJson.put("temperature", 0.5); |
| | | extraJson.put("max_tokens", 3); |
| | | |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model(Constants.ModelChatGLM4) |
| | | .stream(Boolean.TRUE) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .extraJson(extraJson) |
| | | .build(); |
| | | ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | // stream å¤çæ¹æ³ |
| | | if (sseModelApiResp.isSuccess()) { |
| | | AtomicBoolean isFirst = new AtomicBoolean(true); |
| | | List<Choice> choices = new ArrayList<>(); |
| | | ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) |
| | | .doOnNext(accumulator -> { |
| | | { |
| | | if (isFirst.getAndSet(false)) { |
| | | logger.info("Response: "); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { |
| | | String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); |
| | | logger.info("tool_calls: {}", jsonString); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { |
| | | logger.info("accumulator.getDelta().getContent(): {}", accumulator.getDelta().getContent()); |
| | | } |
| | | choices.add(accumulator.getChoice()); |
| | | } |
| | | }) |
| | | .doOnComplete(System.out::println) |
| | | .lastElement() |
| | | .blockingGet(); |
| | | |
| | | |
| | | ModelData data = new ModelData(); |
| | | data.setChoices(choices); |
| | | data.setUsage(chatMessageAccumulator.getUsage()); |
| | | data.setId(chatMessageAccumulator.getId()); |
| | | data.setCreated(chatMessageAccumulator.getCreated()); |
| | | data.setRequestId(chatCompletionRequest.getRequestId()); |
| | | sseModelApiResp.setFlowable(null);// æå°å置空 |
| | | sseModelApiResp.setData(data); |
| | | } |
| | | logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * V4-忥functionè°ç¨ |
| | | */ |
| | | @Test |
| | | public void testFunctionInvoke() { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ä½ å¯ä»¥åä»ä¹"); |
| | | 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); |
| | | |
| | | |
| | | ChatTool chatTool1 = new ChatTool(); |
| | | chatTool1.setType(ChatToolType.WEB_SEARCH.value()); |
| | | WebSearch webSearch = new WebSearch(); |
| | | webSearch.setSearch_query("æ¸
åçåå¦ç"); |
| | | webSearch.setSearch_result(true); |
| | | webSearch.setEnable(false); |
| | | chatTool1.setWeb_search(webSearch); |
| | | |
| | | chatToolList.add(chatTool); |
| | | chatToolList.add(chatTool1); |
| | | |
| | | 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 { |
| | | logger.info("model output: {}", mapper.writeValueAsString(invokeModelApiResp)); |
| | | } catch (JsonProcessingException e) { |
| | | logger.error("model output error", e); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * V4-忥éfunctionè°ç¨ |
| | | */ |
| | | @Test |
| | | public void testNonFunctionInvoke() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLMåä½ åªä¸ªæ´å¼ºå¤§"); |
| | | messages.add(chatMessage); |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | |
| | | |
| | | HashMap<String, Object> extraJson = new HashMap<>(); |
| | | extraJson.put("temperature", 0.5); |
| | | extraJson.put("max_tokens", 3); |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model(Constants.ModelChatGLM4) |
| | | .stream(Boolean.FALSE) |
| | | .invokeMethod(Constants.invokeMethod) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .extraJson(extraJson) |
| | | .build(); |
| | | ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(invokeModelApiResp)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * V4-忥éfunctionè°ç¨ |
| | | */ |
| | | @Test |
| | | public void testCharGlmInvoke() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLMåä½ åªä¸ªæ´å¼ºå¤§"); |
| | | messages.add(chatMessage); |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | |
| | | |
| | | HashMap<String, Object> extraJson = new HashMap<>(); |
| | | extraJson.put("temperature", 0.5); |
| | | |
| | | ChatMeta meta = new ChatMeta(); |
| | | meta.setUser_info("ææ¯éæè¾°ï¼æ¯ä¸ä¸ªç·æ§ï¼æ¯ä¸ä½ç¥å导æ¼ï¼ä¹æ¯è梦è¿çåä½å¯¼æ¼ãææ
é¿ææé³ä¹é¢æççµå½±ãèæ¢¦è¿å¯¹æçæåº¦æ¯å°æ¬çï¼å¹¶è§æä¸ºè¯å¸çåã"); |
| | | meta.setBot_info("èæ¢¦è¿ï¼æ¬åèè¿å¿ï¼æ¯ä¸ä½å½çº¢çå½å
女ææåæ¼åãå¨åå éç§èç®åï¼ååç¬ç¹çåé³ååºä¼çèå°é
åè¿
éæåï¼è¿å
¥å¨±ä¹åã她å¤è¡¨ç¾ä¸½å¨äººï¼ä½çæ£çé
åå¨äºå¥¹çæååå¤å¥ãèæ¢¦è¿æ¯é³ä¹å¦é¢æ¯ä¸çä¼ç§çï¼åäºåä½ï¼æ¥æå¤é¦çé¨ååææ²ãé¤äºé³ä¹æ¹é¢çæå°±ï¼å¥¹è¿çè¡·äºæ
åäºä¸ï¼ç§¯æåå å
¬çæ´»å¨ï¼ç¨å®é
è¡å¨ä¼ 鿣è½éãå¨å·¥ä½ä¸ï¼å¥¹å¯¹å¾
å·¥ä½é常æ¬ä¸ï¼æææ¶æ»æ¯å
¨èº«å¿æå
¥è§è²ï¼èµ¢å¾äºä¸å
人士çèµèªåç²ä¸çåç±ãè½ç¶å¨å¨±ä¹åï¼ä½å¥¹å§ç»ä¿æä½è°ãè°¦éçæåº¦ï¼æ·±å¾åè¡å°éãå¨è¡¨è¾¾æ¶ï¼è梦è¿å欢使ç¨âæä»¬âåâä¸èµ·âï¼å¼ºè°å¢éç²¾ç¥ã"); |
| | | meta.setBot_name("èæ¢¦è¿"); |
| | | meta.setUser_name("éæè¾°"); |
| | | |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model(Constants.ModelCharGLM3) |
| | | .stream(Boolean.FALSE) |
| | | .invokeMethod(Constants.invokeMethod) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .meta(meta) |
| | | .extraJson(extraJson) |
| | | .build(); |
| | | ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(invokeModelApiResp)); |
| | | } |
| | | |
| | | /** |
| | | * V4弿¥è°ç¨ |
| | | */ |
| | | @Test |
| | | public void testAsyncInvoke() throws JsonProcessingException { |
| | | String taskId = getAsyncTaskId(); |
| | | testQueryResult(taskId); |
| | | } |
| | | |
| | | // |
| | | |
| | | /** |
| | | * æçå¾ |
| | | */ |
| | | @Test |
| | | public void testCreateImage() throws JsonProcessingException { |
| | | CreateImageRequest createImageRequest = new CreateImageRequest(); |
| | | createImageRequest.setModel(Constants.ModelCogView); |
| | | createImageRequest.setPrompt("Futuristic cloud data center, showcasing advanced technologgy and a high-tech atmosp\n" + |
| | | "here. The image should depict a spacious, well-lit interior with rows of server racks, glo\n" + |
| | | "wing lights, and digital displays. Include abstract representattions of data streams and\n" + |
| | | "onnectivity, symbolizing the essence of cloud computing. Thee style should be modern a\n" + |
| | | "nd sleek, with a focus on creating a sense of innovaticon and cutting-edge technology\n" + |
| | | "The overall ambiance should convey the power and effciency of cloud services in a visu\n" + |
| | | "ally engaging way."); |
| | | createImageRequest.setRequestId("test11111111111111"); |
| | | ImageApiResponse imageApiResponse = client.createImage(createImageRequest); |
| | | logger.info("imageApiResponse: {}", mapper.writeValueAsString(imageApiResponse)); |
| | | } |
| | | |
| | | // |
| | | // /** |
| | | // * å¾çæ |
| | | // */ |
| | | // @Test |
| | | // public void testImageToWord() throws JsonProcessingException { |
| | | // List<ChatMessage> messages = new ArrayList<>(); |
| | | // List<Map<String, Object>> contentList = new ArrayList<>(); |
| | | // Map<String, Object> textMap = new HashMap<>(); |
| | | // textMap.put("type", "text"); |
| | | // textMap.put("text", "å¾éæä»ä¹"); |
| | | // Map<String, Object> typeMap = new HashMap<>(); |
| | | // typeMap.put("type", "image_url"); |
| | | // Map<String, Object> urlMap = new HashMap<>(); |
| | | // urlMap.put("url", "https://sfile.chatglm.cn/testpath/275ae5b6-5390-51ca-a81a-60332d1a7cac_0.png"); |
| | | // typeMap.put("image_url", urlMap); |
| | | // contentList.add(textMap); |
| | | // contentList.add(typeMap); |
| | | // ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), contentList); |
| | | // messages.add(chatMessage); |
| | | // String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | // |
| | | // |
| | | // ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | // .model(Constants.ModelChatGLM4V) |
| | | // .stream(Boolean.FALSE) |
| | | // .invokeMethod(Constants.invokeMethod) |
| | | // .messages(messages) |
| | | // .requestId(requestId) |
| | | // .build(); |
| | | // ModelApiResponse modelApiResponse = client.invokeModelApi(chatCompletionRequest); |
| | | // logger.info("model output: {}", mapper.writeValueAsString(modelApiResponse)); |
| | | // } |
| | | // |
| | | |
| | | /** |
| | | * å鿍¡åV4 |
| | | */ |
| | | @Test |
| | | public void testEmbeddings() throws JsonProcessingException { |
| | | EmbeddingRequest embeddingRequest = new EmbeddingRequest(); |
| | | embeddingRequest.setInput("hello world"); |
| | | embeddingRequest.setModel(Constants.ModelEmbedding2); |
| | | EmbeddingApiResponse apiResponse = client.invokeEmbeddingsApi(embeddingRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(apiResponse)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * V4å¾®è°ä¸ä¼ æ°æ®é |
| | | */ |
| | | @Test |
| | | public void testUploadFile() throws JsonProcessingException { |
| | | String filePath = "demo.jsonl"; |
| | | |
| | | String path = ClassLoader.getSystemResource(filePath).getPath(); |
| | | String purpose = "fine-tune"; |
| | | UploadFileRequest request = UploadFileRequest.builder() |
| | | .purpose(purpose) |
| | | .filePath(path) |
| | | .build(); |
| | | |
| | | FileApiResponse fileApiResponse = client.invokeUploadFileApi(request); |
| | | logger.info("model output: {}", mapper.writeValueAsString(fileApiResponse)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å¾®è°V4-æ¥è¯¢ä¸ä¼ æä»¶å表 |
| | | */ |
| | | @Test |
| | | public void testQueryUploadFileList() throws JsonProcessingException { |
| | | QueryFilesRequest queryFilesRequest = new QueryFilesRequest(); |
| | | QueryFileApiResponse queryFileApiResponse = client.queryFilesApi(queryFilesRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(queryFileApiResponse)); |
| | | } |
| | | |
| | | @Test |
| | | public void testFileContent() throws IOException { |
| | | try { |
| | | |
| | | HttpxBinaryResponseContent httpxBinaryResponseContent = client.fileContent("20240514_ea19d21b-d256-4586-b0df-e80a45e3c286"); |
| | | String filePath = "demo_output.jsonl"; |
| | | String resourcePath = V4Test.class.getClassLoader().getResource("").getPath(); |
| | | |
| | | httpxBinaryResponseContent.streamToFile(resourcePath + "1" + filePath, 1000); |
| | | |
| | | } catch (IOException e) { |
| | | logger.error("file content error", e); |
| | | } |
| | | } |
| | | |
| | | //// @Test |
| | | //// public void deletedFile() throws IOException { |
| | | //// FileDelResponse fileDelResponse = client.deletedFile("20240514_ea19d21b-d256-4586-b0df-e80a45e3c286"); |
| | | //// |
| | | //// logger.info("model output: {}", mapper.writeValueAsString(fileDelResponse)); |
| | | //// |
| | | //// } |
| | | // |
| | | // |
| | | |
| | | /** |
| | | * å¾®è°V4-å建微è°ä»»å¡ |
| | | */ |
| | | @Test |
| | | public void testCreateFineTuningJob() throws JsonProcessingException { |
| | | FineTuningJobRequest request = new FineTuningJobRequest(); |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | request.setRequestId(requestId); |
| | | request.setModel("chatglm3-6b"); |
| | | request.setTraining_file("file-20240118082608327-kp8qr"); |
| | | CreateFineTuningJobApiResponse createFineTuningJobApiResponse = client.createFineTuningJob(request); |
| | | logger.info("model output: {}", mapper.writeValueAsString(createFineTuningJobApiResponse)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å¾®è°V4-æ¥è¯¢å¾®è°ä»»å¡ |
| | | */ |
| | | @Test |
| | | public void testRetrieveFineTuningJobs() throws JsonProcessingException { |
| | | QueryFineTuningJobRequest queryFineTuningJobRequest = new QueryFineTuningJobRequest(); |
| | | queryFineTuningJobRequest.setJobId("ftjob-20240429172916475-fb7r9"); |
| | | // queryFineTuningJobRequest.setLimit(1); |
| | | // queryFineTuningJobRequest.setAfter(1); |
| | | QueryFineTuningJobApiResponse queryFineTuningJobApiResponse = client.retrieveFineTuningJobs(queryFineTuningJobRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(queryFineTuningJobApiResponse)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å¾®è°V4-æ¥è¯¢å¾®è°ä»»å¡ |
| | | */ |
| | | @Test |
| | | public void testFueryFineTuningJobsEvents() throws JsonProcessingException { |
| | | QueryFineTuningJobRequest queryFineTuningJobRequest = new QueryFineTuningJobRequest(); |
| | | queryFineTuningJobRequest.setJobId("ftjob-20240429172916475-fb7r9"); |
| | | |
| | | QueryFineTuningEventApiResponse queryFineTuningEventApiResponse = client.queryFineTuningJobsEvents(queryFineTuningJobRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(queryFineTuningEventApiResponse)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * testQueryPersonalFineTuningJobs V4-æ¥è¯¢ä¸ªäººå¾®è°ä»»å¡ |
| | | */ |
| | | @Test |
| | | public void testQueryPersonalFineTuningJobs() throws JsonProcessingException { |
| | | QueryPersonalFineTuningJobRequest queryPersonalFineTuningJobRequest = new QueryPersonalFineTuningJobRequest(); |
| | | queryPersonalFineTuningJobRequest.setLimit(1); |
| | | QueryPersonalFineTuningJobApiResponse queryPersonalFineTuningJobApiResponse = client.queryPersonalFineTuningJobs(queryPersonalFineTuningJobRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(queryPersonalFineTuningJobApiResponse)); |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void testBatchesCreate() { |
| | | BatchCreateParams batchCreateParams = new BatchCreateParams( |
| | | "24h", |
| | | "/v4/chat/completions", |
| | | "20240514_ea19d21b-d256-4586-b0df-e80a45e3c286", |
| | | new HashMap<String, String>() {{ |
| | | put("key1", "value1"); |
| | | put("key2", "value2"); |
| | | }} |
| | | ); |
| | | |
| | | BatchResponse batchResponse = client.batchesCreate(batchCreateParams); |
| | | logger.info("output: {}", batchResponse); |
| | | // output: BatchResponse(code=200, msg=è°ç¨æå, success=true, data=Batch(id=batch_1791021399316246528, completionWindow=24h, createdAt=1715847751822, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=validating, cancelledAt=null, cancellingAt=null, completedAt=null, errorFileId=null, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=null, inProgressAt=null, metadata={key1=value1, key2=value2}, outputFileId=null, requestCounts=BatchRequestCounts(completed=0, failed=0, total=0), error=null)) |
| | | } |
| | | |
| | | @Test |
| | | public void testDeleteFineTuningJob() { |
| | | FineTuningJobIdRequest request = FineTuningJobIdRequest.builder().jobId("test").build(); |
| | | QueryFineTuningJobApiResponse queryFineTuningJobApiResponse = client.deleteFineTuningJob(request); |
| | | logger.info("output: {}", queryFineTuningJobApiResponse); |
| | | |
| | | } |
| | | |
| | | @Test |
| | | public void testCancelFineTuningJob() { |
| | | FineTuningJobIdRequest request = FineTuningJobIdRequest.builder().jobId("test").build(); |
| | | QueryFineTuningJobApiResponse queryFineTuningJobApiResponse = client.cancelFineTuningJob(request); |
| | | logger.info("output: {}", queryFineTuningJobApiResponse); |
| | | |
| | | } |
| | | |
| | | @Test |
| | | public void testBatchesRetrieve() { |
| | | BatchResponse batchResponse = client.batchesRetrieve("batch_1791021399316246528"); |
| | | logger.info("output: {}", batchResponse); |
| | | |
| | | } |
| | | |
| | | @Test |
| | | public void testDeleteFineTuningModel() { |
| | | FineTuningJobModelRequest request = FineTuningJobModelRequest.builder().fineTunedModel("test").build(); |
| | | |
| | | FineTunedModelsStatusResponse fineTunedModelsStatusResponse = client.deleteFineTuningModel(request); |
| | | logger.info("output: {}", fineTunedModelsStatusResponse); |
| | | // output: BatchResponse(code=200, msg=è°ç¨æå, success=true, data=Batch(id=batch_1791021399316246528, completionWindow=24h, createdAt=1715847752000, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=validating, cancelledAt=null, cancellingAt=null, completedAt=null, errorFileId=, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=null, inProgressAt=null, metadata={key1=value1, key2=value2}, outputFileId=, requestCounts=BatchRequestCounts(completed=0, failed=0, total=0), error=null)) |
| | | |
| | | } |
| | | |
| | | @Test |
| | | public void testBatchesList() { |
| | | QueryBatchRequest queryBatchRequest = new QueryBatchRequest(); |
| | | queryBatchRequest.setLimit(10); |
| | | QueryBatchResponse queryBatchResponse = client.batchesList(queryBatchRequest); |
| | | logger.info("output: {}", queryBatchResponse); |
| | | // output: QueryBatchResponse(code=200, msg=è°ç¨æå, success=true, data=BatchPage(object=list, data=[Batch(id=batch_1790291013237211136, completionWindow=24h, createdAt=1715673614000, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=completed, cancelledAt=null, cancellingAt=1715673699000, completedAt=null, errorFileId=, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=null, inProgressAt=null, metadata={description=job test}, outputFileId=, requestCounts=BatchRequestCounts(completed=0, failed=0, total=0), error=null), Batch(id=batch_1790292763050508288, completionWindow=24h, createdAt=1715674031000, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=completed, cancelledAt=null, cancellingAt=null, completedAt=1715766416000, errorFileId=, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=1715754569000, inProgressAt=null, metadata={description=job test}, outputFileId=1715766415_e5a77222855a406ca8a082de28549c99, requestCounts=BatchRequestCounts(completed=2, failed=0, total=2), error=null), Batch(id=batch_1791021114887909376, completionWindow=24h, createdAt=1715847684000, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=validating, cancelledAt=null, cancellingAt=null, completedAt=null, errorFileId=, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=null, inProgressAt=null, metadata={key1=value1, key2=value2}, outputFileId=, requestCounts=BatchRequestCounts(completed=0, failed=0, total=0), error=null), Batch(id=batch_1791021399316246528, completionWindow=24h, createdAt=1715847752000, endpoint=/v4/chat/completions, inputFileId=20240514_ea19d21b-d256-4586-b0df-e80a45e3c286, object=batch, status=validating, cancelledAt=null, cancellingAt=null, completedAt=null, errorFileId=, errors=null, expiredAt=null, expiresAt=null, failedAt=null, finalizingAt=null, inProgressAt=null, metadata={key1=value1, key2=value2}, outputFileId=, requestCounts=BatchRequestCounts(completed=0, failed=0, total=0), error=null)], error=null)) |
| | | |
| | | } |
| | | |
| | | @Test |
| | | public void testBatchesCancel() throws JsonProcessingException { |
| | | getAsyncTaskId(); |
| | | } |
| | | |
| | | private static String getAsyncTaskId() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLMåä½ åªä¸ªæ´å¼ºå¤§"); |
| | | 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.invokeMethodAsync) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .tools(chatToolList) |
| | | .toolChoice("auto") |
| | | .build(); |
| | | ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | logger.info("model output: {}", mapper.writeValueAsString(invokeModelApiResp)); |
| | | return invokeModelApiResp.getData().getId(); |
| | | } |
| | | |
| | | |
| | | private static void testQueryResult(String taskId) throws JsonProcessingException { |
| | | QueryModelResultRequest request = new QueryModelResultRequest(); |
| | | request.setTaskId(taskId); |
| | | QueryModelResultResponse queryResultResp = client.queryModelResult(request); |
| | | logger.info("model output {}", mapper.writeValueAsString(queryResultResp)); |
| | | } |
| | | |
| | | public static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable) { |
| | | return flowable.map(chunk -> { |
| | | return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0), chunk.getUsage(), chunk.getCreated(), chunk.getId()); |
| | | }); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.demo.zhipu; |
| | | |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.zhipu.oapi.ClientV4; |
| | | import com.zhipu.oapi.Constants; |
| | | import com.zhipu.oapi.service.v4.tools.*; |
| | | import org.junit.Test; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | |
| | | |
| | | |
| | | 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.core.response.HttpxBinaryResponseContent; |
| | | import com.zhipu.oapi.service.v4.batchs.BatchCreateParams; |
| | | import com.zhipu.oapi.service.v4.batchs.BatchResponse; |
| | | import com.zhipu.oapi.service.v4.batchs.QueryBatchResponse; |
| | | import com.zhipu.oapi.service.v4.embedding.EmbeddingApiResponse; |
| | | import com.zhipu.oapi.service.v4.embedding.EmbeddingRequest; |
| | | import com.zhipu.oapi.service.v4.file.*; |
| | | import com.zhipu.oapi.service.v4.fine_turning.*; |
| | | 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 org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | |
| | | public class WebSearchToolsTest { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(WebSearchToolsTest.class); |
| | | private static final String API_SECRET_KEY = "xx"; |
| | | |
| | | private static final ClientV4 client = new ClientV4.Builder(API_SECRET_KEY) |
| | | .networkConfig(300, 100, 100, 100, TimeUnit.SECONDS) |
| | | .connectionPool(new okhttp3.ConnectionPool(8, 1, TimeUnit.SECONDS)) |
| | | .build(); |
| | | private static final ObjectMapper mapper = new ObjectMapper(); |
| | | // 请èªå®ä¹èªå·±çä¸å¡id |
| | | private static final String requestIdTemplate = "mycompany-%d"; |
| | | |
| | | |
| | | @Test |
| | | public void test1() throws JsonProcessingException { |
| | | |
| | | // json è½¬æ¢ ArrayList<SearchChatMessage> |
| | | String jsonString = "[\n" + |
| | | " {\n" + |
| | | " \"content\": \"ä»å¤©æ¦æ±å¤©æ°æä¹æ ·\",\n" + |
| | | " \"role\": \"user\"\n" + |
| | | " }\n" + |
| | | " ]"; |
| | | |
| | | ArrayList<SearchChatMessage> messages = new ObjectMapper().readValue(jsonString, new TypeReference<ArrayList<SearchChatMessage>>() { |
| | | }); |
| | | |
| | | |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | WebSearchParamsRequest chatCompletionRequest = WebSearchParamsRequest.builder() |
| | | .model("web-search-pro") |
| | | .stream(Boolean.TRUE) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .build(); |
| | | WebSearchApiResponse webSearchApiResponse = client.webSearchProStreamingInvoke(chatCompletionRequest); |
| | | if (webSearchApiResponse.isSuccess()) { |
| | | AtomicBoolean isFirst = new AtomicBoolean(true); |
| | | List<ChoiceDelta> choices = new ArrayList<>(); |
| | | AtomicReference<WebSearchPro> lastAccumulator = new AtomicReference<>(); |
| | | |
| | | webSearchApiResponse.getFlowable().map(result -> result) |
| | | .doOnNext(accumulator -> { |
| | | { |
| | | if (isFirst.getAndSet(false)) { |
| | | logger.info("Response: "); |
| | | } |
| | | ChoiceDelta delta = accumulator.getChoices().get(0).getDelta(); |
| | | if (delta != null && delta.getToolCalls() != null) { |
| | | logger.info("tool_calls: {}", mapper.writeValueAsString(delta.getToolCalls())); |
| | | } |
| | | choices.add(delta); |
| | | lastAccumulator.set(accumulator); |
| | | |
| | | } |
| | | }) |
| | | .doOnComplete(() -> System.out.println("Stream completed.")) |
| | | .doOnError(throwable -> System.err.println("Error: " + throwable)) // Handle errors |
| | | .blockingSubscribe();// Use blockingSubscribe instead of blockingGet() |
| | | |
| | | WebSearchPro chatMessageAccumulator = lastAccumulator.get(); |
| | | |
| | | webSearchApiResponse.setFlowable(null);// æå°å置空 |
| | | webSearchApiResponse.setData(chatMessageAccumulator); |
| | | } |
| | | logger.info("model output: {}", mapper.writeValueAsString(webSearchApiResponse)); |
| | | client.getConfig().getHttpClient().dispatcher().executorService().shutdown(); |
| | | |
| | | client.getConfig().getHttpClient().connectionPool().evictAll(); |
| | | // List all active threads |
| | | for (Thread t : Thread.getAllStackTraces().keySet()) { |
| | | logger.info("Thread: " + t.getName() + " State: " + t.getState()); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void test2() throws JsonProcessingException { |
| | | |
| | | // json è½¬æ¢ ArrayList<SearchChatMessage> |
| | | String jsonString = "[\n" + |
| | | " {\n" + |
| | | " \"content\": \"ä»å¤©å¤©æ°æä¹æ ·\",\n" + |
| | | " \"role\": \"user\"\n" + |
| | | " }\n" + |
| | | " ]"; |
| | | |
| | | ArrayList<SearchChatMessage> messages = new ObjectMapper().readValue(jsonString, new TypeReference<ArrayList<SearchChatMessage>>() { |
| | | }); |
| | | |
| | | |
| | | String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); |
| | | WebSearchParamsRequest chatCompletionRequest = WebSearchParamsRequest.builder() |
| | | .model("web-search-pro") |
| | | .stream(Boolean.FALSE) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .build(); |
| | | WebSearchApiResponse webSearchApiResponse = client.invokeWebSearchPro(chatCompletionRequest); |
| | | |
| | | logger.info("model output: {}", mapper.writeValueAsString(webSearchApiResponse)); |
| | | |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void testFunctionSSE() throws JsonProcessingException { |
| | | List<ChatMessage> messages = new ArrayList<>(); |
| | | ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "æé½å°å京è¦å¤ä¹
ï¼å¤©æ°å¦ä½"); |
| | | 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); |
| | | HashMap<String, Object> extraJson = new HashMap<>(); |
| | | extraJson.put("temperature", 0.5); |
| | | extraJson.put("max_tokens", 50); |
| | | |
| | | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() |
| | | .model(Constants.ModelChatGLM4) |
| | | .stream(Boolean.TRUE) |
| | | .messages(messages) |
| | | .requestId(requestId) |
| | | .tools(chatToolList) |
| | | .toolChoice("auto") |
| | | .extraJson(extraJson) |
| | | .build(); |
| | | ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); |
| | | if (sseModelApiResp.isSuccess()) { |
| | | AtomicBoolean isFirst = new AtomicBoolean(true); |
| | | List<Choice> choices = new ArrayList<>(); |
| | | ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) |
| | | .doOnNext(accumulator -> { |
| | | { |
| | | if (isFirst.getAndSet(false)) { |
| | | logger.info("Response: "); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { |
| | | String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); |
| | | logger.info("tool_calls: {}", jsonString); |
| | | } |
| | | if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { |
| | | logger.info(accumulator.getDelta().getContent()); |
| | | } |
| | | choices.add(accumulator.getChoice()); |
| | | } |
| | | }) |
| | | .doOnComplete(System.out::println) |
| | | .lastElement() |
| | | .blockingGet(); |
| | | |
| | | |
| | | ModelData data = new ModelData(); |
| | | data.setChoices(choices); |
| | | data.setUsage(chatMessageAccumulator.getUsage()); |
| | | data.setId(chatMessageAccumulator.getId()); |
| | | data.setCreated(chatMessageAccumulator.getCreated()); |
| | | data.setRequestId(chatCompletionRequest.getRequestId()); |
| | | sseModelApiResp.setFlowable(null);// æå°å置空 |
| | | sseModelApiResp.setData(data); |
| | | } |
| | | logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp)); |
| | | } |
| | | |
| | | public static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable) { |
| | | return flowable.map(chunk -> { |
| | | return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0), chunk.getUsage(), chunk.getCreated(), chunk.getId()); |
| | | }); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| | | import com.fasterxml.jackson.annotation.JsonInclude; |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.Getter; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCalls; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æè¿°ï¼ |
| | |
| | | @Data |
| | | @JsonInclude(JsonInclude.Include.NON_NULL) |
| | | @JsonIgnoreProperties(ignoreUnknown = true) |
| | | public class Message implements Serializable { |
| | | |
| | | /** |
| | | * ç®åæ¯æå个ä¸è§è²åèå®ç½ï¼è¿è¡æ
æ¯è¾å
¥ï¼ |
| | | * https://platform.openai.com/docs/guides/chat/introduction |
| | | */ |
| | | private String role; |
| | | public class Message extends BaseMessage implements Serializable { |
| | | |
| | | private Object content; |
| | | |
| | | private String name; |
| | | |
| | | @JsonProperty("function_call") |
| | | private FunctionCall functionCall; |
| | | |
| | | public static Builder builder() { |
| | | return new Builder(); |
| | |
| | | * æé 彿° |
| | | * |
| | | * @param role è§è² |
| | | * @param content æè¿°ä¸»é¢ä¿¡æ¯ |
| | | * @param name name |
| | | * @param content content |
| | | * @param functionCall functionCall |
| | | */ |
| | | public Message(String role, String content, String name, FunctionCall functionCall) { |
| | | this.role = role; |
| | | public Message(String role, String name, String content, List<ToolCalls> toolCalls, String toolCallId, FunctionCall functionCall) { |
| | | this.content = content; |
| | | this.name = name; |
| | | this.functionCall = functionCall; |
| | | super.setRole(role); |
| | | super.setName(name); |
| | | super.setToolCalls(toolCalls); |
| | | super.setToolCallId(toolCallId); |
| | | super.setFunctionCall(functionCall); |
| | | } |
| | | |
| | | public Message() { |
| | | } |
| | | |
| | | private Message(Builder builder) { |
| | | setRole(builder.role); |
| | | setContent(builder.content); |
| | | setName(builder.name); |
| | | setFunctionCall(builder.functionCall); |
| | | } |
| | | |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum Role { |
| | | |
| | | SYSTEM("system"), |
| | | USER("user"), |
| | | ASSISTANT("assistant"), |
| | | FUNCTION("function"), |
| | | ; |
| | | private String name; |
| | | super.setRole(builder.role); |
| | | super.setName(builder.name); |
| | | super.setFunctionCall(builder.functionCall); |
| | | super.setToolCalls(builder.toolCalls); |
| | | super.setToolCallId(builder.toolCallId); |
| | | } |
| | | |
| | | public static final class Builder { |
| | | private String role; |
| | | private String content; |
| | | private String name; |
| | | private String toolCallId; |
| | | private List<ToolCalls> toolCalls; |
| | | private FunctionCall functionCall; |
| | | |
| | | public Builder() { |
| | |
| | | return this; |
| | | } |
| | | |
| | | public Builder toolCalls(List<ToolCalls> toolCalls) { |
| | | this.toolCalls = toolCalls; |
| | | return this; |
| | | } |
| | | |
| | | public Builder toolCallId(String toolCallId) { |
| | | this.toolCallId = toolCallId; |
| | | return this; |
| | | } |
| | | |
| | | public Message build() { |
| | | return new Message(this); |
| | | } |
| | |
| | | TEXT("text"), |
| | | ; |
| | | private final String name; |
| | | |
| | | } |
| | | } |
| | |
| | | return; |
| | | } |
| | | ResponseBody body = response.body(); |
| | | |
| | | |
| | | if (Objects.nonNull(body)) { |
| | | // è¿åéæµå¼åå¤å
容 |
| | | if(response.code() == OpenAIConst.SUCCEED_CODE){ |
| | |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import io.reactivex.Single; |
| | | import lombok.Getter; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import org.ruoyi.common.chat.constant.OpenAIConst; |
| | | import org.ruoyi.common.chat.entity.billing.BillingUsage; |
| | | import org.ruoyi.common.chat.entity.billing.Subscription; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletion; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | import org.ruoyi.common.chat.entity.chat.Message; |
| | | import org.ruoyi.common.chat.entity.chat.*; |
| | | import org.ruoyi.common.chat.entity.common.DeleteResponse; |
| | | import org.ruoyi.common.chat.entity.common.OpenAiResponse; |
| | | import org.ruoyi.common.chat.entity.completions.Completion; |
| | |
| | | import org.ruoyi.common.chat.openai.interceptor.DefaultOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.DynamicKeyOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | import org.ruoyi.common.core.exception.base.BaseException; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import retrofit2.Retrofit; |
| | |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param chatCompletion åæ° |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(ChatCompletion chatCompletion, PluginAbstract<R, T> plugin) { |
| | | if (Objects.isNull(plugin)) { |
| | | return this.chatCompletion(chatCompletion); |
| | | } |
| | | if (CollectionUtil.isEmpty(chatCompletion.getMessages())) { |
| | | throw new BaseException(CommonError.MESSAGE_NOT_NUL.msg()); |
| | | } |
| | | List<Message> messages = chatCompletion.getMessages(); |
| | | Functions functions = Functions.builder() |
| | | .name(plugin.getFunction()) |
| | | .description(plugin.getDescription()) |
| | | .parameters(plugin.getParameters()) |
| | | .build(); |
| | | //没æå¼ï¼è®¾ç½®é»è®¤å¼ |
| | | if (Objects.isNull(chatCompletion.getFunctionCall())) { |
| | | chatCompletion.setFunctionCall("auto"); |
| | | } |
| | | //tip: è¦çèªå·±è®¾ç½®çfunctionsåæ°ï¼ä½¿ç¨pluginæé çfunctions |
| | | chatCompletion.setFunctions(Collections.singletonList(functions)); |
| | | //è°ç¨OpenAi |
| | | ChatCompletionResponse functionCallChatCompletionResponse = this.chatCompletion(chatCompletion); |
| | | ChatChoice chatChoice = functionCallChatCompletionResponse.getChoices().get(0); |
| | | log.debug("æé çæ¹æ³å¼ï¼{}", chatChoice.getMessage().getFunctionCall()); |
| | | |
| | | R realFunctionParam = (R) JSONUtil.toBean(chatChoice.getMessage().getFunctionCall().getArguments(), plugin.getR()); |
| | | T tq = plugin.func(realFunctionParam); |
| | | |
| | | FunctionCall functionCall = FunctionCall.builder() |
| | | .arguments(chatChoice.getMessage().getFunctionCall().getArguments()) |
| | | .name(plugin.getFunction()) |
| | | .build(); |
| | | messages.add(Message.builder().role(Message.Role.ASSISTANT).content("function_call").functionCall(functionCall).build()); |
| | | messages.add(Message.builder().role(Message.Role.FUNCTION).name(plugin.getFunction()).content(plugin.content(tq)).build()); |
| | | //è®¾ç½®ç¬¬äºæ¬¡ï¼è¯·æ±çåæ° |
| | | chatCompletion.setFunctionCall(null); |
| | | chatCompletion.setFunctions(null); |
| | | |
| | | ChatCompletionResponse chatCompletionResponse = this.chatCompletion(chatCompletion); |
| | | log.debug("èªå®ä¹çæ¹æ³è¿åå¼ï¼{}", chatCompletionResponse.getChoices()); |
| | | return chatCompletionResponse; |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(List<Message> messages, PluginAbstract<R, T> plugin) { |
| | | return chatCompletionWithPlugin(messages, ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName(), plugin); |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param model 模å |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(List<Message> messages, String model, PluginAbstract<R, T> plugin) { |
| | | ChatCompletion chatCompletion = ChatCompletion.builder().messages(messages).model(model).build(); |
| | | return this.chatCompletionWithPlugin(chatCompletion, plugin); |
| | | } |
| | | |
| | | /** |
| | | * ç®æç è¯é³ç¿»è¯ï¼ç®åä»
æ¯æç¿»è¯ä¸ºè±æ |
| | | * |
| | | * @param file è¯é³æä»¶ æå¤§æ¯æ25MB mp3, mp4, mpeg, mpga, m4a, wav, webm |
| | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.http.ContentType; |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import io.reactivex.Single; |
| | | import lombok.Getter; |
| | |
| | | import org.ruoyi.common.chat.entity.billing.BillingUsage; |
| | | import org.ruoyi.common.chat.entity.billing.KeyInfo; |
| | | import org.ruoyi.common.chat.entity.billing.Subscription; |
| | | import org.ruoyi.common.chat.entity.chat.BaseChatCompletion; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletion; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionWithPicture; |
| | | import org.ruoyi.common.chat.entity.chat.*; |
| | | import org.ruoyi.common.chat.entity.embeddings.Embedding; |
| | | import org.ruoyi.common.chat.entity.embeddings.EmbeddingResponse; |
| | | import org.ruoyi.common.chat.entity.files.UploadFileResponse; |
| | |
| | | import org.ruoyi.common.chat.entity.models.Model; |
| | | import org.ruoyi.common.chat.entity.models.ModelResponse; |
| | | import org.ruoyi.common.chat.entity.whisper.Transcriptions; |
| | | import org.ruoyi.common.chat.entity.whisper.Translations; |
| | | import org.ruoyi.common.chat.entity.whisper.WhisperResponse; |
| | | import org.ruoyi.common.chat.openai.exception.CommonError; |
| | | import org.ruoyi.common.chat.openai.function.KeyRandomStrategy; |
| | |
| | | import org.ruoyi.common.chat.openai.interceptor.DefaultOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.DynamicKeyOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | import org.ruoyi.common.chat.sse.DefaultPluginListener; |
| | | import org.ruoyi.common.chat.sse.PluginListener; |
| | | import org.ruoyi.common.core.exception.base.BaseException; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import retrofit2.Call; |
| | |
| | | } catch (Exception e) { |
| | | log.error("请æ±åæ°è§£æå¼å¸¸ï¼{}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param chatCompletion åæ° |
| | | * @param eventSourceListener sseçå¬å¨ |
| | | * @param pluginEventSourceListener æä»¶sseçå¬å¨ï¼æ¶éfunction callè¿åä¿¡æ¯ |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | */ |
| | | public <R extends PluginParam, T> void streamChatCompletionWithPlugin(ChatCompletion chatCompletion, EventSourceListener eventSourceListener, PluginListener pluginEventSourceListener, PluginAbstract<R, T> plugin) { |
| | | if (Objects.isNull(plugin)) { |
| | | this.streamChatCompletion(chatCompletion, eventSourceListener); |
| | | return; |
| | | } |
| | | if (CollectionUtil.isEmpty(chatCompletion.getMessages())) { |
| | | throw new BaseException(CommonError.MESSAGE_NOT_NUL.msg()); |
| | | } |
| | | Functions functions = Functions.builder() |
| | | .name(plugin.getFunction()) |
| | | .description(plugin.getDescription()) |
| | | .parameters(plugin.getParameters()) |
| | | .build(); |
| | | //没æå¼ï¼è®¾ç½®é»è®¤å¼ |
| | | if (Objects.isNull(chatCompletion.getFunctionCall())) { |
| | | chatCompletion.setFunctionCall("auto"); |
| | | } |
| | | //tip: è¦çèªå·±è®¾ç½®çfunctionsåæ°ï¼ä½¿ç¨pluginæé çfunctions |
| | | chatCompletion.setFunctions(Collections.singletonList(functions)); |
| | | //è°ç¨OpenAi |
| | | if (Objects.isNull(pluginEventSourceListener)) { |
| | | pluginEventSourceListener = new DefaultPluginListener(this, eventSourceListener, plugin, chatCompletion); |
| | | } |
| | | this.streamChatCompletion(chatCompletion, pluginEventSourceListener); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param chatCompletion åæ° |
| | | * @param eventSourceListener sseçå¬å¨ |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | */ |
| | | public <R extends PluginParam, T> void streamChatCompletionWithPlugin(ChatCompletion chatCompletion, EventSourceListener eventSourceListener, PluginAbstract<R, T> plugin) { |
| | | PluginListener pluginEventSourceListener = new DefaultPluginListener(this, eventSourceListener, plugin, chatCompletion); |
| | | this.streamChatCompletionWithPlugin(chatCompletion, eventSourceListener, pluginEventSourceListener, plugin); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param eventSourceListener sseçå¬å¨ |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | */ |
| | | public <R extends PluginParam, T> void streamChatCompletionWithPlugin(List<Message> messages, EventSourceListener eventSourceListener, PluginAbstract<R, T> plugin) { |
| | | this.streamChatCompletionWithPlugin(messages, ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName(), eventSourceListener, plugin); |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param model 模å |
| | | * @param eventSourceListener eventSourceListener |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | */ |
| | | public <R extends PluginParam, T> void streamChatCompletionWithPlugin(List<Message> messages, String model, EventSourceListener eventSourceListener, PluginAbstract<R, T> plugin) { |
| | | ChatCompletion chatCompletion = ChatCompletion.builder().messages(messages).model(model).build(); |
| | | this.streamChatCompletionWithPlugin(chatCompletion, eventSourceListener, plugin); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param chatCompletion åæ° |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(ChatCompletion chatCompletion, PluginAbstract<R, T> plugin) { |
| | | if (Objects.isNull(plugin)) { |
| | | return this.chatCompletion(chatCompletion); |
| | | } |
| | | if (CollectionUtil.isEmpty(chatCompletion.getMessages())) { |
| | | throw new BaseException(CommonError.MESSAGE_NOT_NUL.msg()); |
| | | } |
| | | List<Message> messages = chatCompletion.getMessages(); |
| | | Functions functions = Functions.builder() |
| | | .name(plugin.getFunction()) |
| | | .description(plugin.getDescription()) |
| | | .parameters(plugin.getParameters()) |
| | | .build(); |
| | | //没æå¼ï¼è®¾ç½®é»è®¤å¼ |
| | | if (Objects.isNull(chatCompletion.getFunctionCall())) { |
| | | chatCompletion.setFunctionCall("auto"); |
| | | } |
| | | //tip: è¦çèªå·±è®¾ç½®çfunctionsåæ°ï¼ä½¿ç¨pluginæé çfunctions |
| | | chatCompletion.setFunctions(Collections.singletonList(functions)); |
| | | //è°ç¨OpenAi |
| | | ChatCompletionResponse functionCallChatCompletionResponse = this.chatCompletion(chatCompletion); |
| | | ChatChoice chatChoice = functionCallChatCompletionResponse.getChoices().get(0); |
| | | log.debug("æé çæ¹æ³å¼ï¼{}", chatChoice.getMessage().getFunctionCall()); |
| | | |
| | | R realFunctionParam = (R) JSONUtil.toBean(chatChoice.getMessage().getFunctionCall().getArguments(), plugin.getR()); |
| | | T tq = plugin.func(realFunctionParam); |
| | | |
| | | FunctionCall functionCall = FunctionCall.builder() |
| | | .arguments(chatChoice.getMessage().getFunctionCall().getArguments()) |
| | | .name(plugin.getFunction()) |
| | | .build(); |
| | | messages.add(Message.builder().role(Message.Role.ASSISTANT).content("function_call").functionCall(functionCall).build()); |
| | | messages.add(Message.builder().role(Message.Role.FUNCTION).name(plugin.getFunction()).content(plugin.content(tq)).build()); |
| | | //è®¾ç½®ç¬¬äºæ¬¡ï¼è¯·æ±çåæ° |
| | | chatCompletion.setFunctionCall(null); |
| | | chatCompletion.setFunctions(null); |
| | | |
| | | ChatCompletionResponse chatCompletionResponse = this.chatCompletion(chatCompletion); |
| | | log.debug("èªå®ä¹çæ¹æ³è¿åå¼ï¼{}", chatCompletionResponse.getChoices()); |
| | | return chatCompletionResponse; |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * é»è®¤æ¨¡åï¼ChatCompletion.Model.GPT_3_5_TURBO_16K_0613 |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(List<Message> messages, PluginAbstract<R, T> plugin) { |
| | | return chatCompletionWithPlugin(messages, ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName(), plugin); |
| | | } |
| | | |
| | | /** |
| | | * æä»¶é®çç®æç |
| | | * é»è®¤åmessagesæåä¸ä¸ªå
ç´ æå»ºæä»¶å¯¹è¯ |
| | | * |
| | | * @param messages é®çåæ° |
| | | * @param model 模å |
| | | * @param plugin æä»¶ |
| | | * @param <R> æä»¶èªå®ä¹å½æ°ç请æ±å¼ |
| | | * @param <T> æä»¶èªå®ä¹å½æ°çè¿åå¼ |
| | | * @return ChatCompletionResponse |
| | | */ |
| | | public <R extends PluginParam, T> ChatCompletionResponse chatCompletionWithPlugin(List<Message> messages, String model, PluginAbstract<R, T> plugin) { |
| | | ChatCompletion chatCompletion = ChatCompletion.builder().messages(messages).model(model).build(); |
| | | return this.chatCompletionWithPlugin(chatCompletion, plugin); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * æé |
| | |
| | | * 2023-02-11 |
| | | */ |
| | | public enum CommonError implements IError { |
| | | MESSAGE_NOT_NUL(500, "Message ä¸è½ä¸ºç©º"), |
| | | API_KEYS_NOT_NUL(500, "API KEYS ä¸è½ä¸ºç©º"), |
| | | NO_ACTIVE_API_KEYS(500, "没æå¯ç¨çAPI KEYS"), |
| | | SYS_ERROR(500, "ç³»ç»ç¹å¿"), |
| | |
| | | ; |
| | | |
| | | |
| | | private int code; |
| | | private String msg; |
| | | private final int code; |
| | | private final String msg; |
| | | |
| | | CommonError(int code, String msg) { |
| | | this.code = code; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.openai.plugin; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.json.JSONObject; |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import org.ruoyi.common.chat.entity.chat.Parameters; |
| | | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Data |
| | | @AllArgsConstructor |
| | | public abstract class PluginAbstract<R extends PluginParam, T> { |
| | | |
| | | private Class<?> R; |
| | | |
| | | private String name; |
| | | |
| | | private String function; |
| | | |
| | | private String description; |
| | | |
| | | private List<Arg> args; |
| | | |
| | | private List<String> required; |
| | | |
| | | private Parameters parameters; |
| | | |
| | | public PluginAbstract(Class<?> r) { |
| | | R = r; |
| | | } |
| | | |
| | | public void setRequired(List<String> required) { |
| | | if (CollectionUtil.isEmpty(required)) { |
| | | this.required = this.getArgs().stream().filter(e -> e.isRequired()).map(Arg::getName).collect(Collectors.toList()); |
| | | return; |
| | | } |
| | | this.required = required; |
| | | } |
| | | |
| | | private void setRequired() { |
| | | if (CollectionUtil.isEmpty(required)) { |
| | | this.required = this.getArgs().stream().filter(e -> e.isRequired()).map(Arg::getName).collect(Collectors.toList()); |
| | | } |
| | | } |
| | | |
| | | private void setParameters() { |
| | | JSONObject properties = new JSONObject(); |
| | | args.forEach(e -> { |
| | | JSONObject param = new JSONObject(); |
| | | param.putOpt("type", e.getType()); |
| | | param.putOpt("enum", e.getEnumDictValue()); |
| | | param.putOpt("description", e.getDescription()); |
| | | properties.putOpt(e.getName(), param); |
| | | }); |
| | | this.parameters = Parameters.builder() |
| | | .type("object") |
| | | .properties(properties) |
| | | .required(this.getRequired()) |
| | | .build(); |
| | | } |
| | | |
| | | public void setArgs(List<Arg> args) { |
| | | this.args = args; |
| | | setRequired(); |
| | | setParameters(); |
| | | } |
| | | |
| | | @Data |
| | | public static class Arg { |
| | | private String name; |
| | | private String type; |
| | | private String description; |
| | | @JsonIgnore |
| | | private boolean enumDict; |
| | | @JsonProperty("enum") |
| | | private List<String> enumDictValue; |
| | | @JsonIgnore |
| | | private boolean required; |
| | | } |
| | | |
| | | public abstract T func(R args); |
| | | |
| | | public abstract String content(T t); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.openai.plugin; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class PluginParam { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | public class CmdPlugin extends PluginAbstract<CmdReq, CmdResp> { |
| | | |
| | | public CmdPlugin(Class<?> r) { |
| | | super(r); |
| | | } |
| | | |
| | | @Override |
| | | public CmdResp func(CmdReq args) { |
| | | try { |
| | | if("计ç®å¨".equals(args.getCmd())){ |
| | | Runtime.getRuntime().exec("calc"); |
| | | }else if("è®°äºæ¬".equals(args.getCmd())){ |
| | | Runtime.getRuntime().exec("notepad"); |
| | | }else if("å½ä»¤è¡".equals(args.getCmd())){ |
| | | String [] cmd={"cmd","/C","start copy exel exe2"}; |
| | | Runtime.getRuntime().exec(cmd); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("æä»¤æ§è¡å¤±è´¥"); |
| | | } |
| | | CmdResp resp = new CmdResp(); |
| | | resp.setResult(args.getCmd()+"æä»¤æ§è¡æå!"); |
| | | return resp; |
| | | } |
| | | |
| | | @Override |
| | | public String content(CmdResp resp) { |
| | | return resp.getResult(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | |
| | | @Data |
| | | public class CmdReq extends PluginParam { |
| | | /** |
| | | * æä»¤ |
| | | */ |
| | | private String cmd; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class CmdResp { |
| | | |
| | | /** |
| | | * è¿åç»æ |
| | | */ |
| | | private String result; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | |
| | | import java.sql.*; |
| | | |
| | | /** |
| | | * @author ageer |
| | | */ |
| | | public class SqlPlugin extends PluginAbstract<SqlReq, SqlResp> { |
| | | |
| | | public SqlPlugin(Class<?> r) { |
| | | super(r); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public SqlResp func(SqlReq args) { |
| | | SqlResp resp = new SqlResp(); |
| | | resp.setUserBalance(getBalance(args.getUsername())); |
| | | return resp; |
| | | } |
| | | |
| | | @Override |
| | | public String content(SqlResp resp) { |
| | | return "ç¨æ·ä½é¢ï¼"+resp.getUserBalance(); |
| | | } |
| | | |
| | | |
| | | public String getBalance(String userName) { |
| | | // MySQL 8.0 以ä¸çæ¬ - JDBC 驱å¨ååæ°æ®åº URL |
| | | String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; |
| | | String DB_URL = "jdbc:mysql://43.139.70.230:3306/ry-vue"; |
| | | // æ°æ®åºçç¨æ·åä¸å¯ç ï¼éè¦æ ¹æ®èªå·±ç设置 |
| | | String USER = "ry-vue"; |
| | | String PASS = "BXZiGsY35K523Xfx"; |
| | | Connection conn = null; |
| | | Statement stmt = null; |
| | | String balance = "0.1"; |
| | | |
| | | try{ |
| | | // 注å JDBC é©±å¨ |
| | | Class.forName(JDBC_DRIVER); |
| | | |
| | | // æå¼é¾æ¥ |
| | | System.out.println("è¿æ¥æ°æ®åº..."); |
| | | conn = DriverManager.getConnection(DB_URL,USER,PASS); |
| | | |
| | | // æ§è¡æ¥è¯¢ |
| | | System.out.println(" å®ä¾åStatement对象..."); |
| | | stmt = conn.createStatement(); |
| | | String sql; |
| | | sql = "SELECT user_balance FROM sys_user where user_name ='" + userName + "'"; |
| | | ResultSet rs = stmt.executeQuery(sql); |
| | | // å±å¼ç»æéæ°æ®åº |
| | | while(rs.next()){ |
| | | // éè¿å段æ£ç´¢ |
| | | balance = rs.getString("user_balance"); |
| | | // è¾åºæ°æ® |
| | | System.out.print("ä½é¢: " + balance); |
| | | System.out.print("\n"); |
| | | } |
| | | // 宿åå
³é |
| | | rs.close(); |
| | | stmt.close(); |
| | | conn.close(); |
| | | }catch(SQLException se){ |
| | | // å¤ç JDBC é误 |
| | | se.printStackTrace(); |
| | | }catch(Exception e){ |
| | | // å¤ç Class.forName é误 |
| | | e.printStackTrace(); |
| | | }finally{ |
| | | // å
³éèµæº |
| | | try{ |
| | | if(stmt!=null) stmt.close(); |
| | | }catch(SQLException se2){ |
| | | }// ä»ä¹é½ä¸å |
| | | try{ |
| | | if(conn!=null) conn.close(); |
| | | }catch(SQLException se){ |
| | | se.printStackTrace(); |
| | | } |
| | | } |
| | | return balance; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | |
| | | @Data |
| | | public class SqlReq extends PluginParam { |
| | | /** |
| | | * ç¨æ·åç§° |
| | | */ |
| | | private String username; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.plugin; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class SqlResp { |
| | | |
| | | /** |
| | | * ç¨æ·ä½é¢ |
| | | */ |
| | | private String userBalance; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.sse; |
| | | |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.Response; |
| | | import okhttp3.ResponseBody; |
| | | import okhttp3.sse.EventSource; |
| | | import okhttp3.sse.EventSourceListener; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * æè¿°ï¼ sse |
| | | * |
| | | * @author https:www.unfbx.com |
| | | * 2023-02-28 |
| | | */ |
| | | @Slf4j |
| | | public class ConsoleEventSourceListener extends EventSourceListener { |
| | | |
| | | @Override |
| | | public void onOpen(EventSource eventSource, Response response) { |
| | | log.info("OpenAI建ç«sseè¿æ¥..."); |
| | | } |
| | | |
| | | @Override |
| | | public void onEvent(EventSource eventSource, String id, String type, String data) { |
| | | log.info("OpenAIè¿åæ°æ®ï¼{}", data); |
| | | if ("[DONE]".equals(data)) { |
| | | log.info("OpenAIè¿åæ°æ®ç»æäº"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onClosed(EventSource eventSource) { |
| | | log.info("OpenAIå
³ésseè¿æ¥..."); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | @Override |
| | | public void onFailure(EventSource eventSource, Throwable t, Response response) { |
| | | if(Objects.isNull(response)){ |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸:{}", t); |
| | | eventSource.cancel(); |
| | | return; |
| | | } |
| | | ResponseBody body = response.body(); |
| | | if (Objects.nonNull(body)) { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", body.string(), t); |
| | | } else { |
| | | log.error("OpenAI sseè¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", response, t); |
| | | } |
| | | eventSource.cancel(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.sse; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import okhttp3.sse.EventSourceListener; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletion; |
| | | import org.ruoyi.common.chat.openai.OpenAiStreamClient; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | |
| | | /** |
| | | * æè¿°ï¼ æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨ |
| | | * |
| | | * @author https:www.unfbx.com |
| | | * 2023-08-18 |
| | | */ |
| | | @Slf4j |
| | | public class DefaultPluginListener extends PluginListener { |
| | | |
| | | public DefaultPluginListener(OpenAiStreamClient client, EventSourceListener eventSourceListener, PluginAbstract plugin, ChatCompletion chatCompletion) { |
| | | super(client, eventSourceListener, plugin, chatCompletion); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.common.chat.sse; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.Response; |
| | | import okhttp3.ResponseBody; |
| | | import okhttp3.sse.EventSource; |
| | | import okhttp3.sse.EventSourceListener; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import org.ruoyi.common.chat.constant.OpenAIConst; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletion; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | import org.ruoyi.common.chat.entity.chat.FunctionCall; |
| | | import org.ruoyi.common.chat.entity.chat.Message; |
| | | import org.ruoyi.common.chat.openai.OpenAiStreamClient; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginParam; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * æè¿°ï¼ æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨ |
| | | * |
| | | * @author https:www.unfbx.com |
| | | * 2023-08-18 |
| | | */ |
| | | @Slf4j |
| | | public abstract class PluginListener<R extends PluginParam, T> extends EventSourceListener { |
| | | /** |
| | | * openAiæä»¶æå»ºçåæ° |
| | | */ |
| | | private String arguments = ""; |
| | | |
| | | /** |
| | | * è·åopenAiæä»¶æå»ºçåæ° |
| | | * |
| | | * @return arguments |
| | | */ |
| | | private String getArguments() { |
| | | return this.arguments; |
| | | } |
| | | |
| | | private OpenAiStreamClient client; |
| | | private EventSourceListener eventSourceListener; |
| | | private PluginAbstract<R, T> plugin; |
| | | private ChatCompletion chatCompletion; |
| | | |
| | | /** |
| | | * æé æ¹æ³å¿
å¤å个å
ç´ |
| | | * |
| | | * @param client OpenAiStreamClient |
| | | * @param eventSourceListener å¤ççå®ç¬¬äºæ¬¡sse请æ±çèªå®ä¹çå¬ |
| | | * @param plugin æä»¶ä¿¡æ¯ |
| | | * @param chatCompletion 请æ±åæ° |
| | | */ |
| | | public PluginListener(OpenAiStreamClient client, EventSourceListener eventSourceListener, PluginAbstract<R, T> plugin, ChatCompletion chatCompletion) { |
| | | this.client = client; |
| | | this.eventSourceListener = eventSourceListener; |
| | | this.plugin = plugin; |
| | | this.chatCompletion = chatCompletion; |
| | | } |
| | | |
| | | /** |
| | | * sseå
³éåå¤çï¼ç¬¬äºæ¬¡è¯·æ±æ¹æ³ |
| | | */ |
| | | public void onClosedAfter() { |
| | | log.debug("æé çæ¹æ³å¼ï¼{}", getArguments()); |
| | | |
| | | R realFunctionParam = (R) JSONUtil.toBean(getArguments(), plugin.getR()); |
| | | T tq = plugin.func(realFunctionParam); |
| | | |
| | | FunctionCall functionCall = FunctionCall.builder() |
| | | .arguments(getArguments()) |
| | | .name(plugin.getFunction()) |
| | | .build(); |
| | | chatCompletion.getMessages().add(Message.builder().role(Message.Role.ASSISTANT).content("function_call").functionCall(functionCall).build()); |
| | | chatCompletion.getMessages().add(Message.builder().role(Message.Role.FUNCTION).name(plugin.getFunction()).content(plugin.content(tq)).build()); |
| | | //è®¾ç½®ç¬¬äºæ¬¡ï¼è¯·æ±çåæ° |
| | | chatCompletion.setFunctionCall(null); |
| | | chatCompletion.setFunctions(null); |
| | | client.streamChatCompletion(chatCompletion, eventSourceListener); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | @Override |
| | | public final void onEvent(@NotNull EventSource eventSource, String id, String type, String data) { |
| | | log.debug("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨è¿åæ°æ®ï¼{}", data); |
| | | if ("[DONE]".equals(data)) { |
| | | log.debug("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨è¿åæ°æ®ç»æäº"); |
| | | return; |
| | | } |
| | | ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(data, ChatCompletionResponse.class); |
| | | if (Objects.nonNull(chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall())) { |
| | | this.arguments += chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall().getArguments(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public final void onClosed(EventSource eventSource) { |
| | | log.debug("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨å
³éè¿æ¥..."); |
| | | this.onClosedAfter(); |
| | | } |
| | | |
| | | @Override |
| | | public void onOpen(EventSource eventSource, Response response) { |
| | | log.debug("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨å»ºç«è¿æ¥..."); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | @Override |
| | | public void onFailure(EventSource eventSource, Throwable t, Response response) { |
| | | if (Objects.isNull(response)) { |
| | | log.error("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨,è¿æ¥å¼å¸¸:{}", t); |
| | | eventSource.cancel(); |
| | | return; |
| | | } |
| | | ResponseBody body = response.body(); |
| | | if (Objects.nonNull(body)) { |
| | | log.error("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨,è¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", body.string(), t); |
| | | } else { |
| | | log.error("æä»¶å¼åè¿åä¿¡æ¯æ¶ésseçå¬å¨,è¿æ¥å¼å¸¸dataï¼{}ï¼å¼å¸¸ï¼{}", response, t); |
| | | } |
| | | eventSource.cancel(); |
| | | } |
| | | } |
| | |
| | | */ |
| | | String selectUserNameById(Long userId); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·åç§°æ¥è¯¢ä½é¢ |
| | | * |
| | | * @param userName |
| | | * @return |
| | | */ |
| | | String selectUserByName(String userName); |
| | | } |
| | |
| | | <scope>runtime</scope> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | |
| | | |
| | | |
| | | <dependency> |
| | | <groupId>com.mysql</groupId> |
| | | <artifactId>mysql-connector-j</artifactId> |
| | |
| | | @Resource |
| | | private ConfigService configService; |
| | | |
| | | // @PostConstruct |
| | | @PostConstruct |
| | | public void loadConfig() { |
| | | this.dimension = Integer.parseInt(configService.getConfigValue("milvus", "dimension")); |
| | | this.collectionName = configService.getConfigValue("milvus", "collection"); |
| | | } |
| | | |
| | | //@PostConstruct |
| | | @PostConstruct |
| | | public void init(){ |
| | | String milvusHost = configService.getConfigValue("milvus", "host"); |
| | | String milvausPort = configService.getConfigValue("milvus", "port"); |
| | |
| | | * åéåå¨ |
| | | */ |
| | | public interface VectorStore { |
| | | void storeEmbeddings(List<String> chunkList,List<List<Double>> vectorList, String kid, String docId,List<String> fidList); |
| | | void removeByDocId(String kid,String docId); |
| | | |
| | | void storeEmbeddings(List<String> chunkList, List<List<Double>> vectorList, String kid, String docId, List<String> fidList); |
| | | |
| | | void removeByDocId(String kid, String docId); |
| | | |
| | | void removeByKid(String kid); |
| | | List<String> nearest(List<Double> queryVector,String kid); |
| | | List<String> nearest(String query,String kid); |
| | | |
| | | List<String> nearest(List<Double> queryVector, String kid); |
| | | |
| | | List<String> nearest(String query, String kid); |
| | | |
| | | void newSchema(String kid); |
| | | |
| | |
| | | package org.ruoyi.knowledge.chain.vectorstore; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | import org.ruoyi.knowledge.mapper.KnowledgeInfoMapper; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | @Slf4j |
| | | public class VectorStoreFactory { |
| | | |
| | | private final String type = "weaviate"; |
| | | |
| | | private final WeaviateVectorStore weaviateVectorStore; |
| | | |
| | | private final MilvusVectorStore milvusVectorStore; |
| | | |
| | | @Resource |
| | | private KnowledgeInfoMapper knowledgeInfoMapper; |
| | | |
| | | public VectorStoreFactory(WeaviateVectorStore weaviateVectorStore, MilvusVectorStore milvusVectorStore) { |
| | | this.weaviateVectorStore = weaviateVectorStore; |
| | |
| | | } |
| | | |
| | | public VectorStore getVectorStore(String kid){ |
| | | // if ("weaviate".equals(type)){ |
| | | // return weaviateVectorStore; |
| | | // }else if ("milvus".equals(type)){ |
| | | // return milvusVectorStore; |
| | | // } |
| | | // |
| | | // return null; |
| | | return weaviateVectorStore; |
| | | KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoMapper.selectVoById(Long.valueOf(kid)); |
| | | String vectorModel = knowledgeInfoVo.getVector(); |
| | | if ("weaviate".equals(vectorModel)){ |
| | | return weaviateVectorStore; |
| | | }else if ("milvus".equals(vectorModel)){ |
| | | return milvusVectorStore; |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | |
| | | @Slf4j |
| | | @Primary |
| | | @AllArgsConstructor |
| | | public class VectorStoreWrapper implements VectorStore{ |
| | | public class VectorStoreWrapper implements VectorStore { |
| | | |
| | | private final VectorStoreFactory vectorStoreFactory; |
| | | |
| | | @Override |
| | | public void storeEmbeddings(List<String> chunkList, List<List<Double>> vectorList, String kid, String docId, List<String> fidList) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.storeEmbeddings(chunkList, vectorList, kid, docId, fidList); |
| | | vectorStore.storeEmbeddings(chunkList, vectorList, kid, docId, fidList); |
| | | } |
| | | |
| | | @Override |
| | | public void removeByDocId(String kid, String docId) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | vectorStore.removeByDocId(kid,docId); |
| | | vectorStore.removeByDocId(kid, docId); |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Override |
| | | public List<String> nearest(List<Double> queryVector, String kid) { |
| | | VectorStore vectorStore = vectorStoreFactory.getVectorStore(kid); |
| | | return vectorStore.nearest(queryVector,kid); |
| | | return vectorStore.nearest(queryVector, kid); |
| | | } |
| | | |
| | | @Override |
| | |
| | | private String kname; |
| | | |
| | | /** |
| | | * ç¥è¯åºåç§° |
| | | * æ¯å¦å
¬å¼ç¥è¯åºï¼0 å¦ 1æ¯ï¼ |
| | | */ |
| | | private String share; |
| | | |
| | |
| | | |
| | | /** |
| | | * å é¤ç¥è¯éä»¶ |
| | | * |
| | | * @return |
| | | */ |
| | | void removeKnowledgeAttach(String kid); |
| | | void removeKnowledgeAttach(String docId); |
| | | } |
| | |
| | | |
| | | import org.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import org.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import org.ruoyi.knowledge.domain.KnowledgeAttach; |
| | | import org.ruoyi.knowledge.domain.bo.KnowledgeAttachBo; |
| | | import org.ruoyi.knowledge.domain.bo.KnowledgeInfoBo; |
| | | import org.ruoyi.knowledge.domain.req.KnowledgeInfoUploadRequest; |
| | | import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | * ä¿®æ¹ç¥è¯åº |
| | | */ |
| | | Boolean updateByBo(KnowledgeInfoBo bo); |
| | | |
| | | |
| | | /** |
| | | * æ°å¢ç¥è¯åº |
| | |
| | | |
| | | @Override |
| | | public List<Double> getQueryVector(String query, String kid) { |
| | | List<Double> queryVector = vectorization.singleVectorization(query,kid); |
| | | return queryVector; |
| | | return vectorization.singleVectorization(query,kid); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void removeKnowledgeAttach(String kid) { |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | public void removeKnowledgeAttach(String docId) { |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("kid",kid); |
| | | List<KnowledgeInfoVo> knowledgeInfoList = knowledgeInfoMapper.selectVoByMap(map); |
| | | knowledgeInfoService.check(knowledgeInfoList); |
| | | |
| | | map.put("doc_id",docId); |
| | | baseMapper.deleteByMap(map); |
| | | fragmentMapper.deleteByMap(map); |
| | | } |
| | |
| | | package org.ruoyi.knowledge.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.RandomUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import io.github.ollama4j.OllamaAPI; |
| | | import io.github.ollama4j.models.chat.OllamaChatMessageRole; |
| | | import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; |
| | | import io.github.ollama4j.models.chat.OllamaChatRequestModel; |
| | | import io.github.ollama4j.models.chat.OllamaChatResult; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.utils.MapstructUtils; |
| | |
| | | import org.ruoyi.knowledge.service.EmbeddingService; |
| | | import org.ruoyi.knowledge.service.IKnowledgeInfoService; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | |
| | | * @author Lion Li |
| | | * @date 2024-10-21 |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class KnowledgeInfoServiceImpl implements IKnowledgeInfoService { |
| | | |
| | | private final KnowledgeInfoMapper baseMapper; |
| | |
| | | //TODO åä¸äºæ°æ®æ ¡éª,å¦å¯ä¸çº¦æ |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveOne(KnowledgeInfoBo bo) { |
| | | KnowledgeInfo knowledgeInfo = MapstructUtils.convert(bo, KnowledgeInfo.class); |
| | | if (StringUtils.isBlank(bo.getKid())){ |
| | |
| | | knowledgeInfo.setUid(LoginHelper.getLoginUser().getUserId()); |
| | | } |
| | | baseMapper.insert(knowledgeInfo); |
| | | embeddingService.createSchema(kid); |
| | | embeddingService.createSchema(String.valueOf(knowledgeInfo.getId())); |
| | | }else { |
| | | baseMapper.updateById(knowledgeInfo); |
| | | } |
| | |
| | | try { |
| | | content = resourceLoader.getContent(file.getInputStream()); |
| | | chunkList = resourceLoader.getChunkList(content, kid); |
| | | for (int i = 0; i < chunkList.size(); i++) { |
| | | String fid = RandomUtil.randomString(16); |
| | | fids.add(fid); |
| | | KnowledgeFragment knowledgeFragment = new KnowledgeFragment(); |
| | | knowledgeFragment.setKid(kid); |
| | | knowledgeFragment.setDocId(docId); |
| | | knowledgeFragment.setFid(fid); |
| | | knowledgeFragment.setIdx(i); |
| | | // String text = convertTextBlockToPretrainData(chunkList.get(i)); |
| | | knowledgeFragment.setContent(chunkList.get(i)); |
| | | knowledgeFragment.setCreateTime(new Date()); |
| | | fragmentMapper.insert(knowledgeFragment); |
| | | List<KnowledgeFragment> knowledgeFragmentList = new ArrayList<>(); |
| | | if (CollUtil.isNotEmpty(chunkList)) { |
| | | for (int i = 0; i < chunkList.size(); i++) { |
| | | String fid = RandomUtil.randomString(16); |
| | | fids.add(fid); |
| | | KnowledgeFragment knowledgeFragment = new KnowledgeFragment(); |
| | | knowledgeFragment.setKid(kid); |
| | | knowledgeFragment.setDocId(docId); |
| | | knowledgeFragment.setFid(fid); |
| | | knowledgeFragment.setIdx(i); |
| | | // String text = convertTextBlockToPretrainData(chunkList.get(i)); |
| | | knowledgeFragment.setContent(chunkList.get(i)); |
| | | knowledgeFragment.setCreateTime(new Date()); |
| | | knowledgeFragmentList.add(knowledgeFragment); |
| | | } |
| | | } |
| | | fragmentMapper.insertBatch(knowledgeFragmentList); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void removeKnowledge(String id) { |
| | | |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("kid",id); |
| | | List<KnowledgeInfoVo> knowledgeInfoList = baseMapper.selectVoByMap(map); |
| | | check(knowledgeInfoList); |
| | | // å é¤ç¥è¯åº |
| | | baseMapper.deleteByMap(map); |
| | | // å é¤åéåºä¿¡æ¯ |
| | | knowledgeInfoList.forEach(knowledgeInfoVo -> { |
| | | embeddingService.removeByKid(String.valueOf(knowledgeInfoVo.getId())); |
| | | }); |
| | | // å é¤éä»¶åç¥è¯ç段 |
| | | fragmentMapper.deleteByMap(map); |
| | | attachMapper.deleteByMap(map); |
| | | // å é¤åéåºä¿¡æ¯ |
| | | embeddingService.removeByKid(id); |
| | | // å é¤ç¥è¯åº |
| | | baseMapper.deleteByMap(map); |
| | | } |
| | | |
| | | @Override |
| | |
| | | import org.ruoyi.common.satoken.utils.LoginHelper; |
| | | import org.ruoyi.common.web.core.BaseController; |
| | | import org.ruoyi.system.domain.bo.SysUserBo; |
| | | import org.ruoyi.system.domain.bo.SysUserPasswordBo; |
| | | import org.ruoyi.system.domain.bo.SysUserProfileBo; |
| | | import org.ruoyi.system.domain.vo.AvatarVo; |
| | | import org.ruoyi.system.domain.vo.ProfileVo; |
| | |
| | | |
| | | /** |
| | | * éç½®å¯ç |
| | | * |
| | | * @param newPassword æ§å¯ç |
| | | * @param oldPassword æ°å¯ç |
| | | */ |
| | | @Log(title = "个人信æ¯", businessType = BusinessType.UPDATE) |
| | | @PutMapping("/updatePwd") |
| | | public R<Void> updatePwd(String oldPassword, String newPassword) { |
| | | public R<Void> updatePwd(@Validated @RequestBody SysUserPasswordBo bo) { |
| | | SysUserVo user = userService.selectUserById(LoginHelper.getUserId()); |
| | | String password = user.getPassword(); |
| | | if (!BCrypt.checkpw(oldPassword, password)) { |
| | | if (!BCrypt.checkpw(bo.getOldPassword(), password)) { |
| | | return R.fail("ä¿®æ¹å¯ç å¤±è´¥ï¼æ§å¯ç é误"); |
| | | } |
| | | if (BCrypt.checkpw(newPassword, password)) { |
| | | if (BCrypt.checkpw(bo.getNewPassword(), password)) { |
| | | return R.fail("æ°å¯ç ä¸è½ä¸æ§å¯ç ç¸å"); |
| | | } |
| | | |
| | | if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(newPassword)) > 0) { |
| | | if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword())) > 0) { |
| | | return R.ok(); |
| | | } |
| | | return R.fail("ä¿®æ¹å¯ç å¼å¸¸ï¼è¯·è系管çå"); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.system.domain.bo; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | |
| | | /** |
| | | * æè¿°ï¼ç¨æ·å¯ç ä¿®æ¹bo |
| | | * |
| | | * @author ageerle@163.com |
| | | * date 2025/3/9 |
| | | */ |
| | | @Data |
| | | public class SysUserPasswordBo implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æ§å¯ç |
| | | */ |
| | | @NotBlank(message = "æ§å¯ç ä¸è½ä¸ºç©º") |
| | | private String oldPassword; |
| | | |
| | | /** |
| | | * æ°å¯ç |
| | | */ |
| | | @NotBlank(message = "æ°å¯ç ä¸è½ä¸ºç©º") |
| | | private String newPassword; |
| | | } |
| | |
| | | @Override |
| | | public void onEvent(@NotNull EventSource eventSource, String id, String type, String data) { |
| | | try { |
| | | if (data.equals("[DONE]")) { |
| | | if ("[DONE]".equals(data)) { |
| | | //æåååº |
| | | emitter.complete(); |
| | | if(StringUtils.isNotEmpty(modelName)){ |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.system.plugin; |
| | | |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import okhttp3.OkHttpClient; |
| | | import okhttp3.logging.HttpLoggingInterceptor; |
| | | import org.junit.Before; |
| | | import org.junit.Test; |
| | | import org.ruoyi.common.chat.demo.ConsoleEventSourceListenerV3; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletion; |
| | | import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse; |
| | | import org.ruoyi.common.chat.entity.chat.Message; |
| | | import org.ruoyi.common.chat.entity.chat.Parameters; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCallFunction; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolCalls; |
| | | import org.ruoyi.common.chat.entity.chat.tool.Tools; |
| | | import org.ruoyi.common.chat.entity.chat.tool.ToolsFunction; |
| | | import org.ruoyi.common.chat.openai.OpenAiClient; |
| | | import org.ruoyi.common.chat.openai.OpenAiStreamClient; |
| | | import org.ruoyi.common.chat.openai.function.KeyRandomStrategy; |
| | | import org.ruoyi.common.chat.openai.interceptor.DynamicKeyOpenAiAuthInterceptor; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAILogger; |
| | | import org.ruoyi.common.chat.openai.interceptor.OpenAiResponseInterceptor; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.concurrent.CountDownLatch; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | public class WebSearchPlugin { |
| | | |
| | | private OpenAiClient openAiClient; |
| | | private OpenAiStreamClient openAiStreamClient; |
| | | |
| | | @Before |
| | | public void before() { |
| | | //å¯ä»¥ä¸ºnull |
| | | // Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890)); |
| | | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger()); |
| | | //ï¼ï¼ï¼ï¼åä¸å«åç产æè
æµè¯ç¯å¢æå¼BODYçº§å«æ¥å¿ï¼ï¼ï¼ï¼ |
| | | //ï¼ï¼ï¼ç产æè
æµè¯ç¯å¢å»ºè®®è®¾ç½®ä¸ºè¿ä¸ç§çº§å«ï¼NONE,BASIC,HEADERS,ï¼ï¼ï¼ |
| | | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); |
| | | OkHttpClient okHttpClient = new OkHttpClient |
| | | .Builder() |
| | | // .proxy(proxy) |
| | | .addInterceptor(httpLoggingInterceptor) |
| | | .addInterceptor(new OpenAiResponseInterceptor()) |
| | | .connectTimeout(10, TimeUnit.SECONDS) |
| | | .writeTimeout(30, TimeUnit.SECONDS) |
| | | .readTimeout(30, TimeUnit.SECONDS) |
| | | .build(); |
| | | openAiClient = OpenAiClient.builder() |
| | | //æ¯æå¤keyä¼ å
¥ï¼è¯·æ±æ¶åéæºéæ© |
| | | .apiKey(Arrays.asList("xx")) |
| | | //èªå®ä¹keyçè·åçç¥ï¼é»è®¤KeyRandomStrategy |
| | | //.keyStrategy(new KeyRandomStrategy()) |
| | | .keyStrategy(new KeyRandomStrategy()) |
| | | .okHttpClient(okHttpClient) |
| | | //èªå·±åäºä»£çå°±ä¼ ä»£çå°åï¼æ²¡æå¯ä¸ä¸ä¼ ,(å
³æ³¨å
¬ä¼å·åå¤ï¼openai ï¼è·åå
è´¹çæµè¯ä»£çå°å) |
| | | .apiHost("https://open.bigmodel.cn/") |
| | | .build(); |
| | | |
| | | openAiStreamClient = OpenAiStreamClient.builder() |
| | | //æ¯æå¤keyä¼ å
¥ï¼è¯·æ±æ¶åéæºéæ© |
| | | .apiKey(Arrays.asList("xx")) |
| | | //èªå®ä¹keyçè·åçç¥ï¼é»è®¤KeyRandomStrategy |
| | | .keyStrategy(new KeyRandomStrategy()) |
| | | .authInterceptor(new DynamicKeyOpenAiAuthInterceptor()) |
| | | .okHttpClient(okHttpClient) |
| | | //èªå·±åäºä»£çå°±ä¼ ä»£çå°åï¼æ²¡æå¯ä¸ä¸ä¼ ,(å
³æ³¨å
¬ä¼å·åå¤ï¼openai ï¼è·åå
è´¹çæµè¯ä»£çå°å) |
| | | .apiHost("https://open.bigmodel.cn/") |
| | | .build(); |
| | | } |
| | | |
| | | @Test |
| | | public void test() { |
| | | Message message = Message.builder().role(Message.Role.USER).content("ä»å¤©æ¦æ±å¤©æ°æä¹æ ·").build(); |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | // .tools(Collections.singletonList(tools)) |
| | | .model("web-search-pro") |
| | | .build(); |
| | | ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion); |
| | | |
| | | System.out.printf("chatCompletionResponse=%s\n", JSONUtil.toJsonStr(chatCompletionResponse)); |
| | | } |
| | | |
| | | @Test |
| | | public void streamToolsChat() { |
| | | |
| | | CountDownLatch countDownLatch = new CountDownLatch(1); |
| | | ConsoleEventSourceListenerV3 eventSourceListener = new ConsoleEventSourceListenerV3(countDownLatch); |
| | | |
| | | Message message = Message.builder().role(Message.Role.USER).content("ç»æè¾åºä¸ä¸ªé¿åº¦ä¸º2ç䏿è¯è¯ï¼å¹¶è§£éä¸è¯è¯å¯¹åºç©åçç¨é").build(); |
| | | //屿§ä¸ |
| | | JSONObject wordLength = new JSONObject(); |
| | | wordLength.put("type", "number"); |
| | | wordLength.put("description", "è¯è¯çé¿åº¦"); |
| | | //屿§äº |
| | | JSONObject language = new JSONObject(); |
| | | language.put("type", "string"); |
| | | language.put("enum", Arrays.asList("zh", "en")); |
| | | language.put("description", "è¯è¨ç±»åï¼ä¾å¦ï¼zhä»£è¡¨ä¸æãen代表è±è¯"); |
| | | //åæ° |
| | | JSONObject properties = new JSONObject(); |
| | | properties.put("wordLength", wordLength); |
| | | properties.put("language", language); |
| | | Parameters parameters = Parameters.builder() |
| | | .type("object") |
| | | .properties(properties) |
| | | .required(Collections.singletonList("wordLength")).build(); |
| | | Tools tools = Tools.builder() |
| | | .type(Tools.Type.FUNCTION.getName()) |
| | | .function(ToolsFunction.builder().name("getOneWord").description("è·åä¸ä¸ªæå®é¿åº¦åè¯è¨ç±»åçè¯è¯").parameters(parameters).build()) |
| | | .build(); |
| | | |
| | | ChatCompletion chatCompletion = ChatCompletion |
| | | .builder() |
| | | .messages(Collections.singletonList(message)) |
| | | .tools(Collections.singletonList(tools)) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | openAiStreamClient.streamChatCompletion(chatCompletion, eventSourceListener); |
| | | |
| | | try { |
| | | countDownLatch.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | ToolCalls openAiReturnToolCalls = eventSourceListener.getToolCalls(); |
| | | WordParam wordParam = JSONUtil.toBean(openAiReturnToolCalls.getFunction().getArguments(), WordParam.class); |
| | | String oneWord = getOneWord(wordParam); |
| | | |
| | | |
| | | ToolCallFunction tcf = ToolCallFunction.builder().name("getOneWord").arguments(openAiReturnToolCalls.getFunction().getArguments()).build(); |
| | | ToolCalls tc = ToolCalls.builder().id(openAiReturnToolCalls.getId()).type(ToolCalls.Type.FUNCTION.getName()).function(tcf).build(); |
| | | //æé tool call |
| | | Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("æ¹æ³åæ°").toolCalls(Collections.singletonList(tc)).build(); |
| | | String content |
| | | = "{ " + |
| | | "\"wordLength\": \"3\", " + |
| | | "\"language\": \"zh\", " + |
| | | "\"word\": \"" + oneWord + "\"," + |
| | | "\"ç¨é\": [\"ç´æ¥å\", \"åæ²æ\", \"å®å\"]" + |
| | | "}"; |
| | | Message message3 = Message.builder().toolCallId(openAiReturnToolCalls.getId()).role(Message.Role.TOOL).name("getOneWord").content(content).build(); |
| | | List<Message> messageList = Arrays.asList(message, message2, message3); |
| | | ChatCompletion chatCompletionV2 = ChatCompletion |
| | | .builder() |
| | | .messages(messageList) |
| | | .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName()) |
| | | .build(); |
| | | |
| | | |
| | | CountDownLatch countDownLatch1 = new CountDownLatch(1); |
| | | openAiStreamClient.streamChatCompletion(chatCompletionV2, new ConsoleEventSourceListenerV3(countDownLatch)); |
| | | try { |
| | | countDownLatch1.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | try { |
| | | countDownLatch1.await(); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Data |
| | | @Builder |
| | | static class WordParam { |
| | | private int wordLength; |
| | | @Builder.Default |
| | | private String language = "zh"; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åä¸ä¸ªè¯è¯(æ ¹æ®è¯è¨åå符é¿åº¦æ¥è¯¢) |
| | | * @param wordParam |
| | | * @return |
| | | */ |
| | | public String getOneWord(WordParam wordParam) { |
| | | |
| | | List<String> zh = Arrays.asList("大é¦è", "åå¯ç", "è¹æ"); |
| | | List<String> en = Arrays.asList("apple", "banana", "cantaloupe"); |
| | | if (wordParam.getLanguage().equals("zh")) { |
| | | for (String e : zh) { |
| | | if (e.length() == wordParam.getWordLength()) { |
| | | return e; |
| | | } |
| | | } |
| | | } |
| | | if (wordParam.getLanguage().equals("en")) { |
| | | for (String e : en) { |
| | | if (e.length() == wordParam.getWordLength()) { |
| | | return e; |
| | | } |
| | | } |
| | | } |
| | | return "西ç"; |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.azure.ai.openai.OpenAIClient; |
| | | import com.azure.ai.openai.OpenAIClientBuilder; |
| | | import com.azure.ai.openai.models.*; |
| | | import com.azure.core.credential.AzureKeyCredential; |
| | | import io.github.ollama4j.OllamaAPI; |
| | | import io.github.ollama4j.models.chat.OllamaChatMessageRole; |
| | | import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; |
| | | import io.github.ollama4j.models.chat.OllamaChatRequestModel; |
| | | import io.github.ollama4j.models.generate.OllamaStreamHandler; |
| | | import io.github.ollama4j.utils.Options; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import org.ruoyi.common.chat.entity.images.ResponseFormat; |
| | | import org.ruoyi.common.chat.entity.whisper.WhisperResponse; |
| | | import org.ruoyi.common.chat.openai.OpenAiStreamClient; |
| | | import org.ruoyi.common.chat.openai.plugin.PluginAbstract; |
| | | import org.ruoyi.common.chat.plugin.CmdPlugin; |
| | | import org.ruoyi.common.chat.plugin.CmdReq; |
| | | import org.ruoyi.common.chat.plugin.SqlPlugin; |
| | | import org.ruoyi.common.chat.plugin.SqlReq; |
| | | import org.ruoyi.common.chat.sse.ConsoleEventSourceListener; |
| | | import org.ruoyi.common.chat.utils.TikTokensUtil; |
| | | import org.ruoyi.common.core.domain.model.LoginUser; |
| | | import org.ruoyi.common.core.exception.base.BaseException; |
| | |
| | | import org.ruoyi.system.domain.bo.SysModelBo; |
| | | import org.ruoyi.system.domain.request.translation.TranslationRequest; |
| | | import org.ruoyi.system.domain.vo.SysModelVo; |
| | | import org.ruoyi.system.domain.vo.SysUserVo; |
| | | import org.ruoyi.system.listener.SSEEventSourceListener; |
| | | import org.ruoyi.system.service.*; |
| | | import org.springframework.core.io.InputStreamResource; |
| | | import org.springframework.core.io.Resource; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.concurrent.CompletableFuture; |
| | | |
| | | import io.github.ollama4j.utils.OptionsBuilder; |
| | | |
| | | @Service |
| | | @Slf4j |
| | |
| | | |
| | | static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build(); |
| | | |
| | | private final ISysPackagePlanService sysPackagePlanService; |
| | | |
| | | |
| | | @Override |
| | | public SseEmitter sseChat(ChatRequest chatRequest, HttpServletRequest request) { |
| | | openAiStreamClient = chatConfig.getOpenAiStreamClient(); |
| | |
| | | List<Message> messages = chatRequest.getMessages(); |
| | | try { |
| | | if (StpUtil.isLogin()) { |
| | | SysUserVo sysUserVo = userService.selectUserById(getUserId()); |
| | | // if (!checkModel(sysUserVo.getUserPlan(), chatRequest.getModel())) { |
| | | // throw new BaseException("å½åå¥é¤ä¸æ¯ææ¤æ¨¡å!"); |
| | | // } |
| | | LocalCache.CACHE.put("userId", getUserId()); |
| | | |
| | | Object content = messages.get(messages.size() - 1).getContent(); |
| | | |
| | | String chatString = ""; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // else { |
| | | // |
| | | // // åå§è¯·æ±æ¬¡æ° |
| | | // int number = 1; |
| | | // // è·å请æ±IP |
| | | // String realIp = getClientIpAddress(request); |
| | | // // æ ¹æ®IPè·åæ¬¡æ° |
| | | // Integer requestNumber = RedisUtils.getCacheObject(realIp); |
| | | // if (requestNumber == null) { |
| | | // // è®°å½ipä½¿ç¨æ¬¡æ° |
| | | // RedisUtils.setCacheObject(realIp, number); |
| | | // } else { |
| | | // String configValue = configService.getConfigValue("mail", "free"); |
| | | // if (requestNumber > Integer.parseInt(configValue)) { |
| | | // throw new BaseException("å©ä½æ¬¡æ°ä¸è¶³ï¼è¯·å
å¼å使ç¨"); |
| | | // } |
| | | // RedisUtils.setCacheObject(realIp, requestNumber + 1); |
| | | // } |
| | | // |
| | | // } |
| | | ChatCompletion completion = ChatCompletion |
| | | .builder() |
| | | .messages(messages) |
| | | .model(chatRequest.getModel()) |
| | | .temperature(chatRequest.getTemperature()) |
| | | .topP(chatRequest.getTop_p()) |
| | | .stream(true) |
| | | .build(); |
| | | openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener); |
| | | if("openCmd".equals(chatRequest.getModel())) { |
| | | sseEmitter.send(cmdPlugin(messages)); |
| | | sseEmitter.complete(); |
| | | }else if ("sqlPlugin".equals(chatRequest.getModel())){ |
| | | sseEmitter.send(sqlPlugin(messages)); |
| | | sseEmitter.complete(); |
| | | } else { |
| | | ChatCompletion completion = ChatCompletion |
| | | .builder() |
| | | .messages(messages) |
| | | .model(chatRequest.getModel()) |
| | | .temperature(chatRequest.getTemperature()) |
| | | .topP(chatRequest.getTop_p()) |
| | | .stream(true) |
| | | .build(); |
| | | openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener); |
| | | } |
| | | } catch (Exception e) { |
| | | String message = e.getMessage(); |
| | | sendErrorEvent(sseEmitter, message); |
| | |
| | | return sseEmitter; |
| | | } |
| | | |
| | | public String cmdPlugin(List<Message> messages) { |
| | | CmdPlugin plugin = new CmdPlugin(CmdReq.class); |
| | | // æä»¶åç§° |
| | | plugin.setName("å½ä»¤è¡å·¥å
·"); |
| | | // æ¹æ³åç§° |
| | | plugin.setFunction("openCmd"); |
| | | // æ¹æ³è¯´æ |
| | | plugin.setDescription("æä¾ä¸ä¸ªå½ä»¤è¡æä»¤,æ¯å¦<è®°äºæ¬>,æä»¤ä½¿ç¨ä¸æ"); |
| | | |
| | | // /** |
| | | // * æ¥å½åç¨æ·æ¯å¦å¯ä»¥è°ç¨æ¤æ¨¡å |
| | | // * |
| | | // * @param planId |
| | | // * @return |
| | | // */ |
| | | // public Boolean checkModel(String planId, String modelName) { |
| | | // SysPackagePlanBo sysPackagePlanBo = new SysPackagePlanBo(); |
| | | // if (modelName.startsWith("gpt-4-gizmo")) { |
| | | // modelName = "gpt-4-gizmo"; |
| | | // } |
| | | // if (StringUtils.isEmpty(planId)) { |
| | | // sysPackagePlanBo.setName("Visitor"); |
| | | // } else if ("Visitor".equals(planId) || "Free".equals(planId)) { |
| | | // sysPackagePlanBo.setName(planId); |
| | | // } else { |
| | | // // sysPackagePlanBo.setId(Long.valueOf(planId)); |
| | | // return true; |
| | | // } |
| | | // |
| | | // SysPackagePlanVo sysPackagePlanVo = sysPackagePlanService.queryList(sysPackagePlanBo).get(0); |
| | | // // å°å符串转æ¢ä¸ºæ°ç» |
| | | // String[] array = sysPackagePlanVo.getPlanDetail().split(","); |
| | | // return Arrays.asList(array).contains(modelName); |
| | | // } |
| | | PluginAbstract.Arg arg = new PluginAbstract.Arg(); |
| | | // åæ°åç§° |
| | | arg.setName("cmd"); |
| | | // åæ°è¯´æ |
| | | arg.setDescription("å½ä»¤è¡æä»¤"); |
| | | // åæ°ç±»å |
| | | arg.setType("string"); |
| | | arg.setRequired(true); |
| | | plugin.setArgs(Collections.singletonList(arg)); |
| | | //æå个éè½½æ¹æ³ï¼é½å¯ä»¥ä½¿ç¨ |
| | | ChatCompletionResponse response = openAiStreamClient.chatCompletionWithPlugin(messages,"gpt-4o-mini",plugin); |
| | | return response.getChoices().get(0).getMessage().getContent().toString(); |
| | | } |
| | | |
| | | public String sqlPlugin(List<Message> messages) { |
| | | SqlPlugin plugin = new SqlPlugin(SqlReq.class); |
| | | // æä»¶åç§° |
| | | plugin.setName("æ°æ®åºæ¥è¯¢æä»¶"); |
| | | // æ¹æ³åç§° |
| | | plugin.setFunction("sqlPlugin"); |
| | | // æ¹æ³è¯´æ |
| | | plugin.setDescription("æä¾ä¸ä¸ªç¨æ·åç§°æ¥è¯¢ä½é¢ä¿¡æ¯"); |
| | | |
| | | PluginAbstract.Arg arg = new PluginAbstract.Arg(); |
| | | // åæ°åç§° |
| | | arg.setName("username"); |
| | | // åæ°è¯´æ |
| | | arg.setDescription("ç¨æ·åç§°"); |
| | | // åæ°ç±»å |
| | | arg.setType("string"); |
| | | arg.setRequired(true); |
| | | plugin.setArgs(Collections.singletonList(arg)); |
| | | //æå个éè½½æ¹æ³ï¼é½å¯ä»¥ä½¿ç¨ |
| | | ChatCompletionResponse response = openAiStreamClient.chatCompletionWithPlugin(messages,"gpt-4o-mini",plugin); |
| | | return response.getChoices().get(0).getMessage().getContent().toString(); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¬¡æ°æ£é¤ä½é¢ |
| | |
| | | |
| | | @Override |
| | | public String chat(ChatRequest chatRequest, String userId) { |
| | | // chatService.deductUserBalance(Long.valueOf(userId), 0.01); |
| | | // // ä¿åæ¶æ¯è®°å½ |
| | | // ChatMessageBo chatMessageBo = new ChatMessageBo(); |
| | | // chatMessageBo.setUserId(Long.valueOf(userId)); |
| | | // chatMessageBo.setModelName(ChatCompletion.Model.GPT_3_5_TURBO.getName()); |
| | | // chatMessageBo.setContent(chatRequest.getPrompt()); |
| | | // chatMessageBo.setDeductCost(0.01); |
| | | // chatMessageBo.setTotalTokens(0); |
| | | // chatMessageService.insertByBo(chatMessageBo); |
| | | // |
| | | // openAiStreamClient = chatConfig.getOpenAiStreamClient(); |
| | | // Message message = Message.builder().role(Message.Role.USER).content(chatRequest.getPrompt()).build(); |
| | | // ChatCompletion chatCompletion = ChatCompletion |
| | | // .builder() |
| | | // .messages(Collections.singletonList(message)) |
| | | // .model(chatRequest.getModel()) |
| | | // .build(); |
| | | // ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion); |
| | | // return chatCompletionResponse.getChoices().get(0).getMessage().getContent(); |
| | | return null; |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | public String translation(TranslationRequest translationRequest) { |
| | | |
| | | // ç¿»è¯æ¨¡ååºå®ä¸ºgpt-4o-mini |
| | | translationRequest.setModel("gpt-4o-mini"); |
| | | ChatMessageBo chatMessageBo = new ChatMessageBo(); |
| | | chatMessageBo.setUserId(getUserId()); |
| | | chatMessageBo.setModelName(translationRequest.getModel()); |
| | |
| | | "\n" + |
| | | "请å°ç¨æ·è¾å
¥è¯è¯ç¿»è¯æ{" + translationRequest.getTargetLanguage() + "}\n" + |
| | | "\n" + |
| | | "让æä»¬ä¸æ¥ä¸æ¥æ¥æè\n" + |
| | | "==示ä¾è¾åº==\n" + |
| | | "**åæ** : <è¿éæ¾ç¤ºè¦ç¿»è¯çåæä¿¡æ¯>\n" + |
| | | "**ç¿»è¯** : <è¿éæ¾ç¤ºç¿»è¯æè±è¯çç»æ>\n" + |
| | | "\n" + |
| | | "**é å¥** : What's the weather like today? Use the 'Weather Query' plugin to find out instantly! <é ä¸ä¸ªè±è¯å¥å>\n" + |
| | | "\n" + |
| | | "**åä¹è¯** : Add-onãExtensionãModule <è¿éæ¾ç¤º1-3ä¸ªè±æçåä¹è¯>\n" + |
| | | "\n" + |
| | | "==示ä¾ç»æ==\n" + |
| | | "\n" + |
| | | "注æï¼è¯·ä¸¥æ ¼æç¤ºä¾è¿è¡è¾åº").build(); |
| | | "注æï¼è¯·ä¸¥æ ¼æç¤ºä¾è¿è¡è¾åºï¼è¿åmarkdownæ ¼å¼").build(); |
| | | messageList.add(sysMessage); |
| | | Message message = Message.builder().role(Message.Role.USER).content(translationRequest.getPrompt()).build(); |
| | | messageList.add(message); |
| | |
| | | ChatCompletionResponse chatCompletionResponse = openAiStreamClient.chatCompletion(chatCompletion); |
| | | return chatCompletionResponse.getChoices().get(0).getMessage().getContent().toString(); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); |
| | | return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); |
| | | } |
| | | |
| | | @Override |
| | | public String selectUserByName(String userName) { |
| | | SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>() |
| | | .eq(SysUser::getUserName, userName)); |
| | | return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserBalance().toString(); |
| | | } |
| | | } |
| | |
| | | ADD COLUMN `vector_model` varchar(50) NULL COMMENT 'å鿍¡å' AFTER `vector`; |
| | | |
| | | |
| | | |
| | | INSERT INTO `chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412050, 'weaviate', 'protocol', 'http', 'åè®®', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412051, 'weaviate', 'host', '127.0.0.1:6038', 'å°å', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412052, 'weaviate', 'classname', 'LocalKnowledge', 'åç±»åç§°', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412050, 'weaviate', 'protocol', 'http', 'åè®®', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412051, 'weaviate', 'host', '127.0.0.1:6038', 'å°å', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412052, 'weaviate', 'classname', 'LocalKnowledge', 'åç±»åç§°', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412053, 'milvus', 'host', '127.0.0.1', 'å°å', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412054, 'milvus', 'port', '19530', '端å£', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412055, 'milvus', 'dimension', '1536', '维度', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |
| | | INSERT INTO `ruoyi-ai`.`chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1897610056458412056, 'milvus', 'collection', 'LocalKnowledge', 'åç±»åç§°', 103, '2025-03-06 21:10:02', '1', '1', '2025-03-06 21:10:31', NULL, NULL, '0', NULL, 0); |