Improve suggested notes: limit 8, threshold 0.45, show relevance scores
- Raise similarity threshold 0.30 → 0.45: only genuinely relevant notes shown; loosely-related notes no longer pad the sidebar - Increase max suggested notes 3 → 8 (zero added compute — threshold is the real gate; the embedding call is fixed regardless of limit) - semantic_search_notes now returns list[tuple[float, Note]] instead of list[Note] so scores propagate through context_meta to the frontend - Keyword fallback notes carry score=null (no cosine similarity available) - ChatView sidebar shows % badge on each suggested note: green ≥75%, amber 60–74%, muted <60% Hovering reveals the raw score in a tooltip Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -444,30 +444,38 @@ async def build_context(
|
||||
if current_note_id:
|
||||
search_exclude.add(current_note_id)
|
||||
|
||||
found_notes = []
|
||||
# (score, note) pairs — score is float for semantic results, None for keyword fallback.
|
||||
found_scored: list[tuple[float | None, object]] = []
|
||||
|
||||
# Try semantic search first; fall back to keyword search on failure / no results.
|
||||
try:
|
||||
from fabledassistant.services.embeddings import semantic_search_notes
|
||||
found_notes = await semantic_search_notes(
|
||||
user_id, user_message, exclude_ids=search_exclude or None, limit=3
|
||||
)
|
||||
for score, note in await semantic_search_notes(
|
||||
user_id, user_message, exclude_ids=search_exclude or None, limit=8
|
||||
):
|
||||
found_scored.append((score, note))
|
||||
except Exception:
|
||||
logger.warning("Semantic note search failed, falling back to keyword search", exc_info=True)
|
||||
|
||||
if not found_notes:
|
||||
if not found_scored:
|
||||
keywords = _extract_keywords(user_message)
|
||||
if keywords:
|
||||
try:
|
||||
found_notes = await search_notes_for_context(
|
||||
user_id, keywords, exclude_ids=search_exclude or None, limit=3
|
||||
)
|
||||
for note in await search_notes_for_context(
|
||||
user_id, keywords, exclude_ids=search_exclude or None, limit=8
|
||||
):
|
||||
found_scored.append((None, note))
|
||||
except Exception:
|
||||
logger.warning("Failed to search notes for context", exc_info=True)
|
||||
|
||||
# Populate sidebar candidates (never auto-injected).
|
||||
for n in found_notes:
|
||||
context_meta["auto_notes"].append({"id": n.id, "title": n.title})
|
||||
context_meta["auto_note_ids"] = [n.id for n in found_notes]
|
||||
# Populate sidebar candidates (never auto-injected into system prompt).
|
||||
for score, n in found_scored:
|
||||
context_meta["auto_notes"].append({
|
||||
"id": n.id,
|
||||
"title": n.title,
|
||||
"score": round(score, 2) if score is not None else None,
|
||||
})
|
||||
context_meta["auto_note_ids"] = [n.id for _, n in found_scored]
|
||||
|
||||
# Inject explicitly included notes (user opted in via sidebar click).
|
||||
if include_note_ids:
|
||||
|
||||
Reference in New Issue
Block a user