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:
2026-03-01 12:10:39 -05:00
parent 7728e38318
commit 90afd3f131
4 changed files with 53 additions and 19 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ export interface ConversationDetail extends Conversation {
export interface ContextMeta {
context_note_id: number | null;
context_note_title: string | null;
auto_notes: { id: number; title: string }[];
auto_notes: { id: number; title: string; score?: number | null }[];
}
export interface OllamaStatus {
+23 -1
View File
@@ -38,7 +38,7 @@ const includedNoteIds = ref<Set<number>>(new Set());
const includedNotes = ref<{ id: number; title: string }[]>([]);
// Suggested notes — auto-found by search, not yet included
const suggestedNotes = ref<{ id: number; title: string }[]>([]);
const suggestedNotes = ref<{ id: number; title: string; score?: number | null }[]>([]);
let prevConvId: number | null = null;
@@ -482,6 +482,16 @@ onUnmounted(() => {
<router-link :to="`/notes/${note.id}`" class="context-note-name">
{{ note.title }}
</router-link>
<span
v-if="note.score != null"
class="context-note-score"
:class="{
'score-high': note.score >= 0.75,
'score-medium': note.score >= 0.60 && note.score < 0.75,
'score-low': note.score < 0.60,
}"
:title="`Relevance score: ${note.score}`"
>{{ Math.round(note.score * 100) }}%</span>
<button class="context-note-add" @click="includeNote(note)" title="Add to context">+</button>
</div>
</template>
@@ -807,6 +817,18 @@ onUnmounted(() => {
.context-note-suggested {
opacity: 0.85;
}
.context-note-score {
font-size: 0.67rem;
font-weight: 600;
padding: 0.05rem 0.22rem;
border-radius: 3px;
flex-shrink: 0;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
}
.score-high { color: var(--color-success); background: color-mix(in srgb, var(--color-success) 12%, transparent); }
.score-medium { color: #c98a00; background: rgba(201, 138, 0, 0.12); }
.score-low { color: var(--color-text-muted); background: var(--color-bg-secondary); }
.context-note-remove {
background: none;
border: none;