diff --git a/backend/src/main/java/com/talkforgeai/backend/RestClientConfiguration.java b/backend/src/main/java/com/talkforgeai/backend/RestClientConfiguration.java index b94bbbd2..bfb6efc2 100644 --- a/backend/src/main/java/com/talkforgeai/backend/RestClientConfiguration.java +++ b/backend/src/main/java/com/talkforgeai/backend/RestClientConfiguration.java @@ -45,20 +45,6 @@ public class RestClientConfiguration { @Value("${spring.ai.ollama.base-url}") private String ollamaBaseUrl; - @Value("${elevenlabs.api-key}") - private String elevenLabsApiKey; - - @Value("${elevenlabs.api-url}") - private String elevenLabsBaseUrl; - - @Bean(name = "elevenLabsRestClient") - public RestClient elevenLabsRestClient() { - return RestClient.builder() - .baseUrl(elevenLabsBaseUrl) - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + elevenLabsApiKey) - .build(); - } @Bean(name = "openAiRestClient") public RestClient openAiRestClient() { diff --git a/backend/src/main/java/com/talkforgeai/backend/assistant/controller/AssistantSpringController.java b/backend/src/main/java/com/talkforgeai/backend/assistant/controller/AssistantSpringController.java index 9be24b55..d600e255 100644 --- a/backend/src/main/java/com/talkforgeai/backend/assistant/controller/AssistantSpringController.java +++ b/backend/src/main/java/com/talkforgeai/backend/assistant/controller/AssistantSpringController.java @@ -63,6 +63,7 @@ public class AssistantSpringController { private final AssistantSpringService assistantService; + private final FileStorageService fileStorageService; public AssistantSpringController(AssistantSpringService assistantService, @@ -178,6 +179,11 @@ public ResponseEntity getImage(@PathVariable String threadId, } } + @PostMapping("/threads/{threadId}/regenerate") + public void regenerateThread(@PathVariable("threadId") String threadId) { + assistantService.regenerateThread(threadId); + } + @DeleteMapping("/threads/{threadId}") public void deleteThread(@PathVariable("threadId") String threadId) { assistantService.deleteThread(threadId); diff --git a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantMapper.java b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantMapper.java index a4a4b747..9cc8871d 100644 --- a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantMapper.java +++ b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantMapper.java @@ -73,7 +73,7 @@ public Map mapAssistantProperties( Map properties) { Map mappedProperties = new HashMap<>(); - Arrays.stream(AssistantProperties.values()).forEach(property -> { + Arrays.stream(AssistantProperty.values()).forEach(property -> { AssistantPropertyValue propertyValue = properties.get(property.getKey()); if (propertyValue != null) { mappedProperties.put( @@ -89,8 +89,12 @@ public Map mapAssistantProperties( public Map mapProperties(Map properties) { Map mappedProperties = new HashMap<>(); - Arrays.stream(AssistantProperties.values()).forEach(property -> { + Arrays.stream(AssistantProperty.values()).forEach(property -> { String propertyValue = properties.get(property.getKey()); + if (propertyValue != null && propertyValue.isEmpty()) { + propertyValue = null; + } + AssistantPropertyValue assistantPropertyValue = new AssistantPropertyValue(); assistantPropertyValue.setPropertyValue(propertyValue); mappedProperties.put(property.getKey(), assistantPropertyValue); diff --git a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperties.java b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperty.java similarity index 76% rename from backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperties.java rename to backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperty.java index 9ad1d427..f5c84907 100644 --- a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperties.java +++ b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantProperty.java @@ -16,13 +16,13 @@ package com.talkforgeai.backend.assistant.service; -public enum AssistantProperties { +public enum AssistantProperty { TTS_TYPE("tts_type", ""), SPEECHAPI_VOICE("speechAPI_voice", ""), ELEVENLABS_VOICEID("elevenlabs_voiceId", ""), - ELEVENLABS_MODELID("elevenlabs_modelId", "eleven_monolingual_v2"), + ELEVENLABS_MODELID("elevenlabs_modelId", "eleven_multilingual_v2"), ELEVENLABS_SIMILARITYBOOST("elevenlabs_similarityBoost", "0"), ELEVENLABS_STABILITY("elevenlabs_stability", "0"), @@ -30,20 +30,29 @@ public enum AssistantProperties { MODEL_TOP_P("model_topP", "1.0"), MODEL_FREQUENCY_PENALTY("model_frequencyPenalty", "0"), MODEL_PRESENCE_PENALTY("model_presencePenalty", "0"), + MODEL_MAX_TOKENS("model_maxTokens", "4096"), - FEATURE_PLANTUML("feature_plantUMLGeneration", "false"), FEATURE_IMAGEGENERATION("feature_imageGeneration", "false"), FEATURE_AUTOSPEAKDEFAULT("feature_autoSpeakDefault", "false"), FEATURE_TITLEGENERATION("feature_titleGeneration", "true"); - + private final String key; private final String defaultValue; - AssistantProperties(String key, String defaultValue) { + AssistantProperty(String key, String defaultValue) { this.key = key; this.defaultValue = defaultValue; } + public static AssistantProperty fromKey(String key) { + for (AssistantProperty property : AssistantProperty.values()) { + if (property.getKey().equals(key)) { + return property; + } + } + throw new IllegalArgumentException("Unknown key: " + key); + } + public String getDefaultValue() { return defaultValue; } diff --git a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantSpringService.java b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantSpringService.java index ed2e34ba..ffcc530e 100644 --- a/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantSpringService.java +++ b/backend/src/main/java/com/talkforgeai/backend/assistant/service/AssistantSpringService.java @@ -42,6 +42,7 @@ import com.talkforgeai.backend.memory.functions.MemoryContextStorageFunction.Request; import com.talkforgeai.backend.memory.functions.MemoryContextStorageFunction.Response; import com.talkforgeai.backend.memory.functions.MemoryFunctionContext; +import com.talkforgeai.backend.memory.service.DBVectorStore; import com.talkforgeai.backend.memory.service.MemoryService; import com.talkforgeai.backend.storage.FileStorageService; import com.talkforgeai.backend.transformers.MessageProcessor; @@ -103,8 +104,18 @@ public class AssistantSpringService { public static final Logger LOGGER = LoggerFactory.getLogger(AssistantSpringService.class); - public static final String SYSTEM_MESSAGE_PLANTUML = "You can generate PlantUML diagrams. PlantUML code that you generate will be transformed to a downloadable image."; public static final String SYSTEM_MESSAGE_IMAGE_GEN = "You can generate an image by using the following syntax: !image_gen[]"; + private static final String SYSTEM_MESSAGE_MEMORY = """ + + Use the long term conversation memory from the LONG_TERM_MEMORY section to provide accurate answers. + + --------------------- + LONG_TERM_MEMORY: + %s + --------------------- + + """; + private final UniversalChatService universalChatService; private final UniversalImageGenService universalImageGenService; @@ -144,18 +155,16 @@ public AssistantSpringService( private static @NotNull Mono getInitInfosMono(Mono assistantEntityMono, Mono> pastMessages) { - Mono initInfosMono = Mono.zip( + return Mono.zip( Arrays.asList(assistantEntityMono, pastMessages), args -> new InitInfos((AssistantDto) args[0], (List) args[1])); - return initInfosMono; } private static @NotNull Flux> getRunIdEventFlux(String runId) { - Flux> runIdMono = Flux.just(ServerSentEvent.builder() + return Flux.just(ServerSentEvent.builder() .event("run.started") .data(runId) .build()); - return runIdMono; } private static @NotNull List getFinalPromptMessageList( @@ -174,27 +183,30 @@ public AssistantSpringService( List finalPromptMessageList = new ArrayList<>(promptMessageList); - if (assistantDto.properties() - .get(AssistantProperties.FEATURE_IMAGEGENERATION.getKey()).equals( - "true")) { - finalPromptMessageList.addFirst(new SystemMessage(SYSTEM_MESSAGE_IMAGE_GEN)); + // Remove the last message if it was from the user + if (!finalPromptMessageList.isEmpty() + && finalPromptMessageList.getLast() instanceof UserMessage) { + finalPromptMessageList.removeLast(); } if (assistantDto.properties() - .get(AssistantProperties.FEATURE_PLANTUML.getKey()).equals( - "true")) { - finalPromptMessageList.addFirst(new SystemMessage(SYSTEM_MESSAGE_PLANTUML)); + .get(AssistantProperty.FEATURE_IMAGEGENERATION.getKey()).equals("true")) { + finalPromptMessageList.addFirst(new SystemMessage(SYSTEM_MESSAGE_IMAGE_GEN)); } finalPromptMessageList.addFirst(new SystemMessage(assistantDto.instructions())); - StringBuilder memoryMessage = new StringBuilder(); - if (!memoryResultsList.isEmpty()) { + if (!memoryResultsList.isEmpty() && assistantDto.memory() == MemoryType.AI_DECIDES) { + StringBuilder memoryMessage = new StringBuilder(); memoryMessage.append("Use the following information from memory:\n"); memoryResultsList.forEach( result -> memoryMessage.append(result.content()).append("\n")); memoryMessage.append("\nUser message:\n"); + + String memorySystemMessage = SYSTEM_MESSAGE_MEMORY.formatted(memoryMessage); + finalPromptMessageList.addFirst(new SystemMessage(memorySystemMessage)); } + return finalPromptMessageList; } @@ -262,8 +274,8 @@ public Flux> streamRunConversation(String assistantId, S Mono saveUserMessageMono = getSaveUserMessageMono(assistantId, threadId, userMessage); Mono assistantEntityMono = getAssistantEntityMono(assistantId); - Mono> pastMessages = getPastMessagesMono(threadId); - Mono initInfosMono = getInitInfosMono(assistantEntityMono, pastMessages); + Mono> pastMessagesMono = getPastMessagesMono(threadId); + Mono initInfosMono = getInitInfosMono(assistantEntityMono, pastMessagesMono); StringBuilder assistantMessageContent = new StringBuilder(); @@ -272,12 +284,18 @@ public Flux> streamRunConversation(String assistantId, S .then(initInfosMono) .flux() .flatMap(initInfos -> { - List memorySearchResults = getMemorySearchResults( - initInfos.assistantDto.id(), initInfos.assistantDto.memory(), userMessage); + List memorySearchResults = new ArrayList<>(); + + if (MemoryType.AI_DECIDES == initInfos.assistantDto.memory()) { + LOGGER.info("Searching memory for assistant '{}'", assistantId); + memorySearchResults = getMemorySearchResults( + initInfos.assistantDto.id(), initInfos.assistantDto.memory(), userMessage); + } return Flux.just( new PreparedInfos(initInfos.assistantDto(), initInfos.pastMessages(), - memorySearchResults)); + memorySearchResults) + ); }) .flatMap(preparedInfos -> { AssistantDto assistantDto = preparedInfos.assistantDto(); @@ -341,6 +359,14 @@ public Flux> streamRunConversation(String assistantId, S private @NotNull ServerSentEvent mapChatResponse(@NotNull ChatResponse chatResponse, StringBuilder assistantMessageContent) { + if (chatResponse.getResult() == null || chatResponse.getResult().getOutput() == null) { + LOGGER.warn("Empty ChatResponse received: {}", chatResponse.getResult()); + return ServerSentEvent.builder() + .event("thread.message.delta") + .data("") + .build(); + } + String content = chatResponse.getResult().getOutput().getContent(); LOGGER.trace("ChatResponse received: {}", chatResponse.getResult()); @@ -407,7 +433,8 @@ private FunctionCallbackWrapper getMemoryFunctionCallback( LOGGER.info("Searching memory for message: {}", message); FilterExpressionBuilder expressionBuilder = new FilterExpressionBuilder(); - Expression assistantExpression = expressionBuilder.eq("assistantId", assistantId).build(); + Expression assistantExpression = expressionBuilder.eq(DBVectorStore.SEARCH_CONVERSATION_ID, + assistantId).build(); List searchResults = memoryService.search( SearchRequest.query(message) @@ -701,6 +728,10 @@ public List retrieveModels(LlmSystem system) { return universalChatService.getModels(system); } + public void regenerateThread(String threadId) { + + } + record InitInfos(AssistantDto assistantDto, List pastMessages) { } diff --git a/backend/src/main/java/com/talkforgeai/backend/assistant/service/UniversalChatService.java b/backend/src/main/java/com/talkforgeai/backend/assistant/service/UniversalChatService.java index 6b6ea4fb..fb17a507 100644 --- a/backend/src/main/java/com/talkforgeai/backend/assistant/service/UniversalChatService.java +++ b/backend/src/main/java/com/talkforgeai/backend/assistant/service/UniversalChatService.java @@ -25,6 +25,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.ai.anthropic.AnthropicChatModel; import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; @@ -52,6 +54,8 @@ @Service public class UniversalChatService { + public static final Logger LOGGER = LoggerFactory.getLogger(UniversalChatService.class); + private final int DEFAULT_CHAT_MEMORY_RESPONSE_SIZE = 5; @Qualifier("openAiRestClient") @@ -149,8 +153,8 @@ ChatResponse call(LlmSystem system, String prompt, ChatOptions options) { .chatResponse(); } - Flux stream(AssistantDto assistantDto, List messages, - String userMessage, ChatOptions options) { + Flux stream(AssistantDto assistantDto, List messages, String userPrompt, + ChatOptions options) { List requestResponseAdvisors = new ArrayList<>(); @@ -163,7 +167,7 @@ Flux stream(AssistantDto assistantDto, List messages, .advisors(requestResponseAdvisors) .options(options) .messages(messages) - .user(userMessage) + .user(userPrompt) .stream() .chatResponse(); } @@ -194,10 +198,11 @@ private MistralAiChatOptions getMistralOptions(AssistantDto assistantDto, return MistralAiChatOptions.builder() .withModel(assistantDto.model()) .withTopP( - Float.valueOf(assistantDto.properties().get(AssistantProperties.MODEL_TOP_P.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_TOP_P.getKey(), + assistantDto.properties())) .withTemperature( - Float.valueOf( - assistantDto.properties().get(AssistantProperties.MODEL_TEMPERATURE.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_TEMPERATURE.getKey(), + assistantDto.properties())) .withFunctionCallbacks(functionCallbacks) .build(); } @@ -208,13 +213,16 @@ private OpenAiChatOptions getOpenAiOptions(AssistantDto assistantDto, return OpenAiChatOptions.builder() .withModel(assistantDto.model()) - .withTopP(Float.valueOf(properties.get(AssistantProperties.MODEL_TOP_P.getKey()))) + .withMaxTokens( + getIntegerValueOrDefault(AssistantProperty.MODEL_MAX_TOKENS.getKey(), properties)) + .withTopP(getFloatValueOrDefault(AssistantProperty.MODEL_TOP_P.getKey(), properties)) .withFrequencyPenalty( - Float.valueOf(properties.get(AssistantProperties.MODEL_FREQUENCY_PENALTY.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_FREQUENCY_PENALTY.getKey(), + properties)) .withPresencePenalty( - Float.valueOf(properties.get(AssistantProperties.MODEL_PRESENCE_PENALTY.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_PRESENCE_PENALTY.getKey(), properties)) .withTemperature( - Float.valueOf(properties.get(AssistantProperties.MODEL_TEMPERATURE.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_TEMPERATURE.getKey(), properties)) .withFunctionCallbacks(functionCallbacks) .build(); } @@ -225,11 +233,12 @@ private ChatOptions getOllamaOptions(AssistantDto assistantDto) { return OllamaOptions.create() .withModel(assistantDto.model()) .withFrequencyPenalty( - Float.valueOf(properties.get(AssistantProperties.MODEL_FREQUENCY_PENALTY.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_FREQUENCY_PENALTY.getKey(), + properties)) .withPresencePenalty( - Float.valueOf(properties.get(AssistantProperties.MODEL_PRESENCE_PENALTY.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_PRESENCE_PENALTY.getKey(), properties)) .withTemperature( - Float.valueOf(properties.get(AssistantProperties.MODEL_TEMPERATURE.getKey()))); + getFloatValueOrDefault(AssistantProperty.MODEL_TEMPERATURE.getKey(), properties)); } private ChatOptions getAnthropicOptions(AssistantDto assistantDto) { @@ -237,9 +246,12 @@ private ChatOptions getAnthropicOptions(AssistantDto assistantDto) { return AnthropicChatOptions.builder() .withModel(assistantDto.model()) + .withMaxTokens( + getIntegerValueOrDefault(AssistantProperty.MODEL_MAX_TOKENS.getKey(), properties)) .withTemperature( - Float.valueOf(properties.get(AssistantProperties.MODEL_TEMPERATURE.getKey()))) - .withTopP(Float.valueOf(properties.get(AssistantProperties.MODEL_TOP_P.getKey()))) + getFloatValueOrDefault(AssistantProperty.MODEL_TEMPERATURE.getKey(), + properties)) + .withTopP(Float.valueOf(properties.get(AssistantProperty.MODEL_TOP_P.getKey()))) .build(); } @@ -278,11 +290,27 @@ public List getModels(LlmSystem llmSystem) { case ANSTHROPIC -> { return Arrays.stream(AnthropicApi.ChatModel.values()).map(AnthropicApi.ChatModel::getValue) .toList(); + + //claude-3-5-sonnet-20240620 } default -> throw new IllegalStateException("Unexpected system: " + llmSystem); } } + private Integer getIntegerValueOrDefault(String key, Map properties) { + String value = properties.get(key); + int defaultValue = Integer.parseInt(AssistantProperty.fromKey(key).getDefaultValue()); + if (value == null) { + return defaultValue; + } + return Integer.parseInt(value); + } + + private Float getFloatValueOrDefault(String key, Map properties) { + String value = properties.get(key); + float defaultValue = Float.parseFloat(AssistantProperty.fromKey(key).getDefaultValue()); + return value == null ? defaultValue : Float.parseFloat(value); + } record OpenAiModelResponse(String object, List data) { diff --git a/backend/src/main/java/com/talkforgeai/backend/memory/service/DBVectorStore.java b/backend/src/main/java/com/talkforgeai/backend/memory/service/DBVectorStore.java index eee217ab..fb299979 100644 --- a/backend/src/main/java/com/talkforgeai/backend/memory/service/DBVectorStore.java +++ b/backend/src/main/java/com/talkforgeai/backend/memory/service/DBVectorStore.java @@ -50,6 +50,7 @@ public class DBVectorStore implements ListableVectoreStore { public static final Logger LOGGER = LoggerFactory.getLogger(DBVectorStore.class); + public static final String SEARCH_CONVERSATION_ID = "conversationId"; public static final String SEARCH_ASSISTANT_ID = "assistantId"; public static final String SEARCH_ASSISTANT_NAME = "assistantName"; public static final String SEARCH_SYSTEM = "system"; @@ -137,7 +138,7 @@ public List similaritySearch(SearchRequest request) { Key left = (Key) request.getFilterExpression().left(); Value right = (Value) request.getFilterExpression().right(); - if (left.key().equals(SEARCH_ASSISTANT_ID)) { + if (left.key().contains(SEARCH_CONVERSATION_ID)) { assistantId = right.value().toString(); } } diff --git a/backend/src/main/java/com/talkforgeai/backend/voice/service/TextToSpeechService.java b/backend/src/main/java/com/talkforgeai/backend/voice/service/TextToSpeechService.java index c1453737..ceb0e784 100644 --- a/backend/src/main/java/com/talkforgeai/backend/voice/service/TextToSpeechService.java +++ b/backend/src/main/java/com/talkforgeai/backend/voice/service/TextToSpeechService.java @@ -17,7 +17,7 @@ package com.talkforgeai.backend.voice.service; import com.talkforgeai.backend.assistant.dto.AssistantDto; -import com.talkforgeai.backend.assistant.service.AssistantProperties; +import com.talkforgeai.backend.assistant.service.AssistantProperty; import com.talkforgeai.backend.assistant.service.AssistantSpringService; import com.talkforgeai.backend.voice.dto.TTSRequest; import com.talkforgeai.service.elevenlabs.ElevenLabsService; @@ -50,8 +50,8 @@ public byte[] streamElevenLabsVoice(TTSRequest TTSRequest) { ElevenLabsRequest request = new ElevenLabsRequest( TTSRequest.text(), - assistantProperties.get(AssistantProperties.ELEVENLABS_VOICEID.getKey()), - assistantProperties.get(AssistantProperties.ELEVENLABS_MODELID.getKey()), + assistantProperties.get(AssistantProperty.ELEVENLABS_VOICEID.getKey()), + assistantProperties.get(AssistantProperty.ELEVENLABS_MODELID.getKey()), new ElevenLabsRequest.VoiceSettings() ); diff --git a/frontend/src/components/chat/ChatContainer.vue b/frontend/src/components/chat/ChatContainer.vue index 2ca9595e..b859bd2a 100644 --- a/frontend/src/components/chat/ChatContainer.vue +++ b/frontend/src/components/chat/ChatContainer.vue @@ -57,21 +57,29 @@ export default { console.log('Submit Result Received'); if (this.chatStore.isAutoSpeak) { - const lastChatMessage = this.$refs.chatMessageRef.slice(-1)[0]; - console.log('Auto speaking last Chat-Message:'); - await lastChatMessage.playAudio(); + try { + const lastChatMessage = this.$refs.chatMessageRef.slice(-1)[0]; + console.log('Auto speaking last Chat-Message:'); + await lastChatMessage.playAudio(); + } catch (error) { + this.appStore.handleError(error); + } } }, populateVoices() { - const voices = speechSynthesis.getVoices(); - if (voices.length > 0) { - console.log('Voices already loaded'); - this.speechApiVoices = voices; - } else { - console.log('Voices not loaded, waiting for onvoiceschanged'); - speechSynthesis.onvoiceschanged = () => { - console.log('Voices loaded.'); - }; + try { + const voices = speechSynthesis.getVoices(); + if (voices.length > 0) { + console.log('Voices already loaded'); + this.speechApiVoices = voices; + } else { + console.log('Voices not loaded, waiting for onvoiceschanged'); + speechSynthesis.onvoiceschanged = () => { + console.log('Voices loaded.'); + }; + } + } catch (error) { + this.appStore.handleError(error); } }, chunkUpdateReceived() { diff --git a/frontend/src/components/chat/ChatControl.vue b/frontend/src/components/chat/ChatControl.vue index a3d15adb..b01531bc 100644 --- a/frontend/src/components/chat/ChatControl.vue +++ b/frontend/src/components/chat/ChatControl.vue @@ -21,11 +21,6 @@ - - Regenerate - - Cancel @@ -80,16 +75,6 @@ export default { this.chatStore.updateStatus('Error: ' + error, 'error'); } }, - async onRegenerateRun() { - console.log('Chat Control - Regenerate Run'); - this.appStore.resetErrorState(); - try { - await this.assistants.regenerateCurrentRun(() => this.$emit('chunkUpdateReceived')); - } catch (error) { - this.appStore.handleError(error); - this.chatStore.updateStatus('Error: ' + error, 'error'); - } - }, }, setup() { const chatStore = useChatStore(); // Call useMyStore() inside the setup function diff --git a/frontend/src/components/chat/ChatMessage.vue b/frontend/src/components/chat/ChatMessage.vue index 7fc179cb..da8a4308 100644 --- a/frontend/src/components/chat/ChatMessage.vue +++ b/frontend/src/components/chat/ChatMessage.vue @@ -78,12 +78,6 @@ export default { isUser() { return this.message.role === Role.USER; }, - // isFunctionCall() { - // return this.message.function_call; - // }, - // isFunctionResponse() { - // return this.message.name && this.message.content; - // }, isSpeakable() { return true; }, @@ -102,7 +96,11 @@ export default { }, methods: { async playAudio() { - await this.$refs.chatMessageAudioPlayerRef.playAudio(); + try { + await this.$refs.chatMessageAudioPlayerRef.playAudio(); + } catch (error) { + this.chatStore.handleError(error); + } }, getContent() { if (this.chatStore.parsedMessages[this.message.id] !== undefined) { diff --git a/frontend/src/components/chat/ChatMessageTextToSpeech.vue b/frontend/src/components/chat/ChatMessageTextToSpeech.vue index 05b0f0a1..39be3498 100644 --- a/frontend/src/components/chat/ChatMessageTextToSpeech.vue +++ b/frontend/src/components/chat/ChatMessageTextToSpeech.vue @@ -23,11 +23,13 @@ import {useAssistants} from '@/composable/use-assistants'; import {useHtmlToText} from '@/composable/use-html-to-text'; import {useTextToSpeech} from '@/composable/use-text-to-speech'; import {ThreadMessage} from '@/store/to/thread'; +import {useAppStore} from '@/store/app-store'; export default defineComponent({ name: 'ChatMessageTextToSpeech', setup() { const chatStore = useChatStore(); // Call useMyStore() inside the setup function + const appStore = useAppStore(); const assistants = useAssistants(); const htmlToText = useHtmlToText(); const textToSpeech = useTextToSpeech(); @@ -60,8 +62,12 @@ export default defineComponent({ stopAudio() { console.log('Audio stopped'); - if (this.ttsType === TTSType.SPEECHAPI) { - window.speechSynthesis.cancel(); + try { + if (this.ttsType === TTSType.SPEECHAPI) { + window.speechSynthesis.cancel(); + } + } catch (error) { + this.appStore.handleError(error); } this.audioState = AudioState.Stopped; @@ -72,13 +78,17 @@ export default defineComponent({ return; } - const plainText = this.htmlToText.removeHtml(this.message.content); - this.audioState = AudioState.Loading; + try { + const plainText = this.htmlToText.removeHtml(this.message.content); + this.audioState = AudioState.Loading; - if (this.ttsType === TTSType.SPEECHAPI) { - await this.speakSpeechApi(plainText); - } else { - await this.speakElevenlabs(plainText); + if (this.ttsType === TTSType.SPEECHAPI) { + await this.speakSpeechApi(plainText); + } else { + await this.speakElevenlabs(plainText); + } + } catch (error) { + this.appStore.handleError(error); } }, async speakElevenlabs(plainText) { @@ -96,16 +106,23 @@ export default defineComponent({ await audio.play(); } catch (error) { console.error('Error loading audio stream.', error); + this.appStore.handleError(error); this.audioState = AudioState.Stopped; } }, async speakSpeechApi(plainText) { console.log(`Speaking using SpeechAPI: '${plainText}'`); - this.audioState = AudioState.Playing; - const assistant = this.assistants.getAssistantById(this.message.assistantId); - await this.textToSpeech.speakSpeechAPI(plainText, assistant); - console.log('Stopped...'); - this.audioState = AudioState.Stopped; + try { + this.audioState = AudioState.Playing; + const assistant = this.assistants.getAssistantById(this.message.assistantId); + await this.textToSpeech.speakSpeechAPI(plainText, assistant); + console.log('Stopped...'); + this.audioState = AudioState.Stopped; + } catch (error) { + console.error('Error speaking using SpeechAPI.', error); + this.appStore.handleError(error); + this.audioState = AudioState.Stopped; + } }, }, }); diff --git a/frontend/src/components/chat/ChatView.vue b/frontend/src/components/chat/ChatView.vue index 06eca304..3c5cc86b 100644 --- a/frontend/src/components/chat/ChatView.vue +++ b/frontend/src/components/chat/ChatView.vue @@ -124,7 +124,11 @@ export default defineComponent({ }, methods: { onNewThread() { - this.assistants.newThread(); + try { + this.assistants.newThread(); + } catch (error) { + this.appStore.handleError(error); + } }, onClickBack() { this.$router.push('/'); @@ -146,9 +150,13 @@ export default defineComponent({ }, }, mounted() { - this.chatStore.clearThreadsList(); - this.chatStore.newThread(); - this.fetchData(); + try { + this.chatStore.clearThreadsList(); + this.chatStore.newThread(); + this.fetchData(); + } catch (error) { + this.appStore.handleError(error); + } }, }); diff --git a/frontend/src/components/common/RadioPlayer.vue b/frontend/src/components/common/RadioPlayer.vue index 5f9e04b4..6d8f174f 100644 --- a/frontend/src/components/common/RadioPlayer.vue +++ b/frontend/src/components/common/RadioPlayer.vue @@ -1,5 +1,5 @@