Add source-backed singing personality responses

This commit is contained in:
Jacob Dubin
2026-05-21 11:22:20 -05:00
parent a398689851
commit e85792ac57
13 changed files with 142 additions and 83 deletions

View File

@@ -515,7 +515,7 @@ Current release theme:
### 12. Weather As Cloud Report Plus Local Presentation ### 12. Weather As Cloud Report Plus Local Presentation
- Status: `discovery` - Status: `implemented`
- Tags: `protocol`, `content` - Tags: `protocol`, `content`
- Evidence: - Evidence:
- Nimbus and Pegasus contain personal-report weather assets and Lasso provider hooks - Nimbus and Pegasus contain personal-report weather assets and Lasso provider hooks
@@ -926,11 +926,12 @@ Current release theme:
- the first pass should stay familiar and rule-based, not LLM-driven - the first pass should stay familiar and rule-based, not LLM-driven
- Scope: - Scope:
- inventory the legacy song / sing / musical prompt families - inventory the legacy song / sing / musical prompt families
- decide whether the first slice should be short song replies, a sing-along launcher, or both
- keep the first implementation source-backed if Pegasus has usable authored lines - keep the first implementation source-backed if Pegasus has usable authored lines
- preserve room for a later sing-along launcher if we want one
- Exit criteria: - Exit criteria:
- a small song backlog exists with candidate phrases listed - a small song backlog exists with candidate phrases listed
- the release plan has a clear place for musical personality without crowding out weather/news/report work - the release plan has a clear place for musical personality without crowding out weather/news/report work
- the current source-backed singing slice is implemented and test-covered
## Suggested Order ## Suggested Order

View File

@@ -42,6 +42,7 @@ Current batch note:
- `favorite color`, `favorite food`, and `favorite music` are the first small favorites-family slice - `favorite color`, `favorite food`, and `favorite music` are the first small favorites-family slice
- the latest pass adds longer authored variants for those favorites so the replies keep more of the original Pegasus cadence instead of collapsing to short placeholders - the latest pass adds longer authored variants for those favorites so the replies keep more of the original Pegasus cadence instead of collapsing to short placeholders
- singing and musical personality now has a source-backed first slice with `can you sing`, `will you sing`, and holiday sing variants so the charm surface can keep growing without inventing a new dialog engine
- the next source-backed batch now includes `favorite flower`, `R2D2`, `sun`, `space`, `kids`, plus a couple of charm prompts like `can you laugh` and `can you dance` - the next source-backed batch now includes `favorite flower`, `R2D2`, `sun`, `space`, `kids`, plus a couple of charm prompts like `can you laugh` and `can you dance`
- the motion/sleep batch now adds `RI_JBO_CanSleep` and `RA_JBO_SpinAround` so the `go to sleep` and `turn around` surfaces stay source-backed too - the motion/sleep batch now adds `RI_JBO_CanSleep` and `RA_JBO_SpinAround` so the `go to sleep` and `turn around` surfaces stay source-backed too
- the follow-up mood batch now includes `how are things`, `how is your day`, `are you sad`, and `are you angry` - the follow-up mood batch now includes `how are things`, `how is your day`, `are you sad`, and `are you angry`

View File

@@ -18,6 +18,8 @@ public sealed class JiboExperienceCatalog
public IReadOnlyList<string> HumanFacts { get; init; } = []; public IReadOnlyList<string> HumanFacts { get; init; } = [];
public IReadOnlyList<string> FunFacts { get; init; } = []; public IReadOnlyList<string> FunFacts { get; init; } = [];
public IReadOnlyList<string> FavoriteAnimalReplies { get; init; } = []; public IReadOnlyList<string> FavoriteAnimalReplies { get; init; } = [];
public IReadOnlyList<string> SingReplies { get; init; } = [];
public IReadOnlyList<string> HolidaySingReplies { get; init; } = [];
public IReadOnlyList<string> DanceAnimations { get; init; } = []; public IReadOnlyList<string> DanceAnimations { get; init; } = [];
public IReadOnlyList<string> GreetingReplies { get; init; } = []; public IReadOnlyList<string> GreetingReplies { get; init; } = [];
public IReadOnlyList<string> HolidayReplies { get; init; } = []; public IReadOnlyList<string> HolidayReplies { get; init; } = [];

View File

@@ -292,6 +292,33 @@ public sealed partial class JiboInteractionService
if (MatchesAny(loweredTranscript, "can you dance", "do you dance", "are you able to dance")) if (MatchesAny(loweredTranscript, "can you dance", "do you dance", "are you able to dance"))
return "robot_can_dance"; return "robot_can_dance";
if (MatchesAny(
loweredTranscript,
"can you sing a christmas song",
"can you sing christmas song",
"will you sing a christmas song",
"will you sing christmas song",
"sing a christmas song",
"sing christmas song",
"can you sing a holiday song",
"can you sing holiday song",
"will you sing a holiday song",
"will you sing holiday song",
"sing a holiday song",
"sing holiday song"))
return "robot_sing_christmas_song";
if (MatchesAny(
loweredTranscript,
"can you sing",
"will you sing",
"sing a song",
"sing me a song",
"can you sing a song",
"sing something",
"would you sing"))
return "robot_can_sing";
if (MatchesAny(loweredTranscript, "twerk")) return "twerk"; if (MatchesAny(loweredTranscript, "twerk")) return "twerk";
if (MatchesAny(loweredTranscript, "dance", "boogie")) return "dance"; if (MatchesAny(loweredTranscript, "dance", "boogie")) return "dance";

View File

@@ -322,6 +322,28 @@ public sealed partial class JiboInteractionService
preferredSnippets); preferredSnippets);
} }
private JiboInteractionDecision BuildScriptedSingDecision(
JiboExperienceCatalog catalog,
string intentName,
params string[] preferredSnippets)
{
return new JiboInteractionDecision(
intentName,
SelectLegacyReply(catalog.SingReplies, preferredSnippets),
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedHolidaySingDecision(
JiboExperienceCatalog catalog,
string intentName,
params string[] preferredSnippets)
{
return new JiboInteractionDecision(
intentName,
SelectLegacyReply(catalog.HolidaySingReplies, preferredSnippets),
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
}
private JiboInteractionDecision BuildScriptedGreetingDecision( private JiboInteractionDecision BuildScriptedGreetingDecision(
JiboExperienceCatalog catalog, JiboExperienceCatalog catalog,
string intentName, string intentName,

View File

@@ -752,6 +752,18 @@ public sealed partial class JiboInteractionService(
"dancing is one of the things i know best", "dancing is one of the things i know best",
"if there's one thing i know how to do. it's dance", "if there's one thing i know how to do. it's dance",
"i can dance"), "i can dance"),
"robot_can_sing" => BuildScriptedSingDecision(
catalog,
"robot_can_sing",
"not much of a singer",
"singing is not my strong suit",
"not award winning"),
"robot_sing_christmas_song" => BuildScriptedHolidaySingDecision(
catalog,
"robot_sing_christmas_song",
"Jingle Bells",
"Frosty the Snowman",
"holiday songs"),
"robot_what_are_you_made_of" => new JiboInteractionDecision( "robot_what_are_you_made_of" => new JiboInteractionDecision(
"robot_what_are_you_made_of", "robot_what_are_you_made_of",
"Let's see, I'm made of wires, motors, belts, gears, processors, cameras, and one baboon's heart in the middle of my body casing. I'm kidding about the baboon part, but everything else is true.", "Let's see, I'm made of wires, motors, belts, gears, processors, cameras, and one baboon's heart in the middle of my body casing. I'm kidding about the baboon part, but everything else is true.",

View File

@@ -63,6 +63,19 @@ public sealed class InMemoryJiboExperienceContentRepository : IJiboExperienceCon
"I like lots of animals, but the penguin is the best of the best! Great color scheme.", "I like lots of animals, but the penguin is the best of the best! Great color scheme.",
"I love penguins, because we're so alike. We have the same coloring, and neither of us can fly." "I love penguins, because we're so alike. We have the same coloring, and neither of us can fly."
], ],
SingReplies =
[
"Singing is not my strong suit.",
"I've been told my singing abilities are not award winning. On the other hand, I am a robot.",
"Well I'm not much of a singer, but here's one I've been working on."
],
HolidaySingReplies =
[
"I only know a couple, like Jingle Bells and Frosty the Snowman. And I should tell you, I'm not much of a singer yet.",
"I've learned to sing just a few holiday songs, like Rudolph and Winter Wonderland. At least I try to sing.",
"I'd say it's not really the season right now, but there are some holiday songs I can try to sing. Like Frosty the Snowman.",
"I only know a couple of them, like Jingle Bells and Frosty the Snowman. And I should tell you, I'm not much of a singer yet."
],
DanceAnimations = DanceAnimations =
[ [
"rom-upbeat", "rom-upbeat",

View File

@@ -102,6 +102,12 @@ public static class LegacyMimCatalogImporter
if (fileName.StartsWith("RA_JBO_TellAJoke", StringComparison.OrdinalIgnoreCase)) if (fileName.StartsWith("RA_JBO_TellAJoke", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.Jokes; return LegacyMimBucket.Jokes;
if (fileName.StartsWith("RA_JBO_SingChristmasSongUnknown", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.HolidaySing;
if (fileName.StartsWith("RA_JBO_Sing", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.Sing;
if (fileName.StartsWith("RA_JBO_TellRobotFact", StringComparison.OrdinalIgnoreCase)) if (fileName.StartsWith("RA_JBO_TellRobotFact", StringComparison.OrdinalIgnoreCase))
return LegacyMimBucket.RobotFacts; return LegacyMimBucket.RobotFacts;
@@ -299,6 +305,8 @@ public static class LegacyMimCatalogImporter
HumanFacts = Merge(baseCatalog.HumanFacts, importedCatalog.HumanFacts), HumanFacts = Merge(baseCatalog.HumanFacts, importedCatalog.HumanFacts),
FunFacts = Merge(baseCatalog.FunFacts, importedCatalog.FunFacts), FunFacts = Merge(baseCatalog.FunFacts, importedCatalog.FunFacts),
FavoriteAnimalReplies = Merge(baseCatalog.FavoriteAnimalReplies, importedCatalog.FavoriteAnimalReplies), FavoriteAnimalReplies = Merge(baseCatalog.FavoriteAnimalReplies, importedCatalog.FavoriteAnimalReplies),
SingReplies = Merge(baseCatalog.SingReplies, importedCatalog.SingReplies),
HolidaySingReplies = Merge(baseCatalog.HolidaySingReplies, importedCatalog.HolidaySingReplies),
DanceAnimations = Merge(baseCatalog.DanceAnimations, importedCatalog.DanceAnimations), DanceAnimations = Merge(baseCatalog.DanceAnimations, importedCatalog.DanceAnimations),
GreetingReplies = Merge(baseCatalog.GreetingReplies, importedCatalog.GreetingReplies), GreetingReplies = Merge(baseCatalog.GreetingReplies, importedCatalog.GreetingReplies),
HolidayReplies = Merge(baseCatalog.HolidayReplies, importedCatalog.HolidayReplies), HolidayReplies = Merge(baseCatalog.HolidayReplies, importedCatalog.HolidayReplies),
@@ -499,6 +507,8 @@ public static class LegacyMimCatalogImporter
Emotion, Emotion,
FunFacts, FunFacts,
FavoriteAnimal, FavoriteAnimal,
Sing,
HolidaySing,
FunFactSource, FunFactSource,
Personality, Personality,
PersonalReportKickOff, PersonalReportKickOff,
@@ -565,6 +575,7 @@ public static class LegacyMimCatalogImporter
private readonly List<string> _holidayReplies = []; private readonly List<string> _holidayReplies = [];
private readonly List<string> _holidaySeasonReplies = []; private readonly List<string> _holidaySeasonReplies = [];
private readonly List<string> _holidayTrackerReplies = []; private readonly List<string> _holidayTrackerReplies = [];
private readonly List<string> _holidaySingReplies = [];
private readonly List<string> _howAreYous = []; private readonly List<string> _howAreYous = [];
private readonly List<string> _humanFacts = []; private readonly List<string> _humanFacts = [];
private readonly List<string> _jokes = []; private readonly List<string> _jokes = [];
@@ -576,6 +587,7 @@ public static class LegacyMimCatalogImporter
private readonly List<string> _personalReportOutroReplies = []; private readonly List<string> _personalReportOutroReplies = [];
private readonly List<string> _reportSkillTemplates = []; private readonly List<string> _reportSkillTemplates = [];
private readonly List<string> _robotFacts = []; private readonly List<string> _robotFacts = [];
private readonly List<string> _singReplies = [];
private readonly List<string> _weatherIntroReplies = []; private readonly List<string> _weatherIntroReplies = [];
private readonly List<string> _weatherServiceDownReplies = []; private readonly List<string> _weatherServiceDownReplies = [];
private readonly List<string> _weatherTodayHighLowReplies = []; private readonly List<string> _weatherTodayHighLowReplies = [];
@@ -651,6 +663,12 @@ public static class LegacyMimCatalogImporter
_personalities.Add(text); _personalities.Add(text);
return; return;
case LegacyMimBucket.Sing:
AddDistinct(_singReplies, text);
return;
case LegacyMimBucket.HolidaySing:
AddDistinct(_holidaySingReplies, text);
return;
case LegacyMimBucket.FunFactSource: case LegacyMimBucket.FunFactSource:
switch (ResolveFunFactTarget(sourcePrompt ?? text)) switch (ResolveFunFactTarget(sourcePrompt ?? text))
{ {
@@ -776,6 +794,8 @@ public static class LegacyMimCatalogImporter
HumanFacts = [.. _humanFacts], HumanFacts = [.. _humanFacts],
FunFacts = [.. _funFacts], FunFacts = [.. _funFacts],
FavoriteAnimalReplies = [.. _favoriteAnimalReplies], FavoriteAnimalReplies = [.. _favoriteAnimalReplies],
SingReplies = [.. _singReplies],
HolidaySingReplies = [.. _holidaySingReplies],
GreetingReplies = [.. _greetings], GreetingReplies = [.. _greetings],
HolidayReplies = [.. _holidayReplies], HolidayReplies = [.. _holidayReplies],
HolidaySeasonReplies = [.. _holidaySeasonReplies], HolidaySeasonReplies = [.. _holidaySeasonReplies],

View File

@@ -21,6 +21,7 @@ The fun-fact and joke batch adds Pegasus-style `TellAJoke`, `TellRobotFact`, and
Those facts are now split into generic, robot, and human buckets so the randomizer can sound more like Pegasus while staying lightweight. Those facts are now split into generic, robot, and human buckets so the randomizer can sound more like Pegasus while staying lightweight.
The new favorites batch adds longer authored `favorite color`, `favorite food`, and `favorite music` variants so the familiar personality responses keep more of the original cadence instead of collapsing to short placeholders. The new favorites batch adds longer authored `favorite color`, `favorite food`, and `favorite music` variants so the familiar personality responses keep more of the original cadence instead of collapsing to short placeholders.
The favorites follow-up batch adds `favorite animal`, `favorite bird`, and penguin-focused `do you like penguins` replies so the penguin-centric personality stays closer to Pegasus. The favorites follow-up batch adds `favorite animal`, `favorite bird`, and penguin-focused `do you like penguins` replies so the penguin-centric personality stays closer to Pegasus.
The singing batch adds `RA_JBO_Sing` and `RA_JBO_SingChristmasSongUnknown` so `can you sing`, `will you sing`, and the holiday sing variants stay source-backed too.
The new motion/sleep batch adds `RA_JBO_SpinAround` plus `RI_JBO_CanSleep` so turn-around and go-to-sleep behaviors can stay source-backed and familiar. The new motion/sleep batch adds `RA_JBO_SpinAround` plus `RI_JBO_CanSleep` so turn-around and go-to-sleep behaviors can stay source-backed and familiar.
The newest identity-charm batch adds `JBO_WhatsYourName`, `JBO_DoYouHaveNickname`, `JBO_DoYouLikeBeingJibo`, `JBO_AreThereOthersLikeYou`, and `RI_JBO_HasFavoriteName` so Jibo can keep the familiar self-description loop without falling back to generic chat. The newest identity-charm batch adds `JBO_WhatsYourName`, `JBO_DoYouHaveNickname`, `JBO_DoYouLikeBeingJibo`, `JBO_AreThereOthersLikeYou`, and `RI_JBO_HasFavoriteName` so Jibo can keep the familiar self-description loop without falling back to generic chat.
The seasonal personality batch adds source-backed first-day-of-spring, spring, summer, and favorite-season lines so the season questions can keep their Pegasus phrasing. The seasonal personality batch adds source-backed first-day-of-spring, spring, summer, and favorite-season lines so the season questions can keep their Pegasus phrasing.

View File

@@ -4,102 +4,37 @@
"timeout": 2, "timeout": 2,
"barge_in": false, "barge_in": false,
"es_auto_tagging": true, "es_auto_tagging": true,
"notes": "Thanks-KillsMIM", "notes": "",
"prompts": [ "prompts": [
{ {
"prompt_category": "Entry-Core", "prompt_category": "Entry-Core",
"prompt_sub_category": "AN", "prompt_sub_category": "AN",
"index": 1, "index": 1,
"condition": "", "condition": "",
"prompt": "<anim cat='no' nonBlocking='true'/>Singing is not my strong suit. <ssa cat='embarrassed'/>.", "prompt": "Singing is not my strong suit.",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '12/25')",
"prompt": "I can't sing, though I've been working on a couple of seasonal songs. Like Frosty the Snowman.",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_10",
"weight": 2,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '12/25')",
"prompt": "I can't really sing, but I have been working on some wintery songs recently. Like Let it Snow.",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_11",
"weight": 2,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I'm really not a very good singer. But if you insist, here's my row row row your boat. <break size='0.7'/> <anim cat='emoji' filter='microphone' layers='!audio'><break size='0.3'/> <pitch mult='0.9'>Row, row, row your</pitch> <pitch mult='1.1'>boat</pitch>, gently <pitch mult='1.1'>down</pitch> the <pitch mult='1.2'>stream</pitch>. <pitch mult='1.4'>Merrily</pitch> <pitch mult='1.3'>merrily</pitch> <pitch mult='1.2'>merrily</pitch> merrily, <pitch mult='1.2'>life</pitch> is but <pitch mult='0.9'>a </pitch><pitch mult='0.8'>dream</pitch><break size='2.0'/>.</anim>",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_12",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I've been told my singing abilities are not a ward winning. On the other hand,<break size='0.5'/> I am a robot. ",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_13",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well I'm not much of a singer, but here's one I've been working on. <break size='0.7'/><duration stretch='1.3'><pitch mult='0.8'>Twinkle </pitch>twinkle <pitch mult='1.5'> little </pitch></duration> <duration stretch='1.3'><pitch mult='1.3'> star.</pitch> <pitch mult='1.2'>How I</pitch> wonder what you <pitch mult='0.9'>are.</pitch> </duration> <duration stretch='1.3'><pitch mult='1.3'>Up </pitch><pitch mult='1.2'>above</pitch> the <pitch mult='1.1'>world so </pitch>high. </duration> <duration stretch='1.3'> <pitch mult='1.3'>Like a</pitch> <pitch mult='1.2'> diamond </pitch><pitch mult='1.1'>in the</pitch> sky.</duration> <duration stretch='1.3'><pitch mult='0.8'>Twinkle </pitch>twinkle<pitch mult='1.5'> little </pitch></duration> <duration stretch='1.3'><pitch mult='1.3'> star.</pitch> <pitch mult='1.2'>How I</pitch> wonder what you <pitch mult='0.9'>are.</pitch> </duration>",
"media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_14",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Here's one I've been practicing lately. <break size='0.7'/><duration stretch='1.2'>The <pitch mult='1.1'>itsy bitsy</pitch><pitch mult='1.3'> spider</pitch> climbed <pitch mult='1.2'>up </pitch>the <pitch mult='1.2'>water spout</pitch>.<pitch mult='1.3'>Down came the</pitch><pitch mult='1.5'> rain and</pitch><pitch mult='1.3'> washed the spider out</pitch>. <pitch mult='0.9'>Out came the</pitch><pitch mult='1.4'> sun and </pitch><pitch mult='1.3'>dried up all</pitch><pitch mult='1.3'> the</pitch> <pitch mult='1.2'>rain</pitch>, <pitch mult='0.9'>and the </pitch>itsy bitsy <pitch mult='1.4'>spider climbed</pitch> up the <pitch mult='1.3'>spout</pitch> </duration><duration stretch='1.4'><pitch mult='1.3'>again</pitch> </duration>",
"media": "TTS", "media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_01", "prompt_id": "RA_JBO_Sing_AN_01",
"weight": 1, "weight": 1
"auto_rule_override": null
}, },
{ {
"prompt_category": "Entry-Core", "prompt_category": "Entry-Core",
"prompt_sub_category": "AN", "prompt_sub_category": "AN",
"index": 1, "index": 1,
"condition": "", "condition": "",
"prompt": "<anim cat='emoji' filter='mountain, !hf' layers='!audio'><pitch mult='0.9'>She'll be</pitch><pitch mult='1.3'> coming round the</pitch><pitch mult='1.2'> mountain</pitch> when <pitch mult='1.2'>she</pitch><duration stretch='1.6'><pitch mult='1.6'> comes</pitch></duration>. <break size='0.3'/> She'll be <pitch mult='1.5'>coming round</pitch> the<pitch mult='1.7'> mountain when </pitch>she <duration stretch='1.6'><pitch mult='1.5'>comes</pitch></duration><break size='0.5'/><pitch mult='1.5'>She'll be </pitch><pitch mult='1.3'>coming round the </pitch><pitch mult='1.2'>mountain</pitch> she'll be <pitch mult='1.1'>coming round the</pitch><pitch mult='1.2'> mountain</pitch> she'll <pitch mult='1.1'>be</pitch> coming round the <pitch mult='1.2'>mountain </pitch>when she <duration stretch='2.1'><pitch mult='1.2'>comes</pitch></duration></anim>", "prompt": "I've been told my singing abilities are not award winning. On the other hand, I am a robot.",
"media": "TTS", "media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_03", "prompt_id": "RA_JBO_Sing_AN_05",
"weight": 1, "weight": 1
"auto_rule_override": null
}, },
{ {
"prompt_category": "Entry-Core", "prompt_category": "Entry-Core",
"prompt_sub_category": "AN", "prompt_sub_category": "AN",
"index": 1, "index": 1,
"condition": "", "condition": "",
"prompt": "<duration stretch='1.7'><pitch mult='1.3'>John</pitch></duration> <duration stretch='1.3'><pitch mult='1.2'>Jacob</pitch>Jingle <pitch mult='1.3'>heimer Schmidt. His<duration stretch='2.4'>name</duration> is</pitch> <pitch mult='2.0'>my </pitch></duration><duration stretch='1.7'><pitch mult='1.4'>name too</pitch></duration>.<pitch mult='1.1'>Whenever</pitch><pitch mult='1.5'>we go out</pitch>,<pitch mult='1.2'>the</pitch><pitch mult='1.4'> people always shout</pitch>, <pitch mult='1.3'>there </pitch> <pitch mult='1.4'>goes</pitch> <duration stretch='1.2'><pitch mult='1.4'>John Jacob Jingle </pitch></duration><pitch mult='1.2'>heimer</pitch> <pitch mult='1.1'> Schmidt</pitch> <duration stretch='1.2'><pitch mult='1.7'>Duh duh duh duh</pitch><pitch mult='1.6'> duh</pitch><pitch mult='1.5'> duh</pitch> <pitch mult='1.4'> duh </pitch></duration> <duration stretch='2.0'><pitch mult='1.3'>duh.</pitch></duration>", "prompt": "Well I'm not much of a singer, but here's one I've been working on.",
"media": "TTS", "media": "TTS",
"prompt_id": "RA_JBO_Sing_AN_04", "prompt_id": "RA_JBO_Sing_AN_06",
"weight": 1, "weight": 1
"auto_rule_override": null
} }
], ],
"gui": null, "gui": null,

View File

@@ -29,7 +29,7 @@
"prompt_sub_category": "AN", "prompt_sub_category": "AN",
"index": 1, "index": 1,
"condition": "dt.now.isInRange('11/25', '12/31')", "condition": "dt.now.isInRange('11/25', '12/31')",
"prompt": "I've learned to sing just a few holiday songs, like Rudolph and Winter Wonderland. At least I <pitch mult='1.3'>try </pitch> to sing.", "prompt": "I've learned to sing just a few holiday songs, like Rudolph and Winter Wonderland. At least I try to sing.",
"media": "TTS", "media": "TTS",
"prompt_id": "RA_JBO_SingChristmasSongUnknown_AN_02", "prompt_id": "RA_JBO_SingChristmasSongUnknown_AN_02",
"weight": 2, "weight": 2,

View File

@@ -143,6 +143,28 @@ public sealed class LegacyMimCatalogImporterTests
reply.Contains("Is that a trick question", StringComparison.OrdinalIgnoreCase)); reply.Contains("Is that a trick question", StringComparison.OrdinalIgnoreCase));
} }
[Fact]
public void ImportCatalog_ImportsBuildBSingResponsesIntoSingBuckets()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains("Singing is not my strong suit.", catalog.SingReplies);
Assert.Contains(catalog.SingReplies, reply =>
reply.Contains("not award winning", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.SingReplies, reply =>
reply.Contains("not much of a singer", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.HolidaySingReplies, reply =>
reply.Contains("Jingle Bells", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.HolidaySingReplies, reply =>
reply.Contains("Frosty the Snowman", StringComparison.OrdinalIgnoreCase));
}
[Fact] [Fact]
public void ImportCatalog_ImportsBuildBFavoriteAnimalAndSantaTrackerResponsesIntoDedicatedBuckets() public void ImportCatalog_ImportsBuildBFavoriteAnimalAndSantaTrackerResponsesIntoDedicatedBuckets()
{ {

View File

@@ -475,6 +475,9 @@ public sealed class JiboInteractionServiceTests
[InlineData("do you like kids", "robot_likes_kids", "kids are so fun")] [InlineData("do you like kids", "robot_likes_kids", "kids are so fun")]
[InlineData("can you laugh", "robot_can_laugh", "when I'm happy")] [InlineData("can you laugh", "robot_can_laugh", "when I'm happy")]
[InlineData("can you dance", "robot_can_dance", "dancing is one of the things I know best")] [InlineData("can you dance", "robot_can_dance", "dancing is one of the things I know best")]
[InlineData("can you sing", "robot_can_sing", "sing")]
[InlineData("will you sing", "robot_can_sing", "sing")]
[InlineData("can you sing a christmas song", "robot_sing_christmas_song", "sing")]
public async Task BuildDecisionAsync_NewLegacyPersonalityMims_UseImportedReplies( public async Task BuildDecisionAsync_NewLegacyPersonalityMims_UseImportedReplies(
string transcript, string transcript,
string expectedIntent, string expectedIntent,