import { serve } from 'https://deno.fresh.run/std@0.168.0/http/server.ts' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' import { corsHeaders } from '../_shared/cors.ts' import { OpenAI } from "https://deno.land/x/openai@v4.24.0/mod.ts"; interface EssayAnalysisRequest { essay_id: string; content: string; type_id: string; genre_id: string; } interface EssayAnalysisResponse { overall_score: number; feedback: { structure: string; content: string; language: string; }; strengths: string[]; improvements: string[]; suggestions: string; criteria_scores: { adequacy: number; // Adequação ao tema/gênero coherence: number; // Coerência textual cohesion: number; // Coesão vocabulary: number; // Vocabulário grammar: number; // Gramática/ortografia }; } interface EssayType { id: string; slug: string; title: string; description: string; } interface EssayGenre { id: string; type_id: string; slug: string; title: string; description: string; requirements: { min_words: number; max_words: number; required_elements: string[]; }; } serve(async (req) => { // Handle CORS if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }) } try { // Criar cliente Supabase const supabaseClient = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_ANON_KEY') ?? '' ) // Criar cliente OpenAI const openai = new OpenAI({ apiKey: Deno.env.get('OPENAI_API_KEY'), }); // Obter dados da requisição const { essay_id, content, type_id, genre_id }: EssayAnalysisRequest = await req.json() // Validar dados obrigatórios if (!essay_id || !content || !type_id || !genre_id) { return new Response( JSON.stringify({ error: 'Dados obrigatórios não fornecidos' }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } // Buscar informações do tipo e gênero const { data: typeData, error: typeError } = await supabaseClient .from('essay_types') .select('*') .eq('id', type_id) .single() const { data: genreData, error: genreError } = await supabaseClient .from('essay_genres') .select('*') .eq('id', genre_id) .single() if (typeError || genreError || !typeData || !genreData) { return new Response( JSON.stringify({ error: 'Tipo ou gênero não encontrado' }), { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } const essayType: EssayType = typeData const essayGenre: EssayGenre = genreData // Construir prompt para a análise const prompt = `Você é um professor especialista em análise de textos. Analise a redação a seguir considerando que é do tipo "${essayType.title}" e gênero "${essayGenre.title}". Requisitos específicos do gênero: - Mínimo de palavras: ${essayGenre.requirements.min_words} - Máximo de palavras: ${essayGenre.requirements.max_words} - Elementos obrigatórios: ${essayGenre.requirements.required_elements.join(', ')} Texto para análise: ${content} Forneça uma análise detalhada considerando: 1. Adequação ao tipo e gênero textual 2. Coerência e coesão textual 3. Vocabulário e linguagem 4. Gramática e ortografia 5. Elementos obrigatórios do gênero 6. Pontos fortes 7. Pontos a melhorar 8. Sugestões específicas para aprimoramento Responda em formato JSON seguindo exatamente esta estrutura: { "overall_score": number, // 0 a 100 "feedback": { "structure": string, // Feedback sobre estrutura e organização "content": string, // Feedback sobre conteúdo e ideias "language": string // Feedback sobre linguagem e gramática }, "strengths": string[], // Lista de pontos fortes "improvements": string[], // Lista de pontos a melhorar "suggestions": string, // Sugestões específicas "criteria_scores": { "adequacy": number, // 0 a 100 - Adequação ao tema/gênero "coherence": number, // 0 a 100 - Coerência textual "cohesion": number, // 0 a 100 - Coesão "vocabulary": number, // 0 a 100 - Vocabulário "grammar": number // 0 a 100 - Gramática/ortografia } }` // Realizar análise com OpenAI const completion = await openai.chat.completions.create({ model: "gpt-4-turbo-preview", messages: [ { role: "system", content: "Você é um professor especialista em análise de textos, com vasta experiência em avaliação de redações." }, { role: "user", content: prompt } ], response_format: { type: "json_object" } }); const analysis: EssayAnalysisResponse = JSON.parse(completion.choices[0].message.content) // Salvar análise no banco const { error: saveError } = await supabaseClient .from('essay_analyses') .insert({ essay_id, overall_score: analysis.overall_score, feedback: analysis.feedback, strengths: analysis.strengths, improvements: analysis.improvements, suggestions: analysis.suggestions, criteria_scores: analysis.criteria_scores }) if (saveError) { return new Response( JSON.stringify({ error: 'Erro ao salvar análise' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } // Atualizar status da redação const { error: updateError } = await supabaseClient .from('student_essays') .update({ status: 'analyzed' }) .eq('id', essay_id) if (updateError) { return new Response( JSON.stringify({ error: 'Erro ao atualizar status da redação' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } // Retornar análise return new Response( JSON.stringify(analysis), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } catch (error) { return new Response( JSON.stringify({ error: error.message }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } })