diff --git a/.claude/settings.json b/.claude/settings.json index 9b938bc..921fee4 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -6,7 +6,9 @@ "Bash(python -m ruff check . --fix)", "Bash(ruff check *)", "Bash(powershell -Command \"cd 'c:\\\\\\\\_temp\\\\\\\\_adiuvai_workspace\\\\\\\\api'; .venv\\\\\\\\Scripts\\\\\\\\pytest.exe tests/test_memory_relations.py -v 2>&1 | Out-File -FilePath 'C:\\\\\\\\Users\\\\\\\\musso\\\\\\\\AppData\\\\\\\\Local\\\\\\\\Temp\\\\\\\\pytest_phase3.txt' -Encoding UTF8; Get-Content 'C:\\\\\\\\Users\\\\\\\\musso\\\\\\\\AppData\\\\\\\\Local\\\\\\\\Temp\\\\\\\\pytest_phase3.txt'\")", - "mcp__postgres__execute_sql" + "mcp__postgres__execute_sql", + "mcp__langfuse__listPrompts", + "mcp__langfuse__getPrompt" ] }, "enabledPlugins": { diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..013d11a --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "enabledMcpjsonServers": [ + "langfuse-docs", + "langfuse", + "postgres" + ] +} diff --git a/.gitignore b/.gitignore index c747de4..00b4c05 100644 --- a/.gitignore +++ b/.gitignore @@ -98,3 +98,6 @@ unused_skills/ .claude/skills/webapp-testing/examples/static_html_automation.py .claude/skills/webapp-testing/scripts/with_server.py .mcp.json +docs/node_modules +docs/package.json +docs/package-lock.json \ No newline at end of file diff --git a/adiuvAI b/adiuvAI index e9c790e..7244810 160000 --- a/adiuvAI +++ b/adiuvAI @@ -1 +1 @@ -Subproject commit e9c790e017b201e55a1a60dcefc6e43c5fa16b57 +Subproject commit 7244810fe181bf21968263853881730352226182 diff --git a/api b/api index d5fea95..2c7cac9 160000 --- a/api +++ b/api @@ -1 +1 @@ -Subproject commit d5fea955611969869a6ae754107c4500aa78edfe +Subproject commit 2c7cac9e034a3aaa862db9d9f8f9ccfbf1664e8c diff --git a/docs/adiuvAI-pitch.pptx b/docs/adiuvAI-pitch.pptx new file mode 100644 index 0000000..a88e8fe Binary files /dev/null and b/docs/adiuvAI-pitch.pptx differ diff --git a/docs/build-deck-geopop.js b/docs/build-deck-geopop.js new file mode 100644 index 0000000..2298f4d --- /dev/null +++ b/docs/build-deck-geopop.js @@ -0,0 +1,624 @@ +"use strict"; +const pptxgen = require("pptxgenjs"); + +// ── Paths ────────────────────────────────────────────────────────────────── +const LOGO = "C:/Users/PC-Roby/Documents/_adiuvai_workspace/adiuvAI/assets/logo/logo-icon.png"; +const SCR_H = "C:/Users/PC-Roby/Documents/_adiuvai_workspace/adiuvAI/assets/screenshot/home.png"; +const SCR_HC = "C:/Users/PC-Roby/Documents/_adiuvai_workspace/adiuvAI/assets/screenshot/home_chat.png"; +const OUTPUT = "C:/Users/PC-Roby/Documents/_adiuvai_workspace/docs/adiuvAI-pitch-geopop.pptx"; + +// ── Color tokens (NO # prefix) ───────────────────────────────────────────── +const C = { + canvas: "f4edf3", // light bg + ink: "040404", // primary text + golden: "fbc881", // accent + slate: "8a8ea9", // secondary text + lavender: "c8c3cd", // borders + void: "0c0c0c", // dark bg + paper: "fbfbfb", // text-on-dark / card fill + graphite: "323232", // dark card + green: "2e7d32", + red: "c62828", +}; + +// ── Shadow factory (NEVER reuse same object) ──────────────────────────────── +const mkShadow = () => ({ type: "outer", blur: 8, offset: 2, angle: 135, color: "000000", opacity: 0.08 }); + +// ── Helpers ──────────────────────────────────────────────────────────────── +function eyebrow(sl, text, x, y, w, align = "left") { + sl.addText(text, { + x, y, w, h: 0.28, + fontFace: "Calibri", fontSize: 9, bold: true, + color: C.golden, charSpacing: 2, align, margin: 0, + }); +} + +// ═══════════════════════════════════════════════════════════════════════════ +const pres = new pptxgen(); +pres.layout = "LAYOUT_16x9"; // 10" × 5.625" +pres.title = "adiuvAI — Pitch Deck"; +pres.author = "Roberto Musso"; + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 1 — COVER (dark) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + // Logo top-left + sl.addImage({ path: LOGO, x: 0.4, y: 0.28, w: 0.75, h: 0.75 }); + + // Eyebrow top-right + eyebrow(sl, "BETA · GIUGNO 2026", 1.5, 0.35, 8, "right"); + + // Main headline + sl.addText([ + { text: "Incontra la tua nuova", options: { color: C.paper, breakLine: true } }, + { text: "segretaria.", options: { color: C.golden } }, + ], { + x: 0.5, y: 1.3, w: 9, h: 2.0, + fontFace: "Calibri", fontSize: 54, bold: true, align: "center", + }); + + // Subtitle + sl.addText( + "Una AI che legge la tua posta, organizza il tuo lavoro,\ne ogni mattina ti dice cosa conta davvero. Tutto sul tuo computer.", + { + x: 1, y: 3.4, w: 8, h: 1.15, + fontFace: "Calibri", fontSize: 18, color: C.slate, align: "center", + } + ); + + // Footer + sl.addText("adiuvai.com", { + x: 0, y: 5.28, w: 10, h: 0.28, + fontFace: "Calibri", fontSize: 11, color: C.slate, align: "center", margin: 0, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 2 — CHI PARLA (light) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + // Left golden accent bar + sl.addShape(pres.shapes.RECTANGLE, { + x: 0.35, y: 0.45, w: 0.06, h: 4.7, + fill: { color: C.golden }, line: { color: C.golden }, + }); + + eyebrow(sl, "IL FONDATORE", 0.62, 0.5, 5); + + sl.addText("Roberto Musso", { + x: 0.62, y: 0.82, w: 9, h: 0.9, + fontFace: "Calibri", fontSize: 40, bold: true, color: C.ink, margin: 0, + }); + + sl.addText("AI Senior Architect @ Hewlett Packard Enterprise", { + x: 0.62, y: 1.72, w: 9, h: 0.45, + fontFace: "Calibri", fontSize: 18, color: C.slate, margin: 0, + }); + + // Separator + sl.addShape(pres.shapes.LINE, { + x: 0.62, y: 2.3, w: 8.7, h: 0, + line: { color: C.lavender, width: 0.75 }, + }); + + // Bullets + sl.addText([ + { text: "In Hewlett Packard Enterprise dal 2018", options: { bullet: true, breakLine: true } }, + { text: "AI Delivery Team Lead — guido un team di 6 persone", options: { bullet: true, breakLine: true } }, + { text: "Progetto e consegno soluzioni AI enterprise", options: { bullet: true } }, + ], { + x: 0.62, y: 2.48, w: 8.8, h: 1.55, + fontFace: "Calibri", fontSize: 17, color: C.ink, + }); + + // Closing line + sl.addText( + "adiuvAI nasce da quello che faccio ogni giorno: trasformare l\u2019AI in qualcosa che funziona davvero.", + { + x: 0.62, y: 4.25, w: 8.8, h: 0.85, + fontFace: "Calibri", fontSize: 16, italic: true, color: C.slate, margin: 0, + } + ); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 3 — HOOK (dark) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + sl.addText("Quante app hai aperto adesso?", { + x: 0.4, y: 0.5, w: 9.2, h: 1.5, + fontFace: "Calibri", fontSize: 52, bold: true, color: C.paper, align: "center", + }); + + sl.addText("Ottimista: sei.", { + x: 0.4, y: 1.95, w: 9.2, h: 0.65, + fontFace: "Calibri", fontSize: 26, color: C.slate, align: "center", + }); + + // App pills — 8 × (1.0" wide + 0.1" gap) = 8.8" total; start at 0.6 + const apps = ["Gmail", "Outlook", "Teams", "Slack", "Notion", "Trello", "OneDrive", "WhatsApp"]; + const pW = 1.0, pH = 0.38, pGap = 0.115, pY = 2.82, pX0 = 0.58; + + apps.forEach((app, i) => { + const px = pX0 + i * (pW + pGap); + sl.addShape(pres.shapes.RECTANGLE, { + x: px, y: pY, w: pW, h: pH, + fill: { color: "1c1c1c" }, line: { color: C.golden, width: 1 }, + }); + sl.addText(app, { + x: px, y: pY, w: pW, h: pH, + fontFace: "Calibri", fontSize: 12, bold: true, + color: C.golden, align: "center", valign: "middle", margin: 0, + }); + }); + + // Punchline + sl.addText( + "Otto posti dove si nasconde il tuo lavoro importante.\nE tu salti da uno all\u2019altro. Tutto. Il. Giorno.", + { + x: 0.5, y: 3.45, w: 9, h: 1.85, + fontFace: "Calibri", fontSize: 22, bold: true, color: C.golden, align: "center", + } + ); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 4 — PAIN POINTS (light) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + eyebrow(sl, "COSA SUCCEDE DAVVERO", 0.4, 0.25, 6); + + sl.addText("Il tuo lavoro importante ti sta scappando.", { + x: 0.4, y: 0.55, w: 9.2, h: 0.75, + fontFace: "Calibri", fontSize: 30, bold: true, color: C.ink, margin: 0, + }); + + const cards = [ + { icon: "\u2709\uFE0F", title: "Email importanti", body: "Si nascondono tra le newsletter.\nLe leggi tardi o non le leggi affatto." }, + { icon: "\u2705", title: "I tuoi task", body: "Vivono in tre app diverse.\nNe perderai sempre uno." }, + { icon: "\uD83D\uDCDD", title: "Note riunione", body: "Stanno in un doc che non riaprirai mai.\nLe azioni restano senza seguito." }, + ]; + + const cW = 2.93, cH = 2.75, cY = 1.5, cGap = 0.2, cX0 = 0.41; + + cards.forEach((card, i) => { + const cx = cX0 + i * (cW + cGap); + + sl.addShape(pres.shapes.RECTANGLE, { + x: cx, y: cY, w: cW, h: cH, + fill: { color: C.paper }, line: { color: C.lavender, width: 1.5 }, + shadow: mkShadow(), + }); + + // Golden top bar + sl.addShape(pres.shapes.RECTANGLE, { + x: cx, y: cY, w: cW, h: 0.05, + fill: { color: C.golden }, line: { color: C.golden }, + }); + + sl.addText(card.icon, { + x: cx + 0.18, y: cY + 0.18, w: 0.7, h: 0.7, + fontFace: "Segoe UI Emoji", fontSize: 28, margin: 0, + }); + + sl.addText(card.title, { + x: cx + 0.18, y: cY + 0.98, w: cW - 0.3, h: 0.45, + fontFace: "Calibri", fontSize: 16, bold: true, color: C.ink, margin: 0, + }); + + sl.addText(card.body, { + x: cx + 0.18, y: cY + 1.48, w: cW - 0.3, h: 1.1, + fontFace: "Calibri", fontSize: 14, color: C.slate, margin: 0, + }); + }); + + // Punchline + sl.addText("Spoiler: il problema non sei tu. Sono gli strumenti.", { + x: 0.4, y: 4.52, w: 9.2, h: 0.72, + fontFace: "Calibri", fontSize: 19, bold: true, color: C.golden, align: "center", margin: 0, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 5 — TWIST (dark, minimal) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + sl.addText("Non ti serve un altro tool.", { + x: 0.5, y: 0.95, w: 9, h: 1.3, + fontFace: "Calibri", fontSize: 50, bold: false, color: C.paper, align: "center", + }); + + sl.addText("Ti serve una segretaria.", { + x: 0.5, y: 2.35, w: 9, h: 1.6, + fontFace: "Calibri", fontSize: 64, bold: true, color: C.golden, align: "center", + }); + + sl.addText("Una che legge tutto al posto tuo. E ti dice dove guardare.", { + x: 1, y: 4.25, w: 8, h: 0.65, + fontFace: "Calibri", fontSize: 18, color: C.slate, align: "center", + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 6 — SOLUZIONE (light) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + eyebrow(sl, "LA SOLUZIONE", 0.4, 0.22, 5); + + sl.addText("adiuvAI \u2014 la tua segretaria AI.", { + x: 0.4, y: 0.52, w: 9.2, h: 0.85, + fontFace: "Calibri", fontSize: 36, bold: true, color: C.ink, margin: 0, + }); + + sl.addText("Gli altri tool aspettano che tu li usi. adiuvAI lavora per te.", { + x: 0.4, y: 1.38, w: 9.2, h: 0.48, + fontFace: "Calibri", fontSize: 17, italic: true, color: C.slate, margin: 0, + }); + + const cols = [ + { icon: "\uD83D\uDCE7", title: "Legge la tua posta", body: "Filtra, prioritizza, segnala solo ci\u00F2 che richiede la tua attenzione." }, + { icon: "\uD83D\uDCC5", title: "Tiene in ordine l\u2019agenda", body: "Scadenze, impegni, follow-up \u2014 tutto tracciato senza chiederti nulla." }, + { icon: "\uD83D\uDCCB", title: "Prepara il briefing", body: "Ogni mattina un piano chiaro: ecco cosa conta oggi." }, + { icon: "\uD83D\uDE80", title: "Ti aiuta a eseguire", body: "Prepara bozze, organizza documenti, ti accompagna mentre lavori." }, + ]; + + const coW = 2.2, coH = 3.05, coY = 2.0, coGap = 0.17, coX0 = 0.41; + + cols.forEach((col, i) => { + const cx = coX0 + i * (coW + coGap); + + sl.addShape(pres.shapes.RECTANGLE, { + x: cx, y: coY, w: coW, h: coH, + fill: { color: C.paper }, line: { color: C.lavender, width: 1 }, + }); + + // Left golden accent bar + sl.addShape(pres.shapes.RECTANGLE, { + x: cx, y: coY, w: 0.05, h: coH, + fill: { color: C.golden }, line: { color: C.golden }, + }); + + sl.addText(col.icon, { + x: cx + 0.15, y: coY + 0.18, w: 0.55, h: 0.6, + fontFace: "Segoe UI Emoji", fontSize: 26, margin: 0, + }); + + sl.addText(col.title, { + x: cx + 0.1, y: coY + 0.88, w: coW - 0.18, h: 0.7, + fontFace: "Calibri", fontSize: 14, bold: true, color: C.ink, margin: 0, + }); + + sl.addText(col.body, { + x: cx + 0.1, y: coY + 1.65, w: coW - 0.18, h: 1.22, + fontFace: "Calibri", fontSize: 13, color: C.slate, margin: 0, + }); + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 7 — DAILY BRIEF + CAROSELLO (light + screenshot) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + eyebrow(sl, "LA MATTINA, DIVERSA", 0.35, 0.2, 4.3); + + sl.addText("Il briefing del mattino.\nPoi ti prende per mano.", { + x: 0.35, y: 0.5, w: 4.4, h: 1.25, + fontFace: "Calibri", fontSize: 26, bold: true, color: C.ink, margin: 0, + }); + + sl.addText( + "Ogni mattina, un briefing personalizzato: cosa \u00E8 cambiato, cosa scade, cosa conta oggi.", + { + x: 0.35, y: 1.85, w: 4.4, h: 0.75, + fontFace: "Calibri", fontSize: 14, color: C.ink, margin: 0, + } + ); + + sl.addText([ + { text: "Il carosello attivit\u00E0 ti guida scheda per scheda, passo passo.", options: { bullet: true, breakLine: true } }, + { text: "Chatti con lei mentre lavori. Come se ti fosse al fianco.", options: { bullet: true } }, + ], { + x: 0.35, y: 2.7, w: 4.4, h: 0.85, + fontFace: "Calibri", fontSize: 14, color: C.ink, + }); + + // Quote box + sl.addShape(pres.shapes.RECTANGLE, { + x: 0.35, y: 3.68, w: 4.4, h: 1.5, + fill: { color: C.paper }, line: { color: C.golden, width: 2 }, + shadow: mkShadow(), + }); + + sl.addText( + "\u00ABCliente X di solito paga in ritardo.\nLa tua fattura \u00E8 ancora aperta.\u00BB", + { + x: 0.55, y: 3.8, w: 4.0, h: 0.78, + fontFace: "Calibri", fontSize: 14, italic: true, color: C.ink, margin: 0, + } + ); + + sl.addText("\u2014 il Daily Brief, con memoria relazionale", { + x: 0.55, y: 4.65, w: 4.0, h: 0.38, + fontFace: "Calibri", fontSize: 11, color: C.slate, margin: 0, + }); + + // Screenshot right half + sl.addImage({ + path: SCR_H, + x: 4.95, y: 0.18, w: 4.75, h: 5.25, + sizing: { type: "contain", w: 4.75, h: 5.25 }, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 8 — CHAT (light + screenshot) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + sl.addText("Parla con lei.\nIn italiano. In linguaggio naturale.", { + x: 0.35, y: 0.28, w: 4.4, h: 1.2, + fontFace: "Calibri", fontSize: 24, bold: true, color: C.ink, margin: 0, + }); + + const bubbles = [ + "\u00ABQual \u00E8 la prossima attivit\u00E0 su cui concentrarmi?\u00BB", + "\u00ABRiassumi le email arrivate stamattina.\u00BB", + "\u00ABCrea un\u2019attivit\u00E0: richiamare Luca gioved\u00EC.\u00BB", + "\u00ABCosa \u00E8 cambiato sul progetto Patient Portal?\u00BB", + ]; + + bubbles.forEach((bub, i) => { + const by = 1.62 + i * 0.77; + sl.addShape(pres.shapes.RECTANGLE, { + x: 0.35, y: by, w: 4.4, h: 0.6, + fill: { color: C.paper }, line: { color: C.golden, width: 1.5 }, + }); + sl.addText(bub, { + x: 0.5, y: by, w: 4.1, h: 0.6, + fontFace: "Calibri", fontSize: 13, italic: true, color: C.ink, valign: "middle", margin: 0, + }); + }); + + sl.addText( + "Niente prompt engineering. Niente modelli da scegliere.\nL\u2019AI giusta lavora in background.", + { + x: 0.35, y: 4.82, w: 4.4, h: 0.65, + fontFace: "Calibri", fontSize: 12, italic: true, color: C.slate, margin: 0, + } + ); + + // Screenshot right + sl.addImage({ + path: SCR_HC, + x: 4.95, y: 0.18, w: 4.75, h: 5.25, + sizing: { type: "contain", w: 4.75, h: 5.25 }, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 9 — 11 AGENTI (dark) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + eyebrow(sl, "NON \u00C8 UN WRAPPER DI CHATGPT", 0.5, 0.2, 9, "center"); + + sl.addText("Sono 11 agenti AI specializzati che lavorano insieme.", { + x: 0.4, y: 0.5, w: 9.2, h: 0.85, + fontFace: "Calibri", fontSize: 32, bold: true, color: C.paper, align: "center", margin: 0, + }); + + const agents = [ + "Intent Classifier", "Home Agent", "Floating Agent", "Unified Processor", + "Cloud Processor", "Brief Agent", "Setup Agent", "Memory Extractor", + "Memory Miner", "Memory Auditor", "Embeddings", + ]; + + // Layout: row1=[0..3], row2=[4..7], row3=[8..10] centered + const bW = 2.12, bH = 0.48, bGX = 0.17, bGY = 0.18; + const rowDefs = [ + { items: [0,1,2,3], y: 1.58 }, + { items: [4,5,6,7], y: 1.58 + bH + bGY }, + { items: [8,9,10], y: 1.58 + 2 * (bH + bGY) }, + ]; + + rowDefs.forEach(({ items, y }) => { + const rowW = items.length * bW + (items.length - 1) * bGX; + const x0 = (10 - rowW) / 2; + + items.forEach((idx, ci) => { + const bx = x0 + ci * (bW + bGX); + + sl.addShape(pres.shapes.RECTANGLE, { + x: bx, y, w: bW, h: bH, + fill: { color: C.graphite }, line: { color: C.golden, width: 1 }, + }); + sl.addText(agents[idx], { + x: bx, y, w: bW, h: bH, + fontFace: "Calibri", fontSize: 13, bold: true, + color: C.paper, align: "center", valign: "middle", margin: 0, + }); + }); + }); + + sl.addText("Una tua richiesta \u2192 cinque agenti al lavoro.", { + x: 0.5, y: 3.88, w: 9, h: 1.38, + fontFace: "Calibri", fontSize: 28, bold: true, color: C.golden, align: "center", + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 10 — PRIVACY + COMPLIANCE (dark) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + sl.addText("I tuoi dati non lasciano il tuo computer.", { + x: 0.4, y: 0.28, w: 9.2, h: 1.2, + fontFace: "Calibri", fontSize: 42, bold: true, color: C.paper, align: "center", margin: 0, + }); + + sl.addText("Local-first. Non un claim di marketing, un\u2019architettura.", { + x: 0.4, y: 1.52, w: 9.2, h: 0.5, + fontFace: "Calibri", fontSize: 18, color: C.golden, align: "center", margin: 0, + }); + + const pcCards = [ + { icon: "\uD83D\uDD12", title: "Local-first", body: "DB cifrato sul tuo disco.\nNessun server adiuvAI vede i tuoi contenuti." }, + { icon: "\uD83C\uDDEA\uD83C\uDDFA", title: "EU AI Act", body: "Conforme by design,\nnon adattato a posteriori." }, + { icon: "\uD83D\uDEE1\uFE0F", title: "GDPR", body: "Zero trasferimenti a terzi.\nDPA art. 28 con ogni provider LLM." }, + { icon: "\uD83D\uDEAB", title: "No Training", body: "I tuoi dati non addestrano modelli AI.\nZero Data Retention contrattuale." }, + ]; + + const pCW = 4.35, pCH = 1.55, pCGX = 0.25, pCGY = 0.18; + const pCPositions = [ + { x: 0.4, y: 2.18 }, + { x: 0.4 + pCW + pCGX, y: 2.18 }, + { x: 0.4, y: 2.18 + pCH + pCGY }, + { x: 0.4 + pCW + pCGX, y: 2.18 + pCH + pCGY }, + ]; + + pcCards.forEach((card, i) => { + const { x, y } = pCPositions[i]; + + sl.addShape(pres.shapes.RECTANGLE, { + x, y, w: pCW, h: pCH, + fill: { color: C.graphite }, line: { color: C.golden, width: 1 }, + }); + + sl.addText(card.icon + " " + card.title, { + x: x + 0.18, y: y + 0.12, w: pCW - 0.3, h: 0.45, + fontFace: "Calibri", fontSize: 16, bold: true, color: C.golden, margin: 0, + }); + + sl.addText(card.body, { + x: x + 0.18, y: y + 0.62, w: pCW - 0.3, h: 0.82, + fontFace: "Calibri", fontSize: 13, color: C.paper, margin: 0, + }); + }); + + // Footer note + sl.addText("Private by design, not by promise.", { + x: 0, y: 5.27, w: 10, h: 0.28, + fontFace: "Calibri", fontSize: 12, italic: true, color: C.slate, align: "center", margin: 0, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 11 — POSIZIONAMENTO vs COMPETITOR (light) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.canvas }; + + eyebrow(sl, "PERCH\u00C9 NON GLI ALTRI", 0.4, 0.2, 6); + + sl.addText("Motion, Notion AI, Copilot: tutti cloud-first, tutti generalisti.", { + x: 0.4, y: 0.5, w: 9.2, h: 0.72, + fontFace: "Calibri", fontSize: 26, bold: true, color: C.ink, margin: 0, + }); + + // Build table rows — fresh cell objects per row (no shared references) + const hdrOpts = (txt, al = "center") => ({ text: txt, options: { bold: true, fontSize: 13, color: C.void, fill: { color: C.golden }, align: al } }); + const dataOpts = (txt, clr = C.ink, al = "left") => ({ text: txt, options: { fontSize: 13, color: clr, fill: { color: C.paper }, align: al } }); + const emoOpts = (txt) => ({ text: txt, options: { fontSize: 15, fill: { color: C.paper }, align: "center" } }); + + const tableData = [ + [ hdrOpts("Funzionalit\u00E0", "left"), hdrOpts("adiuvAI"), hdrOpts("Motion"), hdrOpts("Notion AI"), hdrOpts("Copilot") ], + [ dataOpts("Locale, dati sul tuo PC"), emoOpts("\u2705"), emoOpts("\u274C"), emoOpts("\u274C"), emoOpts("\u274C") ], + [ dataOpts("EU AI Act compliant"), emoOpts("\u2705"), dataOpts("\u2014", C.slate, "center"), dataOpts("\u2014", C.slate, "center"), emoOpts("\u26A0\uFE0F") ], + [ dataOpts("Legge email + file + chat"), emoOpts("\u2705"), emoOpts("\u26A0\uFE0F"), emoOpts("\u274C"), emoOpts("\u2705") ], + [ dataOpts("Daily Brief proattivo"), emoOpts("\u2705"), emoOpts("\u274C"), emoOpts("\u274C"), emoOpts("\u274C") ], + [ dataOpts("AI invisibile (zero prompt)"), emoOpts("\u2705"), emoOpts("\u274C"), emoOpts("\u274C"), emoOpts("\u274C") ], + ]; + + sl.addTable(tableData, { + x: 0.4, y: 1.38, w: 9.2, h: 3.45, + colW: [3.4, 1.45, 1.45, 1.45, 1.45], + border: { pt: 1, color: C.lavender }, + fontFace: "Calibri", + }); + + sl.addText("adiuvAI \u00E8 locale, proattiva, pensata per chi lavora con dati propri.", { + x: 0.4, y: 5.08, w: 9.2, h: 0.4, + fontFace: "Calibri", fontSize: 16, bold: true, color: C.golden, align: "center", margin: 0, + }); +} + +// ══════════════════════════════════════════════════════════════════ +// SLIDE 12 — CTA / CLOSING (dark) +// ══════════════════════════════════════════════════════════════════ +{ + const sl = pres.addSlide(); + sl.background = { color: C.void }; + + eyebrow(sl, "BETA \u00B7 GIUGNO 2026", 0.5, 0.28, 9, "center"); + + sl.addText("Gli early adopter\nguidano il roadmap.", { + x: 0.4, y: 0.65, w: 9.2, h: 2.0, + fontFace: "Calibri", fontSize: 46, bold: true, color: C.paper, align: "center", margin: 0, + }); + + sl.addText( + "Accesso prioritario, canale diretto con il team,\nvoce in capitolo sulle prossime feature.", + { + x: 1, y: 2.75, w: 8, h: 0.9, + fontFace: "Calibri", fontSize: 17, color: C.slate, align: "center", + } + ); + + // CTA button + sl.addShape(pres.shapes.RECTANGLE, { + x: 3.2, y: 3.78, w: 3.6, h: 0.7, + fill: { color: C.golden }, line: { color: C.golden }, + }); + sl.addText("Iscriviti alla waitlist \u2192", { + x: 3.2, y: 3.78, w: 3.6, h: 0.7, + fontFace: "Calibri", fontSize: 18, bold: true, + color: C.ink, align: "center", valign: "middle", margin: 0, + }); + + sl.addText("adiuvai.com", { + x: 0.5, y: 4.62, w: 9, h: 0.55, + fontFace: "Calibri", fontSize: 28, bold: true, color: C.paper, align: "center", + }); + + // Logo small bottom-left watermark + sl.addImage({ path: LOGO, x: 0.4, y: 4.95, w: 0.55, h: 0.55 }); + + sl.addText("Roberto Musso \u00B7 roby9115@gmail.com", { + x: 1.1, y: 5.12, w: 8.5, h: 0.28, + fontFace: "Calibri", fontSize: 11, color: C.slate, align: "left", margin: 0, + }); +} + +// ── Write output ──────────────────────────────────────────────────────────── +pres.writeFile({ fileName: OUTPUT }) + .then(() => console.log("OK deck generated:", OUTPUT)) + .catch(err => { console.error("ERROR:", err); process.exit(1); }); diff --git a/docs/llm-provider-report.md b/docs/llm-provider-report.md new file mode 100644 index 0000000..610194e --- /dev/null +++ b/docs/llm-provider-report.md @@ -0,0 +1,418 @@ +# Report Provider LLM per adiuvAI — Aprile 2026 + +> Analisi comparativa dei provider per i **11 agenti AI** configurati in `api/.env.example`. Selezione ottimizzata per costo, qualità, latenza e privacy dei dati, con **due mapping distinti**: Production (Zero Data Retention obbligatorio) e Development (cost-efficient). + +--- + +## Architettura — Gli 11 Agenti + +Ogni variabile `LLM_MODEL_*` in `api/.env.example` controlla un agente con profilo d'uso specifico. Analisi dei requisiti emersa dall'ispezione del codice in `api/app/agents/`, `api/app/core/` e `api/app/memory/`. + +| # | Env Var | Agente | Tool Calling | Latenza | Qualità | Volume/utente | Real-time? | +|---|---------|--------|--------------|---------|---------|--------------|------------| +| 1 | `LLM_MODEL_CLASSIFIER` | **Intent Classifier** — smista i messaggi del floating panel verso task/project/note/timeline | No, output JSON | Alta (<200 ms) | Bassa (output deterministico) | Alto | ✓ Sì | +| 2 | `LLM_MODEL_HOME_AGENT` | **Home Agent** — chat principale con tutti i tool (CRUD task/project/note) | Multi-turno (≤6 step) | Alta (<3 s perceived) | Alta (user-facing) | Alto | ✓ Sì, WS stream | +| 3 | `LLM_MODEL_FLOATING_AGENT` | **Floating Agent** — chat contestuale da task/project/note | Multi-turno (≤6 step) | Alta | Media–alta | Alto | ✓ Sì, WS stream | +| 4 | `LLM_MODEL_UNIFIED_PROCESSOR` | **Unified Processor** — processa file del filesystem locale | Tool loop (≤12 step) | Bassa (batch) | Media | Medio/occasionale | ✗ Background | +| 5 | `LLM_MODEL_CLOUD_PROCESSOR` | **Cloud Processor** — fetch e processing di Gmail/Teams/Outlook | Tool loop (≤12 step) | Bassa | Media | Schedulato | ✗ Background | +| 6 | `LLM_MODEL_BRIEF_AGENT` | **Brief Agent** — daily brief home + project (streaming, read-only tool) | Singolo step, tool read-only | Alta (<4 s) | Alta (prosa curata) | Medio | ✓ Sì | +| 7 | `LLM_MODEL_SETUP_AGENT` | **Setup Agent** — journey conversazionale per costruire `AgentConfig` JSON | Multi-turno (≤15) | Media | Alta (UX critica) | Basso (una tantum) | ✓ Sì, WS | +| 8 | `LLM_MODEL_MEMORY_EXTRACTOR` | **Memory Extractor** — pipeline Mem0 extract+decide (2 call/turno) | No, JSON strutturato | Bassa (off-path) | Bassa (filtrato a valle) | Alto (ogni turno chat) | ✗ Background | +| 9 | `LLM_MODEL_MEMORY_MINER` | **Memory Miner** — pattern mining orario su storia episodica (Power+) | No | Bassa | Media | Orario (Power+) | ✗ Cron | +| 10 | `LLM_MODEL_MEMORY_AUDITOR` | **Memory Auditor** — audit settimanale: contraddizioni + canonicalizzazione relazioni | No, reasoning su fatti | Bassa | Alta (richiede reasoning) | Settimanale | ✗ Cron | +| 11 | `LLM_EMBED_MODEL` | **Embeddings** — vettori 1536-dim per ricerca semantica (LanceDB/Qdrant) | — | Media | Deterministico | Alto | ✓ In-request | + +> **Nota architetturale (Processors):** Il Batch API dei provider LLM **non è utilizzabile** per Unified e Cloud Processor: il loop tool-calling richiede risultati sincroni dal client Electron via WebSocket. Si usa **API Standard** a prezzi di listino. + +--- + +## Conformità — Policy Privacy dei Provider + +Per Production è richiesto un **strict Zero Data Retention** (ZDR): nessuna conservazione prompt/response, nessun logging, nessun uso per training — garantito contrattualmente. Per Development è sufficiente l'opt-out di default dal training. + +| Provider | Sede | ZDR strict (prod) | Opt-out training (dev) | Note | +|----------|------|:-----------------:|:----------------------:|------| +| 🇺🇸 OpenAI | USA | ✓ con **ZDR addendum Enterprise** | ✓ default API | Standard API: 30gg retention logs | +| 🇺🇸 Anthropic | USA | ✓ con **Enterprise ZDR** | ✓ default API | 30gg retention su standard tier | +| 🇺🇸 Google Vertex AI | USA | ✓ **contrattuale** (Vertex, non AI Studio) | ✓ paid tier | Free AI Studio usa dati per training | +| 🇫🇷 Mistral | Francia (EU) | ✓ **ZDR disponibile** | ✓ default | GDPR-native, ottimo per EU residency | +| 🇺🇸 Groq | USA | ✓ **via DPA dedicato** | ✓ default | Cloud inference Llama/Qwen | +| 🇺🇸 Cerebras | USA | ✓ **nessuna conservazione by default** | ✓ | ZDR out-of-the-box — il più rigoroso | +| 🇺🇸 Voyage AI | USA | ✓ ZDR enterprise | ✓ | Embeddings only | +| 🇨🇳 DeepSeek | Cina | ✗ | ⚠️ opt-out limitato, dati in Cina | **Solo Dev, con dati sintetici** | +| 🇨🇳 Zhipu (GLM) | Cina | ✗ | ⚠️ non verificabile | **Solo Dev** | + +--- + +## Confronto Modelli — Miglior Modello per Agente + +Prezzi in USD per milione di token (MTok), aggiornati Aprile 2026. + +### 1. Intent Classifier +*Output JSON deterministico, latenza critica, volume alto* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| OpenAI | `GPT-4.1 Nano` | $0.10 | $0.40 | ✓ ent | Veloce, JSON mode affidabile | +| **Google Vertex** ⭐ | `Gemini 2.5 Flash-Lite` | **$0.10** | **$0.40** | ✓ | **Migliore prezzo+ZDR+latenza** | +| Anthropic | `Claude Haiku 4.5` | $1.00 | $5.00 | ✓ ent | Overkill per pura classificazione | +| Groq | `Llama 3.1 8B` | $0.05 | $0.08 | ✓ DPA | Economico, 840 TPS | +| Cerebras | `Llama 3.1 8B` | $0.10 | $0.10 | ✓ | ZDR by default, velocissimo | + +### 2. Home Agent +*Multi-turno + tool calling completo + streaming* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **Anthropic** ⭐ | `Claude Sonnet 4.6` | $3.00 | $15.00 | ✓ ent | **Top tool use**, caching -90%, 1M ctx | +| OpenAI | `GPT-4.1` | $2.00 | $8.00 | ✓ ent | Solido, JSON mode, 1M ctx | +| Google Vertex | `Gemini 2.5 Flash` | $0.30 | $2.50 | ✓ | Miglior rapporto Q/P per prod | +| Mistral | `Mistral Medium 3` | $1.00 | $3.00 | ✓ | EU residency | +| Groq | `Llama 3.3 70B` | $0.59 | $0.79 | ✓ DPA | Tool calling inferiore ai proprietari | + +### 3. Floating Agent +*Single+multi-turno, contestuale, più compatto del Home* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| OpenAI | `GPT-4.1 Mini` | $0.40 | $1.60 | ✓ ent | Bilanciato | +| **Anthropic** ⭐ | `Claude Haiku 4.5` | $1.00 | $5.00 | ✓ ent | **Tool use affidabile, bassa latenza** | +| Google Vertex | `Gemini 2.5 Flash-Lite` | $0.10 | $0.40 | ✓ | Economico; qualità tool inferiore a Haiku | +| Mistral | `Mistral Small 3.1` | $0.20 | $0.60 | ✓ | EU | + +### 4. Unified Processor (locale) +*Batch, multi-turno (≤12), qualità estrazione importa* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1 Mini` | **$0.40** | **$1.60** | ✓ ent | **Tool loop affidabile, costo contenuto** | +| Anthropic | `Claude Sonnet 4.6` | $3.00 | $15.00 | ✓ ent | Qualità top se budget permette | +| Google Vertex | `Gemini 2.5 Flash` | $0.30 | $2.50 | ✓ | Valida alternativa, input economico | +| Mistral | `Mistral Large 3` | $2.00 | $6.00 | ✓ | EU residency | + +### 5. Cloud Processor (Gmail/Teams/Outlook) +*Batch, multi-turno (≤12), dati sensibili* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1 Mini` | **$0.40** | **$1.60** | ✓ ent | **Robusto su email parsing** | +| Anthropic | `Claude Sonnet 4.6` | $3.00 | $15.00 | ✓ ent | Miglior reasoning su thread email | +| Google Vertex | `Gemini 2.5 Flash` | $0.30 | $2.50 | ✓ | 1M context utile per thread lunghi | + +### 6. Brief Agent (daily brief) +*Singolo step, prosa curata, read-only tool* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1 Mini` | **$0.40** | **$1.60** | ✓ ent | **Prosa di qualità, streaming affidabile** | +| Anthropic | `Claude Haiku 4.5` | $1.00 | $5.00 | ✓ ent | Prosa eccellente, più costoso | +| Google Vertex | `Gemini 2.5 Flash` | $0.30 | $2.50 | ✓ | Alternativa economica | +| Mistral | `Mistral Small 3.1` | $0.20 | $0.60 | ✓ | Economico con EU residency | + +### 7. Setup Agent (journey di configurazione) +*Conversazione multi-turno (≤15), JSON finale, UX critica* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **Anthropic** ⭐ | `Claude Sonnet 4.6` | **$3.00** | **$15.00** | ✓ ent | **Miglior instruction-following, JSON affidabile** | +| OpenAI | `GPT-4.1` | $2.00 | $8.00 | ✓ ent | Eccellente bilanciamento | +| Google Vertex | `Gemini 2.5 Pro` | $1.25 | $10.00 | ✓ | Reasoning solido | + +> Volume bassissimo (≈2 sessioni/mese per utente): il costo è trascurabile anche col modello premium. + +### 8. Memory Extractor (Mem0 extract+decide) +*2 call/turno, JSON strutturato, deterministico, off request-path* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1 Nano` | **$0.10** | **$0.40** | ✓ ent | **Cheapest OpenAI, JSON mode affidabile** | +| Google Vertex | `Gemini 2.5 Flash-Lite` | $0.10 | $0.40 | ✓ | Pari prezzo, valido | +| Anthropic | `Claude Haiku 4.5` | $1.00 | $5.00 | ✓ ent | Troppo costoso per volume alto | + +### 9. Memory Miner (cron orario, Power+) +*Pattern mining su episodi, input medio, occasionale* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1 Mini` | **$0.40** | **$1.60** | ✓ ent | **Reasoning sufficiente per pattern detection** | +| Google Vertex | `Gemini 2.5 Flash` | $0.30 | $2.50 | ✓ | Buona alternativa | +| Anthropic | `Claude Haiku 4.5` | $1.00 | $5.00 | ✓ ent | Qualità superiore, costo +2x | + +### 10. Memory Auditor (cron settimanale) +*Reasoning per contraddizioni + canonicalizzazione, rarissimo* + +| Provider | Modello | In $/MTok | Out $/MTok | ZDR | Note | +|----------|---------|----------|-----------|:---:|------| +| **OpenAI** ⭐ | `GPT-4.1` | **$2.00** | **$8.00** | ✓ ent | **Reasoning robusto, volume trascurabile** | +| Anthropic | `Claude Sonnet 4.6` | $3.00 | $15.00 | ✓ ent | Alternativa premium | +| Google Vertex | `Gemini 2.5 Pro` | $1.25 | $10.00 | ✓ | Ottimo reasoning | + +### 11. Embeddings +*Semantic search, 1536-dim, volume alto* + +| Provider | Modello | $/MTok | Dim | ZDR | Note | +|----------|---------|--------|-----|:---:|------| +| **OpenAI** ⭐ | `text-embedding-3-small` | **$0.02** | 1536 | ✓ ent | **Standard de facto, già in uso (LanceDB 1536-dim)** | +| Voyage AI | `voyage-3.5-lite` | $0.02 | 1024 | ✓ | Qualità superiore ma richiede reindex | +| Google Vertex | `Gemini Embedding` | $0.15 | variabile | ✓ | 7.5x più costoso, nessun vantaggio | + +--- + +## 🔒 Mapping Production (Zero Data Retention obbligatorio) + +Tutti i provider selezionati hanno ZDR contrattualmente garantito. Prevalgono qualità e affidabilità; il costo è ottimizzato entro il vincolo ZDR. + +| # | Agente | Provider | Modello | Razionale | +|---|--------|----------|---------|-----------| +| 1 | Classifier | **OpenAI** | `gpt-4.1-nano` | $0.10/$0.40, JSON mode affidabile, stesso contratto ZDR del resto OpenAI | +| 2 | Home Agent | **Anthropic** | `claude-sonnet-4-6` | Miglior tool calling del mercato; caching -90% riduce il costo; esperienza chat premium | +| 3 | Floating Agent | **Anthropic** | `claude-haiku-4-5` | Tool calling affidabile + bassa latenza; qualità coerente con Home Agent | +| 4 | Unified Processor | **OpenAI** | `gpt-4.1-mini` | Tool loop affidabile a costo contenuto; critico visto che il loop moltiplica le call | +| 5 | Cloud Processor | **OpenAI** | `gpt-4.1-mini` | Stesso profilo del locale; parsing di email/chat consolidato | +| 6 | Brief Agent | **OpenAI** | `gpt-4.1-mini` | Prosa curata, streaming, read-only tools — ottimo bilanciamento | +| 7 | Setup Agent | **Anthropic** | `claude-sonnet-4-6` | Journey conversazionale critica per UX; volume bassissimo giustifica il premium | +| 8 | Memory Extractor | **OpenAI** | `gpt-4.1-nano` | 2 call per turno chat: servono i prezzi più bassi con JSON mode | +| 9 | Memory Miner | **OpenAI** | `gpt-4.1-mini` | Cron orario su Power+: reasoning sufficiente, costo contenuto | +| 10 | Memory Auditor | **OpenAI** | `gpt-4.1` | Reasoning più avanzato per contraddizioni; frequenza settimanale = costo trascurabile | +| 11 | Embeddings | **OpenAI** | `text-embedding-3-small` | Già in uso, 1536-dim compatibile con schema LanceDB/Qdrant | + +### Valori `.env` — Production + +```bash +# Default fallback +LLM_MODEL=gpt-4.1-mini +LLM_EMBED_MODEL=text-embedding-3-small + +# Per-agent overrides (LiteLLM model IDs) +LLM_MODEL_CLASSIFIER=gpt-4.1-nano +LLM_MODEL_HOME_AGENT=anthropic/claude-sonnet-4-6 +LLM_MODEL_FLOATING_AGENT=anthropic/claude-haiku-4-5 +LLM_MODEL_UNIFIED_PROCESSOR=gpt-4.1-mini +LLM_MODEL_CLOUD_PROCESSOR=gpt-4.1-mini +LLM_MODEL_BRIEF_AGENT=gpt-4.1-mini +LLM_MODEL_SETUP_AGENT=anthropic/claude-sonnet-4-6 +LLM_MODEL_MEMORY_EXTRACTOR=gpt-4.1-nano +LLM_MODEL_MEMORY_MINER=gpt-4.1-mini +LLM_MODEL_MEMORY_AUDITOR=gpt-4.1 +``` + +> **2 API key richieste**: OpenAI (Enterprise + ZDR addendum) e Anthropic (Commercial + ZDR addendum). Vedi sezione **[Come attivare ZDR](#come-attivare-zdr-con-openai-e-anthropic)** per la procedura contrattuale. + +--- + +## 💰 Mapping Development (cost-efficient, ZDR non richiesto) + +Priorità: costo minimo e velocità di iterazione. **Niente dati utente reali in questo ambiente** — solo dati sintetici o mock. Nessun vincolo ZDR consente di includere Groq, Cerebras e opzionali DeepSeek. + +| # | Agente | Provider | Modello | Razionale | +|---|--------|----------|---------|-----------| +| 1 | Classifier | **Groq** | `llama-3.1-8b-instant` | $0.05/$0.08: il più economico con 840 TPS | +| 2 | Home Agent | **Google AI Studio** | `gemini-2.5-flash` | 6–7x meno di Sonnet, tool use nativo, 1M ctx | +| 3 | Floating Agent | **Google AI Studio** | `gemini-2.5-flash-lite` | $0.10/$0.40 sufficiente per single-turn | +| 4 | Unified Processor | **Google AI Studio** | `gemini-2.5-flash` | Tool loop funzionante a costo minimo | +| 5 | Cloud Processor | **DeepSeek** | `deepseek-chat` ($0.28/$0.42) | Costo minimo per batch con dati sintetici | +| 6 | Brief Agent | **Groq** | `llama-3.1-8b-instant` | $0.05/$0.08, prosa accettabile per QA | +| 7 | Setup Agent | **Google AI Studio** | `gemini-2.5-flash` | Conversazione decente a costo minimo | +| 8 | Memory Extractor | **Groq** | `llama-3.1-8b-instant` | JSON extraction funziona con fallback retry | +| 9 | Memory Miner | **Groq** | `llama-3.3-70b-versatile` | Pattern mining richiede reasoning; 70B a $0.59/$0.79 | +| 10 | Memory Auditor | **Google AI Studio** | `gemini-2.5-flash` | Reasoning accettabile, quasi gratis a scala dev | +| 11 | Embeddings | **OpenAI** | `text-embedding-3-small` | Stesso dim del prod (1536) — evita reindex al promote | + +### Valori `.env` — Development + +```bash +# Default fallback +LLM_MODEL=gemini/gemini-2.5-flash +LLM_EMBED_MODEL=text-embedding-3-small + +# Per-agent overrides +LLM_MODEL_CLASSIFIER=groq/llama-3.1-8b-instant +LLM_MODEL_HOME_AGENT=gemini/gemini-2.5-flash +LLM_MODEL_FLOATING_AGENT=gemini/gemini-2.5-flash-lite +LLM_MODEL_UNIFIED_PROCESSOR=gemini/gemini-2.5-flash +LLM_MODEL_CLOUD_PROCESSOR=deepseek/deepseek-chat +LLM_MODEL_BRIEF_AGENT=groq/llama-3.1-8b-instant +LLM_MODEL_SETUP_AGENT=gemini/gemini-2.5-flash +LLM_MODEL_MEMORY_EXTRACTOR=groq/llama-3.1-8b-instant +LLM_MODEL_MEMORY_MINER=groq/llama-3.3-70b-versatile +LLM_MODEL_MEMORY_AUDITOR=gemini/gemini-2.5-flash +``` + +> ⚠️ **Non immettere dati utente reali**. Gli embeddings restano `text-embedding-3-small` per non dover reindicizzare passando in Production (stesso schema 1536-dim). + +--- + +## Simulazione — Costo Mensile per Utente + +Utilizzo tipico: 500 Home, 300 Floating, 210 Brief, 100 Unified Processor, 80 Cloud Processor, 10 Setup turn (≈2 sessioni), 1500 Memory Extractor turn, 720 Miner (30gg × 24h Power+), 4 Auditor, 1000 embeddings. + +### Production + +| Agente | Modello | In tok | Out tok | $/mese | +|--------|---------|--------|---------|--------| +| Classifier | GPT-4.1 Nano | 150K | 30K | $0.027 | +| Home Agent | Sonnet 4.6 | 1M | 500K | $10.50 | +| Floating | Haiku 4.5 | 150K | 90K | $0.60 | +| Unified Processor | GPT-4.1 Mini | 300K | 200K | $0.44 | +| Cloud Processor | GPT-4.1 Mini | 240K | 160K | $0.35 | +| Brief Agent | GPT-4.1 Mini | 315K | 105K | $0.29 | +| Setup Agent | Sonnet 4.6 | 40K | 5K | $0.20 | +| Memory Extractor | GPT-4.1 Nano | 750K | 150K | $0.14 | +| Memory Miner | GPT-4.1 Mini | 1.4M | 150K | $0.80 | +| Memory Auditor | GPT-4.1 | 20K | 5K | $0.08 | +| Embeddings | text-embedding-3-small | 500K | — | $0.01 | +| | | | **Totale Production** | **~$13.48/utente/mese** | + +> Con prompt caching Anthropic al 90% sui system prompt ripetuti, Home Agent scende a ~$4–5/mese → totale **~$7–8/utente/mese**. + +### Development (dev team ≈ 100 sessioni test/mese totali, non per utente) + +| Agente | Modello | $/mese totali | +|--------|---------|--------------| +| Classifier | Groq Llama 3.1 8B | $0.004 | +| Home Agent | Gemini 2.5 Flash | $0.58 | +| Floating | Gemini 2.5 Flash-Lite | $0.04 | +| Unified Processor | Gemini 2.5 Flash | $0.09 | +| Cloud Processor | DeepSeek Chat | $0.13 | +| Brief Agent | Groq Llama 3.1 8B | $0.02 | +| Setup Agent | Gemini 2.5 Flash | $0.02 | +| Memory Extractor | Groq Llama 3.1 8B | $0.05 | +| Memory Miner | Groq Llama 3.3 70B | $0.35 | +| Memory Auditor | Gemini 2.5 Flash | $0.02 | +| Embeddings | text-embedding-3-small | $0.01 | +| | **Totale Dev team** | **~$1.35/mese** | + +--- + +## Motivazioni — Decisioni Chiave + +### 🔒 Perché questa separazione Production/Development + +I dati utente di adiuvAI sono E2E-encrypted, ma i prompt agentici contengono metadati operativi (titoli task, nomi progetti, contesto chat) che fluiscono in chiaro verso il LLM provider. Per Production, ZDR contrattuale è non-negoziabile. In Development si usano dati sintetici, quindi i provider più economici senza garanzie ZDR sono perfetti per iterare rapidamente senza bruciare budget. + +### 💬 Claude Sonnet 4.6 per Home Agent (prod) vs Gemini Flash (dev) + +Home Agent è il touchpoint principale: la qualità del tool calling determina la percezione del prodotto. Sonnet 4.6 è il benchmark su tool use. Il caching di Anthropic (-90% sui system prompt) rende il costo sostenibile a scala. In dev, Gemini 2.5 Flash costa **20x meno** con tool calling sufficiente per validare flussi, test di regressione e UI. + +### ⚙️ GPT-4.1 Mini per entrambi i Processor + +Unified e Cloud Processor sono l'unica superficie dove il **tool loop moltiplica il costo** (≤12 turni per file). Il prezzo medio deve essere basso **e** la qualità tool calling alta, altrimenti errori in cascata. GPT-4.1 Mini è lo sweet spot: tool calling OpenAI è robusto, il prezzo è 5x inferiore a Sonnet. Si sconsiglia Groq qui: la qualità tool calling di Llama introduce retry che annullano il risparmio. + +### 🧠 Stratificazione Memory Agents + +- **Extractor** (2 call/turno, volume altissimo) → Nano (cheapest) +- **Miner** (orario Power+, reasoning su pattern) → Mini (compromesso) +- **Auditor** (settimanale, reasoning avanzato) → GPT-4.1 full (il volume azzera il premium) + +Ogni tier di memory ha un profilo costo/qualità diverso: collassarli tutti su un unico modello spreca o sul basso (Auditor poco accurato) o sull'alto (Extractor 10x più caro del necessario). + +### 🇪🇺 Perché non Mistral in prod di default + +Mistral è un'ottima alternativa EU-residency, ma Sonnet 4.6 e GPT-4.1 hanno tool calling ancora superiore nei benchmark di Aprile 2026. Se la priorità diventa **data residency EU** (clienti enterprise europei, GDPR stretto), raccomando uno switch mirato: +- Home Agent → `mistral/mistral-medium-3` +- Background processor → `mistral/mistral-large-3` + +### 🚫 Cina esclusa da Production + +DeepSeek e GLM offrono costi imbattibili ma i dati risiedono in Cina senza garanzie ZDR verificabili per utenti internazionali. **Accettabili in Development solo con dati sintetici**. + +### ⚡ Groq e Cerebras come alternative budget + +In Development, Groq domina per pricing + velocità (394–840 TPS). In Production sono qualificati ZDR (tramite DPA) ma la qualità tool calling di Llama rimane inferiore ai modelli proprietari su flussi multi-turno complessi. Cerebras è strict ZDR by default ma il catalogo modelli è limitato. + +--- + +## Come attivare ZDR con OpenAI e Anthropic + +**Cosa significa ZDR concretamente:** nessuna conservazione di prompt/output oltre la durata della richiesta, nessun logging di contenuti da parte del provider, nessun uso per training o fine-tuning, abuse monitoring basato su metadati anziché contenuti. Sul tier API standard, invece, OpenAI e Anthropic conservano input/output per **30 giorni** a fini di abuse detection — motivo per cui serve il contratto ZDR esplicito. + +### 🔵 OpenAI — Enterprise Privacy / ZDR Addendum + +**Chi ne ha diritto:** clienti con Enterprise Agreement. Per API a basso volume si può comunque richiedere un **Business Associate Agreement** o **Enterprise Privacy Addendum** senza passare a ChatGPT Enterprise. + +**Procedura:** +1. Scrivere a **sales@openai.com** (oppure compilare il form su [openai.com/enterprise](https://openai.com/enterprise/)) indicando: + - Ragione sociale, sede legale, P.IVA, DPO/privacy contact + - Caso d'uso (per adiuvAI: "agentic SaaS con E2E-encrypted user data, API backend") + - Volume stimato mensile (token o $) — utile per pricing + - Modelli usati (`gpt-4.1`, `gpt-4.1-mini`, `gpt-4.1-nano`, `text-embedding-3-small`) + - Requisito esplicito: **"Zero Data Retention (0-day retention)"** e disabilitazione abuse monitoring sul contenuto +2. OpenAI invia **Commercial Agreement + Data Processing Addendum (DPA) + Zero Data Retention Addendum**. +3. Firmare via DocuSign. Tempo medio: **2–4 settimane** dalla prima mail al contratto attivo. +4. OpenAI abilita ZDR a livello di **Organization ID** dell'API — non serve modificare il codice, vale per tutte le chiamate future. +5. Verifica in dashboard: `platform.openai.com` → Settings → Organization → Data Controls. Deve apparire "Zero Data Retention: Enabled". + +**Costo:** l'Enterprise non ha prezzo pubblico; a bassi volumi si può ottenere senza commitment minimo (talvolta con un modesto uplift sulla tariffa API). + +**Documenti utili:** [OpenAI Enterprise Privacy](https://openai.com/enterprise-privacy/), [OpenAI DPA](https://openai.com/policies/data-processing-addendum/), [OpenAI API Data Usage](https://platform.openai.com/docs/models/how-we-use-your-data). + +### 🟣 Anthropic — Commercial Terms + Zero Retention Addendum + +**Chi ne ha diritto:** qualsiasi cliente commerciale. Anthropic è più flessibile di OpenAI: ZDR viene concesso anche a volumi contenuti tramite un addendum al contratto standard. + +**Procedura:** +1. Scrivere a **sales@anthropic.com** (oppure via il form [anthropic.com/contact-sales](https://www.anthropic.com/contact-sales)) indicando: + - Ragione sociale, sede legale, P.IVA + - Caso d'uso e modelli (`claude-sonnet-4-6`, `claude-haiku-4-5`) + - Volume stimato mensile + - Richiesta esplicita: **"Zero Retention Addendum to the Commercial Terms"** + - Se applicabile: GDPR DPA, BAA (per HIPAA) +2. Anthropic invia **Commercial Agreement + DPA + Zero Retention Addendum** (clausola dedicata). +3. Firma via DocuSign. Tempo medio: **1–3 settimane**. +4. Attivazione sull'**Organization** del Claude Console. Verifica in [console.anthropic.com](https://console.anthropic.com) → Settings → Organization → Privacy. +5. Dal contratto attivo: 0-day retention di prompt/response, abuse monitoring basato solo su metadati. + +**Costo:** nessun uplift in genere; il contratto ZDR è incluso nel Commercial Agreement. + +**Documenti utili:** [Anthropic Privacy Policy](https://www.anthropic.com/legal/privacy), [Anthropic Commercial Terms](https://www.anthropic.com/legal/commercial-terms), [Anthropic Trust Center](https://trust.anthropic.com) per SOC 2 / ISO 27001. + +### Checklist pre-firma (entrambi) + +Prima di firmare verifica che il contratto copra: + +- [ ] **Zero retention** esplicita (0 giorni, non "short retention" che può significare 24h o 72h) +- [ ] **No training** sui prompt/output (default API, confermare per scritto) +- [ ] **Abuse monitoring** basato su metadati, non contenuto (altrimenti il provider legge comunque i prompt) +- [ ] **Sub-processor list** consultabile (subcontractor del provider: datacenter, CDN, ecc.) +- [ ] **DPA art. 28 GDPR** firmato contestualmente (obbligatorio se processi dati di utenti EU) +- [ ] **Breach notification SLA** ≤ 72 ore (requisito GDPR) +- [ ] **Data residency** — chiedere conferma region processing (US vs EU). Per adiuvAI può valere la pena pretendere routing EU se la clientela è europea +- [ ] **Audit right** — possibilità di richiedere audit indipendente (rilevante per clienti enterprise propri) + +### Timeline realistica end-to-end + +| Fase | Durata | +|------|--------| +| Primo contatto sales + NDA | 3–5 giorni | +| Legal review interno contratti provider | 1–2 settimane | +| Negoziazione clausole sensibili (residency, audit, pricing) | 1–2 settimane | +| Firma DocuSign + attivazione ZDR su Org ID | 2–3 giorni | +| **Totale** | **4–7 settimane** per provider | + +> 💡 **Consiglio pratico:** parti **in parallelo** con sales@openai.com e sales@anthropic.com lo stesso giorno. Il processo è indipendente e avere entrambi i contratti attivi contemporaneamente è indispensabile per il mapping proposto. + +--- + +## Note & Fonti + +Prezzi aggiornati ad Aprile 2026. Verificare sempre le pagine ufficiali prima di decisioni finali — il mercato LLM cambia mensilmente. + +**Fonti:** +- [OpenAI API Pricing](https://openai.com/api/pricing/) +- [OpenAI Enterprise Privacy + ZDR](https://openai.com/enterprise-privacy/) +- [Anthropic Claude Models](https://platform.claude.com/docs/en/docs/about-claude/models) +- [Anthropic ZDR](https://www.anthropic.com/legal/privacy) +- [Google Vertex AI Pricing](https://cloud.google.com/vertex-ai/pricing) +- [Google Vertex Data Governance](https://cloud.google.com/vertex-ai/docs/generative-ai/data-governance) +- [Mistral AI Pricing](https://mistral.ai/pricing) +- [Mistral Privacy Policy](https://legal.mistral.ai/terms/privacy-policy) +- [Groq On-Demand Pricing](https://groq.com/pricing) +- [Cerebras Privacy Policy](https://www.cerebras.ai/policies) +- [DeepSeek API Pricing](https://api-docs.deepseek.com/quick_start/pricing/) +- [LiteLLM Supported Models](https://docs.litellm.ai/docs/providers) +- [Best AI for Tool Calling 2026](https://llm-stats.com/leaderboards/best-ai-for-tool-calling) +- [AI Cost Board — LLM Pricing 2026](https://aicostboard.com/blog/posts/llm-api-pricing-comparison-2026) + +--- + +*Report generato per adiuvAI · Aprile 2026 · Aggiornato per coprire tutti gli 11 agenti di `api/.env.example` con mapping separati Production/Development.* diff --git a/docs/plan-brief-agent.md b/docs/plan-brief-agent.md index 4cfa17a..810c854 100644 --- a/docs/plan-brief-agent.md +++ b/docs/plan-brief-agent.md @@ -339,16 +339,16 @@ as fallback. - None (external config via MCP). **Tasks** -- [ ] Use `mcp__langfuse-docs__searchLangfuseDocs` to confirm the text-prompt +- [x] Use `mcp__langfuse-docs__searchLangfuseDocs` to confirm the text-prompt variable syntax (`{{variable}}`) and that `label="production"` is the label read by `get_prompt_or_fallback`. -- [ ] Use `mcp__langfuse__createTextPrompt` to create `home_brief` with the +- [x] Use `mcp__langfuse__createTextPrompt` to create `home_brief` with the content from the "Improved prompts → home_brief" section above. Set label to `production`. Variables: `language`, `today`. -- [ ] Use `mcp__langfuse__createTextPrompt` to create `project_brief` with the +- [x] Use `mcp__langfuse__createTextPrompt` to create `project_brief` with the content from the "Improved prompts → project_brief" section above. Set label to `production`. Variables: `language`, `today`, `project_id`. -- [ ] Use `mcp__langfuse__getPrompt` to round-trip both prompts and verify the +- [x] Use `mcp__langfuse__getPrompt` to round-trip both prompts and verify the raw template matches what was sent. **Acceptance** @@ -376,16 +376,16 @@ brief agent over WS, and the `DAILY_BRIEF_PROMPT` constant is deleted. - `adiuvAI/src/main/router/index.ts` **Tasks** -- [ ] Add `WsBriefRequest` frame shape to shared types, mirroring the API +- [x] Add `WsBriefRequest` frame shape to shared types, mirroring the API `WsBriefRequest` schema. -- [ ] In `backend-client.ts`, add `sendBriefRequest(mode, projectId?, callbacks, requestId?)` +- [x] In `backend-client.ts`, add `sendBriefRequest(mode, projectId?, callbacks, requestId?)` modeled on `sendHomeRequest`. It sends `{type:"brief_request", mode, project_id}`. -- [ ] In `orchestrator.ts`: +- [x] In `orchestrator.ts`: - Delete the `DAILY_BRIEF_PROMPT` constant (and the `langSuffix` hack — the backend now owns language injection). - `generateAndCacheBrief()` → call `client.sendBriefRequest("home", undefined, {...})`. - `dailyBrief()` → call `client.sendBriefRequest("home", undefined, {...}, requestId)`. -- [ ] `router/index.ts`: no signature change — only the underlying orchestrator +- [x] `router/index.ts`: no signature change — only the underlying orchestrator was rewired. Leave `ai.dailyBrief` mutation as-is. **Acceptance** diff --git a/skills-lock.json b/skills-lock.json index 9ab8e21..c1a8119 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -6,6 +6,11 @@ "sourceType": "github", "computedHash": "2621a44fbd9fc2636953d1e6e39e5faeed995f7fb958ec12cc98a2f0576f6fa7" }, + "langfuse": { + "source": "langfuse/skills", + "sourceType": "github", + "computedHash": "a72c15d6329867b84c4e7456f4e04d8c06ce5298d1d0068dbe864b8b00fb406c" + }, "remotion-best-practices": { "source": "remotion-dev/skills", "sourceType": "github",