From b69abd2b5ab70aa1d72b5e7224f146c8426394eb Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Sat, 7 Dec 2024 03:49:43 +0800 Subject: [PATCH] feat: basic 3d emotion from LLM completions --- packages/stage/src/components/MainStage.vue | 23 ++- packages/stage/src/components/ThreeDScene.vue | 179 +++++++++++------- packages/stage/src/components/VRMModel.vue | 11 ++ .../stage/src/composables/vrm/expression.ts | 169 +++++++++++++++++ packages/stage/src/constants/emotions.ts | 10 + 5 files changed, 321 insertions(+), 71 deletions(-) create mode 100644 packages/stage/src/composables/vrm/expression.ts diff --git a/packages/stage/src/components/MainStage.vue b/packages/stage/src/components/MainStage.vue index 4af4d1e9f..464a138db 100644 --- a/packages/stage/src/components/MainStage.vue +++ b/packages/stage/src/components/MainStage.vue @@ -11,7 +11,7 @@ import { useMarkdown } from '../composables/markdown' import { useQueue } from '../composables/queue' import { useDelayMessageQueue, useEmotionsMessageQueue, useMessageContentQueue } from '../composables/queues' import { llmInferenceEndToken } from '../constants' -import { EMOTION_EmotionMotionName_value, EmotionThinkMotionName } from '../constants/emotions' +import { EMOTION_EmotionMotionName_value, EMOTION_VRMExpressionName_value, EmotionThinkMotionName } from '../constants/emotions' import SystemPromptV2 from '../constants/prompts/system-v2' import { useLLM } from '../stores/llm' import { useSettings } from '../stores/settings' @@ -25,9 +25,13 @@ import ThreeDScene from './ThreeDScene.vue' const nowSpeakingAvatarBorderOpacityMin = 30 const nowSpeakingAvatarBorderOpacityMax = 100 -const { elevenLabsApiKey, openAiApiBaseURL, openAiApiKey } = storeToRefs(useSettings()) +const { + elevenLabsApiKey, + openAiApiBaseURL, + openAiApiKey, + stageView, +} = storeToRefs(useSettings()) const openAIModel = useLocalStorage<{ id: string, name?: string }>('settings/llm/openai/model', { id: 'openai/gpt-3.5-turbo', name: 'OpenAI GPT3.5 Turbo' }) -const stageView = useLocalStorage('settings/stage/view/model-renderer', '2d') const { streamSpeech, @@ -39,6 +43,7 @@ const { process } = useMarkdown() const listening = ref(false) const live2DViewerRef = ref<{ setMotion: (motionName: string) => Promise }>() +const vrmViewerRef = ref<{ setExpression: (expression: string) => void }>() const supportedModels = ref<{ id: string, name?: string }[]>([]) const messageInput = ref('') const messages = ref>([SystemPromptV2 as SystemMessage]) @@ -131,7 +136,16 @@ const messageContentQueue = useMessageContentQueue(ttsQueue) const emotionsQueue = useQueue({ handlers: [ async (ctx) => { - await live2DViewerRef.value!.setMotion(EMOTION_EmotionMotionName_value[ctx.data]) + if (stageView.value === '3d') { + const value = EMOTION_VRMExpressionName_value[ctx.data] + if (!value) + return + + await vrmViewerRef.value!.setExpression(value) + } + else if (stageView.value === '2d') { + await live2DViewerRef.value!.setMotion(EMOTION_EmotionMotionName_value[ctx.data]) + } }, ], }) @@ -289,6 +303,7 @@ onUnmounted(() => { /> void +}>() + +defineExpose({ + setExpression: (expression: string) => { + modelRef.value?.setExpression(expression) + }, +})