apicol
Couche d'abstraction Python pour appeler un LLM via plusieurs backends interchangeables. Une interface unifiée au format OpenAI pour parler à : API Anthropic native (avec caching, thinking, citations), LiteLLM (qui route vers OpenAI, Gemini, Mistral, Ollama, vLLM, LM Studio, OpenRouter et 100+ providers), et Claude Code CLI (claude -p, usage dev local uniquement).
Sélection du backend par variables d'environnement ou par objet Client configurable. Plusieurs backends peuvent cohabiter dans le même process (bench, fallback applicatif, comparaison).
Statut
v0.1.0 — alpha. Implémentation complète des trois backends (Anthropic natif, LiteLLM, claude -p dev-only), surface publique stable, ≥95 % de couverture. Streaming et tool calls reportés à v0.2/v0.3. Documentation associée :
README.md— ce fichierCLAUDE.md— instructions pour Claude Code travaillant sur ce repoARCHITECTURE.md— décisions techniques structurantesSPEC.md— contrat d'API publiqueCHANGELOG.md— historique des versionspyproject.toml— métadonnées du packagedocs/prd/— PRD-001 (architecture deux niveaux), PRD-002 (séparationclaude -p), PRD-003 (multi-backend simultané)
Pourquoi cette lib
LiteLLM résout déjà 90 % du problème (interface unifiée, 100+ providers, format OpenAI partout). apicol ajoute deux choses que LiteLLM ne fait pas bien :
- Un chemin Anthropic natif préservé. Le compatibility layer OpenAI d'Anthropic ne supporte ni le prompt caching ni le détail du thinking. Pour les usages long-context avec caching agressif, il faut le SDK Anthropic natif.
apicolexpose explicitement cette voie quandAPICOL_TYPE=anthropic, via une méthodeclient.anthropic_native(). - Un backend
claude -ppour le dev local interactif. Strictement marqué « dev only » et exposé via une fonction séparée — pas routé dans l'interface unifiée — pour éviter toute confusion avec un usage programmatique qui violerait les TOS Anthropic (voir PRD-002).
Le reste (OpenAI, Gemini, modèles locaux, OpenRouter) est délégué à LiteLLM sans réinventer la roue.
Installation
Depuis PyPI (cible v0.1.0)
pip install apicol
Depuis le repo Git (phase alpha)
# Dernière version de main
pip install git+https://github.com/JP/apicol.git
# Tag spécifique
pip install git+https://github.com/JP/apicol.git@v0.1.0
# Branche dev
pip install git+https://github.com/JP/apicol.git@dev
Installation editable (dev local)
git clone https://github.com/JP/apicol.git
cd apicol
pip install -e ".[dev]" # base + outils dev (pytest, ruff, mypy)
Ajout en dépendance d'un projet tiers
Dans pyproject.toml (par exemple celui d'Athanor) :
[project]
dependencies = [
"apicol>=0.1.0",
# OU depuis git en phase alpha
"apicol @ git+https://github.com/JP/apicol.git@main",
]
Dans requirements.txt :
apicol>=0.1.0
Avec uv :
uv add apicol
# ou depuis git
uv add "apicol @ git+https://github.com/JP/apicol.git"
Dépendances installées
apicol installe automatiquement :
anthropic(SDK natif pour le backend Anthropic et l'échappatoire native)litellm(délégation pour tous les autres backends)
Python ≥ 3.10 requis.
Variables d'environnement
| Variable | Valeurs | Rôle |
|---|---|---|
APICOL_TYPE |
anthropic, litellm |
Backend par défaut (utilisé par les fonctions globales chat, achat) |
APICOL_KEY |
string | Clé d'API par défaut |
APICOL_MODEL |
string | Modèle par défaut (ex. claude-opus-4-7, openai/gpt-5, ollama/qwen3:32b) |
APICOL_URL |
URL (optionnel) | Endpoint custom (vLLM local, LM Studio, gateway, etc.) |
Pour claude_cli_chat() aucune variable n'est requise.
Pour un usage multi-backend simultané, ces variables ne sont pas suffisantes — on construit des Client explicites (voir Usage ci-dessous).
Usage
Mode simple — fonctions globales et env vars
import os
import apicol
os.environ["APICOL_TYPE"] = "anthropic"
os.environ["APICOL_KEY"] = "sk-ant-..."
os.environ["APICOL_MODEL"] = "claude-opus-4-7"
response = apicol.chat(
messages=[{"role": "user", "content": "Bonjour"}],
reasoning_effort="medium",
)
print(response["choices"][0]["message"]["content"])
Bascule de backend sans toucher au code applicatif :
export APICOL_TYPE=litellm
export APICOL_MODEL=openai/gpt-5
export APICOL_KEY=sk-...
Mode async — achat
import asyncio, apicol
async def main():
response = await apicol.achat(
messages=[{"role": "user", "content": "Bonjour"}],
)
return response
asyncio.run(main())
Mode multi-backend — objet Client
Pour avoir plusieurs configurations actives simultanément dans le même process (bench, fallback applicatif, comparaison) :
import apicol
claude = apicol.Client(
backend="anthropic",
api_key="sk-ant-...",
model="claude-opus-4-7",
)
gpt = apicol.Client(
backend="litellm",
api_key="sk-...",
model="openai/gpt-5",
)
qwen_local = apicol.Client(
backend="litellm",
model="ollama/qwen3:32b",
base_url="http://localhost:11434",
)
prompt = [{"role": "user", "content": "Explique la relativité en 3 phrases"}]
# Bench parallèle
for name, client in [("claude", claude), ("gpt", gpt), ("qwen", qwen_local)]:
response = client.chat(prompt)
print(f"\n=== {name} ===\n{response['choices'][0]['message']['content']}")
Un Client est immutable après construction. Pour changer de configuration, on crée un nouveau client. Cette rigidité simplifie le raisonnement multi-instance.
Mode multi-backend async — AsyncClient
import asyncio, apicol
claude = apicol.AsyncClient(backend="anthropic", api_key="...", model="claude-opus-4-7")
gpt = apicol.AsyncClient(backend="litellm", api_key="...", model="openai/gpt-5")
async def bench():
return await asyncio.gather(
claude.chat(prompt),
gpt.chat(prompt),
)
claude_resp, gpt_resp = asyncio.run(bench())
Accès au SDK Anthropic natif (features avancées)
Pour le prompt caching avec breakpoints fins, les citations, le PDF input, le batch API, ou tout autre feature non-portable :
import apicol
# Via un Client
claude = apicol.Client(backend="anthropic", api_key="...", model="claude-opus-4-7")
native = claude.anthropic_native() # → anthropic.Anthropic préconfiguré
response = native.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
system=[
{
"type": "text",
"text": gros_document,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "Question sur le document"}],
)
# À partir d'ici, tu utilises le SDK Anthropic avec TOUTES ses features.
# Variante depuis les env vars (alias rétrocompatible)
native = apicol.anthropic_client() # équivalent à Client().anthropic_native()
Backend dev only — claude_cli_chat
⚠️ Dev only. Cette fonction est destinée à un usage personnel interactif (un script local que tu lances toi-même). Elle n'est pas destinée à servir une charge programmatique routée selon coût/dispo — un tel usage enfreint les TOS de Claude Pro/Max. Voir PRD-002 pour le détail.
import apicol
# Aucune variable APICOL_* requise — utilise le `claude` CLI authentifié localement
response = apicol.claude_cli_chat(
messages=[{"role": "user", "content": "Résume CHANGELOG.md du dossier courant"}],
)
print(response["choices"][0]["message"]["content"])
Cette fonction est volontairement séparée des fonctions globales chat() / achat() et des objets Client / AsyncClient : aucun chemin de routage ne mène automatiquement vers claude -p.
Paramètres unifiés (niveau 1)
Les méthodes Client.chat(), AsyncClient.chat() et les fonctions globales chat(), achat() acceptent tous les paramètres suivants :
| Paramètre | Type | Comportement |
|---|---|---|
messages |
list[dict] |
Format OpenAI standard |
model |
str | None |
Override du modèle du Client / des env vars |
temperature |
float | None |
0.0 à 2.0, sémantique OpenAI |
max_tokens |
int | None |
Default 4096 |
reasoning_effort |
"none" | "low" | "medium" | "high" |
Mappé selon backend (voir SPEC) |
extra_body |
dict |
Passthrough silencieux vers le SDK sous-jacent (ex. cache_control Anthropic) |
Détails complets et table de mapping reasoning_effort → thinking dans SPEC.md.
Hors périmètre
- Pas de cost tracking, virtual keys, rate limiting, dashboard. Utiliser le proxy LiteLLM standalone pour ça.
- Pas de routage automatique avec fallback/loadbalance au niveau de la lib. Pour ces patterns, l'application orchestre ses
Clientà la main. - Pas de support des modalités exotiques (audio, embeddings, fine-tuning) en v0.1. Chat completion uniquement.
- Pas de streaming en v0.1 (reporté à v0.2 — interface d'events unifiée à concevoir).
- Pas de support des tool calls en v0.1 (reporté à v0.3).
- Pas de routage automatique vers
claude -p. Volontaire — voir PRD-002.
Licence
À définir (MIT probablement).
Release files for apicol 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| apicol-0.1.0.tar.gz | 270.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apicol-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 287.5 kB
Release files / apicol-0.1.0.tar.gz
| Download URL | apicol-0.1.0.tar.gz |
|---|---|
| Size | 270.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f8e0bcefa25210f43a01a39613036cd4d9358c8e85cdf7c9e9a4d8bbeac255bd
|
|
BLAKE2b-256 checksum How to use checksums |
7722b42b4143ac39b7ba134f7b5fabef23d63235bce25e883e6af04330544c49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 14, 2026.
Transparency logRelease files / apicol-0.1.0-py3-none-any.whl
| Download URL | apicol-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
258dd5e96b361daa84c7c99f2339812b6a041cd803cd63d9701a2fef15f32728
|
|
BLAKE2b-256 checksum How to use checksums |
254eb0c282790e6b011ce552f12ac9ec9e722142daa9ca31e1c2af62c74de519
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 14, 2026.
Transparency log