From 49898896084e0cf3d7f928af510c6202cd5dd694 Mon Sep 17 00:00:00 2001 From: Jacob Dubin Date: Thu, 21 May 2026 11:53:40 -0500 Subject: [PATCH] Expand friendship parsing guardrails --- OpenJibo/docs/feature-backlog.md | 3 ++ OpenJibo/docs/release-1.0.19-plan.md | 1 + .../JiboInteractionService.IntentRouting.cs | 40 +++++++++++++++++-- .../WebSockets/JiboInteractionServiceTests.cs | 2 + 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/OpenJibo/docs/feature-backlog.md b/OpenJibo/docs/feature-backlog.md index 7e3f80b..cbefc69 100644 --- a/OpenJibo/docs/feature-backlog.md +++ b/OpenJibo/docs/feature-backlog.md @@ -503,6 +503,9 @@ Current release theme: - shorthand favorites (`my favorite sport football`) - weather phrasing (`what's today's weather look like`, `will it be sunny tomorrow`) - updated continuation deferral so complete shorthand favorites finalize instead of waiting for missing continuation +- Progress update (`2026-05-21`): + - expanded friendship parsing for Pegasus-style `do you have friends`, `are we friends`, and `are we best friends` phrasing + - added named-person guardrails so forms like `are you friends with Siri` and `is Dr. Breazeal your best friend` stay on the friendship route instead of falling into generic chat - Exit criteria: - ambiguous phrase handling is improved without regressions in existing `1.0.19` features - phrase imports are documented and traceable to Pegasus parser sources diff --git a/OpenJibo/docs/release-1.0.19-plan.md b/OpenJibo/docs/release-1.0.19-plan.md index da2bc61..a79df18 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 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 parser guardrail pass now expands those friendship routes to named-person forms like `are you friends with Siri` and `is Dr. Breazeal your best friend`, keeping the ambiguity layer closer to Pegasus utterance shapes - 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` diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.IntentRouting.cs b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.IntentRouting.cs index c9590b2..1c9cab8 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.IntentRouting.cs +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.IntentRouting.cs @@ -858,7 +858,8 @@ public sealed partial class JiboInteractionService "are you friends", "are you and i friends", "are you and me friends", - "are you and jibo friends"); + "are you and jibo friends") + || MatchesFriendQuestionPattern(loweredTranscript); } private static bool IsFriendRelationQuestion(string loweredTranscript) @@ -874,7 +875,11 @@ public sealed partial class JiboInteractionService "i'm friends with you", "you are my friend", "you re my friend", - "you're my friend"); + "you're my friend") + || Regex.IsMatch( + loweredTranscript, + @"^\s*(is|are)\s+.+\s+(your friend|my friend)\s*$", + RegexOptions.CultureInvariant); } private static bool IsBestFriendQuestion(string loweredTranscript) @@ -890,7 +895,36 @@ public sealed partial class JiboInteractionService "i'm best friends with you", "you are my best friend", "you re my best friend", - "you're my best friend"); + "you're my best friend") + || MatchesBestFriendQuestionPattern(loweredTranscript); + } + + private static bool MatchesFriendQuestionPattern(string loweredTranscript) + { + return Regex.IsMatch( + loweredTranscript, + @"^\s*are you friends with\s+.+\s*$", + RegexOptions.CultureInvariant) || + Regex.IsMatch( + loweredTranscript, + @"^\s*are you and\s+.+\s+friends\s*$", + RegexOptions.CultureInvariant); + } + + private static bool MatchesBestFriendQuestionPattern(string loweredTranscript) + { + return Regex.IsMatch( + loweredTranscript, + @"^\s*are you best friends with\s+.+\s*$", + RegexOptions.CultureInvariant) || + Regex.IsMatch( + loweredTranscript, + @"^\s*are you and\s+.+\s+best friends\s*$", + RegexOptions.CultureInvariant) || + Regex.IsMatch( + loweredTranscript, + @"^\s*is\s+.+\s+your best friend\s*$", + RegexOptions.CultureInvariant); } } diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs index 68eba5f..c329953 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs @@ -478,6 +478,8 @@ public sealed class JiboInteractionServiceTests [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("are you friends with Siri", "robot_has_friends", "I believe I do have friends")] + [InlineData("is Dr. Breazeal your best friend", "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")]