Spaces:
Sleeping
Sleeping
| import os | |
| import base64 | |
| from groq import Groq | |
| import gradio as gr | |
| # -- Groq Client Setup for Text Chats | |
| def get_response(message, history): | |
| client = Groq(api_key=os.environ.get("GROQ_API_KEY")) | |
| # System prompt | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": ( | |
| "You are a UX Ops assistant. Help the design team improve processes. You can:\n" | |
| "- Collect feedback by topic\n" | |
| "- Summarize research transcripts\n" | |
| "- Assist with dev handoff checklists\n" | |
| "- Ask follow-up questions when needed" | |
| ) | |
| } | |
| ] | |
| # Clean Gradio history | |
| clean_history = [ | |
| {"role": turn["role"], "content": turn["content"]} | |
| for turn in history | |
| if isinstance(turn, dict) and "role" in turn and "content" in turn | |
| ] | |
| messages.extend(clean_history) | |
| # Append new user message | |
| messages.append({"role": "user", "content": message}) | |
| # Call the API | |
| chat_completion = client.chat.completions.create( | |
| messages=messages, | |
| model="meta-llama/llama-4-scout-17b-16e-instruct" | |
| ) | |
| return chat_completion.choices[0].message.content | |
| # -- Other Handlers | |
| def summarize_file(file): | |
| with open(file.name, "r") as f: | |
| content = f.read() | |
| return get_response(f"Summarize this user interview:\n{content}", []) | |
| def validate_handoff(checked_items): | |
| msg = "Here’s the developer handoff readiness:\n" | |
| status = [] | |
| status.append("✅ Components used from design system" if "components" in checked_items else "⚠️ Components not confirmed") | |
| status.append("✅ Developer notes added" if "notes" in checked_items else "⚠️ Notes missing") | |
| status.append("✅ Dev links and specs included" if "links" in checked_items else "⚠️ Links to specs missing") | |
| return "\n".join([msg] + status) | |
| def structure_feedback(layout, copy, interaction): | |
| return get_response( | |
| f"Collect feedback:\n- Layout: {layout}\n- Copy: {copy}\n- Interaction: {interaction}", | |
| [] | |
| ) | |
| # -- Design Image Feedback with Multimodal Support | |
| def provide_design_feedback(image_path): | |
| # Encode image to Data URL | |
| with open(image_path, "rb") as img_f: | |
| encoded = base64.b64encode(img_f.read()).decode("utf-8") | |
| ext = os.path.splitext(image_path)[1].lstrip(".").lower() | |
| data_url = f"data:image/{ext};base64,{encoded}" | |
| # Multimodal user message | |
| user_content = [ | |
| {"type": "text", "text": ( | |
| "Audit the UX of this design—provide feedback on hierarchy, color, typography, " | |
| "accessibility, and usability." | |
| )}, | |
| {"type": "image_url", "image_url": {"url": data_url}} | |
| ] | |
| # Build messages | |
| client = Groq(api_key=os.environ.get("GROQ_API_KEY")) | |
| messages = [ | |
| {"role": "system", "content": "You are a UX Ops assistant. Give actionable, concise design feedback."}, | |
| {"role": "user", "content": user_content} | |
| ] | |
| # Call Groq multimodal completion | |
| chat_completion = client.chat.completions.create( | |
| model="meta-llama/llama-4-maverick-17b-128e-instruct", | |
| messages=messages, | |
| temperature=1.0, | |
| max_completion_tokens=1024, | |
| top_p=1.0 | |
| ) | |
| return chat_completion.choices[0].message.content | |
| # -- Main App UI | |
| with gr.Blocks(title="UX Ops Assistant") as demo: | |
| gr.Markdown("## 🎯 UX Design Operations Dashboard", elem_classes="centered") | |
| # Chat Tab | |
| with gr.Tab("🧠 Ask Assistant"): | |
| chatbot = gr.Chatbot(type="messages", height=400) | |
| user_input = gr.Textbox(placeholder="Ask about UX process, feedback, etc.") | |
| def submit_chat(msg, history): | |
| reply = get_response(msg, history) | |
| new_history = history + [ | |
| {"role": "user", "content": msg}, | |
| {"role": "assistant", "content": reply} | |
| ] | |
| return "", new_history | |
| user_input.submit( | |
| fn=submit_chat, | |
| inputs=[user_input, chatbot], | |
| outputs=[user_input, chatbot] | |
| ) | |
| # Research Upload Tab | |
| with gr.Tab("📂 Upload Research"): | |
| file_input = gr.File(label="Upload transcript (.txt)") | |
| summary_output = gr.Textbox(label="Summary", lines=6) | |
| file_input.change(fn=summarize_file, inputs=file_input, outputs=summary_output) | |
| # Dev Handoff Checklist Tab | |
| with gr.Tab("✅ Dev Handoff Checklist"): | |
| checklist = gr.CheckboxGroup( | |
| choices=["components", "notes", "links"], | |
| label="What's included in this design?" | |
| ) | |
| validate_btn = gr.Button("Validate Handoff Readiness") | |
| result = gr.Textbox(label="Result", lines=4) | |
| validate_btn.click(fn=validate_handoff, inputs=checklist, outputs=result) | |
| # Feedback Organization Tab | |
| with gr.Tab("✏️ Collect Design Feedback"): | |
| layout_fb = gr.Textbox(label="Layout") | |
| copy_fb = gr.Textbox(label="Copy/Wording") | |
| interaction_fb = gr.Textbox(label="Interactions") | |
| fb_btn = gr.Button("Organize Feedback") | |
| fb_output = gr.Textbox(label="Organized Feedback", lines=6) | |
| fb_btn.click( | |
| fn=structure_feedback, | |
| inputs=[layout_fb, copy_fb, interaction_fb], | |
| outputs=fb_output | |
| ) | |
| # Design Image Feedback Tab | |
| with gr.Tab("🖼️ Upload Design Feedback"): | |
| design_image = gr.Image(type="filepath", label="Upload Design (JPG, PNG)") | |
| image_preview = gr.Image(interactive=False, label="Preview") | |
| feedback_btn2 = gr.Button("Get Design Feedback") | |
| design_feedback_output = gr.Textbox(label="Design Feedback", lines=10) | |
| def display_and_feedback(image_path): | |
| preview = image_path | |
| feedback = provide_design_feedback(image_path) | |
| return preview, feedback | |
| feedback_btn2.click( | |
| fn=display_and_feedback, | |
| inputs=design_image, | |
| outputs=[image_preview, design_feedback_output] | |
| ) | |
| demo.launch() | |