Spaces:
Sleeping
Sleeping
File size: 5,289 Bytes
c541f80 |
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 |
# ui.py
# Gradio Web Interface for Caramel AI
import gradio as gr
import json
import os
from program import get_response, extract_text_from_file
# --- SETUP & BRANDING ---
try:
branding_path = os.path.join(os.path.dirname(__file__), "branding.json")
with open(branding_path, "r", encoding="utf-8") as f:
brand_info = json.load(f)["brand"]
except FileNotFoundError:
brand_info = { "organizationName": "Caramel AI", "slogan": "AI HR Manager", "logo": {"title": ""}, "colors": {"primary": "#F0E68C", "secondary": "#8B4513"}, "email": "contact@example.com", "mobile": "N/A", "website": "#", "socialMedia": {"linkedin": "#", "github": "#", "x": "#"}}
primary_color = brand_info["colors"]["primary"]
secondary_color = brand_info["colors"]["secondary"]
# --- CSS INJECTION ---
try:
css_path = os.path.join(os.path.dirname(__file__), "style.css")
with open(css_path, "r", encoding="utf-8") as f:
css_template = f.read()
final_css = f"""
<style>
:root {{
--brand-primary: {primary_color};
--brand-secondary: {secondary_color};
}}
{css_template}
</style>
"""
except FileNotFoundError:
print("Warning: style.css not found.")
final_css = ""
# --- FIXED: JAVASCRIPT VARIABLE DEFINITION WAS MISSING ---
js_trigger_file_click = """
() => {
// Find the hidden file input element and click it
document.querySelector('#file-uploader input[type="file"]').click();
}
"""
js_theme_toggle = """
() => {
document.body.classList.toggle('dark');
const theme_btn = document.querySelector('#theme-btn button');
if (document.body.classList.contains('dark')) {
theme_btn.textContent = 'βοΈ Light Mode';
} else {
theme_btn.textContent = 'π Dark Mode';
}
}
"""
# --- GRADIO INTERFACE ---
with gr.Blocks(css=final_css, title=brand_info["organizationName"]) as caramel_ai:
gr.HTML(f"""<div id="header"><img src="{brand_info['logo']['title']}" alt="Logo"><h2>{brand_info['organizationName']}</h2><p>{brand_info['slogan']}</p></div>""")
file_context_state = gr.State("")
chatbot = gr.Chatbot(height=550, label="Caramel AI Chat", type="messages")
status_display = gr.Markdown("Status: Ready")
file_uploader = gr.File(label="Upload File", file_count='single', file_types=['.txt', '.pdf'], elem_id="file-uploader")
with gr.Row(elem_id="input-row"):
with gr.Column(min_width=50, elem_id="attachment-btn-container"):
attachment_btn = gr.Button("π")
msg_box = gr.Textbox(placeholder="Ask a question or upload a file...", show_label=False, container=False, scale=8, elem_id="msg-box")
send_btn = gr.Button("Ask", variant="primary", scale=1)
with gr.Row():
memory_switch = gr.Checkbox(label="Remember Conversation", value=True)
clear_btn = gr.Button("π§Ή Clear All")
theme_btn = gr.Button("π Dark Mode", elem_id="theme-btn")
# --- UI LOGIC FUNCTIONS ---
def process_file(file_obj, chat_history):
if not file_obj: return "Status: File upload failed.", "", chat_history
extracted_text = extract_text_from_file(file_obj)
if "Error:" in extracted_text: return extracted_text, None, chat_history
status = f"β
**Processed:** `{os.path.basename(file_obj.name)}`"
history = chat_history + [{"role": "assistant", "content": f"I've read '{os.path.basename(file_obj.name)}'. Ask me anything about it."}]
return status, extracted_text, history
def respond(message, chat_history, memory_enabled, file_context):
if not message.strip(): return "", chat_history, file_context
history_for_api = chat_history if memory_enabled else []
api_history = [{"role": "model" if t["role"] == "assistant" else t["role"], "parts": [t["content"]]} for t in history_for_api]
context = (f"Based ONLY on the context from the document below, answer the user's question.\n\n"
f"--- DOCUMENT CONTEXT ---\n{file_context}\n\n--- USER QUESTION ---\n{message}") if file_context else message
bot_response = get_response(context, api_history)
history = chat_history + [{"role": "user", "content": message}, {"role": "assistant", "content": bot_response}]
return "", history, file_context
def clear_all():
return [], "", None, "Status: Ready", None
# --- EVENT LISTENERS ---
attachment_btn.click(fn=None, js=js_trigger_file_click)
theme_btn.click(fn=None, js=js_theme_toggle)
file_uploader.upload(process_file, inputs=[file_uploader, chatbot], outputs=[status_display, file_context_state, chatbot])
send_btn.click(respond, inputs=[msg_box, chatbot, memory_switch, file_context_state], outputs=[msg_box, chatbot, file_context_state])
msg_box.submit(respond, inputs=[msg_box, chatbot, memory_switch, file_context_state], outputs=[msg_box, chatbot, file_context_state])
clear_btn.click(clear_all, inputs=[], outputs=[chatbot, msg_box, file_context_state, status_display, file_uploader])
gr.HTML(f"""<div id="footer">...</div>""")
if __name__ == "__main__":
caramel_ai.launch() |