From 0a73cb4e1725592470d446a9d2a09e95e27868ca Mon Sep 17 00:00:00 2001 From: 酒亦 <mobaitongxue@163.com> Date: 星期四, 05 六月 2025 12:05:28 +0800 Subject: [PATCH] 上传图片支持使用后台image分类下通义千问模型 --- /dev/null | 75 ------------------ ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageQianwenServiceImpl.java | 140 +++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 75 deletions(-) diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageOpenAiServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageOpenAiServiceImpl.java deleted file mode 100644 index 11b4c1e..0000000 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageOpenAiServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.ruoyi.chat.service.chat.impl; - -import io.modelcontextprotocol.client.McpSyncClient; -import lombok.extern.slf4j.Slf4j; -import org.ruoyi.chat.config.ChatConfig; -import org.ruoyi.chat.enums.ChatModeType; -import org.ruoyi.chat.listener.SSEEventSourceListener; -import org.ruoyi.chat.service.chat.IChatService; -import org.ruoyi.common.chat.entity.chat.ChatCompletion; -import org.ruoyi.common.chat.entity.chat.Message; -import org.ruoyi.common.chat.openai.OpenAiStreamClient; -import org.ruoyi.common.chat.request.ChatRequest; -import org.ruoyi.domain.vo.ChatModelVo; -import org.ruoyi.service.IChatModelService; -import org.springframework.ai.chat.client.ChatClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; - -import java.util.List; - -/** - * 鍥剧墖璇嗗埆妯″瀷 - */ -@Service -@Slf4j -public class ImageOpenAiServiceImpl implements IChatService { - - @Autowired - private IChatModelService chatModelService; - - private final ChatClient chatClient; - - public ImageOpenAiServiceImpl(ChatClient.Builder chatClientBuilder) { - this.chatClient = chatClientBuilder.build(); - } - - @Override - public SseEmitter chat(ChatRequest chatRequest, SseEmitter emitter) { - // 浠庢暟鎹簱鑾峰彇 image 绫诲瀷鐨勬ā鍨嬮厤缃� - ChatModelVo chatModelVo = chatModelService.selectModelByCategory(ChatModeType.IMAGE.getCode()); - if (chatModelVo == null) { - log.error("鏈壘鍒� image 绫诲瀷鐨勬ā鍨嬮厤缃�"); - emitter.completeWithError(new IllegalStateException("鏈壘鍒� image 绫诲瀷鐨勬ā鍨嬮厤缃�")); - return emitter; - } - - // 鍒涘缓 OpenAI 娴佸鎴风 - OpenAiStreamClient openAiStreamClient = ChatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey()); - List<Message> messages = chatRequest.getMessages(); - - // 鍒涘缓 SSE 浜嬩欢婧愮洃鍚櫒 - SSEEventSourceListener listener = new SSEEventSourceListener(emitter, chatRequest.getUserId(), chatRequest.getSessionId()); - - // 鏋勫缓鑱婂ぉ瀹屾垚璇锋眰 - ChatCompletion completion = ChatCompletion - .builder() - .messages(messages) - .model(chatModelVo.getModelName()) // 浣跨敤鏁版嵁搴撲腑閰嶇疆鐨勬ā鍨嬪悕绉� - .stream(true) - .build(); - - // 鍙戣捣娴佸紡鑱婂ぉ瀹屾垚璇锋眰 - openAiStreamClient.streamChatCompletion(completion, listener); - - return emitter; - } - - - @Override - public String getCategory() { - return ChatModeType.IMAGE.getCode(); - } -} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageQianwenServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageQianwenServiceImpl.java new file mode 100644 index 0000000..aefd62f --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/ImageQianwenServiceImpl.java @@ -0,0 +1,140 @@ +package org.ruoyi.chat.service.chat.impl; + +import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation; +import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam; +import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult; +import com.alibaba.dashscope.common.MultiModalMessage; +import com.alibaba.dashscope.common.ResultCallback; +import com.alibaba.dashscope.common.Role; +import com.alibaba.dashscope.exception.NoApiKeyException; +import com.alibaba.dashscope.exception.UploadFileException; +import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel; +import dev.langchain4j.community.model.dashscope.QwenStreamingResponseBuilder; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.SystemMessage; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.internal.Utils; +import dev.langchain4j.model.chat.StreamingChatModel; +import dev.langchain4j.model.chat.response.ChatResponse; +import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; +import io.modelcontextprotocol.client.McpSyncClient; +import io.reactivex.Flowable; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.ruoyi.chat.config.ChatConfig; +import org.ruoyi.chat.enums.ChatModeType; +import org.ruoyi.chat.listener.SSEEventSourceListener; +import org.ruoyi.chat.service.chat.IChatService; +import org.ruoyi.common.chat.entity.chat.ChatCompletion; +import org.ruoyi.common.chat.entity.chat.Message; +import org.ruoyi.common.chat.openai.OpenAiStreamClient; +import org.ruoyi.common.chat.request.ChatRequest; +import org.ruoyi.domain.vo.ChatModelVo; +import org.ruoyi.service.IChatModelService; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.util.*; + +/** + * 鍥剧墖璇嗗埆妯″瀷 + */ +@Service +@Slf4j +public class ImageQianwenServiceImpl implements IChatService { + + @Autowired + private IChatModelService chatModelService; + + @SneakyThrows + @Override + public SseEmitter chat(ChatRequest chatRequest, SseEmitter emitter) { + ChatModelVo chatModelVo = chatModelService.selectModelByCategory("image"); + + // 鍙戦�佹祦寮忔秷鎭� + + MultiModalConversation conv = new MultiModalConversation(); + MultiModalMessage systemMessage = MultiModalMessage.builder().role(Role.SYSTEM.getValue()) + .content(Arrays.asList( + Collections.singletonMap("text",chatRequest.getSysPrompt()))).build(); + // 鑾峰彇鐢ㄦ埛娑堟伅鍐呭 + List<Message> messages = chatRequest.getMessages(); + MultiModalMessage userMessage = null; + //婕暱鐨勬牸寮忚浆鎹� + // 閬嶅巻娑堟伅鍒楄〃锛屾彁鍙栨枃鏈唴瀹� + if (messages != null && !messages.isEmpty()) { + Object content = messages.get(messages.size() - 1).getContent(); + List<Map<String, Object>> contentList = new ArrayList<>(); + StringBuilder textContent = new StringBuilder(); + if (content instanceof List<?>) { + for (Object item : (List<?>) content) { + if (item instanceof Map<?, ?> mapItem) { + String type = (String) mapItem.get("type"); + if ("text".equals(type)) { + String text = (String) mapItem.get("text"); + if (text != null) { + textContent.append(text).append(" "); + } + } else if ("image_url".equals(type)) { + Map<String, String> imageUrl = (Map<String, String>) mapItem.get("image_url"); + contentList.add(Collections.singletonMap("image", imageUrl.get("url"))); + } + } + } + } + // 灏嗘嫾鎺ュ悗鐨勬枃鏈唴瀹规坊鍔犲埌 contentList + if (textContent.length() > 0) { + contentList.add(Collections.singletonMap("text", textContent.toString().trim())); + } + userMessage = MultiModalMessage.builder() + .role(Role.USER.getValue()) + .content(contentList) + .build(); + } + MultiModalConversationParam param = MultiModalConversationParam.builder() + .apiKey(chatModelVo.getApiKey()) + .model(chatModelVo.getModelName()) + .messages(Arrays.asList(systemMessage, userMessage)) + .incrementalOutput(true) + .build(); + + + try { + final QwenStreamingResponseBuilder responseBuilder = new QwenStreamingResponseBuilder(param.getModel(),param.getIncrementalOutput() ); + conv.streamCall(param, new ResultCallback<>() { + @SneakyThrows + public void onEvent(MultiModalConversationResult result) { + + String delta = responseBuilder.append(result); + if (Utils.isNotNullOrEmpty(delta)) { + + emitter.send(delta); + log.info("鏀跺埌娑堟伅鐗囨: {}", delta); + } + } + public void onComplete() { + emitter.complete(); + log.info("娑堟伅缁撴潫", responseBuilder.build()); + } + public void onError(Exception e) { + log.info("璇锋眰澶辫触", e.getMessage()); + } + }); + } catch (NoApiKeyException e) { + emitter.send("璇峰厛閰嶇疆API瀵嗛挜"); + throw new RuntimeException(e); + } catch (UploadFileException e) { + throw new RuntimeException(e); + } + + + return emitter; + } + @Override + public String getCategory() { + return ChatModeType.IMAGE.getCode(); + } +} -- Gitblit v1.9.3