synops/docs/features/ai_verktoy.md
vegard bca0ff1deb Fullfører oppgave 18.2: AI-prosessering endepunkt
POST /intentions/ai_process med source_node_id, ai_preset_id og
direction (node_to_tool / tool_to_node).

Endepunktet validerer input, sjekker at kilde-node og AI-preset
finnes, verifiserer skrivetilgang for tool_to_node-retning, og
legger en ai_process-jobb i køen.

Jobb-handleren (ai_process.rs) henter kilde-content og preset-prompt,
mapper modellprofil → LiteLLM-alias (flash → sidelinja/rutine,
standard → sidelinja/resonering), kaller AI Gateway, og logger
forbruk i både ai_usage_log og resource_usage_log.

Direction-logikk (opprett ny node vs. oppdater eksisterende)
implementeres i oppgave 18.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:24:31 +00:00

250 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature: AI-verktøy (Drag-and-drop tekstbehandling)
**Filsti:** `docs/features/ai_verktoy.md`
## 1. Konsept
Et frittstående verktøy-panel på arbeidsflaten for AI-drevet
tekstbehandling. I stedet for en ✨-knapp inne i editoren er AI-et
et eget verktøy som lever side ved side med chat, artikkelverktøy,
kanban og andre paneler. Brukeren konfigurerer verktøyet med en prompt
og drar innhold til/fra det.
Inspirert av fysiske verktøy: du har en maskin på arbeidsbenken,
konfigurert til å gjøre én ting godt. Du mater inn materiale, og
får bearbeidet materiale tilbake. Maskinen står der klar mellom bruk.
## 2. Brukeropplevelse
### 2.1 Åpne og konfigurere
1. Brukeren trekker AI-verktøyet inn på arbeidsflaten (fra verktøy-paletten).
2. Verktøyet åpner seg med:
- En **prompt-velger** med gjennomarbeidede standardprompter
- Et **fritekst-felt** for egendefinert prompt
- En **modell-indikator** (viser hvilken modell som brukes — styrt av server)
3. Brukeren velger prompt og verktøyet er klart.
4. Verktøyet *husker* konfigurasjonen — det står klart til bruk uten
å rekonfigurere hver gang.
### 2.2 To retninger — to semantikker
| Retning | Metafor | Handling | Resultat |
|---|---|---|---|
| **Verktøy → Node** | "Penselen" | Dra AI-verktøyet og slipp på en tekstnode | In-place revisjon: teksten modifiseres, originalen versjoneres |
| **Node → Verktøy** | "Kverna" | Dra en tekstnode og slipp på AI-verktøyet | Ny node opprettes med `derived_from`-edge til kilden |
**Penselen** — du bruker verktøyet *på* teksten. Passer for korrektur,
språkvask, rensing av innlimt rot. Teksten oppgraderes, originalen
bevares som revisjon.
**Kverna** — du sender teksten *gjennom* verktøyet. Passer for
oppsummering, oversettelse, uttrekk av fakta. Output er et nytt
objekt som kan tas med videre til andre verktøy på flaten.
### 2.3 Typisk bruksscenario
```
Vegard sitter på bussen, leser en artikkel i VG på mobilen.
Ctrl+A → kopierer alt (artikkel + ingresser + annonser + navigasjon).
Limer inn i en ny node i Synops.
Drar AI-verktøyet (konfigurert med "Rens tekst") → noden.
AI-et vasker bort alt som ikke er artikkelen, strukturerer teksten,
forkorter, og oppgir kilde. Originalen er bevart som revisjon.
Ferdig. Ren, lesbar tekst. Ingen rot.
```
## 3. Standardprompter
Gjennomarbeidede, klare til bruk uten konfigurasjon:
| Prompt | Hva den gjør | Typisk retning |
|---|---|---|
| **Rens tekst** | Fjerner støy fra innlimt webinnhold, fikser skrivefeil, strukturerer, oppgir kilde | Verktøy → Node |
| **Korrektør** | Fikser grammatikk og skrivefeil, beholder innhold intakt | Verktøy → Node |
| **Oppsummering** | Kondenserer til 25 setninger med det viktigste | Node → Verktøy |
| **Oversett** | Oversetter til/fra norsk/engelsk | Begge |
| **Skriv om for publisering** | Omskriver til artikkelformat med tittel, ingress, brødtekst | Node → Verktøy |
| **Trekk ut fakta** | Identifiserer påstander, tall, sitater som separate punkter | Node → Verktøy |
| **Forenkle** | Omskriver til klarere, enklere språk | Verktøy → Node |
| **Endre tone** | Formell ↔ uformell, saklig ↔ engasjert | Verktøy → Node |
Brukere kan lage egne prompter og lagre dem. Egendefinerte prompter
lagres som noder (`node_kind: 'ai_preset'`) som kan deles via edges.
## 4. Modellstyring
**Modell bestemmes av serveren, ikke brukeren.**
Hvert AI-verktøy (standardprompt eller egendefinert) har en
server-tildelt modellprofil. Brukeren ser hvilken modell som brukes
(transparens), men kan ikke endre den.
| Prompt-kategori | Modellprofil | Begrunnelse |
|---|---|---|
| Rens tekst, korrektør, forenkle | Flash (billig, rask) | Enkle transformasjoner |
| Oppsummering, oversettelse | Flash (billig, rask) | Rutineoppgaver |
| Skriv om for publisering | Standard | Krever mer resonering |
| Trekk ut fakta | Standard | Nøyaktighet viktigere |
| Egendefinert (default) | Flash | Kan oppgraderes av admin |
Modellprofiler konfigureres i maskinrommet og mappes til LiteLLM-aliaser.
Admin kan justere modellprofil per prompt via Prompt Lab.
**Kostnadskontroll:** Serveren styrer modellvalg for å hindre at brukere
velger den dyreste modellen for alt. AI-forbruk logges per bruker/samling
i `ai_usage_log`.
## 5. AI-verktøyet som node
AI-verktøyet er selv en node i grafen (`node_kind: 'ai_preset'`):
```jsonc
{
"node_kind": "ai_preset",
"title": "Rens tekst",
"metadata": {
"prompt": "Fiks denne teksten. Output på norsk...",
"model_profile": "flash",
"category": "standard", // "standard" | "custom"
"default_direction": "tool_to_node", // hint for UI
"icon": "sparkles",
"color": "#8B5CF6"
}
}
```
Fordeler:
- **Delbart:** Edge til samling/team → alle i teamet har tilgang
- **Versjonerbart:** Promptjustering over tid med revisjonshistorikk
- **Sporbart:** `derived_from`-edge fra output til kilde + `processed_by`-edge
til AI-preset → full provenance i kunnskapsgrafen
- **Gjenbrukbart:** Flere instanser av samme verktøy med ulik konfigurasjon
## 6. Teknisk arkitektur
### 6.1 Signalflyt
```
Bruker drar node → AI-verktøy (eller omvendt)
Frontend sender intention til maskinrommet:
POST /intentions/ai_process
{
source_node_id: "...",
ai_preset_id: "...",
direction: "node_to_tool" | "tool_to_node"
}
Maskinrommet:
1. Hent kilde-node content
2. Hent AI-preset prompt + modellprofil
3. Map modellprofil → LiteLLM-alias
4. Send til AI Gateway (LiteLLM)
5a. direction = tool_to_node:
→ Lagre original som revisjon
→ Oppdater node content med AI-output
5b. direction = node_to_tool:
→ Opprett ny node med AI-output
→ Opprett derived_from-edge til kilde
→ Opprett processed_by-edge til AI-preset
6. Logg forbruk i ai_usage_log
Frontend mottar oppdatering via SpacetimeDB
```
### 6.2 Drag-and-drop integrasjon
AI-verktøyet følger arbeidsflate-konvensjonene fra
`docs/retninger/arbeidsflaten.md`:
**Som mål (node → verktøy):**
- Aksepterer: alle noder med `content`-felt (tekst, chatmeldinger, notater)
- Drop-sone lyser opp med verktøyets farge under drag
- Ved drop: opprett ny node, vis den ved siden av verktøyet
**Som kilde (verktøy → node):**
- Verktøyet kan "dras" til en tekstnode
- Drop-sone på tekstnoden lyser opp
- Ved drop: modifiser noden in-place
**Inkompatibilitet:**
- Lydfiler, bilder, mediefiler → "AI-verktøyet behandler kun tekst"
- Tomme noder → "Noden har ikke innhold å behandle"
### 6.3 Oppdatering av kompatibilitetsmatrisen
Legges til i `docs/retninger/arbeidsflaten.md`:
| Kilde → Mål | AI-verktøy |
|---|---|
| **Chatboble** | Ny node med AI-output + `derived_from` |
| **Tekst/notat** | Ny node med AI-output + `derived_from` |
| **Lydfil** | Inkompatibel: "AI-verktøyet behandler kun tekst" |
| **Transkripsjon** | Ny node med AI-output + `derived_from` |
| **Bilde** | Inkompatibel |
| Kilde → Mål | Tekstnode (fra AI-verktøy) |
|---|---|
| **AI-verktøy** | In-place revisjon av tekstnoden |
## 7. Forhold til eksisterende AI-design
### Erstatter ✨-knappen i editoren
Editor-proposalen (`docs/proposals/editor.md`) beskriver en ✨-knapp
inne i editoren. Med spatial workspace-retningen erstattes denne av
AI-verktøyet som eget panel. Fordeler:
- **Separat konfigurasjonsflate:** Prompt og parametere lever i sitt
eget panel, ikke gjemt bak en meny i editoren
- **Persistent:** Verktøyet står konfigurert og klart. ✨-knappen
krever prompt-valg hver gang
- **Konsistent drag-and-drop:** Samme interaksjonsmønster som mellom
alle andre verktøy på flaten
- **Flere samtidige:** Du kan ha "Rens tekst" og "Oppsummer" som to
separate paneler, begge klare
### Bygger på Prompt Lab
Egendefinerte prompter kan opprettes og testes i Prompt Lab
(`docs/features/prompt_lab.md`) før de deployes som AI-preset-noder.
### Fremtidig: kjeding
Flere AI-verktøy i serie: dra output fra "Oversett" videre til
"Forenkle". Grafen sporer hele transformasjonskjeden via
`derived_from`-edges. Ikke i scope for v1.
## 8. Avgrensning
- Opererer på **hele noden** (hele `content`-feltet), ikke markert utvalg
- Brukeren kan **ikke** velge modell — kun server-tildelt modellprofil
- Ingen sanntids-streaming av AI-output (synkron respons via jobbkø)
- Støtter kun tekst — ikke bilder, lyd eller video
- Kjeding av verktøy er fremtidig funksjonalitet
## 9. Utviklingsfaser
### Fase A: Grunnleggende verktøy-panel
- [x] AI-preset node-type (`node_kind: 'ai_preset'`) + metadata-skjema
- [x] Standard-presets som seed-data (rens tekst, korrektør, oppsummering osv.)
- [x] `POST /intentions/ai_process` endepunkt i maskinrommet
- [ ] Verktøy-panel UI med prompt-velger og modell-indikator
- [ ] Jobbkø-integrasjon med AI Gateway
### Fase B: Drag-and-drop
- [ ] Node → verktøy: opprett ny node med `derived_from`-edge
- [ ] Verktøy → node: in-place revisjon med versjonering
- [ ] Drop-sone feedback (farge, inkompatibilitet)
- [ ] Visuell output: ny node animeres inn ved siden av verktøyet
### Fase C: Egendefinerte prompter
- [ ] Opprett egne AI-preset-noder
- [ ] Del via edges (samling/team)
- [ ] Prompt Lab-integrasjon for testing
## 10. Instruks for Claude Code
- AI-behandling skjer **alltid** via maskinrommet, aldri direkte fra frontend
- Modellprofil → LiteLLM-alias-mapping konfigureres i maskinrommet
- Brukeren kan **ikke** velge modell — dette er en server-side beslutning
- Standardprompter er seed-data som opprettes ved deploy, ikke hardkodet i frontend
- `derived_from`-edge og `processed_by`-edge gir sporbarhet i grafen
- AI-forbruk logges alltid i `ai_usage_log` per bruker, samling og preset
- Hele noden prosesseres — ingen "markert utvalg"-støtte