Skip to main content

SmolLLM

A minimal Python library for interacting with various LLM providers, featuring automatic API key load balancing and streaming responses.

Installation

pip install smolllm
uv add "smolllm @ ../smolllm"

Quick Start

import asyncio
from smolllm import ask_llm

async def main():
    response = await ask_llm(
        "Say hello world",
        model="gemini/gemini-2.0-flash"
    )
    print(response)
    print(response.actual_model)

if __name__ == "__main__":
    asyncio.run(main())

response.model is the winning requested model spec. response.resolved_model is the optional model identity reported by the server. Use response.actual_model for the best available identity: reported when present, otherwise requested.

Reasoning Effort

For reasoning-capable models, pass reasoning_effort through to the provider. Useful for Ollama reasoning models where omitting it can make replies much slower.

response = await ask_llm(
    "Reply with one word.",
    model="ollama/qwen3.5:0.8b",
    base_url="http://rocry-ubuntu.local:11434/v1",
    reasoning_effort="none",
)

Images

image_paths accepts file paths or data: URLs. Each image becomes an image_url part on the last user message: the prompt string, or the last entry of a message list. Files are base64-encoded with a mime type guessed from the extension.

response = await ask_llm(
    "What is in this picture?",
    model="openai/gpt-4o",
    image_paths=["photo.jpg", "data:image/png;base64,iVBORw0..."],
)

With a message list the last message must be a user turn with content, or a ValueError is raised.

Tool Calling

Pass tools through the extra_body escape hatch; assembled tool calls come back on the response. smolllm never executes a tool — you run the loop and replay the results as assistant + tool messages. See examples/tool_calling.py.

response = await ask_llm(messages, extra_body={"tools": TOOLS})
for call in response.tool_calls:
    name = call["function"]["name"]
    args = json.loads(call["function"]["arguments"])

extra_body also carries any other raw request field the library does not model (response_format, service_tier, provider-private params); it is merged last, so you win over library defaults. Fields the library reads back — stream, stream_options, messages, model — are rejected.

Provider Configuration

Format: provider/model_name (e.g., openai/gpt-4, gemini/gemini-2.0-flash)

A bare model name (no /) targets an endpoint directly — pass base_url and api_key explicitly (no env fallback):

response = await ask_llm(
    "hi",
    model="gpt-4",
    base_url="https://my-proxy.example/v1",
    api_key="sk-xxx",
)

API Keys

The library looks for API keys in environment variables following the pattern: {PROVIDER}_API_KEY

Example:

# .env
OPENAI_API_KEY=sk-xxx
GEMINI_API_KEY=key1,key2  # Multiple keys supported

Key/endpoint pairs rejected with a permanent credential status (for example CONSUMER_SUSPENDED or API_KEY_INVALID) are removed from the active pool for the rest of the process lifetime. Error logs redact credential-shaped content; eviction is identified only by a one-way key fingerprint.

Custom Base URLs

Override default API endpoints using: {PROVIDER}_BASE_URL

Example:

OPENAI_BASE_URL=https://custom.openai.com/v1
OLLAMA_BASE_URL=http://localhost:11434/v1

Advanced Configuration

You can combine multiple keys and base URLs in several ways:

  1. One key with multiple base URLs:
OLLAMA_API_KEY=ollama
OLLAMA_BASE_URL=http://localhost:11434/v1,http://other-server:11434/v1
  1. Multiple keys with one base URL:
GEMINI_API_KEY=key1,key2
GEMINI_BASE_URL=https://api.gemini.com/v1
  1. Paired keys and base URLs:
# Must have equal number of keys and URLs
# The library will randomly select matching pairs
GEMINI_API_KEY=key1,key2
GEMINI_BASE_URL=https://api.gemini.com/v1,https://api.gemini.com/v2

Environment Setup Best Practices

When using SmolLLM in your project, you should handle environment variables at your application level:

  1. Create a .env file:
# .env
OPENAI_API_KEY=sk-xxx
GEMINI_API_KEY=xxx,xxx2
ANTHROPIC_API_KEY=sk-xxx
  1. Load the file at the application/process boundary:
uv run --env-file .env app.py

Tips

  • Keep sensitive API keys in .env (add to .gitignore)
  • Create .env.example for documentation
  • For production, consider using your platform's secret management system
  • When using multiple keys, separate with commas (no spaces)

Metadata

Release files for smolllm 0.12.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 smolllm 0.12.0
File Size Uploaded
smolllm-0.12.0.tar.gz 92.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for smolllm 0.12.0
File Interpreter ABI Platform
smolllm-0.12.0-py3-none-any.whl Python 3 none any Details

Total release size: 128.8 kB

Release files / smolllm-0.12.0.tar.gz

Download URL smolllm-0.12.0.tar.gz
Size 92.2 kB
Tags Source
SHA-256 checksum
How to use checksums
07f58b5df47e8fc741606c72d92490cb6df922ba460f6d27ae6b4f3d57ad06e6
BLAKE2b-256 checksum
How to use checksums
c894994404eeb53ffaa8b25b94802ddccad569edd8ec597e56d3d8994fdff55d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / smolllm-0.12.0-py3-none-any.whl

Download URL smolllm-0.12.0-py3-none-any.whl
Size 36.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23c03d83cb8bcf1dd1b93bb3f9c7c123f926545d1e92552e0c04174d1d4fbfe9
BLAKE2b-256 checksum
How to use checksums
1d609e1141926fab60994edd5ca49088061fd971adeb2cc030a92610fa22e16c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.12.0 This release

2 release files

0.11.3

2 release files

0.11.2

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.5

2 release files

0.1.1

2 release files

0.1.0

2 release files

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