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`
|
||||
- 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
|
||||
- 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
|
||||
- recognition follow-ups like `do you know me`
|
||||
- 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
|
||||
- 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
|
||||
|
||||
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`
|
||||
- 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
|
||||
- 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`
|
||||
- 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
|
||||
|
||||
@@ -2432,7 +2432,11 @@ public sealed class JiboInteractionService(
|
||||
cancellationToken);
|
||||
|
||||
if (snapshot?.Headlines.Count > 0)
|
||||
return BuildProviderNewsDecision(snapshot, preferredCategories, requestedHeadlineCount);
|
||||
return BuildProviderNewsDecision(
|
||||
snapshot,
|
||||
catalog,
|
||||
preferredCategories,
|
||||
requestedHeadlineCount);
|
||||
|
||||
var providerStatus = ResolveNewsProviderStatus(snapshot);
|
||||
var providerMessage = snapshot?.ProviderMessage;
|
||||
@@ -2522,6 +2526,7 @@ public sealed class JiboInteractionService(
|
||||
|
||||
private static JiboInteractionDecision BuildProviderNewsDecision(
|
||||
NewsBriefingSnapshot snapshot,
|
||||
JiboExperienceCatalog catalog,
|
||||
IReadOnlyList<string> preferredCategories,
|
||||
int requestedHeadlineCount)
|
||||
{
|
||||
@@ -2543,7 +2548,8 @@ public sealed class JiboInteractionService(
|
||||
|
||||
var leadIn = BuildNewsLeadIn(snapshot.SourceName, preferredCategories);
|
||||
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(
|
||||
spokenBriefing,
|
||||
snapshot.SourceName,
|
||||
|
||||
@@ -281,12 +281,24 @@ internal static class PersonalReportOrchestrator
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@@ -717,6 +729,25 @@ internal static class PersonalReportOrchestrator
|
||||
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)
|
||||
{
|
||||
var selected = templates
|
||||
|
||||
@@ -1900,8 +1900,7 @@ public sealed class JiboInteractionServiceTests
|
||||
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.",
|
||||
decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("commute", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("And that's it.", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("news", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.True(StripMarkup(decision.ReplyText).Length < 500,
|
||||
$"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.Contains("Your calendar says get personal report from jibo, at 6:00 p.m.", decision.ReplyText,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -4878,7 +4878,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Contains("weather", stripped, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("calendar", 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]
|
||||
|
||||
Reference in New Issue
Block a user