Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-guard/src/lexigram/ai/guard/output/length.py: 56%

18 statements  

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

1"""Output length guard. 

2 

3Rejects LLM responses that exceed a configured maximum length. 

4Used to prevent runaway generation and enforce SLA constraints. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import TYPE_CHECKING, Any 

10 

11from lexigram.ai.guard.output.base import AbstractOutputGuard 

12from lexigram.ai.guard.pipeline.result import GuardCheckResult 

13from lexigram.contracts.ai.guards import GuardResultProtocol 

14from lexigram.result import Ok, Result 

15 

16if TYPE_CHECKING: 

17 from lexigram.contracts.ai.exceptions import GuardError 

18 

19 

20class OutputLengthGuard(AbstractOutputGuard): 

21 """GuardProtocol that enforces a maximum LLM response length. 

22 

23 Args: 

24 max_chars: Maximum allowed character count in the response. 

25 action: Action when the limit is exceeded — ``"block"`` (default) 

26 or ``"warn"``. 

27 

28 Example:: 

29 

30 guard = OutputLengthGuard(max_chars=50000, action="warn") 

31 result = await guard.check(llm_response) 

32 """ 

33 

34 def __init__(self, max_chars: int, action: str = "block") -> None: 

35 """Initialise the output length guard. 

36 

37 Args: 

38 max_chars: Maximum allowed character count. 

39 action: ``"block"`` or ``"warn"``. 

40 """ 

41 super().__init__(action=action) 

42 self._max_chars = max_chars 

43 

44 async def check( 

45 self, 

46 content: str, 

47 *, 

48 original_input: str | None = None, 

49 metadata: dict[str, Any] | None = None, 

50 ) -> Result[GuardResultProtocol, GuardError]: 

51 """Check whether the response exceeds the configured length. 

52 

53 Args: 

54 content: LLM response text to measure. 

55 original_input: Unused — present for protocol compatibility. 

56 metadata: Optional metadata. 

57 

58 Returns: 

59 PASS if within limit; BLOCK or WARN if exceeded. 

60 """ 

61 length = len(content) 

62 if length <= self._max_chars: 

63 return Ok(GuardCheckResult.allow(self.name, char_count=length)) 

64 

65 if self._action == "warn": 

66 return Ok( 

67 GuardCheckResult.warn( 

68 self.name, 

69 reason=f"Response length {length} chars exceeds soft limit {self._max_chars}", 

70 char_count=length, 

71 max_chars=self._max_chars, 

72 ) 

73 ) 

74 

75 return Ok( 

76 GuardCheckResult.block( 

77 self.name, 

78 reason=f"Response length {length} chars exceeds maximum {self._max_chars}", 

79 char_count=length, 

80 max_chars=self._max_chars, 

81 ) 

82 ) 

83 

84 

85__all__ = ["OutputLengthGuard"]