Metadata-Version: 2.5
Name: llm-provider-adapter
Version: 0.1.0
Summary: Provider-neutral synchronous chat adapters for OpenAI, Claude, DeepSeek, OpenRouter, and LiteLLM.
Project-URL: Homepage, https://github.com/zhanghao1903/llm-provider-adapter
Project-URL: Repository, https://github.com/zhanghao1903/llm-provider-adapter
Project-URL: Issues, https://github.com/zhanghao1903/llm-provider-adapter/issues
Author: Zhang Hao
License-Expression: MIT
License-File: LICENSE
Keywords: anthropic,deepseek,litellm,llm,openai,openrouter
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: pydantic<3,>=2.10
Provides-Extra: all
Requires-Dist: anthropic<1,>=0.119; extra == 'all'
Requires-Dist: litellm<2,>=1.83; extra == 'all'
Requires-Dist: openai<3,>=2.0; extra == 'all'
Provides-Extra: claude
Requires-Dist: anthropic<1,>=0.119; extra == 'claude'
Provides-Extra: deepseek
Requires-Dist: openai<3,>=2.0; extra == 'deepseek'
Provides-Extra: litellm
Requires-Dist: litellm<2,>=1.83; extra == 'litellm'
Provides-Extra: openai
Requires-Dist: openai<3,>=2.0; extra == 'openai'
Provides-Extra: openrouter
Requires-Dist: litellm<2,>=1.83; extra == 'openrouter'
Description-Content-Type: text/markdown

# llm-provider-adapter

`llm-provider-adapter` is a small, synchronous Python library for calling LLM
chat providers through one stable request, response, retry, error, and
telemetry contract.

Version 0.1 supports OpenAI, Claude, DeepSeek, OpenRouter, and LiteLLM. It does
not provide an Agent framework, persistence, secret storage, async calls,
streaming, multimodal content, or automatic cross-provider fallback.

## Install

Python 3.11 or newer is required. Install only the provider SDK you need:

```bash
pip install "llm-provider-adapter[openai]>=0.1.0,<0.2.0"
pip install "llm-provider-adapter[claude]>=0.1.0,<0.2.0"
pip install "llm-provider-adapter[deepseek]>=0.1.0,<0.2.0"
pip install "llm-provider-adapter[openrouter]>=0.1.0,<0.2.0"
pip install "llm-provider-adapter[litellm]>=0.1.0,<0.2.0"
```

Use `[all]` only when an application must expose every adapter. The core
distribution imports without any provider SDK.

## Minimal chat

Credentials, model IDs, and endpoints are always explicit. The library never
reads environment variables or persists secrets.

```python
from llm_provider_adapter import ChatRequest
from llm_provider_adapter.providers import OpenAIProvider

provider = OpenAIProvider(api_key="...")
response = provider.chat(
    ChatRequest(
        model="gpt-5-mini",
        messages=[{"role": "user", "content": "Return one short greeting."}],
        timeout_seconds=30,
    )
)
print(response.content)
```

No real request is made when using the fake example:

```bash
python examples/fake_chat.py
```

## Tool calling

Tools use the OpenAI function-tool shape at the public boundary. Provider
adapters translate it when required and normalize returned calls into
`ToolCall(id, name, arguments)`.

```python
request = ChatRequest(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "Weather in Shanghai?"}],
    tools=[
        {
            "type": "function",
            "function": {
                "name": "weather",
                "description": "Read weather for a city.",
                "parameters": {
                    "type": "object",
                    "properties": {"city": {"type": "string"}},
                    "required": ["city"],
                },
            },
        }
    ],
    tool_choice="auto",
)
```

Unsupported capabilities fail before the SDK request when possible. Parameters
are never silently discarded to make a request succeed.

## Errors, retries, and timeout

- `RetryPolicy` owns one bounded retry loop; SDK/LiteLLM retries are disabled.
- Authentication, invalid request, capability, and context-limit failures do
  not retry.
- Any recognized timeout, including an SDK-default timeout when the request
  omits `timeout_seconds`, is never automatically replayed because the upstream
  may already have accepted or billed the request.
- The library never changes provider automatically.
- Public errors and retry records omit raw SDK exception text, payloads,
  headers, credentials, and response bodies.

Catch `LLMProviderError` for normalized provider failures and
`MissingProviderExtraError` when the selected optional SDK is absent.

## Telemetry

Pass an object implementing `TelemetryObserver.on_event(event)` to a provider.
Request, response, retry, and error events include provider/model identifiers,
counts, status classifications, request IDs, and normalized usage only. They do
not include messages, tool arguments, headers, raw payloads, arbitrary request
metadata, or raw exception text. Observer failures never change the chat call.

## Documentation

- [Provider support](docs/provider-support.md)
- [Configuration](docs/configuration.md)
- [Security](docs/security.md)
- [Compatibility](docs/compatibility.md)
- [Migration from Taskweavn](docs/migration.md)
- [Release process](docs/releasing.md)

## Development

```bash
uv sync --all-extras --all-groups
uv run ruff check .
uv run mypy src tests
uv run pytest -q
uv build
uv run twine check dist/*
```

The project is licensed under the [MIT License](LICENSE).
