aisapi
Version:
A JavaScript/TypeScript API library for multiple AI providers
395 lines • 17.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeminiProvider = void 0;
const base_1 = require("./base");
/**
* Google Gemini服务接口
* 支持文本生成、对话聊天、流式回复和图像理解功能
*/
class GeminiProvider extends base_1.BaseProvider {
/**
* 创建Gemini服务实例
*/
constructor(options = {}) {
super(options);
this.name = 'Gemini';
this.model = options.model || 'gemini-2.0-flash-001'; // 默认用Gemini 2.0
this.projectId = options.projectId;
this.apiVersion = options.apiVersion || 'v1'; // API版本
this.maxRetries = options.maxRetries || 3;
}
/**
* 获取默认API地址
*/
getDefaultBaseUrl() {
return `https://generativelanguage.googleapis.com/${this.apiVersion}`;
}
/**
* 组装完整的API请求地址
*/
buildRequestUrl(endpoint) {
// 根据配置使用项目ID或API密钥
if (this.projectId) {
return `${this.baseUrl}/${endpoint}?project=${this.projectId}`;
}
else {
return `${this.baseUrl}/${endpoint}?key=${this.apiKey}`;
}
}
/**
* 生成文本内容
*/
generateText(params) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
const modelName = params.model || this.model;
// 准备请求数据
const requestBody = {
contents: [
{
parts: [
{ text: params.prompt }
]
}
],
generationConfig: {
temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7,
topP: (_b = params.topP) !== null && _b !== void 0 ? _b : 0.95,
maxOutputTokens: params.maxTokens || 2048,
}
};
// 添加系统指令
if (params.systemMessage) {
requestBody.contents.unshift({
role: 'system',
parts: [{ text: params.systemMessage }]
});
}
// 需要流式输出就换方法处理
if (params.stream) {
return this.generateTextStream(modelName, requestBody);
}
const url = this.buildRequestUrl(`models/${modelName}:generateContent`);
// 自动重试机制
let retries = 0;
while (retries <= this.maxRetries) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = yield fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorData = yield response.json().catch(() => ({}));
throw new Error(`请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`);
}
const data = yield response.json();
// 解析回复内容
const text = data.candidates[0].content.parts
.map((part) => part.text || '')
.join('');
return {
text,
usage: {
promptTokens: ((_c = data.usageMetadata) === null || _c === void 0 ? void 0 : _c.promptTokenCount) || 0,
completionTokens: ((_d = data.usageMetadata) === null || _d === void 0 ? void 0 : _d.candidatesTokenCount) || 0,
totalTokens: ((_e = data.usageMetadata) === null || _e === void 0 ? void 0 : _e.totalTokenCount) || 0
},
rawResponse: data
};
}
catch (e) {
retries++;
if (retries > this.maxRetries) {
if (e instanceof Error) {
throw new Error(`[${this.name}] ${e.message}`);
}
throw e;
}
// 错误后延迟重试,避免触发频率限制
const delay = Math.min(1000 * Math.pow(2, retries), 60000);
yield new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error(`[${this.name}] 已重试多次但仍失败`);
});
}
/**
* 流式生成文本
*/
generateTextStream(modelName, requestBody) {
return __awaiter(this, void 0, void 0, function* () {
const stream = yield this.createStreamingContent(modelName, requestBody);
// 流式模式只返回流对象,不直接返回内容
return {
text: '',
usage: {
promptTokens: 0,
completionTokens: 0,
totalTokens: 0
},
rawResponse: { stream }
};
});
}
/**
* 聊天对话功能
*/
chatCompletion(params) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
const modelName = params.model || this.model;
// 转换消息格式
const contents = params.messages.map(message => {
return {
role: this.mapRoleToGeminiRole(message.role),
parts: [{ text: message.content }]
};
});
// 准备请求数据
const requestBody = {
contents,
generationConfig: {
temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7,
topP: (_b = params.topP) !== null && _b !== void 0 ? _b : 0.95,
maxOutputTokens: params.maxTokens || 2048
}
};
// 流式模式切换
if (params.stream) {
return this.generateTextStream(modelName, requestBody);
}
const url = this.buildRequestUrl(`models/${modelName}:generateContent`);
// 发送请求
let retries = 0;
while (retries <= this.maxRetries) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = yield fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorData = yield response.json().catch(() => ({}));
throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`);
}
const data = yield response.json();
// 提取返回的文本内容
const text = data.candidates[0].content.parts
.map((part) => part.text || '')
.join('');
return {
text,
usage: {
promptTokens: ((_c = data.usageMetadata) === null || _c === void 0 ? void 0 : _c.promptTokenCount) || 0,
completionTokens: ((_d = data.usageMetadata) === null || _d === void 0 ? void 0 : _d.candidatesTokenCount) || 0,
totalTokens: ((_e = data.usageMetadata) === null || _e === void 0 ? void 0 : _e.totalTokenCount) || 0
},
rawResponse: data
};
}
catch (error) {
retries++;
if (retries > this.maxRetries) {
if (error instanceof Error) {
throw new Error(`[${this.name}] ${error.message}`);
}
throw error;
}
// 指数退避重试
const delay = Math.min(1000 * Math.pow(2, retries), 60000);
yield new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error(`[${this.name}] 达到最大重试次数`);
});
}
/**
* 映射角色名称到Gemini格式
*/
mapRoleToGeminiRole(role) {
switch (role) {
case 'system':
return 'system';
case 'assistant':
return 'model';
case 'user':
default:
return 'user';
}
}
/**
* 创建流式内容生成
*/
createStreamingChatCompletion(params) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const modelName = params.model || this.model;
// 将聊天消息转换为Gemini格式
const contents = params.messages.map(message => {
return {
role: this.mapRoleToGeminiRole(message.role),
parts: [{ text: message.content }]
};
});
// 构建请求体
const requestBody = {
contents,
generationConfig: {
temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7,
topP: (_b = params.topP) !== null && _b !== void 0 ? _b : 0.95,
maxOutputTokens: params.maxTokens || 2048
}
};
return this.createStreamingContent(modelName, requestBody);
});
}
/**
* 创建流式内容请求
*/
createStreamingContent(modelName, requestBody) {
return __awaiter(this, void 0, void 0, function* () {
// 添加流式标志
requestBody.streamGenerationConfig = { streamMode: 'CONCURRENT' };
const url = this.buildRequestUrl(`models/${modelName}:streamGenerateContent`);
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = yield fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream'
},
body: JSON.stringify(requestBody),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorData = yield response.json().catch(() => ({}));
throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`);
}
if (!response.body) {
throw new Error('响应没有可读流');
}
return response.body;
}
catch (error) {
if (error instanceof Error) {
throw new Error(`[${this.name}] ${error.message}`);
}
throw error;
}
});
}
/**
* 生成JSON格式响应
*/
generateJSON(params) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
// 添加系统消息要求JSON输出
const jsonSystemMessage = params.systemMessage
? `${params.systemMessage}\n请以有效的JSON格式返回数据,不要包含额外文本。`
: '请以有效的JSON格式返回数据,不要包含额外文本。';
const modelName = params.model || this.model;
const requestBody = {
contents: [
{
parts: [
{ text: params.prompt }
]
}
],
generationConfig: {
temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.3, // 降低温度,增加确定性
topP: (_b = params.topP) !== null && _b !== void 0 ? _b : 0.95,
maxOutputTokens: params.maxTokens || 2048,
responseMimeType: 'application/json' // 指定JSON MIME类型
}
};
// 添加系统消息
requestBody.contents.unshift({
role: 'system',
parts: [{ text: jsonSystemMessage }]
}); // 使用类型断言解决TypeScript类型问题
const url = this.buildRequestUrl(`models/${modelName}:generateContent`);
let retries = 0;
while (retries <= this.maxRetries) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = yield fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorData = yield response.json().catch(() => ({}));
throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`);
}
const data = yield response.json();
// 提取返回的文本内容
const text = data.candidates[0].content.parts
.map((part) => part.text || '')
.join('');
try {
// 解析JSON
const jsonData = JSON.parse(text);
return {
data: jsonData,
usage: {
promptTokens: ((_c = data.usageMetadata) === null || _c === void 0 ? void 0 : _c.promptTokenCount) || 0,
completionTokens: ((_d = data.usageMetadata) === null || _d === void 0 ? void 0 : _d.candidatesTokenCount) || 0,
totalTokens: ((_e = data.usageMetadata) === null || _e === void 0 ? void 0 : _e.totalTokenCount) || 0
}
};
}
catch (jsonError) {
throw new Error(`[${this.name}] 解析JSON响应失败: ${jsonError instanceof Error ? jsonError.message : String(jsonError)}`);
}
}
catch (error) {
retries++;
if (retries > this.maxRetries) {
if (error instanceof Error) {
throw new Error(`[${this.name}] ${error.message}`);
}
throw error;
}
// 指数退避重试
const delay = Math.min(1000 * Math.pow(2, retries), 60000);
yield new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error(`[${this.name}] 达到最大重试次数`);
});
}
}
exports.GeminiProvider = GeminiProvider;
//# sourceMappingURL=gemini.js.map