feat(r42): improve KB grounding accuracy and add clear-history
R42 was missing knowledge-graph information (e.g. pension questions) because retrieval and context-building dropped relevant facts: - retrieval: exact-token TF-IDF could not match Dutch compound words, so a "pensioen" query scored 0 against "pensioenregeling" / "partnerpensioen" and never retrieved them. Add a compound-word fallback (shared >=6-char stem or containment, 0.4x weight) alongside exact matching. - rag: deep article content was only injected for verbatim-mentioned topics; retrieved topics contributed just a 200-char description. Inject ~1000 chars of content for up to 5 topics (mentions first, then top-ranked retrieved) and widen the description snippet to 320. - prompts: add a NAUWKEURIGHEID block (use all relevant facts, call lookup_topic before giving up) and relax the 4-sentence cap for detail/list answers so complete facts aren't summarised away. Also add a clear-history control: a trash button in the chat header (confirm dialog) wipes chat🧵{userId} and reseeds the greeting via clearThread() in useChat. Tests: compound-word matching + rag deep-content injection. Spec updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,8 @@ client-side and is grounded by local TF-IDF retrieval — **no vector database**
|
||||
context is truncated with a notice.
|
||||
- A greeting message seeds an empty thread.
|
||||
- Each turn calls `callLLM` (fast/standard Claude tier — low latency matters for chat).
|
||||
- The chat header has a **clear** button (trash icon). It confirms, then wipes
|
||||
`chat:thread:{userId}` and reseeds the greeting via `clearThread` in `useChat.js`.
|
||||
|
||||
---
|
||||
|
||||
@@ -25,13 +27,21 @@ client-side and is grounded by local TF-IDF retrieval — **no vector database**
|
||||
|
||||
`buildKbContext` in `rag.js`:
|
||||
1. Build / reuse the TF-IDF index over `topics` (`src/lib/retrieval.js`).
|
||||
2. Retrieve the top **10** topics for the user's message.
|
||||
2. Retrieve the top **10** topics for the user's message. Scoring is exact-token
|
||||
TF-IDF **plus a compound-word fallback**: an unmatched query token (≥6 chars)
|
||||
also matches a document term when they share a ≥6-char stem or one contains
|
||||
the other, at a reduced weight. This recovers Dutch compounds — e.g. a
|
||||
`pensioen` query matches `pensioenregeling` and `partnerpensioen`.
|
||||
3. Always include topics whose `id` or `label` appears verbatim in the message.
|
||||
4. Include relations only when **both** endpoints are in the retrieved set.
|
||||
5. For explicitly mentioned topics, inject up to ~1200 chars of their generated
|
||||
content.
|
||||
5. Inject up to ~1000 chars of generated content for up to **5** topics —
|
||||
verbatim-mentioned first, then the highest-ranked retrieved ones — so a query
|
||||
that never names a topic exactly still gets rich content for what it matched.
|
||||
6. Append a short KB hash so the cached context busts when topics change.
|
||||
|
||||
If the summarised context is still too thin, R42 can call the `lookup_topic`
|
||||
tool to pull a topic's full description and learning content on demand.
|
||||
|
||||
The system prompt (`prompts.js`) is assembled as cacheable blocks: a stable
|
||||
preamble (role, tasks, style, "answer only from the KB"), the KB context block, and
|
||||
a per-turn tail with the user's name and admin/non-admin flag.
|
||||
|
||||
Reference in New Issue
Block a user