"""
LLM sub-package for HypoTestX.
Public API
----------
get_backend(spec, **kwargs) -> LLMBackend
Resolve a backend from a string, class, instance, or callable.
build_schema(df) -> SchemaInfo
Snapshot a DataFrame into a SchemaInfo for the prompt.
"""
from __future__ import annotations
from typing import Any
from .base import LLMBackend, RoutingResult, SchemaInfo, CallableBackend
from .prompts import build_schema, build_system_prompt, build_user_prompt
from .backends import (
OllamaBackend,
OpenAICompatBackend,
GeminiBackend,
HuggingFaceBackend,
FallbackBackend,
)
# ---------------------------------------------------------------------------
# Backend factory
# ---------------------------------------------------------------------------
_STRING_MAP = {
"ollama": OllamaBackend,
"openai": lambda **kw: OpenAICompatBackend(provider="openai", **kw),
"groq": lambda **kw: OpenAICompatBackend(provider="groq", **kw),
"together": lambda **kw: OpenAICompatBackend(provider="together", **kw),
"perplexity": lambda **kw: OpenAICompatBackend(provider="perplexity", **kw),
"mistral": lambda **kw: OpenAICompatBackend(provider="mistral", **kw),
"azure": lambda **kw: OpenAICompatBackend(provider="azure", **kw),
"gemini": GeminiBackend,
"huggingface": HuggingFaceBackend,
"hf": HuggingFaceBackend,
"fallback": FallbackBackend,
"regex": FallbackBackend,
"none": FallbackBackend,
}
[docs]
def get_backend(spec: Any = None, **kwargs) -> LLMBackend:
"""
Resolve *spec* to a concrete ``LLMBackend`` instance.
Parameters
----------
spec : str | LLMBackend | callable | None
- ``None`` / ``"fallback"`` → FallbackBackend (regex, offline)
- ``"gemini"`` → GeminiBackend
- ``"ollama"`` → OllamaBackend
- ``"openai"`` → OpenAICompatBackend(provider="openai")
- ``"groq"`` → OpenAICompatBackend(provider="groq")
- ``"together"`` → OpenAICompatBackend(provider="together")
- ``"mistral"`` → OpenAICompatBackend(provider="mistral")
- ``"perplexity"`` → OpenAICompatBackend(provider="perplexity")
- ``"huggingface"`` → HuggingFaceBackend
- An ``LLMBackend`` instance → returned as-is
- A ``callable`` → wrapped in CallableBackend
**kwargs
Forwarded verbatim to the backend constructor. Supported kwargs:
+-----------------+--------------------------------------+------------------------+
| kwarg | backends | default |
+=================+======================================+========================+
| ``api_key`` | gemini, openai, groq, together, … | — |
| ``model`` | all | provider default |
| ``timeout`` | all | 60 s |
| ``temperature`` | gemini, openai-compat, huggingface | 0.0 |
| ``max_tokens`` | gemini, openai-compat, huggingface | 512 |
| ``host`` | ollama | localhost:11434 |
| ``options`` | ollama | {"temperature": 0} |
| ``token`` | huggingface | — |
| ``use_local`` | huggingface | False |
| ``device`` | huggingface (local) | "cpu" |
| ``base_url`` | openai-compat | provider default |
| ``provider`` | openai-compat | "openai" |
| ``extra_headers``| openai-compat | None |
+-----------------+--------------------------------------+------------------------+
Examples
--------
>>> from hypotestx.core.llm import get_backend
>>> b = get_backend("gemini", api_key="AIza...", model="gemini-2.0-flash-lite")
>>> b = get_backend("groq", api_key="gsk_...", model="llama-3.3-70b-versatile")
>>> b = get_backend("openai", api_key="sk-...", model="gpt-4o", temperature=0.2)
>>> b = get_backend("ollama", model="mistral", host="http://localhost:11434")
>>> b = get_backend("huggingface", token="hf_...", model="HuggingFaceH4/zephyr-7b-beta")
>>> b = get_backend("huggingface", model="microsoft/Phi-3.5-mini-instruct",
... use_local=True, device="cuda")
>>> b = get_backend("together", api_key="...", model="meta-llama/Llama-3-70b-chat-hf")
>>> b = get_backend("mistral", api_key="...", model="mistral-large-latest")
"""
if spec is None:
return FallbackBackend()
if isinstance(spec, LLMBackend):
return spec
# Duck-type: accept any object that exposes a .route() method even if it
# doesn't formally inherit from LLMBackend (useful for testing stubs and
# third-party wrappers).
if hasattr(spec, "route") and callable(getattr(spec, "route")) and not isinstance(spec, type):
return spec # type: ignore[return-value]
if callable(spec) and not isinstance(spec, type):
return CallableBackend(spec)
if isinstance(spec, str):
key = spec.strip().lower()
if key not in _STRING_MAP:
raise ValueError(
f"Unknown backend '{spec}'. "
f"Choose from: {', '.join(_STRING_MAP)}"
)
cls_or_fn = _STRING_MAP[key]
return cls_or_fn(**kwargs)
if isinstance(spec, type) and issubclass(spec, LLMBackend):
return spec(**kwargs)
raise TypeError(
f"backend must be None, a string, an LLMBackend instance, "
f"or a callable — got {type(spec).__name__!r}"
)
__all__ = [
# Factory
"get_backend",
# Base classes / data classes
"LLMBackend",
"CallableBackend",
"RoutingResult",
"SchemaInfo",
# Prompt helpers
"build_schema",
"build_system_prompt",
"build_user_prompt",
# Concrete backends
"OllamaBackend",
"OpenAICompatBackend",
"GeminiBackend",
"HuggingFaceBackend",
"FallbackBackend",
]