UNPKG

@catalystlabs/tryai

Version:

Dead simple AI library. One line setup. Zero config. Just works.

434 lines (325 loc) 11.8 kB
# TryAI Dead simple AI library. One line setup. Zero config. Just works. **Built on battle-tested providers from production systems.** > ⚠️ **Important**: Semantic caching requires deploying your own Modal embedding service. Without it, the library still works perfectly with exact-match caching. See [Configuration](#configuration) for details. ```typescript import { ai } from '@catalystlabs/tryai'; const response = await ai('Hello world'); console.log(response.content); ``` That's it. You're using AI. ## Install ```bash npm install @catalystlabs/tryai # Run the setup wizard to configure your environment npx @catalystlabs/tryai setup ``` ## Features - **Zero Config** - Just works with environment variables - **Simple** - One function to rule them all - **Providers** - OpenAI, Anthropic, Llama 4.0, LM Studio (local) - **Conversation Management** - Built-in state management with @xstate/store - **Prompt Templates** - TOML-based, simple variable replacement - **Pipelines** - Chain prompts together with context - **De-identification** - Remove PII automatically - **Streaming** - Built-in streaming support - **TypeScript** - Full type safety - **Intelligent Routing** - Automatic model selection based on task complexity ## Quick Start ### Simplest Usage ```typescript import { ai } from '@catalystlabs/tryai'; // Just works (uses OPENAI_API_KEY from env) const response = await ai('What is 2+2?'); console.log(response.content); // "4" ``` ### Streaming ```typescript for await (const chunk of ai.stream('Tell me a story')) { process.stdout.write(chunk.content); } ``` ### Different Models ```typescript // Use GPT-4 await ai.model('gpt-4').send('Complex question here'); // Use GPT-3.5 (cheaper) await ai.model('gpt-3.5-turbo').send('Simple question'); // Use Claude import { providers } from '@catalystlabs/tryai'; const claude = providers.claude(); await claude.send('Hello Claude!'); ``` ## Prompt Templates ### Define in Code ```typescript import { definePrompts, prompt } from '@catalystlabs/tryai'; definePrompts({ greeting: 'Say hello to {{name}} in {{language}}', summarize: { prompt: 'Summarize in {{words}} words: {{text}}', options: { temperature: 0.3 } } }); // Use them const response = await prompt('greeting', { name: 'Alice', language: 'Spanish' }); ``` ### Or Use TOML Files Create `prompts.toml`: ```toml greeting = "Say hello to {{name}} in {{language}}" [summarize] prompt = "Summarize in {{words}} words: {{text}}" options = { temperature = 0.3 } ``` Then: ```typescript import { prompt } from '@catalystlabs/tryai'; const response = await prompt('greeting', { name: 'Alice', language: 'Spanish' }); ``` ## Conversations Built-in conversation state management: ```typescript import { forge } from '@catalystlabs/tryai'; const ai = forge(); // Simple chat - conversation managed automatically const response1 = await ai.chat('What is 2+2?'); const response2 = await ai.chat('What was my previous question?'); // AI remembers: "Your previous question was 'What is 2+2?'" // Streaming with conversation context for await (const chunk of ai.chatStream('Tell me a story')) { process.stdout.write(chunk.content); } // Access conversation methods ai.conversation.addSystemMessage('You are a helpful pirate'); ai.conversation.getMessages(); // Get all messages ai.conversation.getMessageCount(); // Count messages ai.conversation.clear(); // Clear messages ai.conversation.end(); // End conversation // Export/Import conversations const data = ai.conversation.export(); // ... save to database ... ai.conversation.import(data); // Subscribe to changes ai.conversation.subscribe((snapshot) => { console.log('Messages:', snapshot.context.messages); }); ``` ### Conversation API ```typescript // Message Management ai.conversation.start(id?: string); // Start new conversation ai.conversation.addUserMessage(content: string); // Add user message ai.conversation.addSystemMessage(content: string); // Add system message ai.conversation.addAIResponse(response, time?); // Add AI response // State Access ai.conversation.getMessages(); // All messages ai.conversation.getMessagesForAPI(includeSystem?); // API-ready format ai.conversation.getLastMessage(); // Most recent message ai.conversation.getUserMessages(); // User messages only ai.conversation.getAssistantMessages(); // AI messages only ai.conversation.getId(); // Conversation ID ai.conversation.getMessageCount(); // Total messages ai.conversation.hasConversation(); // Check if active // State Management ai.conversation.clear(); // Clear all messages ai.conversation.end(); // End conversation ai.conversation.updateSettings(settings); // Update settings ai.conversation.setError(error); // Set error state ai.conversation.clearError(); // Clear error // Metadata & Settings ai.conversation.getSettings(); // Get settings ai.conversation.getMetadata(); // Get metadata ai.conversation.isLoading(); // Check loading state ai.conversation.getError(); // Get current error // Import/Export ai.conversation.export(); // Export to JSON ai.conversation.import(data); // Import from JSON // Subscriptions ai.conversation.subscribe(callback); // Subscribe to changes ai.conversation.destroy(); // Cleanup subscriptions ``` ## Pipelines Advanced prompt chaining with context: ```typescript import { createPipeline } from '@catalystlabs/tryai'; const pipeline = createPipeline(ai) .prompt('List 3 random animals') .iterate(3, 'Tell me about {{previous}}') .transform((response, context) => response.toUpperCase()) .accumulate('results') .run(); ``` ## De-identification Automatically remove PII: ```typescript import { deidentify } from '@catalystlabs/tryai'; const response = await deidentify.ai( 'Email john@example.com at 555-1234', { keepMapping: true } ); // PII is removed before sending to AI // and restored in the response ``` ## Configuration ### Environment Variables ```bash # AI Provider Keys (at least one required) OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-... # Modal Embedding Service (OPTIONAL - for semantic caching) # Users must deploy their own Modal service! # See: https://git.catalystlab.cc/catalyst/tryai/tree/main/modal_services MODAL_EMBEDDING_ENDPOINT=https://your-modal-app.modal.run ``` ### Manual Setup ```typescript import { forge } from '@catalystlabs/tryai'; const ai = forge({ provider: 'openai', apiKey: 'sk-...', model: 'gpt-4', temperature: 0.7 }); ``` ### Pre-configured Providers ```typescript import { providers } from '@catalystlabs/tryai'; const gpt4 = providers.openai(); // GPT-4 const gpt35 = providers.gpt35(); // GPT-3.5-turbo const claude = providers.claude(); // Claude Opus const sonnet = providers.sonnet(); // Claude Sonnet (faster) const llama4 = providers.llama4(); // Llama 4.0 405B const llama70b = providers.llama4_70b(); // Llama 4.0 70B const vision = providers.llama_vision(); // Llama Vision const local = providers.local(); // LM Studio local models ``` ## API ### Core Functions - `ai(message, options?)` - Send a message - `ai.stream(message, options?)` - Stream a response - `ai.model(name)` - Use a different model ### Prompt Functions - `prompt(name, variables?, options?)` - Use a template - `definePrompts(templates)` - Define templates in code - `loadPrompts(path)` - Load TOML file ### Chain Functions - `chain()` - Start a chain - `.step(message, options?)` - Add a step - `.prompt(name, variables?)` - Use template in chain - `.run()` - Execute the chain ### De-identification - `deidentify(text, options?)` - Remove PII - `deidentify.ai(message, options?)` - AI call with PII removal - `reidentify(text)` - Restore PII - `clearMappings()` - Clear stored mappings ## Examples Check out the `/examples` folder for more: - `simple.ts` - All features demonstrated - `chatbot.ts` - Simple chatbot - `pipeline.ts` - Complex processing pipeline ## Philosophy AI should be simple. This library is intentionally minimal. No complex abstractions. No enterprise patterns. No bullshit. Just simple functions that work. ## Advanced Features While the API is simple, the underlying providers are battle-tested and support all advanced features: ### Full Message Control ```typescript // Pass complete message arrays const response = await ai([ { role: 'system', content: 'You are a helpful assistant' }, { role: 'user', content: 'Hello' } ]); ``` ### All Provider Options ```typescript // OpenAI with all parameters await ai('Generate text', { model: 'gpt-4', temperature: 0.9, maxTokens: 100, topP: 0.95, frequencyPenalty: 0.5, presencePenalty: 0.5, stop: ['\n\n'], responseFormat: { type: 'json_object' } }); // Anthropic with specific options await ai('Generate text', { model: 'claude-3-opus-20240229', temperature: 0.7, topK: 40, stopSequences: ['\n\n'] }); ``` ### Streaming with Proper Chunks ```typescript for await (const chunk of ai.stream('Tell a story')) { if (chunk.content) process.stdout.write(chunk.content); if (chunk.usage) console.log('Tokens:', chunk.usage); } ``` See `/examples/advanced.ts` for more. ### Intelligent Routing Mode Use LLMRouter for automatic model selection based on task complexity and priority: ```typescript // Zero config - just set LLMROUTER_URL in .env const response = await ai.routed("Explain quantum computing"); console.log(response.text); console.log(response.metadata.selectedModel); // "gpt-4" or "gpt-3.5-turbo" etc. console.log(response.metadata.cost); // 0.0023 // Submit feedback to improve routing await response.submitFeedback({ helpful: true, rating: 5, comment: "Perfect explanation" }); ``` #### Priority Modes Control the quality/cost tradeoff: ```typescript // Highest quality, regardless of cost const premium = await ai.routed("Complex medical diagnosis", { priority: "quality_first" }); // Balance quality and cost (default) const balanced = await ai.routed("Summarize this article", { priority: "balanced" }); // Minimize cost, accept lower quality const budget = await ai.routed("Simple question", { priority: "aggressive_cost" }); ``` #### Configuration ```env # Required LLMROUTER_URL=http://localhost:8000 # Optional LLMROUTER_API_KEY=your-key ``` The router analyzes your prompt across 7 dimensions (creativity, reasoning, etc.) and selects the optimal model based on your priority mode. It includes semantic caching for 70%+ cost savings on similar queries. ## v0.3.0 Release Notes ### Major Improvements - 🔒 **Enhanced Security** - Path validation prevents directory traversal attacks - 🎯 **Improved Type Safety** - Replaced most `any` types with proper TypeScript interfaces - 💾 **Better Resource Management** - Added `close()` methods for proper cleanup - 🚀 **Truly Optional Features** - All features (cache, safety, analytics) work independently - 🛡️ **Production-Ready Error Handling** - Consistent error messages with better context - 🔧 **No Breaking Changes** - Existing code continues to work ### Resource Cleanup (New Feature) ```typescript import { forge } from '@catalystlabs/tryai'; const ai = forge(); // ... use AI ... await ai.close(); // Clean up all resources ``` ## License MIT