Skip to main content
Glama
bbernstein
by bbernstein
rag-service-simple.ts7.32 kB
import OpenAI from 'openai'; import { ScriptAnalysis } from '../types/lighting'; export class RAGService { private openai: OpenAI; private patterns: Map<string, any> = new Map(); constructor() { this.openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); this.initializeDefaultPatterns(); } async initializeCollection() { // Simple in-memory initialization - no ChromaDB required // Don't log to stdout/stderr as it interferes with MCP protocol } async indexLightingPattern(pattern: { id: string; description: string; context: string; mood: string; fixtureTypes: string[]; colorPalette: string[]; intensity: string; metadata: Record<string, any>; }) { this.patterns.set(pattern.id, pattern); } async analyzeScript(scriptText: string): Promise<ScriptAnalysis> { const prompt = ` Analyze this theatrical script and extract lighting-relevant information. Return a JSON object with the following structure: { "scenes": [ { "sceneNumber": "string", "title": "string (optional)", "content": "string (excerpt)", "mood": "string (e.g., tense, romantic, mysterious)", "characters": ["string"], "stageDirections": ["string"], "lightingCues": ["string"], "timeOfDay": "string (optional)", "location": "string (optional)" } ], "characters": ["string"], "settings": ["string"], "overallMood": "string", "themes": ["string"] } Script text: ${scriptText} Focus on: - Mood and atmosphere descriptions - Time of day and location changes - Stage directions that imply lighting - Character entrances and emotional beats - Explicit lighting cues in the text `; const response = await this.openai.chat.completions.create({ model: 'gpt-4', messages: [{ role: 'user', content: prompt }], temperature: 0.3 }); const content = response.choices[0].message.content || '{}'; try { return JSON.parse(content); } catch (_error) { // If JSON parsing fails, try to extract JSON from the response const jsonMatch = content.match(/\{[\s\S]*\}/); if (jsonMatch) { try { return JSON.parse(jsonMatch[0]); } catch (_e) { // If still fails, return a fallback structure return { scenes: [], characters: [], settings: [], overallMood: 'unknown', themes: [] }; } } return { scenes: [], characters: [], settings: [], overallMood: 'unknown', themes: [] }; } } async findSimilarLightingPatterns( sceneDescription: string, mood: string, limit: number = 5 ) { // Simple pattern matching based on mood const matchingPatterns = Array.from(this.patterns.values()) .filter(pattern => pattern.mood.toLowerCase() === mood.toLowerCase() || pattern.context.toLowerCase().includes(sceneDescription.toLowerCase()) ) .slice(0, limit); return { documents: matchingPatterns.map(p => p.description), metadatas: matchingPatterns.map(p => ({ context: p.context, mood: p.mood, fixtureTypes: p.fixtureTypes.join(','), colorPalette: p.colorPalette.join(','), intensity: p.intensity })), distances: matchingPatterns.map(() => Math.random()) // Mock similarity scores }; } async generateLightingRecommendations( sceneContext: string, mood: string, availableFixtures: string[] ): Promise<{ colorSuggestions: string[]; intensityLevels: Record<string, number>; focusAreas: string[]; reasoning: string; }> { // Find similar patterns const _similarPatterns = await this.findSimilarLightingPatterns(sceneContext, mood); const prompt = `Scene: ${sceneContext} Mood: ${mood} Fixtures: ${availableFixtures.slice(0, 5).join(', ')} JSON: { "colorSuggestions": ["colors"], "intensityLevels": {"ambient": 50, "key": 75, "fill": 60, "background": 30}, "focusAreas": ["areas"], "reasoning": "brief explanation" } Recommend colors and intensities for ${mood} mood.`; const response = await this.openai.chat.completions.create({ model: 'gpt-4', messages: [{ role: 'user', content: prompt }], temperature: 0.4 }); const content = response.choices[0].message.content || '{}'; try { return JSON.parse(content); } catch (_error) { // If JSON parsing fails, try to extract JSON from the response const jsonMatch = content.match(/\{[\s\S]*\}/); if (jsonMatch) { try { return JSON.parse(jsonMatch[0]); } catch (_e) { // If still fails, return a fallback structure return { colorSuggestions: [], intensityLevels: { ambient: 50, key: 75, fill: 60, background: 30 }, focusAreas: [], reasoning: 'Unable to parse AI response, using default values' }; } } return { colorSuggestions: [], intensityLevels: { ambient: 50, key: 75, fill: 60, background: 30 }, focusAreas: [], reasoning: 'Unable to parse AI response, using default values' }; } } private initializeDefaultPatterns() { const defaultPatterns = [ { id: 'romantic-warm', description: 'Warm romantic lighting with soft amber tones', context: 'intimate dialogue, love scenes, tender moments', mood: 'romantic', fixtureTypes: ['LED_PAR'], colorPalette: ['amber', 'warm white', 'rose'], intensity: 'moderate', metadata: { colorTemp: '2700K', focusType: 'soft' } }, { id: 'dramatic-tension', description: 'High contrast dramatic lighting with sharp angles', context: 'conflict scenes, confrontations, climactic moments', mood: 'tense', fixtureTypes: ['MOVING_HEAD', 'LED_PAR'], colorPalette: ['deep red', 'stark white', 'blue'], intensity: 'dramatic', metadata: { contrast: 'high', focusType: 'sharp' } }, { id: 'mysterious-cool', description: 'Cool mysterious lighting with blue undertones', context: 'supernatural scenes, night scenes, mystery', mood: 'mysterious', fixtureTypes: ['LED_PAR', 'MOVING_HEAD'], colorPalette: ['deep blue', 'purple', 'cool white'], intensity: 'subtle', metadata: { colorTemp: '5600K', atmosphere: 'ethereal' } }, { id: 'cheerful-bright', description: 'Bright cheerful lighting with natural tones', context: 'comedy scenes, daytime scenes, celebrations', mood: 'cheerful', fixtureTypes: ['LED_PAR'], colorPalette: ['warm white', 'yellow', 'light blue'], intensity: 'dramatic', metadata: { colorTemp: '4000K', feel: 'natural' } } ]; for (const pattern of defaultPatterns) { this.patterns.set(pattern.id, pattern); } } async seedDefaultPatterns() { // Already done in constructor console.log('Default patterns loaded'); } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bbernstein/lacylights-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server