Architecture¶
LLM Answer Watcher follows Domain-Driven Design principles with strict separation of concerns.
Core Domains¶
llm_answer_watcher/
├── config/ # Configuration loading and validation
├── llm_runner/ # LLM client abstraction
├── extractor/ # Brand mention detection
├── storage/ # SQLite and JSON persistence
├── report/ # HTML report generation
├── utils/ # Shared utilities
└── cli.py # CLI interface
Design Patterns¶
1. Provider Abstraction¶
class LLMClient(Protocol):
def generate_answer(self, prompt: str) -> LLMResponse:
...
def build_client(provider: str, model: str) -> LLMClient:
...
2. API-First Contract¶
def run_all(config: RuntimeConfig) -> dict:
# Internal "POST /run" contract
# OSS CLI calls in-process
# Cloud will expose over HTTP
return {"run_id": "...", "cost_usd": 0.01}
3. Dual-Mode CLI¶
class OutputMode(Enum):
HUMAN = "human" # Rich formatting
JSON = "json" # Structured output
QUIET = "quiet" # Minimal output
See API Contract for internal API details.