From fb996e22acb897c3bf49ffe46f11a1075e820acb Mon Sep 17 00:00:00 2001 From: sepehr Date: Mon, 27 Apr 2026 00:29:03 +0200 Subject: [PATCH] fix: make label suggestions content-specific, not generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrote prompts to be strict about content relevance — only suggest labels directly related to THIS note's content. Raised confidence threshold to 0.5 in code, 0.7 in prompt. Limited to max 2 suggestions from existing labels. Prevents same labels being suggested for every note. Co-Authored-By: Claude Opus 4.7 --- .../services/contextual-auto-tag.service.ts | 173 ++++++------------ 1 file changed, 60 insertions(+), 113 deletions(-) diff --git a/memento-note/lib/ai/services/contextual-auto-tag.service.ts b/memento-note/lib/ai/services/contextual-auto-tag.service.ts index d1d60b2..a23e72c 100644 --- a/memento-note/lib/ai/services/contextual-auto-tag.service.ts +++ b/memento-note/lib/ai/services/contextual-auto-tag.service.ts @@ -133,11 +133,11 @@ export class ContextualAutoTagService { return [] } - // Filter and map suggestions (case-insensitive) + // Filter and map suggestions (case-insensitive, strict threshold) const lowerAvailable = availableLabels.map((l: string) => l.toLowerCase()) const suggestions = suggestionsArray .filter((s: any) => { - return s.label && lowerAvailable.includes(s.label.toLowerCase()) && (s.confidence || 0) > 0.3 + return s.label && lowerAvailable.includes(s.label.toLowerCase()) && (s.confidence || 0) > 0.5 }) .map((s: any) => { const originalLabel = availableLabels.find((l: string) => l.toLowerCase() === s.label.toLowerCase()) || s.label @@ -149,7 +149,7 @@ export class ContextualAutoTagService { } }) .sort((a: any, b: any) => b.confidence - a.confidence) - .slice(0, 5) + .slice(0, 3) console.log('[ContextualAutoTag] filtered existing suggestions:', suggestions.length, suggestions.map((s: any) => `${s.label}(${s.confidence})`)) return suggestions as LabelSuggestion[] @@ -252,172 +252,119 @@ export class ContextualAutoTagService { const instructions: Record = { fr: ` -Tu es un assistant qui suggère les labels les plus appropriés pour une note. +Tu es un assistant qui suggère des labels PERTINENTS pour une note. CONTENU DE LA NOTE : ${noteContent.substring(0, 1000)} -NOTEBOOK ACTUEL : -${notebookName} +CARNET : ${notebookName} -LABELS DISPONIBLES DANS CE NOTEBOOK : +LABELS DISPONIBLES : ${labelList} -TÂCHE : -Analyse le contenu de la note et suggère les labels les PLUS appropriés parmi les labels disponibles ci-dessus. -Considère : -1. La pertinence du label pour le contenu -2. Le nombre de labels (maximum 3 suggestions) -3. La confiance (seuil minimum : 0.6) +RÈGLES STRICTES : +- Ne suggère un label QUE s'il est DIRECTEMENT en rapport avec le contenu de cette note précise +- Un label "voyage" n'est pertinent QUE si la note parle de voyage +- Un label "projet" n'est pertinent QUE si la note parle d'un projet spécifique +- Ne suggère PAS un label juste parce qu'il existe dans le carnet +- Maximum 2 suggestions +- Confiance < 0.7 = ne pas suggérer +- Si AUCUN label n'est clairement pertinent, retourne un tableau VIDE -RÈGLES : -- Suggère SEULEMENT des labels qui sont dans la liste des labels disponibles -- Retourne au maximum 3 suggestions -- Chaque suggestion doit avoir une confiance > 0.6 -- Si aucun label n'est pertinent, retourne un tableau vide - -FORMAT DE RÉPONSE (JSON uniquement) : -{ - "suggestions": [ - { "label": "nom_du_label", "confidence": 0.85, "reasoning": "Pourquoi ce label est pertinent" } - ] -} +Réponds en JSON : +{"suggestions":[{"label":"nom","confidence":0.85,"reasoning":"pourquoi"}]} Ta réponse : `.trim(), en: ` -You are an assistant that suggests the most appropriate labels for a note. +You are an assistant that suggests RELEVANT labels for a note. NOTE CONTENT: ${noteContent.substring(0, 1000)} -CURRENT NOTEBOOK: -${notebookName} +NOTEBOOK: ${notebookName} -AVAILABLE LABELS IN THIS NOTEBOOK: +AVAILABLE LABELS: ${labelList} -TASK: -Analyze the note content and suggest the MOST appropriate labels from the available labels above. -Consider: -1. Label relevance to content -2. Number of labels (maximum 3 suggestions) -3. Confidence (minimum threshold: 0.6) +STRICT RULES: +- Only suggest a label if it is DIRECTLY related to the content of THIS specific note +- A "travel" label is relevant ONLY if the note is about travel +- A "project" label is relevant ONLY if the note discusses a specific project +- Do NOT suggest a label just because it exists in the notebook +- Maximum 2 suggestions +- Confidence < 0.7 = do not suggest +- If NO label is clearly relevant, return an EMPTY array -RULES: -- Suggest ONLY labels that are in the available labels list -- Return maximum 3 suggestions -- Each suggestion must have confidence > 0.6 -- If no label is relevant, return an empty array - -RESPONSE FORMAT (JSON only): -{ - "suggestions": [ - { "label": "label_name", "confidence": 0.85, "reasoning": "Why this label is relevant" } - ] -} +Respond in JSON: +{"suggestions":[{"label":"name","confidence":0.85,"reasoning":"why"}]} Your response: `.trim(), fa: ` -شما یک دستیار هستید که مناسب‌ترین برچسب‌ها را برای یک یادداشت پیشنهاد می‌دهید. +تو دستیاری هستی که برچسب‌های مرتبط برای یادداشت پیشنهاد می‌دهی. محتوای یادداشت: ${noteContent.substring(0, 1000)} -دفترچه فعلی: -${notebookName} +دفترچه: ${notebookName} -برچسب‌های موجود در این دفترچه: +برچسب‌های موجود: ${labelList} -وظیفه: -محتوای یادداشت را تحلیل کنید و مناسب‌ترین برچسب‌ها را از لیست برچسب‌های موجود در بالا پیشنهاد دهید. -در نظر بگیرید: -1. ارتباط برچسب با محتوا -2. تعداد برچسب‌ها (حداکثر ۳ پیشنهاد) -3. اطمینان (حداقل آستانه: 0.6) +قوانین سخت‌گیرانه: +- فقط برچسبی را پیشنهاد بده که مستقیماً با محتوای همین یادداشت مرتبط باشد +- برچسب "سفر" فقط وقتی مرتبط است که یادداشت درباره سفر باشد +- حداکثر ۲ پیشنهاد +- اطمینان < 0.7 = پیشنهاد نده +- اگر هیچ برچسبی مرتبط نیست، آرایه خالی برگردان -قوانین: -- فقط برچسب‌هایی را پیشنهاد دهید که در لیست برچسب‌های موجود هستند -- حداکثر ۳ پیشنهاد برگردانید -- هر پیشنهاد باید دارای اطمینان > 0.6 باشد -- اگر هیچ برچسبی مرتبط نیست، یک اینرایه خالی برگردانید - -فرمت پاسخ (فقط JSON): -{ - "suggestions": [ - { "label": "نام_برچسب", "confidence": 0.85, "reasoning": "چرا این برچسب مرتبط است" } - ] -} +پاسخ JSON: +{"suggestions":[{"label":"نام","confidence":0.85,"reasoning":"چرا"}]} پاسخ شما: `.trim(), es: ` -Eres un asistente que sugiere las etiquetas más apropiadas para una nota. +Eres un asistente que sugiere etiquetas RELEVANTES para una nota. CONTENIDO DE LA NOTA: ${noteContent.substring(0, 1000)} -CUADERNO ACTUAL: -${notebookName} +CUADERNO: ${notebookName} -ETIQUETAS DISPONIBLES EN ESTE CUADERNO: +ETIQUETAS DISPONIBLES: ${labelList} -TAREA: -Analiza el contenido de la nota y sugiere las etiquetas MÁS apropiadas de las etiquetas disponibles arriba. -Considera: -1. Relevancia de la etiqueta para el contenido -2. Número de etiquetas (máximo 3 sugerencias) -3. Confianza (umbral mínimo: 0.6) +REGLAS ESTRICTAS: +- Solo sugiere una etiqueta si está DIRECTAMENTE relacionada con el contenido de ESTA nota +- Máximo 2 sugerencias +- Confianza < 0.7 = no sugerir +- Si NINGUNA etiqueta es relevante, devuelve un array VACÍO -REGLAS: -- Sugiere SOLO etiquetas que estén en la lista de etiquetas disponibles -- Devuelve máximo 3 sugerencias -- Cada sugerencia debe tener confianza > 0.6 -- Si ninguna etiqueta es relevante, devuelve un array vacío - -FORMATO DE RESPUESTA (solo JSON): -{ - "suggestions": [ - { "label": "nombre_etiqueta", "confidence": 0.85, "reasoning": "Por qué esta etiqueta es relevante" } - ] -} +Responde en JSON: +{"suggestions":[{"label":"nombre","confidence":0.85,"reasoning":"por qué"}]} Tu respuesta: `.trim(), de: ` -Du bist ein Assistent, der die passendsten Labels für eine Notiz vorschlägt. +Du bist ein Assistent, der RELEVANTE Labels für eine Notiz vorschlägt. NOTIZINHALT: ${noteContent.substring(0, 1000)} -AKTUELLES NOTIZBUCH: -${notebookName} +NOTIZBUCH: ${notebookName} -VERFÜGBARE LABELS IN DIESEM NOTIZBUCH: +VERFÜGBARE LABELS: ${labelList} -AUFGABE: -Analysiere den Notizinhalt und schlage die AM BESTEN geeigneten Labels aus den oben verfügbaren Labels vor. -Berücksichtige: -1. Relevanz des Labels für den Inhalt -2. Anzahl der Labels (maximal 3 Vorschläge) -3. Konfidenz (Mindestschwellenwert: 0.6) +STRIKTE REGELN: +- Schlage ein Label nur vor, wenn es DIREKT mit dem Inhalt DIESER Notiz zusammenhängt +- Maximal 2 Vorschläge +- Konfidenz < 0.7 = nicht vorschlagen +- Wenn KEIN Label relevant ist, gib ein LEERES Array zurück -REGELN: -- Schlage NUR Labels vor, die in der Liste der verfügbaren Labels sind -- Gib maximal 3 Vorschläge zurück -- Jeder Vorschlag muss eine Konfidenz > 0.6 haben -- Wenn kein Label relevant ist, gib ein leeres Array zurück - -ANTWORTFORMAT (nur JSON): -{ - "suggestions": [ - { "label": "label_name", "confidence": 0.85, "reasoning": "Warum dieses Label relevant ist" } - ] -} +Antworte in JSON: +{"suggestions":[{"label":"name","confidence":0.85,"reasoning":"warum"}]} Deine Antwort: `.trim()