feat(ai): migrate to Google Gemini 2.5 Flash-Lite, drop Mistral/Ollama
Replace the Mistral + Ollama AI stack with a single Google Gemini provider backed by google.golang.org/genai. API key moves from env/Helm to the DB (AES-256-GCM, key derived from JWT_SECRET via HKDF) so it can be rotated via the admin UI without a pod restart. New: - pkg/crypto/secretbox — AES-256-GCM encrypt/decrypt for secrets at rest - pkg/ai/gemini — GeminiProvider with grounding, structured output, usage recording, and hot-reload (Reinitialize swaps client under mutex) - pkg/ai/usage — UsageRecorder interface + UsageEvent struct - domain/settings/store — DB-backed settings (model, grounding toggle, key) - domain/settings/usage — UsageRepo implementing UsageRecorder; ai_usage table - migrations 000021 (system_settings) + 000022 (ai_usage) - settings API: GET /ai, POST /ai/key, POST /ai/model, POST /ai/grounding, GET /ai/usage - admin UI: 4-card settings page — provider status, model selector, grounding toggle with quota, usage rollups + recent-calls table Removed: - pkg/ai/ollama, mistral_provider, ratelimiter (+ tests) - Helm AI_API_KEY, AI_PROVIDER, AI_MODEL_COMPLEX, AI_AGENT_DISCOVERY, AI_RATE_LIMIT_RPS env vars Call sites set Grounded+CallType: research (true/"research"), enrich Pass B (true/"enrich_b"), similarity (false/"similarity"). Integration test updated to use a stub ai.Provider instead of a fake Ollama HTTP server.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
{{- if or .Values.ai.apiKey .Values.turnstile.secretKey .Values.discovery.token }}
|
||||
{{- if or .Values.turnstile.secretKey .Values.discovery.token }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
@@ -8,9 +8,6 @@ metadata:
|
||||
{{- include "marktvogt-backend.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
{{- if .Values.ai.apiKey }}
|
||||
AI_API_KEY: {{ .Values.ai.apiKey | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.turnstile.secretKey }}
|
||||
TURNSTILE_SECRET_KEY: {{ .Values.turnstile.secretKey | quote }}
|
||||
{{- end }}
|
||||
|
||||
@@ -51,7 +51,7 @@ spec:
|
||||
- secretRef:
|
||||
name: {{ include "marktvogt-backend.fullname" . }}-smtp
|
||||
{{- end }}
|
||||
{{- if or .Values.ai.apiKey .Values.turnstile.secretKey .Values.discovery.token }}
|
||||
{{- if or .Values.turnstile.secretKey .Values.discovery.token }}
|
||||
# AI, Turnstile + Discovery credentials (Helm-managed, passed via CI)
|
||||
- secretRef:
|
||||
name: {{ include "marktvogt-backend.fullname" . }}-ci-secrets
|
||||
@@ -97,10 +97,6 @@ spec:
|
||||
secretKeyRef:
|
||||
name: {{ include "marktvogt-backend.fullname" . }}-ci-secrets
|
||||
key: DISCOVERY_TOKEN
|
||||
- name: AI_AGENT_DISCOVERY
|
||||
value: {{ .Values.ai.agentDiscovery | quote }}
|
||||
- name: AI_RATE_LIMIT_RPS
|
||||
value: {{ .Values.ai.rateLimitRps | default 1 | quote }}
|
||||
- name: DISCOVERY_BATCH_SIZE
|
||||
value: {{ .Values.discovery.batchSize | default 4 | quote }}
|
||||
- name: DISCOVERY_FORWARD_MONTHS
|
||||
|
||||
@@ -81,8 +81,6 @@ config:
|
||||
SMTP_FROM: "noreply@marktvogt.de"
|
||||
ADMIN_EMAIL: "contact@marktvogt.de"
|
||||
FRONTEND_URL: "https://marktvogt.de"
|
||||
AI_MODEL_COMPLEX: "mistral-large-latest"
|
||||
|
||||
# Name of the manually-created Secret containing:
|
||||
# JWT_SECRET, SENTRY_DSN,
|
||||
# OAUTH_{GOOGLE,APPLE,FACEBOOK,GITHUB}_{CLIENT_ID,CLIENT_SECRET}
|
||||
@@ -95,12 +93,6 @@ smtp:
|
||||
user: ""
|
||||
password: ""
|
||||
|
||||
# AI research credentials — passed via Woodpecker secrets during deploy.
|
||||
ai:
|
||||
apiKey: ""
|
||||
agentDiscovery: "" # set via CI secret in production
|
||||
rateLimitRps: 1
|
||||
|
||||
# Discovery cron — token passed via CI secrets during deploy.
|
||||
discovery:
|
||||
enabled: true
|
||||
|
||||
Reference in New Issue
Block a user