import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' const openai = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY') }) interface ReadingAnalysis { fluency_score: number pronunciation_score: number accuracy_score: number comprehension_score: number words_per_minute: number pause_count: number error_count: number self_corrections: number strengths: string[] improvements: string[] suggestions: string raw_data: any } export async function analyzeReading( transcription: string, storyId: string ): Promise { try { console.log('Analisando leitura para story_id:', storyId) const supabase = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' ) // Busca a história com o texto da página const { data: storyPages, error: storyError } = await supabase .from('story_pages') .select('text') .eq('story_id', storyId) .order('page_number', { ascending: true }) if (storyError) { console.error('Erro ao buscar história:', storyError) throw storyError } if (!storyPages || storyPages.length === 0) { console.error('Dados da história inválidos:', storyPages) throw new Error('Texto da história não encontrado') } // Concatena todos os textos das páginas const originalText = storyPages.map(page => page.text).join(' ') console.log('Texto original:', originalText) console.log('Transcrição:', transcription) // Análise com GPT-4 const analysis = await openai.chat.completions.create({ model: "gpt-4o-mini", messages: [ { role: "system", content: `Você é um especialista em análise de leitura infantil. Analise a transcrição comparando com o texto original. Forneça métricas detalhadas e feedback construtivo. Retorne apenas o JSON solicitado, sem texto adicional.` }, { role: "user", content: ` Texto Original: "${originalText}" Transcrição: "${transcription}" Analise e retorne as métricas no formato JSON.` } ], response_format: { type: "json_object" }, temperature: 0.7, max_tokens: 1000, functions: [ { name: "analyze_reading", description: "Analisa a leitura e retorna métricas", parameters: { type: "object", properties: { fluency_score: { type: "number", description: "Pontuação de fluência (0-100)" }, pronunciation_score: { type: "number", description: "Pontuação de pronúncia (0-100)" }, accuracy_score: { type: "number", description: "Pontuação de precisão (0-100)" }, comprehension_score: { type: "number", description: "Pontuação de compreensão (0-100)" }, words_per_minute: { type: "number", description: "Palavras por minuto" }, pause_count: { type: "number", description: "Número de pausas" }, error_count: { type: "number", description: "Número de erros" }, self_corrections: { type: "number", description: "Número de autocorreções" }, strengths: { type: "array", items: { type: "string" }, description: "3-5 pontos fortes" }, improvements: { type: "array", items: { type: "string" }, description: "3-5 pontos para melhorar" }, suggestions: { type: "string", description: "Sugestão personalizada" } }, required: [ "fluency_score", "pronunciation_score", "accuracy_score", "comprehension_score", "words_per_minute", "pause_count", "error_count", "self_corrections", "strengths", "improvements", "suggestions" ] } } ] }) if (!analysis.choices[0]?.message?.function_call?.arguments) { throw new Error('Análise vazia do GPT') } console.log('Resposta do GPT:', analysis.choices[0].message.function_call.arguments) const result = JSON.parse(analysis.choices[0].message.function_call.arguments) return { ...result, raw_data: analysis } } catch (error) { console.error('Erro detalhado na análise:', error) throw error } }