Python API Reference
Complete reference for using llm-discovery as a Python library.
Package Version
Get the installed version of llm-discovery:
from llm_discovery import __version__
print(__version__) # Example: "0.1.0"
The version is dynamically retrieved from package metadata using importlib.metadata.
Note
The version attribute uses Pydantic v2 for data validation throughout the library.
All model classes inherit from pydantic.BaseModel for automatic validation and serialization.
DiscoveryClient Class
The main interface for fetching and managing LLM model information.
Import
from llm_discovery import DiscoveryClient
Constructor
class DiscoveryClient:
def __init__(
self,
*,
config: Config | None = None
):
"""
Initialize DiscoveryClient.
Args:
config: Configuration object (auto-generated from environment variables if None)
Raises:
ConfigurationError: Required environment variables not set
RuntimeError: Configuration validation failed
"""
Example:
from llm_discovery import DiscoveryClient
# Auto-configuration from environment variables
client = DiscoveryClient()
# Custom configuration
from llm_discovery.models import Config
custom_config = Config.from_env()
client = DiscoveryClient(config=custom_config)
fetch_models()
Fetch model list from all providers concurrently.
async def fetch_models(self) -> list[Model]:
"""
Fetch model list from all providers.
Returns:
List of Model objects
Raises:
ProviderFetchError: API fetch failed (fail-fast behavior)
PartialFetchError: Partial fetch failure
AuthenticationError: Invalid credentials
ConfigurationError: Environment variables not set
"""
Example:
import asyncio
from llm_discovery import DiscoveryClient
from llm_discovery.exceptions import ProviderFetchError, PartialFetchError
async def main():
client = DiscoveryClient()
try:
models = await client.fetch_models()
print(f"Fetched {len(models)} models")
for model in models:
print(f"{model.provider_name}/{model.model_id}: {model.model_name}")
except ProviderFetchError as e:
print(f"API fetch failed: {e}")
# External retry management (cron, CI/CD, etc.)
except PartialFetchError as e:
print(f"Partial failure: {e}")
print(f"Successful providers: {e.successful_providers}")
print(f"Failed providers: {e.failed_providers}")
asyncio.run(main())
Tip
Use asyncio.run() for async best practices. The library is fully async-native using modern Python async/await patterns.
get_cached_models()
Retrieve models from local cache without API calls.
def get_cached_models(self) -> list[Model]:
"""
Retrieve models from local cache.
Returns:
List of cached Model objects
Raises:
CacheNotFoundError: Cache file does not exist
CacheCorruptedError: Cache file is corrupted or invalid
"""
Example:
from llm_discovery import DiscoveryClient
from llm_discovery.exceptions import CacheNotFoundError
client = DiscoveryClient()
try:
models = client.get_cached_models()
print(f"Loaded {len(models)} models from cache")
except CacheNotFoundError:
print("No cache found. Run 'update' command first.")
Config Class
Configuration management for llm-discovery.
Import
from llm_discovery.models.config import Config
from_env()
Create configuration from environment variables.
@classmethod
def from_env(cls) -> Config:
"""
Create Config from environment variables.
Returns:
Config object
Raises:
ConfigurationError: Required environment variables not set
ValueError: Invalid environment variable values
"""
Example:
from llm_discovery.models.config import Config
# Load from environment variables
config = Config.from_env()
print(config.openai_api_key) # Masked: "sk-...***"
print(config.cache_dir) # Path to cache directory
Environment Variables:
OPENAI_API_KEY: OpenAI API key (optional)GOOGLE_API_KEY: Google AI Studio API key (optional)GOOGLE_GENAI_USE_VERTEXAI: Use Vertex AI instead of AI Studio (optional, default: false)GOOGLE_APPLICATION_CREDENTIALS: Path to GCP credentials JSON (required if using Vertex AI)LLM_DISCOVERY_CACHE_DIR: Custom cache directory (optional, default:~/.cache/llm-discovery)
ProviderSnapshot Class
Represents a snapshot of models from a single provider.
Import
from llm_discovery.models.provider import ProviderSnapshot
Attributes
class ProviderSnapshot(BaseModel):
provider_name: str # Provider identifier (e.g., "openai", "google")
models: list[Model] # List of models from this provider
fetched_at: datetime # Timestamp when models were fetched (UTC)
source: ModelSource # Data source (API or CACHE)
Example:
from llm_discovery import DiscoveryClient
async def main():
client = DiscoveryClient()
snapshots = await client.fetch_all_models()
for snapshot in snapshots:
print(f"Provider: {snapshot.provider_name}")
print(f"Fetched at: {snapshot.fetched_at}")
print(f"Models: {len(snapshot.models)}")
Model Class
Represents a single LLM model.
Import
from llm_discovery.models.provider import Model
Attributes
class Model(BaseModel):
model_id: str # Unique model identifier
model_name: str # Human-readable model name
provider_name: str # Provider name
source: ModelSource # Data source (API or CACHE)
fetched_at: datetime # Timestamp (UTC)
capabilities: list[str] # Model capabilities (optional)
Example:
from llm_discovery import DiscoveryClient
async def main():
client = DiscoveryClient()
models = await client.fetch_models()
# Filter models by capability
chat_models = [m for m in models if "chat" in m.capabilities]
for model in chat_models:
print(f"{model.provider_name}/{model.model_id}")
print(f" Name: {model.model_name}")
print(f" Capabilities: {', '.join(model.capabilities)}")
Data Export Formats
Export model data in multiple formats.
JSON Export
from llm_discovery.services.exporters import JSONExporter
exporter = JSONExporter()
models = client.get_cached_models()
json_data = exporter.export(models)
# Save to file
with open("models.json", "w") as f:
f.write(json_data)
Output Format:
{
"models": [
{
"model_id": "gpt-4",
"model_name": "GPT-4",
"provider_name": "openai",
"source": "API",
"fetched_at": "2025-10-19T12:00:00Z",
"capabilities": ["chat", "completion"]
}
],
"metadata": {
"total_count": 1,
"fetched_at": "2025-10-19T12:00:00Z"
}
}
CSV Export
from llm_discovery.services.exporters import CSVExporter
exporter = CSVExporter()
csv_data = exporter.export(models)
with open("models.csv", "w") as f:
f.write(csv_data)
Output Format:
provider_name,model_id,model_name,source,fetched_at,capabilities
openai,gpt-4,GPT-4,API,2025-10-19T12:00:00Z,"chat,completion"
YAML Export
from llm_discovery.services.exporters import YAMLExporter
exporter = YAMLExporter()
yaml_data = exporter.export(models)
with open("models.yaml", "w") as f:
f.write(yaml_data)
Output Format:
models:
- model_id: gpt-4
model_name: GPT-4
provider_name: openai
source: API
fetched_at: '2025-10-19T12:00:00Z'
capabilities:
- chat
- completion
Markdown Export
from llm_discovery.services.exporters import MarkdownExporter
exporter = MarkdownExporter()
markdown_data = exporter.export(models)
with open("models.md", "w") as f:
f.write(markdown_data)
Output Format:
# LLM Models
| Provider | Model ID | Model Name | Source | Fetched At |
|----------|----------|------------|--------|------------|
| openai | gpt-4 | GPT-4 | API | 2025-10-19T12:00:00Z |
TOML Export
from llm_discovery.services.exporters import TOMLExporter
exporter = TOMLExporter()
toml_data = exporter.export(models)
with open("models.toml", "w") as f:
f.write(toml_data)
Output Format:
[[models]]
model_id = "gpt-4"
model_name = "GPT-4"
provider_name = "openai"
source = "API"
fetched_at = "2025-10-19T12:00:00Z"
capabilities = ["chat", "completion"]
Exception Handling
All exceptions inherit from LLMDiscoveryError.
Exception Hierarchy
LLMDiscoveryError
├── ConfigurationError # Configuration issues
├── ProviderFetchError # API fetch failures
│ ├── AuthenticationError # Invalid credentials
│ └── NetworkError # Network connectivity issues
├── PartialFetchError # Partial fetch failures
├── CacheError # Cache-related errors
│ ├── CacheNotFoundError # Cache file not found
│ └── CacheCorruptedError # Cache file corrupted
└── ExportError # Export format errors
Example Error Handling
from llm_discovery import DiscoveryClient
from llm_discovery.exceptions import (
ConfigurationError,
AuthenticationError,
ProviderFetchError,
CacheNotFoundError
)
async def fetch_with_error_handling():
try:
client = DiscoveryClient()
models = await client.fetch_models()
return models
except ConfigurationError as e:
print(f"Configuration error: {e}")
print("Please check environment variables")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
print("Please verify API keys")
except ProviderFetchError as e:
print(f"Failed to fetch models: {e}")
# Fallback to cache
try:
return client.get_cached_models()
except CacheNotFoundError:
print("No cache available")
raise
except Exception as e:
print(f"Unexpected error: {e}")
raise
Complete Usage Example
import asyncio
from datetime import UTC, datetime
from llm_discovery import DiscoveryClient
from llm_discovery.models.config import Config
from llm_discovery.services.exporters import JSONExporter
from llm_discovery.exceptions import (
ProviderFetchError,
CacheNotFoundError
)
async def main():
# Load configuration
config = Config.from_env()
client = DiscoveryClient(config=config)
# Fetch models from all providers
try:
models = await client.fetch_models()
print(f"✓ Fetched {len(models)} models from APIs")
except ProviderFetchError as e:
print(f"✗ API fetch failed: {e}")
# Fallback to cache
try:
models = client.get_cached_models()
print(f"✓ Loaded {len(models)} models from cache")
except CacheNotFoundError:
print("✗ No cache available")
return
# Filter models by provider
openai_models = [m for m in models if m.provider_name == "openai"]
google_models = [m for m in models if m.provider_name == "google"]
print(f"\nOpenAI models: {len(openai_models)}")
print(f"Google models: {len(google_models)}")
# Export to JSON
exporter = JSONExporter()
json_data = exporter.export(models)
with open("models.json", "w") as f:
f.write(json_data)
print(f"\n✓ Exported to models.json")
# Display recent models
recent_models = sorted(
models,
key=lambda m: m.fetched_at,
reverse=True
)[:10]
print("\nRecent models:")
for model in recent_models:
print(f" {model.provider_name}/{model.model_id}: {model.model_name}")
if __name__ == "__main__":
asyncio.run(main())
Next Steps
CLI Reference: See technical contract at
specs/001-llm-model-discovery/contracts/cli-interface.mdError Handling: See
specs/001-llm-model-discovery/contracts/error-handling.mdContributing: See
CONTRIBUTING.mdin the repository root