Add KI-Chatbot Feature

This commit is contained in:
Nadine Ganz 2025-09-04 17:30:35 +02:00
parent 7500481bb3
commit 2cce77e5ef
4 changed files with 971 additions and 420 deletions

View File

@ -286,6 +286,8 @@ Tree("26_Castello_Castelli_di_Bellinzona_Intro") {
BTC.Hide("GO.HINTS.SpeechErrorHint")
BTC.Hide("MediaPlayer.VIDEOS.ChatbotBurgenFidle_12")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle02")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle04")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotInterak_FIdle02")
}
BTC.Run("MediaPlayer.VIDEOS.OutroF1")
BTC.Run("MediaPlayer.VIDEOS.OutroFidle2")
@ -715,19 +717,59 @@ Tree("26_Castello_Castelli_di_Bellinzona_Castelli_Bot_offene_Fragen") {
}
}
// TODO: KI-Chatbot implementieren
// Temporaerer Workaround: Info-Message
BTC.Run("MediaPlayer.VIDEOS.CastelliBotoffeneF_F01")
BTC.Hide("GO.HINTS.StandUpHint")
BTC.Run("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle02")
BTC.SetBool("UserStartetBot", false)
Composite(Race) {
Composite(Sequence) {
// U druckt Knopf
BTC.Run("NamedPokeEvent.INTERACTABLES.ChatbotButton")
BTC.SetBool("UserStartetBot")
RunTree("26_Castello_Castelli_di_Bellinzona_Castelli_Bot_Interaktion")
}
Composite(Sequence) {
BTC.Wait(10)
BTC.CompareBool("UserStartetBot", false)
BTC.AbortEventListener("NamedPokeEvent.INTERACTABLES.ChatbotButton")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle02")
BTC.Run("MediaPlayer.VIDEOS.CastelliBotoffeneF_F3")
BTC.Run("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle04")
Composite(Race) {
Composite(Sequence) {
// U druckt Knopf
BTC.Run("NamedPokeEvent.INTERACTABLES.ChatbotButton")
BTC.SetBool("UserStartetBot")
RunTree("26_Castello_Castelli_di_Bellinzona_Castelli_Bot_Interaktion")
}
Composite(Sequence) {
BTC.Wait(10)
BTC.CompareBool("UserStartetBot", false)
BTC.AbortEventListener("NamedPokeEvent.INTERACTABLES.ChatbotButton")
}
}
}
}
}
}
Tree("26_Castello_Castelli_di_Bellinzona_Castelli_Bot_Interaktion") {
// --- Castelli di Bellinzona - Castelli Bot Interaktion ---
Composite(Sequence) {
Composite(Marathon) {
BTC.Set("TextMeshPro.HINTS.SpeechErrorTitle", "text", "Coming soon")
BTC.Set("TextMeshPro.HINTS.SpeechErrorText", "text", "Offenes Gespräch mit Chatbot\n ist noch in Arbeit. Stay tuned!")
BTC.Show("GO.HINTS.SpeechErrorHint")
BTC.Run("Timeline.TIMELINES.TimelineCastelloCh_atbot_End")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle04")
BTC.Hide("MediaPlayer.VIDEOS.CastelliBotoffeneF_FIdle02")
}
BTC.Hide("GO.HINTS.StandUpHint")
BTC.Run("MediaPlayer.VIDEOS.CastelliBotInterak_F1")
BTC.Run("MediaPlayer.VIDEOS.CastelliBotInterak_FIdle02")
BTC.Wait(7)
BTC.SetSpeechRecognitionLanguage("de-DE") // muss geloescht werden am Ende
BTC.StartChatbotConversation()
BTC.ChatbotConversationEnded()
BTC.SpeechOutputEnded()
BTC.Run("Timeline.TIMELINES.TimelineCastelloCh_atbot_End")
}
}

View File

@ -772,6 +772,8 @@ public class BTC : MonoBehaviour {
private bool _onIntentRecognitionSucceededEventTriggered = false;
private bool _onUserSpeechInputStartedEventTriggered = false;
private bool _onIntentRecognitionFailedEventTriggered = false;
private bool _onConversationInitiatedEventTriggered = false;
private bool _onConversationEndedEventTriggered = false;
private bool _onSpeechOutputStartedEventTriggered = false;
private bool _onSpeechOutputEndedEventTriggered = false;
private bool _abortSpeechEventListener = false;
@ -795,6 +797,10 @@ public class BTC : MonoBehaviour {
_speechMng.SpeechSynthesizerService.OnSpeechOutputStartedEvent += SpeechOutputStartedEventHandler;
_speechMng.SpeechSynthesizerService.OnSpeechOutputEndedEvent += SpeechOutputEndedEventHandler;
// Chatbot Conversation Events
_speechMng.ConversationService.OnConversationInitiatedEvent += ChatbotConversationStartetEventHandler;
_speechMng.ConversationService.OnConversationEndedEvent += ChatbotConversationEndedEventHandler;
// Error Event
_speechMng.OnViaggioAIErrorEvent += SpeechErrorEventHandler;
@ -809,6 +815,8 @@ public class BTC : MonoBehaviour {
_speechMng.IntentRecognitionService.OnIntentRecognitionSucceededEvent -= IntentRecognitionSucceededEventHandler;
_speechMng.SpeechRecognitionService.OnUserSpeechInputStartedEvent -= UserSpeechInputStartedEventHandler;
_speechMng.IntentRecognitionService.OnIntentRecognitionFailedEvent -= IntentRecognitionFailedEventHandler;
_speechMng.ConversationService.OnConversationInitiatedEvent -= ChatbotConversationStartetEventHandler;
_speechMng.ConversationService.OnConversationEndedEvent -= ChatbotConversationEndedEventHandler;
_speechMng.SpeechSynthesizerService.OnSpeechOutputStartedEvent -= SpeechOutputStartedEventHandler;
_speechMng.SpeechSynthesizerService.OnSpeechOutputEndedEvent -= SpeechOutputEndedEventHandler;
_speechMng.OnViaggioAIErrorEvent -= SpeechErrorEventHandler;
@ -831,6 +839,16 @@ public class BTC : MonoBehaviour {
_onIntentRecognitionFailedEventTriggered = true;
}
private void ChatbotConversationStartetEventHandler(object sender, string e)
{
_onConversationInitiatedEventTriggered = true;
}
private void ChatbotConversationEndedEventHandler(object sender, string e)
{
_onConversationEndedEventTriggered = true;
}
private void SpeechOutputStartedEventHandler(object sender, bool e)
{
_onSpeechOutputStartedEventTriggered = true;
@ -1008,6 +1026,47 @@ public class BTC : MonoBehaviour {
}
}
[Task]
public void StartChatbotConversation()
{
if (Task.getState == NodeState.FirstRun)
{
string languageCode = "de-DE";
string instructions = "Antworte immer auf Deutsch.";
string context = "Du bist ein allwissendes Wesen, welches ausschliesslich Fragen zu Astronomie beantwortet. Sag <Hallo was möchtest du zu Astronomie wissen?>. Antworte immer so kurz wie möglich. Das Gespräch started jetzt.";
int maxRoundTrips = 5;
float maxSilenceBeforeTimeOut = 10;
string outroText = $"Vielen Dank, das Gespräch ist nun beendet";
_onConversationInitiatedEventTriggered = false;
_speechMng.StartConversation(languageCode, instructions, context, maxRoundTrips, maxSilenceBeforeTimeOut, outroText);
}
if (Task.getState == NodeState.Running)
{
if (_onConversationInitiatedEventTriggered)
{
Task.SetSucceeded();
return;
}
}
}
[Task]
public void ChatbotConversationEnded()
{
if (Task.getState == NodeState.FirstRun)
{
_onConversationEndedEventTriggered = false;
}
if (_onConversationEndedEventTriggered)
{
Task.SetSucceeded();
return;
}
}
[Task]
public void SetSpeechRecognitionLanguage(string languageCode)
{
@ -1039,8 +1098,6 @@ public class BTC : MonoBehaviour {
if (Task.getState == NodeState.FirstRun)
{
_onSpeechOutputStartedEventTriggered = false;
_onSpeechOutputEndedEventTriggered = false;
_speechMng.SynthesizeText(text, SpeechData.languageCode, SpeechData.voiceName);
}
@ -1055,6 +1112,11 @@ public class BTC : MonoBehaviour {
[Task]
public void SpeechOutputEnded()
{
if (Task.getState == NodeState.FirstRun)
{
_onSpeechOutputEndedEventTriggered = false;
}
if (_onSpeechOutputEndedEventTriggered)
{
Debug.Log("SynthesizeText: Speech Output ended.");

File diff suppressed because it is too large Load Diff

View File

@ -311,7 +311,7 @@ public class ConversationService : MonoBehaviour
textToSynthesize += this.outroText;
this.ConversationState = EConversationState.Ended;
this.stopConversation();
this.stopConversation(false);
}
else
{
@ -354,18 +354,21 @@ public class ConversationService : MonoBehaviour
{
this.logIfInDebugMode("Conversation timed out -> Stopping");
this.stopConversation();
this.stopConversation(true);
}
}
private void stopConversation()
private void stopConversation(bool timeOut)
{
this.logIfInDebugMode("Stopping conversation");
this.OnConversationEndedEvent?.Invoke(this, $"Conversation stopped");
vaim.SpeechSynthesizerService.Synthesize(this.outroText, this.languageCode);
if (timeOut)
{
vaim.SpeechSynthesizerService.Synthesize(this.outroText, this.languageCode);
}
this.ConversationState = EConversationState.Ended;
vaim.StopConversation();