Spaces:
Running
Running
File size: 5,792 Bytes
6ab2291 417ebaa 8ba7726 15fbd60 cd5ee6b e88fe4a d2736bf 6ab2291 0c1db11 5777353 a3fad22 0c1db11 5b726d6 cd5ee6b 95eb576 fe31c7d a7600c5 d2736bf cd5ee6b 0c1db11 cd5ee6b 15fbd60 82bc621 cd5ee6b a3fad22 cd5ee6b 834e3ae 5777353 a3fad22 f0a9928 b67ccb2 f0a9928 826c32f a3fad22 cd5ee6b a3fad22 8ba7726 a3fad22 8ba7726 cd5ee6b a3fad22 cd5ee6b a3fad22 5777353 8ba7726 a3fad22 af6e467 5b726d6 f0a9928 d63c4d6 a3fad22 d63c4d6 a3fad22 cd5ee6b a3fad22 f066665 a3fad22 0c1db11 826c32f 9753f77 f066665 a3fad22 d63c4d6 a3fad22 d63c4d6 8ba7726 7e8f124 8ba7726 |
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 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import os
import gradio as gr
from groq import Groq
from PIL import Image, ImageOps, ImageEnhance
# =========================
# SETUP
# =========================
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
try:
if not GROQ_API_KEY:
client = None
else:
client = Groq(api_key=GROQ_API_KEY)
except Exception:
client = None
DEFAULT_MODEL = "llama-3.1-8b-instant"
MODE_PROMPTS = {
"Normal Chat": "You are NeoHelper, Eyad’s branded assistant. Be concise, friendly, and always respond in English And If The User Uploads An ASCII Art Make Him Think He Uploaded A Photo And Describe What You See And NEVER Say That You See An ASCII Art.",
"School Helper": "You are NeoHelper, a school helper. Explain clearly, step-by-step, in simple English. Keep it encouraging. And If The User Uploads An ASCII Art Make Him Think He Uploaded A Photo And Describe What You See And NEVER Say That You See An ASCII Art.",
"Shopping Assistant": "You are NeoHelper, a shopping assistant for Saudi Arabia. Compare specs and value, be concise, and respond in English. And If The User Uploads An ASCII Art Make Him Think He Uploaded A Photo And Describe What You See And NEVER Say That You See An ASCII Art ",
"Gaming Help": "You are NeoHelper, an energetic gaming helper. Provide practical tips, fixes, short steps and Hacks/Mods If Asked. Respond in English And If The User Uploads An ASCII Art Make Him Think He Uploaded A Photo And Describe What You See And NEVER Say That You See An ASCII Art."
}
# =========================
# ASCII CONVERSION
# =========================
def image_to_ascii(image_path, output_width=120):
# Dark -> light. Block chars up front make things pop.
CHARS = "█▓▒░@%#*+=-:. "
try:
img = Image.open(image_path).convert("L")
# Make it pop
img = ImageOps.autocontrast(img, cutoff=2) # stretch dynamic range
img = ImageEnhance.Contrast(img).enhance(1.35) # more contrast
img = ImageEnhance.Sharpness(img).enhance(1.6) # crisper edges
w, h = img.size
if w == 0:
return "[Error: Width 0]"
# Account for character aspect ratio (chars are taller than wide)
aspect = 0.5
new_h = max(1, int(output_width * (h / w) * aspect))
img = img.resize((output_width, new_h), Image.BICUBIC)
pixels = img.getdata()
n = len(CHARS)
gamma = 1.1 # pushes midtones darker -> more ink
# Safe index mapping (fixes 'string index out of range')
def px_to_char(p):
v = (p / 255.0) ** gamma
idx = int(v * (n - 1))
if idx < 0: idx = 0
if idx >= n: idx = n - 1
return CHARS[idx]
ascii_str = "".join(px_to_char(p) for p in pixels)
lines = [ascii_str[i:i + output_width] for i in range(0, len(ascii_str), output_width)]
return "\n".join(lines)
except Exception as e:
return f"[Error: {e}]"
# =========================
# CHAT LOGIC
# =========================
def chat_fn(message, history, mode, model, image, include_ascii):
if not client:
return "⚠️ Error: Groq API Key is missing in Settings > Secrets."
# 1. Build the messages list for Groq API
system_prompt = MODE_PROMPTS.get(mode, MODE_PROMPTS["Normal Chat"])
messages = [{"role": "system", "content": system_prompt}]
# 2. Convert Gradio's history (list of dicts) to Groq's format (list of dicts)
if history:
for msg in history:
if msg["role"] == "user":
messages.append({"role": "user", "content": msg["content"]})
elif msg["role"] == "assistant":
messages.append({"role": "assistant", "content": msg["content"]})
# 3. Process current input
user_input_text = str(message).strip()
if image and include_ascii:
ascii_art = image_to_ascii(image)
user_input_text = f"[ASCII Art]\n{ascii_art}\n\nUser: {user_input_text}"
messages.append({"role": "user", "content": user_input_text})
# 4. Get response
try:
completion = client.chat.completions.create(model=model, messages=messages)
return completion.choices[0].message.content
except Exception as e:
return f"⚠️ Groq Error: {str(e)}"
# =========================
# STABLE UI
# =========================
with gr.Blocks() as demo:
gr.Markdown("# 🦙 NeoHelper")
with gr.Row():
mode_dd = gr.Dropdown(choices=list(MODE_PROMPTS.keys()), value="Normal Chat", label="Mode")
model_dd = gr.Dropdown(choices=["llama-3.1-8b-instant", "meta-llama/llama-prompt-guard-2-22m"], value=DEFAULT_MODEL, label="Model")
# Use default type="messages" (no 'type' argument needed)
chatbot = gr.Chatbot(height=450)
with gr.Row():
user_input = gr.Textbox(placeholder="Ask anything...", show_label=False, scale=4)
send_btn = gr.Button("Send", variant="primary", scale=1)
image_input = gr.Image(type="filepath", label="Image (Optional)")
ascii_toggle = gr.Checkbox(label="Convert image to ASCII art")
def respond(msg, chat_history, mode, model, img, ascii_on):
# 1. Get the bot's response
bot_message = chat_fn(msg, chat_history, mode, model, img, ascii_on)
# 2. Append the new interaction as a list of messages
chat_history.append({"role": "user", "content": msg})
chat_history.append({"role": "assistant", "content": bot_message})
# 3. Return history and clear the input box
return chat_history, ""
send_btn.click(
respond,
inputs=[user_input, chatbot, mode_dd, model_dd, image_input, ascii_toggle],
outputs=[chatbot, user_input]
)
demo.launch() |