From e0cd94387c3588755fc81071951829f4cf591b9c Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Thu, 5 Sep 2024 23:38:43 +0800 Subject: [PATCH 1/9] BIGTOP-4213: Add AI chat platform DashScop --- .../bigtop-manager-ai-assistant/pom.xml | 4 + .../ai/assistant/GeneralAssistantFactory.java | 47 ++- .../assistant/provider/AIAssistantConfig.java | 9 +- .../provider/LocSystemPromptProvider.java | 19 +- .../provider/PersistentProvider.java | 56 +++ .../assistant/store/PersistentRepository.java | 67 ++++ .../ai/assistant/AIAssistantServiceTest.java | 6 +- .../assistant/SystemPromptProviderTests.java | 4 +- .../manager/ai/core/AbstractAIAssistant.java | 77 +--- .../manager/ai/core/enums/PlatformType.java | 3 +- .../manager/ai/core/factory/AIAssistant.java | 33 +- .../ai/core/factory/AIAssistantFactory.java | 23 +- .../provider/AIAssistantConfigProvider.java | 2 + .../core/provider/SystemPromptProvider.java | 8 +- .../bigtop-manager-ai-dashscope/pom.xml | 49 +++ .../ai/dashscope/DashScopeAssistant.java | 351 ++++++++++++++++++ .../ai/dashscope/DashScopeThreadParam.java | 36 ++ .../ai/dashscope/DashScopeToolBox.java | 42 +++ .../DashScopeMessageRepository.java | 27 ++ .../manager/ai/openai/OpenAIAssistant.java | 92 ++++- bigtop-manager-ai/pom.xml | 1 + .../bigtop/manager/dao/po/ChatThreadPO.java | 4 + .../manager/dao/repository/ChatThreadDao.java | 4 + .../mapper/mysql/ChatThreadMapper.xml | 19 + .../service/impl/AIChatServiceImpl.java | 47 ++- .../main/resources/ddl/MySQL-DDL-CREATE.sql | 4 +- pom.xml | 6 + 27 files changed, 861 insertions(+), 179 deletions(-) create mode 100644 bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java create mode 100644 bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java create mode 100644 bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml create mode 100644 bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java create mode 100644 bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeThreadParam.java create mode 100644 bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeToolBox.java create mode 100644 bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/pom.xml b/bigtop-manager-ai/bigtop-manager-ai-assistant/pom.xml index 62ca8b3f7..f1810e8ba 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/pom.xml +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/pom.xml @@ -39,6 +39,10 @@ org.apache.bigtop bigtop-manager-ai-core + + org.apache.bigtop + bigtop-manager-ai-dashscope + org.apache.bigtop bigtop-manager-dao diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java index 2bc988e81..a916a4ce5 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java @@ -19,6 +19,7 @@ package org.apache.bigtop.manager.ai.assistant; import org.apache.bigtop.manager.ai.assistant.provider.LocSystemPromptProvider; +import org.apache.bigtop.manager.ai.assistant.provider.PersistentProvider; import org.apache.bigtop.manager.ai.core.AbstractAIAssistantFactory; import org.apache.bigtop.manager.ai.core.enums.PlatformType; import org.apache.bigtop.manager.ai.core.enums.SystemPrompt; @@ -27,12 +28,11 @@ import org.apache.bigtop.manager.ai.core.factory.ToolBox; import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; import org.apache.bigtop.manager.ai.core.provider.SystemPromptProvider; +import org.apache.bigtop.manager.ai.dashscope.DashScopeAssistant; import org.apache.bigtop.manager.ai.openai.OpenAIAssistant; import org.apache.commons.lang3.NotImplementedException; -import dev.langchain4j.data.message.SystemMessage; -import dev.langchain4j.store.memory.chat.ChatMemoryStore; import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore; import java.util.Objects; @@ -40,23 +40,23 @@ public class GeneralAssistantFactory extends AbstractAIAssistantFactory { private final SystemPromptProvider systemPromptProvider; - private final ChatMemoryStore chatMemoryStore; + private final PersistentProvider persistentProvider; public GeneralAssistantFactory() { - this(new LocSystemPromptProvider(), new InMemoryChatMemoryStore()); + this(new LocSystemPromptProvider(), new PersistentProvider()); } public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider) { - this(systemPromptProvider, new InMemoryChatMemoryStore()); + this(systemPromptProvider, new PersistentProvider()); } - public GeneralAssistantFactory(ChatMemoryStore chatMemoryStore) { - this(new LocSystemPromptProvider(), chatMemoryStore); + public GeneralAssistantFactory(PersistentProvider persistentProvider) { + this(new LocSystemPromptProvider(), persistentProvider); } - public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider, ChatMemoryStore chatMemoryStore) { + public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider, PersistentProvider persistentProvider) { this.systemPromptProvider = systemPromptProvider; - this.chatMemoryStore = chatMemoryStore; + this.persistentProvider = persistentProvider; } @Override @@ -64,30 +64,39 @@ public AIAssistant createWithPrompt( PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, - SystemPrompt systemPrompts) { + SystemPrompt systemPrompts, + boolean isPersistent) { AIAssistant aiAssistant; if (Objects.requireNonNull(platformType) == PlatformType.OPENAI) { aiAssistant = OpenAIAssistant.builder() .id(id) - .memoryStore(chatMemoryStore) + .memoryStore(isPersistent ? persistentProvider.getChatMemoryStore() : new InMemoryChatMemoryStore()) .withConfigProvider(assistantConfig) .build(); + } else if (Objects.requireNonNull(platformType) == PlatformType.DASH_SCOPE) { + aiAssistant = DashScopeAssistant.builder() + .id(id) + .withConfigProvider(assistantConfig) + .messageRepository(persistentProvider.getPersistentRepository()) + .build(); } else { throw new PlatformNotFoundException(platformType.getValue()); } - - SystemMessage systemPrompt = systemPromptProvider.getSystemPrompt(systemPrompts); - aiAssistant.setSystemPrompt(systemPrompt); - String locale = assistantConfig.getLanguage(); - if (locale != null) { - aiAssistant.setSystemPrompt(systemPromptProvider.getLanguagePrompt(locale)); + if (isPersistent) { + String systemPrompt = systemPromptProvider.getSystemMessage(systemPrompts); + aiAssistant.setSystemPrompt(systemPrompt); + String locale = assistantConfig.getLanguage(); + if (locale != null) { + aiAssistant.setSystemPrompt(systemPromptProvider.getLanguagePrompt(locale)); + } } return aiAssistant; } @Override - public AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id) { - return createWithPrompt(platformType, assistantConfig, id, SystemPrompt.DEFAULT_PROMPT); + public AIAssistant create( + PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, boolean isPersistent) { + return createWithPrompt(platformType, assistantConfig, id, SystemPrompt.DEFAULT_PROMPT, isPersistent); } @Override diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java index fdd3b0dad..051245212 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java @@ -68,6 +68,11 @@ public Map getConfigs() { return configs; } + @Override + public void addConfigs(Map configMap) { + configs.putAll(configMap); + } + @Override public String getLanguage() { return language; @@ -109,7 +114,9 @@ public Builder addConfig(String key, String value) { } public Builder addConfigs(Map configMap) { - configs.putAll(configMap); + if (configMap != null) { + configs.putAll(configMap); + } return this; } diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/LocSystemPromptProvider.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/LocSystemPromptProvider.java index 7163fb258..33e16e7d8 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/LocSystemPromptProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/LocSystemPromptProvider.java @@ -23,7 +23,6 @@ import org.springframework.util.ResourceUtils; -import dev.langchain4j.data.message.SystemMessage; import lombok.extern.slf4j.Slf4j; import java.io.File; @@ -36,7 +35,7 @@ public class LocSystemPromptProvider implements SystemPromptProvider { @Override - public SystemMessage getSystemPrompt(SystemPrompt systemPrompt) { + public String getSystemMessage(SystemPrompt systemPrompt) { if (systemPrompt == SystemPrompt.DEFAULT_PROMPT) { systemPrompt = SystemPrompt.BIGDATA_PROFESSOR; } @@ -45,8 +44,8 @@ public SystemMessage getSystemPrompt(SystemPrompt systemPrompt) { } @Override - public SystemMessage getSystemPrompt() { - return getSystemPrompt(SystemPrompt.DEFAULT_PROMPT); + public String getSystemMessage() { + return getSystemMessage(SystemPrompt.DEFAULT_PROMPT); } private String loadTextFromFile(String fileName) { @@ -64,23 +63,23 @@ private String loadTextFromFile(String fileName) { } } - private SystemMessage loadPromptFromFile(String fileName) { + private String loadPromptFromFile(String fileName) { final String filePath = fileName + ".st"; String text = loadTextFromFile(filePath); if (text == null) { - return SystemMessage.from("You are a helpful assistant."); + return "You are a helpful assistant."; } else { - return SystemMessage.from(text); + return text; } } - public SystemMessage getLanguagePrompt(String locale) { + public String getLanguagePrompt(String locale) { final String filePath = SystemPrompt.LANGUAGE_PROMPT.getValue() + '-' + locale + ".st"; String text = loadTextFromFile(filePath); if (text == null) { - return SystemMessage.from("Answer in " + locale); + return "Answer in " + locale; } else { - return SystemMessage.from(text); + return text; } } } diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java new file mode 100644 index 000000000..2937164ef --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.assistant.provider; + +import org.apache.bigtop.manager.ai.assistant.store.PersistentChatMemoryStore; +import org.apache.bigtop.manager.ai.assistant.store.PersistentRepository; +import org.apache.bigtop.manager.dao.repository.ChatMessageDao; +import org.apache.bigtop.manager.dao.repository.ChatThreadDao; + +import dev.langchain4j.store.memory.chat.ChatMemoryStore; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PersistentProvider { + private final ChatThreadDao chatThreadDao; + private final ChatMessageDao chatMessageDao; + + public PersistentProvider(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { + this.chatThreadDao = chatThreadDao; + this.chatMessageDao = chatMessageDao; + } + + public PersistentProvider() { + chatMessageDao = null; + chatThreadDao = null; + } + + public PersistentRepository getPersistentRepository() { + if (chatThreadDao == null) { + return new PersistentRepository(); + } + return new PersistentRepository(chatThreadDao, chatMessageDao); + } + + public ChatMemoryStore getChatMemoryStore() { + return new PersistentChatMemoryStore(chatThreadDao, chatMessageDao); + } +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java new file mode 100644 index 000000000..7549a0aea --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java @@ -0,0 +1,67 @@ +package org.apache.bigtop.manager.ai.assistant.store; + +import org.apache.bigtop.manager.ai.core.enums.MessageSender; +import org.apache.bigtop.manager.ai.dashscope.repository.DashScopeMessageRepository; +import org.apache.bigtop.manager.dao.po.ChatMessagePO; +import org.apache.bigtop.manager.dao.po.ChatThreadPO; +import org.apache.bigtop.manager.dao.repository.ChatMessageDao; +import org.apache.bigtop.manager.dao.repository.ChatThreadDao; + +public class PersistentRepository implements DashScopeMessageRepository { + private final ChatThreadDao chatThreadDao; + private final ChatMessageDao chatMessageDao; + + private boolean noPersistent() { + return chatThreadDao == null || chatMessageDao == null; + } + + public PersistentRepository(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { + this.chatThreadDao = chatThreadDao; + this.chatMessageDao = chatMessageDao; + } + + public PersistentRepository() { + this.chatThreadDao = null; + this.chatMessageDao = null; + } + + private ChatMessagePO getChatMessagePO(String message, Long threadId, MessageSender sender) { + if (noPersistent()) { + return null; + } + ChatThreadPO chatThreadPO = chatThreadDao.findById(threadId); + ChatMessagePO chatMessagePO = new ChatMessagePO(); + chatMessagePO.setUserId(chatThreadPO.getUserId()); + chatMessagePO.setThreadId(threadId); + chatMessagePO.setSender(sender.getValue()); + chatMessagePO.setMessage(message); + return chatMessagePO; + } + + @Override + public void saveUserMessage(String message, Long threadId) { + if (noPersistent()) { + return; + } + ChatMessagePO chatMessagePO = getChatMessagePO(message, threadId, MessageSender.USER); + chatMessageDao.save(chatMessagePO); + } + + @Override + public void saveAiMessage(String message, Long threadId) { + if (noPersistent()) { + return; + } + ChatMessagePO chatMessagePO = getChatMessagePO(message, threadId, MessageSender.AI); + chatMessageDao.save(chatMessagePO); + } + + @Override + public void saveSystemMessage(String message, Long threadId) { + if (noPersistent()) { + return; + } + ChatMessagePO chatMessagePO = getChatMessagePO(message, threadId, MessageSender.SYSTEM); + chatMessageDao.save(chatMessagePO); + } +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java index 0e623ef00..812f4af5d 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java @@ -64,14 +64,14 @@ public void init() { emmit.next(text.charAt(i) + ""); } })); - when(aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId)) + when(aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false)) .thenReturn(this.aiAssistant); when(aiAssistant.getPlatform()).thenReturn(PlatformType.OPENAI); } @Test public void createNew2SimpleChat() { - AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId); + AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false); String ask = aiAssistant.ask("1?"); assertFalse(ask.isEmpty()); System.out.println(ask); @@ -79,7 +79,7 @@ public void createNew2SimpleChat() { @Test public void createNew2StreamChat() throws InterruptedException { - AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId); + AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false); Flux stringFlux = aiAssistant.streamAsk("stream 1?"); stringFlux.subscribe( System.out::println, diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java index 1f768e17d..6943d8b40 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java @@ -35,10 +35,10 @@ public class SystemPromptProviderTests { @Test public void loadSystemPromptByIdTest() { - SystemMessage systemPrompt1 = systemPromptProvider.getSystemPrompt(SystemPrompt.BIGDATA_PROFESSOR); + SystemMessage systemPrompt1 = systemPromptProvider.getSystemMessage(SystemPrompt.BIGDATA_PROFESSOR); assertFalse(systemPrompt1.text().isEmpty()); - SystemMessage systemPrompt2 = systemPromptProvider.getSystemPrompt(); + SystemMessage systemPrompt2 = systemPromptProvider.getSystemMessage(); assertFalse(systemPrompt2.text().isEmpty()); assertEquals(systemPrompt1.text(), systemPrompt2.text()); diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/AbstractAIAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/AbstractAIAssistant.java index 5b0f383a8..d7b155f85 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/AbstractAIAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/AbstractAIAssistant.java @@ -20,85 +20,12 @@ import org.apache.bigtop.manager.ai.core.factory.AIAssistant; -import dev.langchain4j.data.message.AiMessage; -import dev.langchain4j.data.message.ChatMessage; -import dev.langchain4j.data.message.SystemMessage; -import dev.langchain4j.memory.ChatMemory; -import dev.langchain4j.model.StreamingResponseHandler; -import dev.langchain4j.model.chat.ChatLanguageModel; -import dev.langchain4j.model.chat.StreamingChatLanguageModel; -import dev.langchain4j.model.output.Response; -import reactor.core.publisher.Flux; -import reactor.core.publisher.FluxSink; - public abstract class AbstractAIAssistant implements AIAssistant { - private final ChatLanguageModel chatLanguageModel; - private final StreamingChatLanguageModel streamingChatLanguageModel; - private final Object assistantId; - private final ChatMemory chatMemory; protected static final Integer MEMORY_LEN = 10; - public AbstractAIAssistant( - ChatLanguageModel chatLanguageModel, - StreamingChatLanguageModel streamingChatLanguageModel, - ChatMemory chatMemory) { - this.chatLanguageModel = chatLanguageModel; - this.streamingChatLanguageModel = streamingChatLanguageModel; - this.chatMemory = chatMemory; - this.assistantId = this.chatMemory.id(); - } - - @Override - public Flux streamAsk(ChatMessage chatMessage) { - chatMemory.add(chatMessage); - return Flux.create( - emitter -> streamingChatLanguageModel.generate(chatMemory.messages(), new StreamingResponseHandler<>() { - @Override - public void onNext(String token) { - emitter.next(token); - } - - @Override - public void onError(Throwable error) { - emitter.error(error); - } - - @Override - public void onComplete(Response response) { - StreamingResponseHandler.super.onComplete(response); - chatMemory.add(response.content()); - } - }), - FluxSink.OverflowStrategy.BUFFER); - } - - @Override - public String ask(ChatMessage chatMessage) { - chatMemory.add(chatMessage); - Response generate = chatLanguageModel.generate(chatMemory.messages()); - String aiMessage = generate.content().text(); - chatMemory.add(AiMessage.from(aiMessage)); - return aiMessage; - } - - @Override - public void setSystemPrompt(SystemMessage systemPrompt) { - chatMemory.add(systemPrompt); - } - - @Override - public Object getId() { - return chatMemory.id(); - } - - @Override - public void resetMemory() { - chatMemory.clear(); - } - @Override - public ChatMemory getMemory() { - return this.chatMemory; + public boolean test() { + return ask("1+1=") != null; } } diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/enums/PlatformType.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/enums/PlatformType.java index cadbb2a66..83029c93d 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/enums/PlatformType.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/enums/PlatformType.java @@ -27,7 +27,8 @@ @Getter public enum PlatformType { - OPENAI("openai"); + OPENAI("openai"), + DASH_SCOPE("dashscope"); private final String value; diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java index 6834b0513..d70f75682 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java @@ -20,12 +20,11 @@ import org.apache.bigtop.manager.ai.core.enums.PlatformType; -import dev.langchain4j.data.message.ChatMessage; -import dev.langchain4j.data.message.SystemMessage; -import dev.langchain4j.data.message.UserMessage; -import dev.langchain4j.memory.ChatMemory; import reactor.core.publisher.Flux; +import java.util.HashMap; +import java.util.Map; + public interface AIAssistant { /** @@ -40,20 +39,14 @@ public interface AIAssistant { * @param userMessage * @return */ - Flux streamAsk(ChatMessage userMessage); + Flux streamAsk(String userMessage); /** * This is a conversation based on blocking output. * @param userMessage * @return */ - String ask(ChatMessage userMessage); - - /** - * This is primarily used to retrieve the AI assistant's history of chat conversations. - * @return - */ - ChatMemory getMemory(); + String ask(String userMessage); /** * This is used to get the AIAssistant's Platform @@ -61,19 +54,11 @@ public interface AIAssistant { */ PlatformType getPlatform(); - void setSystemPrompt(SystemMessage systemPrompt); - - void resetMemory(); - - default Flux streamAsk(String message) { - return streamAsk(UserMessage.from(message)); + default Map creatThread() { + return new HashMap<>(); } - default String ask(String message) { - return ask(UserMessage.from(message)); - } + void setSystemPrompt(String systemPrompt); - default void setSystemPrompt(String systemPrompt) { - setSystemPrompt(SystemMessage.systemMessage(systemPrompt)); - } + boolean test(); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java index d6b24034b..f86c0df7c 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java @@ -22,24 +22,21 @@ import org.apache.bigtop.manager.ai.core.enums.SystemPrompt; import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; -import java.util.UUID; - public interface AIAssistantFactory { AIAssistant createWithPrompt( - PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, SystemPrompt systemPrompt); + PlatformType platformType, + AIAssistantConfigProvider assistantConfig, + Object id, + SystemPrompt systemPrompt, + boolean isPersistent); - AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id); + AIAssistant create( + PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, boolean isPersistent); - /** - * TODO Create AIAssistant without memory, should delete UUID - * - * @param platformType platform type - * @param assistantConfig assistant config - * @return AIAssistant - */ - default AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig) { - return create(platformType, assistantConfig, UUID.randomUUID().toString()); + default AIAssistant create( + PlatformType platformType, AIAssistantConfigProvider assistantConfig, boolean isPersistent) { + return create(platformType, assistantConfig, null, isPersistent); } ToolBox createToolBox(PlatformType platformType); diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java index b49d99c86..c9011b0b9 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java @@ -27,5 +27,7 @@ public interface AIAssistantConfigProvider { Map getConfigs(); + void addConfigs(Map configMap); + String getLanguage(); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/SystemPromptProvider.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/SystemPromptProvider.java index 90f0013ae..83bb0d50b 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/SystemPromptProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/SystemPromptProvider.java @@ -20,14 +20,12 @@ import org.apache.bigtop.manager.ai.core.enums.SystemPrompt; -import dev.langchain4j.data.message.SystemMessage; - public interface SystemPromptProvider { - SystemMessage getSystemPrompt(SystemPrompt systemPrompt); + String getSystemMessage(SystemPrompt systemPrompt); // return default system prompt - SystemMessage getSystemPrompt(); + String getSystemMessage(); - SystemMessage getLanguagePrompt(String locale); + String getLanguagePrompt(String locale); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml b/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml new file mode 100644 index 000000000..a31feec46 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml @@ -0,0 +1,49 @@ + + + + 4.0.0 + + org.apache.bigtop + bigtop-manager-ai + ${revision} + + + bigtop-manager-ai-dashscope + ${project.artifactId} + Bigtop Manager AI DashScope + + + + org.apache.bigtop + bigtop-manager-ai-core + ${revision} + + + + dev.langchain4j + langchain4j-open-ai + + + com.alibaba + dashscope-sdk-java + 2.16.3 + + + diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java new file mode 100644 index 000000000..f55c9c9c4 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -0,0 +1,351 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.dashscope; + +import org.apache.bigtop.manager.ai.core.AbstractAIAssistant; +import org.apache.bigtop.manager.ai.core.enums.PlatformType; +import org.apache.bigtop.manager.ai.core.factory.AIAssistant; +import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; +import org.apache.bigtop.manager.ai.dashscope.repository.DashScopeMessageRepository; + +import com.alibaba.dashscope.aigc.generation.Generation; +import com.alibaba.dashscope.aigc.generation.GenerationParam; +import com.alibaba.dashscope.assistants.Assistant; +import com.alibaba.dashscope.assistants.AssistantParam; +import com.alibaba.dashscope.assistants.Assistants; +import com.alibaba.dashscope.common.GeneralListParam; +import com.alibaba.dashscope.common.ListResult; +import com.alibaba.dashscope.common.Message; +import com.alibaba.dashscope.common.Role; +import com.alibaba.dashscope.exception.InputRequiredException; +import com.alibaba.dashscope.exception.InvalidateParameter; +import com.alibaba.dashscope.exception.NoApiKeyException; +import com.alibaba.dashscope.threads.AssistantStreamEvents; +import com.alibaba.dashscope.threads.AssistantThread; +import com.alibaba.dashscope.threads.ContentBase; +import com.alibaba.dashscope.threads.ContentText; +import com.alibaba.dashscope.threads.ThreadParam; +import com.alibaba.dashscope.threads.Threads; +import com.alibaba.dashscope.threads.messages.Messages; +import com.alibaba.dashscope.threads.messages.TextMessageParam; +import com.alibaba.dashscope.threads.messages.ThreadMessage; +import com.alibaba.dashscope.threads.messages.ThreadMessageDelta; +import com.alibaba.dashscope.threads.runs.AssistantStreamMessage; +import com.alibaba.dashscope.threads.runs.Run; +import com.alibaba.dashscope.threads.runs.RunParam; +import com.alibaba.dashscope.threads.runs.Runs; +import dev.langchain4j.internal.ValidationUtils; +import io.reactivex.Flowable; +import reactor.core.publisher.Flux; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DashScopeAssistant extends AbstractAIAssistant { + private Assistants assistants = null; + private Messages messages = null; + private Threads threads = null; + private Runs runs = null; + private final DashScopeMessageRepository messageRepository; + private final DashScopeThreadParam dashScopeThreadParam; + + public DashScopeAssistant(DashScopeMessageRepository messageRepository, DashScopeThreadParam dashScopeThreadParam) { + this.messageRepository = messageRepository; + this.dashScopeThreadParam = dashScopeThreadParam; + } + + private Assistants getAssistants() { + if (assistants == null) { + assistants = new Assistants(); + } + return assistants; + } + + private Threads getThreads() { + if (threads == null) { + threads = new Threads(); + } + return threads; + } + + private Messages getMessages() { + if (messages == null) { + messages = new Messages(); + } + return messages; + } + + private Runs getRuns() { + if (runs == null) { + runs = new Runs(); + } + return runs; + } + + @Override + public PlatformType getPlatform() { + return PlatformType.DASH_SCOPE; + } + + @Override + public void setSystemPrompt(String systemPrompt) { + TextMessageParam textMessageParam = TextMessageParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .role(Role.ASSISTANT.getValue()) + .content(systemPrompt) + .build(); + try { + getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + } catch (NoApiKeyException | InputRequiredException e) { + throw new RuntimeException(e); + } + RunParam runParam = RunParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .assistantId(dashScopeThreadParam.getAssistantId()) + .build(); + try { + getRuns().create(dashScopeThreadParam.getAssistantThreadId(), runParam); + } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { + throw new RuntimeException(e); + } + messageRepository.saveSystemMessage(systemPrompt, (Long) dashScopeThreadParam.getThreadId()); + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public Object getId() { + return dashScopeThreadParam.getThreadId(); + } + + private String getValueFromAssistantStreamMessage(AssistantStreamMessage assistantStreamMessage) { + ThreadMessageDelta threadMessageDelta = (ThreadMessageDelta) assistantStreamMessage.getData(); + StringBuilder streamMessage = new StringBuilder(); + + List contents = threadMessageDelta.getDelta().getContent(); + for (ContentBase content : contents) { + ContentText contentText = (ContentText) content; + streamMessage.append(contentText.getText().getValue()); + } + return streamMessage.toString(); + } + + @Override + public Flux streamAsk(String userMessage) { + messageRepository.saveUserMessage(userMessage, (Long) dashScopeThreadParam.getThreadId()); + TextMessageParam textMessageParam = TextMessageParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .role(Role.USER.getValue()) + .content(userMessage) + .build(); + try { + ThreadMessage message = getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + } catch (NoApiKeyException | InputRequiredException e) { + throw new RuntimeException(e); + } + + RunParam runParam = RunParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .assistantId(dashScopeThreadParam.getAssistantId()) + .stream(true) + .build(); + Flowable runFlowable = null; + try { + runFlowable = getRuns().createStream(dashScopeThreadParam.getAssistantThreadId(), runParam); + } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { + throw new RuntimeException(e); + } + StringBuilder finalMessage = new StringBuilder(); + return Flux.from(runFlowable) + .map(assistantStreamMessage -> { + String message = + assistantStreamMessage.getEvent().equals(AssistantStreamEvents.THREAD_MESSAGE_DELTA) + ? getValueFromAssistantStreamMessage(assistantStreamMessage) + : ""; + finalMessage.append(message); // 在这里拼接消息 + return message; + }) + .doOnComplete(() -> { + messageRepository.saveAiMessage(finalMessage.toString(), (Long) dashScopeThreadParam.getThreadId()); + System.out.println("Stream processing completed."); + }); + } + + @Override + public String ask(String userMessage) { + messageRepository.saveUserMessage(userMessage, (Long) dashScopeThreadParam.getThreadId()); + TextMessageParam textMessageParam = TextMessageParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .role(Role.USER.getValue()) + .content(userMessage) + .build(); + try { + ThreadMessage message = getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + } catch (NoApiKeyException | InputRequiredException e) { + throw new RuntimeException(e); + } + + RunParam runParam = RunParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .assistantId(dashScopeThreadParam.getAssistantId()) + .build(); + Run run; + try { + run = getRuns().create(dashScopeThreadParam.getAssistantThreadId(), runParam); + } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { + throw new RuntimeException(e); + } + while (true) { + if (run.getStatus().equals(Run.Status.CANCELLED) + || run.getStatus().equals(Run.Status.COMPLETED) + || run.getStatus().equals(Run.Status.FAILED) + || run.getStatus().equals(Run.Status.REQUIRES_ACTION) + || run.getStatus().equals(Run.Status.EXPIRED)) { + break; + } else { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + try { + run = runs.retrieve( + dashScopeThreadParam.getAssistantThreadId(), run.getId(), dashScopeThreadParam.getApiKey()); + } catch (NoApiKeyException e) { + throw new RuntimeException(e); + } + } + + ListResult threadMessages = null; + try { + threadMessages = messages.list( + dashScopeThreadParam.getAssistantThreadId(), + GeneralListParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .build()); + } catch (NoApiKeyException | InputRequiredException e) { + throw new RuntimeException(e); + } + List threadMessage = threadMessages.getData(); + if (threadMessage.isEmpty()) { + return null; + } + List contents = threadMessage.get(0).getContent(); + StringBuilder finalMessage = new StringBuilder(); + for (ContentBase content : contents) { + ContentText contentText = (ContentText) content; + finalMessage.append(contentText.getText().getValue()); + } + messageRepository.saveAiMessage(finalMessage.toString(), (Long) dashScopeThreadParam.getThreadId()); + return finalMessage.toString(); + } + + @Override + public boolean test() { + Generation generation = new Generation(); + GenerationParam param = GenerationParam.builder() + .apiKey(dashScopeThreadParam.getApiKey()) + .model(dashScopeThreadParam.getModel()) + .build(); + + Message userMsg = + Message.builder().role(Role.USER.getValue()).content("1+1=").build(); + param.setMessages(Collections.singletonList(userMsg)); + try { + generation.call(param); + } catch (NoApiKeyException | InputRequiredException e) { + throw new RuntimeException(e); + } + return true; + } + + @Override + public Map creatThread() { + AssistantParam param = AssistantParam.builder() + .model(dashScopeThreadParam.getModel()) + .apiKey(dashScopeThreadParam.getApiKey()) + .name("DashScope Assistant") + .build(); + Map threadInfo = new HashMap<>(); + try { + Assistant assistant = getAssistants().create(param); + threadInfo.put("assistantId", assistant.getId()); + } catch (NoApiKeyException e) { + throw new RuntimeException(e); + } + ThreadParam threadParam = + ThreadParam.builder().apiKey(dashScopeThreadParam.getApiKey()).build(); + try { + AssistantThread assistantThread = getThreads().create(threadParam); + threadInfo.put("assistantThreadId", assistantThread.getId()); + } catch (NoApiKeyException e) { + throw new RuntimeException(e); + } + return threadInfo; + } + + public static class Builder { + private Object id; + private AIAssistantConfigProvider configProvider; + private DashScopeMessageRepository messageRepository; + + public Builder() {} + + public Builder withConfigProvider(AIAssistantConfigProvider configProvider) { + this.configProvider = configProvider; + return this; + } + + public Builder id(Object id) { + this.id = id; + return this; + } + + public Builder messageRepository(DashScopeMessageRepository messageRepository) { + this.messageRepository = messageRepository; + return this; + } + + public AIAssistant build() { + String model = ValidationUtils.ensureNotNull(configProvider.getModel(), "model"); + String apiKey = ValidationUtils.ensureNotNull( + configProvider.getCredentials().get("apiKey"), "apiKey"); + DashScopeThreadParam param = new DashScopeThreadParam(); + param.setApiKey(apiKey); + param.setModel(model); + String assistantThreadId = configProvider.getConfigs().get("assistantThreadId"); + if (assistantThreadId != null) { + param.setAssistantThreadId(assistantThreadId); + } + String assistantId = configProvider.getConfigs().get("assistantId"); + if (assistantId != null) { + param.setAssistantId(assistantId); + } + if (id != null) { + param.setThreadId(id); + } + return new DashScopeAssistant(messageRepository, param); + } + } +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeThreadParam.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeThreadParam.java new file mode 100644 index 000000000..06e6f088c --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeThreadParam.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.dashscope; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DashScopeThreadParam { + private Object threadId; + + private String assistantId; + + private String assistantThreadId; + + private String model; + + private String apiKey; +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeToolBox.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeToolBox.java new file mode 100644 index 000000000..6a5ac84e9 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeToolBox.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.dashscope; + +import org.apache.bigtop.manager.ai.core.factory.ToolBox; + +import reactor.core.publisher.Flux; + +import java.util.List; + +public class DashScopeToolBox implements ToolBox { + @Override + public List getTools() { + return null; + } + + @Override + public String invoke(String toolName) { + return null; + } + + @Override + public Flux streamInvoke(String toolName) { + return null; + } +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java new file mode 100644 index 000000000..b0d9248d9 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.dashscope.repository; + +public interface DashScopeMessageRepository { + default void saveUserMessage(String message, Long threadId) {} + + default void saveAiMessage(String message, Long threadId) {} + + default void saveSystemMessage(String message, Long threadId) {} +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-openai/src/main/java/org/apache/bigtop/manager/ai/openai/OpenAIAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-openai/src/main/java/org/apache/bigtop/manager/ai/openai/OpenAIAssistant.java index f5325802b..59eba5807 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-openai/src/main/java/org/apache/bigtop/manager/ai/openai/OpenAIAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-openai/src/main/java/org/apache/bigtop/manager/ai/openai/OpenAIAssistant.java @@ -20,27 +20,104 @@ import org.apache.bigtop.manager.ai.core.AbstractAIAssistant; import org.apache.bigtop.manager.ai.core.enums.PlatformType; +import org.apache.bigtop.manager.ai.core.exception.AssistantConfigNotSetException; import org.apache.bigtop.manager.ai.core.factory.AIAssistant; import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.data.message.SystemMessage; +import dev.langchain4j.data.message.UserMessage; import dev.langchain4j.internal.ValidationUtils; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; +import dev.langchain4j.model.StreamingResponseHandler; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.openai.OpenAiStreamingChatModel; +import dev.langchain4j.model.output.Response; import dev.langchain4j.store.memory.chat.ChatMemoryStore; +import reactor.core.publisher.Flux; +import reactor.core.publisher.FluxSink; public class OpenAIAssistant extends AbstractAIAssistant { + private final ChatLanguageModel chatLanguageModel; + private final StreamingChatLanguageModel streamingChatLanguageModel; + private final ChatMemory chatMemory; + private static final String BASE_URL = "https://api.openai.com/v1"; - private OpenAIAssistant( + public OpenAIAssistant( ChatLanguageModel chatLanguageModel, StreamingChatLanguageModel streamingChatLanguageModel, ChatMemory chatMemory) { - super(chatLanguageModel, streamingChatLanguageModel, chatMemory); + this.chatLanguageModel = chatLanguageModel; + this.streamingChatLanguageModel = streamingChatLanguageModel; + this.chatMemory = chatMemory; + } + + @Override + public Flux streamAsk(String chatMessage) { + if (chatMemory == null || streamingChatLanguageModel == null) { + throw new AssistantConfigNotSetException("threadId"); + } + chatMemory.add(UserMessage.from(chatMessage)); + return Flux.create( + emitter -> streamingChatLanguageModel.generate(chatMemory.messages(), new StreamingResponseHandler<>() { + @Override + public void onNext(String token) { + emitter.next(token); + } + + @Override + public void onError(Throwable error) { + emitter.error(error); + } + + @Override + public void onComplete(Response response) { + StreamingResponseHandler.super.onComplete(response); + chatMemory.add(response.content()); + } + }), + FluxSink.OverflowStrategy.BUFFER); + } + + @Override + public String ask(String chatMessage) { + if (chatMemory == null || chatLanguageModel == null) { + throw new AssistantConfigNotSetException("threadId"); + } + chatMemory.add(UserMessage.from(chatMessage)); + Response generate = chatLanguageModel.generate(chatMemory.messages()); + String aiMessage = generate.content().text(); + chatMemory.add(AiMessage.from(aiMessage)); + return aiMessage; + } + + @Override + public void setSystemPrompt(String systemPrompt) { + if (chatMemory == null) { + throw new AssistantConfigNotSetException("threadId"); + } + chatMemory.add(SystemMessage.systemMessage(systemPrompt)); + } + + public void setSystemPrompt(SystemMessage systemPrompt) { + if (chatMemory == null) { + throw new AssistantConfigNotSetException("threadId"); + } + chatMemory.add(systemPrompt); + } + + @Override + public Object getId() { + return chatMemory.id(); + } + + public void resetMemory() { + chatMemory.clear(); } @Override @@ -76,7 +153,6 @@ public Builder memoryStore(ChatMemoryStore chatMemoryStore) { } public AIAssistant build() { - ValidationUtils.ensureNotNull(id, "id"); String model = ValidationUtils.ensureNotNull(configProvider.getModel(), "model"); String apiKey = ValidationUtils.ensureNotNull( configProvider.getCredentials().get("apiKey"), "apiKey"); @@ -90,11 +166,13 @@ public AIAssistant build() { .baseUrl(BASE_URL) .modelName(model) .build(); - MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder() - .id(id) + MessageWindowChatMemory.Builder builder = MessageWindowChatMemory.builder() .chatMemoryStore(chatMemoryStore) - .maxMessages(MEMORY_LEN) - .build(); + .maxMessages(MEMORY_LEN); + if (id != null) { + builder.id(id); + } + MessageWindowChatMemory chatMemory = builder.build(); return new OpenAIAssistant(openAiChatModel, openaiStreamChatModel, chatMemory); } } diff --git a/bigtop-manager-ai/pom.xml b/bigtop-manager-ai/pom.xml index 58a969811..c731441fa 100644 --- a/bigtop-manager-ai/pom.xml +++ b/bigtop-manager-ai/pom.xml @@ -32,6 +32,7 @@ Bigtop Manager AI bigtop-manager-ai-openai + bigtop-manager-ai-dashscope bigtop-manager-ai-core bigtop-manager-ai-assistant diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java index e4c8628e9..f17cfb33e 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java @@ -25,6 +25,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; +import java.util.Map; @Data @EqualsAndHashCode(callSuper = true) @@ -37,6 +38,9 @@ public class ChatThreadPO extends BasePO implements Serializable { @Column(name = "model", nullable = false, length = 255) private String model; + @Column(name = "thread_info", columnDefinition = "json", nullable = false) + private Map threadInfo; + @Column(name = "user_id") private Long userId; diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ChatThreadDao.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ChatThreadDao.java index a691b7b3c..895cba8f5 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ChatThreadDao.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ChatThreadDao.java @@ -29,6 +29,10 @@ public interface ChatThreadDao extends BaseDao { ChatThreadPO findById(Long id); + ChatThreadPO findByThreadId(@Param("id") Long id); + List findAllByPlatformAuthorizedIdAndUserId( @Param("platformId") Long platformAuthorizedId, @Param("userId") Long userId); + + void saveWithThreadInfo(ChatThreadPO chatThreadPO); } diff --git a/bigtop-manager-dao/src/main/resources/mapper/mysql/ChatThreadMapper.xml b/bigtop-manager-dao/src/main/resources/mapper/mysql/ChatThreadMapper.xml index be702079b..5ecd9a2ae 100644 --- a/bigtop-manager-dao/src/main/resources/mapper/mysql/ChatThreadMapper.xml +++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/ChatThreadMapper.xml @@ -24,6 +24,11 @@ id, user_id, platform_id, model + + + + + + + + + INSERT INTO llm_chat_thread (platform_id, user_id, model, thread_info) + VALUES (#{platformId}, #{userId}, #{model}, #{threadInfo, typeHandler=org.apache.bigtop.manager.dao.handler.JsonTypeHandler}) + ON DUPLICATE KEY UPDATE + platform_id = VALUES(platform_id), + user_id = VALUES(user_id), + model = VALUES(model), + thread_info = VALUES(thread_info) + + \ No newline at end of file diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java index 16ef8e54f..918339822 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java @@ -20,7 +20,7 @@ import org.apache.bigtop.manager.ai.assistant.GeneralAssistantFactory; import org.apache.bigtop.manager.ai.assistant.provider.AIAssistantConfig; -import org.apache.bigtop.manager.ai.assistant.store.PersistentChatMemoryStore; +import org.apache.bigtop.manager.ai.assistant.provider.PersistentProvider; import org.apache.bigtop.manager.ai.core.enums.MessageSender; import org.apache.bigtop.manager.ai.core.enums.PlatformType; import org.apache.bigtop.manager.ai.core.factory.AIAssistant; @@ -54,6 +54,7 @@ import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Flux; import jakarta.annotation.Resource; @@ -64,6 +65,7 @@ import java.util.Objects; @Service +@Slf4j public class AIChatServiceImpl implements AIChatService { @Resource private PlatformDao platformDao; @@ -79,21 +81,20 @@ public class AIChatServiceImpl implements AIChatService { private AIAssistantFactory aiAssistantFactory; - private final AIAssistantFactory aiTestFactory = new GeneralAssistantFactory(); - public AIAssistantFactory getAiAssistantFactory() { if (aiAssistantFactory == null) { - aiAssistantFactory = - new GeneralAssistantFactory(new PersistentChatMemoryStore(chatThreadDao, chatMessageDao)); + aiAssistantFactory = new GeneralAssistantFactory(new PersistentProvider(chatThreadDao, chatMessageDao)); } return aiAssistantFactory; } - private AIAssistantConfig getAIAssistantConfig(PlatformAuthorizedDTO platformAuthorizedDTO) { + private AIAssistantConfig getAIAssistantConfig( + PlatformAuthorizedDTO platformAuthorizedDTO, Map configs) { return AIAssistantConfig.builder() .setModel(platformAuthorizedDTO.getModel()) .setLanguage(LocaleContextHolder.getLocale().toString()) .addCredentials(platformAuthorizedDTO.getCredentials()) + .addConfigs(configs) .build(); } @@ -101,24 +102,27 @@ private PlatformType getPlatformType(String platformName) { return PlatformType.getPlatformType(platformName.toLowerCase()); } - private AIAssistant buildAIAssistant(PlatformAuthorizedDTO platformAuthorizedDTO, Long threadId) { + private AIAssistant buildAIAssistant( + PlatformAuthorizedDTO platformAuthorizedDTO, Long threadId, Map configs) { return getAiAssistantFactory() .create( getPlatformType(platformAuthorizedDTO.getPlatformName()), - getAIAssistantConfig(platformAuthorizedDTO), - threadId); + getAIAssistantConfig(platformAuthorizedDTO, configs), + threadId, + threadId != null); } private Boolean testAuthorization(PlatformAuthorizedDTO platformAuthorizedDTO) { - AIAssistant aiAssistant = aiTestFactory.create( - getPlatformType(platformAuthorizedDTO.getPlatformName()), getAIAssistantConfig(platformAuthorizedDTO)); + AIAssistant aiAssistant = getAiAssistantFactory() + .create( + getPlatformType(platformAuthorizedDTO.getPlatformName()), + getAIAssistantConfig(platformAuthorizedDTO, null), + false); try { - aiAssistant.ask("1+1="); + return aiAssistant.test(); } catch (Exception e) { throw new ApiException(ApiExceptionEnum.CREDIT_INCORRECT, e.getMessage()); } - - return true; } @Override @@ -233,7 +237,13 @@ public ChatThreadVO createChatThreads(Long platformId, String model) { chatThreadPO.setUserId(userId); chatThreadPO.setModel(model); chatThreadPO.setPlatformId(platformAuthorizedPO.getId()); - chatThreadDao.save(chatThreadPO); + + PlatformAuthorizedDTO platformAuthorizedDTO = new PlatformAuthorizedDTO( + platformPO.getName(), platformAuthorizedPO.getCredentials(), chatThreadPO.getModel()); + AIAssistant aiAssistant = buildAIAssistant(platformAuthorizedDTO, null, null); + Map threadInfo = aiAssistant.creatThread(); + chatThreadPO.setThreadInfo(threadInfo); + chatThreadDao.saveWithThreadInfo(chatThreadPO); return ChatThreadConverter.INSTANCE.fromPO2VO(chatThreadPO); } @@ -267,9 +277,9 @@ public List getAllChatThreads(Long platformId, String model) { @Override public SseEmitter talk(Long platformId, Long threadId, String message) { - ChatThreadPO chatThreadPO = chatThreadDao.findById(threadId); + ChatThreadPO chatThreadPO = chatThreadDao.findByThreadId(threadId); Long userId = SessionUserHolder.getUserId(); - if (chatThreadPO == null || !Objects.equals(userId, chatThreadPO.getUserId())) { + if (!Objects.equals(userId, chatThreadPO.getUserId())) { throw new ApiException(ApiExceptionEnum.CHAT_THREAD_NOT_FOUND); } PlatformAuthorizedPO platformAuthorizedPO = platformAuthorizedDao.findByPlatformId(platformId); @@ -280,7 +290,8 @@ public SseEmitter talk(Long platformId, Long threadId, String message) { PlatformPO platformPO = platformDao.findById(platformAuthorizedPO.getPlatformId()); PlatformAuthorizedDTO platformAuthorizedDTO = new PlatformAuthorizedDTO( platformPO.getName(), platformAuthorizedPO.getCredentials(), chatThreadPO.getModel()); - AIAssistant aiAssistant = buildAIAssistant(platformAuthorizedDTO, chatThreadPO.getId()); + AIAssistant aiAssistant = + buildAIAssistant(platformAuthorizedDTO, chatThreadPO.getId(), chatThreadPO.getThreadInfo()); Flux stringFlux = aiAssistant.streamAsk(message); SseEmitter emitter = new SseEmitter(); diff --git a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql index 3988894f8..fb6c27f70 100644 --- a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql +++ b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql @@ -342,6 +342,7 @@ CREATE TABLE `llm_chat_thread` `platform_id` BIGINT(20) UNSIGNED NOT NULL, `user_id` BIGINT(20) UNSIGNED NOT NULL, `model` VARCHAR(255) NOT NULL, + `thread_info` JSON DEFAULT NULL, `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_by` BIGINT DEFAULT NULL, @@ -374,4 +375,5 @@ VALUES (1, now(), now(), 'Administrator', '21232f297a57a5a743894a0e4a801fc3', tr -- Adding default ai chat platform INSERT INTO bigtop_manager.llm_platform (id,credential,NAME,support_models) VALUES -(1,'{"apiKey": "API Key"}','OpenAI','gpt-3.5-turbo,gpt-4,gpt-4o,gpt-3.5-turbo-16k,gpt-4-turbo-preview,gpt-4-32k,gpt-4o-mini'); \ No newline at end of file +(1,'{"apiKey": "API Key"}','OpenAI','gpt-3.5-turbo,gpt-4,gpt-4o,gpt-3.5-turbo-16k,gpt-4-turbo-preview,gpt-4-32k,gpt-4o-mini'), +(2,'{"apiKey": "API Key"}','DashScope','qwen-max,qwen-plus,qwen-turbo'); diff --git a/pom.xml b/pom.xml index 66f14b04f..bcf37b4fe 100644 --- a/pom.xml +++ b/pom.xml @@ -136,6 +136,12 @@ ${project.version} + + org.apache.bigtop + bigtop-manager-ai-dashscope + ${project.version} + + org.apache.bigtop bigtop-manager-ai-assistant From 675dd8aac2b8c111b15b99fdaceb074ae9680ec7 Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Thu, 5 Sep 2024 23:40:06 +0800 Subject: [PATCH 2/9] add license --- .../assistant/store/PersistentRepository.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java index 7549a0aea..e7d9d74fe 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package org.apache.bigtop.manager.ai.assistant.store; import org.apache.bigtop.manager.ai.core.enums.MessageSender; From 87a0b4f212d43e01ca1d262a2b3af8673222d72b Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Thu, 5 Sep 2024 23:44:38 +0800 Subject: [PATCH 3/9] fix unit test --- .../ai/assistant/SystemPromptProviderTests.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java index 6943d8b40..6094a7634 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/SystemPromptProviderTests.java @@ -24,8 +24,6 @@ import org.junit.jupiter.api.Test; -import dev.langchain4j.data.message.SystemMessage; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -35,12 +33,12 @@ public class SystemPromptProviderTests { @Test public void loadSystemPromptByIdTest() { - SystemMessage systemPrompt1 = systemPromptProvider.getSystemMessage(SystemPrompt.BIGDATA_PROFESSOR); - assertFalse(systemPrompt1.text().isEmpty()); + String systemPrompt1 = systemPromptProvider.getSystemMessage(SystemPrompt.BIGDATA_PROFESSOR); + assertFalse(systemPrompt1.isEmpty()); - SystemMessage systemPrompt2 = systemPromptProvider.getSystemMessage(); - assertFalse(systemPrompt2.text().isEmpty()); + String systemPrompt2 = systemPromptProvider.getSystemMessage(); + assertFalse(systemPrompt2.isEmpty()); - assertEquals(systemPrompt1.text(), systemPrompt2.text()); + assertEquals(systemPrompt1, systemPrompt2); } } From cf867e381b68ba62217a44d80942d9b7d9da18c2 Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Fri, 6 Sep 2024 09:17:06 +0800 Subject: [PATCH 4/9] remove chinese comment --- .../manager/ai/core/factory/AIAssistant.java | 12 +++++++++ .../ai/dashscope/DashScopeAssistant.java | 26 +++++++++---------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java index d70f75682..209d9e7eb 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java @@ -54,11 +54,23 @@ public interface AIAssistant { */ PlatformType getPlatform(); + /** + * This is used to create a thread + * @return + */ default Map creatThread() { return new HashMap<>(); } + /** + * This is used to set system prompt + * @return + */ void setSystemPrompt(String systemPrompt); + /** + * This is used to test whether the configuration is correct + * @return + */ boolean test(); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java index f55c9c9c4..83d6df983 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -100,6 +100,18 @@ private Runs getRuns() { return runs; } + private String getValueFromAssistantStreamMessage(AssistantStreamMessage assistantStreamMessage) { + ThreadMessageDelta threadMessageDelta = (ThreadMessageDelta) assistantStreamMessage.getData(); + StringBuilder streamMessage = new StringBuilder(); + + List contents = threadMessageDelta.getDelta().getContent(); + for (ContentBase content : contents) { + ContentText contentText = (ContentText) content; + streamMessage.append(contentText.getText().getValue()); + } + return streamMessage.toString(); + } + @Override public PlatformType getPlatform() { return PlatformType.DASH_SCOPE; @@ -138,18 +150,6 @@ public Object getId() { return dashScopeThreadParam.getThreadId(); } - private String getValueFromAssistantStreamMessage(AssistantStreamMessage assistantStreamMessage) { - ThreadMessageDelta threadMessageDelta = (ThreadMessageDelta) assistantStreamMessage.getData(); - StringBuilder streamMessage = new StringBuilder(); - - List contents = threadMessageDelta.getDelta().getContent(); - for (ContentBase content : contents) { - ContentText contentText = (ContentText) content; - streamMessage.append(contentText.getText().getValue()); - } - return streamMessage.toString(); - } - @Override public Flux streamAsk(String userMessage) { messageRepository.saveUserMessage(userMessage, (Long) dashScopeThreadParam.getThreadId()); @@ -182,7 +182,7 @@ public Flux streamAsk(String userMessage) { assistantStreamMessage.getEvent().equals(AssistantStreamEvents.THREAD_MESSAGE_DELTA) ? getValueFromAssistantStreamMessage(assistantStreamMessage) : ""; - finalMessage.append(message); // 在这里拼接消息 + finalMessage.append(message); return message; }) .doOnComplete(() -> { From be46f2c830822c859dd53dede4a69cdd3d93b0bd Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Fri, 6 Sep 2024 09:31:43 +0800 Subject: [PATCH 5/9] remove system.out --- .../apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java index 83d6df983..e9cbf6b6b 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -187,7 +187,6 @@ public Flux streamAsk(String userMessage) { }) .doOnComplete(() -> { messageRepository.saveAiMessage(finalMessage.toString(), (Long) dashScopeThreadParam.getThreadId()); - System.out.println("Stream processing completed."); }); } From 9a11a146d2061ade0c00393c9d233e3d7afcff3c Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Mon, 9 Sep 2024 15:02:31 +0800 Subject: [PATCH 6/9] fix dashscope/pom.xml --- bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml b/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml index a31feec46..0a7259a10 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/pom.xml @@ -36,14 +36,16 @@ ${revision} - - dev.langchain4j - langchain4j-open-ai - com.alibaba dashscope-sdk-java 2.16.3 + + + org.slf4j + slf4j-simple + + From 9b8f7f58f5bd79abf664ed35bb35e2a7a40023af Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Tue, 10 Sep 2024 11:08:44 +0800 Subject: [PATCH 7/9] fix structural errors --- .../ai/assistant/GeneralAssistantFactory.java | 22 ++++++++++--------- .../assistant/provider/AIAssistantConfig.java | 5 ----- ...ider.java => PersistentStoreProvider.java} | 20 +++++++++-------- ....java => PersistentMessageRepository.java} | 11 +++------- .../provider/AIAssistantConfigProvider.java | 2 -- .../core/repository/MessageRepository.java} | 4 ++-- .../ai/dashscope/DashScopeAssistant.java | 10 ++++----- .../service/impl/AIChatServiceImpl.java | 5 +++-- 8 files changed, 36 insertions(+), 43 deletions(-) rename bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/{PersistentProvider.java => PersistentStoreProvider.java} (73%) rename bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/{PersistentRepository.java => PersistentMessageRepository.java} (88%) rename bigtop-manager-ai/{bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java => bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/repository/MessageRepository.java} (90%) diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java index a916a4ce5..78b00ff7f 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java @@ -19,7 +19,7 @@ package org.apache.bigtop.manager.ai.assistant; import org.apache.bigtop.manager.ai.assistant.provider.LocSystemPromptProvider; -import org.apache.bigtop.manager.ai.assistant.provider.PersistentProvider; +import org.apache.bigtop.manager.ai.assistant.provider.PersistentStoreProvider; import org.apache.bigtop.manager.ai.core.AbstractAIAssistantFactory; import org.apache.bigtop.manager.ai.core.enums.PlatformType; import org.apache.bigtop.manager.ai.core.enums.SystemPrompt; @@ -40,23 +40,24 @@ public class GeneralAssistantFactory extends AbstractAIAssistantFactory { private final SystemPromptProvider systemPromptProvider; - private final PersistentProvider persistentProvider; + private final PersistentStoreProvider persistentStoreProvider; public GeneralAssistantFactory() { - this(new LocSystemPromptProvider(), new PersistentProvider()); + this(new LocSystemPromptProvider(), new PersistentStoreProvider()); } public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider) { - this(systemPromptProvider, new PersistentProvider()); + this(systemPromptProvider, new PersistentStoreProvider()); } - public GeneralAssistantFactory(PersistentProvider persistentProvider) { - this(new LocSystemPromptProvider(), persistentProvider); + public GeneralAssistantFactory(PersistentStoreProvider persistentStoreProvider) { + this(new LocSystemPromptProvider(), persistentStoreProvider); } - public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider, PersistentProvider persistentProvider) { + public GeneralAssistantFactory( + SystemPromptProvider systemPromptProvider, PersistentStoreProvider persistentStoreProvider) { this.systemPromptProvider = systemPromptProvider; - this.persistentProvider = persistentProvider; + this.persistentStoreProvider = persistentStoreProvider; } @Override @@ -70,14 +71,15 @@ public AIAssistant createWithPrompt( if (Objects.requireNonNull(platformType) == PlatformType.OPENAI) { aiAssistant = OpenAIAssistant.builder() .id(id) - .memoryStore(isPersistent ? persistentProvider.getChatMemoryStore() : new InMemoryChatMemoryStore()) + .memoryStore( + isPersistent ? persistentStoreProvider.getChatMemoryStore() : new InMemoryChatMemoryStore()) .withConfigProvider(assistantConfig) .build(); } else if (Objects.requireNonNull(platformType) == PlatformType.DASH_SCOPE) { aiAssistant = DashScopeAssistant.builder() .id(id) .withConfigProvider(assistantConfig) - .messageRepository(persistentProvider.getPersistentRepository()) + .messageRepository(persistentStoreProvider.getPersistentRepository()) .build(); } else { throw new PlatformNotFoundException(platformType.getValue()); diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java index 051245212..132c37a14 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/AIAssistantConfig.java @@ -68,11 +68,6 @@ public Map getConfigs() { return configs; } - @Override - public void addConfigs(Map configMap) { - configs.putAll(configMap); - } - @Override public String getLanguage() { return language; diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java similarity index 73% rename from bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java rename to bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java index 2937164ef..7e6acb446 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java @@ -19,38 +19,40 @@ package org.apache.bigtop.manager.ai.assistant.provider; import org.apache.bigtop.manager.ai.assistant.store.PersistentChatMemoryStore; -import org.apache.bigtop.manager.ai.assistant.store.PersistentRepository; +import org.apache.bigtop.manager.ai.assistant.store.PersistentMessageRepository; +import org.apache.bigtop.manager.ai.core.repository.MessageRepository; import org.apache.bigtop.manager.dao.repository.ChatMessageDao; import org.apache.bigtop.manager.dao.repository.ChatThreadDao; import dev.langchain4j.store.memory.chat.ChatMemoryStore; +import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore; import lombok.Getter; import lombok.Setter; @Getter @Setter -public class PersistentProvider { +public class PersistentStoreProvider { private final ChatThreadDao chatThreadDao; private final ChatMessageDao chatMessageDao; - public PersistentProvider(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { + public PersistentStoreProvider(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { this.chatThreadDao = chatThreadDao; this.chatMessageDao = chatMessageDao; } - public PersistentProvider() { + public PersistentStoreProvider() { chatMessageDao = null; chatThreadDao = null; } - public PersistentRepository getPersistentRepository() { - if (chatThreadDao == null) { - return new PersistentRepository(); - } - return new PersistentRepository(chatThreadDao, chatMessageDao); + public MessageRepository getPersistentRepository() { + return new PersistentMessageRepository(chatThreadDao, chatMessageDao); } public ChatMemoryStore getChatMemoryStore() { + if (chatThreadDao == null) { + return new InMemoryChatMemoryStore(); + } return new PersistentChatMemoryStore(chatThreadDao, chatMessageDao); } } diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentMessageRepository.java similarity index 88% rename from bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java rename to bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentMessageRepository.java index e7d9d74fe..7b9c37154 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentRepository.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/store/PersistentMessageRepository.java @@ -19,13 +19,13 @@ package org.apache.bigtop.manager.ai.assistant.store; import org.apache.bigtop.manager.ai.core.enums.MessageSender; -import org.apache.bigtop.manager.ai.dashscope.repository.DashScopeMessageRepository; +import org.apache.bigtop.manager.ai.core.repository.MessageRepository; import org.apache.bigtop.manager.dao.po.ChatMessagePO; import org.apache.bigtop.manager.dao.po.ChatThreadPO; import org.apache.bigtop.manager.dao.repository.ChatMessageDao; import org.apache.bigtop.manager.dao.repository.ChatThreadDao; -public class PersistentRepository implements DashScopeMessageRepository { +public class PersistentMessageRepository implements MessageRepository { private final ChatThreadDao chatThreadDao; private final ChatMessageDao chatMessageDao; @@ -33,16 +33,11 @@ private boolean noPersistent() { return chatThreadDao == null || chatMessageDao == null; } - public PersistentRepository(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { + public PersistentMessageRepository(ChatThreadDao chatThreadDao, ChatMessageDao chatMessageDao) { this.chatThreadDao = chatThreadDao; this.chatMessageDao = chatMessageDao; } - public PersistentRepository() { - this.chatThreadDao = null; - this.chatMessageDao = null; - } - private ChatMessagePO getChatMessagePO(String message, Long threadId, MessageSender sender) { if (noPersistent()) { return null; diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java index c9011b0b9..b49d99c86 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/AIAssistantConfigProvider.java @@ -27,7 +27,5 @@ public interface AIAssistantConfigProvider { Map getConfigs(); - void addConfigs(Map configMap); - String getLanguage(); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/repository/MessageRepository.java similarity index 90% rename from bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java rename to bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/repository/MessageRepository.java index b0d9248d9..1ad582f18 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/repository/DashScopeMessageRepository.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/repository/MessageRepository.java @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.bigtop.manager.ai.dashscope.repository; +package org.apache.bigtop.manager.ai.core.repository; -public interface DashScopeMessageRepository { +public interface MessageRepository { default void saveUserMessage(String message, Long threadId) {} default void saveAiMessage(String message, Long threadId) {} diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java index e9cbf6b6b..4abc3f4f0 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -22,7 +22,7 @@ import org.apache.bigtop.manager.ai.core.enums.PlatformType; import org.apache.bigtop.manager.ai.core.factory.AIAssistant; import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; -import org.apache.bigtop.manager.ai.dashscope.repository.DashScopeMessageRepository; +import org.apache.bigtop.manager.ai.core.repository.MessageRepository; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationParam; @@ -64,10 +64,10 @@ public class DashScopeAssistant extends AbstractAIAssistant { private Messages messages = null; private Threads threads = null; private Runs runs = null; - private final DashScopeMessageRepository messageRepository; + private final MessageRepository messageRepository; private final DashScopeThreadParam dashScopeThreadParam; - public DashScopeAssistant(DashScopeMessageRepository messageRepository, DashScopeThreadParam dashScopeThreadParam) { + public DashScopeAssistant(MessageRepository messageRepository, DashScopeThreadParam dashScopeThreadParam) { this.messageRepository = messageRepository; this.dashScopeThreadParam = dashScopeThreadParam; } @@ -307,7 +307,7 @@ public Map creatThread() { public static class Builder { private Object id; private AIAssistantConfigProvider configProvider; - private DashScopeMessageRepository messageRepository; + private MessageRepository messageRepository; public Builder() {} @@ -321,7 +321,7 @@ public Builder id(Object id) { return this; } - public Builder messageRepository(DashScopeMessageRepository messageRepository) { + public Builder messageRepository(MessageRepository messageRepository) { this.messageRepository = messageRepository; return this; } diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java index 918339822..527fcc8de 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java @@ -20,7 +20,7 @@ import org.apache.bigtop.manager.ai.assistant.GeneralAssistantFactory; import org.apache.bigtop.manager.ai.assistant.provider.AIAssistantConfig; -import org.apache.bigtop.manager.ai.assistant.provider.PersistentProvider; +import org.apache.bigtop.manager.ai.assistant.provider.PersistentStoreProvider; import org.apache.bigtop.manager.ai.core.enums.MessageSender; import org.apache.bigtop.manager.ai.core.enums.PlatformType; import org.apache.bigtop.manager.ai.core.factory.AIAssistant; @@ -83,7 +83,8 @@ public class AIChatServiceImpl implements AIChatService { public AIAssistantFactory getAiAssistantFactory() { if (aiAssistantFactory == null) { - aiAssistantFactory = new GeneralAssistantFactory(new PersistentProvider(chatThreadDao, chatMessageDao)); + aiAssistantFactory = + new GeneralAssistantFactory(new PersistentStoreProvider(chatThreadDao, chatMessageDao)); } return aiAssistantFactory; } From fd4b115c785f329c7a2e8a6408dc3ff7ce2d40db Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Tue, 10 Sep 2024 11:49:19 +0800 Subject: [PATCH 8/9] add base store provider in ai-core --- .../ai/assistant/GeneralAssistantFactory.java | 38 ++++++++----------- .../provider/PersistentStoreProvider.java | 7 +++- .../ai/assistant/AIAssistantServiceTest.java | 6 +-- .../ai/core/factory/AIAssistantFactory.java | 14 ++----- .../core/provider/MessageStoreProvider.java | 29 ++++++++++++++ .../ai/dashscope/DashScopeAssistant.java | 3 ++ .../service/impl/AIChatServiceImpl.java | 3 +- 7 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/MessageStoreProvider.java diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java index 78b00ff7f..7ff16bcfa 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/GeneralAssistantFactory.java @@ -27,20 +27,19 @@ import org.apache.bigtop.manager.ai.core.factory.AIAssistant; import org.apache.bigtop.manager.ai.core.factory.ToolBox; import org.apache.bigtop.manager.ai.core.provider.AIAssistantConfigProvider; +import org.apache.bigtop.manager.ai.core.provider.MessageStoreProvider; import org.apache.bigtop.manager.ai.core.provider.SystemPromptProvider; import org.apache.bigtop.manager.ai.dashscope.DashScopeAssistant; import org.apache.bigtop.manager.ai.openai.OpenAIAssistant; import org.apache.commons.lang3.NotImplementedException; -import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore; - import java.util.Objects; public class GeneralAssistantFactory extends AbstractAIAssistantFactory { private final SystemPromptProvider systemPromptProvider; - private final PersistentStoreProvider persistentStoreProvider; + private final MessageStoreProvider messageStoreProvider; public GeneralAssistantFactory() { this(new LocSystemPromptProvider(), new PersistentStoreProvider()); @@ -50,14 +49,14 @@ public GeneralAssistantFactory(SystemPromptProvider systemPromptProvider) { this(systemPromptProvider, new PersistentStoreProvider()); } - public GeneralAssistantFactory(PersistentStoreProvider persistentStoreProvider) { - this(new LocSystemPromptProvider(), persistentStoreProvider); + public GeneralAssistantFactory(MessageStoreProvider messageStoreProvider) { + this(new LocSystemPromptProvider(), messageStoreProvider); } public GeneralAssistantFactory( - SystemPromptProvider systemPromptProvider, PersistentStoreProvider persistentStoreProvider) { + SystemPromptProvider systemPromptProvider, MessageStoreProvider messageStoreProvider) { this.systemPromptProvider = systemPromptProvider; - this.persistentStoreProvider = persistentStoreProvider; + this.messageStoreProvider = messageStoreProvider; } @Override @@ -65,40 +64,35 @@ public AIAssistant createWithPrompt( PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, - SystemPrompt systemPrompts, - boolean isPersistent) { + SystemPrompt systemPrompts) { AIAssistant aiAssistant; if (Objects.requireNonNull(platformType) == PlatformType.OPENAI) { aiAssistant = OpenAIAssistant.builder() .id(id) - .memoryStore( - isPersistent ? persistentStoreProvider.getChatMemoryStore() : new InMemoryChatMemoryStore()) + .memoryStore(messageStoreProvider.getChatMemoryStore()) .withConfigProvider(assistantConfig) .build(); } else if (Objects.requireNonNull(platformType) == PlatformType.DASH_SCOPE) { aiAssistant = DashScopeAssistant.builder() .id(id) .withConfigProvider(assistantConfig) - .messageRepository(persistentStoreProvider.getPersistentRepository()) + .messageRepository(messageStoreProvider.getMessageRepository()) .build(); } else { throw new PlatformNotFoundException(platformType.getValue()); } - if (isPersistent) { - String systemPrompt = systemPromptProvider.getSystemMessage(systemPrompts); - aiAssistant.setSystemPrompt(systemPrompt); - String locale = assistantConfig.getLanguage(); - if (locale != null) { - aiAssistant.setSystemPrompt(systemPromptProvider.getLanguagePrompt(locale)); - } + String systemPrompt = systemPromptProvider.getSystemMessage(systemPrompts); + aiAssistant.setSystemPrompt(systemPrompt); + String locale = assistantConfig.getLanguage(); + if (locale != null) { + aiAssistant.setSystemPrompt(systemPromptProvider.getLanguagePrompt(locale)); } return aiAssistant; } @Override - public AIAssistant create( - PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, boolean isPersistent) { - return createWithPrompt(platformType, assistantConfig, id, SystemPrompt.DEFAULT_PROMPT, isPersistent); + public AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id) { + return createWithPrompt(platformType, assistantConfig, id, SystemPrompt.DEFAULT_PROMPT); } @Override diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java index 7e6acb446..3e24ced99 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/main/java/org/apache/bigtop/manager/ai/assistant/provider/PersistentStoreProvider.java @@ -20,6 +20,7 @@ import org.apache.bigtop.manager.ai.assistant.store.PersistentChatMemoryStore; import org.apache.bigtop.manager.ai.assistant.store.PersistentMessageRepository; +import org.apache.bigtop.manager.ai.core.provider.MessageStoreProvider; import org.apache.bigtop.manager.ai.core.repository.MessageRepository; import org.apache.bigtop.manager.dao.repository.ChatMessageDao; import org.apache.bigtop.manager.dao.repository.ChatThreadDao; @@ -31,7 +32,7 @@ @Getter @Setter -public class PersistentStoreProvider { +public class PersistentStoreProvider implements MessageStoreProvider { private final ChatThreadDao chatThreadDao; private final ChatMessageDao chatMessageDao; @@ -45,10 +46,12 @@ public PersistentStoreProvider() { chatThreadDao = null; } - public MessageRepository getPersistentRepository() { + @Override + public MessageRepository getMessageRepository() { return new PersistentMessageRepository(chatThreadDao, chatMessageDao); } + @Override public ChatMemoryStore getChatMemoryStore() { if (chatThreadDao == null) { return new InMemoryChatMemoryStore(); diff --git a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java index 812f4af5d..0e623ef00 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java +++ b/bigtop-manager-ai/bigtop-manager-ai-assistant/src/test/java/org/apache/bigtop/manager/ai/assistant/AIAssistantServiceTest.java @@ -64,14 +64,14 @@ public void init() { emmit.next(text.charAt(i) + ""); } })); - when(aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false)) + when(aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId)) .thenReturn(this.aiAssistant); when(aiAssistant.getPlatform()).thenReturn(PlatformType.OPENAI); } @Test public void createNew2SimpleChat() { - AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false); + AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId); String ask = aiAssistant.ask("1?"); assertFalse(ask.isEmpty()); System.out.println(ask); @@ -79,7 +79,7 @@ public void createNew2SimpleChat() { @Test public void createNew2StreamChat() throws InterruptedException { - AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId, false); + AIAssistant aiAssistant = aiAssistantFactory.create(PlatformType.OPENAI, configProvider, threadId); Flux stringFlux = aiAssistant.streamAsk("stream 1?"); stringFlux.subscribe( System.out::println, diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java index f86c0df7c..5a7d63a0a 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistantFactory.java @@ -25,18 +25,12 @@ public interface AIAssistantFactory { AIAssistant createWithPrompt( - PlatformType platformType, - AIAssistantConfigProvider assistantConfig, - Object id, - SystemPrompt systemPrompt, - boolean isPersistent); + PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, SystemPrompt systemPrompt); - AIAssistant create( - PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id, boolean isPersistent); + AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig, Object id); - default AIAssistant create( - PlatformType platformType, AIAssistantConfigProvider assistantConfig, boolean isPersistent) { - return create(platformType, assistantConfig, null, isPersistent); + default AIAssistant create(PlatformType platformType, AIAssistantConfigProvider assistantConfig) { + return create(platformType, assistantConfig, null); } ToolBox createToolBox(PlatformType platformType); diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/MessageStoreProvider.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/MessageStoreProvider.java new file mode 100644 index 000000000..9e7fee153 --- /dev/null +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/provider/MessageStoreProvider.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.bigtop.manager.ai.core.provider; + +import org.apache.bigtop.manager.ai.core.repository.MessageRepository; + +import dev.langchain4j.store.memory.chat.ChatMemoryStore; + +public interface MessageStoreProvider { + MessageRepository getMessageRepository(); + + ChatMemoryStore getChatMemoryStore(); +} diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java index 4abc3f4f0..6aff9b757 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -119,6 +119,9 @@ public PlatformType getPlatform() { @Override public void setSystemPrompt(String systemPrompt) { + if (dashScopeThreadParam.getAssistantId() == null) { + return; + } TextMessageParam textMessageParam = TextMessageParam.builder() .apiKey(dashScopeThreadParam.getApiKey()) .role(Role.ASSISTANT.getValue()) diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java index 527fcc8de..41002ce7e 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java @@ -109,8 +109,7 @@ private AIAssistant buildAIAssistant( .create( getPlatformType(platformAuthorizedDTO.getPlatformName()), getAIAssistantConfig(platformAuthorizedDTO, configs), - threadId, - threadId != null); + threadId); } private Boolean testAuthorization(PlatformAuthorizedDTO platformAuthorizedDTO) { From 43c3c0d8deafbf4886ffca226eb857e21e440c1c Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Tue, 10 Sep 2024 14:09:57 +0800 Subject: [PATCH 9/9] fix typo & remove some getter --- .../manager/ai/core/factory/AIAssistant.java | 2 +- .../ai/dashscope/DashScopeAssistant.java | 54 +++++-------------- .../service/impl/AIChatServiceImpl.java | 2 +- 3 files changed, 15 insertions(+), 43 deletions(-) diff --git a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java index 209d9e7eb..b79474c55 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-core/src/main/java/org/apache/bigtop/manager/ai/core/factory/AIAssistant.java @@ -58,7 +58,7 @@ public interface AIAssistant { * This is used to create a thread * @return */ - default Map creatThread() { + default Map createThread() { return new HashMap<>(); } diff --git a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java index 6aff9b757..538a67476 100644 --- a/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java +++ b/bigtop-manager-ai/bigtop-manager-ai-dashscope/src/main/java/org/apache/bigtop/manager/ai/dashscope/DashScopeAssistant.java @@ -60,10 +60,10 @@ import java.util.Map; public class DashScopeAssistant extends AbstractAIAssistant { - private Assistants assistants = null; - private Messages messages = null; - private Threads threads = null; - private Runs runs = null; + private final Assistants assistants = new Assistants(); + private final Messages messages = new Messages(); + private final Threads threads = new Threads(); + private final Runs runs = new Runs(); private final MessageRepository messageRepository; private final DashScopeThreadParam dashScopeThreadParam; @@ -72,34 +72,6 @@ public DashScopeAssistant(MessageRepository messageRepository, DashScopeThreadPa this.dashScopeThreadParam = dashScopeThreadParam; } - private Assistants getAssistants() { - if (assistants == null) { - assistants = new Assistants(); - } - return assistants; - } - - private Threads getThreads() { - if (threads == null) { - threads = new Threads(); - } - return threads; - } - - private Messages getMessages() { - if (messages == null) { - messages = new Messages(); - } - return messages; - } - - private Runs getRuns() { - if (runs == null) { - runs = new Runs(); - } - return runs; - } - private String getValueFromAssistantStreamMessage(AssistantStreamMessage assistantStreamMessage) { ThreadMessageDelta threadMessageDelta = (ThreadMessageDelta) assistantStreamMessage.getData(); StringBuilder streamMessage = new StringBuilder(); @@ -128,7 +100,7 @@ public void setSystemPrompt(String systemPrompt) { .content(systemPrompt) .build(); try { - getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + messages.create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); } catch (NoApiKeyException | InputRequiredException e) { throw new RuntimeException(e); } @@ -137,7 +109,7 @@ public void setSystemPrompt(String systemPrompt) { .assistantId(dashScopeThreadParam.getAssistantId()) .build(); try { - getRuns().create(dashScopeThreadParam.getAssistantThreadId(), runParam); + runs.create(dashScopeThreadParam.getAssistantThreadId(), runParam); } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { throw new RuntimeException(e); } @@ -162,7 +134,7 @@ public Flux streamAsk(String userMessage) { .content(userMessage) .build(); try { - ThreadMessage message = getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + ThreadMessage message = messages.create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); } catch (NoApiKeyException | InputRequiredException e) { throw new RuntimeException(e); } @@ -174,7 +146,7 @@ public Flux streamAsk(String userMessage) { .build(); Flowable runFlowable = null; try { - runFlowable = getRuns().createStream(dashScopeThreadParam.getAssistantThreadId(), runParam); + runFlowable = runs.createStream(dashScopeThreadParam.getAssistantThreadId(), runParam); } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { throw new RuntimeException(e); } @@ -202,7 +174,7 @@ public String ask(String userMessage) { .content(userMessage) .build(); try { - ThreadMessage message = getMessages().create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); + ThreadMessage message = messages.create(dashScopeThreadParam.getAssistantThreadId(), textMessageParam); } catch (NoApiKeyException | InputRequiredException e) { throw new RuntimeException(e); } @@ -213,7 +185,7 @@ public String ask(String userMessage) { .build(); Run run; try { - run = getRuns().create(dashScopeThreadParam.getAssistantThreadId(), runParam); + run = runs.create(dashScopeThreadParam.getAssistantThreadId(), runParam); } catch (NoApiKeyException | InputRequiredException | InvalidateParameter e) { throw new RuntimeException(e); } @@ -283,7 +255,7 @@ public boolean test() { } @Override - public Map creatThread() { + public Map createThread() { AssistantParam param = AssistantParam.builder() .model(dashScopeThreadParam.getModel()) .apiKey(dashScopeThreadParam.getApiKey()) @@ -291,7 +263,7 @@ public Map creatThread() { .build(); Map threadInfo = new HashMap<>(); try { - Assistant assistant = getAssistants().create(param); + Assistant assistant = assistants.create(param); threadInfo.put("assistantId", assistant.getId()); } catch (NoApiKeyException e) { throw new RuntimeException(e); @@ -299,7 +271,7 @@ public Map creatThread() { ThreadParam threadParam = ThreadParam.builder().apiKey(dashScopeThreadParam.getApiKey()).build(); try { - AssistantThread assistantThread = getThreads().create(threadParam); + AssistantThread assistantThread = threads.create(threadParam); threadInfo.put("assistantThreadId", assistantThread.getId()); } catch (NoApiKeyException e) { throw new RuntimeException(e); diff --git a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java index 41002ce7e..025b4d48d 100644 --- a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java +++ b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/AIChatServiceImpl.java @@ -241,7 +241,7 @@ public ChatThreadVO createChatThreads(Long platformId, String model) { PlatformAuthorizedDTO platformAuthorizedDTO = new PlatformAuthorizedDTO( platformPO.getName(), platformAuthorizedPO.getCredentials(), chatThreadPO.getModel()); AIAssistant aiAssistant = buildAIAssistant(platformAuthorizedDTO, null, null); - Map threadInfo = aiAssistant.creatThread(); + Map threadInfo = aiAssistant.createThread(); chatThreadPO.setThreadInfo(threadInfo); chatThreadDao.saveWithThreadInfo(chatThreadPO); return ChatThreadConverter.INSTANCE.fromPO2VO(chatThreadPO);