Grok API 和 OpenAI API 到底有什么区别?一篇文章搞懂协议兼容、Responses API、流式输出与完整接入代码

在这里插入图片描述

最近很多开发者开始接入 Grok,但第一次看到 Grok API 时,经常会产生一个疑问:

Grok API 是不是就是 OpenAI API?

答案是:

不是同一个 API,但 Grok 的 xAI API 对 OpenAI REST API 做了高度兼容。

这意味着,如果你的项目本来就已经接入了 OpenAI,那么接入 Grok 通常不需要重新写一套客户端。

很多情况下,只需要修改:

Base URL
API Key
Model

就可以完成切换。

xAI 官方 REST API 文档明确说明,其 Inference API 提供 OpenAI REST API compatibility,而且同时支持 Chat Completions 和 Responses API。当前 xAI 官方更推荐使用 Responses API。

本文将从协议、请求格式、流式输出、Function Calling、Responses API、Python、Node.js、Go、curl 等多个角度完整介绍 Grok API。

本文示例统一使用:

Base URL:

https://ai.silicogrove.com

因此完整接口地址通常为:

https://ai.silicogrove.com/v1/chat/completions

https://ai.silicogrove.com/v1/responses

如果你使用 OpenAI SDK,则通常配置:

https://ai.silicogrove.com/v1

一、先说结论:Grok API 和 OpenAI API 是什么关系?

可以简单理解成:

                OpenAI API Protocol
                       │
          ┌────────────┴────────────┐
          │                         │
 Chat Completions              Responses API
          │                         │
    /v1/chat/completions        /v1/responses
          │                         │
   ┌──────┼───────┐           ┌─────┼──────┐
   │      │       │           │     │      │
OpenAI   Grok  其他兼容商     OpenAI Grok 其他兼容商

Grok 并不是运行在 OpenAI 的服务器上。

它是 xAI 自己的模型、自己的基础设施、自己的 API。

但是 xAI 在 API 设计上主动兼容了 OpenAI。

所以你可以使用:

from openai import OpenAI

来调用 Grok。

也可以使用:

import OpenAI from "openai";

调用 Grok。

甚至很多原本为 OpenAI 编写的 Agent、CLI、AI SDK,只要支持自定义:

base_url
api_key
model

理论上都可以非常方便地接入 Grok。

xAI 官方文档自己的示例也直接使用 OpenAI SDK,并通过修改 base_url 接入 Grok。


二、Grok 支持哪些 OpenAI 风格接口?

最重要的两个是:

POST /v1/chat/completions

以及:

POST /v1/responses

其中:

Chat Completions

也就是大家最熟悉的:

/v1/chat/completions

请求结构类似:

{
  "model": "grok-4.5",
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ]
}

xAI 官方 REST API 目前仍然提供 /v1/chat/completions,支持文本以及图片理解等场景。


Responses API

新项目更建议使用:

/v1/responses

请求结构变成:

{
  "model": "grok-4.5",
  "input": "你好"
}

xAI 官方目前明确将 Responses API 作为推荐交互方式,而 Chat Completions 更多作为兼容已有系统的旧式接口存在。

如果现在从零开发一个新的 AI 项目,我更建议直接围绕:

Responses API

设计。


三、最简单的 curl 调用 Grok

先来看最简单的方式。

假设已经有 API Key:

export API_KEY="sk-xxxxxxxxxxxxxxxx"

请求:

curl https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "messages": [
      {
        "role": "user",
        "content": "你好,请用一句话介绍一下 Grok。"
      }
    ]
  }'

你会得到类似:

{
  "id": "chatcmpl_xxxxxxxxx",
  "object": "chat.completion",
  "created": 1786896000,
  "model": "grok-4.5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Grok 是 xAI 开发的大语言模型系列。"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 18,
    "completion_tokens": 16,
    "total_tokens": 34
  }
}

是不是非常熟悉?

因为这就是典型的 OpenAI Chat Completions 风格。


四、加上 System Prompt

实际开发基本不会只有 user 消息。

完整请求可以这样写:

curl https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "messages": [
      {
        "role": "system",
        "content": "你是一名资深 Go 后端工程师,回答问题时优先提供可以直接运行的代码。"
      },
      {
        "role": "user",
        "content": "使用 Go 写一个 HTTP Server。"
      }
    ]
  }'

对于以前已经接入 OpenAI 的程序,这种代码通常完全不用重新设计。


五、Responses API curl 完整示例

现在我们换成比较新的 Responses API。

curl https://ai.silicogrove.com/v1/responses \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "input": "请用简单的语言解释什么是大语言模型。"
  }'

和 Chat Completions 最大的区别之一,就是:

以前:

{
  "messages": []
}

现在可以直接:

{
  "input": "..."
}

Responses API 非常适合:

AI Agent
工具调用
多模态
Web Search
复杂推理
多轮执行

这种新一代 AI 应用。


六、Responses API 使用消息数组

当然,input 不一定必须是字符串。

也可以写成:

curl https://ai.silicogrove.com/v1/responses \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "input": [
      {
        "role": "system",
        "content": "你是一名专业程序员。"
      },
      {
        "role": "user",
        "content": "解释一下 Redis 分布式锁。"
      }
    ]
  }'

所以从设计思路来看:

Chat Completions

messages
  ↓
model
  ↓
assistant message

逐渐演化成:

Responses

input
  ↓
model
  ↓
tools
  ↓
reasoning
  ↓
output

这对于 Agent 系统明显更加友好。


七、流式输出 curl

AI 聊天程序一般都不会等待整个回答生成完成。

而是:

你
↓
发送请求
↓
模型开始输出
↓
前端逐字展示

这就是 Streaming。

例如:

curl -N https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "写一篇关于 Go 协程的简短介绍。"
      }
    ]
  }'

关键参数只有:

"stream": true

curl 中建议加:

-N

避免 curl 对返回内容进行缓冲。

输出大致会变成连续 SSE 数据:

data: {...}

data: {...}

data: {...}

然后客户端不断读取增量内容。


八、Python 调用 Grok

如果以前用过 OpenAI Python SDK,基本不需要学习新的东西。

安装:

pip install openai

完整代码:

from openai import OpenAI

API_KEY = "sk-xxxxxxxxxxxxxxxx"

client = OpenAI(
    api_key=API_KEY,
    base_url="https://ai.silicogrove.com/v1"
)

response = client.chat.completions.create(
    model="grok-4.5",
    messages=[
        {
            "role": "system",
            "content": "你是一名专业的 Python 工程师。"
        },
        {
            "role": "user",
            "content": "写一个 Python 快速排序,并解释实现原理。"
        }
    ]
)

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

注意这里:

base_url="https://ai.silicogrove.com/v1"

而 curl 使用的是完整接口:

https://ai.silicogrove.com/v1/chat/completions

这是很多开发者第一次配置时容易搞错的地方。


九、Python Responses API

推荐的新方式:

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx",
    base_url="https://ai.silicogrove.com/v1"
)

response = client.responses.create(
    model="grok-4.5",
    input="使用 Python 写一个简单的 HTTP Server。"
)

print(response.output_text)

可以看到代码非常简单:

response = client.responses.create(...)

甚至比:

client.chat.completions.create(...)

更加直观。


十、Python 流式输出

完整程序:

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx",
    base_url="https://ai.silicogrove.com/v1"
)

stream = client.chat.completions.create(
    model="grok-4.5",
    messages=[
        {
            "role": "user",
            "content": "详细介绍一下 Kubernetes。"
        }
    ],
    stream=True
)

for chunk in stream:

    if not chunk.choices:
        continue

    delta = chunk.choices[0].delta

    if delta.content:
        print(delta.content, end="", flush=True)

print()

运行:

python app.py

终端就会像 ChatGPT 一样不断显示内容。


十一、Python 完整命令行聊天机器人

我们直接做一个能连续聊天的程序。

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx",
    base_url="https://ai.silicogrove.com/v1"
)

messages = [
    {
        "role": "system",
        "content": "你是一名专业的 AI 编程助手。"
    }
]

print("Grok CLI Chat")
print("输入 exit 退出")
print("-" * 50)

while True:

    user_input = input("\nYou: ")

    if user_input.lower() in ["exit", "quit"]:
        break

    messages.append({
        "role": "user",
        "content": user_input
    })

    stream = client.chat.completions.create(
        model="grok-4.5",
        messages=messages,
        stream=True
    )

    print("\nGrok: ", end="")

    assistant_content = ""

    for chunk in stream:

        if not chunk.choices:
            continue

        content = chunk.choices[0].delta.content

        if content:

            assistant_content += content

            print(
                content,
                end="",
                flush=True
            )

    messages.append({
        "role": "assistant",
        "content": assistant_content
    })

    print()

现在运行:

python chat.py

就可以直接:

You: Redis 和 Memcached 有什么区别?

Grok: Redis 和 Memcached 都属于内存缓存系统,但是……

然后继续:

You: 那 Go 项目应该选哪个?

由于:

messages

一直保存着,所以模型可以理解之前的上下文。


十二、Node.js 调用 Grok

安装:

npm install openai

package.json:

{
  "type": "module",
  "dependencies": {
    "openai": "^5.0.0"
  }
}

创建:

app.js

完整代码:

import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.API_KEY,
    baseURL: "https://ai.silicogrove.com/v1"
});

async function main() {

    const completion =
        await client.chat.completions.create({
            model: "grok-4.5",

            messages: [
                {
                    role: "system",
                    content: "你是一名专业 Node.js 工程师。"
                },
                {
                    role: "user",
                    content: "使用 Express 写一个 REST API。"
                }
            ]
        });

    console.log(
        completion.choices[0].message.content
    );
}

main();

配置 Key:

export API_KEY="sk-xxxxxxxxxxxxxxxx"

运行:

node app.js

十三、Node.js Responses API

Responses API 更简单:

import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.API_KEY,
    baseURL: "https://ai.silicogrove.com/v1"
});

async function main() {

    const response =
        await client.responses.create({
            model: "grok-4.5",
            input: "使用 Node.js 写一个 WebSocket Server。"
        });

    console.log(response.output_text);
}

main();

十四、Node.js 流式输出

完整实现:

import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.API_KEY,
    baseURL: "https://ai.silicogrove.com/v1"
});

async function main() {

    const stream =
        await client.chat.completions.create({

            model: "grok-4.5",

            messages: [
                {
                    role: "user",
                    content: "详细介绍微服务架构。"
                }
            ],

            stream: true
        });

    for await (const chunk of stream) {

        const content =
            chunk.choices?.[0]?.delta?.content;

        if (content) {
            process.stdout.write(content);
        }
    }

    process.stdout.write("\n");
}

main();

这也是现在 Web AI 应用最常见的实现方式。


十五、Go 调用 Grok

Go 开发者其实不一定非要安装 SDK。

因为 OpenAI 协议本质就是:

HTTP + JSON

所以直接使用标准库就可以。

完整代码:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const (
	BaseURL = "https://ai.silicogrove.com"
	APIKey  = "sk-xxxxxxxxxxxxxxxx"
)

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type ChatRequest struct {
	Model    string    `json:"model"`
	Messages []Message `json:"messages"`
}

type ChatResponse struct {
	ID      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`

	Choices []struct {
		Index int `json:"index"`

		Message struct {
			Role    string `json:"role"`
			Content string `json:"content"`
		} `json:"message"`

		FinishReason string `json:"finish_reason"`
	} `json:"choices"`

	Usage struct {
		PromptTokens     int `json:"prompt_tokens"`
		CompletionTokens int `json:"completion_tokens"`
		TotalTokens      int `json:"total_tokens"`
	} `json:"usage"`
}

func main() {

	requestBody := ChatRequest{
		Model: "grok-4.5",

		Messages: []Message{
			{
				Role:    "system",
				Content: "你是一名资深 Go 工程师。",
			},
			{
				Role:    "user",
				Content: "使用 Gin 写一个 REST API。",
			},
		},
	}

	data, err := json.Marshal(requestBody)

	if err != nil {
		panic(err)
	}

	req, err := http.NewRequest(
		http.MethodPost,
		BaseURL+"/v1/chat/completions",
		bytes.NewBuffer(data),
	)

	if err != nil {
		panic(err)
	}

	req.Header.Set(
		"Authorization",
		"Bearer "+APIKey,
	)

	req.Header.Set(
		"Content-Type",
		"application/json",
	)

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)

	if err != nil {
		panic(err)
	}

	if resp.StatusCode != http.StatusOK {

		fmt.Println(
			"HTTP Error:",
			resp.StatusCode,
		)

		fmt.Println(string(body))

		return
	}

	var result ChatResponse

	err = json.Unmarshal(
		body,
		&result,
	)

	if err != nil {
		panic(err)
	}

	if len(result.Choices) == 0 {
		fmt.Println("没有返回内容")
		return
	}

	fmt.Println(
		result.Choices[0].
			Message.
			Content,
	)

	fmt.Println()

	fmt.Printf(
		"Tokens: %d\n",
		result.Usage.TotalTokens,
	)
}

运行:

go run main.go

这种方式的最大优势就是:

完全不依赖任何第三方 SDK。


十六、Go 封装成客户端

真正项目里肯定不能每次都手写:

http.NewRequest()

可以自己封装一个客户端。

例如:

package grok

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"time"
)

type Client struct {
	BaseURL    string
	APIKey     string
	HTTPClient *http.Client
}

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type ChatRequest struct {
	Model       string    `json:"model"`
	Messages    []Message `json:"messages"`
	Temperature float64   `json:"temperature,omitempty"`
}

type ChatResponse struct {
	ID string `json:"id"`

	Choices []struct {
		Message struct {
			Role    string `json:"role"`
			Content string `json:"content"`
		} `json:"message"`

		FinishReason string `json:"finish_reason"`
	} `json:"choices"`

	Usage struct {
		PromptTokens     int `json:"prompt_tokens"`
		CompletionTokens int `json:"completion_tokens"`
		TotalTokens      int `json:"total_tokens"`
	} `json:"usage"`
}

func NewClient(
	baseURL string,
	apiKey string,
) *Client {

	return &Client{
		BaseURL: baseURL,
		APIKey:  apiKey,

		HTTPClient: &http.Client{
			Timeout: 120 * time.Second,
		},
	}
}

func (c *Client) Chat(
	model string,
	messages []Message,
) (*ChatResponse, error) {

	payload := ChatRequest{
		Model:    model,
		Messages: messages,
	}

	data, err := json.Marshal(payload)

	if err != nil {
		return nil, err
	}

	url :=
		c.BaseURL +
			"/v1/chat/completions"

	req, err := http.NewRequest(
		http.MethodPost,
		url,
		bytes.NewReader(data),
	)

	if err != nil {
		return nil, err
	}

	req.Header.Set(
		"Authorization",
		"Bearer "+c.APIKey,
	)

	req.Header.Set(
		"Content-Type",
		"application/json",
	)

	resp, err :=
		c.HTTPClient.Do(req)

	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	body, err :=
		io.ReadAll(resp.Body)

	if err != nil {
		return nil, err
	}

	if resp.StatusCode < 200 ||
		resp.StatusCode >= 300 {

		return nil, fmt.Errorf(
			"API error status=%d body=%s",
			resp.StatusCode,
			string(body),
		)
	}

	var result ChatResponse

	if err := json.Unmarshal(
		body,
		&result,
	); err != nil {

		return nil, err
	}

	if len(result.Choices) == 0 {

		return nil,
			errors.New(
				"empty choices",
			)
	}

	return &result, nil
}

使用:

package main

import (
	"fmt"

	"example.com/project/grok"
)

func main() {

	client :=
		grok.NewClient(
			"https://ai.silicogrove.com",
			"sk-xxxxxxxxxxxxxxxx",
		)

	response, err :=
		client.Chat(
			"grok-4.5",

			[]grok.Message{
				{
					Role: "system",
					Content:
						"你是一名资深后端工程师。",
				},
				{
					Role: "user",
					Content:
						"解释什么是 API Gateway。",
				},
			},
		)

	if err != nil {
		panic(err)
	}

	fmt.Println(
		response.
			Choices[0].
			Message.
			Content,
	)
}

这样整个项目就只需要:

client.Chat(...)

了。


十七、为什么最好不要设计一个 GrokProtocol?

如果你正在开发 API Gateway、中转 API、AI SDK 或类似 new-api 的平台,一个非常重要的问题是:

到底应该把 Grok 单独作为一个协议,还是把它归类到 OpenAI Compatible?

例如千万不要设计成:

Protocol
├── OpenAI
├── Claude
├── Gemini
├── DeepSeek
├── Grok
├── OpenRouter
└── ...

这会造成大量重复代码。

更合理的是:

Protocol
│
├── OpenAI Chat Completions
│
├── OpenAI Responses
│
├── Anthropic Messages
│
└── Gemini GenerateContent

然后 Provider 再分:

Provider
│
├── OpenAI
├── xAI
├── DeepSeek
├── OpenRouter
├── SiliconFlow
└── Other OpenAI Compatible

也就是:

Protocol != Provider

这是设计 AI Gateway 非常关键的一点。


十八、一个更合理的 Go Provider 设计

例如:

type Provider interface {

	Name() string

	BaseURL() string

	APIKey() string

	Headers() map[string]string
}

OpenAI:

type OpenAIProvider struct {
	Key string
}

func (p *OpenAIProvider) Name() string {
	return "openai"
}

func (p *OpenAIProvider) BaseURL() string {
	return "https://api.openai.com"
}

func (p *OpenAIProvider) APIKey() string {
	return p.Key
}

func (p *OpenAIProvider) Headers() map[string]string {

	return map[string]string{
		"Authorization":
			"Bearer " + p.Key,
	}
}

Grok:

type GrokProvider struct {
	Key string
}

func (p *GrokProvider) Name() string {
	return "grok"
}

func (p *GrokProvider) BaseURL() string {
	return "https://ai.silicogrove.com"
}

func (p *GrokProvider) APIKey() string {
	return p.Key
}

func (p *GrokProvider) Headers() map[string]string {

	return map[string]string{
		"Authorization":
			"Bearer " + p.Key,
	}
}

可以发现:

Request Protocol

完全可以复用。

真正变的只有:

BaseURL
APIKey
Model
Provider 特有能力

十九、Function Calling

Grok 同样支持 Function Calling。

xAI 官方目前还支持将自定义 Function Calling 与服务器端工具组合使用。

例如定义一个天气函数:

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

完整 curl:

curl https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "messages": [
      {
        "role": "user",
        "content": "北京现在天气怎么样?"
      }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "获取指定城市天气",
          "parameters": {
            "type": "object",
            "properties": {
              "city": {
                "type": "string",
                "description": "城市名称"
              }
            },
            "required": [
              "city"
            ]
          }
        }
      }
    ]
  }'

模型可能不会直接回答天气。

而是返回:

{
  "tool_calls": [
    {
      "id": "call_xxx",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{\"city\":\"北京\"}"
      }
    }
  ]
}

你的程序读取:

get_weather

然后执行真正的代码。

比如:

def get_weather(city):
    return {
        "city": city,
        "temperature": "31°C",
        "weather": "晴"
    }

再把结果交给模型。

这其实就是现在绝大多数 AI Agent 的底层逻辑:

User
 ↓
LLM
 ↓
决定调用工具
 ↓
Function Call
 ↓
程序执行
 ↓
Function Result
 ↓
LLM
 ↓
最终回答

二十、Structured Outputs

开发 AI 应用经常遇到一个问题。

你告诉模型:

返回 JSON

结果它返回:

```json
{
   ...
}
```

或者突然多说一句:

当然可以,以下是结果:

这样程序:

json.loads()

直接炸掉。

Structured Outputs 就是解决这个问题的。

xAI 官方目前提供 Structured Outputs,可以让支持的模型按照给定 JSON Schema 返回数据。

例如:

{
  "name": "王小明",
  "age": 25,
  "skills": [
    "Go",
    "Python"
  ]
}

这种功能特别适合:

简历解析
发票识别
实体提取
数据清洗
Agent 参数生成
API 参数生成
爬虫数据结构化

二十一、Grok 和 OpenAI 最大的不同:x_search

虽然 Grok 高度兼容 OpenAI API,但是:

不要理解成 Grok 与 OpenAI 100% 一模一样。

因为 Grok 有自己的能力。

其中一个非常有代表性的功能就是:

x_search

也就是搜索 X 平台。

xAI 官方目前在 Responses API 中支持 x_search,并且该工具可以通过 OpenAI Responses API 兼容 SDK 使用。

例如概念上可以:

response = client.responses.create(
    model="grok-4.5",

    input="最近 X 上大家都在讨论哪些 AI Agent?",

    tools=[
        {
            "type": "x_search"
        }
    ]
)

这就不是普通 OpenAI 模型完全对应的能力了。


二十二、Grok Web Search

除了 X Search,还有:

web_search

Grok 可以在生成回答过程中搜索互联网和访问网页,从而回答需要实时信息的问题。xAI 官方把 Web Search 作为服务器端工具提供。

例如:

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx",
    base_url="https://ai.silicogrove.com/v1"
)

response = client.responses.create(

    model="grok-4.5",

    input=
        "搜索最近 AI Agent 领域发生的重要新闻。",

    tools=[
        {
            "type": "web_search"
        }
    ]
)

print(response.output_text)

还可以同时:

tools=[
    {
        "type": "web_search"
    },
    {
        "type": "x_search"
    }
]

xAI 官方文档也给出了使用 OpenAI SDK同时配置 web_search 和 x_search 的示例。


二十三、为什么 Responses API 对 Agent 更重要?

过去 Chat Completions 的核心设计思路其实就是:

聊天

所以核心结构是:

messages

但现在 AI 已经不只是聊天机器人。

现在越来越多应用是:

AI Agent

Agent 需要:

搜索互联网
调用 API
执行代码
读文件
操作数据库
调用 MCP
浏览网页
调用 Function
执行多轮任务

所以接口结构自然会从:

messages → completion

升级为:

input

 ↓

model

 ↓

reasoning

 ↓

tool

 ↓

tool result

 ↓

model

 ↓

output

因此现在如果开发:

AI Agent Framework
AI Gateway
AI SDK
MCP Client
CLI Agent
Coding Agent

最好同时考虑:

Chat Completions

+

Responses API

而不是只实现:

/v1/chat/completions

二十四、OpenAI 和 Grok 协议对比

简单整理一下:

能力 OpenAI Grok
Chat Completions 支持 支持
Responses API 支持 支持
OpenAI SDK 原生 兼容
Streaming 支持 支持
Function Calling 支持 支持
Structured Outputs 支持 支持
图片理解 支持 支持,取决于模型
Web Search 支持相关工具能力 支持
X Search 无直接同名对应能力 支持
Base URL OpenAI 地址 xAI 或兼容 Gateway
模型 GPT 系列 Grok 系列

因此:

协议高度兼容,但模型能力和 Provider 扩展并不完全相同。


二十五、为什么有些 OpenAI 客户端换 Base URL 就能使用 Grok?

现在很多软件都有类似配置:

{
  "api_key": "sk-xxx",
  "base_url": "https://ai.silicogrove.com/v1",
  "model": "grok-4.5"
}

原因就在这里。

因为客户端真正做的事情只是:

POST /v1/chat/completions

Body:

{
  "model": "...",
  "messages": []
}

Header:

Authorization: Bearer xxx

只要服务器实现了相同协议,客户端通常根本不关心服务器背后到底运行的是:

GPT

Grok

DeepSeek

Qwen

Llama

Mistral

这也是 OpenAI Compatible API 能成为今天 AI 行业事实标准之一的重要原因。


二十六、API Gateway 应该怎么设计?

如果让我设计一个 AI API Gateway,我会至少分三层。

第一层:Protocol

Protocol
│
├── OpenAI Chat Completions
├── OpenAI Responses
├── Anthropic Messages
└── Gemini GenerateContent

第二层:Provider

Provider
│
├── OpenAI
├── xAI
├── Anthropic
├── Google
├── DeepSeek
├── OpenRouter
└── Other

第三层:Model

Provider: xAI

Models
│
├── grok-4.5
├── ...
└── ...

因此一条请求经过 Gateway:

Client
  ↓
OpenAI Protocol
  ↓
Gateway
  ↓
Model Router
  ↓
Provider
  ↓
xAI

客户端甚至不需要知道真正的上游是谁。


二十七、一个统一 AI Client 的 Go 设计

可以设计:

type AIClient struct {
	BaseURL string
	APIKey  string
}

func NewAIClient(
	baseURL string,
	apiKey string,
) *AIClient {

	return &AIClient{
		BaseURL: baseURL,
		APIKey:  apiKey,
	}
}

然后:

grokClient :=
	NewAIClient(
		"https://ai.silicogrove.com",
		"sk-xxx",
	)

以后如果切到其他 OpenAI Compatible Provider:

otherClient :=
	NewAIClient(
		"https://example.com",
		"sk-xxx",
	)

业务层仍然调用:

client.Chat(...)

这就是为什么:

协议与 Provider 一定要解耦。


二十八、环境变量推荐配置

实际项目千万别写:

api_key="sk-xxxxx"

应该放环境变量。

Linux/macOS:

export AI_API_KEY="sk-xxxxxxxx"
export AI_BASE_URL="https://ai.silicogrove.com/v1"
export AI_MODEL="grok-4.5"

Python:

import os

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("AI_API_KEY"),
    base_url=os.getenv("AI_BASE_URL")
)

MODEL = os.getenv("AI_MODEL")

response = client.responses.create(
    model=MODEL,
    input="你好"
)

print(response.output_text)

Node.js:

import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.AI_API_KEY,
    baseURL: process.env.AI_BASE_URL
});

const response =
    await client.responses.create({

        model:
            process.env.AI_MODEL,

        input:
            "你好"
    });

console.log(
    response.output_text
);

这样以后换模型根本不用改代码:

export AI_MODEL="grok-4.5"

二十九、curl 最小模板

如果只是测试接口,保存下面这份基本够用了。

Chat Completions:

curl https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "messages": [
      {
        "role": "user",
        "content": "你好"
      }
    ]
  }'

Responses:

curl https://ai.silicogrove.com/v1/responses \
  -H "Authorization: Bearer sk-xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "input": "你好"
  }'

Streaming:

curl -N https://ai.silicogrove.com/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "介绍一下 Grok"
      }
    ]
  }'

基本上只要这三个请求成功,就已经能证明一个 OpenAI Compatible Grok 接口的核心聊天能力已经跑通了。


三十、常见错误

1. Base URL 多写了一层 /v1

比如 SDK 配置:

base_url=
"https://ai.silicogrove.com/v1"

SDK 自己会追加:

/chat/completions

最终:

https://ai.silicogrove.com/v1/chat/completions

这是正确的。

如果你的 Gateway SDK 配置逻辑本身还会添加 /v1,就需要根据具体客户端调整。

所以最终判断标准永远是:

实际发出的 URL 是什么?

2. 模型不存在

例如:

{
  "model": "grok-xxxxx"
}

但是 Gateway 没配置这个模型。

就可能返回:

model_not_found

因此文章里的:

grok-4.5

只是调用示例。

真正使用时应以对应 API 服务当前开放的模型列表为准。


3. 401

一般是:

API Key 错误

或者:

Authorization Header 没传

正确格式:

Authorization: Bearer sk-xxxx

不是:

Authorization: sk-xxxx

4. 404

重点检查:

/v1

例如:

https://ai.silicogrove.com/chat/completions

和:

https://ai.silicogrove.com/v1/chat/completions

不是同一个地址。


5. Streaming 没有逐字显示

先检查:

"stream": true

curl 再加:

-N

如果中间还有:

Nginx
Cloudflare
Gateway

则还要检查中间层有没有对 SSE 进行 Buffer。


在这里插入图片描述

三十一、到底应该使用 Chat Completions 还是 Responses?

如果是维护老项目:

Chat Completions

完全可以继续使用。

尤其你的系统里面已经大量使用:

messages
choices
delta
tool_calls

没必要为了“新”强行全部重写。

但如果现在开发一个新的:

Agent
Coding Agent
MCP Client
AI Assistant
自动化系统
Deep Research

我会优先考虑:

Responses API

因为 xAI 自己目前也推荐 Responses API。


三十二、最终总结

回到文章最开始的问题:

Grok API 和 OpenAI API 一样吗?

最准确的说法应该是:

Grok API 不是 OpenAI API,但 Grok 所使用的 xAI API 高度兼容 OpenAI REST API。

因此:

OpenAI SDK

通常可以直接调用 Grok。

原来:

client = OpenAI(
    api_key="OPENAI_API_KEY"
)

现在:

client = OpenAI(
    api_key="API_KEY",
    base_url=
        "https://ai.silicogrove.com/v1"
)

然后把:

model

换成对应 Grok 模型即可。

从工程设计来看,更应该理解为:

OpenAI Protocol
        │
        ├── OpenAI Provider
        ├── xAI / Grok Provider
        ├── DeepSeek Provider
        ├── OpenRouter Provider
        └── Other Compatible Provider

而不是:

OpenAI Protocol

Grok Protocol

DeepSeek Protocol

全部各写一遍。

如果正在开发 AI Gateway、API 中转平台或者统一 AI SDK,那么最合理的架构应该是:

Protocol
    ↓
Provider Adapter
    ↓
Model Router
    ↓
Upstream

这样未来接入新的 OpenAI Compatible 模型时,很多时候只需要:

新增 Provider
+
配置 Base URL
+
配置模型

而完全不需要重新开发一整套协议。

这才是 OpenAI Compatible API 对今天 AI 开发最大的价值。

posted @ 2026-08-16 22:21  JavaPub  阅读(49)  评论(0)    收藏  举报