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 .backends import (
    FallbackBackend,
    GeminiBackend,
    HuggingFaceBackend,
    OllamaBackend,
    OpenAICompatBackend,
)
from .base import CallableBackend, LLMBackend, RoutingResult, SchemaInfo
from .prompts import build_schema, build_system_prompt, build_user_prompt

# ---------------------------------------------------------------------------
# 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: .. list-table:: :header-rows: 1 :widths: 18 38 22 * - kwarg - backends - default * - ``api_key`` - gemini, openai, groq, together, ... - (required) * - ``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 - (required) * - ``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", ]