feat: Beschreibung generieren Button im Neuer-Fall-Modal
KI-gestütztes Prompt Enhancement: Button generiert per Haiku aus dem Titel eine strukturierte Beschreibung. Unterscheidet zwischen Live-Monitoring (kompakte Vorfallsbeschreibung) und Recherche (strukturiertes Briefing mit Schwerpunkten und Suchbegriffen). - Neuer Endpoint POST /api/incidents/enhance-description - Button erscheint für beide Lage-Typen, aktiv ab 3 Zeichen Titel - Info-Hinweis wechselt je nach Typ mit Beispiel - Spinner-Animation während der Generierung
Dieser Commit ist enthalten in:
@@ -1,7 +1,7 @@
|
||||
"""Incidents-Router: Lagen verwalten (Multi-Tenant)."""
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, status
|
||||
from fastapi.responses import StreamingResponse
|
||||
from models import IncidentCreate, IncidentUpdate, IncidentResponse, SubscriptionUpdate, SubscriptionResponse
|
||||
from models import IncidentCreate, IncidentUpdate, IncidentResponse, SubscriptionUpdate, SubscriptionResponse, DescriptionEnhanceRequest
|
||||
from auth import get_current_user
|
||||
from middleware.license_check import require_writable_license
|
||||
from database import db_dependency, get_db
|
||||
@@ -155,6 +155,65 @@ async def get_refreshing_incidents(
|
||||
}
|
||||
|
||||
|
||||
# --- Beschreibung generieren (Prompt Enhancement) ---
|
||||
|
||||
ENHANCE_PROMPT_RESEARCH = """Du generierst ein strukturiertes Recherche-Briefing fuer ein OSINT-Lagemonitoring-System.
|
||||
WICHTIG: Verwende IMMER echte UTF-8-Umlaute (ae, oe, ue, ss) und KEINE Umschreibungen.
|
||||
|
||||
Titel: {title}
|
||||
Vorhandener Kontext: {context}
|
||||
Typ: Hintergrundrecherche
|
||||
|
||||
Erstelle ein praezises Recherche-Briefing mit:
|
||||
1. Vollstaendiger Name/Bezeichnung des Themas (inkl. Rechtsform bei Unternehmen, voller Name bei Personen)
|
||||
2. Recherche-Schwerpunkte (5-8 thematische Punkte, z.B. Geschichte, Finanzen, Fuehrung, Kontroversen, Innovation)
|
||||
3. Relevante Suchbegriffe (deutsch + englisch, inkl. Abkuerzungen und alternative Schreibweisen)
|
||||
|
||||
Schreibe NUR das Briefing als Fliesstext mit Aufzaehlungen. Keine Erklaerungen davor oder danach."""
|
||||
|
||||
ENHANCE_PROMPT_ADHOC = """Du generierst eine praezise Vorfallsbeschreibung fuer ein OSINT-Lagemonitoring-System.
|
||||
WICHTIG: Verwende IMMER echte UTF-8-Umlaute (ae, oe, ue, ss) und KEINE Umschreibungen.
|
||||
|
||||
Titel: {title}
|
||||
Vorhandener Kontext: {context}
|
||||
Typ: Live-Monitoring (aktuelle Ereignisse)
|
||||
|
||||
Erstelle eine knappe, informative Beschreibung mit:
|
||||
1. Was ist passiert / worum geht es
|
||||
2. Wo (geographischer Kontext)
|
||||
3. Wer ist beteiligt (Akteure, Organisationen, Laender)
|
||||
4. Wonach soll gesucht werden (aktuelle Entwicklungen, Reaktionen, Hintergruende)
|
||||
|
||||
Schreibe NUR die Beschreibung als Fliesstext (3-5 Zeilen). Keine Erklaerungen davor oder danach."""
|
||||
|
||||
_enhance_logger = logging.getLogger("osint.enhance")
|
||||
|
||||
|
||||
@router.post("/enhance-description")
|
||||
async def enhance_description(
|
||||
data: DescriptionEnhanceRequest,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
"""Generiert eine strukturierte Beschreibung per KI aus dem Titel."""
|
||||
from agents.claude_client import call_claude
|
||||
from config import CLAUDE_MODEL_FAST
|
||||
|
||||
template = ENHANCE_PROMPT_RESEARCH if data.type == "research" else ENHANCE_PROMPT_ADHOC
|
||||
context = data.description.strip() if data.description and data.description.strip() else "Kein Kontext angegeben"
|
||||
prompt = template.format(title=data.title.strip(), context=context)
|
||||
|
||||
try:
|
||||
result, usage = await call_claude(prompt, tools=None, model=CLAUDE_MODEL_FAST)
|
||||
_enhance_logger.info(
|
||||
f"Beschreibung generiert fuer \"{data.title[:50]}\": "
|
||||
f"{usage.input_tokens}in/{usage.output_tokens}out"
|
||||
)
|
||||
return {"description": result.strip()}
|
||||
except Exception as e:
|
||||
_enhance_logger.error(f"Beschreibung generieren fehlgeschlagen: {e}")
|
||||
raise HTTPException(status_code=500, detail="Beschreibung konnte nicht generiert werden")
|
||||
|
||||
|
||||
@router.get("/{incident_id}", response_model=IncidentResponse)
|
||||
async def get_incident(
|
||||
incident_id: int,
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren