以下内容基本上是 AI 生成的,我还没校对,可能质量不高
oai2ollama¶
当初只是为了临时解决 copilot 中不支持自定义 openai compatible API 的问题,于是参考 这个 comment 的例子,封装了一个 CLI 发布到 PyPI 并 跟帖,结果居然 挺受欢迎 的
oai2ollama 是一个 API 适配器(Reverse Proxy)。它将 OpenAI 兼容的 API 包装成 Ollama 兼容的 API。
Features¶
- Bridge the Gap: 让只支持 Ollama 的工具(如某些本地 Agent、IDE 插件)能够使用 OpenAI、DeepSeek 或其他云端模型。
- Seamless Proxy: 实现了 Ollama 的
/api/tags,/api/generate,/api/chat等核心端点。 - Streaming Support: 完美支持流式输出(SSE),体验丝滑。
Implementation¶
基于 FastAPI 和 Httpx 构建。它启动一个 Web 服务器,接收符合 Ollama 协议的请求,将其转换为 OpenAI 协议的请求发送给上游提供商,收到响应后再转换回 Ollama 的格式返回给客户端。
配置管理¶
用 pydantic-settings 实现了 CLI 参数和 env 的统一配置,一遍配置,两种方式指定都可以。
见 config.py:
from pydantic_settings import BaseSettings, CliSuppress
from typing import Literal
class Settings(BaseSettings):
api_key: str
base_url: HttpUrl
capabilities: list[Literal["tools", "insert", "vision", "embedding", "thinking"]] = []
extra_models: list[str] = []
@model_validator(mode="after")
def _warn_legacy_capacities(self: Self): #(1)!
if self.capacities:
print("\n Warning: 'capacities' is a previous typo, please use 'capabilities' instead.\n")
self.capabilities.extend(self.capacities)
return self
env = Settings() # 从 .env 和 CLI args 中加载配置
- 之前错把
capabilities拼成了capacities,加了个模型验证器来兼容老配置。
FastAPI 应用¶
见 _app.py:
# oai2ollama/_app.py
from fastapi import FastAPI
from httpx import AsyncClient
app = FastAPI()
@app.post("/v1/chat/completions")
async def chat_completions(request: Request, client=_new_client):
data = await request.json()
if data.get("stream", False): #(1)!
async def stream():
async with client.stream("POST", "/chat/completions", json=data) as response:
async for chunk in response.aiter_bytes():
yield chunk
return StreamingResponse(stream(), media_type="text/event-stream")
res = await client.post("/chat/completions", json=data)
return res.json()
- 通过是否具有
stream字段来判断是否需要流式响应。
核心路由¶
| 端点 | 功能 |
|---|---|
/api/tags |
列出可用模型 |
/api/show |
返回模型信息(静态) |
/v1/models |
OpenAI 风格的模型列表 |
/v1/chat/completions |
聊天补全(支持流式) |
/api/version |
返回 Ollama 版本号 |
我的巧思¶
这个项目的灵感来源于一个反直觉的需求:通常大家是想把 Ollama 伪装成 OpenAI(因为 OpenAI 生态更丰富),但我反其道而行之。
为什么?因为现在有很多针对本地 LLM 优化的工具(比如 VS Code 的某些 Copilot 替代品)强制要求连接 Ollama。通过 Oai2Ollama,你可以“欺骗”这些工具,让它们以为自己在连本地模型,实际上背后跑的是强大的 GPT-4 或 Claude。
深入洞见¶
核心难点在于 Protocol Translation。
Ollama 的 API 响应格式(JSON Objects stream)与 OpenAI 的 SSE(Server-Sent Events)格式虽然相似但细节不同。
在 oai2ollama/_app.py 中,流式响应直接透传 OpenAI 的 SSE 字节流。由于 StreamingResponse 接收的是 async generator,它会把 chunk 二进制数据直接推向客户端,保持极低的延迟。