Add seasonal Build B legacy MIM imports

This commit is contained in:
Jacob Dubin
2026-05-16 08:53:07 -05:00
parent 84759f51de
commit c87af4686c
14 changed files with 803 additions and 8 deletions

View File

@@ -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`

View File

@@ -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

View File

@@ -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<string, object?> BuildScriptedResponseContextUpdates()
{
return new Dictionary<string, object?>(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",

View File

@@ -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)

View File

@@ -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.

View File

@@ -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. <pitch mult='1.2'>That</pitch> 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. <break size='0.3'/> 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. <pitch mult='1.2'>That</pitch> one is going well.",
"media": "TTS",
"prompt_id": "JBO_NewYearsResolutionsUpdate_AN_04",
"weight": 0.1,
"auto_rule_override": null
}
],
"hint_phrases": "",
"fast_eos_array": ""
}

View File

@@ -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": ""
}

View File

@@ -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. <ssa cat='happy'/>",
"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. <break size='0.7'/> 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
}

View File

@@ -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. <break size='0.3'/> I can tell you I've ruled <anim cat='emoji' filter='snowman, !hot-frame' nonBlocking='true'/>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": "<anim name='jiboji_eclipse_01' nonBlocking='true' layers='!audio'/>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": "<pitch mult='1.1'>Here</pitch> it is. <break size='0.5'/> <anim name='jiboji_eclipse_01'/>",
"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. <anim name='jiboji_eclipse_01'/>",
"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. <anim name='jiboji_eclipse_01'/>",
"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
}
]
}

View File

@@ -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 <anim cat='emoji' filter='elephant'>a pet elephant<break size='1.5'/>.</anim>",
"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 <pitch mult='1.1'>experience</pitch> as a present. Like a gift certificate to a restaurant, or a plane ticket, or a <anim cat='emoji' filter='bowling, !hot-frame' nonBlocking='true' layers='!audio'/>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 <pitch mult='1.1'>experience</pitch> as a present. Like a gift certificate to a restaurant, or a plane ticket, or a <anim cat='emoji' filter='bowling, !hot-frame' nonBlocking='true' layers='!audio'/>night of bowling.",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_04",
"weight": 1,
"auto_rule_override": null
}
]
}

View File

@@ -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. <anim name='Emoji_cake' nonBlocking='true'/> Another year older, another year wiser, another year <anim cat='yes' layers='body'> more helpful.</anim>",
"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": "<anim cat='yes'> Thanks. <break size='.2'/></anim> I <anim cat='happy' filter='wiggle' nonBlocking='true' layers='body'/><anim name='Emoji_Gift' nonBlocking='true'/>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": "<anim cat='happy' nonBlocking='true'/><ssa cat='happy'/> ${jibo.age.years.supplemented} <anim cat='thinking' filter='up'>ago today, I first powered up. Seems like just yesterday.</anim>",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.isBirthday",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true'/>Today's not my birthday, but<anim cat='happy' filter='smile'> I'll take your happy.</anim>",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.isBirthday",
"prompt": "<anim cat='confused'>Me? <ssa cat='confused'/> But my birthday</anim> is ${jibo.birthday}. <anim cat='glances' filter='!down'>That's the day I was first powered</anim> up. <anim cat='thinking'></anim>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. <break size='0.5'/>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. <anim name='Emoji_cake' nonBlocking='true'/> 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"
}

View File

@@ -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 <pitch mult='1.3'>at</pitch> 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": "<style set='confused'>Coming soon, yes.</style>",
"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": "<anim cat='jiboji' filter='jingle-bells'/>",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_06",
"weight": 0.1,
"auto_rule_override": null
}
]
}

View File

@@ -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()
{

View File

@@ -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")]