feat(eu-umbau): Bedrock als zweiter KI-Modellweg (Phase 1)

Zweiter Modellweg ueber AWS Bedrock (EU-Inferenzprofile Frankfurt), umschaltbar
je Lage (incidents.ai_backend) > Organisation (org_setting ai_backend) > global
(ENV AI_BACKEND, Default cli). Neue Datei agents/bedrock_client.py (Converse
API, nur eu.-Profile, Token-zu-USD-Umrechnung ueber BEDROCK_PRICING, gleiche
Fehlerkategorien wie das CLI). Routing zentral in call_claude; Aufrufe mit
WebSearch/WebFetch laufen bis zur staan-Schleife (Phase 2) weiter uebers CLI.
Migration: Spalte incidents.ai_backend. requirements: boto3.
Hinweis Promote: boto3 muss im Live-venv installiert werden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-07-30 19:48:52 +00:00
Ursprung 59cd97adac
Commit fc33cccd44
7 geänderte Dateien mit 331 neuen und 3 gelöschten Zeilen

Datei anzeigen

@@ -4,12 +4,17 @@ import contextvars
import json
import logging
from dataclasses import dataclass
from config import CLAUDE_PATH, CLAUDE_TIMEOUT, CLAUDE_MODEL_FAST, CLAUDE_MODEL_STANDARD
from config import CLAUDE_PATH, CLAUDE_TIMEOUT, CLAUDE_MODEL_FAST, CLAUDE_MODEL_STANDARD, AI_BACKEND
# ContextVar fuer Cancel-Event: Wird vom Orchestrator gesetzt,
# call_claude prueft automatisch darauf -- kein Durchreichen noetig.
_cancel_event_var: contextvars.ContextVar[asyncio.Event | None] = contextvars.ContextVar("_cancel_event_var", default=None)
# ContextVar für das KI-Backend des laufenden Refreshs ('cli' oder 'bedrock').
# Der Orchestrator setzt es je Lage (Auflösung Lage vor Organisation vor
# globalem Default AI_BACKEND). None = globaler Default aus config.
_ai_backend_var: contextvars.ContextVar[str | None] = contextvars.ContextVar("_ai_backend_var", default=None)
logger = logging.getLogger("osint.claude_client")
@@ -88,6 +93,17 @@ async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", mod
model: Optionales Modell (z.B. CLAUDE_MODEL_FAST fuer Haiku). None = CLAUDE_MODEL_STANDARD (Opus 4.7).
timeout: Override in Sekunden. None = Fallback auf globalen CLAUDE_TIMEOUT (1800s).
"""
backend = _ai_backend_var.get(None) or AI_BACKEND
if backend == "bedrock":
if tools:
# Phase 1 des EU-Umbaus. Bedrock hat keine eingebaute Websuche,
# Aufrufe mit Tools laufen bis zur staan-Schleife (Phase 2)
# weiter über das CLI.
logger.info(f"Backend 'bedrock' aktiv, Aufruf braucht aber Tools ({tools}) und läuft übers CLI (Phase 1)")
else:
from agents.bedrock_client import call_bedrock
return await call_bedrock(prompt, model=model, raw_text=raw_text, timeout=timeout)
effective_model = model or CLAUDE_MODEL_STANDARD
effective_timeout = timeout if timeout is not None else CLAUDE_TIMEOUT
cmd = [CLAUDE_PATH, "-p", "-", "--output-format", "json", "--model", effective_model]