spandana30 commited on
Commit
a305086
Β·
verified Β·
1 Parent(s): 476140f

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -0
app.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import streamlit as st
3
+ import os
4
+ import time
5
+ import base64
6
+ from typing import Dict, List, TypedDict
7
+ from langgraph.graph import StateGraph, END
8
+ from huggingface_hub import InferenceClient
9
+
10
+ # Use Mistral model only
11
+ client = InferenceClient(
12
+ model="mistralai/Mistral-7B-Instruct-v0.2",
13
+ token=st.secrets["HF_TOKEN"]
14
+ )
15
+
16
+ class AgentState(TypedDict):
17
+ messages: List[Dict[str, str]]
18
+ design_specs: str
19
+ html: str
20
+ css: str
21
+ feedback: str
22
+ iteration: int
23
+ done: bool
24
+ timings: Dict[str, float]
25
+
26
+ DESIGNER_PROMPT = """You're a UI designer. Create design specs for:
27
+ {user_request}
28
+ Include:
29
+ 1. Color palette (primary, secondary, accent)
30
+ 2. Font choices
31
+ 3. Layout structure
32
+ 4. Component styles
33
+ Don't write code - just design guidance."""
34
+
35
+ ENGINEER_PROMPT = """Create a complete HTML page with embedded CSS for:
36
+ {design_specs}
37
+ Requirements:
38
+ 1. Full HTML document with <!DOCTYPE>
39
+ 2. CSS inside <style> tags in head
40
+ 3. Mobile-responsive
41
+ 4. Semantic HTML
42
+ 5. Ready-to-use (will work when saved as .html)
43
+ Output JUST the complete HTML file content:"""
44
+
45
+ QA_PROMPT = """Review this website:
46
+ {html}
47
+ Check for:
48
+ 1. Visual quality
49
+ 2. Responsiveness
50
+ 3. Functionality
51
+ Reply "APPROVED" if perfect, or suggest improvements."""
52
+
53
+ def time_agent(agent_func, state: AgentState, label: str):
54
+ start = time.time()
55
+ result = agent_func(state)
56
+ duration = time.time() - start
57
+ result["timings"] = state["timings"]
58
+ result["timings"][label] = duration
59
+ return result
60
+
61
+ def designer_agent(state: AgentState):
62
+ specs = call_model(DESIGNER_PROMPT.format(user_request=state["messages"][-1]["content"]))
63
+ return {"design_specs": specs, "messages": state["messages"] + [{"role": "designer", "content": specs}]}
64
+
65
+ def engineer_agent(state: AgentState):
66
+ html = call_model(ENGINEER_PROMPT.format(design_specs=state["design_specs"]))
67
+ if not html.strip().startswith("<!DOCTYPE"):
68
+ html = f"""<!DOCTYPE html>
69
+ <html><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>
70
+ <title>Generated UI</title></head><body>{html}</body></html>"""
71
+ return {"html": html, "messages": state["messages"] + [{"role": "software_engineer", "content": html}]}
72
+
73
+ def qa_agent(state: AgentState, max_iter: int):
74
+ feedback = call_model(QA_PROMPT.format(html=state["html"]))
75
+ done = "APPROVED" in feedback or state["iteration"] >= max_iter
76
+ return {"feedback": feedback, "done": done, "iteration": state["iteration"] + 1,
77
+ "messages": state["messages"] + [{"role": "qa", "content": feedback}]}
78
+
79
+ def call_model(prompt: str, max_retries=3) -> str:
80
+ for attempt in range(max_retries):
81
+ try:
82
+ return client.text_generation(
83
+ prompt,
84
+ max_new_tokens=3000,
85
+ temperature=0.3,
86
+ return_full_text=False
87
+ )
88
+ except Exception as e:
89
+ st.error(f"Model call failed (attempt {attempt+1}): {e}")
90
+ time.sleep(2)
91
+ return "<html><body><h1>Error generating UI</h1></body></html>"
92
+
93
+ def generate_ui(user_request: str, max_iter: int):
94
+ state = {"messages": [{"role": "user", "content": user_request}], "design_specs": "", "html": "",
95
+ "css": "", "feedback": "", "iteration": 0, "done": False, "timings": {}}
96
+
97
+ workflow = StateGraph(AgentState)
98
+ workflow.add_node("designer", lambda s: time_agent(designer_agent, s, "designer"))
99
+ workflow.add_node("software_engineer", lambda s: time_agent(engineer_agent, s, "software_engineer"))
100
+ workflow.add_node("qa", lambda s: time_agent(lambda x: qa_agent(x, max_iter), s, "qa"))
101
+ workflow.add_edge("designer", "software_engineer")
102
+ workflow.add_edge("software_engineer", "qa")
103
+ workflow.add_conditional_edges("qa", lambda s: END if s["done"] else "software_engineer")
104
+ workflow.set_entry_point("designer")
105
+ app = workflow.compile()
106
+ total_start = time.time()
107
+ final_state = app.invoke(state)
108
+ return final_state["html"], final_state, time.time() - total_start
109
+
110
+ def main():
111
+ st.set_page_config(page_title="Multi-Agent Collaboration", layout="wide")
112
+ st.title("🀝 Multi-Agent Collaboration (Mistral)")
113
+ with st.sidebar:
114
+ max_iter = st.slider("Max QA Iterations", 1, 5, 2)
115
+
116
+ prompt = st.text_area("πŸ“ Describe the UI you want:", "A coffee shop landing page with hero, menu, and contact form.", height=150)
117
+
118
+ if st.button("πŸš€ Generate UI"):
119
+ with st.spinner("Agents working..."):
120
+ html, final_state, total_time = generate_ui(prompt, max_iter)
121
+ st.success("βœ… UI Generated Successfully!")
122
+ st.components.v1.html(html, height=600, scrolling=True)
123
+
124
+ st.subheader("πŸ“₯ Download HTML")
125
+ b64 = base64.b64encode(html.encode()).decode()
126
+ st.markdown(f'<a href="data:file/html;base64,{b64}" download="ui.html">Download HTML</a>', unsafe_allow_html=True)
127
+
128
+ st.subheader("🧠 Agent Log")
129
+ log = "".join([f"---\n{m['role'].title()}:\n{m['content']}\n\n" for m in final_state["messages"]])
130
+ st.text_area("Agent Communication", value=log, height=300)
131
+
132
+ st.subheader("πŸ“Š Performance")
133
+ st.write(f"⏱️ Total Time: {total_time:.2f} seconds")
134
+ st.write(f"πŸ” Iterations: {final_state['iteration']}")
135
+ for stage in ["designer", "software_engineer", "qa"]:
136
+ st.write(f"🧩 {stage.title().replace('_', ' ')} Time: {final_state['timings'].get(stage, 0):.2f}s")
137
+
138
+ if __name__ == "__main__":
139
+ main()