Polish news and personal report phrasing
This commit is contained in:
@@ -847,7 +847,7 @@ Current release theme:
|
|||||||
- identity charm prompts like `what's your name`, `do you have a nickname`, `do you like being Jibo`, `are there others like you`, and `what is your favorite name`
|
- identity charm prompts like `what's your name`, `do you have a nickname`, `do you like being Jibo`, `are there others like you`, and `what is your favorite name`
|
||||||
- attraction and preference prompts like `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, and `do you like kids`
|
- attraction and preference prompts like `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, and `do you like kids`
|
||||||
- longer authored variants for the same prompt family when Pegasus shows richer phrasing
|
- longer authored variants for the same prompt family when Pegasus shows richer phrasing
|
||||||
- charm/capability prompts like `can you laugh` and `can you dance`
|
- charm/capability prompts like `can you laugh`, `can you dance`, `can you sing`, and `will you sing`
|
||||||
- mood / affect questions
|
- mood / affect questions
|
||||||
- recognition follow-ups like `do you know me`
|
- recognition follow-ups like `do you know me`
|
||||||
- follow-up state prompts that should stay warm and locally grounded
|
- follow-up state prompts that should stay warm and locally grounded
|
||||||
@@ -917,6 +917,21 @@ Current release theme:
|
|||||||
- decide whether the composition layer should sit above the prompt catalog or beside it as a dedicated response post-processor
|
- decide whether the composition layer should sit above the prompt catalog or beside it as a dedicated response post-processor
|
||||||
- keep this separate from the authored-variant backlog item so we do not blur prompt richness with runtime composition
|
- keep this separate from the authored-variant backlog item so we do not blur prompt richness with runtime composition
|
||||||
|
|
||||||
|
### 33. Singing And Musical Personality
|
||||||
|
|
||||||
|
- Status: `discovery`
|
||||||
|
- Tags: `content`, `docs`, `protocol`
|
||||||
|
- Why now:
|
||||||
|
- Jibo’s charm surface includes musical and sing-along behavior, and it fits naturally after the current personality and holiday batches
|
||||||
|
- the first pass should stay familiar and rule-based, not LLM-driven
|
||||||
|
- Scope:
|
||||||
|
- 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
|
||||||
|
- Exit criteria:
|
||||||
|
- 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
|
||||||
|
|
||||||
## Suggested Order
|
## Suggested Order
|
||||||
|
|
||||||
Before closing `1.0.18`:
|
Before closing `1.0.18`:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Keep a running checklist of the legacy persona questions and identity surfaces w
|
|||||||
- favorite-style prompts: `what is your favorite color`, `what is your favorite food`, `what is your favorite music`
|
- favorite-style prompts: `what is your favorite color`, `what is your favorite food`, `what is your favorite music`
|
||||||
- attraction and preference prompts: `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, `do you like kids`
|
- attraction and preference prompts: `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, `do you like kids`
|
||||||
- longer authored variants for the same prompt family when Pegasus shows richer phrasing, especially multi-clause and follow-up-heavy responses
|
- longer authored variants for the same prompt family when Pegasus shows richer phrasing, especially multi-clause and follow-up-heavy responses
|
||||||
- capability and charm prompts: `can you laugh`, `can you dance`
|
- capability and charm prompts: `can you laugh`, `can you dance`, `can you sing`, `will you sing`
|
||||||
- affect and mood: `how are you`, `are you happy`, `are you sad`, `are you angry`
|
- affect and mood: `how are you`, `are you happy`, `are you sad`, `are you angry`
|
||||||
- memory and identity recall: `who am i`, `what is my name`, `when is my birthday`, `what is my favorite music`
|
- memory and identity recall: `who am i`, `what is my name`, `when is my birthday`, `what is my favorite music`
|
||||||
- greeting and presence charm: `good morning`, `welcome back`, `who is this`, person-aware greeting follow-ups
|
- greeting and presence charm: `good morning`, `welcome back`, `who is this`, person-aware greeting follow-ups
|
||||||
|
|||||||
@@ -2432,7 +2432,11 @@ public sealed class JiboInteractionService(
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
if (snapshot?.Headlines.Count > 0)
|
if (snapshot?.Headlines.Count > 0)
|
||||||
return BuildProviderNewsDecision(snapshot, preferredCategories, requestedHeadlineCount);
|
return BuildProviderNewsDecision(
|
||||||
|
snapshot,
|
||||||
|
catalog,
|
||||||
|
preferredCategories,
|
||||||
|
requestedHeadlineCount);
|
||||||
|
|
||||||
var providerStatus = ResolveNewsProviderStatus(snapshot);
|
var providerStatus = ResolveNewsProviderStatus(snapshot);
|
||||||
var providerMessage = snapshot?.ProviderMessage;
|
var providerMessage = snapshot?.ProviderMessage;
|
||||||
@@ -2522,6 +2526,7 @@ public sealed class JiboInteractionService(
|
|||||||
|
|
||||||
private static JiboInteractionDecision BuildProviderNewsDecision(
|
private static JiboInteractionDecision BuildProviderNewsDecision(
|
||||||
NewsBriefingSnapshot snapshot,
|
NewsBriefingSnapshot snapshot,
|
||||||
|
JiboExperienceCatalog catalog,
|
||||||
IReadOnlyList<string> preferredCategories,
|
IReadOnlyList<string> preferredCategories,
|
||||||
int requestedHeadlineCount)
|
int requestedHeadlineCount)
|
||||||
{
|
{
|
||||||
@@ -2543,7 +2548,8 @@ public sealed class JiboInteractionService(
|
|||||||
|
|
||||||
var leadIn = BuildNewsLeadIn(snapshot.SourceName, preferredCategories);
|
var leadIn = BuildNewsLeadIn(snapshot.SourceName, preferredCategories);
|
||||||
var joinedHeadlines = string.Join(" ", headlines.Select(static headline => $"{headline.Title}."));
|
var joinedHeadlines = string.Join(" ", headlines.Select(static headline => $"{headline.Title}."));
|
||||||
var spokenBriefing = $"{leadIn} {joinedHeadlines}".Trim();
|
var outroTemplate = ChooseShortestTemplate(catalog.NewsOutroReplies) ?? "And that's the news.";
|
||||||
|
var spokenBriefing = $"{leadIn} {joinedHeadlines} {outroTemplate}".Trim();
|
||||||
return BuildNewsDecision(
|
return BuildNewsDecision(
|
||||||
spokenBriefing,
|
spokenBriefing,
|
||||||
snapshot.SourceName,
|
snapshot.SourceName,
|
||||||
|
|||||||
@@ -281,12 +281,24 @@ internal static class PersonalReportOrchestrator
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (toggles.CalendarEnabled)
|
if (toggles.CalendarEnabled)
|
||||||
reportSections.Add((await buildCalendarDecisionAsync(turn, cancellationToken)).ReplyText);
|
{
|
||||||
|
var calendarReply = (await buildCalendarDecisionAsync(turn, cancellationToken)).ReplyText;
|
||||||
|
if (!string.IsNullOrWhiteSpace(calendarReply))
|
||||||
|
{
|
||||||
|
reportSections.Add(calendarReply);
|
||||||
|
|
||||||
|
var calendarOutro = ChooseShortestTemplate(catalog.CalendarOutroReplies);
|
||||||
|
if (!string.IsNullOrWhiteSpace(calendarOutro))
|
||||||
|
reportSections.Add(RenderPersonalReportTemplate(calendarOutro!, userName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (toggles.CommuteEnabled)
|
if (toggles.CommuteEnabled)
|
||||||
{
|
{
|
||||||
var commuteReply = (await buildCommuteDecisionAsync(turn, cancellationToken)).ReplyText;
|
var commuteReply = (await buildCommuteDecisionAsync(turn, cancellationToken)).ReplyText;
|
||||||
reportSections.Add(ChooseFirstSentence(commuteReply));
|
var commuteSnippet = ChooseFirstSentence(commuteReply);
|
||||||
|
if (!string.IsNullOrWhiteSpace(commuteSnippet))
|
||||||
|
reportSections.Add(commuteSnippet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toggles.NewsEnabled)
|
if (toggles.NewsEnabled)
|
||||||
@@ -717,6 +729,25 @@ internal static class PersonalReportOrchestrator
|
|||||||
return string.IsNullOrWhiteSpace(firstSentence) ? value.Trim() : firstSentence;
|
return string.IsNullOrWhiteSpace(firstSentence) ? value.Trim() : firstSentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ChooseFirstTwoSentences(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
|
||||||
|
|
||||||
|
var segments = value
|
||||||
|
.Split(['.', '!', '?'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||||
|
.Take(2)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (segments.Length == 0) return string.Empty;
|
||||||
|
|
||||||
|
var joined = string.Join(". ", segments);
|
||||||
|
return value.TrimEnd().EndsWith(".", StringComparison.Ordinal) ||
|
||||||
|
value.TrimEnd().EndsWith("!", StringComparison.Ordinal) ||
|
||||||
|
value.TrimEnd().EndsWith("?", StringComparison.Ordinal)
|
||||||
|
? $"{joined}."
|
||||||
|
: joined;
|
||||||
|
}
|
||||||
|
|
||||||
private static string? ChooseShortestTemplate(IEnumerable<string> templates)
|
private static string? ChooseShortestTemplate(IEnumerable<string> templates)
|
||||||
{
|
{
|
||||||
var selected = templates
|
var selected = templates
|
||||||
|
|||||||
@@ -1900,8 +1900,7 @@ public sealed class JiboInteractionServiceTests
|
|||||||
Assert.Contains(
|
Assert.Contains(
|
||||||
"For your weather. In Boston, U.S., it's light rain and 61 degrees Fahrenheit. Today's high is 65, and the low is 54.",
|
"For your weather. In Boston, U.S., it's light rain and 61 degrees Fahrenheit. Today's high is 65, and the low is 54.",
|
||||||
decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("And that's it.", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("commute", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
|
||||||
Assert.Contains("news", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("news", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.True(StripMarkup(decision.ReplyText).Length < 500,
|
Assert.True(StripMarkup(decision.ReplyText).Length < 500,
|
||||||
$"Personal report speech was still too long: {StripMarkup(decision.ReplyText).Length} chars.");
|
$"Personal report speech was still too long: {StripMarkup(decision.ReplyText).Length} chars.");
|
||||||
@@ -1951,6 +1950,7 @@ public sealed class JiboInteractionServiceTests
|
|||||||
Assert.Equal("personal_report_delivered", decision.IntentName);
|
Assert.Equal("personal_report_delivered", decision.IntentName);
|
||||||
Assert.Contains("Your calendar says get personal report from jibo, at 6:00 p.m.", decision.ReplyText,
|
Assert.Contains("Your calendar says get personal report from jibo, at 6:00 p.m.", decision.ReplyText,
|
||||||
StringComparison.OrdinalIgnoreCase);
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -4878,7 +4878,7 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
Assert.Contains("weather", stripped, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("weather", stripped, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("calendar", stripped, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("calendar", stripped, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("news", stripped, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("news", stripped, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.True(stripped.Length < 500, $"Personal report speech was still too long: {stripped.Length} chars.");
|
Assert.True(stripped.Length < 600, $"Personal report speech was still too long: {stripped.Length} chars.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
Reference in New Issue
Block a user