Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

### Quick-router tool-call accuracy

- **News**: strip a leading `please` in `asks_for_news` so polite forms
(`please read the news`, `please tell me the news`) route to a fresh
`web_search` for top headlines — trailing `please` / time qualifiers were
already handled (#908).
- **Scene / routine**: strip a leading `please` before the exact-match set and
the `activate`/`start`/`run` prefix loop, so polite forms
(`please activate the movie scene`, `please goodnight`, `please I am home`)
Expand Down
40 changes: 40 additions & 0 deletions crates/genie-core/src/tools/quick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3147,6 +3147,11 @@ fn weather_request(text: &str) -> Option<(String, bool)> {
/// swallows the play_media "morning news" audio-briefing forms handled later in
/// dispatch.
fn asks_for_news(text: &str) -> bool {
// A leading "please" is politeness, not part of the request. The set below
// is exact, so "please read the news" / "please tell me the news" fell
// through to the LLM even though the trailing-"please" forms already
// route. Mirror asks_current_time / scene-routine / shopping-list.
let text = text.strip_prefix("please ").unwrap_or(text);
let text = text.trim_end_matches(" please").trim_end();
let text = strip_trailing_time_qualifier(text);
matches!(
Expand Down Expand Up @@ -7469,6 +7474,41 @@ mod tests {
}
}

#[test]
fn news_request_accepts_a_leading_please() {
// Trailing "please" is already stripped in asks_for_news. A leading
// "please" was not: the set is exact, so polite forms fell through to
// the LLM even though their non-"please" / trailing-"please" versions
// already route.
for utterance in [
"Please read the news",
"Please what's the news?",
"Please tell me the news",
"Please give me the news",
"Please show me the news",
"Please the latest news",
"Please catch me up on the news",
// Leading politeness composes with trailing tails.
"Please read the news please",
"Please what's the news today?",
] {
let call = route(utterance).unwrap_or_else(|| panic!("no route for {utterance:?}"));
assert_eq!(call.name, "web_search", "{utterance:?}");
assert_eq!(
call.arguments["query"], "top news headlines",
"{utterance:?}"
);
assert_eq!(call.arguments["fresh"], true, "{utterance:?}");
}

// Negatives: stripping "please" must not invent a news route for an
// unrelated polite request, and must not steal play_media briefing forms.
assert!(route("please help me").is_none());
let call = route("please put on the morning news").unwrap();
assert_eq!(call.name, "play_media");
assert_eq!(call.arguments["query"], "morning news");
}

#[test]
fn routes_lookup_to_web_search() {
let call = route("look up ESP32 C6 Thread support").unwrap();
Expand Down
Loading