Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import os
import openai # pyright: ignore[reportMissingImports]
from fastapi import FastAPI # type: ignore
from pydantic import BaseModel # pyright: ignore[reportMissingImports]
from typing import List, Literal, Optional
from dotenv import load_dotenv # type: ignore

# Charger les variables d'environnement
load_dotenv()

# Initialiser le client OpenAI
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# Initialiser l'application FastAPI
app = FastAPI(
title="AI 3D Presentation Generator API",
description="API pour générer des présentations 3D en utilisant l'IA.",
version="1.0.0"
)

# --- Modèles de données Pydantic pour la validation ---
# Ces modèles définissent la structure exacte du JSON que nous attendons de l'IA.

class SceneObject(BaseModel):
type: Literal["text", "box", "sphere", "cone", "cylinder"]
content: Optional[str] = None
position: List[float]
color: str
size: Optional[float] = None
scale: Optional[List[float]] = None
rotation: Optional[List[float]] = None
material: Optional[str] = None

class Scene3D(BaseModel):
cameraPosition: List[float]
objects: List[SceneObject]
lighting: dict

class Slide(BaseModel):
id: int
title: str
content: str
scene3D: Scene3D

class Presentation(BaseModel):
title: str
slides: List[Slide]

# --- Service d'IA ---
def generate_presentation_with_ai(topic: str) -> Presentation:
"""
Appelle l'API OpenAI pour générer la structure de la présentation.
"""
print(f"Génération d'une présentation sur le thème : '{topic}'...")

# Un prompt très structuré pour guider l'IA et forcer une sortie JSON
system_prompt = """
Tu es un expert en création de présentations 3D immersives. Ton unique mission est de transformer un sujet donné en un objet JSON valide décrivant une présentation.
Le JSON doit suivre EXACTEMENT la structure Pydantic suivante :
{
"title": "string",
"slides": [
{
"id": 1,
"title": "string",
"content": "string",
"scene3D": {
"cameraPosition": [x, y, z],
"objects": [
{
"type": "text",
"content": "string",
"position": [x, y, z],
"size": 0.5,
"color": "#FFFFFF"
},
{
"type": "sphere",
"position": [x, y, z],
"color": "#4F46E5",
"material": "emissive"
}
],
"lighting": { "type": "ambient", "intensity": 0.5 }
}
}
]
}
Génère 2 diapositives pour le sujet donné. Le style doit être moderne, épuré et professionnel.
Réponds UNIQUEMENT avec l'objet JSON, sans aucun autre texte, ni explication, ni formatage markdown.
"""

try:
response = client.chat.completions.create(
model="gpt-4-turbo-preview",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Sujet : '{topic}'"}
],
temperature=0.7,
)

# L'API OpenAI nous garantit un JSON valide grâce à response_format
presentation_data = response.choices[0].message.content

# Pydantic va valider et parser le JSON dans notre modèle
validated_presentation = Presentation.model_validate_json(presentation_data)
print("Génération réussie et validation OK.")
return validated_presentation

except Exception as e:
print(f"Erreur lors de l'appel à l'API OpenAI: {e}")
# En cas d'erreur, on peut retourner une présentation par défaut ou lever une exception
raise ValueError("L'IA n'a pas pu générer la présentation.")

# --- Endpoint de l'API ---
class GenerationRequest(BaseModel):
topic: str

@app.post("/generate-presentation", response_model=Presentation)
async def create_presentation(request: GenerationRequest):
"""
Endpoint principal qui prend un sujet et retourne une présentation 3D générée par l'IA.
"""
if not request.topic:
raise HTTPException(status_code=400, detail="Le sujet est requis.") # type: ignore

try:
presentation = generate_presentation_with_ai(request.topic)
return presentation
except ValueError as e:
raise HTTPException(status_code=500, detail=str(e)) # type: ignore
except Exception as e:
raise HTTPException(status_code=500, detail="Une erreur interne est survenue.") # type: ignore

# Pour lancer le serveur : uvicorn main:app --reload
import requests # pyright: ignore[reportMissingModuleSource]

# Vous devriez stocker ce token de manière sécurisée après le flux OAuth
CANVA_API_TOKEN = "votre_token_d_acces_canva"

def get_user_canva_designs():
headers = {
"Authorization": f"Bearer {CANVA_API_TOKEN}"
}
# L'endpoint de l'API Canva pour lister les designs
url = "https://api.canva.com/v1/designs"

try:
response = requests.get(url, headers=headers)
response.raise_for_status() # Lève une exception pour les réponses 4xx/5xx
return response.json()
except requests.exceptions.RequestException as e:
print(f"Erreur lors de l'appel à l'API Canva: {e}")
return None

# Vous pourriez ensuite appeler cette fonction et passer les résultats à votre service d'IA
# pour qu'il transforme le contenu d'un design spécifique en présentation 3D.