Metadata-Version: 2.5
Name: my-llm-py
Version: 1.0.4
Summary: Profile-driven async LLM adapter for OpenAI, Anthropic, Gemini and Ollama.
Project-URL: Repository, https://github.com/JJJJSTIYYYY/my-llm
Project-URL: Issues, https://github.com/JJJJSTIYYYY/my-llm/issues
Author-email: JJJJSTIYYYY <wavejustiy@gmail.com>
Maintainer-email: JJJJSTIYYYY <wavejustiy@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: adapter,adaptor,anthropic,gemini,llm,ollama,openai
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: anthropic<1,>=0.76
Requires-Dist: google-genai<2,>=1.56
Requires-Dist: ollama<1,>=0.6.3
Requires-Dist: openai<3,>=2.0
Description-Content-Type: text/markdown

<div align="center">

# my-llm-py

[![PyPI](https://img.shields.io/pypi/v/my-llm-py.svg)](https://pypi.org/project/my-llm-py/)
![Python](https://img.shields.io/badge/Python-3.12+-3776AB?style=flat&logo=python)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/JJJJSTIYYYY/my-llm/blob/main/LICENSE)
[![Discord](https://img.shields.io/badge/Discord-Join%20Us-5865F2?style=flat&logo=discord&logoColor=white)](https://discord.gg/tUCQthwK5)
[![QQ群](https://custom-icon-badges.demolab.com/badge/QQ群-639459172-00BFFF?style=flat&logo=tencent-qq)](https://qun.qq.com/universal-share/share?ac=1&authKey=ommoQrT2zhzHU%2FUxv8pfGCJbNifW%2BJyUAFBkNdzkHTPUxdxCnlgxm5aNgGslTmdE&busi_data=eyJncm91cENvZGUiOiI2Mzk0NTkxNzIiLCJ0b2tlbiI6Im9ZZkdNUWZnSVV1Y2REeUhKNnlTbWEwc05Bb093djRzUXdXNE55dklBVnlBQk9XbGNpS0ZXSDlzK3orSW1sQ3YiLCJ1aW4iOiIzMTI5NDI0NTcyIn0%3D&data=OGTchcr80RAQg8Z8_GZTdvBb7kZDeM9B3hHcNqLaAX2ZK_KYq260C4CubblEBT1bK5fP6zgtnCk2D8fIoph1ZQ&svctype=4&tempid=h5_group_info)

**通用的 LLM Provider 协议适配器**

</div>

my-llm-py 是一个 Python 异步 LLM 协议适配库，支持 OpenAI Chat、OpenAI Responses、Anthropic、Gemini 和 Ollama 五种协议自由组合。

**用一种协议请求另一种协议的 API，按输入协议返回结果。标准协议直接转换，非标准协议通过配置兼容。**

```text
OpenAI Chat 格式输入 → 任意协议 API → OpenAI Chat 格式输出
```

消息、工具和流事件一并转换。更换上游 API，业务层继续使用原有协议收发数据。

## 主要功能与亮点

| 功能 | 说明 |
| --- | --- |
| 跨协议调用 | 标准协议直接转换，输入输出协议与上游 API 独立选择。 |
| 轮次恢复 | 保留未知字段、原生签名与密文，未修改的转换结果可恢复原生轮次；请求前过滤不支持字段。 |
| 统一工具调用 | 转换工具定义、调用和结果；流式参数自动组装，响应成功结束后交付完整调用。工具由应用执行。 |
| 流式与完整回复 | 支持文本、可见思考增量；流结束后通过 `stream.result` 获取完整消息。 |
| 多模态转换 | 按协议与模型能力转换图片、音频、视频和文件等内容。 |
| 配置兼容 | 非标准协议通过配置兼容，适配服务与模型的参数、字段路径及思考内容等差异，配置可拓展。 |
| 独立格式转换 | 无需调用模型，即可转换消息、工具和完整流事件列表；标准模式下支持同协议无损往返。 |
| 异步并发 | 复用官方 SDK 客户端，请求状态独立；支持取消、提前退出和资源清理。 |
| 协议扩展 | 实现四个抽象基类并注册，即可接入现有调用与转换流程。 |

输入接受标准字典或可转为字典的官方 SDK 对象，输出为所选输入协议的标准字典。
跨协议转换受目标协议的表达能力限制，详见[兼容边界](docs/reference/configuration.md#跨协议请求的处理边界)。
新增协议通过 `MyCodec.register(codec)` 在启动时注册，协议默认值随 Codec 声明；
无需修改公共入口或协议枚举，详见[接入指南](docs/guides/adding-protocol.md)。

## 安装

需要 **Python 3.12+**。

```sh
pip install my-llm-py
# 或 uv add my-llm-py
```

## 快速开始

以下示例使用 **OpenAI Chat 格式**调用 **Anthropic Messages API**，返回 **Chat assistant 消息**。
设置 `ANTHROPIC_API_KEY` 和 `LLM_MODEL` 环境变量后运行，模型 ID 填写服务支持的值。

```python
import asyncio
import os

from my_llm import ModelProfile, MyLLM, ProviderProfile


async def main():
    async with MyLLM(
        provider=ProviderProfile(
            protocol="anthropic",  # 实际请求的 API 协议
            api_key=os.environ["ANTHROPIC_API_KEY"],
        ),
        model=ModelProfile(model=os.environ["LLM_MODEL"], max_tokens=4096),
        stdio_protocol="openai_chat",  # 输入和输出均使用 Chat 协议
    ) as llm:
        message = await llm.generate(messages=[{"role": "user", "content": "你好"}])
        print(message["content"])


asyncio.run(main())
```

更换 `provider.protocol` 及对应连接、模型配置，即可切换上游 API；`stdio_protocol` 决定业务层使用的格式。
建议像示例一样显式指定 `stdio_protocol`。省略时仅在消息与工具整批唯一匹配一种协议时自动绑定；
零匹配或多种协议都匹配时抛出 `MessageValidationError`。普通 role/content 文本存在协议歧义，需要显式指定。

### 流式调用

在上例的 `async with MyLLM(stdio_protocol="openai_chat", ...)` 内调用下面的函数，流事件也按 Chat (openai_chat) 协议返回：

```python
async def print_answer(llm):
    stream = await llm.generate(
        messages=[{"role": "user", "content": "你好"}],
        stream=True,
    )
    async with stream:
        async for event in stream:
            for choice in event.get("choices", []):
                print(choice["delta"].get("content", ""), end="", flush=True)
    return stream.result
```

使用 `async with` 管理实例和流。传入工具前，在 `ModelProfile` 中设置 `supports_function_calling=True`。

### 独立格式转换

`MyCodec` 可离线转换协议格式，无需 API 密钥：

```python
from my_llm import MyCodec

converted = MyCodec().convert(
    [{"role": "user", "content": "你好"}],
    input_format="openai_chat",
    target_format="gemini",
)
print(converted["messages"])
# [{"role": "user", "parts": [{"text": "你好"}]}]
```

## 支持的协议

以下标识均可用于 `ProviderProfile.protocol` 和 `stdio_protocol`：

| 协议标识 | 对应 API |
| --- | --- |
| `openai_chat` | OpenAI Chat Completions 及兼容服务 |
| `openai_responses` | OpenAI Responses 及兼容服务 |
| `anthropic` | Anthropic Messages |
| `gemini` | Gemini GenerateContent |
| `ollama` | Ollama Chat |

同一实例的消息与工具使用同一种输入输出协议。

## 安装最新的开发版本 (main 分支)

```sh
git clone https://github.com/JJJJSTIYYYY/my-llm.git
cd ./my-llm
uv sync --group dev --locked
uv run pytest -q
uv run ruff check src tests examples
uv run ruff format --check src tests examples
uv run python examples/local_demo.py
uv build
```

## 文档

- [API 使用指南](docs/reference/api.md)：生成、流式消费、工具回合与格式转换。
- [配置指南](docs/reference/configuration.md)：连接、模型、思考参数与兼容服务。
- [协议模板](docs/reference/schema/README.md)：五种协议的请求、返回和流事件。
- [扩展协议](docs/guides/adding-protocol.md) · [本地开发](docs/guides/development.md) · [构建验证](docs/guides/building.md)
- [全部文档](docs/README.md)

项目采用 [Apache License 2.0](LICENSE)。
