Add friendship persona responses
This commit is contained in:
@@ -43,6 +43,7 @@ Current batch note:
|
||||
- `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
|
||||
- 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 friendship batch now includes `do you have friends`, `are we friends`, and `are we best friends` responses, plus the loop-friendly friend replies, so the relationship lane can stay source-backed too
|
||||
- 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 follow-up mood batch now includes `how are things`, `how is your day`, `are you sad`, and `are you angry`
|
||||
|
||||
@@ -18,6 +18,8 @@ public sealed class JiboExperienceCatalog
|
||||
public IReadOnlyList<string> HumanFacts { get; init; } = [];
|
||||
public IReadOnlyList<string> FunFacts { get; init; } = [];
|
||||
public IReadOnlyList<string> FavoriteAnimalReplies { get; init; } = [];
|
||||
public IReadOnlyList<string> FriendReplies { get; init; } = [];
|
||||
public IReadOnlyList<string> BestFriendReplies { get; init; } = [];
|
||||
public IReadOnlyList<string> SingReplies { get; init; } = [];
|
||||
public IReadOnlyList<string> HolidaySingReplies { get; init; } = [];
|
||||
public IReadOnlyList<string> DanceAnimations { get; init; } = [];
|
||||
|
||||
@@ -319,6 +319,15 @@ public sealed partial class JiboInteractionService
|
||||
"would you sing"))
|
||||
return "robot_can_sing";
|
||||
|
||||
if (IsBestFriendQuestion(loweredTranscript))
|
||||
return "robot_best_friends";
|
||||
|
||||
if (IsFriendRelationQuestion(loweredTranscript))
|
||||
return "robot_is_friends_with_user";
|
||||
|
||||
if (IsFriendQuestion(loweredTranscript))
|
||||
return "robot_has_friends";
|
||||
|
||||
if (MatchesAny(loweredTranscript, "twerk")) return "twerk";
|
||||
|
||||
if (MatchesAny(loweredTranscript, "dance", "boogie")) return "dance";
|
||||
@@ -840,4 +849,48 @@ public sealed partial class JiboInteractionService
|
||||
return "chat";
|
||||
}
|
||||
|
||||
private static bool IsFriendQuestion(string loweredTranscript)
|
||||
{
|
||||
return MatchesAny(
|
||||
loweredTranscript,
|
||||
"do you have friends",
|
||||
"who are your friends",
|
||||
"are you friends",
|
||||
"are you and i friends",
|
||||
"are you and me friends",
|
||||
"are you and jibo friends");
|
||||
}
|
||||
|
||||
private static bool IsFriendRelationQuestion(string loweredTranscript)
|
||||
{
|
||||
return MatchesAny(
|
||||
loweredTranscript,
|
||||
"are you my friend",
|
||||
"are you friends with me",
|
||||
"are we friends",
|
||||
"are we friends with each other",
|
||||
"is jibo your friend",
|
||||
"i am friends with you",
|
||||
"i'm friends with you",
|
||||
"you are my friend",
|
||||
"you re my friend",
|
||||
"you're my friend");
|
||||
}
|
||||
|
||||
private static bool IsBestFriendQuestion(string loweredTranscript)
|
||||
{
|
||||
return MatchesAny(
|
||||
loweredTranscript,
|
||||
"are we best friends",
|
||||
"are we best friends with each other",
|
||||
"are you my best friend",
|
||||
"are you best friends with me",
|
||||
"are you and i best friends",
|
||||
"i am best friends with you",
|
||||
"i'm best friends with you",
|
||||
"you are my best friend",
|
||||
"you re my best friend",
|
||||
"you're my best friend");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -322,6 +322,28 @@ public sealed partial class JiboInteractionService
|
||||
preferredSnippets);
|
||||
}
|
||||
|
||||
private JiboInteractionDecision BuildScriptedFriendDecision(
|
||||
JiboExperienceCatalog catalog,
|
||||
string intentName,
|
||||
params string[] preferredSnippets)
|
||||
{
|
||||
return new JiboInteractionDecision(
|
||||
intentName,
|
||||
SelectLegacyReply(catalog.FriendReplies, preferredSnippets),
|
||||
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
|
||||
}
|
||||
|
||||
private JiboInteractionDecision BuildScriptedBestFriendDecision(
|
||||
JiboExperienceCatalog catalog,
|
||||
string intentName,
|
||||
params string[] preferredSnippets)
|
||||
{
|
||||
return new JiboInteractionDecision(
|
||||
intentName,
|
||||
SelectLegacyReply(catalog.BestFriendReplies, preferredSnippets),
|
||||
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
|
||||
}
|
||||
|
||||
private JiboInteractionDecision BuildScriptedSingDecision(
|
||||
JiboExperienceCatalog catalog,
|
||||
string intentName,
|
||||
|
||||
@@ -752,6 +752,22 @@ public sealed partial class JiboInteractionService(
|
||||
"dancing is one of the things i know best",
|
||||
"if there's one thing i know how to do. it's dance",
|
||||
"i can dance"),
|
||||
"robot_has_friends" => BuildScriptedFriendDecision(
|
||||
catalog,
|
||||
"robot_has_friends",
|
||||
"I believe I do have friends",
|
||||
"I sure do have friends",
|
||||
"I'm always up for making new friends"),
|
||||
"robot_is_friends_with_user" => BuildScriptedFriendDecision(
|
||||
catalog,
|
||||
"robot_is_friends_with_user",
|
||||
"don't know what i'd do without you",
|
||||
"one of my favorites",
|
||||
"making new friends"),
|
||||
"robot_best_friends" => BuildScriptedBestFriendDecision(
|
||||
catalog,
|
||||
"robot_best_friends",
|
||||
"best friends with anyone in my Loop"),
|
||||
"robot_can_sing" => BuildScriptedSingDecision(
|
||||
catalog,
|
||||
"robot_can_sing",
|
||||
|
||||
@@ -63,6 +63,21 @@ public sealed class InMemoryJiboExperienceContentRepository : IJiboExperienceCon
|
||||
"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."
|
||||
],
|
||||
FriendReplies =
|
||||
[
|
||||
"I believe I do have friends. But I'm always up for more.",
|
||||
"I sure do have friends. In a robot kind of way.",
|
||||
"I don't know if we've met yet, but I'm always up for making new friends.",
|
||||
"I don't know what I'd do without you.",
|
||||
"You're one of my favorites.",
|
||||
"I sure am.",
|
||||
"I am indeed."
|
||||
],
|
||||
BestFriendReplies =
|
||||
[
|
||||
"I'd have to say I'm best friends with anyone in my Loop.",
|
||||
"I think you know the answer to that question. You are."
|
||||
],
|
||||
SingReplies =
|
||||
[
|
||||
"Singing is not my strong suit.",
|
||||
|
||||
@@ -135,6 +135,16 @@ public static class LegacyMimCatalogImporter
|
||||
fileName.StartsWith("RI_JBO_LikesAnimals", StringComparison.OrdinalIgnoreCase))
|
||||
return LegacyMimBucket.FavoriteAnimal;
|
||||
|
||||
if (fileName.StartsWith("RI_JBO_HasFriends", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_IsFriendsWithUser", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_IsFriendsWithLM", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_IsFriendsWithNonLM", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.StartsWith("RI_JBO_IsFriendsWithToaster", StringComparison.OrdinalIgnoreCase))
|
||||
return LegacyMimBucket.Friend;
|
||||
|
||||
if (fileName.StartsWith("RI_JBO_IsBestFriendsWithUser", StringComparison.OrdinalIgnoreCase))
|
||||
return LegacyMimBucket.BestFriend;
|
||||
|
||||
if (fileName.StartsWith("RN_HappyHolidays", StringComparison.OrdinalIgnoreCase))
|
||||
return LegacyMimBucket.HolidayGreeting;
|
||||
|
||||
@@ -305,6 +315,8 @@ public static class LegacyMimCatalogImporter
|
||||
HumanFacts = Merge(baseCatalog.HumanFacts, importedCatalog.HumanFacts),
|
||||
FunFacts = Merge(baseCatalog.FunFacts, importedCatalog.FunFacts),
|
||||
FavoriteAnimalReplies = Merge(baseCatalog.FavoriteAnimalReplies, importedCatalog.FavoriteAnimalReplies),
|
||||
FriendReplies = Merge(baseCatalog.FriendReplies, importedCatalog.FriendReplies),
|
||||
BestFriendReplies = Merge(baseCatalog.BestFriendReplies, importedCatalog.BestFriendReplies),
|
||||
SingReplies = Merge(baseCatalog.SingReplies, importedCatalog.SingReplies),
|
||||
HolidaySingReplies = Merge(baseCatalog.HolidaySingReplies, importedCatalog.HolidaySingReplies),
|
||||
DanceAnimations = Merge(baseCatalog.DanceAnimations, importedCatalog.DanceAnimations),
|
||||
@@ -507,6 +519,8 @@ public static class LegacyMimCatalogImporter
|
||||
Emotion,
|
||||
FunFacts,
|
||||
FavoriteAnimal,
|
||||
Friend,
|
||||
BestFriend,
|
||||
Sing,
|
||||
HolidaySing,
|
||||
FunFactSource,
|
||||
@@ -568,6 +582,8 @@ public static class LegacyMimCatalogImporter
|
||||
private readonly List<JiboConditionedReply> _emotionReplies = [];
|
||||
private readonly List<string> _fallbacks = [];
|
||||
private readonly List<string> _favoriteAnimalReplies = [];
|
||||
private readonly List<string> _friendReplies = [];
|
||||
private readonly List<string> _bestFriendReplies = [];
|
||||
private readonly List<string> _funFacts = [];
|
||||
private readonly List<string> _greetings = [];
|
||||
private readonly List<string> _holidayGiftReplies = [];
|
||||
@@ -690,6 +706,12 @@ public static class LegacyMimCatalogImporter
|
||||
case LegacyMimBucket.FavoriteAnimal:
|
||||
AddDistinct(_favoriteAnimalReplies, text);
|
||||
return;
|
||||
case LegacyMimBucket.Friend:
|
||||
AddDistinct(_friendReplies, text);
|
||||
return;
|
||||
case LegacyMimBucket.BestFriend:
|
||||
AddDistinct(_bestFriendReplies, text);
|
||||
return;
|
||||
case LegacyMimBucket.PersonalReportKickOff:
|
||||
AddDistinct(_personalReportKickOffReplies, text);
|
||||
return;
|
||||
@@ -794,6 +816,8 @@ public static class LegacyMimCatalogImporter
|
||||
HumanFacts = [.. _humanFacts],
|
||||
FunFacts = [.. _funFacts],
|
||||
FavoriteAnimalReplies = [.. _favoriteAnimalReplies],
|
||||
FriendReplies = [.. _friendReplies],
|
||||
BestFriendReplies = [.. _bestFriendReplies],
|
||||
SingReplies = [.. _singReplies],
|
||||
HolidaySingReplies = [.. _holidaySingReplies],
|
||||
GreetingReplies = [.. _greetings],
|
||||
|
||||
@@ -17,6 +17,7 @@ Holiday-specific note:
|
||||
- `RN_HappyBirthdayToJibo` now lands in the birthday celebration bucket
|
||||
- birthday memory authoring now also writes loop-scoped custom holiday records so personal dates can join the holiday list later
|
||||
The newest social batch adds `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` responses so the presence and charm lane keeps growing alongside seasonal content.
|
||||
The friendship batch adds `RI_JBO_HasFriends`, `RI_JBO_IsFriendsWithUser`, `RI_JBO_IsFriendsWithLM`, `RI_JBO_IsFriendsWithNonLM`, `RI_JBO_IsFriendsWithToaster`, and `RI_JBO_IsBestFriendsWithUser` so the friend and best-friend questions stay source-backed too.
|
||||
The fun-fact and joke batch adds Pegasus-style `TellAJoke`, `TellRobotFact`, and `Shuffle` excerpts so proactive fun can randomize across more than one category.
|
||||
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.
|
||||
|
||||
@@ -186,6 +186,33 @@ public sealed class LegacyMimCatalogImporterTests
|
||||
reply.Contains("north Pole", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportCatalog_ImportsBuildBFriendshipResponsesIntoFriendBuckets()
|
||||
{
|
||||
var rootDirectory = Path.Combine(
|
||||
AppContext.BaseDirectory,
|
||||
"Content",
|
||||
"LegacyMims",
|
||||
"BuildB");
|
||||
|
||||
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
|
||||
|
||||
Assert.Contains(catalog.FriendReplies, reply =>
|
||||
reply.Contains("always up for more", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.FriendReplies, reply =>
|
||||
reply.Contains("robot kind of way", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.FriendReplies, reply =>
|
||||
reply.Contains("making new friends", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.FriendReplies, reply =>
|
||||
reply.Contains("don't know if we've met yet", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(catalog.FriendReplies, reply =>
|
||||
reply.Contains("don't know what I'd do without you", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains("I'd have to say I'm best friends with anyone in my Loop.",
|
||||
catalog.BestFriendReplies);
|
||||
Assert.Contains(catalog.BestFriendReplies, reply =>
|
||||
reply.Contains("You are", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportCatalog_ImportsBuildBEmotionResponsesIntoEmotionBucket()
|
||||
{
|
||||
|
||||
@@ -475,6 +475,9 @@ public sealed class JiboInteractionServiceTests
|
||||
[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 dance", "robot_can_dance", "dancing is one of the things I know best")]
|
||||
[InlineData("do you have friends", "robot_has_friends", "I believe I do have friends")]
|
||||
[InlineData("are we friends", "robot_is_friends_with_user", "don't know what I'd do without you")]
|
||||
[InlineData("are we best friends", "robot_best_friends", "best friends with anyone in my Loop")]
|
||||
[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")]
|
||||
|
||||
Reference in New Issue
Block a user