|
| 1 | +# @objectstack/service-ai |
| 2 | + |
| 3 | +AI Service for ObjectStack — implements `IAIService` with LLM adapter layer, conversation management, tool registry, and REST/SSE routes. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- **Multi-Provider LLM Support**: Supports OpenAI, Anthropic, Google, and custom gateway providers via Vercel AI SDK |
| 8 | +- **Conversation Management**: Track and manage AI conversations with full history |
| 9 | +- **Tool Registry**: Register and execute tools that AI agents can call |
| 10 | +- **Streaming Support**: Real-time streaming responses via Server-Sent Events (SSE) |
| 11 | +- **REST API**: Auto-generated endpoints for AI operations |
| 12 | +- **Type-Safe**: Full TypeScript support with type inference |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +```bash |
| 17 | +pnpm add @objectstack/service-ai |
| 18 | +``` |
| 19 | + |
| 20 | +### Peer Dependencies |
| 21 | + |
| 22 | +Install the LLM provider(s) you need: |
| 23 | + |
| 24 | +```bash |
| 25 | +# OpenAI |
| 26 | +pnpm add @ai-sdk/openai |
| 27 | + |
| 28 | +# Anthropic (Claude) |
| 29 | +pnpm add @ai-sdk/anthropic |
| 30 | + |
| 31 | +# Google (Gemini) |
| 32 | +pnpm add @ai-sdk/google |
| 33 | + |
| 34 | +# Custom Gateway |
| 35 | +pnpm add @ai-sdk/gateway |
| 36 | +``` |
| 37 | + |
| 38 | +All peer dependencies are optional — install only what you need. |
| 39 | + |
| 40 | +## Basic Usage |
| 41 | + |
| 42 | +```typescript |
| 43 | +import { defineStack } from '@objectstack/spec'; |
| 44 | +import { ServiceAI } from '@objectstack/service-ai'; |
| 45 | +import { openai } from '@ai-sdk/openai'; |
| 46 | + |
| 47 | +const stack = defineStack({ |
| 48 | + services: [ |
| 49 | + ServiceAI.configure({ |
| 50 | + models: { |
| 51 | + default: openai('gpt-4'), |
| 52 | + fast: openai('gpt-3.5-turbo'), |
| 53 | + }, |
| 54 | + }), |
| 55 | + ], |
| 56 | +}); |
| 57 | +``` |
| 58 | + |
| 59 | +## Configuration |
| 60 | + |
| 61 | +```typescript |
| 62 | +interface AIServiceConfig { |
| 63 | + /** Map of model IDs to AI SDK model instances */ |
| 64 | + models: Record<string, LanguageModel>; |
| 65 | + |
| 66 | + /** Default model to use when not specified */ |
| 67 | + defaultModel?: string; |
| 68 | + |
| 69 | + /** Maximum conversation history length */ |
| 70 | + maxHistoryLength?: number; |
| 71 | + |
| 72 | + /** Enable streaming responses (default: true) */ |
| 73 | + enableStreaming?: boolean; |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +## Service API |
| 78 | + |
| 79 | +The `IAIService` interface provides: |
| 80 | + |
| 81 | +### Conversation Management |
| 82 | + |
| 83 | +```typescript |
| 84 | +// Get AI service from kernel |
| 85 | +const ai = kernel.getService<IAIService>('ai'); |
| 86 | + |
| 87 | +// Create a new conversation |
| 88 | +const conversation = await ai.createConversation({ |
| 89 | + model: 'default', |
| 90 | + systemPrompt: 'You are a helpful assistant.', |
| 91 | +}); |
| 92 | + |
| 93 | +// Send a message |
| 94 | +const response = await ai.sendMessage({ |
| 95 | + conversationId: conversation.id, |
| 96 | + message: 'What is ObjectStack?', |
| 97 | +}); |
| 98 | + |
| 99 | +// Stream a message |
| 100 | +const stream = await ai.streamMessage({ |
| 101 | + conversationId: conversation.id, |
| 102 | + message: 'Explain in detail...', |
| 103 | +}); |
| 104 | + |
| 105 | +for await (const chunk of stream) { |
| 106 | + process.stdout.write(chunk.text); |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +### Tool Registry |
| 111 | + |
| 112 | +```typescript |
| 113 | +// Register a tool |
| 114 | +ai.registerTool({ |
| 115 | + name: 'get_weather', |
| 116 | + description: 'Get current weather for a location', |
| 117 | + parameters: { |
| 118 | + type: 'object', |
| 119 | + properties: { |
| 120 | + location: { type: 'string', description: 'City name' }, |
| 121 | + }, |
| 122 | + required: ['location'], |
| 123 | + }, |
| 124 | + execute: async ({ location }) => { |
| 125 | + // Your tool implementation |
| 126 | + return { temperature: 72, condition: 'sunny' }; |
| 127 | + }, |
| 128 | +}); |
| 129 | + |
| 130 | +// Tools are automatically available to AI agents |
| 131 | +const response = await ai.sendMessage({ |
| 132 | + conversationId: conversation.id, |
| 133 | + message: 'What is the weather in San Francisco?', |
| 134 | +}); |
| 135 | +``` |
| 136 | + |
| 137 | +## REST API Endpoints |
| 138 | + |
| 139 | +When used with `@objectstack/rest`, the following endpoints are auto-generated: |
| 140 | + |
| 141 | +``` |
| 142 | +POST /api/v1/ai/conversations # Create conversation |
| 143 | +GET /api/v1/ai/conversations/:id # Get conversation |
| 144 | +POST /api/v1/ai/conversations/:id/messages # Send message |
| 145 | +GET /api/v1/ai/conversations/:id/stream # Stream response (SSE) |
| 146 | +GET /api/v1/ai/tools # List available tools |
| 147 | +POST /api/v1/ai/tools/:name/execute # Execute a tool |
| 148 | +``` |
| 149 | + |
| 150 | +## Multi-Model Configuration |
| 151 | + |
| 152 | +```typescript |
| 153 | +import { openai } from '@ai-sdk/openai'; |
| 154 | +import { anthropic } from '@ai-sdk/anthropic'; |
| 155 | +import { google } from '@ai-sdk/google'; |
| 156 | + |
| 157 | +const stack = defineStack({ |
| 158 | + services: [ |
| 159 | + ServiceAI.configure({ |
| 160 | + models: { |
| 161 | + // Fast model for simple tasks |
| 162 | + fast: openai('gpt-3.5-turbo'), |
| 163 | + |
| 164 | + // Default model for general use |
| 165 | + default: openai('gpt-4'), |
| 166 | + |
| 167 | + // Advanced reasoning |
| 168 | + reasoning: openai('gpt-4-turbo'), |
| 169 | + |
| 170 | + // Anthropic Claude |
| 171 | + claude: anthropic('claude-3-opus-20240229'), |
| 172 | + |
| 173 | + // Google Gemini |
| 174 | + gemini: google('gemini-pro'), |
| 175 | + }, |
| 176 | + defaultModel: 'default', |
| 177 | + }), |
| 178 | + ], |
| 179 | +}); |
| 180 | +``` |
| 181 | + |
| 182 | +## Advanced Features |
| 183 | + |
| 184 | +### Custom System Prompts |
| 185 | + |
| 186 | +```typescript |
| 187 | +const conversation = await ai.createConversation({ |
| 188 | + model: 'default', |
| 189 | + systemPrompt: `You are an expert in ObjectStack. |
| 190 | + Answer questions about the framework accurately and concisely. |
| 191 | + Always provide code examples when relevant.`, |
| 192 | +}); |
| 193 | +``` |
| 194 | + |
| 195 | +### Conversation History |
| 196 | + |
| 197 | +```typescript |
| 198 | +// Get full conversation history |
| 199 | +const history = await ai.getConversationHistory(conversationId); |
| 200 | + |
| 201 | +// Clear conversation history |
| 202 | +await ai.clearConversation(conversationId); |
| 203 | + |
| 204 | +// Delete conversation |
| 205 | +await ai.deleteConversation(conversationId); |
| 206 | +``` |
| 207 | + |
| 208 | +### Error Handling |
| 209 | + |
| 210 | +```typescript |
| 211 | +try { |
| 212 | + const response = await ai.sendMessage({ |
| 213 | + conversationId: conversation.id, |
| 214 | + message: 'Hello', |
| 215 | + }); |
| 216 | +} catch (error) { |
| 217 | + if (error.code === 'RATE_LIMIT_EXCEEDED') { |
| 218 | + // Handle rate limiting |
| 219 | + } else if (error.code === 'MODEL_NOT_FOUND') { |
| 220 | + // Handle missing model |
| 221 | + } |
| 222 | +} |
| 223 | +``` |
| 224 | + |
| 225 | +## Integration with ObjectStack Agents |
| 226 | + |
| 227 | +The AI service integrates with the `@objectstack/spec/ai` agent protocol: |
| 228 | + |
| 229 | +```typescript |
| 230 | +import { defineAgent } from '@objectstack/spec'; |
| 231 | + |
| 232 | +const myAgent = defineAgent({ |
| 233 | + name: 'code_assistant', |
| 234 | + model: 'default', |
| 235 | + systemPrompt: 'You help write ObjectStack code.', |
| 236 | + tools: ['create_object', 'create_field', 'create_view'], |
| 237 | +}); |
| 238 | + |
| 239 | +// Agent automatically uses the AI service |
| 240 | +const result = await myAgent.execute({ |
| 241 | + input: 'Create a contact object with name and email fields', |
| 242 | +}); |
| 243 | +``` |
| 244 | + |
| 245 | +## Architecture |
| 246 | + |
| 247 | +The service follows a layered architecture: |
| 248 | + |
| 249 | +1. **Adapter Layer**: Abstracts different LLM providers (OpenAI, Anthropic, Google) |
| 250 | +2. **Conversation Manager**: Handles conversation state and history |
| 251 | +3. **Tool Registry**: Manages tool registration and execution |
| 252 | +4. **REST Routes**: Auto-generated HTTP endpoints |
| 253 | +5. **SSE Streaming**: Real-time streaming support |
| 254 | + |
| 255 | +## Contract Implementation |
| 256 | + |
| 257 | +Implements `IAIService` from `@objectstack/spec/contracts`: |
| 258 | + |
| 259 | +```typescript |
| 260 | +interface IAIService { |
| 261 | + createConversation(options: ConversationOptions): Promise<Conversation>; |
| 262 | + sendMessage(options: MessageOptions): Promise<Message>; |
| 263 | + streamMessage(options: MessageOptions): AsyncIterable<MessageChunk>; |
| 264 | + registerTool(tool: AITool): void; |
| 265 | + getConversationHistory(conversationId: string): Promise<Message[]>; |
| 266 | + deleteConversation(conversationId: string): Promise<void>; |
| 267 | +} |
| 268 | +``` |
| 269 | + |
| 270 | +## Performance Considerations |
| 271 | + |
| 272 | +- **Streaming**: Use streaming for long responses to improve perceived performance |
| 273 | +- **Model Selection**: Choose appropriate models based on task complexity |
| 274 | +- **Conversation History**: Limit history length to control token usage |
| 275 | +- **Caching**: Provider-level caching is handled automatically |
| 276 | + |
| 277 | +## Best Practices |
| 278 | + |
| 279 | +1. **Model Selection**: Use fast models for simple tasks, advanced models for complex reasoning |
| 280 | +2. **System Prompts**: Provide clear, specific instructions in system prompts |
| 281 | +3. **Tool Design**: Keep tools focused and well-documented |
| 282 | +4. **Error Handling**: Always handle rate limits and API errors gracefully |
| 283 | +5. **Streaming**: Use streaming for better UX on long-running queries |
| 284 | + |
| 285 | +## License |
| 286 | + |
| 287 | +Apache-2.0 |
| 288 | + |
| 289 | +## See Also |
| 290 | + |
| 291 | +- [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs) |
| 292 | +- [@objectstack/spec/ai Protocol](../../spec/src/ai/) |
| 293 | +- [AI Agent Guide](/content/docs/guides/ai/) |
0 commit comments