"""In-memory LLM for testing — returns canned responses, no API calls.""" from typing import Optional from domain.models import RuleSearchResult, LLMResponse from domain.ports import LLMPort class FakeLLM(LLMPort): """Returns predictable responses based on whether rules were provided. Configurable for testing specific scenarios (low confidence, errors, etc.). """ def __init__( self, default_answer: str = "Based on the rules, here is the answer.", default_confidence: float = 0.9, no_rules_answer: str = "I don't have a rule that addresses this question.", no_rules_confidence: float = 0.1, force_error: Optional[Exception] = None, ): self.default_answer = default_answer self.default_confidence = default_confidence self.no_rules_answer = no_rules_answer self.no_rules_confidence = no_rules_confidence self.force_error = force_error self.calls: list[dict] = [] async def generate_response( self, question: str, rules: list[RuleSearchResult], conversation_history: Optional[list[dict[str, str]]] = None, ) -> LLMResponse: self.calls.append( { "question": question, "rules": rules, "history": conversation_history, } ) if self.force_error: raise self.force_error if rules: return LLMResponse( answer=self.default_answer, cited_rules=[r.rule_id for r in rules], confidence=self.default_confidence, needs_human=False, ) else: return LLMResponse( answer=self.no_rules_answer, cited_rules=[], confidence=self.no_rules_confidence, needs_human=True, )