Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-llm/src/lexigram/ai/llm/parsers/pydantic.py: 46%

24 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 07:19 +0800

1"""Pydantic Output Parser.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, cast 

6 

7from lexigram.ai.llm.structured.exceptions import ParseError, SchemaValidationError 

8from lexigram.ai.llm.structured.parser import ( 

9 extract_json_block, 

10 validate_against_model, 

11) 

12from lexigram.logging import ( 

13 get_logger, 

14) 

15 

16if TYPE_CHECKING: 

17 from pydantic import BaseModel 

18 

19logger = get_logger(__name__) 

20 

21 

22class PydanticOutputParser: 

23 """Parse LLM responses into Pydantic models. 

24 

25 Uses the existing structured parser's validation logic to parse 

26 and validate against a Pydantic model. 

27 

28 Example: 

29 >>> from pydantic import BaseModel 

30 >>> 

31 >>> class User(BaseModel): 

32 ... name: str 

33 ... age: int 

34 >>> 

35 >>> parser = PydanticOutputParser(User) 

36 >>> result = parser.parse('{"name": "John", "age": 30}') 

37 >>> assert result.name == "John" 

38 """ 

39 

40 def __init__(self, model: type[BaseModel]) -> None: 

41 """Initialize with a Pydantic model class. 

42 

43 Args: 

44 model: Pydantic BaseModel subclass to parse into. 

45 """ 

46 self._model = model 

47 

48 def parse(self, text: str) -> BaseModel: 

49 """Parse text into a Pydantic model instance. 

50 

51 Args: 

52 text: Raw LLM response text that may contain JSON. 

53 

54 Returns: 

55 Validated Pydantic model instance. 

56 

57 Raises: 

58 ParseError: When JSON cannot be extracted. 

59 SchemaValidationError: When validation fails. 

60 """ 

61 try: 

62 parsed = extract_json_block(text) 

63 except ValueError as exc: 

64 raise ParseError(str(exc)) from exc 

65 

66 try: 

67 return cast("BaseModel", validate_against_model(parsed, self._model)) 

68 except (TypeError, ValueError) as exc: 

69 raise SchemaValidationError(str(exc)) from exc 

70 

71 def get_format_instructions(self) -> str: 

72 """Return format instructions for the LLM. 

73 

74 Returns: 

75 Format instruction string telling the model to output valid JSON 

76 that matches the Pydantic model schema. 

77 """ 

78 from lexigram.serialization import dumps_str 

79 

80 schema = ( 

81 self._model.model_json_schema() 

82 if hasattr(self._model, "model_json_schema") 

83 else {"type": "object"} 

84 ) 

85 schema_str = dumps_str(schema, indent=2) 

86 return ( 

87 f"Your response should be a valid JSON object matching this schema:\n\n" 

88 f"{schema_str}\n\n" 

89 "Do not include any text before or after the JSON. " 

90 "Do not use markdown code fences." 

91 ) 

92 

93 

94__all__ = ["PydanticOutputParser"]