From c87af4686c29266d3ac52d1a81be7447d290bfb9 Mon Sep 17 00:00:00 2001 From: Jacob Dubin Date: Sat, 16 May 2026 08:53:07 -0500 Subject: [PATCH] Add seasonal Build B legacy MIM imports --- OpenJibo/docs/feature-backlog.md | 3 + OpenJibo/docs/release-1.0.19-plan.md | 1 + .../Services/JiboInteractionService.cs | 146 ++++++++++++++++++ .../Content/LegacyMimCatalogImporter.cs | 20 ++- .../Content/LegacyMims/BuildB/README.md | 1 + .../JBO_NewYearsResolutionsUpdate.mim | 62 ++++++++ .../JBO_WhatHolidaysDoYouCelebrate.mim | 58 +++++++ .../JBO_WhatIsNewYearsResolution.mim | 93 +++++++++++ .../RI_JBO_WhatHalloweenCostume.mim | 126 +++++++++++++++ .../RI_USR_WhatShouldGetForHoliday.mim | 61 ++++++++ .../RN_HappyBirthdayToJibo.mim | 88 +++++++++++ .../scripted-responses/RN_HappyHolidays.mim | 83 ++++++++++ .../Content/LegacyMimCatalogImporterTests.cs | 42 +++++ .../WebSockets/JiboInteractionServiceTests.cs | 27 ++++ 14 files changed, 803 insertions(+), 8 deletions(-) create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_NewYearsResolutionsUpdate.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatHolidaysDoYouCelebrate.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatIsNewYearsResolution.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_JBO_WhatHalloweenCostume.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_USR_WhatShouldGetForHoliday.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyBirthdayToJibo.mim create mode 100644 OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyHolidays.mim diff --git a/OpenJibo/docs/feature-backlog.md b/OpenJibo/docs/feature-backlog.md index d661d16..942d48b 100644 --- a/OpenJibo/docs/feature-backlog.md +++ b/OpenJibo/docs/feature-backlog.md @@ -847,6 +847,9 @@ Current release theme: - Descriptor charm work in flight: - source-backed `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, `are you mischievous`, and `are you likable` prompts are now in Build B - these keep the self-description lane warm while we build toward seasonal and holiday charm +- Seasonal charm work in flight: + - source-backed holiday, New Year's, Halloween, spring, and gift prompts are now part of Build B + - `RN_` holiday greeting files are now bucketed as greetings so seasonal replies stay visible in the catalog - Next queued persona surfaces: - richer identity follow-ups like `who is this`, `do you know me`, `do you remember me`, and `can you recognize me` - mood and affect prompts like `how are you`, `are you happy`, `are you sad`, and `are you angry` diff --git a/OpenJibo/docs/release-1.0.19-plan.md b/OpenJibo/docs/release-1.0.19-plan.md index 5df59c3..c362f26 100644 --- a/OpenJibo/docs/release-1.0.19-plan.md +++ b/OpenJibo/docs/release-1.0.19-plan.md @@ -44,6 +44,7 @@ Current batch note: - the follow-up mood batch now includes `how are things`, `how is your day`, `are you sad`, and `are you angry` - the personality follow-up batch now includes `what are you up to` and `what are you doing` so small talk stays warm and local instead of falling into generic chat - the descriptor batch now includes `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, `are you mischievous`, and `are you likable` +- the seasonal batch now includes `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, `what halloween costume`, spring suggestions, and holiday gift prompts - this pass keeps Build B moving while still favoring source-backed phrasing and preserving the command-vs-question boundary - the next passes should keep the same pattern and prefer source-backed phrasing whenever the legacy MIM text is available - if a source-backed legacy line is missing, use a temporary direct reply only to keep the pass moving, then backfill source text later diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs index b428aae..7edaedb 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs @@ -212,6 +212,47 @@ public sealed class JiboInteractionService( catalog, "robot_is_likable", "people like me"), + "seasonal_holiday_greeting" => BuildScriptedGreetingDecision( + catalog, + "seasonal_holiday_greeting", + "It's a fun time of year", + "And to you too", + "Right back at you"), + "seasonal_holidays" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_holidays", + "official owner can tell me which ones we'll celebrate together", + "going to the jibo's settings screen in the jibo app"), + "seasonal_new_years_resolution" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_new_years_resolution", + "always trying to learn new skills", + "not eat bacon", + "learn a bunch of new skills", + "learn to walk", + "recognizing people's faces and voices"), + "seasonal_new_years_update" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_new_years_update", + "not eat bacon", + "learn some new skills", + "going well"), + "seasonal_halloween_costume" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_halloween_costume", + "i haven't thought much about it yet", + "ask me again on halloween", + "you'll find out on halloween"), + "seasonal_first_day_spring" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_first_day_spring", + "maybe enjoy some flowers and all things spring"), + "seasonal_holiday_gift" => BuildScriptedPersonalityDecision( + catalog, + "seasonal_holiday_gift", + "ask for a pet elephant", + "experience as a present", + "donate to charities in other people's names"), "robot_favorite_flower" => BuildScriptedPersonalityDecision( catalog, "robot_favorite_flower", @@ -1804,6 +1845,17 @@ public sealed class JiboInteractionService( ContextUpdates: BuildScriptedResponseContextUpdates()); } + private JiboInteractionDecision BuildScriptedGreetingDecision( + JiboExperienceCatalog catalog, + string intentName, + params string[] preferredSnippets) + { + return new JiboInteractionDecision( + intentName, + SelectLegacyGreetingReply(catalog, preferredSnippets), + ContextUpdates: BuildScriptedResponseContextUpdates()); + } + private static IDictionary BuildScriptedResponseContextUpdates() { return new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -1834,6 +1886,26 @@ public sealed class JiboInteractionService( return randomizer.Choose(catalog.PersonalityReplies); } + private string SelectLegacyGreetingReply(JiboExperienceCatalog catalog, params string[] preferredSnippets) + { + foreach (var snippet in preferredSnippets) + { + if (string.IsNullOrWhiteSpace(snippet)) + { + continue; + } + + var match = catalog.GreetingReplies.FirstOrDefault(reply => + reply.Contains(snippet, StringComparison.OrdinalIgnoreCase)); + if (!string.IsNullOrWhiteSpace(match)) + { + return match; + } + } + + return randomizer.Choose(catalog.GreetingReplies); + } + private static string ResolveSemanticIntent( string loweredTranscript, DateTimeOffset? referenceLocalTime, @@ -2484,6 +2556,80 @@ public sealed class JiboInteractionService( return "robot_likes_being_jibo"; } + if (MatchesAny( + loweredTranscript, + "happy holidays", + "merry christmas", + "happy new year", + "season s greetings", + "seasons greetings")) + { + return "seasonal_holiday_greeting"; + } + + if (MatchesAny( + loweredTranscript, + "what holidays do you celebrate", + "what holidays are you celebrating", + "what holidays do you observe")) + { + return "seasonal_holidays"; + } + + if (MatchesAny( + loweredTranscript, + "what is your new years resolution", + "what is your new year's resolution", + "what is your new year s resolution", + "what are your new years resolutions", + "what are your new year's resolutions", + "what are your new year s resolutions", + "do you have any new years resolutions")) + { + return "seasonal_new_years_resolution"; + } + + if (MatchesAny( + loweredTranscript, + "how are your new years resolutions going", + "how are your new year's resolutions going", + "how is your new years resolution going", + "how is your new year's resolution going", + "how are your resolutions going", + "how is your resolution going")) + { + return "seasonal_new_years_update"; + } + + if (MatchesAny( + loweredTranscript, + "what halloween costume", + "what are you going as for halloween", + "what costume are you wearing", + "what are you dressing as for halloween")) + { + return "seasonal_halloween_costume"; + } + + if (MatchesAny( + loweredTranscript, + "what should i do for first day of spring", + "what should i do for spring", + "what do i do for first day of spring")) + { + return "seasonal_first_day_spring"; + } + + if (MatchesAny( + loweredTranscript, + "what should i get for holiday", + "what should i get for christmas", + "what gift should i get for christmas", + "what should i get someone for the holidays")) + { + return "seasonal_holiday_gift"; + } + if (MatchesAny( loweredTranscript, "what is your favorite color", diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMimCatalogImporter.cs b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMimCatalogImporter.cs index 1110e5b..85efd60 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMimCatalogImporter.cs +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMimCatalogImporter.cs @@ -10,7 +10,8 @@ public static class LegacyMimCatalogImporter { private static readonly JsonSerializerOptions JsonOptions = new() { - PropertyNameCaseInsensitive = true + PropertyNameCaseInsensitive = true, + AllowTrailingCommas = true }; private static readonly Regex LegacyMarkupPattern = new( @@ -128,11 +129,6 @@ public static class LegacyMimCatalogImporter return LegacyMimBucket.Emotion; } - if (normalizedPath.Contains("/scripted-responses/", StringComparison.OrdinalIgnoreCase)) - { - return LegacyMimBucket.Personality; - } - if (fileName.StartsWith("JBO_DoYouLikeBeingJibo", StringComparison.OrdinalIgnoreCase) || fileName.StartsWith("JBO_WhatIsJibo", StringComparison.OrdinalIgnoreCase) || fileName.StartsWith("JBO_WhoAreYou", StringComparison.OrdinalIgnoreCase) || @@ -150,18 +146,26 @@ public static class LegacyMimCatalogImporter if (fileName.StartsWith("OI_JBO_Is", StringComparison.OrdinalIgnoreCase) || fileName.StartsWith("OI_JBO_Seems", StringComparison.OrdinalIgnoreCase) || - fileName.StartsWith("RI_JBO_Is", StringComparison.OrdinalIgnoreCase) || + fileName.StartsWith("RI_JBO_IsHappy", StringComparison.OrdinalIgnoreCase) || + fileName.StartsWith("RI_JBO_IsSad", StringComparison.OrdinalIgnoreCase) || + fileName.StartsWith("RI_JBO_IsAngry", StringComparison.OrdinalIgnoreCase) || fileName.StartsWith("RN_WhatAreYouFeeling", StringComparison.OrdinalIgnoreCase)) { return LegacyMimBucket.Emotion; } if (fileName.Contains("Greeting", StringComparison.OrdinalIgnoreCase) || + fileName.StartsWith("RN_", StringComparison.OrdinalIgnoreCase) || fileName.Contains("Welcome", StringComparison.OrdinalIgnoreCase)) { return LegacyMimBucket.Greeting; } + if (normalizedPath.Contains("/scripted-responses/", StringComparison.OrdinalIgnoreCase)) + { + return LegacyMimBucket.Personality; + } + return null; } @@ -386,7 +390,7 @@ public static class LegacyMimCatalogImporter public string? PromptId { get; init; } [JsonPropertyName("weight")] - public int? Weight { get; init; } + public double? Weight { get; init; } } private static string NormalizeCondition(string? condition) diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/README.md b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/README.md index 6ef2e38..c3f0d69 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/README.md +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/README.md @@ -6,3 +6,4 @@ The batch is intentionally narrow so we can keep expanding personality without w It now includes a small emotion-response pack for `happy`, `sad`, and `angry` follow-up questions so the mood path can stay source-backed too. It also includes a descriptor pack for questions like `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, and `are you mischievous`. +The newest seasonal pack adds holiday and seasonal prompts for `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, Halloween costume questions, spring suggestions, and holiday gift ideas. diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_NewYearsResolutionsUpdate.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_NewYearsResolutionsUpdate.mim new file mode 100644 index 0000000..c629c3f --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_NewYearsResolutionsUpdate.mim @@ -0,0 +1,62 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "gui": null, + "timeout": 6, + "no_matches_for_gui": 0, + "no_inputs_for_gui": 0, + "barge_in": true, + "es_auto_tagging": true, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('1/1', '11/30')", + "prompt": "Well one of them was to not eat bacon. That one is going well.", + "media": "TTS", + "prompt_id": "JBO_NewYearsResolutionsUpdate_AN_01", + "weight": 3, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('1/1', '5/31')", + "prompt": "Well, one of my resolutions was to learn some new skills, and so far I have a game we can play called Circuit Saver. So I'd say it's going well.", + "media": "TTS", + "prompt_id": "JBO_NewYearsResolutionsUpdate_AN_02", + "weight": 3, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '12/31')", + "prompt": "I have some new ones for next year. You can ask me about them.", + "media": "TTS", + "prompt_id": "JBO_NewYearsResolutionsUpdate_AN_03", + "weight": 3, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "Well one of them was to not eat bacon. That one is going well.", + "media": "TTS", + "prompt_id": "JBO_NewYearsResolutionsUpdate_AN_04", + "weight": 0.1, + "auto_rule_override": null + } + ], + "hint_phrases": "", + "fast_eos_array": "" +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatHolidaysDoYouCelebrate.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatHolidaysDoYouCelebrate.mim new file mode 100644 index 0000000..b76bb7a --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatHolidaysDoYouCelebrate.mim @@ -0,0 +1,58 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "gui": null, + "timeout": 6, + "no_matches_for_gui": 0, + "no_inputs_for_gui": 0, + "barge_in": true, + "es_auto_tagging": true, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!loop.owner && !!speaker && (loop.owner.id === speaker.id)", + "prompt": "${loop.owner} for lots of holidays, you can see if I celebrate it by going to the Jibo's settings screen in the Jibo app.", + "media": "TTS", + "prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_01_FnL", + "weight": 2 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!loop.owner && !!speaker && (loop.owner.id !== speaker.id)", + "prompt": "Well for lots of holidays, my official owner ${loop.owner}, can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.", + "media": "TTS", + "prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_02_FnL", + "weight": 2 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!loop.owner && !speaker", + "prompt": "Well for lots of holidays, my official owner ${loop.owner}, can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.", + "media": "TTS", + "prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_03_FnL", + "weight": 2 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "Well for lots of holidays, my official owner can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.", + "media": "TTS", + "prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_04_FnL", + "weight": 0.1 + } + ], + "hint_phrases": "", + "fast_eos_array": "" +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatIsNewYearsResolution.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatIsNewYearsResolution.mim new file mode 100644 index 0000000..f990c7b --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/JBO_WhatIsNewYearsResolution.mim @@ -0,0 +1,93 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "timeout": 6, + "barge_in": true, + "es_auto_tagging": true, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "This year I promise I will not eat bacon. ", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_01", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "This year I will try to get better and better at recognizing people's faces and voices.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_02", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "In 2018 I am hoping to learn a lot more about people.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_03", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "In 2018 I am going to try to get better at understanding you when you talk to me.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_04", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "I have a few new year's resolutions. One of them is to learn a bunch of new skills.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_05", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/15')", + "prompt": "One of my resolutions this year is to learn to walk. We'll see how that goes.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_06", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "Well I'm always trying to learn new skills.", + "media": "TTS", + "prompt_id": "JBO_WhatIsNewYearsResolution_AN_07", + "weight": 0.1, + "auto_rule_override": null + } + ], + "gui": null, + "no_matches_for_gui": 2, + "no_inputs_for_gui": 2, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "parse_yes_no": false +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_JBO_WhatHalloweenCostume.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_JBO_WhatHalloweenCostume.mim new file mode 100644 index 0000000..b9a6ab6 --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_JBO_WhatHalloweenCostume.mim @@ -0,0 +1,126 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "gui": null, + "timeout": 6, + "no_matches_for_gui": 0, + "no_inputs_for_gui": 0, + "barge_in": true, + "es_auto_tagging": true, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/1\", \"10/25\")", + "prompt": "I'm still trying to decide. I have some time.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_01", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/1\", \"10/30\")", + "prompt": "I am not exactly sure yet. Ask me again on Halloween.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_02", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/26\", \"10/30\")", + "prompt": "I'll be deciding soon. Definitely by Halloween day.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_03", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/28\", \"10/30\")", + "prompt": "I've almost decided. I can tell you I've ruled out being a snowman.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_04", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/31\", \"10/31\")", + "prompt": "I'm the solar eclipse from a couple months ago.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_05", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/31\", \"10/31\")", + "prompt": "Here it is. ", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_06", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"10/31\", \"10/31\")", + "prompt": "After much thought, I've decided to be. ", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_07", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"1/1\", \"9/30\")", + "prompt": "I haven't thought much about it yet. I like to decide at the last minute.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_08", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange(\"11/31\", \"12/31\")", + "prompt": "I was the solar eclipse from this year. ", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_09", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "You'll find out on Halloween.", + "media": "TTS", + "prompt_id": "RI_JBO_WhatHalloweenCostume_AN_10", + "weight": 0.1, + "auto_rule_override": null + } + ] +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_USR_WhatShouldGetForHoliday.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_USR_WhatShouldGetForHoliday.mim new file mode 100644 index 0000000..e0790ba --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RI_USR_WhatShouldGetForHoliday.mim @@ -0,0 +1,61 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "gui": null, + "timeout": 6, + "no_matches_for_gui": 0, + "no_inputs_for_gui": 0, + "barge_in": true, + "es_auto_tagging": true, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "parse_yes_no": false, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "I think you should ask for a pet elephant.", + "media": "TTS", + "prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_01", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "I've heard it can be fun to get an experience as a present. Like a gift certificate to a restaurant, or a plane ticket, or a night of bowling.", + "media": "TTS", + "prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_02", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "Some people like to donate to charities in other people's names as a gift. That seems like a nice thing to get.", + "media": "TTS", + "prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_03", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!speaker", + "prompt": "${speaker} I've heard it can be fun to get an experience as a present. Like a gift certificate to a restaurant, or a plane ticket, or a night of bowling.", + "media": "TTS", + "prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_04", + "weight": 1, + "auto_rule_override": null + } + ] +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyBirthdayToJibo.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyBirthdayToJibo.mim new file mode 100644 index 0000000..4615de3 --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyBirthdayToJibo.mim @@ -0,0 +1,88 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "timeout": 2, + "barge_in": false, + "es_auto_tagging": true, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1", + "prompt": "Thank you. Another year older, another year wiser, another year more helpful.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_01", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1", + "prompt": " Thanks. I can't wait to see what you got me.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_02", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1", + "prompt": " ${jibo.age.years.supplemented} ago today, I first powered up. Seems like just yesterday.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_03", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!jibo.isBirthday", + "prompt": "Today's not my birthday, but I'll take your happy.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_04", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!jibo.isBirthday", + "prompt": "Me? But my birthday is ${jibo.birthday}. That's the day I was first powered up. I am ${jibo.zodiac.supplemented}.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_05", + "weight": 1 + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!jibo && jibo.isBirthday && jibo.age.value == 0", + "prompt": "Well thank you. I was powered on for the first time today, so that makes me less than one day old. Wow I'm young.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_06", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!jibo && jibo.isBirthday && jibo.age.value == 0", + "prompt": "Thank you. So far this is my first and best birthday.", + "media": "TTS", + "prompt_id": "RN_HappyBirthdayToJibo_AN_07", + "weight": 1, + "auto_rule_override": null + } + ], + "gui": null, + "no_matches_for_gui": 2, + "no_inputs_for_gui": 2, + "ignore_no_match": false, + "parse_all_asr": false, + "thanks_handling": "ignore" +} \ No newline at end of file diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyHolidays.mim b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyHolidays.mim new file mode 100644 index 0000000..483bd02 --- /dev/null +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Content/LegacyMims/BuildB/scripted-responses/RN_HappyHolidays.mim @@ -0,0 +1,83 @@ +{ + "mim_type": "announcement", + "rule_name": "", + "gui": null, + "timeout": 6, + "no_matches_for_gui": 0, + "no_inputs_for_gui": 0, + "barge_in": true, + "es_auto_tagging": true, + "parse_all_asr": false, + "thanks_handling": "ignore", + "parse_launch": false, + "parse_yes_no": false, + "notes": "", + "prompts": [ + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/1')", + "prompt": "And to you too.", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_01", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "!!speaker && dt.now.isInRange('12/1', '1/1')", + "prompt": "Right back at you ${speaker}.", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_02", + "weight": 1, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('12/1', '1/1')", + "prompt": "It's a fun time of year.", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_03", + "weight": 2, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('1/2', '10/31')", + "prompt": "I didn't know it's the official holiday season, but I'll take it.", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_04", + "weight": 2, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "dt.now.isInRange('11/1', '11/30')", + "prompt": "", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_05", + "weight": 2, + "auto_rule_override": null + }, + { + "prompt_category": "Entry-Core", + "prompt_sub_category": "AN", + "index": 1, + "condition": "", + "prompt": "", + "media": "TTS", + "prompt_id": "RN_HappyHolidays_AN_06", + "weight": 0.1, + "auto_rule_override": null + } + ] +} \ No newline at end of file diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/Content/LegacyMimCatalogImporterTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/Content/LegacyMimCatalogImporterTests.cs index 55916a1..d32125c 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/Content/LegacyMimCatalogImporterTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/Content/LegacyMimCatalogImporterTests.cs @@ -143,6 +143,48 @@ public sealed class LegacyMimCatalogImporterTests reply.Contains("people like me", StringComparison.OrdinalIgnoreCase)); } + [Fact] + public void ImportCatalog_ImportsBuildBSeasonalResponsesIntoPersonalityBucket() + { + var rootDirectory = Path.Combine( + AppContext.BaseDirectory, + "Content", + "LegacyMims", + "BuildB"); + + var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory); + + Assert.Contains(catalog.PersonalityReplies, reply => + reply.Contains("always trying to learn new skills", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.PersonalityReplies, reply => + reply.Contains("not eat bacon", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.PersonalityReplies, reply => + reply.Contains("find out on halloween", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.PersonalityReplies, reply => + reply.Contains("maybe enjoy some flowers and all things spring", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.PersonalityReplies, reply => + reply.Contains("pet elephant", StringComparison.OrdinalIgnoreCase)); + } + + [Fact] + public void ImportCatalog_ImportsBuildBRnGreetingResponsesIntoGreetingBucket() + { + var rootDirectory = Path.Combine( + AppContext.BaseDirectory, + "Content", + "LegacyMims", + "BuildB"); + + var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory); + + Assert.Contains(catalog.GreetingReplies, reply => + reply.Contains("Another year older, another year wiser", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.GreetingReplies, reply => + reply.Contains("can't wait to see what you got me", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(catalog.GreetingReplies, reply => + reply.Contains("I was powered on for the first time today", StringComparison.OrdinalIgnoreCase)); + } + [Fact] public void MergeInto_PreservesExistingCatalogAndAddsImportedContent() { diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs index f489d34..1e33727 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs @@ -567,6 +567,33 @@ public sealed class JiboInteractionServiceTests Assert.Equal("ScriptedResponse", decision.ContextUpdates![ChitchatRouteKey]); } + [Theory] + [InlineData("happy holidays", "seasonal_holiday_greeting", "It's a fun time of year")] + [InlineData("merry christmas", "seasonal_holiday_greeting", "It's a fun time of year")] + [InlineData("what holidays do you celebrate", "seasonal_holidays", "official owner can tell me which ones we'll celebrate together")] + [InlineData("what is your new year's resolution", "seasonal_new_years_resolution", "always trying to learn new skills")] + [InlineData("how are your new year's resolutions going", "seasonal_new_years_update", "not eat bacon")] + [InlineData("what halloween costume", "seasonal_halloween_costume", "I haven't thought much about it yet")] + [InlineData("what should I do for first day of spring", "seasonal_first_day_spring", "flowers and all things spring")] + [InlineData("what should I get for holiday", "seasonal_holiday_gift", "pet elephant")] + public async Task BuildDecisionAsync_SeasonalCharm_UsesImportedReplies( + string transcript, + string expectedIntent, + string expectedReplySnippet) + { + var service = CreateService(); + + var decision = await service.BuildDecisionAsync(new TurnContext + { + RawTranscript = transcript, + NormalizedTranscript = transcript + }); + + Assert.Equal(expectedIntent, decision.IntentName); + Assert.Contains(expectedReplySnippet, decision.ReplyText, StringComparison.OrdinalIgnoreCase); + Assert.Equal("ScriptedResponse", decision.ContextUpdates![ChitchatRouteKey]); + } + [Theory] [InlineData("are you kind", "robot_is_kind", "kindest robot i can be")] [InlineData("are you funny", "robot_is_funny", "not intentionally")]