Files
kite/backend/ai/utils.py
T
curo1305 a548266461 refactor(backend): extract shared helper modules per architecture rules
- Add backend/ai/utils.py — parse_classification, parse_suggestions, strip_code_fences
  shared by all AI providers; removes duplicated private functions from
  anthropic_provider.py and openai_provider.py
- Add backend/deps/utils.py — get_client_ip, parse_uuid request-parsing helpers;
  removes local _ip() variants from admin.py, auth.py, shares.py, folders.py
- Add backend/storage/exceptions.py — canonical CloudConnectionError definition;
  all routers and backends import from here instead of redefining
- Move validate_password_strength to backend/services/auth.py; removes duplicated
  _validate_password_strength from admin.py and auth.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 16:10:35 +02:00

52 lines
1.6 KiB
Python

"""Shared AI response parsing utilities — used by all provider implementations."""
from __future__ import annotations
import json
import re
from ai.base import ClassificationResult
def strip_code_fences(text: str) -> str:
"""Remove markdown code fences (```json ... ```) from *text*."""
text = re.sub(r"```(?:json)?\s*", "", text)
text = re.sub(r"```", "", text)
return text.strip()
def parse_classification(raw: str) -> ClassificationResult:
"""Parse a classification JSON response into a ClassificationResult.
Tolerates markdown code fences and extracts the first JSON object found.
Returns an empty ClassificationResult on any parse failure.
"""
raw = strip_code_fences(raw)
match = re.search(r"\{.*\}", raw, re.DOTALL)
if match:
try:
data = json.loads(match.group())
return ClassificationResult(
topics=data.get("assigned_topics", []),
suggested_new_topics=data.get("new_topic_suggestions", []),
reasoning=data.get("reasoning", ""),
)
except json.JSONDecodeError:
pass
return ClassificationResult()
def parse_suggestions(raw: str) -> list[str]:
"""Parse a topic-suggestion JSON response into a list of topic name strings.
Tolerates markdown code fences. Returns an empty list on parse failure.
"""
raw = strip_code_fences(raw)
match = re.search(r"\{.*\}", raw, re.DOTALL)
if match:
try:
data = json.loads(match.group())
return data.get("suggested_topics", [])
except json.JSONDecodeError:
pass
return []