Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-prompt/src/lexigram/ai/prompt/service/models.py: 94%

36 statements  

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

1"""Data models for PromptService — templates, requests, results, and provider enum.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6import enum 

7from typing import Any 

8 

9from lexigram.ai.prompt.rendering.engine import RenderFormat 

10 

11 

12class LLMProvider(str, enum.Enum): 

13 """Target LLM provider for provider-specific prompt escaping. 

14 

15 Use this enum to tag a :class:`PromptTemplate` with its intended provider 

16 so that :class:`~lexigram.ai.prompt.service.service.PromptService` can 

17 apply the correct escaping when rendering. 

18 

19 Values: 

20 ANTHROPIC: Anthropic Claude API. Variable values are wrapped in 

21 ``<parameter name="…">…</parameter>`` XML tags (scaffolded; 

22 full escaping is future work — see the ``_escape_*`` 

23 methods in ``service.py``). 

24 OPENAI: OpenAI GPT API. Curly braces inside variable values are 

25 escaped to prevent accidental format-string interpretation. 

26 AZURE: Azure OpenAI Service. Delegates to OPENAI escaping rules. 

27 GENERIC: No escaping. Values are substituted verbatim. 

28 """ 

29 

30 ANTHROPIC = "anthropic" 

31 OPENAI = "openai" 

32 AZURE = "azure" 

33 GENERIC = "generic" 

34 

35 

36@dataclass(frozen=True) 

37class PromptTemplate: 

38 """A named, versioned prompt template with variable declarations. 

39 

40 This is the primary value object stored and served by 

41 :class:`~lexigram.ai.prompt.service.service.PromptService`. 

42 

43 Attributes: 

44 name: Template name used as lookup key. 

45 version: Semver-style or arbitrary version string (e.g. ``"v1"``, 

46 ``"1.0.0"``). The service treats ``"latest"`` as a special 

47 sentinel that always resolves to the most recently loaded 

48 version. 

49 content: Raw template string. Placeholder syntax depends on 

50 ``format``. 

51 format: Render format for this template — a 

52 :class:`~lexigram.ai.prompt.rendering.engine.RenderFormat` 

53 value: ``f_string`` (``{variable}``), ``jinja2`` 

54 (``{{ variable }}``, loops/filters/conditionals), ``dollar`` 

55 (``$variable``), or ``simple`` (literal, no substitution). 

56 provider: Target LLM provider for escaping. Defaults to GENERIC. 

57 required_variables: Variable names that MUST be supplied at render 

58 time. Missing required variables raise. 

59 optional_defaults: Default values for optional variables. Keys that 

60 appear here but not in *required_variables* are 

61 optional. 

62 description: Human-readable description of the template purpose. 

63 metadata: Arbitrary app-defined metadata (tags, author, etc.). 

64 """ 

65 

66 name: str 

67 version: str 

68 content: str 

69 format: RenderFormat = RenderFormat.F_STRING 

70 provider: LLMProvider = LLMProvider.GENERIC 

71 required_variables: tuple[str, ...] = field(default_factory=tuple) 

72 optional_defaults: dict[str, Any] = field(default_factory=dict) 

73 description: str = "" 

74 metadata: dict[str, Any] = field(default_factory=dict) 

75 

76 def __post_init__(self) -> None: 

77 # Normalise: required_variables must be a tuple (frozen dataclass). 

78 if not isinstance(self.required_variables, tuple): 

79 object.__setattr__( 

80 self, "required_variables", tuple(self.required_variables) 

81 ) 

82 

83 

84@dataclass(frozen=True) 

85class PromptRenderRequest: 

86 """Input to :meth:`~lexigram.ai.prompt.service.service.PromptService.render`. 

87 

88 Attributes: 

89 name: Template name to look up. 

90 variables: Variable name → value mapping for substitution. 

91 version: Specific version to render. Defaults to ``"latest"``. 

92 """ 

93 

94 name: str 

95 variables: dict[str, Any] = field(default_factory=dict) 

96 version: str = "latest" 

97 

98 

99@dataclass(frozen=True) 

100class PromptRenderResult: 

101 """Output from :meth:`~lexigram.ai.prompt.service.service.PromptService.render`. 

102 

103 Attributes: 

104 name: Template name that was rendered. 

105 version: Concrete version that was used (never ``"latest"``). 

106 rendered: The fully substituted prompt string. 

107 provider: Provider the escaping was applied for. 

108 """ 

109 

110 name: str 

111 version: str 

112 rendered: str 

113 provider: LLMProvider 

114 

115 

116__all__ = [ 

117 "LLMProvider", 

118 "PromptRenderRequest", 

119 "PromptRenderResult", 

120 "PromptTemplate", 

121]