Source code for hypotestx.core.llm

"""
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", ]