Simple AI Provider

A professional, extensible TypeScript package for integrating multiple AI providers into your applications with a unified interface. Currently supports Claude (Anthropic) and OpenAI (GPT) with plans to add more providers.

Features

  • 🎯 Unified Interface: Same API across all AI providers
  • 🔒 Type-Safe: Full TypeScript support with comprehensive type definitions
  • 🚀 Easy to Use: Simple factory functions and intuitive configuration
  • 📡 Streaming Support: Real-time streaming responses where supported
  • 🛡️ Error Handling: Robust error handling with categorized error types
  • 🔧 Extensible: Easy to add new AI providers
  • 📦 Modern: Built with ES modules and modern JavaScript features
  • 🌐 Multi-Provider: Switch between Claude and OpenAI seamlessly

Installation

npm install simple-ai-provider
# or
yarn add simple-ai-provider
# or
bun add simple-ai-provider

Quick Start

Basic Usage with Claude

import { createClaudeProvider } from 'simple-ai-provider';

// Create a Claude provider
const claude = createClaudeProvider('your-anthropic-api-key');

// Initialize the provider
await claude.initialize();

// Generate a completion
const response = await claude.complete({
  messages: [
    { role: 'user', content: 'Hello! How are you today?' }
  ],
  maxTokens: 100,
  temperature: 0.7
});

console.log(response.content);

Basic Usage with OpenAI

import { createOpenAIProvider } from 'simple-ai-provider';

// Create an OpenAI provider
const openai = createOpenAIProvider('your-openai-api-key');

// Initialize the provider
await openai.initialize();

// Generate a completion
const response = await openai.complete({
  messages: [
    { role: 'user', content: 'Hello! How are you today?' }
  ],
  maxTokens: 100,
  temperature: 0.7
});

console.log(response.content);

Multi-Provider Usage

import { createProvider, createClaudeProvider, createOpenAIProvider } from 'simple-ai-provider';

// Method 1: Using specific factory functions
const claude = createClaudeProvider('your-anthropic-api-key');
const openai = createOpenAIProvider('your-openai-api-key');

// Method 2: Using generic factory
const claude2 = createProvider('claude', { apiKey: 'your-anthropic-api-key' });
const openai2 = createProvider('openai', { apiKey: 'your-openai-api-key' });

// Initialize both
await Promise.all([claude.initialize(), openai.initialize()]);

// Use the same interface for both providers
const prompt = { messages: [{ role: 'user', content: 'Explain AI' }] };

const claudeResponse = await claude.complete(prompt);
const openaiResponse = await openai.complete(prompt);

Streaming Responses

import { createOpenAIProvider } from 'simple-ai-provider';

const openai = createOpenAIProvider('your-openai-api-key');
await openai.initialize();

// Stream a completion
for await (const chunk of openai.stream({
  messages: [
    { role: 'user', content: 'Write a short story about a robot.' }
  ],
  maxTokens: 500
})) {
  if (!chunk.isComplete) {
    process.stdout.write(chunk.content);
  } else {
    console.log('\n\nUsage:', chunk.usage);
  }
}

Advanced Configuration

import { ClaudeProvider, OpenAIProvider } from 'simple-ai-provider';

// Claude with custom configuration
const claude = new ClaudeProvider({
  apiKey: 'your-anthropic-api-key',
  defaultModel: 'claude-3-5-sonnet-20241022',
  timeout: 30000,
  maxRetries: 3,
  baseUrl: 'https://api.anthropic.com' // optional custom endpoint
});

// OpenAI with organization and project
const openai = new OpenAIProvider({
  apiKey: 'your-openai-api-key',
  defaultModel: 'gpt-4',
  organization: 'org-your-org-id',
  project: 'proj-your-project-id',
  timeout: 60000,
  maxRetries: 5
});

await Promise.all([claude.initialize(), openai.initialize()]);

const response = await openai.complete({
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'Explain quantum computing in simple terms.' }
  ],
  model: 'gpt-4-turbo',
  maxTokens: 300,
  temperature: 0.5,
  topP: 0.9,
  stopSequences: ['\n\n']
});

API Reference

Core Types

AIMessage

interface AIMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
  metadata?: Record<string, any>;
}

CompletionParams

interface CompletionParams {
  messages: AIMessage[];
  model?: string;
  maxTokens?: number;
  temperature?: number;
  topP?: number;
  stopSequences?: string[];
  stream?: boolean;
}

CompletionResponse

interface CompletionResponse {
  content: string;
  model: string;
  usage: TokenUsage;
  id: string;
  metadata?: Record<string, any>;
}

Factory Functions

createClaudeProvider(apiKey, options?)

Creates a Claude provider with simplified configuration.

const claude = createClaudeProvider('your-api-key', {
  defaultModel: 'claude-3-5-sonnet-20241022',
  timeout: 30000
});

createOpenAIProvider(apiKey, options?)

Creates an OpenAI provider with simplified configuration.

const openai = createOpenAIProvider('your-api-key', {
  defaultModel: 'gpt-4',
  organization: 'org-123',
  timeout: 60000
});

createProvider(type, config)

Generic factory function for creating any provider type.

const claude = createProvider('claude', {
  apiKey: 'your-api-key',
  defaultModel: 'claude-3-5-sonnet-20241022'
});

const openai = createProvider('openai', {
  apiKey: 'your-api-key',
  defaultModel: 'gpt-4'
});

Provider Methods

initialize(): Promise<void>

Initializes the provider and validates the configuration.

complete(params): Promise<CompletionResponse>

Generates a completion based on the provided parameters.

stream(params): AsyncIterable<CompletionChunk>

Generates a streaming completion.

getInfo(): ProviderInfo

Returns information about the provider and its capabilities.

isInitialized(): boolean

Checks if the provider has been initialized.

Error Handling

The package provides comprehensive error handling with categorized error types:

import { AIProviderError, AIErrorType } from 'simple-ai-provider';

try {
  const response = await openai.complete({
    messages: [{ role: 'user', content: 'Hello!' }]
  });
} catch (error) {
  if (error instanceof AIProviderError) {
    switch (error.type) {
      case AIErrorType.AUTHENTICATION:
        console.error('Invalid API key');
        break;
      case AIErrorType.RATE_LIMIT:
        console.error('Rate limit exceeded');
        break;
      case AIErrorType.INVALID_REQUEST:
        console.error('Invalid request parameters');
        break;
      default:
        console.error('Unknown error:', error.message);
    }
  }
}

Supported Models

Claude (Anthropic)

  • claude-3-5-sonnet-20241022 (default)
  • claude-3-5-haiku-20241022
  • claude-3-opus-20240229
  • claude-3-sonnet-20240229
  • claude-3-haiku-20240307

OpenAI (GPT)

  • gpt-4 (default)
  • gpt-4-turbo
  • gpt-4-turbo-preview
  • gpt-4-0125-preview
  • gpt-4-1106-preview
  • gpt-3.5-turbo
  • gpt-3.5-turbo-0125
  • gpt-3.5-turbo-1106

Environment Variables

You can set your API keys as environment variables:

export ANTHROPIC_API_KEY="your-anthropic-api-key"
export OPENAI_API_KEY="your-openai-api-key"
const claude = createClaudeProvider(process.env.ANTHROPIC_API_KEY!);
const openai = createOpenAIProvider(process.env.OPENAI_API_KEY!);

Provider Comparison

Feature Claude OpenAI
Models 5 models 8+ models
Max Context 200K tokens 128K tokens
Streaming
Vision
Function Calling
JSON Mode
System Messages (separate) (inline)

Best Practices

  1. Always initialize providers before using them
  2. Handle errors gracefully with proper error types
  3. Use appropriate models for your use case (speed vs. capability)
  4. Set reasonable timeouts for your application
  5. Implement retry logic for production applications
  6. Monitor token usage to control costs
  7. Use environment variables for API keys
  8. Consider provider-specific features when choosing

Advanced Usage

Provider Registry

import { ProviderRegistry } from 'simple-ai-provider';

// List all registered providers
console.log(ProviderRegistry.getRegisteredProviders()); // ['claude', 'openai']

// Create provider by name
const provider = ProviderRegistry.create('openai', {
  apiKey: 'your-api-key'
});

// Check if provider is registered
if (ProviderRegistry.isRegistered('claude')) {
  console.log('Claude is available!');
}

Custom Error Handling

function handleAIError(error: unknown, providerName: string) {
  if (error instanceof AIProviderError) {
    console.error(`${providerName} Error (${error.type}):`, error.message);
    
    if (error.statusCode) {
      console.error('HTTP Status:', error.statusCode);
    }
    
    if (error.originalError) {
      console.error('Original Error:', error.originalError.message);
    }
  }
}

Extending the Package

To add a new AI provider, extend the BaseAIProvider class:

import { BaseAIProvider } from 'simple-ai-provider';

class MyCustomProvider extends BaseAIProvider {
  protected async doInitialize(): Promise<void> {
    // Initialize your provider
  }

  protected async doComplete(params: CompletionParams): Promise<CompletionResponse> {
    // Implement completion logic
  }

  protected async *doStream(params: CompletionParams): AsyncIterable<CompletionChunk> {
    // Implement streaming logic
  }

  public getInfo(): ProviderInfo {
    return {
      name: 'MyCustomProvider',
      version: '1.0.0',
      models: ['my-model'],
      maxContextLength: 4096,
      supportsStreaming: true
    };
  }
}

// Register your provider
ProviderRegistry.register('mycustom', MyCustomProvider);

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

MIT

Changelog

1.0.0

  • Initial release
  • Claude provider implementation
  • OpenAI provider implementation
  • Streaming support for both providers
  • Comprehensive error handling
  • TypeScript support
  • Provider registry system
  • Multi-provider examples
Description
No description provided
Readme MIT 159 KiB
Languages
TypeScript 100%