跳到主要内容

AI API集成基础

在现代前端开发中,AI API集成是构建智能应用的核心技能。本文将深入探讨如何在前端项目中高效、安全地集成各种AI服务,包括API设计模式、错误处理、性能优化和最佳实践。

AI API集成架构

整体架构设计

核心API管理器

// 统一AI API管理器
class AIAPIManager {
constructor(config = {}) {
this.providers = new Map();
this.config = {
timeout: config.timeout || 30000,
retryAttempts: config.retryAttempts || 3,
retryDelay: config.retryDelay || 1000,
cacheEnabled: config.cacheEnabled !== false,
rateLimitEnabled: config.rateLimitEnabled !== false,
...config
};

this.cache = new APICache(config.cache);
this.rateLimiter = new RateLimiter(config.rateLimit);
this.monitor = new APIMonitor();
this.authenticator = new APIAuthenticator();

this.setupInterceptors();
}

// 注册AI服务提供商
registerProvider(name, provider) {
if (!provider.baseURL || !provider.authenticate) {
throw new Error('Provider must have baseURL and authenticate methods');
}

this.providers.set(name, {
...provider,
name,
registeredAt: Date.now(),
stats: {
totalRequests: 0,
successfulRequests: 0,
failedRequests: 0,
averageResponseTime: 0,
lastUsed: null
}
});

console.log(`AI Provider '${name}' registered successfully`);
}

// 统一API调用接口
async call(providerName, endpoint, options = {}) {
const provider = this.providers.get(providerName);
if (!provider) {
throw new Error(`Provider '${providerName}' not found`);
}

const requestId = this.generateRequestId();
const startTime = Date.now();

try {
// 1. 认证检查
await this.authenticator.ensureAuthenticated(provider);

// 2. 速率限制检查
if (this.config.rateLimitEnabled) {
await this.rateLimiter.checkLimit(providerName);
}

// 3. 缓存检查
const cacheKey = this.generateCacheKey(providerName, endpoint, options);
if (this.config.cacheEnabled && options.useCache !== false) {
const cachedResult = await this.cache.get(cacheKey);
if (cachedResult) {
this.monitor.recordCacheHit(providerName, requestId);
return { ...cachedResult, fromCache: true };
}
}

// 4. 执行API调用
const result = await this.executeRequest(provider, endpoint, options, requestId);

// 5. 缓存结果
if (this.config.cacheEnabled && options.useCache !== false && result.success) {
await this.cache.set(cacheKey, result, options.cacheTTL);
}

// 6. 更新统计信息
this.updateProviderStats(provider, true, Date.now() - startTime);

return result;

} catch (error) {
this.updateProviderStats(provider, false, Date.now() - startTime);
this.monitor.recordError(providerName, requestId, error);
throw this.enhanceError(error, providerName, endpoint);
}
}

// 执行具体的API请求
async executeRequest(provider, endpoint, options, requestId) {
const requestConfig = {
method: options.method || 'POST',
url: `${provider.baseURL}${endpoint}`,
headers: {
'Content-Type': 'application/json',
'User-Agent': 'AIApp/1.0',
'X-Request-ID': requestId,
...provider.defaultHeaders,
...options.headers
},
timeout: options.timeout || this.config.timeout,
data: options.data,
params: options.params
};

// 添加认证信息
await provider.authenticate(requestConfig);

// 执行请求(带重试机制)
return await this.executeWithRetry(requestConfig, provider.name);
}

// 重试机制
async executeWithRetry(requestConfig, providerName) {
let lastError;

for (let attempt = 0; attempt <= this.config.retryAttempts; attempt++) {
try {
const response = await this.httpClient.request(requestConfig);

return {
success: true,
data: response.data,
status: response.status,
headers: response.headers,
requestId: requestConfig.headers['X-Request-ID'],
attempt: attempt + 1,
provider: providerName
};

} catch (error) {
lastError = error;

// 检查是否应该重试
if (attempt === this.config.retryAttempts || !this.shouldRetry(error)) {
break;
}

// 计算退避延迟
const delay = this.calculateBackoffDelay(attempt);
await this.sleep(delay);

console.warn(`Retry attempt ${attempt + 1} for ${providerName} after ${delay}ms`);
}
}

throw lastError;
}

// 批量API调用
async batchCall(requests, options = {}) {
const batchSize = options.batchSize || 5;
const results = [];

for (let i = 0; i < requests.length; i += batchSize) {
const batch = requests.slice(i, i + batchSize);

const batchPromises = batch.map(async (request, index) => {
try {
const result = await this.call(
request.provider,
request.endpoint,
request.options
);

return {
index: i + index,
success: true,
result,
request
};
} catch (error) {
return {
index: i + index,
success: false,
error,
request
};
}
});

const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults.map(r => r.value));

// 批次间延迟
if (options.batchDelay && i + batchSize < requests.length) {
await this.sleep(options.batchDelay);
}

// 进度回调
if (options.onProgress) {
options.onProgress({
completed: Math.min(i + batchSize, requests.length),
total: requests.length,
progress: Math.min(i + batchSize, requests.length) / requests.length
});
}
}

return results;
}

// 流式API调用
async streamCall(providerName, endpoint, options = {}, onChunk) {
const provider = this.providers.get(providerName);
if (!provider) {
throw new Error(`Provider '${providerName}' not found`);
}

if (!provider.supportsStreaming) {
throw new Error(`Provider '${providerName}' does not support streaming`);
}

const requestConfig = {
...options,
responseType: 'stream',
headers: {
...options.headers,
'Accept': 'text/event-stream'
}
};

try {
const response = await this.executeRequest(provider, endpoint, requestConfig);

return new Promise((resolve, reject) => {
let buffer = '';
let fullContent = '';

response.data.on('data', (chunk) => {
buffer += chunk.toString();
const lines = buffer.split('\n');
buffer = lines.pop(); // 保留不完整的行

for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);

if (data === '[DONE]') {
resolve(fullContent);
return;
}

try {
const parsed = JSON.parse(data);
const content = this.extractStreamContent(parsed, provider);

if (content) {
fullContent += content;
onChunk({
content,
fullContent,
data: parsed,
finished: false
});
}
} catch (error) {
console.warn('Failed to parse stream data:', data);
}
}
}
});

response.data.on('end', () => {
resolve(fullContent);
});

response.data.on('error', (error) => {
reject(error);
});
});

} catch (error) {
throw this.enhanceError(error, providerName, endpoint);
}
}

// 健康检查
async healthCheck(providerName = null) {
const providersToCheck = providerName
? [this.providers.get(providerName)]
: Array.from(this.providers.values());

const results = await Promise.allSettled(
providersToCheck.map(async (provider) => {
if (!provider) return null;

try {
const startTime = Date.now();
await this.call(provider.name, provider.healthEndpoint || '/health', {
timeout: 5000,
useCache: false
});

return {
provider: provider.name,
status: 'healthy',
responseTime: Date.now() - startTime,
timestamp: Date.now()
};
} catch (error) {
return {
provider: provider.name,
status: 'unhealthy',
error: error.message,
timestamp: Date.now()
};
}
})
);

return results
.map(r => r.value)
.filter(r => r !== null);
}

// 获取提供商统计信息
getProviderStats(providerName = null) {
if (providerName) {
const provider = this.providers.get(providerName);
return provider ? provider.stats : null;
}

const stats = {};
for (const [name, provider] of this.providers) {
stats[name] = provider.stats;
}
return stats;
}

// 辅助方法
generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}

generateCacheKey(provider, endpoint, options) {
const key = {
provider,
endpoint,
data: options.data,
params: options.params
};
return `api_${this.hashObject(key)}`;
}

hashObject(obj) {
return btoa(JSON.stringify(obj)).replace(/[^a-zA-Z0-9]/g, '').substr(0, 16);
}

shouldRetry(error) {
const retryableStatusCodes = [429, 500, 502, 503, 504];
const retryableErrorCodes = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND'];

return retryableStatusCodes.includes(error.response?.status) ||
retryableErrorCodes.includes(error.code) ||
error.message.includes('timeout');
}

calculateBackoffDelay(attempt) {
return this.config.retryDelay * Math.pow(2, attempt) + Math.random() * 1000;
}

updateProviderStats(provider, success, responseTime) {
const stats = provider.stats;
stats.totalRequests++;
stats.lastUsed = Date.now();

if (success) {
stats.successfulRequests++;
} else {
stats.failedRequests++;
}

// 计算平均响应时间
stats.averageResponseTime = (
(stats.averageResponseTime * (stats.totalRequests - 1) + responseTime) /
stats.totalRequests
);
}

enhanceError(error, providerName, endpoint) {
const enhancedError = new Error(error.message);
enhancedError.originalError = error;
enhancedError.provider = providerName;
enhancedError.endpoint = endpoint;
enhancedError.status = error.response?.status;
enhancedError.code = error.code;
enhancedError.timestamp = Date.now();

// 添加用户友好的错误信息
if (error.response?.status === 401) {
enhancedError.userMessage = 'API认证失败,请检查密钥配置';
} else if (error.response?.status === 429) {
enhancedError.userMessage = '请求频率过高,请稍后再试';
} else if (error.response?.status >= 500) {
enhancedError.userMessage = 'AI服务暂时不可用,请稍后再试';
} else if (error.code === 'ETIMEDOUT') {
enhancedError.userMessage = '请求超时,请检查网络连接';
}

return enhancedError;
}

sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

具体AI服务集成

1. OpenAI API集成

// OpenAI服务提供商
class OpenAIProvider {
constructor(apiKey, options = {}) {
this.apiKey = apiKey;
this.baseURL = options.baseURL || 'https://api.openai.com/v1';
this.organization = options.organization;
this.supportsStreaming = true;

this.defaultHeaders = {
'Authorization': `Bearer ${this.apiKey}`,
'OpenAI-Organization': this.organization
};

this.models = {
'gpt-4': { maxTokens: 8192, costPer1kTokens: 0.03 },
'gpt-3.5-turbo': { maxTokens: 4096, costPer1kTokens: 0.002 },
'text-embedding-ada-002': { maxTokens: 8191, costPer1kTokens: 0.0001 }
};
}

async authenticate(requestConfig) {
// OpenAI使用Bearer token认证,已在defaultHeaders中设置
return requestConfig;
}

// 聊天完成
async chatCompletion(messages, options = {}) {
const requestData = {
model: options.model || 'gpt-3.5-turbo',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.maxTokens,
top_p: options.topP,
frequency_penalty: options.frequencyPenalty,
presence_penalty: options.presencePenalty,
stop: options.stop,
stream: options.stream || false
};

return await this.apiManager.call('openai', '/chat/completions', {
method: 'POST',
data: requestData,
...options
});
}

// 流式聊天
async streamChatCompletion(messages, options = {}, onChunk) {
return await this.apiManager.streamCall(
'openai',
'/chat/completions',
{
method: 'POST',
data: {
...options,
messages,
stream: true
}
},
onChunk
);
}

// 文本嵌入
async createEmbedding(input, options = {}) {
const requestData = {
model: options.model || 'text-embedding-ada-002',
input: Array.isArray(input) ? input : [input]
};

return await this.apiManager.call('openai', '/embeddings', {
method: 'POST',
data: requestData,
...options
});
}

// 图像生成
async generateImage(prompt, options = {}) {
const requestData = {
prompt,
model: options.model || 'dall-e-3',
n: options.n || 1,
size: options.size || '1024x1024',
quality: options.quality || 'standard',
style: options.style
};

return await this.apiManager.call('openai', '/images/generations', {
method: 'POST',
data: requestData,
...options
});
}

// 语音转文字
async transcribeAudio(audioFile, options = {}) {
const formData = new FormData();
formData.append('file', audioFile);
formData.append('model', options.model || 'whisper-1');

if (options.language) formData.append('language', options.language);
if (options.prompt) formData.append('prompt', options.prompt);
if (options.responseFormat) formData.append('response_format', options.responseFormat);
if (options.temperature) formData.append('temperature', options.temperature.toString());

return await this.apiManager.call('openai', '/audio/transcriptions', {
method: 'POST',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
},
...options
});
}

// 文字转语音
async generateSpeech(text, options = {}) {
const requestData = {
model: options.model || 'tts-1',
input: text,
voice: options.voice || 'alloy',
response_format: options.responseFormat || 'mp3',
speed: options.speed || 1.0
};

return await this.apiManager.call('openai', '/audio/speech', {
method: 'POST',
data: requestData,
responseType: 'blob',
...options
});
}

// 模型列表
async listModels() {
return await this.apiManager.call('openai', '/models', {
method: 'GET',
useCache: true,
cacheTTL: 3600000 // 1小时缓存
});
}

// 计算token数量(估算)
estimateTokens(text) {
// 简单估算:1 token ≈ 4 字符
return Math.ceil(text.length / 4);
}

// 计算成本
calculateCost(model, inputTokens, outputTokens = 0) {
const modelInfo = this.models[model];
if (!modelInfo) return null;

const totalTokens = inputTokens + outputTokens;
return (totalTokens / 1000) * modelInfo.costPer1kTokens;
}
}

2. Anthropic Claude API集成

// Anthropic服务提供商
class AnthropicProvider {
constructor(apiKey, options = {}) {
this.apiKey = apiKey;
this.baseURL = options.baseURL || 'https://api.anthropic.com/v1';
this.supportsStreaming = true;

this.defaultHeaders = {
'x-api-key': this.apiKey,
'anthropic-version': '2023-06-01'
};

this.models = {
'claude-3-opus-20240229': { maxTokens: 200000, costPer1kTokens: 0.015 },
'claude-3-sonnet-20240229': { maxTokens: 200000, costPer1kTokens: 0.003 },
'claude-3-haiku-20240307': { maxTokens: 200000, costPer1kTokens: 0.00025 }
};
}

async authenticate(requestConfig) {
// Anthropic使用x-api-key认证,已在defaultHeaders中设置
return requestConfig;
}

// 消息完成
async createMessage(messages, options = {}) {
// 转换消息格式
const anthropicMessages = this.convertMessages(messages);

const requestData = {
model: options.model || 'claude-3-sonnet-20240229',
max_tokens: options.maxTokens || 1024,
messages: anthropicMessages,
temperature: options.temperature,
top_p: options.topP,
top_k: options.topK,
stop_sequences: options.stopSequences,
stream: options.stream || false
};

return await this.apiManager.call('anthropic', '/messages', {
method: 'POST',
data: requestData,
...options
});
}

// 流式消息
async streamMessage(messages, options = {}, onChunk) {
return await this.apiManager.streamCall(
'anthropic',
'/messages',
{
method: 'POST',
data: {
...options,
messages: this.convertMessages(messages),
stream: true
}
},
onChunk
);
}

// 转换消息格式(OpenAI -> Anthropic)
convertMessages(messages) {
return messages.map(msg => {
if (msg.role === 'system') {
// Anthropic将system消息合并到第一个user消息中
return null;
}

return {
role: msg.role === 'assistant' ? 'assistant' : 'user',
content: msg.content
};
}).filter(msg => msg !== null);
}

// 文本完成(兼容性方法)
async complete(prompt, options = {}) {
const messages = [{ role: 'user', content: prompt }];
return await this.createMessage(messages, options);
}
}

3. Google AI API集成

// Google AI服务提供商
class GoogleAIProvider {
// ... 现有代码 ...
}

### 4. DeepSeek API集成

```javascript
// DeepSeek服务提供商
class DeepSeekProvider {
constructor(apiKey, options = {}) {
this.apiKey = apiKey;
this.baseURL = options.baseURL || 'https://api.deepseek.com/v1';
this.supportsStreaming = true;

this.defaultHeaders = {
'Authorization': `Bearer ${this.apiKey}`
};

this.models = {
'deepseek-chat': { maxTokens: 32768, costPer1kTokens: 0.001 }, // 示例价格
'deepseek-coder': { maxTokens: 32768, costPer1kTokens: 0.001 }
};
}

async authenticate(requestConfig) {
// DeepSeek使用Bearer token认证
return requestConfig;
}

// 聊天完成
async chatCompletion(messages, options = {}) {
const requestData = {
model: options.model || 'deepseek-chat',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.maxTokens,
top_p: options.topP,
frequency_penalty: options.frequencyPenalty,
presence_penalty: options.presencePenalty,
stop: options.stop,
stream: options.stream || false
};

return await this.apiManager.call('deepseek', '/chat/completions', {
method: 'POST',
data: requestData,
...options
});
}

// 流式聊天
async streamChatCompletion(messages, options = {}, onChunk) {
return await this.apiManager.streamCall(
'deepseek',
'/chat/completions',
{
method: 'POST',
data: {
...options,
model: options.model || 'deepseek-chat',
messages,
stream: true
}
},
onChunk
);
}
}

高级功能实现

1. 智能缓存系统

// 智能API缓存系统
class APICache {
constructor(options = {}) {
this.storage = options.storage || 'memory'; // 'memory', 'localStorage', 'indexedDB'
this.defaultTTL = options.defaultTTL || 3600000; // 1小时
this.maxSize = options.maxSize || 1000;
this.compressionEnabled = options.compression !== false;

this.cache = new Map();
this.accessTimes = new Map();
this.hitCount = 0;
this.missCount = 0;

this.initializeStorage();
}

async initializeStorage() {
switch (this.storage) {
case 'localStorage':
this.storageAdapter = new LocalStorageAdapter();
break;
case 'indexedDB':
this.storageAdapter = new IndexedDBAdapter();
await this.storageAdapter.initialize();
break;
default:
this.storageAdapter = new MemoryAdapter();
}
}

async get(key) {
try {
let cacheEntry = this.cache.get(key);

if (!cacheEntry && this.storageAdapter) {
cacheEntry = await this.storageAdapter.get(key);
if (cacheEntry) {
this.cache.set(key, cacheEntry);
}
}

if (!cacheEntry) {
this.missCount++;
return null;
}

// 检查过期时间
if (Date.now() > cacheEntry.expiresAt) {
await this.delete(key);
this.missCount++;
return null;
}

// 更新访问时间
this.accessTimes.set(key, Date.now());
this.hitCount++;

// 解压缩数据
const data = this.compressionEnabled
? await this.decompress(cacheEntry.data)
: cacheEntry.data;

return data;

} catch (error) {
console.error('Cache get error:', error);
this.missCount++;
return null;
}
}

async set(key, data, ttl = null) {
try {
const expiresAt = Date.now() + (ttl || this.defaultTTL);

// 压缩数据
const compressedData = this.compressionEnabled
? await this.compress(data)
: data;

const cacheEntry = {
data: compressedData,
createdAt: Date.now(),
expiresAt,
size: this.calculateSize(compressedData)
};

// 检查缓存大小限制
await this.ensureCapacity();

// 存储到内存缓存
this.cache.set(key, cacheEntry);
this.accessTimes.set(key, Date.now());

// 存储到持久化存储
if (this.storageAdapter) {
await this.storageAdapter.set(key, cacheEntry);
}

} catch (error) {
console.error('Cache set error:', error);
}
}

async delete(key) {
this.cache.delete(key);
this.accessTimes.delete(key);

if (this.storageAdapter) {
await this.storageAdapter.delete(key);
}
}

async clear() {
this.cache.clear();
this.accessTimes.clear();

if (this.storageAdapter) {
await this.storageAdapter.clear();
}
}

// 确保缓存容量不超限
async ensureCapacity() {
if (this.cache.size < this.maxSize) return;

// 使用LRU策略清理缓存
const entries = Array.from(this.accessTimes.entries())
.sort((a, b) => a[1] - b[1]) // 按访问时间排序
.slice(0, Math.floor(this.maxSize * 0.2)); // 清理20%的最旧条目

for (const [key] of entries) {
await this.delete(key);
}
}

// 缓存统计
getStats() {
const totalRequests = this.hitCount + this.missCount;
return {
hitCount: this.hitCount,
missCount: this.missCount,
hitRate: totalRequests > 0 ? this.hitCount / totalRequests : 0,
cacheSize: this.cache.size,
maxSize: this.maxSize
};
}

// 数据压缩
async compress(data) {
if (typeof data === 'string') {
// 使用简单的压缩算法
return btoa(unescape(encodeURIComponent(data)));
}
return data;
}

async decompress(data) {
if (typeof data === 'string') {
try {
return decodeURIComponent(escape(atob(data)));
} catch {
return data; // 如果解压失败,返回原数据
}
}
return data;
}

calculateSize(data) {
return JSON.stringify(data).length;
}
}

2. 速率限制器

// 智能速率限制器
class RateLimiter {
constructor(options = {}) {
this.limits = new Map();
this.defaultLimits = {
requestsPerMinute: options.requestsPerMinute || 60,
requestsPerHour: options.requestsPerHour || 3600,
tokensPerMinute: options.tokensPerMinute || 90000,
tokensPerHour: options.tokensPerHour || 1000000
};

this.windows = new Map();
this.cleanupInterval = setInterval(() => this.cleanup(), 60000); // 每分钟清理一次
}

// 设置提供商特定的限制
setProviderLimits(provider, limits) {
this.limits.set(provider, {
...this.defaultLimits,
...limits
});
}

// 检查速率限制
async checkLimit(provider, estimatedTokens = 0) {
const limits = this.limits.get(provider) || this.defaultLimits;
const now = Date.now();

// 获取或创建时间窗口
if (!this.windows.has(provider)) {
this.windows.set(provider, {
requests: [],
tokens: []
});
}

const window = this.windows.get(provider);

// 清理过期的记录
this.cleanupWindow(window, now);

// 检查请求频率限制
const recentRequests = window.requests.filter(time => now - time < 60000); // 1分钟内
const hourlyRequests = window.requests.filter(time => now - time < 3600000); // 1小时内

if (recentRequests.length >= limits.requestsPerMinute) {
const waitTime = 60000 - (now - recentRequests[0]);
throw new RateLimitError(`Rate limit exceeded: ${limits.requestsPerMinute} requests per minute`, waitTime);
}

if (hourlyRequests.length >= limits.requestsPerHour) {
const waitTime = 3600000 - (now - hourlyRequests[0]);
throw new RateLimitError(`Rate limit exceeded: ${limits.requestsPerHour} requests per hour`, waitTime);
}

// 检查token限制
if (estimatedTokens > 0) {
const recentTokens = window.tokens
.filter(record => now - record.time < 60000)
.reduce((sum, record) => sum + record.count, 0);

const hourlyTokens = window.tokens
.filter(record => now - record.time < 3600000)
.reduce((sum, record) => sum + record.count, 0);

if (recentTokens + estimatedTokens > limits.tokensPerMinute) {
const waitTime = 60000 - (now - window.tokens.find(r => now - r.time < 60000)?.time || 0);
throw new RateLimitError(`Token rate limit exceeded: ${limits.tokensPerMinute} tokens per minute`, waitTime);
}

if (hourlyTokens + estimatedTokens > limits.tokensPerHour) {
const waitTime = 3600000 - (now - window.tokens.find(r => now - r.time < 3600000)?.time || 0);
throw new RateLimitError(`Token rate limit exceeded: ${limits.tokensPerHour} tokens per hour`, waitTime);
}
}

// 记录请求
window.requests.push(now);
if (estimatedTokens > 0) {
window.tokens.push({ time: now, count: estimatedTokens });
}
}

// 清理过期的时间窗口记录
cleanupWindow(window, now) {
const oneHourAgo = now - 3600000;
window.requests = window.requests.filter(time => time > oneHourAgo);
window.tokens = window.tokens.filter(record => record.time > oneHourAgo);
}

// 定期清理
cleanup() {
const now = Date.now();
for (const [provider, window] of this.windows) {
this.cleanupWindow(window, now);

// 如果窗口为空,删除它
if (window.requests.length === 0 && window.tokens.length === 0) {
this.windows.delete(provider);
}
}
}

// 获取当前使用情况
getCurrentUsage(provider) {
const window = this.windows.get(provider);
if (!window) return null;

const now = Date.now();
const recentRequests = window.requests.filter(time => now - time < 60000).length;
const hourlyRequests = window.requests.filter(time => now - time < 3600000).length;

const recentTokens = window.tokens
.filter(record => now - record.time < 60000)
.reduce((sum, record) => sum + record.count, 0);

const hourlyTokens = window.tokens
.filter(record => now - record.time < 3600000)
.reduce((sum, record) => sum + record.count, 0);

const limits = this.limits.get(provider) || this.defaultLimits;

return {
requests: {
perMinute: { current: recentRequests, limit: limits.requestsPerMinute },
perHour: { current: hourlyRequests, limit: limits.requestsPerHour }
},
tokens: {
perMinute: { current: recentTokens, limit: limits.tokensPerMinute },
perHour: { current: hourlyTokens, limit: limits.tokensPerHour }
}
};
}

destroy() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
}
}

// 速率限制错误类
class RateLimitError extends Error {
constructor(message, waitTime) {
super(message);
this.name = 'RateLimitError';
this.waitTime = waitTime;
this.retryAfter = new Date(Date.now() + waitTime);
}
}

3. API监控系统

// API监控系统
class APIMonitor {
constructor(options = {}) {
this.metrics = new Map();
this.alerts = [];
this.thresholds = {
errorRate: options.errorRateThreshold || 0.1, // 10%错误率
responseTime: options.responseTimeThreshold || 5000, // 5秒响应时间
...options.thresholds
};

this.listeners = new Set();
this.reportingInterval = options.reportingInterval || 60000; // 1分钟

this.startReporting();
}

// 记录API调用
recordAPICall(provider, endpoint, duration, success, error = null) {
const key = `${provider}:${endpoint}`;

if (!this.metrics.has(key)) {
this.metrics.set(key, {
provider,
endpoint,
totalCalls: 0,
successfulCalls: 0,
failedCalls: 0,
totalDuration: 0,
averageResponseTime: 0,
minResponseTime: Infinity,
maxResponseTime: 0,
errors: [],
lastCall: null,
recentCalls: [] // 最近100次调用的详细信息
});
}

const metric = this.metrics.get(key);

// 更新基本统计
metric.totalCalls++;
metric.totalDuration += duration;
metric.averageResponseTime = metric.totalDuration / metric.totalCalls;
metric.minResponseTime = Math.min(metric.minResponseTime, duration);
metric.maxResponseTime = Math.max(metric.maxResponseTime, duration);
metric.lastCall = Date.now();

if (success) {
metric.successfulCalls++;
} else {
metric.failedCalls++;
metric.errors.push({
timestamp: Date.now(),
error: error?.message || 'Unknown error',
status: error?.status,
code: error?.code
});

// 保持最近50个错误
if (metric.errors.length > 50) {
metric.errors.shift();
}
}

// 记录最近调用详情
metric.recentCalls.push({
timestamp: Date.now(),
duration,
success,
error: error?.message
});

// 保持最近100次调用
if (metric.recentCalls.length > 100) {
metric.recentCalls.shift();
}

// 检查告警条件
this.checkAlerts(key, metric);
}

// 记录缓存命中
recordCacheHit(provider, requestId) {
const key = `${provider}:cache`;

if (!this.metrics.has(key)) {
this.metrics.set(key, {
provider,
endpoint: 'cache',
hits: 0,
misses: 0,
hitRate: 0
});
}

const metric = this.metrics.get(key);
metric.hits++;
metric.hitRate = metric.hits / (metric.hits + metric.misses);
}

// 记录错误
recordError(provider, requestId, error) {
const errorKey = `${provider}:errors`;

if (!this.metrics.has(errorKey)) {
this.metrics.set(errorKey, {
provider,
endpoint: 'errors',
totalErrors: 0,
errorsByType: new Map(),
recentErrors: []
});
}

const metric = this.metrics.get(errorKey);
metric.totalErrors++;

const errorType = error.constructor.name;
metric.errorsByType.set(errorType, (metric.errorsByType.get(errorType) || 0) + 1);

metric.recentErrors.push({
timestamp: Date.now(),
requestId,
type: errorType,
message: error.message,
status: error.status,
code: error.code
});

// 保持最近100个错误
if (metric.recentErrors.length > 100) {
metric.recentErrors.shift();
}
}

// 检查告警条件
checkAlerts(key, metric) {
const now = Date.now();
const recentCalls = metric.recentCalls.filter(call => now - call.timestamp < 300000); // 5分钟内

if (recentCalls.length < 10) return; // 样本太少

const errorRate = recentCalls.filter(call => !call.success).length / recentCalls.length;
const avgResponseTime = recentCalls.reduce((sum, call) => sum + call.duration, 0) / recentCalls.length;

// 错误率告警
if (errorRate > this.thresholds.errorRate) {
this.createAlert({
type: 'HIGH_ERROR_RATE',
provider: metric.provider,
endpoint: metric.endpoint,
value: errorRate,
threshold: this.thresholds.errorRate,
message: `High error rate detected: ${(errorRate * 100).toFixed(2)}%`
});
}

// 响应时间告警
if (avgResponseTime > this.thresholds.responseTime) {
this.createAlert({
type: 'HIGH_RESPONSE_TIME',
provider: metric.provider,
endpoint: metric.endpoint,
value: avgResponseTime,
threshold: this.thresholds.responseTime,
message: `High response time detected: ${avgResponseTime.toFixed(0)}ms`
});
}
}

// 创建告警
createAlert(alert) {
const alertKey = `${alert.type}:${alert.provider}:${alert.endpoint}`;
const existingAlert = this.alerts.find(a => a.key === alertKey && !a.resolved);

if (existingAlert) {
// 更新现有告警
existingAlert.count++;
existingAlert.lastOccurrence = Date.now();
existingAlert.value = alert.value;
} else {
// 创建新告警
const newAlert = {
...alert,
key: alertKey,
id: this.generateAlertId(),
timestamp: Date.now(),
lastOccurrence: Date.now(),
count: 1,
resolved: false
};

this.alerts.push(newAlert);

// 通知监听器
this.notifyListeners('alert', newAlert);
}
}

// 获取监控报告
generateReport(timeRange = 3600000) { // 默认1小时
const now = Date.now();
const cutoff = now - timeRange;

const report = {
timestamp: now,
timeRange,
summary: {
totalProviders: new Set(Array.from(this.metrics.values()).map(m => m.provider)).size,
totalEndpoints: this.metrics.size,
totalCalls: 0,
totalErrors: 0,
averageResponseTime: 0
},
providers: {},
alerts: this.alerts.filter(alert => alert.timestamp > cutoff && !alert.resolved),
topErrors: this.getTopErrors(timeRange)
};

// 按提供商分组统计
for (const [key, metric] of this.metrics) {
if (metric.lastCall && metric.lastCall > cutoff) {
const provider = metric.provider;

if (!report.providers[provider]) {
report.providers[provider] = {
totalCalls: 0,
successfulCalls: 0,
failedCalls: 0,
averageResponseTime: 0,
endpoints: {}
};
}

const providerStats = report.providers[provider];
providerStats.totalCalls += metric.totalCalls;
providerStats.successfulCalls += metric.successfulCalls;
providerStats.failedCalls += metric.failedCalls;

providerStats.endpoints[metric.endpoint] = {
totalCalls: metric.totalCalls,
successRate: metric.totalCalls > 0 ? metric.successfulCalls / metric.totalCalls : 0,
averageResponseTime: metric.averageResponseTime,
minResponseTime: metric.minResponseTime,
maxResponseTime: metric.maxResponseTime
};

report.summary.totalCalls += metric.totalCalls;
report.summary.totalErrors += metric.failedCalls;
}
}

// 计算总体平均响应时间
const totalDuration = Array.from(this.metrics.values())
.reduce((sum, metric) => sum + metric.totalDuration, 0);
report.summary.averageResponseTime = report.summary.totalCalls > 0
? totalDuration / report.summary.totalCalls
: 0;

return report;
}

// 获取热门错误
getTopErrors(timeRange = 3600000) {
const now = Date.now();
const cutoff = now - timeRange;
const errorCounts = new Map();

for (const metric of this.metrics.values()) {
if (metric.errors) {
const recentErrors = metric.errors.filter(error => error.timestamp > cutoff);

for (const error of recentErrors) {
const key = `${error.error} (${error.status || error.code || 'Unknown'})`;
errorCounts.set(key, (errorCounts.get(key) || 0) + 1);
}
}
}

return Array.from(errorCounts.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([error, count]) => ({ error, count }));
}

// 添加监听器
addListener(listener) {
this.listeners.add(listener);
}

// 移除监听器
removeListener(listener) {
this.listeners.delete(listener);
}

// 通知监听器
notifyListeners(event, data) {
for (const listener of this.listeners) {
try {
listener(event, data);
} catch (error) {
console.error('Monitor listener error:', error);
}
}
}

// 开始定期报告
startReporting() {
this.reportingTimer = setInterval(() => {
const report = this.generateReport();
this.notifyListeners('report', report);
}, this.reportingInterval);
}

// 停止监控
stop() {
if (this.reportingTimer) {
clearInterval(this.reportingTimer);
}
}

generateAlertId() {
return `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}

使用示例

完整集成示例

// 完整的AI API集成示例
class AIApplication {
constructor() {
this.apiManager = new AIAPIManager({
timeout: 30000,
retryAttempts: 3,
cacheEnabled: true,
rateLimitEnabled: true
});

this.setupProviders();
this.setupMonitoring();
}

setupProviders() {
// 注册OpenAI
this.apiManager.registerProvider('openai', new OpenAIProvider(
process.env.OPENAI_API_KEY,
{ organization: process.env.OPENAI_ORG_ID }
));

// 注册Anthropic
this.apiManager.registerProvider('anthropic', new AnthropicProvider(
process.env.ANTHROPIC_API_KEY
));

// 注册Google AI
this.apiManager.registerProvider('google', new GoogleAIProvider(
process.env.GOOGLE_AI_API_KEY
));

// 设置速率限制
this.apiManager.rateLimiter.setProviderLimits('openai', {
requestsPerMinute: 60,
tokensPerMinute: 90000
});
}

setupMonitoring() {
this.apiManager.monitor.addListener((event, data) => {
switch (event) {
case 'alert':
console.warn('API Alert:', data);
this.handleAlert(data);
break;
case 'report':
console.log('API Report:', data.summary);
break;
}
});
}

// 智能聊天(自动选择最佳提供商)
async chat(message, options = {}) {
const providers = ['openai', 'anthropic', 'google'];

for (const provider of providers) {
try {
const result = await this.apiManager.call(provider, '/chat', {
data: { message, ...options },
timeout: 15000
});

return {
response: result.data.response,
provider,
fromCache: result.fromCache
};

} catch (error) {
console.warn(`Provider ${provider} failed:`, error.message);

if (provider === providers[providers.length - 1]) {
throw new Error('All AI providers failed');
}
}
}
}

// 批量处理
async batchProcess(messages, options = {}) {
const requests = messages.map(message => ({
provider: 'openai',
endpoint: '/chat',
options: {
data: { message, ...options }
}
}));

return await this.apiManager.batchCall(requests, {
batchSize: 5,
batchDelay: 1000,
onProgress: (progress) => {
console.log(`Batch progress: ${Math.round(progress.progress * 100)}%`);
}
});
}

// 流式聊天
async streamChat(message, onChunk, options = {}) {
return await this.apiManager.streamCall(
'openai',
'/chat/stream',
{
data: { message, stream: true, ...options }
},
onChunk
);
}

// 健康检查
async checkHealth() {
return await this.apiManager.healthCheck();
}

// 获取统计信息
getStats() {
return {
providers: this.apiManager.getProviderStats(),
cache: this.apiManager.cache.getStats(),
monitor: this.apiManager.monitor.generateReport()
};
}

// 处理告警
handleAlert(alert) {
// 实现告警处理逻辑
// 例如:发送通知、切换提供商、调整参数等

if (alert.type === 'HIGH_ERROR_RATE') {
console.log(`Switching away from ${alert.provider} due to high error rate`);
// 实现提供商切换逻辑
}
}
}

// 使用示例
const aiApp = new AIApplication();

// 简单聊天
aiApp.chat('Hello, how are you?')
.then(result => {
console.log('Response:', result.response);
console.log('Provider:', result.provider);
})
.catch(error => {
console.error('Chat error:', error);
});

// 流式聊天
aiApp.streamChat(
'Tell me a story',
(chunk) => {
console.log('Chunk:', chunk.content);
if (chunk.finished) {
console.log('Full story:', chunk.fullContent);
}
}
);

// 批量处理
const messages = ['Hello', 'How are you?', 'Tell me a joke'];
aiApp.batchProcess(messages)
.then(results => {
results.forEach((result, index) => {
if (result.success) {
console.log(`Message ${index + 1}:`, result.result.data.response);
} else {
console.error(`Message ${index + 1} failed:`, result.error.message);
}
});
});

最佳实践

1. 错误处理策略

// 分层错误处理
class ErrorHandler {
static handle(error, context = {}) {
const errorInfo = {
timestamp: Date.now(),
context,
originalError: error
};

// 根据错误类型进行分类处理
if (error instanceof RateLimitError) {
return this.handleRateLimit(error, errorInfo);
} else if (error.status === 401) {
return this.handleAuthError(error, errorInfo);
} else if (error.status >= 500) {
return this.handleServerError(error, errorInfo);
} else if (error.code === 'ETIMEDOUT') {
return this.handleTimeoutError(error, errorInfo);
} else {
return this.handleGenericError(error, errorInfo);
}
}

static handleRateLimit(error, errorInfo) {
console.warn('Rate limit exceeded:', error.message);

return {
type: 'RATE_LIMIT',
message: '请求过于频繁,请稍后再试',
retryAfter: error.retryAfter,
canRetry: true,
retryDelay: error.waitTime
};
}

static handleAuthError(error, errorInfo) {
console.error('Authentication failed:', error.message);

return {
type: 'AUTH_ERROR',
message: 'API认证失败,请检查密钥配置',
canRetry: false,
requiresUserAction: true
};
}

static handleServerError(error, errorInfo) {
console.error('Server error:', error.message);

return {
type: 'SERVER_ERROR',
message: 'AI服务暂时不可用,请稍后再试',
canRetry: true,
retryDelay: 5000
};
}

static handleTimeoutError(error, errorInfo) {
console.warn('Request timeout:', error.message);

return {
type: 'TIMEOUT',
message: '请求超时,请检查网络连接',
canRetry: true,
retryDelay: 2000
};
}

static handleGenericError(error, errorInfo) {
console.error('Generic error:', error.message);

return {
type: 'GENERIC_ERROR',
message: '请求失败,请稍后再试',
canRetry: true,
retryDelay: 1000
};
}
}

2. 性能优化

// 性能优化工具
class PerformanceOptimizer {
constructor() {
this.requestQueue = [];
this.processing = false;
this.batchSize = 5;
this.batchDelay = 100;
}

// 请求去重
deduplicateRequests(requests) {
const seen = new Set();
return requests.filter(request => {
const key = this.generateRequestKey(request);
if (seen.has(key)) {
return false;
}
seen.add(key);
return true;
});
}

// 请求合并
async batchRequests(requests) {
const batches = [];
for (let i = 0; i < requests.length; i += this.batchSize) {
batches.push(requests.slice(i, i + this.batchSize));
}

const results = [];
for (const batch of batches) {
const batchResults = await Promise.allSettled(
batch.map(request => this.executeRequest(request))
);
results.push(...batchResults);

if (batches.indexOf(batch) < batches.length - 1) {
await this.sleep(this.batchDelay);
}
}

return results;
}

// 智能缓存预热
async preheatCache(commonRequests) {
console.log('Preheating cache with common requests...');

const preheatPromises = commonRequests.map(async (request) => {
try {
await this.executeRequest(request);
console.log(`Cache preheated for: ${request.endpoint}`);
} catch (error) {
console.warn(`Failed to preheat cache for ${request.endpoint}:`, error.message);
}
});

await Promise.allSettled(preheatPromises);
console.log('Cache preheating completed');
}

// 连接池管理
manageConnectionPool() {
// 实现HTTP连接池管理
return {
maxConnections: 10,
keepAlive: true,
timeout: 30000
};
}

generateRequestKey(request) {
return `${request.provider}:${request.endpoint}:${JSON.stringify(request.data)}`;
}

sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

3. 安全最佳实践

// 安全管理器
class SecurityManager {
constructor() {
this.apiKeys = new Map();
this.encryptionKey = this.generateEncryptionKey();
}

// 安全存储API密钥
storeAPIKey(provider, apiKey) {
const encrypted = this.encrypt(apiKey);
this.apiKeys.set(provider, encrypted);

// 不在内存中保留明文密钥
apiKey = null;
}

// 获取API密钥
getAPIKey(provider) {
const encrypted = this.apiKeys.get(provider);
if (!encrypted) return null;

return this.decrypt(encrypted);
}

// 请求数据脱敏
sanitizeRequestData(data) {
const sanitized = JSON.parse(JSON.stringify(data));

// 移除敏感信息
const sensitiveFields = ['password', 'token', 'key', 'secret', 'credential'];

const sanitizeObject = (obj) => {
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
sanitizeObject(obj[key]);
} else if (sensitiveFields.some(field => key.toLowerCase().includes(field))) {
obj[key] = '[REDACTED]';
}
}
};

sanitizeObject(sanitized);
return sanitized;
}

// 输入验证
validateInput(input, rules) {
const errors = [];

for (const [field, rule] of Object.entries(rules)) {
const value = input[field];

if (rule.required && (value === undefined || value === null || value === '')) {
errors.push(`${field} is required`);
continue;
}

if (value !== undefined && value !== null) {
if (rule.type && typeof value !== rule.type) {
errors.push(`${field} must be of type ${rule.type}`);
}

if (rule.minLength && value.length < rule.minLength) {
errors.push(`${field} must be at least ${rule.minLength} characters`);
}

if (rule.maxLength && value.length > rule.maxLength) {
errors.push(`${field} must be no more than ${rule.maxLength} characters`);
}

if (rule.pattern && !rule.pattern.test(value)) {
errors.push(`${field} format is invalid`);
}
}
}

return {
valid: errors.length === 0,
errors
};
}

// 简单加密(生产环境应使用更强的加密)
encrypt(text) {
return btoa(text); // 简化实现,生产环境应使用AES等
}

decrypt(encrypted) {
return atob(encrypted); // 简化实现
}

generateEncryptionKey() {
return Math.random().toString(36).substring(2, 15);
}
}

学习检验

理论问题

  1. API集成架构

    • 解释AI API集成的核心组件及其作用
    • 描述统一API管理器的设计原理
    • 分析不同AI服务提供商的API差异
  2. 性能优化

    • 说明缓存策略在API集成中的重要性
    • 解释速率限制的实现原理和必要性
    • 描述批量处理和流式处理的适用场景
  3. 错误处理

    • 列举常见的API错误类型及处理策略
    • 解释重试机制的设计原则
    • 描述降级策略的实现方法

实践练习

  1. 基础集成

    // 练习:实现一个简单的OpenAI API客户端
    class SimpleOpenAIClient {
    constructor(apiKey) {
    // TODO: 实现构造函数
    }

    async chat(message) {
    // TODO: 实现聊天功能
    }

    async generateImage(prompt) {
    // TODO: 实现图像生成
    }
    }
  2. 错误处理

    // 练习:实现带重试机制的API调用
    async function callWithRetry(apiCall, maxRetries = 3) {
    // TODO: 实现重试逻辑
    }
  3. 缓存实现

    // 练习:实现一个LRU缓存
    class LRUCache {
    constructor(capacity) {
    // TODO: 实现LRU缓存
    }

    get(key) {
    // TODO: 实现获取方法
    }

    set(key, value) {
    // TODO: 实现设置方法
    }
    }

实践项目建议

初级项目

  1. AI聊天客户端

    • 集成OpenAI GPT API
    • 实现基本的聊天界面
    • 添加错误处理和加载状态
  2. 多模态AI工具

    • 集成文本和图像生成API
    • 实现文件上传和处理
    • 添加结果展示和下载功能

中级项目

  1. AI API代理服务

    • 实现多个AI服务的统一接口
    • 添加认证和速率限制
    • 实现请求日志和监控
  2. 智能内容生成平台

    • 集成多个AI服务
    • 实现内容模板和批量生成
    • 添加用户管理和计费功能

高级项目

  1. 企业级AI网关

    • 实现负载均衡和故障转移
    • 添加详细的监控和告警
    • 实现成本控制和优化
  2. AI服务编排平台

    • 实现复杂的AI工作流
    • 添加可视化编排界面
    • 实现分布式执行和状态管理

延伸阅读

核心文档

推荐文章

  • "Building Resilient API Integrations"
  • "Rate Limiting Strategies for APIs"
  • "Caching Best Practices for AI Applications"
  • "Error Handling in Distributed Systems"

开源项目

在线资源