AI From U AI FROM U.COM

博客 / 指南

把 OpenAI SDK 指向新的 base URL

把已有的 OpenAI SDK 应用接到这里只需要改两处:base URL 和 key。/v1/chat/completions 和 /v1/responses 都在服务,流式输出和工具调用原样透传;四个别名可以直接写,OpenAI 风格的模型名会按重量级读成对应的那一档,改不动的 model 一行照样能跑。

一个已经在对 OpenAI SDK 说话的应用,不需要重写就能对我们说话。要动的只有两样:构造 client 用的 base URL,和它用来认证的密钥。这两行上下的所有东西 — 调用本身、messages、各项参数、你把回答读回来的方式 — 都还是你原来写的样子。

要改的就是那两行

在 Python 里,base URL 和密钥就是构造 client 的那两个参数。构造函数之后的每一行都不是我们的:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://aifromu.com/v1",
    api_key=os.environ["AIFROMU_API_KEY"],
)

resp = client.chat.completions.create(
    model="terra",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)

在 Node 里也是同样这两样,写在构造 client 的那个对象里:

import OpenAI from "openai";

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

const resp = await client.chat.completions.create({
  model: "terra",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(resp.choices[0].message.content);

密钥从客户控制台来:登录之后打开 Keys 页面,你在那里领到的那把密钥,就是这个 client 发出去的那把。上面两个例子都从环境变量里读它,而不是写进文件,用的名字是 AIFROMU_API_KEY,因为一把和代码放在一起的密钥,在有人 clone 这个仓库的那一刻就必须重新轮换。

两个 endpoint、流式输出和工具调用

/v1/chat/completions 和 /v1/responses 这里都在服务,所以你的代码原本调的是哪一个,接着调哪一个就行 — 进来这一步不需要在两者之间做迁移。流式输出原样透传,工具调用也一样:请求按你写的形状发上去,事件按 SDK 本来就在解析的形状回下来。

你写的模型名会怎么处理

四个别名 — astra、sol、terra 和 luna — 可以直接用,一个客户端写哪个名字,就是在要卡片上那个模型。而一个写着 OpenAI 模型名的客户端,会被按它的重量级来读:带 mini 或 nano 的名字用 luna 服务,普通的 4 系名字用 terra,frontier 或 o 系名字用 sol,gpt-6 的名字用 astra。正是这一点让一行没动过的 model 在换掉 base URL 之后的第一个请求里就照样能跑;而花多少钱就按多少钱记 — 按实际服务这个请求的那一档,不按发问时写的那个名字。

一个哪一档都套不上的名字不会被猜:请求会被拒绝,拒绝信息里点出那四个模型的名字,所以配置错了是你在第一次调用时就看得见的事,而不是等到账单上才发现的事。猜才是更糟的那种失败,因为它是无声的 — 一个被读成错误档位的名字,会让一个人的请求以低于成本的价格得到服务,让另一个人为自己从未拿到的能力付钱,而这两个请求里没有任何一处会说出这件事。

确认跑通了,以及怎么读报错

第一次调用本身就是全部的验证:回答回来了,就说明 base URL 和密钥两样都对,文件里其他任何地方都不需要改。如果没回来,那句拒绝会告诉你是两样里的哪一样出了问题 — 一把用不了的密钥,回的是密钥无效;一个本网关不服务的模型,回的是它确实服务的那四个名字。

再往后的报错同样是实话。上游拒绝一个请求时,它给出的校验理由会原样传到你手里,而不是被压平成一句含糊的字符串,所以上下文太长、某个参数写错,都会在回答里直说。429 上的 Retry-After 会保留,因为各家 SDK 正是靠这个 header 来安排自己的重试节奏的;一个把它丢掉之后再转出来的限流,是一个只能让你的客户端去猜的限流。

一个哪一档都套不上的名字不会被猜:请求会被拒绝,拒绝信息里点出那四个模型的名字,所以配置错了是你在第一次调用时就看得见的事,而不是等到账单上才发现的事。

本文为机器翻译,母语审校待完成。以英文版为准。