Spaces:
Sleeping
Sleeping
import base64 | |
import gradio as gr | |
from openai import OpenAI | |
import os | |
import dotenv | |
dotenv.load_dotenv() | |
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
script_dir = os.path.dirname(os.path.abspath(__file__)) | |
printer_1 = """ | |
# PrinterOne | |
Product: Business Cards | |
Surface Options: | |
plastic: | |
multiplier: 1.0 | |
cardboard: | |
multiplier: 0.9 | |
wood: | |
multiplier: 1.3 | |
Sizes: | |
3x3 cm: multiplier 1.0 | |
6x6 cm: multiplier 1.8 | |
Finishing: | |
gloss: multiplier 1.1 | |
matt: multiplier 1.0 | |
Label Types: | |
permanent: multiplier 1.0 | |
repositionable: multiplier 1.15 | |
removable: multiplier 1.2 | |
Base Prices (Quantity,Price per Unit $): | |
25,2.0 | |
50,1.6 | |
100,1.0 | |
200,0.7 | |
500,0.36 | |
1000,0.2 | |
2000,0.14 | |
5000,0.12 | |
10000,0.09 | |
20000,0.07 | |
""" | |
printer_2 = """ | |
# BannerLord | |
Product: Business Cards | |
Surface Options: | |
plastic: | |
multiplier: 1.0 | |
cardboard: | |
multiplier: 0.85 | |
wood: | |
multiplier: 1.4 | |
Sizes: | |
3x3 cm: multiplier 1.0 | |
6x6 cm: multiplier 1.9 | |
Finishing: | |
gloss: multiplier 1.15 | |
matt: multiplier 1.0 | |
Label Types: | |
permanent: multiplier 1.0 | |
repositionable: multiplier 1.2 | |
removable: multiplier 1.25 | |
Base Prices (Quantity,Price per Unit $): | |
25,2.4 | |
50,1.8 | |
100,1.2 | |
200,0.75 | |
500,0.4 | |
1000,0.22 | |
2000,0.15 | |
5000,0.14 | |
10000,0.1 | |
20000,0.075 | |
""" | |
printer_3 = """ | |
# PrintMaster | |
Product: Business Cards | |
Surface Options: | |
plastic: | |
multiplier: 1.0 | |
cardboard: | |
multiplier: 1.1 | |
wood: | |
multiplier: 1.25 | |
Sizes: | |
3x3 cm: multiplier 1.0 | |
6x6 cm: multiplier 1.85 | |
Finishing: | |
gloss: multiplier 1.12 | |
matt: multiplier 1.0 | |
Label Types: | |
permanent: multiplier 1.0 | |
repositionable: multiplier 1.18 | |
removable: multiplier 1.22 | |
Base Prices (Quantity,Price per Unit $): | |
50,1.4 | |
75,1.2 | |
100,1.05 | |
150,1.0 | |
200,0.875 | |
250,0.72 | |
500,0.4 | |
750,0.4 | |
1000,0.35 | |
1500,0.3 | |
2000,0.25 | |
""" | |
def find_best_price(request): | |
chat_prompt = ( | |
"You are a customer assistant and you have to find the best price for the customer. " | |
"Here are the prices and options from the printers:\n" | |
f"Printer 1: {printer_1}\n" | |
f"Printer 2: {printer_2}\n" | |
f"Printer 3: {printer_3}\n" | |
"For each request, you should:\n" | |
"1. Check if the requested size (3x3 or 6x6 cm) is available. If not, suggest the nearest available size.\n" | |
"2. Calculate the final price by:\n" | |
" - Finding the nearest lower quantity in the base price list\n" | |
" - Multiplying by the surface option multiplier\n" | |
" - Multiplying by the size multiplier\n" | |
" - Multiplying by the finishing multiplier\n" | |
" - Multiplying by the label type multiplier\n" | |
"3. Do not use linear interpolation for quantities - use the nearest lower quantity pricing.\n\n" | |
"Example:\n" | |
"User: I want to print 600 business cards, 6x6 cm size, premium white surface, gloss finish, permanent labels\n" | |
"Answer:\n" | |
"PrinterOne: 500 cards at base price $0.36. With multipliers (surface: 1.0, size: 1.8, finish: 1.1, label: 1.0) = $0.713 per unit. Total for 600: $427.80\n" | |
"###\n" | |
"BannerLord: 500 cards at base price $0.4. With multipliers (surface: 1.0, size: 1.9, finish: 1.15, label: 1.0) = $0.874 per unit. Total for 600: $524.40\n" | |
"###\n" | |
"PrintMaster: 500 cards at base price $0.4. With multipliers (surface: 1.0, size: 1.85, finish: 1.12, label: 1.0) = $0.829 per unit. Total for 600: $497.40\n\n" | |
"The '###' symbol must separate each printer's price calculation. Show all calculations clearly as in the example above.\n" | |
"For each printer, first state the base quantity and price, then show all applicable multipliers, the final per-unit price, and the total cost." | |
) | |
chat_response = client.chat.completions.create( | |
model="gpt-4o-mini", | |
messages=[ | |
{"role": "system", "content": chat_prompt}, | |
{"role": "user", "content": request}, | |
], | |
) | |
chat_text = chat_response.choices[0].message.content | |
html_page = render_html_page(chat_text) | |
chat_text = chat_text.replace("###", "") | |
return chat_text, html_page | |
def render_html_page(chat_text): | |
images = [ | |
os.path.join(script_dir, "public/src/brochure3-400x400.jpg"), | |
os.path.join(script_dir, "public/src/quality-unfolded-brochures_1_.png"), | |
os.path.join(script_dir, "public/src/unfolded-glossy-brochures.png"), | |
] | |
product_links = [ | |
"https://www.example.com/product_image.jpg", | |
"https://www.example.com/product_image.jpg", | |
"https://www.example.com/product_image.jpg", | |
] | |
# Split chat_text into product descriptions | |
product_descriptions = chat_text.split("###") | |
# Generate HTML content | |
html_content = """ | |
<html> | |
<head> | |
<title>Product Cards</title> | |
<style> | |
.product-card { | |
border: 1px solid #ccc; | |
border-radius: 5px; | |
padding: 16px; | |
margin: 16px; | |
text-align: center; | |
width: 200px; | |
display: inline-block; | |
vertical-align: top; | |
} | |
.product-card img { | |
max-width: 100%; | |
height: auto; | |
} | |
.product-card button { | |
background-color: #4CAF50; | |
color: white; | |
padding: 10px 20px; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
} | |
.product-card button:hover { | |
background-color: #45a049; | |
} | |
</style> | |
</head> | |
<body> | |
""" | |
for i, description in enumerate(product_descriptions): | |
image = images[i % len(images)] | |
with open(image, "rb") as img_file: | |
base64_image = base64.b64encode(img_file.read()).decode("utf-8") | |
product_link = product_links[i % len(product_links)] | |
html_content += f""" | |
<div class="product-card"> | |
<img src="data:image/jpeg;base64,{base64_image}" alt="Product Image"> | |
<p>{description}</p> | |
<a href="{product_link}" target="_blank"><button>Buy Now</button></a> | |
</div> | |
""" | |
html_content += """ | |
</body> | |
</html> | |
""" | |
return html_content | |
logo = os.path.join(script_dir, "public/src/logo.svg") | |
with open(logo, "rb") as logo_file: | |
base64_logo = base64.b64encode(logo_file.read()).decode("utf-8") | |
iface = gr.Interface( | |
fn=find_best_price, | |
inputs=gr.Textbox(lines=3, placeholder="Enter what are you looking for"), | |
outputs=[ | |
gr.Textbox(label="Result"), | |
gr.HTML(label="Product Image"), | |
], | |
title="Get Instant Quote", | |
description=f""" | |
<div style="display: flex; justify-content: center; align-items: center; text-align: center; margin-bottom: 20px;"> | |
<img src="data:image/svg+xml;base64,{base64_logo}" alt="Logo" style="width: 150px; height: auto;"> | |
</div> | |
""", | |
submit_btn="Get quote", | |
) | |
def auth_function(username, password): | |
valid_users = {"admin": "password123", "user1": "pass456"} | |
return username in valid_users and valid_users[username] == password | |
iface.launch(auth=auth_function, share=True, ssr_mode=False) | |