diff --git a/FastAPI/api/database.py b/FastAPI/api/database.py index af5c18ca..e664fbf0 100644 --- a/FastAPI/api/database.py +++ b/FastAPI/api/database.py @@ -1,3 +1,4 @@ +# database.py from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker diff --git a/FastAPI/api/gemini.py b/FastAPI/api/gemini.py new file mode 100644 index 00000000..3537ed8b --- /dev/null +++ b/FastAPI/api/gemini.py @@ -0,0 +1,78 @@ +# gemini.py +import os +import time +import google.generativeai as genai +from google.api_core.exceptions import ( + ResourceExhausted, InternalServerError +) + +# Configure the API key from environment variable +genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) + +# AI Model Configuration +generation_config = { + "temperature": 1.0, + "top_p": 0.95, + "top_k": 40, + "max_output_tokens": 2000, + "response_mime_type": "text/plain", +} + +main_model = genai.GenerativeModel( + model_name="gemini-1.5-flash-002", + generation_config=generation_config, + system_instruction=""" + You are the world's best salesperson and a business analyst. Your job is to identify potential communities to target for advertisement. + """ +) + +mainChat = main_model.start_chat(history=[], enable_automatic_function_calling=False) +retries = 0 + +def call_gemini(productName: str, productDescription: str, productAdditional: str = "No Additional Information to Provide"): + global retries, mainChat + + if retries >= 3: + retries = 0 + return "An unexpected error occurred. Please try again later." + + model_prompt = f""" + You are trying to sell a {productName}. Given the following information, identify at least three potential communities to target for advertisement: + + ### Product Name: + {productName} + + ### Product Description: + {productDescription} + + ### Additional Information (Optional): + {productAdditional} + + ### Instructions: + Step 1. Identify at least three very specific potential communities to target for advertisement. Be as specific as possible when naming communities to target. For each community, include a short justification for why this specific community. + Step 2. For each of your targeted communities, identify the optimal means of advertisement (either text or image, or both). + Step 3. + a. If creating a textual advertisement, generate a full-length text that can be directly used. + b. If creating a visual advertisement (image), generate a prompt for an AI image generator. + + ### Formatting Instructions: + - Follow the sample output as closely as possible. + - After outputting step 1, print "BREAK HERE" to separate sections. + """ + + try: + startTime = time.time() + response = mainChat.send_message(model_prompt) + endTime = time.time() + + print(f'Gemini responded in {round(endTime - startTime, 2)} seconds') + return response.text + + except (ResourceExhausted, InternalServerError) as e: + retries += 1 + print(f'Error encountered: {e}. Retrying... ({retries}/3)') + time.sleep(1) + return call_gemini(productName, productDescription, productAdditional) + except Exception as e: + print(f'Unknown error: {e}') + return "An unexpected error occurred while contacting Gemini." diff --git a/FastAPI/api/main.py b/FastAPI/api/main.py index 8f3ae1f4..79f4ef96 100644 --- a/FastAPI/api/main.py +++ b/FastAPI/api/main.py @@ -1,20 +1,24 @@ +# main.py from fastapi import FastAPI, Depends, HTTPException +from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from sqlalchemy.orm import Session from typing import Optional +import os + from database import SessionLocal, engine import models -from fastapi.middleware.cors import CORSMiddleware +from gemini import call_gemini # Import the function from gemini.py # Create database tables models.Base.metadata.create_all(bind=engine) app = FastAPI() -# Allow CORS from the frontend URL +# Allow CORS from all origins (adjust as needed) app.add_middleware( CORSMiddleware, - allow_origins=["http://localhost:3000"], # Frontend URL + allow_origins=["*"], # For development; specify origins in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], @@ -24,8 +28,8 @@ class OutputDataRequest(BaseModel): name: str description: str - extra: str = None - image: str = None + extra: Optional[str] = None + image: Optional[str] = None # Dependency to get a database session def get_db(): @@ -41,44 +45,40 @@ def read_root(): # Helper function to get output data by name def get_output_data_by_name(name: str, db: Session) -> Optional[models.OutputData]: - """ - Retrieve output data from the database by name. - - Args: - name (str): The name of the output data to retrieve. - db (Session): The database session. - - Returns: - Optional[models.OutputData]: The retrieved output data or None if not found. - """ return db.query(models.OutputData).filter(models.OutputData.name == name).first() # POST endpoint to submit or update data @app.post("/submit_output/") async def submit_output(data: OutputDataRequest, db: Session = Depends(get_db)): + # Call Gemini to get model response based on form data + gemini_response = call_gemini(data.name, data.description, data.extra or "No Additional Information to Provide") + + if not gemini_response: + raise HTTPException(status_code=500, detail="Failed to get response from Gemini.") + # Check if a record with the same name already exists existing_data = get_output_data_by_name(data.name, db) - + if existing_data: # Update existing record - existing_data.description = data.description + existing_data.description = gemini_response # Store Gemini response existing_data.extra = data.extra existing_data.image = data.image db.commit() db.refresh(existing_data) - return {"message": "Data updated successfully", "data": existing_data} + return {"message": "Data updated successfully", "data": existing_data, "gemini_response": gemini_response} else: - # Insert new record if no existing record is found + # Insert new record new_data = models.OutputData( name=data.name, - description=data.description, + description=gemini_response, # Store Gemini response extra=data.extra, image=data.image, ) db.add(new_data) db.commit() db.refresh(new_data) - return {"message": "Data stored successfully", "data": new_data} + return {"message": "Data stored successfully", "data": new_data, "gemini_response": gemini_response} # GET endpoint to retrieve data by name @app.get("/output_data/{name}") diff --git a/FastAPI/api/models.py b/FastAPI/api/models.py index 8877a69e..a371cad6 100644 --- a/FastAPI/api/models.py +++ b/FastAPI/api/models.py @@ -1,3 +1,4 @@ +# models.py from sqlalchemy import Column, Integer, String from database import Base @@ -5,7 +6,7 @@ class OutputData(Base): __tablename__ = 'output_data' id = Column(Integer, primary_key=True, index=True) - name = Column(String, unique=True, index=True) # Keeps name unique to avoid duplicates + name = Column(String, unique=True, index=True) description = Column(String) extra = Column(String, nullable=True) - image = Column(String, nullable=True) # Stores image URL or base64 string + image = Column(String, nullable=True) diff --git a/FastAPI/api/workout_app.db b/FastAPI/api/workout_app.db index 42edfb62..4861e43b 100644 Binary files a/FastAPI/api/workout_app.db and b/FastAPI/api/workout_app.db differ diff --git a/src/components/Output.jsx b/src/components/Output.jsx index a412aac1..cffab5fa 100644 --- a/src/components/Output.jsx +++ b/src/components/Output.jsx @@ -1,8 +1,10 @@ +// Output.jsx import React, { useEffect, useState } from 'react'; import axios from 'axios'; const Output = ({ formData }) => { const [submittedData, setSubmittedData] = useState(null); + const [geminiResponse, setGeminiResponse] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -15,13 +17,16 @@ const Output = ({ formData }) => { const submitAndFetchData = async () => { try { // Submit data to backend - await axios.post('http://127.0.0.1:8000/submit_output/', { + const submitResponse = await axios.post('http://127.0.0.1:8000/submit_output/', { name: formData.name, description: formData.description, extra: formData.extra, image: formData.image, }); + // Set geminiResponse using data from response + setGeminiResponse(submitResponse.data.gemini_response); + // Fetch data from backend after submission const response = await axios.get(`http://127.0.0.1:8000/output_data/${formData.name}`); setSubmittedData(response.data); @@ -43,16 +48,29 @@ const Output = ({ formData }) => {
ID: {submittedData.id}
-Product Name: {submittedData.name}
-Description: {submittedData.description}
- {submittedData.extra &&Additional Info: {submittedData.extra}
} - {submittedData.image && ( -ID: {submittedData.id}
+Product Name: {submittedData.name}
+Description: {submittedData.description}
+ {submittedData.extra &&Additional Info: {submittedData.extra}
} + {submittedData.image && ( +{geminiResponse}
+ ) : ( +No Gemini response available.
+ )} +