pulse-ai-utils
Version:
Utility functions and helpers for AI-powered applications
247 lines (179 loc) • 8.3 kB
Markdown
# Pulse AI Utils
A powerful TypeScript library for AI-powered applications with multi-provider LLM support. Provides unified interfaces for OpenAI, Gemini, Claude, and 100+ models via OpenRouter.
## ✨ Features
- 🤖 **Multi-Provider Support**: OpenAI, Gemini, Claude, and 100+ models
- 🔄 **Unified Interface**: Same API for all providers
- 🔑 **BYOK Support**: Bring Your Own Key for provider-specific APIs
- 📊 **Structured Data**: Built-in Zod schema validation
- 🌐 **Web Search**: AI-powered web queries with caching
- 🎯 **Type-Safe**: Full TypeScript support with proper types
## Installation
```bash
npm install pulse-ai-utils
```
## 🚀 Quick Start
```typescript
import { OpenAIHelper, OpenRouter } from 'pulse-ai-utils';
// Auto-loads API keys from your .env file
const openai = new OpenAIHelper(); // Uses OPENAI_API_KEY from .env
// Auto-loads keys for different providers
const gemini = OpenRouter.forGemini(); // Uses OPENROUTER_API_KEY + GEMINI_API_KEY from .env
const claude = OpenRouter.forClaude(); // Uses OPENROUTER_API_KEY + CLAUDE_API_KEY from .env
// Use remote config for dynamic model selection (recommended)
const smartOpenai = await OpenAIHelper.createWithRemoteConfig();
const smartGemini = await OpenRouter.forGeminiWithRemoteConfig();
const webOptimized = await OpenRouter.createForWebFetching();
// Or pass keys explicitly if needed
const customOpenai = new OpenAIHelper('your-openai-key');
const customGemini = OpenRouter.forGemini('openrouter-key', 'gemini-key');
```
### Environment Configuration
The library automatically reads API keys from your project's root `.env` file. Simply create a `.env` file in your project root:
```bash
# .env file in your project root
OPENAI_API_KEY=your-openai-key
OPENROUTER_API_KEY=your-openrouter-key
GEMINI_API_KEY=your-gemini-key
CLAUDE_API_KEY=your-claude-key
```
**No need to call `dotenv.config()`** - the library handles this automatically!
### Remote Configuration (Firebase Remote Config)
The library also supports dynamic model selection via Firebase Remote Config. This allows you to change models without code deployments:
```bash
# Firebase Remote Config Parameters (optional)
pulse-ai-util-openai-model=gpt-4o # OpenAI model selection
pulse-ai-util-openrouter-model=google/gemini-2.0-flash-exp # OpenRouter model
pulse-ai-util-gemini-model=google/gemini-2.0-flash-exp # Gemini-specific model
pulse-ai-web-openrouter-model=claude-3-5-sonnet-20241022 # Optimized for web fetching
```
These remote config values take precedence over environment variables, providing dynamic configuration capabilities.
#### Required Environment Variables
At least one of these is required:
```bash
OPENAI_API_KEY=your-openai-key # For direct OpenAI access
OPENROUTER_API_KEY=your-openrouter-key # For multi-provider access via OpenRouter
```
#### Optional Environment Variables
```bash
# Provider-specific keys for BYOK (Bring Your Own Key)
GEMINI_API_KEY=your-gemini-key # Google AI Studio key
CLAUDE_API_KEY=your-claude-key # Anthropic Claude key
# Model Selection (optional - smart defaults provided)
OPENROUTER_MODEL=google/gemini-2.0-flash-exp # Default OpenRouter model
GEMINI_MODEL=google/gemini-2.0-flash-exp # Default Gemini model
# Optional Configuration
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1 # Custom OpenRouter URL
LLM_CACHE_DB_ID=llmCache # Firestore cache collection
```
## Usage
### LLMQueryHandler
Fetch arbitrary structured data using web search.
```typescript
import { LLMQueryHandler } from 'pulse-ai-utils';
const queryHandler = new LLMQueryHandler('your-api-key');
// Use in an Express route
app.post('/llm-query', (req, res) => queryHandler.query(req, res));
```
## 🤖 LLM Providers
### OpenAI Helper - Direct OpenAI API
```typescript
import { OpenAIHelper } from 'pulse-ai-utils';
// Auto-loads from OPENAI_API_KEY env var, or pass explicitly
const openai = new OpenAIHelper(undefined, undefined, 'gpt-4o');
// Or with explicit key: new OpenAIHelper('your-api-key', undefined, 'gpt-4o');
// 🌟 Recommended: Use remote config for dynamic model selection
const smartOpenai = await OpenAIHelper.createWithRemoteConfig();
// Update model from remote config for long-running processes
await openai.updateModelFromRemoteConfig();
// Fetch structured data from the web
const result = await openai.fetchStructuredDataFromWeb({
prompt: 'Find upcoming tech events in San Francisco',
zodSchema: yourZodSchema,
userLocation: {
type: 'approximate',
country: 'US',
region: 'CA',
city: 'San Francisco'
},
locationGranularity: 'city',
});
// Get available OpenAI models
const models = await openai.getAvailableModels();
// Returns: ['gpt-4o', 'gpt-4', 'gpt-3.5-turbo', ...]
```
### OpenRouter - Universal Multi-Provider Access
Access 100+ models from multiple providers through a unified interface:
```typescript
import { OpenRouter } from 'pulse-ai-utils';
// Auto-loads from environment variables (.env file)
const router = new OpenRouter();
// Factory methods auto-load from .env - no keys needed!
const gemini = OpenRouter.forGemini(); // Uses OPENROUTER_API_KEY + GEMINI_API_KEY
const claude = OpenRouter.forClaude(); // Uses OPENROUTER_API_KEY + CLAUDE_API_KEY
const gpt = OpenRouter.forGPT(); // Uses OPENROUTER_API_KEY
// 🌟 Recommended: Use remote config for dynamic model selection
const smartRouter = await OpenRouter.createWithRemoteConfig();
const smartGemini = await OpenRouter.forGeminiWithRemoteConfig();
const webOptimized = await OpenRouter.createForWebFetching(); // Uses pulse-ai-web-openrouter-model
// Update model from remote config for long-running processes
await router.updateModelFromRemoteConfig();
await router.updateModelFromRemoteConfig(true); // Use web-optimized model
// Or pass keys explicitly if needed
const customGemini = OpenRouter.forGemini('openrouter-key', 'gemini-key');
const customClaude = OpenRouter.forClaude('openrouter-key', 'claude-key');
// Get available models with provider info
const models = await router.getAvailableModels();
// Returns: [
// { id: 'google/gemini-2.0-flash-exp', name: 'Gemini 2.0 Flash', provider: 'Google' },
// { id: 'anthropic/claude-3.5-sonnet', name: 'Claude 3.5 Sonnet', provider: 'Anthropic' },
// ...
// ]
```
### Model Selection Guide
```typescript
// 🌟 Best: Remote config with dynamic model selection (recommended)
const smartOpenai = await OpenAIHelper.createWithRemoteConfig();
const smartGemini = await OpenRouter.forGeminiWithRemoteConfig();
const webOptimized = await OpenRouter.createForWebFetching(); // Special web-optimized model
// ✅ Good: Environment variables (auto-loads from .env)
const openai = new OpenAIHelper();
const gemini = OpenRouter.forGemini();
const claude = OpenRouter.forClaude();
// ✅ Fallback: Explicit configuration
const customGemini = OpenRouter.forGemini(undefined, undefined, 'google/gemini-2.0-flash-exp');
const customClaude = OpenRouter.forClaude(undefined, undefined, 'anthropic/claude-3.5-sonnet');
```
### Remote Config Priority Order
1. **Firebase Remote Config** (highest priority) - `pulse-ai-util-*-model`
2. **Environment Variables** (.env file) - `OPENAI_MODEL`, `OPENROUTER_MODEL`, etc.
3. **Default Values** (fallback) - `gpt-4o`, `google/gemini-2.0-flash-exp`, etc.
### Utility Functions
```typescript
import {
getSchemaByCategory,
sanitizeId,
zodToJsonSchema
} from 'pulse-ai-utils';
// Get schema for a category
const schema = getSchemaByCategory('events');
// Sanitize an ID
const cleanId = sanitizeId('https://example.com/path/');
// Result: 'example.com-path'
// Convert Zod schema to JSON schema
const jsonSchema = zodToJsonSchema(myZodSchema);
```
## License
0BSD
## Versioning and Publishing
To release a new version of this package:
1. Open `package.json` in this directory and update the `version` field to the desired version tag (for example, `"3.4.1"`).
2. In your terminal, ensure you're in this directory:
```bash
cd lib
```
3. Build and publish to npm:
```bash
npm run build
npm publish
```
Your new version will be published under the `latest` tag on npm.