Metadata-Version: 2.4
Name: llm-rosetta
Version: 0.2.5
Summary: LLM-Rosetta: A library to convert between different LLM provider API standards using intermediate representation (IR).
Author-email: Oaklight <oaklight@gmx.com>
License-Expression: MIT
Project-URL: Documentation, https://llm-rosetta.readthedocs.io
Project-URL: Repository, https://github.com/Oaklight/llm-rosetta
Project-URL: Issues, https://github.com/Oaklight/llm-rosetta/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typing_extensions>=4.0.0; python_version < "3.11"
Provides-Extra: openai
Requires-Dist: openai; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic; extra == "anthropic"
Provides-Extra: google
Requires-Dist: google-genai; extra == "google"
Provides-Extra: gateway
Requires-Dist: starlette>=0.27.0; extra == "gateway"
Requires-Dist: uvicorn>=0.24.0; extra == "gateway"
Requires-Dist: httpx[socks]>=0.25.0; extra == "gateway"
Provides-Extra: dev
Requires-Dist: python-dotenv; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ty>=0.0.21; extra == "dev"
Requires-Dist: build>=1.2.2.post1; extra == "dev"
Requires-Dist: twine>=6.1.0; extra == "dev"
Provides-Extra: all
Requires-Dist: llm-rosetta[anthropic,dev,gateway,google,openai]; extra == "all"
Dynamic: license-file

# LLM-Rosetta

[![PyPI version](https://img.shields.io/pypi/v/llm-rosetta?color=green)](https://pypi.org/project/llm-rosetta/)
[![GitHub release](https://img.shields.io/github/v/release/Oaklight/llm-rosetta?color=green)](https://github.com/Oaklight/llm-rosetta/releases/latest)
[![CI](https://github.com/Oaklight/llm-rosetta/actions/workflows/ci.yml/badge.svg)](https://github.com/Oaklight/llm-rosetta/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Oaklight/llm-rosetta)

[English Version](README_en.md) | [中文版](README_zh.md)

**LLM-Rosetta** — A Python library for converting between different LLM provider API formats using a hub-and-spoke architecture with a central IR (Intermediate Representation).

## Full Documentation

Full documentation is available at:

- **English**: [https://llm-rosetta.readthedocs.io/en/latest/](https://llm-rosetta.readthedocs.io/en/latest/)
- **中文**: [https://llm-rosetta.readthedocs.io/zh-cn/latest/](https://llm-rosetta.readthedocs.io/zh-cn/latest/)

## The Problem

When building applications that work with multiple LLM providers, you face an N² conversion problem — every provider pair requires its own conversion logic. LLM-Rosetta solves this with a hub-and-spoke approach: each provider only needs a single converter to/from the shared IR format.

```
Provider A ──→ IR ──→ Provider B
Provider C ──→ IR ──→ Provider D
         ... and so on
```

## Supported Providers

| Provider | API Standard | Request | Response | Streaming |
|----------|-------------|:-------:|:--------:|:---------:|
| OpenAI | Chat Completions | ✅ | ✅ | ✅ |
| OpenAI | Responses API | ✅ | ✅ | ✅ |
| Anthropic | Messages API | ✅ | ✅ | ✅ |
| Google | GenAI API | ✅ | ✅ | ✅ |

### Ollama & Other OpenAI-Compatible Servers

LLM-Rosetta works out of the box with any server that exposes OpenAI-compatible endpoints. [Ollama](https://ollama.com/) (v0.13+) is a great example — it supports three of the four API formats that LLM-Rosetta converts between:

| Ollama Endpoint | LLM-Rosetta Converter | Since |
|---|---|---|
| `/v1/chat/completions` | `openai_chat` | Early versions |
| `/v1/responses` | `openai_responses` | v0.13.3 |
| `/v1/messages` | `anthropic` | v0.14.0 |

Other compatible servers include [HuggingFace TGI](https://github.com/huggingface/text-generation-inference), [vLLM](https://github.com/vllm-project/vllm), and [LM Studio](https://lmstudio.ai/).

## Features

- Unified IR format for messages, tool calls, and content parts
- Bidirectional conversion: requests to provider format, responses from provider format
- Streaming support with typed stream events
- Auto-detection of provider from request/response objects
- Support for text, images, tool calls, and tool results
- Zero required dependencies (only `typing_extensions`); provider SDKs are optional

## Installation

### Basic Installation

Install the core package (requires **Python >= 3.8**):

```bash
pip install llm-rosetta
```

### Installing with Provider SDKs

```bash
# Individual providers
pip install llm-rosetta[openai]
pip install llm-rosetta[anthropic]
pip install llm-rosetta[google]

# All providers
pip install llm-rosetta[openai,anthropic,google]
```

### Optional Dependencies

| Extra | Packages | Description |
|-------|----------|-------------|
| `openai` | `openai` | OpenAI Chat Completions & Responses API |
| `anthropic` | `anthropic` | Anthropic Messages API |
| `google` | `google-genai` | Google GenAI API |

## Quick Start

```python
from llm_rosetta import OpenAIChatConverter, AnthropicConverter

# Create converters
openai_conv = OpenAIChatConverter()
anthropic_conv = AnthropicConverter()

# Convert an OpenAI response to IR, then to Anthropic format
ir_messages = openai_conv.response_from_provider(openai_response)
anthropic_request = anthropic_conv.request_to_provider(ir_messages)
```

### Auto-Detection

```python
from llm_rosetta import convert, detect_provider

# Automatically detect provider and convert
provider = detect_provider(some_response)
ir_messages = convert(some_response, direction="from_provider")
```

### Cross-Provider Conversation

```python
from llm_rosetta import OpenAIChatConverter, GoogleGenAIConverter
from llm_rosetta.types.ir import Message, ContentPart

# Shared IR message history
ir_messages = []

# Turn 1: Ask OpenAI
ir_messages.append(Message(role="user", content=[ContentPart(type="text", text="Hello!")]))
openai_request = openai_conv.request_to_provider({"messages": ir_messages})
openai_response = openai_client.chat.completions.create(**openai_request)
ir_messages.extend(openai_conv.response_from_provider(openai_response))

# Turn 2: Continue with Google — full context preserved
google_request = google_conv.request_to_provider({"messages": ir_messages})
```

## Related Projects

LLM-Rosetta is part of the ToolRegistry ecosystem:

- **[ToolRegistry](https://github.com/Oaklight/ToolRegistry)** — Tool registration and management for LLM function calling
- **[ToolRegistry Hub](https://github.com/Oaklight/toolregistry-hub)** — Ready-to-use tool collection
- **[ToolRegistry Server](https://github.com/Oaklight/toolregistry-server)** — OpenAPI and MCP server adapters

## Contributing

Contributions are welcome! Please visit the [GitHub repository](https://github.com/Oaklight/llm-rosetta) to get started.

## License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
