Ai Chat Integration
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
AI Chat Integration
This document explains how AI chat and generation features are integrated into our monorepo applications.
Overview
Our monorepo includes comprehensive AI integration through the @gograb-ai library, which provides:
- AI-powered content generation
- Multiple AI provider support (OpenAI, Anthropic, Gemini)
- Mock generation for development
- Unified API across providers
Architecture
@gograb-ai Library
├── Services
│ ├── AIFactoryService - Main factory for AI operations
│ ├── OpenAIService - OpenAI integration
│ ├── AnthropicService - Anthropic Claude integration
│ ├── GeminiService - Google Gemini integration
│ └── MenuGenerationService - Specialized menu generation
├── Models
│ ├── AIProvider enum
│ ├── Message interfaces
│ └── Generation interfaces
└── Proxy
├── Anthropic proxy server
└── OpenAI proxy server
Using AI Generation
1. Basic Setup
import { AIFactoryService, AIProvider, MessageRole } from '@gograb-ai';
export class MyComponent {
private aiFactory = inject(AIFactoryService);
async generateContent(prompt: string): Promise<string> {
const messages = [
{
role: MessageRole.System,
content: 'You are a helpful assistant.'
},
{
role: MessageRole.User,
content: prompt
}
];
try {
const response = await this.aiFactory.chat(
messages,
{ provider: AIProvider.ANTHROPIC }
);
return response;
} catch (error) {
console.error('AI generation failed:', error);
return this.generateFallbackContent(prompt);
}
}
}
2. Menu Generation Example
The UX Menu component demonstrates advanced AI integration:
import { MenuGenerationService } from '@gograb-ai';
export class UxMenuComponent {
private menuGenService = inject(MenuGenerationService);
async generateMenu(prompt: string): Promise<void> {
const request = {
purpose: prompt,
includeIcons: true,
includeBadges: true,
includeSubmenus: true,
style: 'navigation'
};
this.menuGenService.generateMenu(request).subscribe(result => {
if (result) {
this.applyGeneratedMenu(result);
}
});
}
}
AI Providers
OpenAI
// Configuration
const openAIConfig = {
apiKey: process.env['OPENAI_API_KEY'],
model: 'gpt-4',
temperature: 0.7
};
Anthropic (Claude)
// Configuration
const anthropicConfig = {
apiKey: process.env['ANTHROPIC_API_KEY'],
model: 'claude-3-opus-20240229',
maxTokens: 4000
};
Mock Provider
For development without API keys:
// Automatically used when API keys are not available
const mockConfig = {
provider: AIProvider.MOCK,
delay: 1000 // Simulate processing time
};
Proxy Servers
Anthropic Proxy
Located at libs/gograb-ai/src/proxy/anthropic-proxy.js:
// Start the proxy server
node libs/gograb-ai/src/proxy/anthropic-proxy.js
// Default port: 3001
// Endpoint: http://localhost:3001/api/anthropic/messages
Environment Variables
# .env.local
ANTHROPIC_API_KEY=your-api-key-here
OPENAI_API_KEY=your-api-key-here
GEMINI_API_KEY=your-api-key-here
Widget AI Generation Pattern
Each widget should follow this pattern for AI generation:
1. Create AI Service
@Injectable({
providedIn: 'root'
})
export class WidgetAIService {
private aiFactory = inject(AIFactoryService);
async generateConfiguration(prompt: string): Promise<WidgetConfig> {
// Build system prompt
const systemPrompt = this.buildSystemPrompt();
// Create messages
const messages = [
{ role: MessageRole.System, content: systemPrompt },
{ role: MessageRole.User, content: prompt }
];
try {
// Try real AI first
const response = await this.aiFactory.chat(messages);
return this.parseResponse(response);
} catch (error) {
// Fall back to mock generation
return this.generateMockConfiguration(prompt);
}
}
private generateMockConfiguration(prompt: string): WidgetConfig {
// Intelligent mock generation based on prompt analysis
const lowerPrompt = prompt.toLowerCase();
if (lowerPrompt.includes('dashboard')) {
return this.generateDashboardConfig();
} else if (lowerPrompt.includes('form')) {
return this.generateFormConfig();
}
return this.generateDefaultConfig();
}
}
2. Storage Integration
AI-generated content should be automatically saved:
async generateWithAI(): Promise<void> {
const result = await this.aiService.generateConfiguration(this.prompt);
if (result) {
// Apply configuration
this.widgetConfig.set(result.config);
// Auto-save to storage
const variation = {
id: `ai-${Date.now()}`,
name: `AI: ${this.prompt.slice(0, 30)}...`,
config: result.config,
createdAt: Date.now()
};
this.storageService.saveVariation(variation).subscribe();
}
}
Best Practices
1. Error Handling
Always implement fallback strategies:
try {
// Try real AI
const result = await this.aiFactory.chat(messages);
return this.parseResponse(result);
} catch (error) {
console.error('AI generation failed:', error);
// Check error type
if (error.message.includes('401')) {
this.showError('Invalid API key');
} else if (error.message.includes('429')) {
this.showError('Rate limit exceeded');
}
// Use mock generation
return this.generateMockContent(prompt);
}
2. Prompt Engineering
Structure prompts for better results:
private buildSystemPrompt(): string {
return `You are an expert UI/UX designer specializing in ${this.widgetType}.
Guidelines:
- Generate modern, accessible designs
- Use appropriate color schemes
- Follow Material Design principles
- Include proper spacing and typography
Respond with valid JSON matching this structure:
${JSON.stringify(this.getExpectedStructure(), null, 2)}`;
}
3. Response Parsing
Safely parse AI responses:
private parseResponse(response: string): WidgetConfig | null {
try {
// Extract JSON from response
const jsonMatch = response.match(/\{[\s\S]*\}/);
if (!jsonMatch) {
throw new Error('No JSON found in response');
}
const parsed = JSON.parse(jsonMatch[0]);
// Validate structure
if (!this.isValidConfig(parsed)) {
throw new Error('Invalid configuration structure');
}
return parsed;
} catch (error) {
console.error('Failed to parse AI response:', error);
return null;
}
}
4. User Experience
Provide feedback during generation:
aiGenerationStatus = signal<string>('');
async generateContent(): Promise<void> {
this.aiGenerationStatus.set('Initializing AI...');
try {
this.aiGenerationStatus.set('Analyzing request...');
await this.delay(500);
this.aiGenerationStatus.set('Generating content...');
const result = await this.aiService.generate(this.prompt);
this.aiGenerationStatus.set('Processing result...');
await this.applyResult(result);
this.aiGenerationStatus.set('');
this.showSuccess('Content generated successfully!');
} catch (error) {
this.aiGenerationStatus.set('');
this.showError('Generation failed');
}
}
Mock Generation Strategy
Implement intelligent mock generation:
private analyzePurpose(prompt: string): WidgetPurpose {
const lower = prompt.toLowerCase();
const purposes = {
navigation: ['menu', 'nav', 'sidebar'],
data: ['table', 'grid', 'list'],
form: ['form', 'input', 'field'],
dashboard: ['dashboard', 'chart', 'metric'],
settings: ['settings', 'config', 'preferences']
};
for (const [purpose, keywords] of Object.entries(purposes)) {
if (keywords.some(keyword => lower.includes(keyword))) {
return purpose as WidgetPurpose;
}
}
return 'general';
}
private generateMockContent(prompt: string): WidgetConfig {
const purpose = this.analyzePurpose(prompt);
const templates = this.getTemplatesForPurpose(purpose);
// Select appropriate template
const template = templates.find(t =>
this.matchesPrompt(t, prompt)
) || templates[0];
// Customize based on prompt
return this.customizeTemplate(template, prompt);
}
Testing AI Features
Unit Tests
describe('WidgetAIService', () => {
let service: WidgetAIService;
let aiFactory: jasmine.SpyObj<AIFactoryService>;
beforeEach(() => {
const spy = jasmine.createSpyObj('AIFactoryService', ['chat']);
TestBed.configureTestingModule({
providers: [
WidgetAIService,
{ provide: AIFactoryService, useValue: spy }
]
});
service = TestBed.inject(WidgetAIService);
aiFactory = TestBed.inject(AIFactoryService) as jasmine.SpyObj<AIFactoryService>;
});
it('should generate configuration from prompt', async () => {
const mockResponse = JSON.stringify({
config: { theme: 'dark' },
items: []
});
aiFactory.chat.and.returnValue(Promise.resolve(mockResponse));
const result = await service.generateConfiguration('dark theme menu');
expect(result.config.theme).toBe('dark');
});
it('should fall back to mock on error', async () => {
aiFactory.chat.and.returnValue(Promise.reject(new Error('API error')));
const result = await service.generateConfiguration('test menu');
expect(result).toBeDefined();
expect(result.config).toBeDefined();
});
});
Troubleshooting
Common Issues
401 Unauthorized
- Check API key is set correctly
- Verify proxy server is running
- Check API key validity
Rate Limiting
- Implement exponential backoff
- Cache responses when appropriate
- Use mock generation during development
Parsing Errors
- Log raw responses for debugging
- Implement robust JSON extraction
- Validate response structure
Debug Mode
Enable detailed logging:
const DEBUG_AI = true;
if (DEBUG_AI) {
console.log('AI Request:', { messages, options });
console.log('AI Response:', response);
console.log('Parsed Result:', result);
}
Future Enhancements
Streaming Responses
- Implement streaming for long generations
- Show partial results as they arrive
Context Management
- Maintain conversation history
- Implement context windows
Fine-tuning
- Collect user feedback
- Improve prompts based on usage
Multi-modal Support
- Image generation for UI mockups
- Voice input for commands
Conclusion
AI integration in our monorepo provides:
- 🤖 Intelligent content generation
- 🔄 Multiple provider support
- 🛡️ Graceful fallbacks
- 💾 Automatic persistence
- 🎨 Widget-specific customization
Follow these patterns to ensure consistent, reliable AI features across all applications.