OpenAI 兼容性

Ollama 提供了 OpenAI 兼容接口,这意味着你可以用 OpenAI 的 SDK 和工具直接调用 Ollama,只需要改一下接口地址。

为什么需要兼容?

OpenAI 的 API 已经成为事实上的标准。很多应用、框架、工具都是基于 OpenAI API 开发的。

如果 Ollama 能兼容 OpenAI 接口,就能:

  • 无缝切换到本地模型
  • 复用现有的 OpenAI 代码
  • 使用支持 OpenAI 的第三方工具

兼容接口地址

Ollama 的 OpenAI 兼容接口:

http://localhost:11434/v1

这个 /v1 后缀和 OpenAI 的接口路径一致。

支持的接口

Chat Completions

POST /v1/chat/completions

对应 Ollama 的 /api/chat

Completions

POST /v1/completions

对应 Ollama 的 /api/generate

Embeddings

POST /v1/embeddings

对应 Ollama 的 /api/embeddings

Models

GET /v1/models

列出可用模型。

使用 OpenAI SDK

Python

安装 SDK:

pip install openai

代码示例:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

response = client.chat.completions.create(
    model="llama3.2",
    messages=[
        {"role": "user", "content": "你好"}
    ]
)

print(response.choices[0].message.content)

注意几点:

  • base_url 改成 Ollama 地址
  • api_key 可以随便填,Ollama 不验证
  • model 填 Ollama 的模型名

流式输出

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

stream = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "写一首诗"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Completions 接口

response = client.completions.create(
    model="llama3.2",
    prompt="用 Python 写一个快速排序"
)

print(response.choices[0].text)

Embeddings 接口

response = client.embeddings.create(
    model="llama3.2",
    input="这是一段需要向量化的文本"
)

embedding = response.data[0].embedding
print(f"向量维度: {len(embedding)}")

列出模型

models = client.models.list()
for model in models:
    print(model.id)

使用 JavaScript SDK

import OpenAI from 'openai';

const client = new OpenAI({
    baseURL: 'http://localhost:11434/v1',
    apiKey: 'ollama'
});

async function main() {
    const response = await client.chat.completions.create({
        model: 'llama3.2',
        messages: [{ role: 'user', content: '你好' }]
    });
    
    console.log(response.choices[0].message.content);
}

main();

兼容性差异

虽然接口兼容,但有些细节不同:

模型名称

OpenAI 用 gpt-4gpt-3.5-turbo 这样的名称,Ollama 用自己的模型名:

# OpenAI
model="gpt-4"

# Ollama
model="llama3.2"

参数支持

Ollama 支持部分 OpenAI 参数:

参数支持情况
temperature支持
top_p支持
max_tokens支持(映射到 num_predict)
stop支持
frequency_penalty不支持
presence_penalty不支持
n不支持(只返回一个结果)
logit_bias不支持

响应格式

基本一致,但有些字段可能缺失:

{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "llama3.2",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "你好!"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 10,
    "completion_tokens": 5,
    "total_tokens": 15
  }
}

usage 字段的 token 统计是估算值。

与 LangChain 集成

LangChain 支持 OpenAI 兼容接口:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
    model="llama3.2"
)

response = llm.invoke("你好")
print(response.content)

与其他工具集成

LlamaIndex

from llama_index.llms.openai_like import OpenAILike

llm = OpenAILike(
    api_base="http://localhost:11434/v1",
    api_key="ollama",
    model="llama3.2"
)

AutoGen

from autogen import AssistantAgent

agent = AssistantAgent(
    name="assistant",
    llm_config={
        "config_list": [{
            "base_url": "http://localhost:11434/v1",
            "api_key": "ollama",
            "model": "llama3.2"
        }]
    }
)

Function Calling

Ollama 支持 Function Calling(工具调用):

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "北京今天天气怎么样?"}],
    tools=tools
)

if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    print(f"调用函数: {tool_call.function.name}")
    print(f"参数: {tool_call.function.arguments}")

Vision 支持

多模态模型(如 llava)支持图片输入:

import base64

with open("image.png", "rb") as f:
    image_data = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="llava",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "这张图片里有什么?"},
                {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_data}"}}
            ]
        }
    ]
)

print(response.choices[0].message.content)