Skip to main content

A thin, unified LLM abstraction layer. Call any LLM with a single API.

Project description

anyllm

anyllm logo

PyPI Python License

A thin, unified LLM abstraction layer. Call any LLM with a single API.

Local-first: Uses Ollama/llama.cpp by default. Cloud APIs optional. When local models are available, anyllm automatically prefers them over cloud providers, ensuring your applications work offline.

Simpler than litellm -- focused on the essentials. No bloat, no complex abstractions. Just anyllm.chat().

Provider Support

Provider API Key Env Var Streaming Local
OpenAI (+ compatible APIs) OPENAI_API_KEY Yes No
Anthropic Claude ANTHROPIC_API_KEY Yes No
Ollama -- Yes Yes
llama.cpp server -- Yes Yes

Installation

pip install anyllm

With optional provider SDKs:

pip install anyllm[openai]      # OpenAI SDK
pip install anyllm[anthropic]   # Anthropic SDK
pip install anyllm[all]         # All optional SDKs

Note: anyllm works without any provider SDKs installed -- it uses httpx for all HTTP calls by default.

Quick Start

Simple Chat

import anyllm

# Auto-detects the best available provider
response = anyllm.chat("What is the meaning of life?")
print(response.content)

OpenAI

export OPENAI_API_KEY="sk-..."
response = anyllm.chat("Hello!", model="openai/gpt-4")
print(response.content)
print(f"Tokens used: {response.usage.total_tokens}")

Anthropic Claude

export ANTHROPIC_API_KEY="sk-ant-..."
response = anyllm.chat("Hello!", model="anthropic/claude-sonnet-4-20250514")
print(response.content)

Ollama (Local)

ollama pull llama3
response = anyllm.chat("Hello!", model="ollama/llama3")
print(response.content)

llama.cpp Server

./llama-server -m model.gguf
response = anyllm.chat("Hello!", model="llamacpp/default")
print(response.content)

Streaming

for chunk in anyllm.chat("Tell me a story", model="openai/gpt-4", stream=True):
    print(chunk, end="", flush=True)
print()

Full Message Format

response = anyllm.chat(
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What is Python?"},
    ],
    model="openai/gpt-4",
    temperature=0.7,
    max_tokens=500,
)

Or use the system parameter shorthand:

response = anyllm.chat(
    "What is Python?",
    model="openai/gpt-4",
    system="You are a helpful assistant.",
)

Configuration

Environment Variables

Variable Description
OPENAI_API_KEY OpenAI API key
OPENAI_BASE_URL Custom OpenAI-compatible API base URL
ANTHROPIC_API_KEY Anthropic API key
OLLAMA_HOST Ollama server URL (default: http://localhost:11434)
ANYLLM_DEFAULT_MODEL Default model to use

Config File

Create ~/.anyllm/config.json:

{
  "default_model": "openai/gpt-4",
  "openai_api_key": "sk-...",
  "ollama_base_url": "http://localhost:11434"
}

Programmatic Configuration

import anyllm

# Set default model
anyllm.set_default("ollama/llama3")

# Check available providers
print(anyllm.available_providers())  # ['openai', 'ollama']

# List models
print(anyllm.list_models())
# {'openai': ['gpt-4', 'gpt-3.5-turbo', ...], 'ollama': ['llama3', ...]}

# Direct config access
config = anyllm.get_config()
config.set("openai_base_url", "http://localhost:1234/v1")

Response Object

response = anyllm.chat("Hello!", model="openai/gpt-4")

response.content        # "Hello! How can I help you?"
response.model          # "gpt-4"
response.usage          # Usage(prompt_tokens=10, completion_tokens=8, total_tokens=18)
response.raw_response   # Raw API response dict

Local-First / Edge AI

anyllm is designed with a local-first philosophy. When auto-detecting providers, it checks local options (Ollama, llama.cpp) before cloud APIs. This means your applications work offline by default when local models are available.

import anyllm

# See what local models are available
print(anyllm.list_local_models())
# {'ollama': ['llama3', 'mistral', ...]}

# Auto-detection prefers local -- this uses Ollama if running
response = anyllm.chat("Hello!")

# Explicitly use a local model
response = anyllm.chat("Hello!", model="ollama/llama3")

Error Handling

anyllm includes automatic retry with exponential backoff for transient errors:

# Retries up to 3 times by default
response = anyllm.chat("Hello!", model="openai/gpt-4", max_retries=3)

License

MIT License. See LICENSE for details.

Author

Viet-Anh Nguyen -- nrl.ai -- GitHub

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anyllm-0.2.0.tar.gz (39.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anyllm-0.2.0-py3-none-any.whl (32.9 kB view details)

Uploaded Python 3

File details

Details for the file anyllm-0.2.0.tar.gz.

File metadata

  • Download URL: anyllm-0.2.0.tar.gz
  • Upload date:
  • Size: 39.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for anyllm-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e74e5d265f3ece7ca663012a5ff7934f29409dbf4a2d3ee64f923313484d3272
MD5 d8bfb2450c00f362884475ea19d6d0cf
BLAKE2b-256 94994a91a34723c37845212959cfdd33121a3c6f36003376fd21a4c35d9f50a6

See more details on using hashes here.

File details

Details for the file anyllm-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: anyllm-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 32.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for anyllm-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bf36d3acf00eb0ca9e0a8fe6ae855e6eef7dba747655be8b3b1b3bfec16c21fc
MD5 939a208bb1d0d52cc143bc15ab6194fb
BLAKE2b-256 102712c1d803aa23d1ad8d46cb705c97e176c4ab9a5628379b32177d74227caf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page