在 TypeScript 中使用 Gemini API 并进行 OpenAI 回退
文章介绍了如何在 TypeScript 中使用 Gemini API 并实现 OpenAI 回退机制。为了应对 Gemini 的速率限制,作者构建了辅助函数,允许在 Gemini API 失败时自动切换到 OpenAI。核心是定义了模型类型,并创建了 `getCompletion` 和 `getJSONCompletion` 两个函数,分别用于普通和结构化输出,方便开发者在应用中使用。代码示例展示了如何配置和调用这些函数,实现 API 的灵活切换和类型安全。
使用 Gemini API 并进行 OpenAI 回退的 Typescript 实现
2025-04-04
如果你想使用 Gemini 的公共 API,但同时希望在达到速率限制时有一个安全的备用方案,可以使用 OpenAI TS/JS library 和一些辅助函数。 在我的特定用例中,我需要一个类型安全的解决方案,用于一个 chartmaker app,并具备回退功能,因为 Gemini 的 gemini-2.5-pro-exp-03-25
模型被限制为 20 个请求/分钟。
首先,你需要定义你想要使用的模型,以便在使用辅助函数时它们显示为自动建议:
type Model = ChatCompletionParseParams['model'] | 'gemini-2.5-pro-exp-03-25' | 'gemini-2.0-flash';
辅助函数需要一个参数;一个包含 2 个配置对象的数组,用于所需的 AI 查询(原则上,你可以添加任意数量的配置对象,或选择与 OpenAI 库兼容的其他 AI):
export const getCompletion = async (
options: [
Omit<ChatCompletionParseParams, 'model'> & { model: Model },
Omit<ChatCompletionParseParams, 'model'> & { model: Model },
],
) => {
try {
const isGemini = options[0].model.includes('gemini');
const openai = new OpenAI(
isGemini
? {
apiKey: process.env.GEMINI_API_KEY,
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
}
: { apiKey: process.env.OPENAI_API_KEY },
);
return await openai.chat.completions.create(options[0]);
} catch (error) {
console.log(`Failed completion for first model (${options[0].model})`, error);
const isGemini = options[1].model.includes('gemini');
const openai = new OpenAI(
isGemini
? {
apiKey: process.env.GEMINI_API_KEY,
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
}
: { apiKey: process.env.OPENAI_API_KEY },
);
return await openai.chat.completions.create(options[1]);
}
};
该辅助函数可以按以下方式使用:
const messages = [{ role: 'user', content: 'Tell a short joke.' }];
const completion = await getCompletion([
{ model: 'gemini-2.0-flash', messages },
{ model: 'gpt-3.5-turbo', messages },
]);
console.log(completion);
// {
// "choices": [
// {
// "finish_reason": "stop",
// "index": 0,
// "message": {
// "content": "Why don't scientists trust atoms?\n\nBecause they make up everything!\n",
// "role": "assistant"
// }
// }
// ],
// "created": 1743757243,
// "model": "gemini-2.0-flash",
// "object": "chat.completion",
// "usage": {
// "completion_tokens": 16,
// "prompt_tokens": 5,
// "total_tokens": 21
// }
// }
你还可以创建一个辅助函数,用于类型安全的结构化输出:
export const getJSONCompletion = async <T>(
options: [
Omit<ChatCompletionParseParams, 'model'> & { model: Model },
Omit<ChatCompletionParseParams, 'model'> & { model: Model },
],
): Promise<ParsedChatCompletion<T> & { _request_id?: string | null | undefined }> => {
try {
const isGemini = options[0].model.includes('gemini');
const openai = new OpenAI(
isGemini
? {
apiKey: process.env.GEMINI_API_KEY,
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
}
: { apiKey: process.env.OPENAI_API_KEY },
);
return await openai.beta.chat.completions.parse({ ...options[0] });
} catch (error) {
console.log('Failed completion for first model', error);
const isGemini = options[1].model.includes('gemini');
const openai = new OpenAI(
isGemini
? {
apiKey: process.env.GEMINI_API_KEY,
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
}
: { apiKey: process.env.OPENAI_API_KEY },
);
return await openai.beta.chat.completions.parse({ ...options[1] });
}
};
它可以按以下方式使用:
import z from 'zod';
//... Omitted for brevity
const messages = [{ role: "user", content: "Your instructions..."}] satisfies ChatCompletionMessageParam[];
const format = z.object({ customizations: z.array(z.string()) });
const responseFormat = zodResponseFormat(format, 'chart-customizations');
const completion = await getJSONCompletion<z.infer<typeof format>>(
[
{ model: 'gemini-2.5-pro-exp-03-25', response_format: responseFormat, messages, temperature: 0 },
{ model: 'o3-mini-2025-01-31', reasoning_effort: 'high', response_format: responseFormat, messages },
],
);
const customizationsArr = completion.choices[0].message.parsed?.customizations;