Learn how to integrate and manage connections to all major AI providers in a unified way. This comprehensive guide covers setup, authentication, and best practices for OpenAI, Anthropic, Google AI, Azure OpenAI, and AWS Bedrock.
Provider Overview and Selection
Provider Capabilities Comparison
Provider | Models | Strengths | Best For | Pricing |
---|---|---|---|---|
OpenAI | GPT-4, GPT-3.5 | General purpose, widely adopted | Chat, content generation | Pay-per-token |
Anthropic | Claude 3.5 Sonnet, Claude 3 Haiku | Safety-focused, reasoning | Analysis, reasoning tasks | Pay-per-token |
Google AI | Gemini Pro, PaLM | Multimodal, integration | Search, multimodal tasks | Pay-per-token |
Azure OpenAI | GPT-4, GPT-3.5 | Enterprise features, compliance | Enterprise applications | Pay-per-token + hosting |
AWS Bedrock | Claude, Llama, Titan | Managed service, security | Enterprise, regulated industries | Pay-per-token + hosting |
:::tip Provider Selection Strategy Choose providers based on your specific needs: OpenAI for general use, Anthropic for reasoning tasks, Google for multimodal needs, Azure for enterprise compliance, and AWS for managed infrastructure. :::
OpenAI Integration
Setup and Authentication
// OpenAI SDK setup
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
organization: process.env.OPENAI_ORG_ID, // Optional
});
// Basic completion
async function openaiCompletion(prompt, model = 'gpt-4') {
try {
const response = await openai.chat.completions.create({
model: model,
messages: [{ role: 'user', content: prompt }],
max_tokens: 1000,
temperature: 0.7,
});
return {
text: response.choices[0].message.content,
usage: response.usage,
cost: calculateOpenAICost(response.usage, model)
};
} catch (error) {
console.error('OpenAI API error:', error);
throw error;
}
}
// Cost calculation
function calculateOpenAICost(usage, model) {
const pricing = {
'gpt-4': { input: 0.03, output: 0.06 },
'gpt-3.5-turbo': { input: 0.0015, output: 0.002 }
};
const rates = pricing[model] || pricing['gpt-3.5-turbo'];
return (usage.prompt_tokens * rates.input + usage.completion_tokens * rates.output) / 1000;
}
Advanced OpenAI Features
// Streaming responses
async function openaiStreamingCompletion(prompt) {
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
process.stdout.write(content);
}
}
}
// Function calling
async function openaiWithFunctions(prompt) {
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
functions: [
{
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' }
},
required: ['location']
}
}
],
function_call: 'auto'
});
return response;
}
Anthropic Claude Integration
Setup and Authentication
// Anthropic SDK setup
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Basic completion
async function claudeCompletion(prompt, model = 'claude-3-5-sonnet-20241022') {
try {
const response = await anthropic.messages.create({
model: model,
max_tokens: 1000,
temperature: 0.7,
messages: [{ role: 'user', content: prompt }]
});
return {
text: response.content[0].text,
usage: response.usage,
cost: calculateClaudeCost(response.usage, model)
};
} catch (error) {
console.error('Anthropic API error:', error);
throw error;
}
}
// Cost calculation for Claude
function calculateClaudeCost(usage, model) {
const pricing = {
'claude-3-5-sonnet-20241022': { input: 0.003, output: 0.015 },
'claude-3-haiku-20240307': { input: 0.00025, output: 0.00125 }
};
const rates = pricing[model] || pricing['claude-3-5-sonnet-20241022'];
return (usage.input_tokens * rates.input + usage.output_tokens * rates.output) / 1000;
}
Advanced Claude Features
// System prompts with Claude
async function claudeWithSystem(userPrompt, systemPrompt) {
const response = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1000,
system: systemPrompt,
messages: [{ role: 'user', content: userPrompt }]
});
return response.content[0].text;
}
// Claude streaming
async function claudeStreaming(prompt) {
const stream = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1000,
messages: [{ role: 'user', content: prompt }],
stream: true
});
for await (const event of stream) {
if (event.type === 'content_block_delta') {
process.stdout.write(event.delta.text);
}
}
}
Google AI Integration
Setup and Authentication
// Google AI SDK setup
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_AI_API_KEY);
// Basic completion
async function geminiCompletion(prompt, model = 'gemini-pro') {
try {
const model_instance = genAI.getGenerativeModel({ model: model });
const result = await model_instance.generateContent(prompt);
const response = await result.response;
return {
text: response.text(),
usage: response.usageMetadata,
cost: calculateGeminiCost(response.usageMetadata, model)
};
} catch (error) {
console.error('Google AI API error:', error);
throw error;
}
}
// Cost calculation for Gemini
function calculateGeminiCost(usage, model) {
const pricing = {
'gemini-pro': { input: 0.0005, output: 0.0015 },
'gemini-pro-vision': { input: 0.00025, output: 0.0005 }
};
const rates = pricing[model] || pricing['gemini-pro'];
return (usage.promptTokenCount * rates.input + usage.candidatesTokenCount * rates.output) / 1000;
}
Multimodal Capabilities
// Image analysis with Gemini
async function geminiVision(imageBase64, prompt) {
const model = genAI.getGenerativeModel({ model: 'gemini-pro-vision' });
const result = await model.generateContent([
prompt,
{
inlineData: {
mimeType: 'image/jpeg',
data: imageBase64
}
}
]);
return result.response.text();
}
// Chat with Gemini
async function geminiChat(messages) {
const model = genAI.getGenerativeModel({ model: 'gemini-pro' });
const chat = model.startChat({
history: messages.slice(0, -1).map(msg => ({
role: msg.role === 'user' ? 'user' : 'model',
parts: [{ text: msg.content }]
}))
});
const result = await chat.sendMessage(messages[messages.length - 1].content);
return result.response.text();
}
Azure OpenAI Integration
Setup and Authentication
// Azure OpenAI SDK setup
import { OpenAI } from 'openai';
const azureOpenAI = new OpenAI({
apiKey: process.env.AZURE_OPENAI_API_KEY,
baseURL: `https://${process.env.AZURE_OPENAI_RESOURCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_DEPLOYMENT_NAME}`,
defaultQuery: { 'api-version': '2024-02-15-preview' },
defaultHeaders: {
'api-key': process.env.AZURE_OPENAI_API_KEY,
},
});
// Basic completion with Azure
async function azureCompletion(prompt, deploymentName = 'gpt-4') {
try {
const response = await azureOpenAI.chat.completions.create({
model: deploymentName, // This is your deployment name
messages: [{ role: 'user', content: prompt }],
max_tokens: 1000,
temperature: 0.7,
});
return {
text: response.choices[0].message.content,
usage: response.usage,
cost: calculateAzureCost(response.usage, deploymentName)
};
} catch (error) {
console.error('Azure OpenAI API error:', error);
throw error;
}
}
// Azure-specific cost calculation
function calculateAzureCost(usage, model) {
// Azure pricing includes hosting costs
const basePricing = {
'gpt-4': { input: 0.03, output: 0.06 },
'gpt-35-turbo': { input: 0.0015, output: 0.002 }
};
const rates = basePricing[model] || basePricing['gpt-35-turbo'];
const tokenCost = (usage.prompt_tokens * rates.input + usage.completion_tokens * rates.output) / 1000;
// Add Azure hosting overhead (approximately 10-20%)
return tokenCost * 1.15;
}
Azure-Specific Features
// Azure content filtering
async function azureCompletionWithFiltering(prompt) {
const response = await azureOpenAI.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
max_tokens: 1000,
// Azure-specific parameters
content_filter_results: true,
});
// Check content filtering results
if (response.choices[0].content_filter_results) {
console.log('Content filter results:', response.choices[0].content_filter_results);
}
return response;
}
// Managed identity authentication (for Azure services)
import { DefaultAzureCredential } from '@azure/identity';
const credential = new DefaultAzureCredential();
const token = await credential.getToken('https://cognitiveservices.azure.com/.default');
const azureOpenAIWithManagedIdentity = new OpenAI({
baseURL: `https://${process.env.AZURE_OPENAI_RESOURCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_DEPLOYMENT_NAME}`,
defaultQuery: { 'api-version': '2024-02-15-preview' },
defaultHeaders: {
'Authorization': `Bearer ${token.token}`,
},
});
AWS Bedrock Integration
Setup and Authentication
// AWS Bedrock SDK setup
import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime';
const bedrockClient = new BedrockRuntimeClient({
region: process.env.AWS_REGION || 'us-east-1',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});
// Claude on Bedrock
async function bedrockClaudeCompletion(prompt, modelId = 'anthropic.claude-3-sonnet-20240229-v1:0') {
try {
const request = {
anthropic_version: 'bedrock-2023-05-31',
max_tokens: 1000,
messages: [{ role: 'user', content: prompt }],
temperature: 0.7
};
const command = new InvokeModelCommand({
modelId: modelId,
contentType: 'application/json',
body: JSON.stringify(request),
});
const response = await bedrockClient.send(command);
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
return {
text: responseBody.content[0].text,
usage: responseBody.usage,
cost: calculateBedrockCost(responseBody.usage, modelId)
};
} catch (error) {
console.error('Bedrock API error:', error);
throw error;
}
}
// Bedrock cost calculation
function calculateBedrockCost(usage, modelId) {
const pricing = {
'anthropic.claude-3-sonnet-20240229-v1:0': { input: 0.003, output: 0.015 },
'anthropic.claude-3-haiku-20240307-v1:0': { input: 0.00025, output: 0.00125 },
'meta.llama2-70b-chat-v1': { input: 0.00195, output: 0.00256 }
};
const rates = pricing[modelId] || pricing['anthropic.claude-3-sonnet-20240229-v1:0'];
return (usage.input_tokens * rates.input + usage.output_tokens * rates.output) / 1000;
}
Other Bedrock Models
// Amazon Titan
async function bedrockTitanCompletion(prompt) {
const request = {
inputText: prompt,
textGenerationConfig: {
maxTokenCount: 1000,
temperature: 0.7,
topP: 0.9
}
};
const command = new InvokeModelCommand({
modelId: 'amazon.titan-text-express-v1',
contentType: 'application/json',
body: JSON.stringify(request),
});
const response = await bedrockClient.send(command);
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
return responseBody.results[0].outputText;
}
// Cohere on Bedrock
async function bedrockCohereCompletion(prompt) {
const request = {
prompt: prompt,
max_tokens: 1000,
temperature: 0.7,
p: 0.9
};
const command = new InvokeModelCommand({
modelId: 'cohere.command-text-v14',
contentType: 'application/json',
body: JSON.stringify(request),
});
const response = await bedrockClient.send(command);
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
return responseBody.generations[0].text;
}
Unified Provider Interface
Provider Abstraction Layer
// Unified provider interface
class UnifiedAIProvider {
constructor() {
this.providers = new Map();
this.setupProviders();
}
setupProviders() {
this.providers.set('openai', {
complete: openaiCompletion,
stream: openaiStreamingCompletion,
models: ['gpt-4', 'gpt-3.5-turbo']
});
this.providers.set('anthropic', {
complete: claudeCompletion,
stream: claudeStreaming,
models: ['claude-3-5-sonnet-20241022', 'claude-3-haiku-20240307']
});
this.providers.set('google', {
complete: geminiCompletion,
stream: null, // Gemini doesn't support streaming in this example
models: ['gemini-pro', 'gemini-pro-vision']
});
this.providers.set('azure', {
complete: azureCompletion,
stream: null,
models: ['gpt-4', 'gpt-35-turbo']
});
this.providers.set('bedrock', {
complete: bedrockClaudeCompletion,
stream: null,
models: ['anthropic.claude-3-sonnet-20240229-v1:0']
});
}
async complete(prompt, options = {}) {
const { provider = 'openai', model, stream = false } = options;
const providerConfig = this.providers.get(provider);
if (!providerConfig) {
throw new Error(`Provider ${provider} not supported`);
}
if (stream && providerConfig.stream) {
return await providerConfig.stream(prompt, model);
} else {
return await providerConfig.complete(prompt, model);
}
}
getAvailableProviders() {
return Array.from(this.providers.keys());
}
getProviderModels(provider) {
const providerConfig = this.providers.get(provider);
return providerConfig ? providerConfig.models : [];
}
}
Intelligent Provider Selection
// Smart provider selection based on requirements
class IntelligentProviderSelector {
constructor(unifiedProvider) {
this.unifiedProvider = unifiedProvider;
this.providerMetrics = new Map();
}
async selectOptimalProvider(prompt, requirements = {}) {
const {
maxCost = Infinity,
maxLatency = Infinity,
minAccuracy = 0,
preferredProviders = [],
taskType = 'general'
} = requirements;
// Provider scoring based on requirements
const scores = new Map();
for (const provider of this.unifiedProvider.getAvailableProviders()) {
const metrics = this.providerMetrics.get(provider) || this.getDefaultMetrics(provider);
let score = 0;
// Cost factor (lower cost = higher score)
if (metrics.avgCost <= maxCost) {
score += (maxCost - metrics.avgCost) / maxCost * 30;
}
// Latency factor (lower latency = higher score)
if (metrics.avgLatency <= maxLatency) {
score += (maxLatency - metrics.avgLatency) / maxLatency * 25;
}
// Accuracy factor
if (metrics.accuracy >= minAccuracy) {
score += metrics.accuracy * 25;
}
// Task-specific bonuses
score += this.getTaskSpecificScore(provider, taskType) * 15;
// Preference bonus
if (preferredProviders.includes(provider)) {
score += 5;
}
scores.set(provider, score);
}
// Return the highest scoring provider
return [...scores.entries()].sort((a, b) => b[1] - a[1])[0][0];
}
getDefaultMetrics(provider) {
const defaults = {
openai: { avgCost: 0.02, avgLatency: 1.5, accuracy: 0.85 },
anthropic: { avgCost: 0.008, avgLatency: 2.0, accuracy: 0.87 },
google: { avgCost: 0.001, avgLatency: 1.2, accuracy: 0.82 },
azure: { avgCost: 0.023, avgLatency: 1.8, accuracy: 0.85 },
bedrock: { avgCost: 0.008, avgLatency: 2.5, accuracy: 0.87 }
};
return defaults[provider] || { avgCost: 0.01, avgLatency: 2.0, accuracy: 0.8 };
}
getTaskSpecificScore(provider, taskType) {
const taskScores = {
'reasoning': { anthropic: 10, openai: 8, google: 6, azure: 8, bedrock: 9 },
'creative': { openai: 10, anthropic: 8, google: 7, azure: 10, bedrock: 8 },
'analysis': { anthropic: 10, openai: 9, google: 8, azure: 9, bedrock: 10 },
'general': { openai: 8, anthropic: 8, google: 7, azure: 8, bedrock: 8 }
};
return taskScores[taskType]?.[provider] || 5;
}
}
Error Handling and Fallbacks
Robust Error Handling
// Comprehensive error handling
class RobustAIProvider {
constructor() {
this.unifiedProvider = new UnifiedAIProvider();
this.selector = new IntelligentProviderSelector(this.unifiedProvider);
this.retryConfig = {
maxRetries: 3,
baseDelay: 1000,
maxDelay: 10000
};
}
async completeWithFallback(prompt, requirements = {}) {
const primaryProvider = await this.selector.selectOptimalProvider(prompt, requirements);
const fallbackProviders = this.getFallbackProviders(primaryProvider, requirements);
const providers = [primaryProvider, ...fallbackProviders];
for (const provider of providers) {
try {
return await this.executeWithRetry(
() => this.unifiedProvider.complete(prompt, { provider }),
provider
);
} catch (error) {
console.warn(`Provider ${provider} failed: ${error.message}`);
// If this was the last provider, throw the error
if (provider === providers[providers.length - 1]) {
throw new Error(`All providers failed. Last error: ${error.message}`);
}
// Continue to next provider
continue;
}
}
}
getFallbackProviders(primaryProvider, requirements) {
const allProviders = this.unifiedProvider.getAvailableProviders();
return allProviders
.filter(p => p !== primaryProvider)
.sort((a, b) => {
// Simple fallback ordering - prefer cheaper options
const costA = this.selector.getDefaultMetrics(a).avgCost;
const costB = this.selector.getDefaultMetrics(b).avgCost;
return costA - costB;
})
.slice(0, 2); // Limit to 2 fallback providers
}
async executeWithRetry(fn, provider) {
let lastError;
for (let attempt = 0; attempt < this.retryConfig.maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
// Don't retry on certain error types
if (this.isNonRetryableError(error)) {
throw error;
}
// Calculate delay with exponential backoff
const delay = Math.min(
this.retryConfig.baseDelay * Math.pow(2, attempt),
this.retryConfig.maxDelay
);
console.log(`Attempt ${attempt + 1} failed for ${provider}, retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
isNonRetryableError(error) {
const nonRetryableMessages = [
'invalid api key',
'insufficient credits',
'content policy violation',
'model not found'
];
return nonRetryableMessages.some(msg =>
error.message.toLowerCase().includes(msg)
);
}
}
Configuration Management
Environment-Based Configuration
// Configuration management for different environments
class AIProviderConfig {
constructor(environment = 'production') {
this.environment = environment;
this.config = this.loadConfig();
}
loadConfig() {
const baseConfig = {
openai: {
apiKey: process.env.OPENAI_API_KEY,
organization: process.env.OPENAI_ORG_ID,
timeout: 30000,
rateLimits: {
requestsPerMinute: 3500,
tokensPerMinute: 90000
}
},
anthropic: {
apiKey: process.env.ANTHROPIC_API_KEY,
timeout: 30000,
rateLimits: {
requestsPerMinute: 1000,
tokensPerMinute: 40000
}
},
google: {
apiKey: process.env.GOOGLE_AI_API_KEY,
timeout: 30000,
rateLimits: {
requestsPerMinute: 60,
tokensPerMinute: 32000
}
},
azure: {
apiKey: process.env.AZURE_OPENAI_API_KEY,
resourceName: process.env.AZURE_OPENAI_RESOURCE_NAME,
deploymentName: process.env.AZURE_OPENAI_DEPLOYMENT_NAME,
apiVersion: '2024-02-15-preview',
timeout: 30000
},
bedrock: {
region: process.env.AWS_REGION || 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
timeout: 30000
}
};
// Environment-specific overrides
if (this.environment === 'development') {
baseConfig.openai.rateLimits.requestsPerMinute = 100;
baseConfig.anthropic.rateLimits.requestsPerMinute = 50;
}
return baseConfig;
}
getProviderConfig(provider) {
return this.config[provider];
}
validateConfig() {
const requiredEnvVars = {
openai: ['OPENAI_API_KEY'],
anthropic: ['ANTHROPIC_API_KEY'],
google: ['GOOGLE_AI_API_KEY'],
azure: ['AZURE_OPENAI_API_KEY', 'AZURE_OPENAI_RESOURCE_NAME'],
bedrock: ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY']
};
const missingVars = [];
for (const [provider, vars] of Object.entries(requiredEnvVars)) {
for (const varName of vars) {
if (!process.env[varName]) {
missingVars.push(`${provider}: ${varName}`);
}
}
}
if (missingVars.length > 0) {
throw new Error(`Missing environment variables: ${missingVars.join(', ')}`);
}
}
}
Usage Examples
Complete Integration Example
// Complete example using all providers
async function demonstrateMultiProviderIntegration() {
// Initialize configuration
const config = new AIProviderConfig('production');
config.validateConfig();
// Initialize robust provider
const aiProvider = new RobustAIProvider();
// Example 1: Simple completion with automatic provider selection
try {
const result = await aiProvider.completeWithFallback(
"Explain quantum computing in simple terms",
{
maxCost: 0.05,
maxLatency: 3000,
taskType: 'general'
}
);
console.log('Response:', result.text);
console.log('Cost:', result.cost);
} catch (error) {
console.error('All providers failed:', error.message);
}
// Example 2: Provider-specific usage
const providers = ['openai', 'anthropic', 'google'];
for (const provider of providers) {
try {
const result = await aiProvider.unifiedProvider.complete(
"What are the benefits of renewable energy?",
{ provider, model: 'default' }
);
console.log(`${provider} response:`, result.text.substring(0, 100) + '...');
} catch (error) {
console.error(`${provider} failed:`, error.message);
}
}
}
// Run the demonstration
demonstrateMultiProviderIntegration();
:::warning Security Note Never commit API keys to version control. Use environment variables or secure configuration management systems for all credentials. :::
Best Practices
Security Best Practices
-
API Key Management
- Use environment variables for all API keys
- Rotate keys regularly
- Implement key-specific rate limiting
- Monitor key usage for anomalies
-
Error Handling
- Implement comprehensive retry logic
- Use exponential backoff for rate limit errors
- Log errors without exposing sensitive data
- Provide meaningful error messages to users
-
Cost Management
- Implement spending alerts and limits
- Monitor usage patterns across providers
- Use cheaper models for non-critical tasks
- Cache responses when appropriate
-
Performance Optimization
- Implement connection pooling
- Use appropriate timeouts
- Monitor latency across providers
- Implement circuit breakers for failing providers
Conclusion
Integrating multiple AI providers requires careful planning and robust implementation. By using the patterns and code examples in this guide, you can build a resilient, cost-effective, and high-performance AI integration that leverages the best features of each provider.
Start with a single provider integration, then gradually add others using the unified interface pattern. Always implement proper error handling and fallback strategies to ensure your application remains reliable even when individual providers experience issues.
Remember to monitor your usage patterns and costs across all providers to optimize your AI spending while maintaining the quality and performance your users expect.