feat(ai): localize AI features
This commit is contained in:
@@ -10,7 +10,7 @@ export class NotebookSuggestionService {
|
||||
* @param userId - User ID (for fetching user's notebooks)
|
||||
* @returns Suggested notebook or null (if no good match)
|
||||
*/
|
||||
async suggestNotebook(noteContent: string, userId: string): Promise<Notebook | null> {
|
||||
async suggestNotebook(noteContent: string, userId: string, language: string = 'en'): Promise<Notebook | null> {
|
||||
// 1. Get all notebooks for this user
|
||||
const notebooks = await prisma.notebook.findMany({
|
||||
where: { userId },
|
||||
@@ -28,7 +28,7 @@ export class NotebookSuggestionService {
|
||||
}
|
||||
|
||||
// 2. Build prompt for AI (always in French - interface language)
|
||||
const prompt = this.buildPrompt(noteContent, notebooks)
|
||||
const prompt = this.buildPrompt(noteContent, notebooks, language)
|
||||
|
||||
// 3. Call AI
|
||||
try {
|
||||
@@ -57,9 +57,9 @@ export class NotebookSuggestionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the AI prompt for notebook suggestion (always in French - interface language)
|
||||
* Build the AI prompt for notebook suggestion (localized)
|
||||
*/
|
||||
private buildPrompt(noteContent: string, notebooks: any[]): string {
|
||||
private buildPrompt(noteContent: string, notebooks: any[], language: string = 'en'): string {
|
||||
const notebookList = notebooks
|
||||
.map(nb => {
|
||||
const labels = nb.labels.map((l: any) => l.name).join(', ')
|
||||
@@ -68,7 +68,8 @@ export class NotebookSuggestionService {
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
return `
|
||||
const instructions: Record<string, string> = {
|
||||
fr: `
|
||||
Tu es un assistant qui suggère à quel carnet une note devrait appartenir.
|
||||
|
||||
CONTENU DE LA NOTE :
|
||||
@@ -107,7 +108,148 @@ Exemples :
|
||||
- "Achat d'une chemise et d'un jean" → carnet "Personnel"
|
||||
|
||||
Ta suggestion :
|
||||
`.trim(),
|
||||
en: `
|
||||
You are an assistant that suggests which notebook a note should belong to.
|
||||
|
||||
NOTE CONTENT:
|
||||
${noteContent.substring(0, 500)}
|
||||
|
||||
AVAILABLE NOTEBOOKS:
|
||||
${notebookList}
|
||||
|
||||
TASK:
|
||||
Analyze the note content (regardless of language) and suggest the MOST appropriate notebook for this note.
|
||||
Consider:
|
||||
1. The subject/theme of the note (MOST IMPORTANT)
|
||||
2. Existing labels in each notebook
|
||||
3. The number of notes (prefer notebooks with related content)
|
||||
|
||||
CLASSIFICATION GUIDE:
|
||||
- SPORT/EXERCISE/SHOPPING/GROCERIES → Personal Notebook
|
||||
- HOBBIES/PASSIONS/OUTINGS → Personal Notebook
|
||||
- HEALTH/FITNESS/DOCTOR → Personal Notebook or Health
|
||||
- FAMILY/FRIENDS → Personal Notebook
|
||||
- WORK/MEETINGS/PROJECTS/CLIENTS → Work Notebook
|
||||
- CODING/TECH/DEVELOPMENT → Work Notebook or Code
|
||||
- FINANCE/BILLS/BANKING → Personal Notebook or Finance
|
||||
|
||||
RULES:
|
||||
- Return ONLY the notebook name, EXACTLY as listed above (case insensitive)
|
||||
- If no good match exists, return "NONE"
|
||||
- If the note is too generic/vague, return "NONE"
|
||||
- Do not include explanations or extra text
|
||||
|
||||
Examples:
|
||||
- "Meeting with John about project planning" → notebook "Work"
|
||||
- "Grocery list or buying clothes" → notebook "Personal"
|
||||
- "Python script for data analysis" → notebook "Code"
|
||||
- "Gym session or fitness" → notebook "Personal"
|
||||
|
||||
Your suggestion:
|
||||
`.trim(),
|
||||
fa: `
|
||||
شما یک دستیار هستید که پیشنهاد میدهد یک یادداشت به کدام دفترچه تعلق داشته باشد.
|
||||
|
||||
محتوای یادداشت:
|
||||
${noteContent.substring(0, 500)}
|
||||
|
||||
دفترچههای موجود:
|
||||
${notebookList}
|
||||
|
||||
وظیفه:
|
||||
محتوای یادداشت را تحلیل کنید (صرف نظر از زبان) و مناسبترین دفترچه را برای این یادداشت پیشنهاد دهید.
|
||||
در نظر بگیرید:
|
||||
1. موضوع/تم یادداشت (مهمترین)
|
||||
2. برچسبهای موجود در هر دفترچه
|
||||
3. تعداد یادداشتها (دفترچههای با محتوای مرتبط را ترجیح دهید)
|
||||
|
||||
راهنمای طبقهبندی:
|
||||
- ورزش/تمرین/خرید → دفترچه شخصی
|
||||
- سرگرمیها/علایق/گردش → دفترچه شخصی
|
||||
- سلامت/تناسب اندام/پزشک → دفترچه شخصی یا سلامت
|
||||
- خانواده/دوستان → دفترچه شخصی
|
||||
- کار/جلسات/پروژهها/مشتریان → دفترچه کار
|
||||
- کدنویسی/تکنولوژی/توسعه → دفترچه کار یا کد
|
||||
- مالی/قبضها/بانک → دفترچه شخصی یا مالی
|
||||
|
||||
قوانین:
|
||||
- فقط نام دفترچه را برگردانید، دقیقاً همانطور که در بالا ذکر شده است (بدون حساسیت به حروف بزرگ و کوچک)
|
||||
- اگر تطابق خوبی وجود ندارد، "NONE" را برگردانید
|
||||
- اگر یادداشت خیلی کلی/مبهم است، "NONE" را برگردانید
|
||||
- توضیحات یا متن اضافی را شامل نکنید
|
||||
|
||||
پیشناد شما:
|
||||
`.trim(),
|
||||
es: `
|
||||
Eres un asistente que sugiere a qué cuaderno debería pertenecer una nota.
|
||||
|
||||
CONTENIDO DE LA NOTA:
|
||||
${noteContent.substring(0, 500)}
|
||||
|
||||
CUADERNOS DISPONIBLES:
|
||||
${notebookList}
|
||||
|
||||
TAREA:
|
||||
Analiza el contenido de la nota (independientemente del idioma) y sugiere el cuaderno MÁS apropiado para esta nota.
|
||||
Considera:
|
||||
1. El tema/asunto de la nota (LO MÁS IMPORTANTE)
|
||||
2. Etiquetas existentes en cada cuaderno
|
||||
3. El número de notas (prefiere cuadernos con contenido relacionado)
|
||||
|
||||
GUÍA DE CLASIFICACIÓN:
|
||||
- DEPORTE/EJERCICIO/COMPRAS → Cuaderno Personal
|
||||
- HOBBIES/PASIONES/SALIDAS → Cuaderno Personal
|
||||
- SALUD/FITNESS/DOCTOR → Cuaderno Personal o Salud
|
||||
- FAMILIA/AMIGOS → Cuaderno Personal
|
||||
- TRABAJO/REUNIONES/PROYECTOS → Cuaderno Trabajo
|
||||
- CODING/TECH/DESARROLLO → Cuaderno Trabajo o Código
|
||||
- FINANZAS/FACTURAS/BANCO → Cuaderno Personal o Finanzas
|
||||
|
||||
REGLAS:
|
||||
- Devuelve SOLO el nombre del cuaderno, EXACTAMENTE como se lista arriba (insensible a mayúsculas/minúsculas)
|
||||
- Si no existe una buena coincidencia, devuelve "NONE"
|
||||
- Si la nota es demasiado genérica/vaga, devuelve "NONE"
|
||||
- No incluyas explicaciones o texto extra
|
||||
|
||||
Tu sugerencia:
|
||||
`.trim(),
|
||||
de: `
|
||||
Du bist ein Assistent, der vorschlägt, zu welchem Notizbuch eine Notiz gehören sollte.
|
||||
|
||||
NOTIZINHALT:
|
||||
${noteContent.substring(0, 500)}
|
||||
|
||||
VERFÜGBARE NOTIZBÜCHER:
|
||||
${notebookList}
|
||||
|
||||
AUFGABE:
|
||||
Analysiere den Notizinhalt (unabhängig von der Sprache) und schlage das AM BESTEN geeignete Notizbuch für diese Notiz vor.
|
||||
Berücksichtige:
|
||||
1. Das Thema/den Inhalt der Notiz (AM WICHTIGSTEN)
|
||||
2. Vorhandene Labels in jedem Notizbuch
|
||||
3. Die Anzahl der Notizen (bevorzuge Notizbücher mit verwandtem Inhalt)
|
||||
|
||||
KLASSIFIZIERUNGSLEITFADEN:
|
||||
- SPORT/ÜBUNG/EINKAUFEN → Persönliches Notizbuch
|
||||
- HOBBYS/LEIDENSCHAFTEN → Persönliches Notizbuch
|
||||
- GESUNDHEIT/FITNESS/ARZT → Persönliches Notizbuch oder Gesundheit
|
||||
- FAMILIE/FREUNDE → Persönliches Notizbuch
|
||||
- ARBEIT/MEETINGS/PROJEKTE → Arbeitsnotizbuch
|
||||
- CODING/TECH/ENTWICKLUNG → Arbeitsnotizbuch oder Code
|
||||
- FINANZEN/RECHNUNGEN/BANK → Persönliches Notizbuch oder Finanzen
|
||||
|
||||
REGELN:
|
||||
- Gib NUR den Namen des Notizbuchs zurück, GENAU wie oben aufgeführt (Groß-/Kleinschreibung egal)
|
||||
- Wenn keine gute Übereinstimmung existiert, gib "NONE" zurück
|
||||
- Wenn die Notiz zu allgemein/vage ist, gib "NONE" zurück
|
||||
- Füge keine Erklärungen oder zusätzlichen Text hinzu
|
||||
|
||||
Dein Vorschlag:
|
||||
`.trim()
|
||||
}
|
||||
|
||||
return instructions[language] || instructions['en'] || instructions['fr']
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,14 +260,15 @@ Ta suggestion :
|
||||
*/
|
||||
async suggestNotebooksBatch(
|
||||
noteContents: string[],
|
||||
userId: string
|
||||
userId: string,
|
||||
language: string = 'en'
|
||||
): Promise<Map<number, Notebook | null>> {
|
||||
const results = new Map<number, Notebook | null>()
|
||||
|
||||
// For efficiency, we could batch this into a single AI call
|
||||
// For now, process sequentially (could be parallelized)
|
||||
for (let i = 0; i < noteContents.length; i++) {
|
||||
const suggestion = await this.suggestNotebook(noteContents[i], userId)
|
||||
const suggestion = await this.suggestNotebook(noteContents[i], userId, language)
|
||||
results.set(i, suggestion)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user