feat(ai): localize AI features
This commit is contained in:
@@ -28,7 +28,7 @@ export class AutoLabelCreationService {
|
||||
* @param userId - User ID (for authorization)
|
||||
* @returns Suggested labels or null if not enough notes/no patterns found
|
||||
*/
|
||||
async suggestLabels(notebookId: string, userId: string): Promise<AutoLabelSuggestion | null> {
|
||||
async suggestLabels(notebookId: string, userId: string, language: string = 'en'): Promise<AutoLabelSuggestion | null> {
|
||||
// 1. Get notebook with existing labels
|
||||
const notebook = await prisma.notebook.findFirst({
|
||||
where: {
|
||||
@@ -84,7 +84,7 @@ export class AutoLabelCreationService {
|
||||
}
|
||||
|
||||
// 2. Use AI to detect recurring themes
|
||||
const suggestions = await this.detectRecurringThemes(notes, notebook)
|
||||
const suggestions = await this.detectRecurringThemes(notes, notebook, language)
|
||||
|
||||
return suggestions
|
||||
}
|
||||
@@ -94,13 +94,14 @@ export class AutoLabelCreationService {
|
||||
*/
|
||||
private async detectRecurringThemes(
|
||||
notes: any[],
|
||||
notebook: any
|
||||
notebook: any,
|
||||
language: string
|
||||
): Promise<AutoLabelSuggestion | null> {
|
||||
const existingLabelNames = new Set<string>(
|
||||
notebook.labels.map((l: any) => l.name.toLowerCase())
|
||||
)
|
||||
|
||||
const prompt = this.buildPrompt(notes, existingLabelNames)
|
||||
const prompt = this.buildPrompt(notes, existingLabelNames, language)
|
||||
|
||||
try {
|
||||
const config = await getSystemConfig()
|
||||
@@ -128,9 +129,9 @@ export class AutoLabelCreationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build prompt for AI (always in French - interface language)
|
||||
* Build prompt for AI (localized)
|
||||
*/
|
||||
private buildPrompt(notes: any[], existingLabelNames: Set<string>): string {
|
||||
private buildPrompt(notes: any[], existingLabelNames: Set<string>, language: string = 'en'): string {
|
||||
const notesSummary = notes
|
||||
.map((note, index) => {
|
||||
const title = note.title || 'Sans titre'
|
||||
@@ -141,7 +142,8 @@ export class AutoLabelCreationService {
|
||||
|
||||
const existingLabels = Array.from(existingLabelNames).join(', ')
|
||||
|
||||
return `
|
||||
const instructions: Record<string, string> = {
|
||||
fr: `
|
||||
Tu es un assistant qui détecte les thèmes récurrents dans des notes pour suggérer de nouvelles étiquettes.
|
||||
|
||||
CARNET ANALYSÉ :
|
||||
@@ -182,7 +184,178 @@ Exemples de bonnes étiquettes :
|
||||
- "marie", "jean", "équipe" (personnes)
|
||||
|
||||
Ta réponse (JSON seulement) :
|
||||
`.trim(),
|
||||
en: `
|
||||
You are an assistant that detects recurring themes in notes to suggest new labels.
|
||||
|
||||
ANALYZED NOTEBOOK:
|
||||
${notes.length} notes
|
||||
|
||||
EXISTING LABELS (do not suggest these):
|
||||
${existingLabels || 'None'}
|
||||
|
||||
NOTEBOOK NOTES:
|
||||
${notesSummary}
|
||||
|
||||
TASK:
|
||||
Analyze the notes and detect recurring themes (keywords, subjects, places, people).
|
||||
A theme must appear in at least 5 different notes to be suggested.
|
||||
|
||||
RESPONSE FORMAT (JSON):
|
||||
{
|
||||
"labels": [
|
||||
{
|
||||
"nom": "label_name",
|
||||
"note_indices": [0, 5, 12, 23, 45],
|
||||
"confiance": 0.85
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
RULES:
|
||||
- Label name must be short (max 1-2 words)
|
||||
- A theme must appear in 5+ notes to be suggested
|
||||
- Confidence must be > 0.60
|
||||
- Do not suggest labels that already exist
|
||||
- Prioritize places, people, clear categories
|
||||
- Maximum 5 suggestions
|
||||
|
||||
Examples of good labels:
|
||||
- "tokyo", "kyoto", "osaka" (places)
|
||||
- "hotels", "restaurants", "flights" (categories)
|
||||
- "mary", "john", "team" (people)
|
||||
|
||||
Your response (JSON only):
|
||||
`.trim(),
|
||||
fa: `
|
||||
شما یک دستیار هستید که تمهای تکرارشونده در یادداشتها را برای پیشنهاد برچسبهای جدید شناسایی میکنید.
|
||||
|
||||
دفترچه تحلیل شده:
|
||||
${notes.length} یادداشت
|
||||
|
||||
برچسبهای موجود (اینها را پیشنهاد ندهید):
|
||||
${existingLabels || 'هیچ'}
|
||||
|
||||
یادداشتهای دفترچه:
|
||||
${notesSummary}
|
||||
|
||||
وظیفه:
|
||||
یادداشتها را تحلیل کنید و تمهای تکرارشونده (کلمات کلیدی، موضوعات، مکانها، افراد) را شناسایی کنید.
|
||||
یک تم باید حداقل در ۵ یادداشت مختلف ظاهر شود تا پیشنهاد داده شود.
|
||||
|
||||
فرمت پاسخ (JSON):
|
||||
{
|
||||
"labels": [
|
||||
{
|
||||
"nom": "نام_برچسب",
|
||||
"note_indices": [0, 5, 12, 23, 45],
|
||||
"confiance": 0.85
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
قوانین:
|
||||
- نام برچسب باید کوتاه باشد (حداکثر ۱-۲ کلمه)
|
||||
- یک تم باید در ۵+ یادداشت ظاهر شود تا پیشنهاد داده شود
|
||||
- اطمینان باید > 0.60 باشد
|
||||
- برچسبهایی که قبلاً وجود دارند را پیشنهاد ندهید
|
||||
- اولویت با مکانها، افراد، دستهبندیهای واضح است
|
||||
- حداکثر ۵ پیشنهاد
|
||||
|
||||
مثالهای برچسب خوب:
|
||||
- "توکیو"، "کیوتو"، "اوزاکا" (مکانها)
|
||||
- "هتلها"، "رستورانها"، "پروازها" (دستهبندیها)
|
||||
- "مریم"، "علی"، "تیم" (افراد)
|
||||
|
||||
پاسخ شما (فقط JSON):
|
||||
`.trim(),
|
||||
es: `
|
||||
Eres un asistente que detecta temas recurrentes en notas para sugerir nuevas etiquetas.
|
||||
|
||||
CUADERNO ANALIZADO:
|
||||
${notes.length} notas
|
||||
|
||||
ETIQUETAS EXISTENTES (no sugerir estas):
|
||||
${existingLabels || 'Ninguna'}
|
||||
|
||||
NOTAS DEL CUADERNO:
|
||||
${notesSummary}
|
||||
|
||||
TAREA:
|
||||
Analiza las notas y detecta temas recurrentes (palabras clave, temas, lugares, personas).
|
||||
Un tema debe aparecer en al menos 5 notas diferentes para ser sugerido.
|
||||
|
||||
FORMATO DE RESPUESTA (JSON):
|
||||
{
|
||||
"labels": [
|
||||
{
|
||||
"nom": "nombre_etiqueta",
|
||||
"note_indices": [0, 5, 12, 23, 45],
|
||||
"confiance": 0.85
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
REGLAS:
|
||||
- El nombre de la etiqueta debe ser corto (máx 1-2 palabras)
|
||||
- Un tema debe aparecer en 5+ notas para ser sugerido
|
||||
- La confianza debe ser > 0.60
|
||||
- No sugieras etiquetas que ya existen
|
||||
- Prioriza lugares, personas, categorías claras
|
||||
- Máximo 5 sugerencias
|
||||
|
||||
Ejemplos de buenas etiquetas:
|
||||
- "tokio", "kyoto", "osaka" (lugares)
|
||||
- "hoteles", "restaurantes", "vuelos" (categorías)
|
||||
- "maría", "juan", "equipo" (personas)
|
||||
|
||||
Tu respuesta (solo JSON):
|
||||
`.trim(),
|
||||
de: `
|
||||
Du bist ein Assistent, der wiederkehrende Themen in Notizen erkennt, um neue Labels vorzuschlagen.
|
||||
|
||||
ANALYSIERTES NOTIZBUCH:
|
||||
${notes.length} Notizen
|
||||
|
||||
VORHANDENE LABELS (schlage diese nicht vor):
|
||||
${existingLabels || 'Keine'}
|
||||
|
||||
NOTIZBUCH-NOTIZEN:
|
||||
${notesSummary}
|
||||
|
||||
AUFGABE:
|
||||
Analysiere die Notizen und erkenne wiederkehrende Themen (Schlüsselwörter, Themen, Orte, Personen).
|
||||
Ein Thema muss in mindestens 5 verschiedenen Notizen erscheinen, um vorgeschlagen zu werden.
|
||||
|
||||
ANTWORTFORMAT (JSON):
|
||||
{
|
||||
"labels": [
|
||||
{
|
||||
"nom": "label_name",
|
||||
"note_indices": [0, 5, 12, 23, 45],
|
||||
"confiance": 0.85
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
REGELN:
|
||||
- Der Labelname muss kurz sein (max 1-2 Wörter)
|
||||
- Ein Thema muss in 5+ Notizen erscheinen, um vorgeschlagen zu werden
|
||||
- Konfidenz muss > 0.60 sein
|
||||
- Schlage keine Labels vor, die bereits existieren
|
||||
- Priorisiere Orte, Personen, klare Kategorien
|
||||
- Maximal 5 Vorschläge
|
||||
|
||||
Beispiele für gute Labels:
|
||||
- "tokio", "kyoto", "osaka" (Orte)
|
||||
- "hotels", "restaurants", "flüge" (Kategorien)
|
||||
- "maria", "johannes", "team" (Personen)
|
||||
|
||||
Deine Antwort (nur JSON):
|
||||
`.trim()
|
||||
}
|
||||
|
||||
return instructions[language] || instructions['en'] || instructions['fr']
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user