perfumegen / app.py
doevent's picture
Upload app.py
a704ca8 verified
from flask import Flask, render_template, request, jsonify
from gradio_client import Client, handle_file
import os
import json
import random # For demo data variation
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB max upload size
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
API_TOKEN_HF = os.environ['API_TOKEN_HF']
# --- Demo Data ---
# This will be used for initial page load and if the API call fails or is mocked
BASE_AROMA_NAMES_ORDER = [ # Keep this order consistent with frontend
"Rose", "Ocean Breeze", "Fresh Cut Grass", "Lemon Zest", "Lavender",
"Sweet Orange", "Cool Mint", "Vanilla Bean", "Wild Berry", "Spring Rain"
]
client = Client("doevent/gemini_others", hf_token=API_TOKEN_HF, download_files="uploads")
def get_demo_perfume_data():
perfume_name = random.choice(["Demo Garden", "Demo Whisper", "Demo Flare", "Demo Dream"])
slogan = random.choice([
"Awaken your senses.", "Dare to dream.", "The essence of you.", "An unforgettable journey."
])
# Create a random set of aromas and doses
num_active_aromas = random.randint(2, 10)
active_aromas_sample = random.sample(BASE_AROMA_NAMES_ORDER, num_active_aromas)
aromas_data = []
total_dose_for_demo = 0 # To simulate filling the flask
for i, name in enumerate(BASE_AROMA_NAMES_ORDER):
if name in active_aromas_sample and total_dose_for_demo < 0.8: # Limit total demo dose
dose = round(random.uniform(0.1, 0.3), 2)
aromas_data.append({"name": name, "dose": dose})
total_dose_for_demo += dose
# else: # We can include all aromas with 0 dose if needed by frontend for table population
# aromas_data.append({"name": name, "dose": 0.0})
return {
"perfume_name": perfume_name,
"slogan": slogan,
"aromas": aromas_data # This list might only contain active aromas
}
@app.route('/')
def index():
initial_data = get_demo_perfume_data()
return render_template('index.html', initial_data=initial_data, base_aromas_ordered=BASE_AROMA_NAMES_ORDER)
@app.route('/analyze_image', methods=['POST'])
def analyze_image_route():
if 'imageFile' not in request.files:
return jsonify({"error": "No image file provided"}), 400
file = request.files['imageFile']
if file.filename == '':
return jsonify({"error": "No image selected"}), 400
if file:
try:
filename = "uploaded_image_" + file.filename # Add some uniqueness if needed
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(image_path)
custom_prompt_for_perfume = (
"Based on the visual elements, mood, and potential theme of this image, "
"invent a unique perfume. I need the following information structured as a JSON object:\n"
"1. 'perfume_name': A creative and fitting name for the perfume.\n"
"2. 'slogan': A short, catchy slogan for this perfume.\n"
"3. 'aromas': A list of 2 to 10 base aroma notes. For each note, provide its 'name' "
f"(chosen from this list: {', '.join(BASE_AROMA_NAMES_ORDER)}, or a very similar common scent if appropriate) "
"and its 'dose' as a decimal proportion (e.g., 0.3 for 30%). "
"Ideally, the total dose should be equal to a full bottle of 10.0 for 100%"
"\nExample of 'aromas' list: [{'name': 'Rose', 'dose': 0.4}, {'name': 'Lavender', 'dose': 0.2}]"
)
api_result_raw = client.predict(
files_list=[handle_file(image_path)],
message=custom_prompt_for_perfume,
model_name="gemini-2.0-flash",
temperature=0.7,
max_output_tokens=1024,
system_prompt_load= "",
type_mime_name="application/json",
output_schema=None,
google_search_opt=False,
other_options_json=None,
thinking_mode=False,
thinking_budget=None,
api_name="/predict"
)
os.remove(image_path) # Clean up uploaded file
# print("Raw API Result:", api_result_raw)
api_result_raw = api_result_raw[0]["candidates"][0]["content"]["parts"][0]['text']
print("Raw API Result:", api_result_raw)
return api_result_raw
except Exception as e:
print(f"Error during API call or processing: {e}")
# In case of any error, return demo data for now for frontend testing
# os.remove(image_path) # Ensure cleanup even on error
error_data = get_demo_perfume_data()
error_data["api_error"] = f"An error occurred: {str(e)}. Displaying demo data."
return jsonify(error_data), 500 # Send 500 to indicate server-side error
return jsonify({"error": "Invalid file"}), 400
if __name__ == '__main__':
app.run(host="0.0.0.0", port=7860, debug=True) # Use a different port if 5000 is common