openai-io
轻量级的 OpenAI 大模型 IO 库:只保留 chat.completions / completions / embeddings
三件套,同步(OpenAI)与异步(AsyncOpenAI)双客户端,传输层基于 httpx,
数据模型基于 pydantic v2。
为什么不用官方 SDK
官方 SDK 功能全,但用起来有几处不太顺手:
- 太重。模型 IO 只占它的一小部分,
images、audio、files、batch、assistants这些资源平时根本用不到,依赖和包体积都跟着上去了。 messages是 TypedDict,{"role": "user", "content": "..."}全靠手写,没有对象、 没有自动补全,多轮对话拼起来很啰嗦。- 类型太绕:
NotGiven哨兵、一长串 Union、各种*_Param,IDE 提示经常是几行 联合类型,报错也不好读。
这个库只做 chat / completions / embeddings 三件事,messages 换成 langchain 风格的
对象,接口和官方 SDK 保持一致,迁移成本低。
特性
- 轻量:只依赖
httpx和pydantic - 同步
OpenAI与异步AsyncOpenAI双客户端 - langchain 风格 message:
SystemMessage/HumanMessage/AIMessage/ToolMessage/FunctionMessage/ChatMessage(不依赖 langchain-core) - 流式输出(SSE):
stream=True返回可迭代的Stream/AsyncStream - 异常体系与 openai SDK 对齐,自动重试(指数退避 + 抖动)
安装
pip install -e .
要求 Python >= 3.12。
快速开始
同步
from openai_io import OpenAI
from openai_io.messages import HumanMessage, SystemMessage
client = OpenAI() # 或 OpenAI(api_key="sk-...")
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
SystemMessage(content="你是一个友好的助手"),
HumanMessage(content="你好"),
],
)
print(resp.choices[0].message.content)
# embeddings
vectors = client.embeddings.create(model="text-embedding-3-small", input="你好")
print(vectors.data[0].embedding[:5])
# 旧版文本补全
comp = client.completions.create(model="gpt-3.5-turbo-instruct", prompt="1+1=?")
print(comp.choices[0].text)
异步
import asyncio
from openai_io import AsyncOpenAI
from openai_io.messages import HumanMessage
async def main() -> None:
client = AsyncOpenAI()
resp = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[HumanMessage(content="你好")],
)
print(resp.choices[0].message.content)
asyncio.run(main())
流式输出
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[HumanMessage(content="讲个故事")],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="")
异步流式使用 async for chunk in await client.chat.completions.create(..., stream=True)。
Message 体系(与原生 openai 的差异)
原生 openai SDK 的 messages 参数是 TypedDict 风格({"role": ..., "content": ...}),
本库改为 langchain 风格的类:
from openai_io import AIMessage, FunctionCall, HumanMessage, SystemMessage, ToolCall, ToolMessage
messages = [
SystemMessage(content="你是助手"),
HumanMessage(content="北京天气如何?"),
AIMessage(
content=None,
tool_calls=[ToolCall(id="call_1", function=FunctionCall(name="get_weather", arguments='{"city": "北京"}'))],
),
ToolMessage(content="晴,25°C", tool_call_id="call_1"),
]
BaseMessage抽象基类:content/additional_kwargs/response_metadata/name/id,type为类别标识("human"/"ai"/"tool"…)content支持多模态 part 列表([{"type": "text", ...}, {"type": "image_url", ...}])- 兼容原始 dict:
messages可以混合传入BaseMessage与{"role": ..., "content": ...}, 迁移时无需一次性替换全部代码 - pydantic 2.13 起构造参数为关键字形式:
HumanMessage(content="你好")
与 openai SDK 的对应关系
| openai SDK | openai-io |
|---|---|
from openai import OpenAI |
from openai_io import OpenAI |
client.chat.completions.create(...) |
client.chat.completions.create(...) |
client.completions.create(...) |
client.completions.create(...) |
client.embeddings.create(...) |
client.embeddings.create(...) |
from openai import AsyncOpenAI |
from openai_io import AsyncOpenAI |
openai.OpenAIError 等异常 |
openai_io.OpenAIError 等,类名一致 |
请求参数(temperature / max_tokens / tools / …) |
同名同语义;未传参不写入请求体(NotGiven 哨兵语义一致) |
| TypedDict messages | langchain 风格 BaseMessage(也可传 dict) |
create 的入口参数与 openai SDK 对齐,含 stream / stream_options / tools /
tool_choice / response_format / seed 等;未显式传参的字段不会出现在请求体中。
开发
uv sync --extra dev
uv run ruff check src tests && uv run ruff format --check src tests
uv run pyright
uv run pytest
测试使用 httpx.MockTransport 注入 mock 响应,无需真实 API key。
许可证
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openai_io-0.1.3.tar.gz.
File metadata
- Download URL: openai_io-0.1.3.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cc159587f4b185f4ee595afb9c8baa90d8ab4ab1129986ff5e857b893ae352c
|
|
| MD5 |
589655bc478ef7d0cb408285cfad90b5
|
|
| BLAKE2b-256 |
79a0c973ac5890ce5c8705c02a6c4772f96e4c326c3e872e35e392077bbd0217
|
File details
Details for the file openai_io-0.1.3-py3-none-any.whl.
File metadata
- Download URL: openai_io-0.1.3-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cd8e76a6d3fd0519acfd8fba88b0e7da696e3897ca20d48e404c520a93de7e3
|
|
| MD5 |
bee90214c3fb71ead074eae027417eb2
|
|
| BLAKE2b-256 |
a993b57483ae9aaf3cf02aa6f8fc8d908e339cbf644d9dcc0f985ccea372d322
|