From 322004e0b40f1941f66551cfae2ff75e3b857ea9 Mon Sep 17 00:00:00 2001 From: Claude Dev Date: Sat, 28 Mar 2026 00:20:36 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20Beschreibung=20generieren=20gibt=20jetzt?= =?UTF-8?q?=20reinen=20Flie=C3=9Ftext=20aus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer raw_text Parameter in call_claude() umgeht den JSON-System-Prompt. Haiku gibt direkt lesbaren Text zurück statt JSON-Objekte. Gesamtes JSON-Parsing (_json_to_text, Markdown-Strip) entfernt. --- src/agents/claude_client.py | 13 ++++++----- src/routers/incidents.py | 45 ++----------------------------------- 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/src/agents/claude_client.py b/src/agents/claude_client.py index 9d030ec..ca75ccc 100644 --- a/src/agents/claude_client.py +++ b/src/agents/claude_client.py @@ -43,7 +43,7 @@ def _sanitize_mdash(text: str) -> str: """Entfernt Gedankenstriche aus LLM-Output (KI-Indikator).""" return text.replace("\u2014", ", ").replace("\u2013", ", ") -async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", model: str | None = None) -> tuple[str, ClaudeUsage]: +async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", model: str | None = None, raw_text: bool = False) -> tuple[str, ClaudeUsage]: """Ruft Claude CLI auf. Gibt (result_text, usage) zurück. Prompt wird via stdin uebergeben um OS ARG_MAX Limits zu vermeiden. @@ -60,11 +60,12 @@ async def call_claude(prompt: str, tools: str | None = "WebSearch,WebFetch", mod cmd.extend(["--allowedTools", tools]) else: cmd.extend(["--max-turns", "1", "--allowedTools", ""]) - cmd.extend(["--append-system-prompt", - "CRITICAL: You are a JSON-only output agent. " - "Output EXCLUSIVELY a single valid JSON object. " - "No explanatory text, no markdown fences, no continuation of previous responses. " - "Start your response with { and end with }."]) + if not raw_text: + cmd.extend(["--append-system-prompt", + "CRITICAL: You are a JSON-only output agent. " + "Output EXCLUSIVELY a single valid JSON object. " + "No explanatory text, no markdown fences, no continuation of previous responses. " + "Start your response with { and end with }."]) process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, diff --git a/src/routers/incidents.py b/src/routers/incidents.py index b2f03c1..9803acc 100644 --- a/src/routers/incidents.py +++ b/src/routers/incidents.py @@ -186,30 +186,6 @@ Erstelle eine knappe, informative Beschreibung mit: Schreibe NUR die Beschreibung als Fliesstext (3-5 Zeilen). Keine Erklaerungen davor oder danach.""" -def _json_to_text(obj, depth=0): - """Konvertiert verschachteltes JSON in lesbaren Fliesstext.""" - parts = [] - if isinstance(obj, str): - return obj - if isinstance(obj, list): - for item in obj: - if isinstance(item, str): - parts.append(f"- {item}") - elif isinstance(item, dict): - parts.append(_json_to_text(item, depth + 1)) - return "\n".join(parts) - if isinstance(obj, dict): - for key, val in obj.items(): - if isinstance(val, str): - parts.append(val) - elif isinstance(val, list): - parts.append(_json_to_text(val, depth + 1)) - elif isinstance(val, dict): - parts.append(_json_to_text(val, depth + 1)) - return "\n".join(parts) - return str(obj) - - _enhance_logger = logging.getLogger("osint.enhance") @@ -227,29 +203,12 @@ async def enhance_description( prompt = template.format(title=data.title.strip(), context=context) try: - result, usage = await call_claude(prompt, tools=None, model=CLAUDE_MODEL_FAST) - - # call_claude erzwingt bei tools=None JSON-Output — - # Haiku wrapped den Text dann in ein JSON-Objekt (oft verschachtelt) - text = result.strip() - # Markdown-Code-Block-Wrapper entfernen - import re as _re - _md = _re.search(r'`{3}(?:json)?\s*\n?(.*?)\n?\s*`{3}', text, _re.DOTALL) - if _md: - text = _md.group(1).strip() - try: - import json as _json - parsed = _json.loads(text) - if isinstance(parsed, dict): - text = _json_to_text(parsed) - except (ValueError, TypeError): - pass # Kein JSON — text direkt verwenden - + result, usage = await call_claude(prompt, tools=None, model=CLAUDE_MODEL_FAST, raw_text=True) _enhance_logger.info( f"Beschreibung generiert fuer \"{data.title[:50]}\": " f"{usage.input_tokens}in/{usage.output_tokens}out" ) - return {"description": text} + 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")