GoGma commited on
Commit
58bad43
·
verified ·
1 Parent(s): 708be9c

Add FastAPI REST API wrapper for n8n integration

Browse files
Files changed (1) hide show
  1. api_wrapper.py +232 -0
api_wrapper.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Sofia AI API Wrapper - FastAPI REST API
3
+ Integración completa para n8n y automatización externa
4
+ """
5
+
6
+ from fastapi import FastAPI, HTTPException, Header, Depends
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from pydantic import BaseModel
9
+ from typing import Optional, List, Dict
10
+ import os
11
+ from generation import generate_image_from_prompt
12
+
13
+ # Crear instancia de FastAPI
14
+ app = FastAPI(
15
+ title="Sofia AI API",
16
+ description="API REST para integración con n8n y automatización del sistema Sofia AI",
17
+ version="1.0.0"
18
+ )
19
+
20
+ # Configurar CORS para permitir llamadas desde n8n
21
+ app.add_middleware(
22
+ CORSMiddleware,
23
+ allow_origins=["*"], # En producción, especifica tu dominio de n8n
24
+ allow_credentials=True,
25
+ allow_methods=["*"],
26
+ allow_headers=["*"],
27
+ )
28
+
29
+ # Modelos Pydantic para validación de datos
30
+ class ImageGenerationRequest(BaseModel):
31
+ prompt: str
32
+ style: str = "lifestyle"
33
+ model_name: str = "SG161222/RealVisXL_V4.0_Lightning"
34
+
35
+ class ImageGenerationResponse(BaseModel):
36
+ success: bool
37
+ image_path: Optional[str]
38
+ message: str
39
+
40
+ class ContentRequest(BaseModel):
41
+ topic: str
42
+ platform: str
43
+ tone: str = "engaging"
44
+
45
+ class ContentResponse(BaseModel):
46
+ success: bool
47
+ content: str
48
+ platform: str
49
+
50
+ class WorkflowRequest(BaseModel):
51
+ topic: str
52
+ platform: str
53
+ style: str = "lifestyle"
54
+ tone: str = "engaging"
55
+
56
+ class WorkflowResponse(BaseModel):
57
+ success: bool
58
+ content: str
59
+ image_path: Optional[str]
60
+ optimization_score: Optional[int]
61
+ suggestions: List[str]
62
+
63
+ # Autenticación simple con API Key
64
+ API_KEY = os.getenv("SOFIA_API_KEY", "sofia_dev_key_2026")
65
+
66
+ def verify_api_key(x_api_key: str = Header(None)):
67
+ if x_api_key != API_KEY:
68
+ raise HTTPException(status_code=401, detail="API Key inválida")
69
+ return x_api_key
70
+
71
+ # ====================
72
+ # ENDPOINTS
73
+ # ====================
74
+
75
+ @app.get("/")
76
+ def root():
77
+ return {
78
+ "message": "Sofia AI API - Sistema Multi-Agente",
79
+ "version": "1.0.0",
80
+ "endpoints": {
81
+ "health": "/health",
82
+ "image_generate": "/api/v1/image/generate",
83
+ "content_create": "/api/v1/content/create",
84
+ "workflow_complete": "/api/v1/workflow/complete"
85
+ },
86
+ "docs": "/docs"
87
+ }
88
+
89
+ @app.get("/health")
90
+ def health_check():
91
+ """Endpoint de salud para monitoreo"""
92
+ return {
93
+ "status": "healthy",
94
+ "service": "sofia-ai-api",
95
+ "timestamp": "2026-02-09T22:00:00Z"
96
+ }
97
+
98
+ @app.post("/api/v1/image/generate", response_model=ImageGenerationResponse)
99
+ def generate_image(
100
+ request: ImageGenerationRequest,
101
+ api_key: str = Depends(verify_api_key)
102
+ ):
103
+ """
104
+ Genera una imagen de Sofia Rivera usando HuggingFace API
105
+
106
+ - **prompt**: Descripción de la imagen a generar
107
+ - **style**: Estilo (lifestyle, fitness, fashion, beach, Personalizado)
108
+ - **model_name**: Modelo a usar (por defecto RealVisXL)
109
+ """
110
+ try:
111
+ # Base de Sofia para consistencia
112
+ sofia_base = "Professional portrait of Sofia Rivera, a beautiful 25yo Spanish-Latina woman, hazel eyes, wavy dark chocolate hair, sun-kissed skin, highly detailed, 8k, instagram style, "
113
+
114
+ # Construir prompt completo
115
+ if request.style == "Personalizado":
116
+ full_prompt = sofia_base + request.prompt
117
+ else:
118
+ full_prompt = sofia_base + request.style
119
+
120
+ # Generar imagen
121
+ img_path, status = generate_image_from_prompt(
122
+ prompt=full_prompt,
123
+ model_name=request.model_name
124
+ )
125
+
126
+ if img_path:
127
+ return ImageGenerationResponse(
128
+ success=True,
129
+ image_path=img_path,
130
+ message=status
131
+ )
132
+ else:
133
+ return ImageGenerationResponse(
134
+ success=False,
135
+ image_path=None,
136
+ message=status
137
+ )
138
+
139
+ except Exception as e:
140
+ raise HTTPException(status_code=500, detail=f"Error generando imagen: {str(e)}")
141
+
142
+ @app.post("/api/v1/content/create", response_model=ContentResponse)
143
+ def create_content(
144
+ request: ContentRequest,
145
+ api_key: str = Depends(verify_api_key)
146
+ ):
147
+ """
148
+ Crea contenido para redes sociales
149
+
150
+ - **topic**: Tema del contenido
151
+ - **platform**: Plataforma (Instagram, Twitter, LinkedIn, TikTok)
152
+ - **tone**: Tono del contenido (engaging, professional, casual, inspirational)
153
+ """
154
+ try:
155
+ content_templates = {
156
+ "instagram": f"✨ {request.topic} ✨\n\nCaption: Let's talk about {request.topic}! 💫\n\nHashtags: #{request.topic.replace(' ', '')} #SofiaAI #ContentCreation",
157
+ "twitter": f"💭 Thinking about {request.topic}...\n\nWhat's your take? 🤔\n\n#{request.topic.replace(' ', '')} #SofiaAI",
158
+ "linkedin": f"Professional insight on {request.topic}\n\nIn today's digital landscape, {request.topic} is becoming increasingly important.\n\n#ProfessionalDevelopment #{request.topic.replace(' ', '')}",
159
+ "tiktok": f"🎬 Video idea: {request.topic}\n\nHook: Did you know about {request.topic}?\nContent: [Engaging explanation]\nCTA: Follow for more!\n\n#{request.topic.replace(' ', '')} #Viral"
160
+ }
161
+
162
+ content = content_templates.get(
163
+ request.platform.lower(),
164
+ f"Content about {request.topic} for {request.platform}"
165
+ )
166
+
167
+ return ContentResponse(
168
+ success=True,
169
+ content=content,
170
+ platform=request.platform
171
+ )
172
+
173
+ except Exception as e:
174
+ raise HTTPException(status_code=500, detail=f"Error creando contenido: {str(e)}")
175
+
176
+ @app.post("/api/v1/workflow/complete", response_model=WorkflowResponse)
177
+ def complete_workflow(
178
+ request: WorkflowRequest,
179
+ api_key: str = Depends(verify_api_key)
180
+ ):
181
+ """
182
+ Workflow completo: Genera contenido + imagen en un solo paso
183
+ Perfecto para integración con n8n
184
+
185
+ - **topic**: Tema
186
+ - **platform**: Plataforma de destino
187
+ - **style**: Estilo de imagen
188
+ - **tone**: Tono del contenido
189
+ """
190
+ try:
191
+ # 1. Crear contenido
192
+ content_templates = {
193
+ "instagram": f"✨ {request.topic} ✨\n\nCaption: Let's talk about {request.topic}! 💫\n\nHashtags: #{request.topic.replace(' ', '')} #SofiaRivera #IAInfluencer",
194
+ "twitter": f"💭 {request.topic}\n\nWhat's your take? 🤔\n\n#{request.topic.replace(' ', '')} #SofiaAI",
195
+ "linkedin": f"Professional insight on {request.topic}\n\nIn today's digital landscape, {request.topic} is crucial.\n\n#Leadership #{request.topic.replace(' ', '')}",
196
+ "tiktok": f"🎬 {request.topic}\n\nHook: You won't believe this!\nContent: [About {request.topic}]\nCTA: Follow @SofiaRivera!\n\n#{request.topic.replace(' ', '')}"
197
+ }
198
+
199
+ content = content_templates.get(request.platform.lower(), f"Content: {request.topic}")
200
+
201
+ # 2. Generar imagen
202
+ sofia_base = "Professional portrait of Sofia Rivera, a beautiful 25yo Spanish-Latina woman, hazel eyes, wavy dark chocolate hair, sun-kissed skin, highly detailed, 8k, instagram style, "
203
+ full_prompt = sofia_base + request.style
204
+
205
+ img_path, status = generate_image_from_prompt(prompt=full_prompt)
206
+
207
+ # 3. Optimización simple
208
+ suggestions = []
209
+ score = 100
210
+
211
+ if len(content) < 50:
212
+ suggestions.append("⚠️ Content seems short. Consider adding more value.")
213
+ score -= 15
214
+
215
+ if "#" not in content:
216
+ suggestions.append("💡 Add relevant hashtags")
217
+ score -= 15
218
+
219
+ return WorkflowResponse(
220
+ success=True,
221
+ content=content,
222
+ image_path=img_path,
223
+ optimization_score=max(score, 0),
224
+ suggestions=suggestions
225
+ )
226
+
227
+ except Exception as e:
228
+ raise HTTPException(status_code=500, detail=f"Error en workflow: {str(e)}")
229
+
230
+ if __name__ == "__main__":
231
+ import uvicorn
232
+ uvicorn.run(app, host="0.0.0.0", port=7860)