diff --git a/concepts/Billing-Konzept.md b/concepts/Billing-Konzept.md index 741e0c2..29067f4 100644 --- a/concepts/Billing-Konzept.md +++ b/concepts/Billing-Konzept.md @@ -26,8 +26,9 @@ Mandant (Kostenstelle) ``` ### 3. LLM-Provider-Steuerung -- Benutzer können pro Workflow definieren, welche **AICore-Provider** erlaubt sind -- Zuordnung auf Level **AICore-Connector**: `anthropic`, `openai`, `perplexity`, `tavily`, `internal` +- Benutzer können pro Workflow definieren, welche **AICore-Provider** verwendet werden +- Provider-Liste ist **dynamisch** basierend auf registrierten AICore-Plugins (Plug&Play) +- Zuordnung auf Level **AICore-Connector** (z.B. `anthropic`, `openai`, `perplexity`, `tavily`, `internal`, weitere zukünftig) - Ermöglicht Kostenkontrolle und Compliance-Anforderungen ### 4. Transparente Kostenerfassung @@ -194,15 +195,25 @@ class UsageStatistics(BaseModel): costByFeature: Dict[str, float] # {'playground': 15.00, 'automation': 5.80} ``` -### Erweiterung bestehender Modelle +### Hinweis: Chat-Daten bleiben User-owned + +**Wichtig:** Die Chat-Modelle (`ChatWorkflow`, `ChatStat`, `ChatMessage`, etc.) speichern **keine** `mandateId`. Sie sind "User-owned" und die Mandanten-Zuordnung erfolgt über RBAC-Filterung zur Laufzeit. + +**Billing-Zuordnung:** Der Mandanten-Kontext wird **in der BillingTransaction** gespeichert, nicht im ChatWorkflow: +- Bei jedem AI-Call wird der `mandateId` aus dem Request-Context in der Transaktion gespeichert +- Die Verknüpfung Workflow → Mandant erfolgt über `BillingTransaction.workflowId` +- Statistiken werden aus den BillingTransactions aggregiert, nicht aus ChatStat ```python -# Erweiterung: ChatWorkflow (datamodelChat.py) -class ChatWorkflow(BaseModel): - # ... bestehende Felder ... - - # NEU: Mandanten-Kontext für Billing - mandateId: Optional[str] # FK → Mandate +# KEINE Änderung an ChatWorkflow erforderlich! +# ChatWorkflow bleibt "User-owned, no mandate context" + +# Stattdessen: BillingTransaction speichert den Mandanten-Kontext +class BillingTransaction(BaseModel): + # ... + workflowId: Optional[str] # Referenz zum Workflow + featureInstanceId: Optional[str] # Feature-Instanz (z.B. chatplayground) + # mandateId kommt über BillingAccount ``` **Hinweis:** Die Provider-Steuerung erfolgt NICHT über Datenbank-Attribute, sondern über das RBAC-System (siehe Abschnitt "LLM-Provider als RBAC Resources"). @@ -245,23 +256,35 @@ class ChatWorkflow(BaseModel): Die Steuerung, welche LLM-Provider ein Benutzer verwenden darf, erfolgt über das RBAC-System: -**Registrierte Resources:** +**Resource-Namenskonvention:** +``` +resource.aicore.{connectorType} +``` + +**Dynamische Registrierung:** +- Jedes AICore-Plugin registriert sich automatisch als RBAC-Resource +- Die Liste der verfügbaren Provider wird aus `ModelRegistry.getConnectors()` ermittelt +- Neue Plugins werden automatisch erkannt (Plug&Play) + +**Beispiel aktuell registrierter Provider:** - `resource.aicore.anthropic` - `resource.aicore.openai` - `resource.aicore.perplexity` - `resource.aicore.tavily` - `resource.aicore.internal` +- *(weitere zukünftig via Plug&Play)* **Bootstrap-Berechtigungen (Mandate ROOT):** -- **SysAdmin:** Alle Provider (USE) -- **Admin:** Alle Provider (USE) -- **User:** Alle Provider (USE) +- **SysAdmin:** Alle registrierten Provider (USE) +- **Admin:** Alle registrierten Provider (USE) +- **User:** Alle registrierten Provider (USE) **Vorteile des RBAC-Ansatzes:** - Zentrale Verwaltung über bestehende Rollen-Struktur - Granulare Steuerung pro Mandant möglich - Keine zusätzlichen Datenbank-Attribute erforderlich - Konsistent mit bestehendem Berechtigungssystem +- Automatische Erweiterung bei neuen AICore-Plugins --- @@ -463,9 +486,13 @@ def _setupRootMandate(): def _setupAicoreRbacPermissions(mandateId: str): - """Erstellt RBAC-Berechtigungen für LLM-Provider""" + """Erstellt RBAC-Berechtigungen für LLM-Provider (dynamisch)""" + + # Provider dynamisch aus ModelRegistry laden (Plug&Play) + from modules.aicore.aicoreModelRegistry import modelRegistry + connectors = modelRegistry.discoverConnectors() + providers = [c.getConnectorType() for c in connectors] - providers = ['anthropic', 'openai', 'perplexity', 'tavily', 'internal'] roles = ['sysadmin', 'admin', 'user'] for role in roles: @@ -696,9 +723,10 @@ Static Block: BILLING **Integration in:** `/workflows/playground` **Funktionen:** -- Dropdown/Checkboxen für erlaubte Provider +- Provider-Liste wird **dynamisch** aus registrierten AICore-Plugins geladen - Zeigt nur Provider an, für die der User RBAC-Berechtigung hat - Auswahl gilt für den nächsten AI-Call +- Preise werden aus den Plugin-Definitionen gelesen ``` ┌─────────────────────────────────────────────────────────┐ @@ -729,7 +757,7 @@ Das Automation-Editor Modal wird in drei Tabs aufgeteilt: **Tab-Struktur:** 1. **General** - Name, Beschreibung, Schedule, Status 2. **Modellierung** - Template, Placeholders, Preview -3. **LLM Modelle** - Provider-Auswahl basierend auf RBAC-Berechtigungen +3. **LLM Modelle** - Provider-Auswahl (dynamisch aus AICore-Plugins, gefiltert nach RBAC) ``` ┌─────────────────────────────────────────────────────────┐ @@ -739,7 +767,7 @@ Das Automation-Editor Modal wird in drei Tabs aufgeteilt: │ ───────────────────────────────────────────────────── │ │ TAB: LLM Modelle │ │ │ -│ Verfügbare Provider (basierend auf Ihren Berechtigungen): +│ Verfügbare Provider (dynamisch, RBAC-gefiltert): │ ○ Anthropic (Claude) CHF 0.020/1k tokens │ │ ● OpenAI (GPT-4) CHF 0.015/1k tokens │ │ ○ Perplexity (Web) CHF 0.008/1k tokens │ @@ -822,36 +850,36 @@ anbei erhalten Sie den monatlichen Kostenreport für Ihren Mandanten ZUSAMMENFASSUNG ─────────────────────────────────────────────────────── -Gesamtkosten: $ 156.80 USD +Gesamtkosten: CHF 156.80 Anzahl AI-Operationen: 423 -Durchschnitt pro Operation: $ 0.37 USD +Durchschnitt pro Operation: CHF 0.37 AUFSCHLÜSSELUNG NACH PROVIDER ─────────────────────────────────────────────────────── -Anthropic (Claude) $ 112.50 USD (72%) -OpenAI (GPT-4) $ 38.30 USD (24%) -Internal $ 6.00 USD (4%) +Anthropic (Claude) CHF 112.50 (72%) +OpenAI (GPT-4) CHF 38.30 (24%) +Internal CHF 6.00 (4%) AUFSCHLÜSSELUNG NACH FEATURE ─────────────────────────────────────────────────────── -Chat Playground $ 95.00 USD (61%) -Automation $ 45.80 USD (29%) -Chatbot (Feature) $ 16.00 USD (10%) +Chat Playground CHF 95.00 (61%) +Automation CHF 45.80 (29%) +Chatbot (Feature) CHF 16.00 (10%) TOP 5 NUTZER (nach Verbrauch) ─────────────────────────────────────────────────────── -1. Max Mustermann $ 48.50 USD -2. Anna Schmidt $ 35.20 USD -3. Peter Weber $ 28.90 USD -4. Lisa Müller $ 22.10 USD -5. Thomas Meier $ 12.30 USD +1. Max Mustermann CHF 48.50 +2. Anna Schmidt CHF 35.20 +3. Peter Weber CHF 28.90 +4. Lisa Müller CHF 22.10 +5. Thomas Meier CHF 12.30 KONTOSTAND ─────────────────────────────────────────────────────── -Vorheriger Stand: $ 456.05 USD -Verbrauch: -$ 156.80 USD +Vorheriger Stand: CHF 456.05 +Verbrauch: -CHF 156.80 ─────────────────────────────────────────────────────── -Aktueller Stand: $ 299.25 USD +Aktueller Stand: CHF 299.25 Bei Fragen stehen wir Ihnen gerne zur Verfügung. @@ -871,8 +899,8 @@ Betreff: ⚠️ PowerOn - Niedriges Guthaben für SOHA Treuhand AG Ihr Guthaben für den Mandanten "SOHA Treuhand AG" hat die Warnschwelle unterschritten. -Aktuelles Guthaben: $ 45.00 USD -Warnschwelle: $ 50.00 USD (10%) +Aktuelles Guthaben: CHF 45.00 +Warnschwelle: CHF 50.00 (10%) Bitte laden Sie Ihr Guthaben auf, um Unterbrechungen zu vermeiden. @@ -888,29 +916,29 @@ PowerOn Platform ### Phase 1: Datenmodell & Grundstruktur -1. **Datenbank-Schema erstellen** +1. **Neue Billing-Datenbank erstellen** (`poweron_billing`) - `BillingAccount`, `BillingTransaction`, `BillingSettings`, `UsageStatistics` Tabellen - Migration für bestehende Mandanten (Default: `UNLIMITED`) -2. **Erweiterung bestehender Modelle** - - `ChatWorkflow.mandateId` hinzufügen - - `ChatWorkflow.allowedProviders` hinzufügen - - `AutomationDefinition.allowedProviders` hinzufügen +2. **Keine Änderung an Chat-Modellen** + - Chat-Daten bleiben "User-owned" (kein mandateId in ChatWorkflow) + - Mandanten-Kontext wird in BillingTransaction gespeichert 3. **BillingService implementieren** - Balance-Prüfung - - Transaktions-Erfassung - - Provider-Validierung + - Transaktions-Erfassung mit mandateId aus Request-Context + - Provider-Validierung über RBAC ### Phase 2: Integration in Workflows -1. **ChatWorkflow erweitern** - - `mandateId` bei Start speichern - - Provider-Filter bei Model-Selection +1. **Billing-Integration in WorkflowProcessor** + - `mandateId` und `featureInstanceId` aus Request-Context verwenden + - BillingTransaction bei jedem AI-Call erstellen (mit mandateId) + - Provider-Filter über RBAC bei Model-Selection 2. **Billing-Checks einbauen** - - Vor jedem AI-Call: Balance prüfen - - Nach jedem AI-Call: Kosten erfassen + - Vor jedem AI-Call: Balance prüfen (BillingAccount des Mandanten) + - Nach jedem AI-Call: Kosten als BillingTransaction erfassen 3. **Error Handling** - `InsufficientBalanceException` @@ -947,7 +975,8 @@ PowerOn Platform 1. **Root-Mandant Setup** - `PREPAY_USER` Modell - - 10 USD Startguthaben für neue User + - 10 CHF Startguthaben für neue User + - RBAC-Berechtigungen für alle LLM-Provider 2. **Bestehende User migrieren** - Accounts erstellen @@ -956,6 +985,7 @@ PowerOn Platform 3. **Bestehende Mandanten migrieren** - Default-Settings erstellen - `UNLIMITED` oder `PREPAY_MANDATE` + - RBAC-Berechtigungen für LLM-Provider erstellen ### Phase 6: Email-Reports @@ -973,9 +1003,9 @@ PowerOn Platform --- -## Offene Fragen und Entscheidungen +## Entscheidungen -### Beantwortet +### Architektur-Entscheidungen 1. **Soll Chat Playground über Mandanten laufen?** → **Ja**, dies ist für konsistente Verrechnung notwendig. `ChatWorkflow.mandateId` wird aus dem Request-Context übernommen. @@ -984,29 +1014,47 @@ PowerOn Platform → `data.chat.*` und `data.files.*` sind aktuell `USER_OWNED`. Für Billing muss `ChatWorkflow` den Mandanten-Kontext speichern. 3. **Läuft Automation bereits über Mandanten?** - → **Ja**, `AutomationDefinition.mandateId` existiert bereits. Erweiterung nur um `allowedProviders`. + → **Ja**, `AutomationDefinition.mandateId` existiert bereits. -### Noch zu klären +4. **Provider-Steuerung** + → Über RBAC-System als Resources (`resource.aicore.*`), NICHT als Datenbank-Attribute. + +### Geschäftsentscheidungen 1. **Payment-Integration** - - Wie laden Kunden Guthaben auf? (Stripe, Rechnung, manuell) - - Self-Service oder nur Admin? + → Stripe-Anbindung wird vorbereitet (zukünftig) + → Aktuell: SysAdmin-Seite für manuelle Guthaben-Aufladung 2. **Preisgestaltung** - - Aufschlag auf Provider-Kosten? (z.B. +20%) - - Fixkosten pro Mandant/User? + → **50% Aufschlag** auf Provider-Kosten, direkt in AICore-Modellen definiert + → Preise werden in CHF kalkuliert und gespeichert 3. **Währung** - - Nur USD intern, Anzeige in CHF/EUR? - - Wechselkurs-Handling? + → **Alles in CHF**, keine Währungsumrechnung im System + → Provider-Kosten werden intern auf CHF umgerechnet und mit 50% Aufschlag versehen 4. **Datenhaltung** - - Wie lange Transaktions-Historie aufbewahren? - - Archivierung alter Daten? + → **10 Jahre** Aufbewahrungspflicht für Transaktionen + → Automatische Archivierung/Löschung nach 10 Jahren 5. **GDPR/Datenschutz** - - User-Löschung: Was passiert mit Billing-Daten? - - Anonymisierung nach X Jahren? + → Transaktionsdaten nach 10 Jahren löschen + → Gelöschte User: Nur ID-Referenz in Transaktionen (bereits anonym, da keine personenbezogenen Daten) + → Daten im System belassen für Mandanten-Abrechnungen + +### Preistabelle (50% Aufschlag) - Beispiele + +Jedes AICore-Plugin definiert seine eigenen Preise via `calculatePriceCHF()`. Die Preise werden dynamisch aus den Plugins geladen. + +| Provider | Provider-Kosten (ca.) | Interner Preis (CHF) | +|------------|----------------------|----------------------| +| Anthropic | $0.015/1k tokens | CHF 0.020/1k tokens | +| OpenAI | $0.010/1k tokens | CHF 0.015/1k tokens | +| Perplexity | $0.005/1k tokens | CHF 0.008/1k tokens | +| Tavily | $0.003/1k tokens | CHF 0.005/1k tokens | +| Internal | $0.001/1k tokens | CHF 0.002/1k tokens | + +**Hinweis:** Preise werden direkt in den AICore-Plugin-Modellen definiert (`calculatePriceCHF`) und beinhalten bereits den 50% Aufschlag. --- @@ -1016,11 +1064,13 @@ PowerOn Platform |---------|--------------| | **AICore** | Plugin-System für LLM-Provider Integration | | **Billing Account** | Konto für Guthaben/Saldo (pro Mandant oder User) | +| **Billing Address** | Rechnungsadresse, erforderlich für CREDIT_POSTPAY | | **Connector** | AICore-Plugin für einen spezifischen Provider | | **Kostenstelle** | Mandant, dem Kosten zugeordnet werden | | **Mandate** | Mandant/Tenant in der Multi-Tenant-Architektur | | **Provider** | LLM-Anbieter (anthropic, openai, etc.) | -| **priceCHF** | Berechneter Preis einer AI-Operation in USD | +| **priceCHF** | Berechneter Preis einer AI-Operation in CHF (inkl. 50% Aufschlag) | +| **RBAC Resource** | Berechtigungs-Objekt für Provider-Zugriff (z.B. `resource.aicore.anthropic`) | --- @@ -1031,18 +1081,19 @@ PowerOn Platform ``` gateway/modules/ ├── aicore/ -│ ├── aicoreModelSelector.py # Provider-Filter hinzufügen +│ ├── aicoreModelSelector.py # Provider-Filter via RBAC +│ ├── aicorePluginAnthropic.py # Preise auf CHF mit 50% Aufschlag +│ ├── aicorePluginOpenai.py # Preise auf CHF mit 50% Aufschlag │ └── aicoreBase.py # connectorType für Billing ├── datamodels/ -│ ├── datamodelChat.py # ChatWorkflow erweitern +│ ├── datamodelChat.py # ChatWorkflow.mandateId hinzufügen │ └── datamodelUam.py # Mandate-Referenz -├── features/automation/ -│ └── datamodelFeatureAutomation.py # allowedProviders hinzufügen ├── interfaces/ -│ └── interfaceBootstrap.py # Root-Mandant Billing Setup +│ ├── interfaceBootstrap.py # Root-Mandant Billing Setup + RBAC +│ └── interfaceRbac.py # Resource-Berechtigungen für Provider ├── workflows/ │ ├── automation/mainWorkflow.py # Billing-Integration -│ └── processing/workflowProcessor.py # Balance-Checks +│ └── processing/workflowProcessor.py # Balance-Checks + RBAC Provider-Check └── routes/ └── routeChat.py # mandateId im Workflow speichern ```