diff --git a/py b/py new file mode 100644 index 00000000..2f10b005 --- /dev/null +++ b/py @@ -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.