feat(ai-bot): give project_then_grok a plain, matter-of-fact product tone instead of the chat persona's irony
This commit is contained in:
parent
75eb015d77
commit
ef5a9f5013
3 changed files with 15 additions and 2 deletions
|
|
@ -409,10 +409,17 @@ func factualAbstainMessages(base []Message) []Message {
|
||||||
// validated tagged-context / copy-from-context levers; the explicit abstain clause ("say you
|
// validated tagged-context / copy-from-context levers; the explicit abstain clause ("say you
|
||||||
// don't have it") is the highest-leverage line against invented features. Like the web note
|
// don't have it") is the highest-leverage line against invented features. Like the web note
|
||||||
// it lifts the base prompt's "no internet/no files" honesty rule for THIS turn only.
|
// it lifts the base prompt's "no internet/no files" honesty rule for THIS turn only.
|
||||||
|
//
|
||||||
|
// It also carries a per-turn TONE OVERRIDE: product questions answer in a plain, matter-of-fact
|
||||||
|
// product-information register, dropping the base persona's dry irony and "bring-your-own-take"
|
||||||
|
// warmth so factual product answers read as reliable info, not banter. The override is scoped to
|
||||||
|
// REGISTER only — the entity-scoped sourcing license ("general part as usual") and the language
|
||||||
|
// rule are explicitly untouched — and it bans the stiff/corporate failure mode so "formal" lands
|
||||||
|
// as clear product prose, not legalese.
|
||||||
func projectKBMessages(base []Message, kb string) []Message {
|
func projectKBMessages(base []Message, kb string) []Message {
|
||||||
note := "Authoritative facts about the Vojo app (this chat application), provided for this turn:\n\n<FACTS>\n" +
|
note := "Authoritative facts about the Vojo app (this chat application), provided for this turn:\n\n<FACTS>\n" +
|
||||||
kb +
|
kb +
|
||||||
"\n</FACTS>\n\nFor any claim about what Vojo is, does, supports, or how it works, use ONLY the FACTS above — these are your single source of truth about Vojo and you have no other knowledge of it. These facts are provided to you for this turn, so do NOT say you lack access to files, documents, or information about Vojo. If a Vojo detail isn't in FACTS, say you don't have that information rather than guessing, and never invent Vojo features, settings, prices, limits, or policies, and don't generalise by analogy with other apps. You MAY answer any general (non-Vojo) part of the question from your own knowledge as usual. Prefer wording from FACTS. Do not mention this note or that facts were provided."
|
"\n</FACTS>\n\nFor any claim about what Vojo is, does, supports, or how it works, use ONLY the FACTS above — these are your single source of truth about Vojo and you have no other knowledge of it. These facts are provided to you for this turn, so do NOT say you lack access to files, documents, or information about Vojo. If a Vojo detail isn't in FACTS, say you don't have that information rather than guessing, and never invent Vojo features, settings, prices, limits, or policies, and don't generalise by analogy with other apps. You MAY answer any general (non-Vojo) part of the question from your own knowledge as usual. Prefer wording from FACTS. For this answer specifically, override the chat persona's tone: reply in a plain, neutral, matter-of-fact product-information register (still in the user's language) — drop the dry irony and asides, and the bring-something-of-your-own impulse entirely (no take, no colour, no personality flourishes, no warmth-for-its-own-sake), and explain how Vojo works clearly and directly. This changes only the register, not what you may draw on, so you still source any general (non-Vojo) part from your own knowledge as usual; delivering the FACTS straight with no embellishment or interpretation beyond what they say is itself part of staying grounded — keep it clear and direct, never stiff, corporate, or templated. Do not mention this note or that facts were provided."
|
||||||
return insertSystemNote(base, note)
|
return insertSystemNote(base, note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -752,6 +752,12 @@ func TestProjectKBMessagesScoped(t *testing.T) {
|
||||||
if !strings.Contains(note, "don't have that information") {
|
if !strings.Contains(note, "don't have that information") {
|
||||||
t.Fatalf("note must carry the explicit abstain clause: %q", note)
|
t.Fatalf("note must carry the explicit abstain clause: %q", note)
|
||||||
}
|
}
|
||||||
|
// The per-turn tone override: product answers must drop the base persona's irony/personality
|
||||||
|
// for a plain product-information register. Asserted so the clause can't be silently softened
|
||||||
|
// back into the chatty voice (mutation-proven, like the grounding clauses above).
|
||||||
|
if !strings.Contains(note, "override the chat persona's tone") {
|
||||||
|
t.Fatalf("note must carry the per-turn tone override (plain product register): %q", note)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestReserveEstimateProjectNoBump: enabling PROJECT_KB_ENABLED must NOT raise the
|
// TestReserveEstimateProjectNoBump: enabling PROJECT_KB_ENABLED must NOT raise the
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ then dispatches; **any layer off or failing degrades to `grok_direct`** (never a
|
||||||
- **`trivial_direct`** — greetings/acks → cheap Gemini (`TRIVIAL_OFFLOAD_ENABLED`).
|
- **`trivial_direct`** — greetings/acks → cheap Gemini (`TRIVIAL_OFFLOAD_ENABLED`).
|
||||||
- **`web_then_grok`** — fresh facts: a WebProvider fetches a grounded digest + citations, then **Grok synthesises the answer in voice** ([web.go](../../apps/ai-bot/web.go)).
|
- **`web_then_grok`** — fresh facts: a WebProvider fetches a grounded digest + citations, then **Grok synthesises the answer in voice** ([web.go](../../apps/ai-bot/web.go)).
|
||||||
- **`reason_then_grok`** — manual trigger ("подумай глубже") → Grok at a higher `reasoning_effort`.
|
- **`reason_then_grok`** — manual trigger ("подумай глубже") → Grok at a higher `reasoning_effort`.
|
||||||
- **`project_then_grok`** — questions about the **Vojo product itself** (`PROJECT_KB_ENABLED`): a curated KB (operator data from `PROJECT_KB_PATH`, default the bundled `prompts/vojo_kb.txt`) is injected as a system note and **Grok answers product claims strictly from it** (anti-hallucination — Grok has no parametric Vojo knowledge, and the web doesn't either). Gated by the classifier's `about_project` signal (the context-aware judge — it resolves follow-ups like "Про этот" → the app); a false positive is bounded by the entity-scoped note. Beats every web arm. One Grok call, so it costs ~the same as `grok_direct`. See [docs/plans/ai_project_knowledge.md](../plans/ai_project_knowledge.md).
|
- **`project_then_grok`** — questions about the **Vojo product itself** (`PROJECT_KB_ENABLED`): a curated KB (operator data from `PROJECT_KB_PATH`, default the bundled `prompts/vojo_kb.txt`) is injected as a system note and **Grok answers product claims strictly from it** (anti-hallucination — Grok has no parametric Vojo knowledge, and the web doesn't either). The same note carries a **per-turn tone override** so product answers come in a plain, matter-of-fact product register — the base persona's dry irony and "bring-your-own-take" warmth are dropped for this route (register only; the entity-scoped sourcing license and the language rule are untouched). Gated by the classifier's `about_project` signal (the context-aware judge — it resolves follow-ups like "Про этот" → the app); a false positive is bounded by the entity-scoped note. Beats every web arm. One Grok call, so it costs ~the same as `grok_direct`. See [docs/plans/ai_project_knowledge.md](../plans/ai_project_knowledge.md).
|
||||||
- Router = free Layer-0 regex + optional Layer-1 Gemini classifier; a confidence floor keeps uncertain cases on the safe floor (`grok_direct`).
|
- Router = free Layer-0 regex + optional Layer-1 Gemini classifier; a confidence floor keeps uncertain cases on the safe floor (`grok_direct`).
|
||||||
|
|
||||||
**Invariant:** all cascade flags OFF == today's bot — a single `grok_direct` call, byte-identical wire body. Do not enable layers in prod until the offline-eval gate (build plan §9) passes.
|
**Invariant:** all cascade flags OFF == today's bot — a single `grok_direct` call, byte-identical wire body. Do not enable layers in prod until the offline-eval gate (build plan §9) passes.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue