from fastapi import FastAPI, HTTPException, UploadFile, File from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Optional, List import json from datetime import datetime from pathlib import Path from .vector_store import VectorStore from .brand_style import BrandStyle from .config import Config import openai import os # Initialize OpenAI openai.api_key = Config.OPENAI_API_KEY # Initialize app = FastAPI(title="Marketing Assistant AI", version="0.1.0") vector_store = VectorStore() brand_style = BrandStyle() # Create user_queries directory user_queries_path = Path("data/user_queries") user_queries_path.mkdir(parents=True, exist_ok=True) # CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Models class CampaignRequest(BaseModel): prompt: str content_type: str = "general" tone: Optional[str] = None class Campaign(BaseModel): content: str content_type: str metadata: dict = {} class UserFeedback(BaseModel): query_id: str rating: int # 1-5 scale comments: Optional[str] = None used_output: bool = False modifications_made: Optional[str] = None # Helper function to log user queries def log_user_query(request: CampaignRequest, generated_copy: str = None, success: bool = None): """Log user query to data/user_queries/""" query_id = f"query_{datetime.now().strftime('%Y%m%d_%H%M%S_%f')}" query_log = { "query_id": query_id, "timestamp": datetime.now().isoformat(), "user_input": { "prompt": request.prompt, "content_type": request.content_type, "tone": request.tone }, "status": "completed" if success else "failed" if success is False else "processing", "generated_output": generated_copy, "success": success } # Save to user_queries folder query_file = user_queries_path / f"{query_id}.json" with open(query_file, 'w') as f: json.dump(query_log, f, indent=2) return query_id # Routes @app.post("/generate") async def generate_copy(request: CampaignRequest): """Generate marketing copy based on prompt and brand guidelines""" query_id = None try: # Log the initial query query_id = log_user_query(request) # Get similar content from vector store similar = vector_store.search(request.prompt, request.content_type) # Format similar content for context similar_content = "" if similar: similar_content = "\n\nSimilar past campaigns for reference:\n" for i, campaign in enumerate(similar[:3], 1): similar_content += f"{i}. {campaign.get('content', '')}\n" # Generate with OpenAI system_prompt = brand_style.get_prompt(request) user_prompt = f"Create marketing copy for: {request.prompt}{similar_content}" response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], temperature=0.7, max_tokens=500 ) generated_copy = response.choices[0].message.content # Update query log with success log_user_query(request, generated_copy, True) # Store the generated copy for future reference new_campaign = { "content": generated_copy, "content_type": request.content_type, "metadata": { "prompt": request.prompt, "tone": request.tone, "generated_at": datetime.now().isoformat(), "query_id": query_id } } # Add to vector store for future similarity searches vector_store.add_campaign(new_campaign) return { "result": generated_copy, "query_id": query_id } except Exception as e: # Log the error if query_id: log_user_query(request, str(e), False) print(f"Error in generate_copy: {str(e)}") # For debugging raise HTTPException(status_code=500, detail=str(e)) @app.post("/add-campaign") async def add_campaign(campaign: Campaign): """Add a new campaign to the vector store""" try: # Add timestamp to metadata campaign_data = campaign.dict() campaign_data["metadata"]["added_at"] = datetime.now().isoformat() vector_store.add_campaign(campaign_data) return {"status": "success"} except Exception as e: print(f"Error in add_campaign: {str(e)}") # For debugging raise HTTPException(status_code=500, detail=str(e)) @app.get("/search") async def search_campaigns(query: str, limit: int = 5): """Search for similar campaigns""" try: results = vector_store.search(query, k=limit) return {"results": results} except Exception as e: print(f"Error in search_campaigns: {str(e)}") # For debugging raise HTTPException(status_code=500, detail=str(e)) @app.get("/") async def root(): """Health check endpoint""" return {"message": "Marketing Assistant AI is running", "version": "0.1.0"} @app.get("/health") async def health_check(): """Detailed health check""" return { "status": "healthy", "vector_store_size": len(vector_store.campaigns), "timestamp": datetime.now().isoformat() } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)