story-generator/supabase/functions/generate-story/index.ts
Lucas Santana 03732de610 feat: implementa geração de histórias com IA
- Adiciona integração com OpenAI GPT e DALL-E
- Implementa fluxo de geração de histórias
- Adiciona feedback visual do processo
- Melhora tratamento de erros
- Adiciona logs para debug

Resolves: #FEAT-123
2024-12-23 09:03:23 -03:00

171 lines
5.3 KiB
TypeScript

import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import OpenAI from 'https://esm.sh/openai@4.20.1'
const openai = new OpenAI({
apiKey: Deno.env.get('OPENAI_API_KEY')
});
interface StoryPrompt {
theme_id: string;
subject_id: string;
character_id: string;
setting_id: string;
context?: string;
}
serve(async (req) => {
const { record } = await req.json()
try {
// Criar cliente Supabase
const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_ANON_KEY') ?? ''
)
// Buscar detalhes das categorias selecionadas
const [themeResult, subjectResult, characterResult, settingResult] = await Promise.all([
supabase.from('story_themes').select('*').eq('id', record.theme_id).single(),
supabase.from('story_subjects').select('*').eq('id', record.subject_id).single(),
supabase.from('story_characters').select('*').eq('id', record.character_id).single(),
supabase.from('story_settings').select('*').eq('id', record.setting_id).single()
])
// Log para debug
console.log('Resultados das consultas:', {
theme: themeResult,
subject: subjectResult,
character: characterResult,
setting: settingResult
});
// Verificar erros nas consultas
if (themeResult.error) throw new Error(`Erro ao buscar tema: ${themeResult.error.message}`);
if (subjectResult.error) throw new Error(`Erro ao buscar disciplina: ${subjectResult.error.message}`);
if (characterResult.error) throw new Error(`Erro ao buscar personagem: ${characterResult.error.message}`);
if (settingResult.error) throw new Error(`Erro ao buscar cenário: ${settingResult.error.message}`);
// Verificar se os dados existem
if (!themeResult.data) throw new Error(`Tema não encontrado: ${record.theme_id}`);
if (!subjectResult.data) throw new Error(`Disciplina não encontrada: ${record.subject_id}`);
if (!characterResult.data) throw new Error(`Personagem não encontrado: ${record.character_id}`);
if (!settingResult.data) throw new Error(`Cenário não encontrado: ${record.setting_id}`);
const theme = themeResult.data;
const subject = subjectResult.data;
const character = characterResult.data;
const setting = settingResult.data;
// Log dos dados recebidos
console.log('Record recebido:', record);
console.log('Dados encontrados:', {
theme,
subject,
character,
setting
});
// Construir o prompt para o GPT
const prompt = `
Crie uma história educativa para crianças com as seguintes características:
Tema: ${theme.title}
Disciplina: ${subject.title}
Personagem Principal: ${character.title}
Cenário: ${setting.title}
${record.context ? `Contexto Adicional: ${record.context}` : ''}
Requisitos:
- História adequada para crianças de 6-12 anos
- Conteúdo educativo focado em ${subject.title}
- Linguagem clara e envolvente
- 3-5 páginas de conteúdo
- Cada página deve ter um texto curto e sugestão para uma imagem
- Evitar conteúdo sensível ou inadequado
- Incluir elementos de ${theme.title}
- Ambientado em ${setting.title}
- Personagem principal baseado em ${character.title}
Formato da resposta:
{
"title": "Título da História",
"pages": [
{
"text": "Texto da página",
"image_prompt": "Descrição para gerar a imagem"
}
]
}
`
// Gerar história com GPT-4 Turbo
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: "Você é um contador de histórias infantis especializado em conteúdo educativo."
},
{
role: "user",
content: prompt
}
],
temperature: 0.7,
max_tokens: 1000
});
const storyContent = JSON.parse(completion.choices[0].message.content || '{}');
// Gerar imagens com DALL-E
const pages = await Promise.all(
storyContent.pages.map(async (page: any) => {
const imageResponse = await openai.images.generate({
prompt: `${page.image_prompt}. Style: children's book illustration, colorful, educational, safe for kids`,
n: 1,
size: "1024x1024"
});
return {
text: page.text,
image: imageResponse.data[0].url
}
})
);
// Atualizar história no Supabase
await supabase
.from('stories')
.update({
title: storyContent.title,
content: {
title: storyContent.title,
pages: pages,
theme: theme.title,
subject: subject.title,
character: character.title,
setting: setting.title,
context: record.context
},
status: 'published'
})
.eq('id', record.id)
return new Response(
JSON.stringify({ success: true }),
{ headers: { 'Content-Type': 'application/json' } }
)
} catch (error) {
console.error('Erro ao gerar história:', error)
return new Response(
JSON.stringify({ error: error.message }),
{
headers: { 'Content-Type': 'application/json' },
status: 500
}
)
}
})