Skip to main content

dd-llm

Shared LLM abstraction layer for Digital Duck projects.

Zero core dependencies. Adapters lazy-import their SDKs only when used.

Install

pip install -e .              # zero deps — claude_cli adapter works out of the box
pip install -e ".[openai]"    # + OpenAI SDK (also covers openrouter, ollama)
pip install -e ".[anthropic]" # + Anthropic SDK
pip install -e ".[gemini]"    # + Google GenAI SDK
pip install -e ".[momagrid]"   # + httpx (Momagrid hub)
pip install -e ".[bedrock]"    # + boto3
pip install -e ".[all]"       # all provider SDKs

Quick Start

from dd_llm import call_llm

# Uses LLM_PROVIDER env var (default: "openai")
response = call_llm("What is 2+2?")

# Specify provider
response = call_llm("Hello", provider="claude_cli")

# With messages
response = call_llm(messages=[
    {"role": "system", "content": "You are helpful."},
    {"role": "user", "content": "Hi"},
])

Built-in Adapters

Name Class Needs Notes
claude_cli ClaudeCLIAdapter the claude CLI Dev provider, $0 via Claude Code subscription. Prompt goes in via stdin; ANTHROPIC_API_KEY is stripped from the child so it cannot bill the paid API; limit errors carry error_type == "ModelOverloaded"
gemini_cli GeminiCLIAdapter the gemini CLI Same idea for Gemini CLI
openai OpenAIAdapter openai Direct OpenAI API
anthropic AnthropicAdapter anthropic Direct Anthropic API
gemini GeminiAdapter google-genai Direct Google API
vertex VertexAdapter google-genai Gemini on Vertex AI (ADC auth)
openrouter OpenAIAdapter (configured) openai OpenAI-compatible endpoint
ollama OpenAIAdapter (configured) openai Local OpenAI-compatible endpoint
deepseek OpenAIAdapter (configured) openai, DEEPSEEK_API_KEY DeepSeek API
qwen OpenAIAdapter (configured) openai, DASHSCOPE_API_KEY Alibaba DashScope
azure_openai AzureOpenAIAdapter openai, AZURE_OPENAI_* model is the deployment name
bedrock BedrockAdapter boto3 Converse API; estimates cost
momagrid MomagridAdapter httpx Decentralised inference via a Momagrid hub; fills response_worker
echo EchoAdapter none Returns the prompt; for tests

dd_llm.model_compatible(adapter, model) says whether a model name is plausible for an adapter (claude_cli only speaks claude-*, openrouter models contain a slash, ...), so callers can drop a stray model hint instead of making a doomed call.

dd_llm.parse_llm_spec("claude_cli:claude-haiku-5-5") returns ("claude_cli", "claude-haiku-5-5"). It is the parser behind the --llm ADAPTER:MODEL flag of the CLIs built on dd-llm (grafr, spl3): only the first : splits, so ollama:gemma3:12b and openrouter:meta/llama-3 work, and a bare claude_cli gives ("claude_cli", None).

Custom Adapters

from dd_llm import LLMAdapter, LLMResponse, register_adapter, call_llm

class MyAdapter(LLMAdapter):
    def call(self, prompt="", *, messages=None, **kwargs):
        result = my_internal_api(prompt)
        return LLMResponse(content=result, success=True, provider="my_api", model="v1")

register_adapter("my_api", MyAdapter)

# Now usable everywhere
response = call_llm("hello", provider="my_api")

UnifiedLLMProvider

Multi-provider client with retry (exponential backoff + jitter) and automatic fallback to alternative providers.

from dd_llm import UnifiedLLMProvider

provider = UnifiedLLMProvider(
    primary_provider="openai",
    fallback_providers=["anthropic", "ollama"],
    max_retries=3,
)

result = provider.call("Explain quantum computing")
if result.success:
    print(result.content)
    print(f"Provider: {result.provider}, Model: {result.model}")
    print(f"Tokens: {result.input_tokens} in, {result.output_tokens} out")

Environment Variables

Variable Description Default
LLM_PROVIDER Primary provider name openai
LLM_MODEL Default model (all providers) per-provider
LLM_MODEL_OPENAI Override model for OpenAI gpt-4o
LLM_MODEL_ANTHROPIC Override model for Anthropic claude-sonnet-4-5-20250929
LLM_MODEL_GEMINI Override model for Gemini gemini-2.0-flash
LLM_MAX_RETRIES Max retries per provider 3
LLM_INITIAL_WAIT Initial backoff (seconds) 1
LLM_MAX_WAIT Max backoff (seconds) 30
OPENAI_API_KEY OpenAI API key —
ANTHROPIC_API_KEY Anthropic API key —
GEMINI_API_KEY Google Gemini API key —
OPENROUTER_API_KEY OpenRouter API key —
OLLAMA_HOST Ollama base URL http://localhost:11434
DEEPSEEK_API_KEY, DASHSCOPE_API_KEY DeepSeek, Qwen keys —
AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_API_KEY, AZURE_OPENAI_API_VERSION Azure OpenAI —
MOMAGRID_HUB_URL, MOMAGRID_API_KEY Momagrid hub (else ~/.igrid/config.yaml) http://localhost:9000
GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION Vertex AI —

License

MIT

Metadata

Release files for dd-llm 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dd-llm 0.2.0
File Size Uploaded Provenance
dd_llm-0.2.0.tar.gz 25.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for dd-llm 0.2.0
File Interpreter ABI Platform
dd_llm-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.0 kB

Release files / dd_llm-0.2.0.tar.gz

Download URL dd_llm-0.2.0.tar.gz
Size 25.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cb50ff8bf179ee4606ec658ab1822c5d7c8b2b62f4e7115c6568e9b1921c6cd0
BLAKE2b-256 checksum
How to use checksums
0af87f2d2ec35277a1ce591dda652a8629d704b91ed784ab3041b71910a2da29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.5

Release files / dd_llm-0.2.0-py3-none-any.whl

Download URL dd_llm-0.2.0-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
03e5427ef02808daee2e77da775e38e758db2cdb50615f41bab16d22e1a1f3a5
BLAKE2b-256 checksum
How to use checksums
b4a66cdc59f230f497435af9b93f251e7a86941a5b95667638e9c91604986fd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.5

Security for dd-llm 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page