Files
Momento/memento-note/lib/ai/services/notebook-organizer.service.ts
Antigravity b9a80f9e64
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 5m37s
CI / Deploy production (on server) (push) Successful in 2m2s
feat: Organisateur IA — analyse carnet + tags + doublons + regroupements
- Service notebook-organizer.service.ts : analyse IA des notes
- Endpoint /api/ai/organize-notebook
- Dialog avec 4 sections :
  1. Résumé de l'état du carnet
  2. Tags suggérés (cliquable pour appliquer)
  3. Regroupements logiques par catégorie
  4. Détection de doublons avec explication
- Bouton 'Organiser' (Wand2) dans la barre du carnet
- i18n FR/EN complet
- Complète les 3 scénarios : Prof (wizard+exercices), Étudiant (wizard+planning), Ingénieur (organisateur)
2026-06-14 20:16:01 +00:00

105 lines
3.6 KiB
TypeScript

import { getChatProvider } from '../factory'
import { getSystemConfig } from '@/lib/config'
export interface OrganizationSuggestion {
suggestedTags: Array<{ name: string; noteIds: string[] }>
duplicates: Array<{ note1Id: string; note1Title: string; note2Id: string; note2Title: string; reason: string }>
categories: Array<{ name: string; noteIds: string[]; noteTitles: string[] }>
summary: string
}
export class NotebookOrganizerService {
async analyze(
notes: Array<{ id: string; title: string; contentPreview: string }>,
language?: string
): Promise<OrganizationSuggestion> {
const lang = language || 'fr'
const langName = lang === 'fr' ? 'français' : lang === 'fa' ? 'فارسی' : 'English'
const notesList = notes.map(n =>
`ID: ${n.id}\nTitre: ${n.title}\nAperçu: ${n.contentPreview.slice(0, 200)}`
).join('\n---\n')
const prompt = `Tu es un expert en organisation de connaissances. Analyse ces notes et propose une organisation.
LANGUE : ${langName}
NOTES DANS LE CARNET :
${notesList}
Analyse les notes et retourne :
1. **suggestedTags** — Tags pertinents à appliquer (3-8 tags). Pour chaque tag, liste les IDs des notes qui correspondent.
2. **duplicates** — Notes qui se chevauchent ou répètent la même information. Pour chaque paire, explique pourquoi.
3. **categories** — Regroupements logiques (2-5 catégories). Pour chaque catégorie, liste les IDs et titres des notes.
4. **summary** — Un résumé court de l'état du carnet et des recommandations.
FORMAT JSON UNIQUEMENT :
\`\`\`json
{
"suggestedTags": [
{ "name": "nom-du-tag", "noteIds": ["id1", "id2"] }
],
"duplicates": [
{ "note1Id": "id1", "note1Title": "...", "note2Id": "id2", "note2Title": "...", "reason": "..." }
],
"categories": [
{ "name": "Nom catégorie", "noteIds": ["id1"], "noteTitles": ["Titre"] }
],
"summary": "Résumé court..."
}
\`\`\`
Si aucune note en double n'est trouvée, retourne un array vide pour "duplicates".`
const config = await getSystemConfig()
const provider = getChatProvider(config)
const raw = await provider.generateText(prompt)
return this.parseResponse(raw)
}
private parseResponse(raw: string): OrganizationSuggestion {
const jsonMatch = raw.match(/```json\s*([\s\S]+?)\s*```/)
let jsonStr = jsonMatch ? jsonMatch[1] : raw
const start = jsonStr.indexOf('{')
const end = jsonStr.lastIndexOf('}')
if (start >= 0 && end > start) {
jsonStr = jsonStr.slice(start, end + 1)
}
try {
const parsed = JSON.parse(jsonStr)
return {
suggestedTags: (parsed.suggestedTags || []).map((t: any) => ({
name: String(t.name || ''),
noteIds: Array.isArray(t.noteIds) ? t.noteIds.map(String) : [],
})),
duplicates: (parsed.duplicates || []).map((d: any) => ({
note1Id: String(d.note1Id || ''),
note1Title: String(d.note1Title || ''),
note2Id: String(d.note2Id || ''),
note2Title: String(d.note2Title || ''),
reason: String(d.reason || ''),
})),
categories: (parsed.categories || []).map((c: any) => ({
name: String(c.name || ''),
noteIds: Array.isArray(c.noteIds) ? c.noteIds.map(String) : [],
noteTitles: Array.isArray(c.noteTitles) ? c.noteTitles.map(String) : [],
})),
summary: String(parsed.summary || ''),
}
} catch {
return {
suggestedTags: [],
duplicates: [],
categories: [],
summary: 'Analyse impossible — réessayer plus tard.',
}
}
}
}
export const notebookOrganizerService = new NotebookOrganizerService()