跳转至

以下内容基本上是 AI 生成的,我还没校对,可能质量不高

oai2ollama

当初只是为了临时解决 copilot 中不支持自定义 openai compatible API 的问题,于是参考 这个 comment 的例子,封装了一个 CLI 发布到 PyPI 并 跟帖,结果居然 挺受欢迎

Docs   ·   Repo   ·   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

基于 FastAPIHttpx 构建。它启动一个 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 中加载配置
  1. 之前错把 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()
  1. 通过是否具有 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 二进制数据直接推向客户端,保持极低的延迟。