Spaces:
Sleeping
Sleeping
File size: 4,621 Bytes
23ddaac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | import os
import asyncio
import json
import traceback
from pathlib import Path
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from dotenv import load_dotenv
# Import Agents
from agents.visual_analyst import VisualAnalyst
from agents.memory_agent import MemoryAgent
from agents.writer_agent import WriterAgent
load_dotenv()
app = FastAPI()
BASE_DIR = Path(__file__).resolve().parent
# Initialize Agents
try:
visual_agent = VisualAnalyst()
memory_agent = MemoryAgent()
writer_agent = WriterAgent()
# Try seeding database, but don't crash if it fails (optional robustness)
try:
memory_agent.seed_database()
except Exception as e:
print(f"⚠️ Memory Agent Seed Warning: {e}")
print("✅ All Agents Online")
except Exception as e:
print(f"❌ Agent Startup Failed: {e}")
# We continue, but endpoints might fail if agents aren't ready.
@app.get("/")
async def read_root():
landing_page = BASE_DIR / "landingpage.html"
if not landing_page.exists():
raise HTTPException(status_code=404, detail="landingpage.html not found")
return FileResponse(landing_page)
@app.get("/dashboard")
async def read_dashboard():
dashboard_page = BASE_DIR / "dashboard.html"
if not dashboard_page.exists():
raise HTTPException(status_code=404, detail="dashboard.html not found")
return FileResponse(dashboard_page)
@app.post("/generate-catalog")
async def generate_catalog(file: UploadFile = File(...)):
file_path = None
try:
# 1. Save Temp File
os.makedirs("uploads", exist_ok=True)
file_path = f"uploads/{file.filename}"
with open(file_path, "wb") as f:
f.write(await file.read())
# 2. Run AI Pipeline (Sequential)
print("▶️ Starting Visual Analysis...")
visual_data = await visual_agent.analyze_image(file_path)
print("▶️ Retrieving Keywords...")
query = f"{visual_data.get('main_color', '')} {visual_data.get('product_type', 'product')}"
seo_keywords = memory_agent.retrieve_keywords(query)
# 2b. AI Fallback: Generate keywords if Pinecone returns empty
if not seo_keywords:
print("🤖 Database empty. Using AI Fallback for SEO keywords.")
try:
fallback_prompt = (
f"The internal keyword database is empty for this product. "
f"Based on these visual features: {json.dumps(visual_data)}, "
f"generate a list of 10 high-converting e-commerce SEO tags "
f"and return them as a JSON array of strings. Return ONLY the JSON array."
)
fallback_response = visual_agent.client.models.generate_content(
model="gemini-2.5-flash",
contents=fallback_prompt
)
import re
match = re.search(r'\[.*\]', fallback_response.text, re.DOTALL)
if match:
seo_keywords = json.loads(match.group(0))
else:
seo_keywords = [tag.strip() for tag in fallback_response.text.split(",") if tag.strip()]
print(f"✅ AI Fallback generated {len(seo_keywords)} keywords.")
except Exception as fallback_err:
print(f"⚠️ AI Fallback also failed: {fallback_err}")
seo_keywords = []
print("▶️ Writing Listing...")
listing = writer_agent.write_listing(visual_data, seo_keywords)
# 3. Construct Final Payload
final_data = {
"visual_data": visual_data,
"seo_keywords": seo_keywords,
"listing": listing
}
return JSONResponse(content=final_data)
except Exception as e:
error_details = traceback.format_exc()
print(f"❌ Error in generate-catalog: {e}")
print(error_details)
return JSONResponse(
content={
"error": "An internal server error occurred.",
"type": type(e).__name__
},
status_code=500
)
finally:
# Cleanup
if file_path and os.path.exists(file_path):
try:
os.remove(file_path)
except Exception as cleanup_error:
print(f"⚠️ Cleanup Warning: {cleanup_error}")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)
|