Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-llm/src/lexigram/ai/llm/parsers/json.py: 53%
19 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""JSON Output Parser."""
3from __future__ import annotations
5from typing import Any
7from lexigram.ai.llm.structured.exceptions import ParseError
8from lexigram.ai.llm.structured.parser import extract_json_block
9from lexigram.logging import (
10 get_logger,
11)
13logger = get_logger(__name__)
16class JSONOutputParser:
17 """Parse LLM responses into JSON dicts.
19 Handles common LLM output patterns like markdown code fences,
20 prose before/after JSON, and malformed JSON.
22 Example:
23 >>> parser = JSONOutputParser()
24 >>> result = parser.parse('{"key": "value"}')
25 >>> assert result == {"key": "value"}
26 """
28 def parse(self, text: str) -> dict[str, Any]:
29 """Parse text into a JSON dict.
31 Args:
32 text: Raw LLM response text that may contain JSON.
34 Returns:
35 Parsed JSON as a dict.
37 Raises:
38 ParseError: When JSON cannot be extracted or parsed.
39 """
40 try:
41 parsed = extract_json_block(text)
42 except ValueError as exc:
43 raise ParseError(str(exc)) from exc
45 if not isinstance(parsed, dict):
46 raise ParseError(f"Expected JSON object, got {type(parsed).__name__}")
48 logger.debug("json_parsed", keys=list(parsed.keys()))
49 return parsed
51 def get_format_instructions(self) -> str:
52 """Return format instructions for the LLM.
54 Returns:
55 Format instruction string telling the model to output valid JSON.
56 """
57 return (
58 "Your response should be a valid JSON object. "
59 "Do not include any text before or after the JSON. "
60 "Do not use markdown code fences."
61 )
64__all__ = ["JSONOutputParser"]