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 []
}
// 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<string, string> = {
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()