spandana30 commited on
Commit
50e0854
Β·
verified Β·
1 Parent(s): 9ccfc13

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -155
app.py CHANGED
@@ -1,185 +1,172 @@
1
  import streamlit as st
2
  import os
3
  import time
4
- import gc
5
- import torch
6
- from transformers import AutoTokenizer, AutoModelForCausalLM
7
- from peft import PeftModel
8
  from typing import Dict, List, TypedDict
9
  from langgraph.graph import StateGraph, END
 
10
 
11
- HF_TOKEN = os.getenv("HF_TOKEN")
12
-
13
- AGENT_MODEL_CONFIG = {
14
- "product_manager": {
15
- "base_id": "unsloth/gemma-3-1b-it",
16
- "adapter_id": "spandana30/project-manager-gemma"
17
- },
18
- "project_manager": {
19
- "base_id": "unsloth/gemma-3-1b-it",
20
- "adapter_id": "spandana30/project-manager-gemma"
21
- },
22
- "software_engineer": {
23
- "base_id": "unsloth/gemma-3-1b-it",
24
- "adapter_id": "spandana30/project-manager-gemma"
25
- },
26
- "qa_engineer": {
27
- "base_id": "unsloth/gemma-3-1b-it",
28
- "adapter_id": "spandana30/project-manager-gemma"
29
- }
30
- }
31
-
32
- @st.cache_resource
33
- def load_agent_model(base_id, adapter_id):
34
- base_model = AutoModelForCausalLM.from_pretrained(
35
- base_id,
36
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
37
- device_map="auto" if torch.cuda.is_available() else None,
38
- token=HF_TOKEN
39
- )
40
- model = PeftModel.from_pretrained(base_model, adapter_id, token=HF_TOKEN)
41
- tokenizer = AutoTokenizer.from_pretrained(adapter_id, token=HF_TOKEN)
42
- return model.eval(), tokenizer
43
-
44
- def call_model(prompt: str, model, tokenizer) -> str:
45
- inputs = tokenizer(prompt, return_tensors="pt", truncation=True).to(model.device)
46
- outputs = model.generate(
47
- **inputs,
48
- max_new_tokens=512,
49
- do_sample=False,
50
- temperature=0.3
51
- )
52
- return tokenizer.decode(outputs[0], skip_special_tokens=True)
53
 
54
  class AgentState(TypedDict):
55
  messages: List[Dict[str, str]]
 
56
  html: str
57
- refined_request: str
58
- final_prompt: str
59
  feedback: str
60
  iteration: int
61
  done: bool
62
  timings: Dict[str, float]
63
 
64
- def agent(template: str, state: AgentState, agent_key: str, timing_label: str):
65
- st.write(f'πŸ›  Running agent: {agent_key}')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  start = time.time()
67
- model, tokenizer = load_agent_model(**AGENT_MODEL_CONFIG[agent_key])
68
-
69
- latest_input = (
70
- state.get("final_prompt")
71
- or state.get("refined_request")
72
- or state["messages"][-1]["content"]
73
- )
74
- prompt = template.format(user_input=latest_input, html=state.get("html", ""), final_prompt=state.get("final_prompt", ""))
75
- st.write(f'πŸ“€ Prompt for {agent_key}:', prompt)
76
-
77
- response = call_model(prompt, model, tokenizer)
78
- st.write(f'πŸ“₯ Response from {agent_key}:', response[:500])
79
-
80
- state["messages"].append({"role": agent_key, "content": response})
81
- state["timings"][timing_label] = time.time() - start
82
- gc.collect()
83
- return response
84
-
85
- PROMPTS = {
86
- "product_manager": (
87
- "You are a Product Manager. Your role is to gather and prioritize user requirements "
88
- "to ensure the project aligns with business goals. "
89
- "Take the user's input and rewrite it as a clear, well-scoped requirement. "
90
- "**Do not generate any code or implementation details.**\n\n"
91
- "User input:\n{user_input}"
92
- ),
93
- "project_manager": (
94
- "You are a Project Manager. Based on the refined requirement below, outline a realistic and actionable "
95
- "design specification. Include necessary UI components and their functionality, but **do not generate code**. "
96
- "Your goal is to organize the work in a way that supports efficient development.\n\n"
97
- "Refined requirement:\n{user_input}"
98
- ),
99
- "software_engineer": (
100
- "You are a Software Engineer. Based on the design specification below, generate a complete HTML page "
101
- "with embedded CSS. The output should include a DOCTYPE declaration, semantic structure, and responsive layout. "
102
- "**Only output the HTML code.**\n\nDesign spec:\n{final_prompt}"
103
- ),
104
- "qa_engineer": (
105
- "You are a QA Engineer. Your responsibility is to test and evaluate the HTML below for correctness, responsiveness, "
106
- "and quality. Provide clear feedback on any issues you find. If everything looks perfect, respond with 'APPROVED'.\n\n"
107
- "HTML code:\n{html}"
108
- )
109
- }
110
-
111
- def generate_ui(user_prompt: str, max_iter: int):
112
- state: AgentState = {
113
- "messages": [{"role": "user", "content": user_prompt}],
114
- "html": "",
115
- "refined_request": "",
116
- "final_prompt": "",
117
- "feedback": "",
118
- "iteration": 0,
119
- "done": False,
120
- "timings": {}
121
- }
122
 
123
  workflow = StateGraph(AgentState)
124
-
125
- workflow.add_node("product_manager", lambda s: {
126
- "messages": s["messages"] + [{
127
- "role": "product_manager",
128
- "content": (pm := agent(PROMPTS["product_manager"], s, "product_manager", "product_manager"))
129
- }],
130
- "refined_request": pm
131
- })
132
-
133
- workflow.add_node("project_manager", lambda s: {
134
- "messages": s["messages"] + [{
135
- "role": "project_manager",
136
- "content": (pr := agent(PROMPTS["project_manager"], s, "project_manager", "project_manager"))
137
- }],
138
- "final_prompt": pr
139
- })
140
-
141
- workflow.add_node("software_engineer", lambda s: {
142
- "html": (html := agent(PROMPTS["software_engineer"], s, "software_engineer", "software_engineer")),
143
- "messages": s["messages"] + [{"role": "software_engineer", "content": html}]
144
- })
145
-
146
- def qa_fn(s):
147
- feedback = agent(PROMPTS["qa_engineer"], s, "qa_engineer", "qa_engineer")
148
- done = "APPROVED" in feedback or s["iteration"] >= max_iter
149
- return {
150
- "feedback": feedback,
151
- "done": done,
152
- "iteration": s["iteration"] + 1,
153
- "messages": s["messages"] + [{"role": "qa_engineer", "content": feedback}]
154
- }
155
-
156
- workflow.add_node("qa_engineer", qa_fn)
157
 
158
  workflow.add_edge("product_manager", "project_manager")
159
- workflow.add_edge("project_manager", "software_engineer")
160
- workflow.add_edge("software_engineer", "qa_engineer")
161
- workflow.add_conditional_edges("qa_engineer", lambda s: END if s["done"] else "software_engineer")
 
162
  workflow.set_entry_point("product_manager")
163
 
164
  app = workflow.compile()
 
165
  final_state = app.invoke(state)
166
- return final_state
167
 
168
  def main():
169
- st.set_page_config(page_title="Multi-Agent UI Generator", layout="wide")
170
- st.title("πŸ€– Multi-Agent Collaboration (Gemma Only)")
171
- max_iter = st.sidebar.slider("Max QA Iterations", 1, 5, 2)
172
- prompt = st.text_area("Describe your UI:", "A landing page for a coffee shop with a hero image, menu, and contact form.", height=150)
 
 
 
173
  if st.button("πŸš€ Generate UI"):
174
  with st.spinner("Agents working..."):
175
- final = generate_ui(prompt, max_iter)
176
- st.success("βœ… UI Generated")
177
- st.write("🧠 Final state:", final)
178
- st.subheader("πŸ” Output HTML")
179
- st.components.v1.html(final["html"], height=600, scrolling=True)
180
- st.subheader("🧠 Agent Messages")
181
- for msg in final["messages"]:
182
- st.markdown(f"**{msg['role'].title()}**:\n```\n{msg['content']}\n```")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  if __name__ == "__main__":
185
- main()
 
1
  import streamlit as st
2
  import os
3
  import time
4
+ import base64
 
 
 
5
  from typing import Dict, List, TypedDict
6
  from langgraph.graph import StateGraph, END
7
+ from huggingface_hub import InferenceClient
8
 
9
+ client = InferenceClient(
10
+ model="mistralai/Mistral-7B-Instruct-v0.2",
11
+ token=st.secrets["HF_TOKEN"]
12
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  class AgentState(TypedDict):
15
  messages: List[Dict[str, str]]
16
+ design_specs: str
17
  html: str
18
+ css: str
 
19
  feedback: str
20
  iteration: int
21
  done: bool
22
  timings: Dict[str, float]
23
 
24
+ PRODUCT_MANAGER_PROMPT = """You're a product manager. Given the user request:
25
+ {user_request}
26
+ Break it down into clear features and priorities."""
27
+
28
+ PROJECT_MANAGER_PROMPT = """You're a project manager. Based on these features:
29
+ {features}
30
+ Draft a quick development plan with key tasks and timeline."""
31
+
32
+ ARCHITECT_PROMPT = """You're a software architect. Create design specs for:
33
+ {user_request}
34
+ Include:
35
+ 1. Color palette (primary, secondary, accent)
36
+ 2. Font choices
37
+ 3. Layout structure
38
+ 4. Component styles
39
+ Don't write code - just design guidance."""
40
+
41
+ ENGINEER_PROMPT = """Create a complete HTML page with embedded CSS for:
42
+ {design_specs}
43
+ Requirements:
44
+ 1. Full HTML document with <!DOCTYPE>
45
+ 2. CSS inside <style> tags in head
46
+ 3. Mobile-responsive
47
+ 4. Semantic HTML
48
+ 5. Ready-to-use (will work when saved as .html)
49
+ Output JUST the complete HTML file content:"""
50
+
51
+ QA_PROMPT = """Review this website:
52
+ {html}
53
+ Check for:
54
+ 1. Visual quality
55
+ 2. Responsiveness
56
+ 3. Functionality
57
+ Reply "APPROVED" if perfect, or suggest improvements."""
58
+
59
+ def call_model(prompt: str, max_retries=3) -> str:
60
+ for attempt in range(max_retries):
61
+ try:
62
+ return client.text_generation(
63
+ prompt,
64
+ max_new_tokens=3000,
65
+ temperature=0.3,
66
+ return_full_text=False
67
+ )
68
+ except Exception as e:
69
+ st.error(f"Model call failed (attempt {attempt+1}): {e}")
70
+ time.sleep(2)
71
+ return "<html><body><h1>Error generating UI</h1></body></html>"
72
+
73
+ def time_agent(agent_func, state: AgentState, label: str):
74
  start = time.time()
75
+ result = agent_func(state)
76
+ duration = time.time() - start
77
+ result["timings"] = state["timings"]
78
+ result["timings"][label] = duration
79
+ return result
80
+
81
+ def product_manager_agent(state: AgentState):
82
+ features = call_model(PRODUCT_MANAGER_PROMPT.format(user_request=state["messages"][-1]["content"]))
83
+ return {"messages": state["messages"] + [{"role": "product_manager", "content": features}]}
84
+
85
+ def project_manager_agent(state: AgentState):
86
+ features_msg = next((m["content"] for m in state["messages"] if m["role"] == "product_manager"), "")
87
+ plan = call_model(PROJECT_MANAGER_PROMPT.format(features=features_msg))
88
+ return {"messages": state["messages"] + [{"role": "project_manager", "content": plan}]}
89
+
90
+ def software_architect_agent(state: AgentState):
91
+ specs = call_model(ARCHITECT_PROMPT.format(user_request=state["messages"][-1]["content"]))
92
+ return {"design_specs": specs, "messages": state["messages"] + [{"role": "software_architect", "content": specs}]}
93
+
94
+ def engineer_agent(state: AgentState):
95
+ html = call_model(ENGINEER_PROMPT.format(design_specs=state["design_specs"]))
96
+ if not html.strip().startswith("<!DOCTYPE"):
97
+ html = f"""<!DOCTYPE html>
98
+ <html><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>
99
+ <title>Generated UI</title></head><body>{html}</body></html>"""
100
+ return {"html": html, "messages": state["messages"] + [{"role": "software_engineer", "content": html}]}
101
+
102
+ def qa_agent(state: AgentState, max_iter: int):
103
+ feedback = call_model(QA_PROMPT.format(html=state["html"]))
104
+ done = "APPROVED" in feedback or state["iteration"] >= max_iter
105
+ return {"feedback": feedback, "done": done, "iteration": state["iteration"] + 1,
106
+ "messages": state["messages"] + [{"role": "qa", "content": feedback}]}
107
+
108
+ def generate_ui(user_request: str, max_iter: int):
109
+ state = {"messages": [{"role": "user", "content": user_request}], "design_specs": "", "html": "",
110
+ "css": "", "feedback": "", "iteration": 0, "done": False, "timings": {}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  workflow = StateGraph(AgentState)
113
+ workflow.add_node("product_manager", lambda s: time_agent(product_manager_agent, s, "product_manager"))
114
+ workflow.add_node("project_manager", lambda s: time_agent(project_manager_agent, s, "project_manager"))
115
+ workflow.add_node("software_architect", lambda s: time_agent(software_architect_agent, s, "software_architect"))
116
+ workflow.add_node("software_engineer", lambda s: time_agent(engineer_agent, s, "software_engineer"))
117
+ workflow.add_node("qa", lambda s: time_agent(lambda x: qa_agent(x, max_iter), s, "qa"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  workflow.add_edge("product_manager", "project_manager")
120
+ workflow.add_edge("project_manager", "software_architect")
121
+ workflow.add_edge("software_architect", "software_engineer")
122
+ workflow.add_edge("software_engineer", "qa")
123
+ workflow.add_conditional_edges("qa", lambda s: END if s["done"] else "software_engineer")
124
  workflow.set_entry_point("product_manager")
125
 
126
  app = workflow.compile()
127
+ total_start = time.time()
128
  final_state = app.invoke(state)
129
+ return final_state["html"], final_state, time.time() - total_start
130
 
131
  def main():
132
+ st.set_page_config(page_title="Multi-Agent Collaboration", layout="wide")
133
+ st.title("🀝 Multi-Agent Collaboration")
134
+ with st.sidebar:
135
+ max_iter = st.slider("Max QA Iterations", 1, 5, 2)
136
+
137
+ prompt = st.text_area("πŸ“ Describe the UI you want:", "A coffee shop landing page with hero, menu, and contact form.", height=150)
138
+
139
  if st.button("πŸš€ Generate UI"):
140
  with st.spinner("Agents working..."):
141
+ html, final_state, total_time = generate_ui(prompt, max_iter)
142
+ st.success("βœ… UI Generated Successfully!")
143
+ st.components.v1.html(html, height=600, scrolling=True)
144
+
145
+ st.subheader("πŸ“… Download HTML")
146
+ b64 = base64.b64encode(html.encode()).decode()
147
+ st.markdown(f'<a href="data:file/html;base64,{b64}" download="ui.html">Download HTML</a>', unsafe_allow_html=True)
148
+
149
+ st.subheader("🧐 Agent Communication Log")
150
+ history_text = ""
151
+ for msg in final_state["messages"]:
152
+ role = msg["role"].replace("_", " ").title()
153
+ content = msg["content"]
154
+ history_text += f"---\n{role}:\n{content}\n\n"
155
+ st.text_area("Agent Dialogue", value=history_text, height=300)
156
+
157
+ b64_hist = base64.b64encode(history_text.encode()).decode()
158
+ st.markdown(
159
+ f'<a href="data:file/txt;base64,{b64_hist}" download="agent_communication.txt" '
160
+ 'style="padding: 0.4em 1em; background: #4CAF50; color: white; border-radius: 0.3em; text-decoration: none;">'
161
+ 'πŸ“… Download Communication Log</a>',
162
+ unsafe_allow_html=True
163
+ )
164
+
165
+ st.subheader("πŸ“Š Performance")
166
+ st.write(f"⏱️ Total Time: {total_time:.2f} seconds")
167
+ st.write(f"πŸ” Iterations: {final_state['iteration']}")
168
+ for stage in ["product_manager", "project_manager", "software_architect", "software_engineer", "qa"]:
169
+ st.write(f"πŸ€– {stage.title().replace('_', ' ')} Time: {final_state['timings'].get(stage, 0):.2f}s")
170
 
171
  if __name__ == "__main__":
172
+ main()