refactor: consolidate LLM JSON parsing into shared llm_utils module
Extracted duplicate _strip_markdown_fences / _parse_llm_json functions from 7 files into app/services/llm_utils.py. Two shared functions: - strip_markdown_fences(): fence stripping only - parse_llm_json(): fence stripping + JSON parse + error logging Files updated: flowpilot_engine, knowledge_flywheel, session_to_flow_service, ai_tree_generator_service, ai_fix_service, ai_chat_service, kb_conversion_service Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ flow with fallback branches, powered by AI.
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import uuid
|
||||
from typing import Any, Optional
|
||||
from uuid import UUID
|
||||
@@ -16,6 +15,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.core.ai_provider import get_ai_provider
|
||||
from app.core.config import settings
|
||||
from app.core.ai_tree_validator import validate_generated_procedural_steps
|
||||
from app.services.llm_utils import parse_llm_json
|
||||
from app.models.session import Session
|
||||
from app.models.tree import Tree
|
||||
|
||||
@@ -80,13 +80,6 @@ Rules:
|
||||
"""
|
||||
|
||||
|
||||
def _strip_markdown_fences(text: str) -> str:
|
||||
"""Strip markdown code fences if the model wrapped its JSON response."""
|
||||
text = text.strip()
|
||||
match = re.match(r"^```(?:json)?\s*([\s\S]*?)```$", text)
|
||||
if match:
|
||||
return match.group(1).strip()
|
||||
return text
|
||||
|
||||
|
||||
def _build_session_context(session: Session, tree: Optional[Tree]) -> str:
|
||||
@@ -222,11 +215,7 @@ async def generate_flow_from_session(
|
||||
)
|
||||
|
||||
# Strip markdown fences and parse JSON
|
||||
raw_text = _strip_markdown_fences(raw_text)
|
||||
try:
|
||||
generated = json.loads(raw_text)
|
||||
except json.JSONDecodeError as e:
|
||||
raise ValueError(f"AI returned invalid JSON: {e}") from e
|
||||
generated = parse_llm_json(raw_text)
|
||||
|
||||
# Validate the generated steps
|
||||
val_errors = validate_generated_procedural_steps(generated)
|
||||
|
||||
Reference in New Issue
Block a user