Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-llm/src/lexigram/ai/llm/di/factories.py: 52%
25 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Factory functions for creating LLM service instances from configuration.
3These factories are used by LLMProvider to construct concrete client
4implementations from typed config objects without hardcoding dependencies.
5"""
7from __future__ import annotations
9from typing import TYPE_CHECKING
11from lexigram.contracts.ai import LLMClientProtocol
12from lexigram.contracts.ai.providers import ProviderRegistryProtocol
13from lexigram.logging import (
14 get_logger,
15)
17if TYPE_CHECKING:
18 from lexigram.ai.llm.config import ClientConfig
19 from lexigram.ai.llm.protocols import LLMCacheProtocol
20 from lexigram.contracts.infra.cache import CacheBackendProtocol
22logger = get_logger(__name__)
25async def create_llm_client(
26 config: ClientConfig,
27 registry: ProviderRegistryProtocol,
28) -> LLMClientProtocol:
29 """Instantiate an LLM client from provider configuration via the registry.
31 Delegates to :class:`~lexigram.ai.llm.registry.ProviderRegistry` so that
32 all built-in **and** custom providers registered at runtime are supported
33 without requiring changes to this factory.
35 Args:
36 config: LLM-specific configuration block.
38 Returns:
39 A concrete LLMClientProtocol for the configured provider.
41 Raises:
42 ValueError: When ``config.provider`` is not registered.
43 """
44 try:
45 provider_info = registry.get_provider(config.provider) # type: ignore[attr-defined]
46 except KeyError as exc:
47 msg = f"Unsupported LLM provider: {config.provider!r}"
48 raise ValueError(msg) from exc
50 client = provider_info.client_class(config)
51 if not isinstance(client, LLMClientProtocol):
52 msg = (
53 f"LLM client for provider {config.provider!r} does not satisfy "
54 "the LLMClientProtocol protocol. Ensure the client implements complete(), "
55 "stream_chat(), health_check(), and close()."
56 )
57 raise TypeError(msg)
58 return client
61async def create_llm_cache(
62 config: ClientConfig,
63 cache: CacheBackendProtocol | None,
64) -> LLMCacheProtocol:
65 """Create an LLM response cache instance from configuration.
67 Args:
68 config: LLM configuration carrying cache settings.
69 cache: Platform cache backend (required when enable_cache=True).
71 Returns:
72 A configured LLMCacheProtocol instance.
74 Raises:
75 ValueError: When enable_cache is True but no CacheBackendProtocol is provided.
76 """
77 from lexigram.ai.llm.caching.core import LLMCache, RedisLLMCache
79 if cache is not None:
80 return RedisLLMCache(cache_backend=cache, ttl=config.cache_ttl) # type: ignore[return-value]
82 if config.enable_cache and cache is None:
83 msg = "CacheBackendProtocol required for LLM caching but not found in container"
84 raise ValueError(msg)
86 return LLMCache(ttl=config.cache_ttl) # type: ignore[return-value]