fix: make label suggestions content-specific, not generic
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s

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 <noreply@anthropic.com>
This commit is contained in:
2026-04-27 00:29:03 +02:00
parent 2d10e5527a
commit fb996e22ac

View File

@@ -133,11 +133,11 @@ export class ContextualAutoTagService {
return [] return []
} }
// Filter and map suggestions (case-insensitive) // Filter and map suggestions (case-insensitive, strict threshold)
const lowerAvailable = availableLabels.map((l: string) => l.toLowerCase()) const lowerAvailable = availableLabels.map((l: string) => l.toLowerCase())
const suggestions = suggestionsArray const suggestions = suggestionsArray
.filter((s: any) => { .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) => { .map((s: any) => {
const originalLabel = availableLabels.find((l: string) => l.toLowerCase() === s.label.toLowerCase()) || s.label 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) .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})`)) console.log('[ContextualAutoTag] filtered existing suggestions:', suggestions.length, suggestions.map((s: any) => `${s.label}(${s.confidence})`))
return suggestions as LabelSuggestion[] return suggestions as LabelSuggestion[]
@@ -252,172 +252,119 @@ export class ContextualAutoTagService {
const instructions: Record<string, string> = { const instructions: Record<string, string> = {
fr: ` 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 : CONTENU DE LA NOTE :
${noteContent.substring(0, 1000)} ${noteContent.substring(0, 1000)}
NOTEBOOK ACTUEL : CARNET : ${notebookName}
${notebookName}
LABELS DISPONIBLES DANS CE NOTEBOOK : LABELS DISPONIBLES :
${labelList} ${labelList}
TÂCHE : RÈGLES STRICTES :
Analyse le contenu de la note et suggère les labels les PLUS appropriés parmi les labels disponibles ci-dessus. - Ne suggère un label QUE s'il est DIRECTEMENT en rapport avec le contenu de cette note précise
Considère : - Un label "voyage" n'est pertinent QUE si la note parle de voyage
1. La pertinence du label pour le contenu - Un label "projet" n'est pertinent QUE si la note parle d'un projet spécifique
2. Le nombre de labels (maximum 3 suggestions) - Ne suggère PAS un label juste parce qu'il existe dans le carnet
3. La confiance (seuil minimum : 0.6) - Maximum 2 suggestions
- Confiance < 0.7 = ne pas suggérer
- Si AUCUN label n'est clairement pertinent, retourne un tableau VIDE
RÈGLES : Réponds en JSON :
- Suggère SEULEMENT des labels qui sont dans la liste des labels disponibles {"suggestions":[{"label":"nom","confidence":0.85,"reasoning":"pourquoi"}]}
- 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" }
]
}
Ta réponse : Ta réponse :
`.trim(), `.trim(),
en: ` 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: NOTE CONTENT:
${noteContent.substring(0, 1000)} ${noteContent.substring(0, 1000)}
CURRENT NOTEBOOK: NOTEBOOK: ${notebookName}
${notebookName}
AVAILABLE LABELS IN THIS NOTEBOOK: AVAILABLE LABELS:
${labelList} ${labelList}
TASK: STRICT RULES:
Analyze the note content and suggest the MOST appropriate labels from the available labels above. - Only suggest a label if it is DIRECTLY related to the content of THIS specific note
Consider: - A "travel" label is relevant ONLY if the note is about travel
1. Label relevance to content - A "project" label is relevant ONLY if the note discusses a specific project
2. Number of labels (maximum 3 suggestions) - Do NOT suggest a label just because it exists in the notebook
3. Confidence (minimum threshold: 0.6) - Maximum 2 suggestions
- Confidence < 0.7 = do not suggest
- If NO label is clearly relevant, return an EMPTY array
RULES: Respond in JSON:
- Suggest ONLY labels that are in the available labels list {"suggestions":[{"label":"name","confidence":0.85,"reasoning":"why"}]}
- 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" }
]
}
Your response: Your response:
`.trim(), `.trim(),
fa: ` fa: `
شما یک دستیار هستید که مناسب‌ترین برچسب‌ها را برای یک یادداشت پیشنهاد می‌دهید. تو دستیاری هستی که برچسب‌های مرتبط برای یادداشت پیشنهاد می‌دهی.
محتوای یادداشت: محتوای یادداشت:
${noteContent.substring(0, 1000)} ${noteContent.substring(0, 1000)}
دفترچه فعلی: دفترچه: ${notebookName}
${notebookName}
برچسب‌های موجود در این دفترچه: برچسب‌های موجود:
${labelList} ${labelList}
وظیفه: قوانین سخت‌گیرانه:
محتوای یادداشت را تحلیل کنید و مناسب‌ترین برچسب‌ها را از لیست برچسب‌های موجود در بالا پیشنهاد دهید. - فقط برچسبی را پیشنهاد بده که مستقیماً با محتوای همین یادداشت مرتبط باشد
در نظر بگیرید: - برچسب "سفر" فقط وقتی مرتبط است که یادداشت درباره سفر باشد
1. ارتباط برچسب با محتوا - حداکثر ۲ پیشنهاد
2. تعداد برچسب‌ها (حداکثر ۳ پیشنهاد) - اطمینان < 0.7 = پیشنهاد نده
3. اطمینان (حداقل آستانه: 0.6) - اگر هیچ برچسبی مرتبط نیست، آرایه خالی برگردان
قوانین: پاسخ JSON:
- فقط برچسب‌هایی را پیشنهاد دهید که در لیست برچسب‌های موجود هستند {"suggestions":[{"label":"نام","confidence":0.85,"reasoning":"چرا"}]}
- حداکثر ۳ پیشنهاد برگردانید
- هر پیشنهاد باید دارای اطمینان > 0.6 باشد
- اگر هیچ برچسبی مرتبط نیست، یک اینرایه خالی برگردانید
فرمت پاسخ (فقط JSON):
{
"suggestions": [
{ "label": "نام_برچسب", "confidence": 0.85, "reasoning": "چرا این برچسب مرتبط است" }
]
}
پاسخ شما: پاسخ شما:
`.trim(), `.trim(),
es: ` 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: CONTENIDO DE LA NOTA:
${noteContent.substring(0, 1000)} ${noteContent.substring(0, 1000)}
CUADERNO ACTUAL: CUADERNO: ${notebookName}
${notebookName}
ETIQUETAS DISPONIBLES EN ESTE CUADERNO: ETIQUETAS DISPONIBLES:
${labelList} ${labelList}
TAREA: REGLAS ESTRICTAS:
Analiza el contenido de la nota y sugiere las etiquetas MÁS apropiadas de las etiquetas disponibles arriba. - Solo sugiere una etiqueta si está DIRECTAMENTE relacionada con el contenido de ESTA nota
Considera: - Máximo 2 sugerencias
1. Relevancia de la etiqueta para el contenido - Confianza < 0.7 = no sugerir
2. Número de etiquetas (máximo 3 sugerencias) - Si NINGUNA etiqueta es relevante, devuelve un array VACÍO
3. Confianza (umbral mínimo: 0.6)
REGLAS: Responde en JSON:
- Sugiere SOLO etiquetas que estén en la lista de etiquetas disponibles {"suggestions":[{"label":"nombre","confidence":0.85,"reasoning":"por qué"}]}
- 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" }
]
}
Tu respuesta: Tu respuesta:
`.trim(), `.trim(),
de: ` 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: NOTIZINHALT:
${noteContent.substring(0, 1000)} ${noteContent.substring(0, 1000)}
AKTUELLES NOTIZBUCH: NOTIZBUCH: ${notebookName}
${notebookName}
VERFÜGBARE LABELS IN DIESEM NOTIZBUCH: VERFÜGBARE LABELS:
${labelList} ${labelList}
AUFGABE: STRIKTE REGELN:
Analysiere den Notizinhalt und schlage die AM BESTEN geeigneten Labels aus den oben verfügbaren Labels vor. - Schlage ein Label nur vor, wenn es DIREKT mit dem Inhalt DIESER Notiz zusammenhängt
Berücksichtige: - Maximal 2 Vorschläge
1. Relevanz des Labels für den Inhalt - Konfidenz < 0.7 = nicht vorschlagen
2. Anzahl der Labels (maximal 3 Vorschläge) - Wenn KEIN Label relevant ist, gib ein LEERES Array zurück
3. Konfidenz (Mindestschwellenwert: 0.6)
REGELN: Antworte in JSON:
- Schlage NUR Labels vor, die in der Liste der verfügbaren Labels sind {"suggestions":[{"label":"name","confidence":0.85,"reasoning":"warum"}]}
- 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" }
]
}
Deine Antwort: Deine Antwort:
`.trim() `.trim()