Anshini commited on
Commit
cae1f36
Β·
verified Β·
1 Parent(s): fb68cce

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +246 -0
app.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from typing import TypedDict, Optional
3
+ from langgraph.graph import StateGraph, END
4
+ from together import Together
5
+ import os
6
+ import re
7
+
8
+ # Initialize Together client
9
+ client = Together(api_key="44a45a44e10d7b5298")
10
+
11
+ def llm_invoke(prompt: str) -> str:
12
+ """Call Together LLM with consistent config"""
13
+ try:
14
+ response = client.completions.create(
15
+ model="mistralai/Mixtral-8x7B-Instruct-v0.1",
16
+ prompt=prompt,
17
+ max_tokens=1024,
18
+ temperature=0.2,
19
+ stop=["</s>"]
20
+ )
21
+ return response.choices[0].text.strip()
22
+ except Exception as e:
23
+ st.error(f"LLM API Error: {str(e)}")
24
+ return "Error in LLM response"
25
+
26
+ # State Definition
27
+ class AgentState(TypedDict):
28
+ domain: str
29
+ goal: str
30
+ follow_up_questions: Optional[str]
31
+ follow_up_answers: Optional[str]
32
+ agents_needed: Optional[str]
33
+ code_generator: Optional[str]
34
+ explanation: Optional[str]
35
+
36
+ # Agent Functions
37
+ def collect_domain_goal(state: AgentState) -> AgentState:
38
+ """Simply pass through the domain and goal"""
39
+ return state
40
+
41
+ def needs_follow_up(goal: str) -> bool:
42
+ """Check if extra context is needed for files/data"""
43
+ prompt = f"""
44
+ Does this system goal require clarifying questions about input data, file structure, or formats?
45
+
46
+ Goal: {goal}
47
+
48
+ Respond only 'yes' or 'no'.
49
+ """
50
+ response = llm_invoke(prompt).strip().lower()
51
+ return response == "yes"
52
+
53
+ def ask_follow_up_questions(state: AgentState) -> AgentState:
54
+ """Generate follow-up questions if needed"""
55
+ if needs_follow_up(state["goal"]):
56
+ prompt = f"""
57
+ Based on the domain: {state['domain']} and goal: {state['goal']},
58
+ list 2–3 critical follow-up questions about:
59
+ - Data/file formats (CSV, JSON, etc.)
60
+ - Column names or structure
61
+ - Required reference files (terms, conditions, etc.)
62
+ - Any APIs or databases used
63
+
64
+ Return in bullet-point format.
65
+ """
66
+ state["follow_up_questions"] = llm_invoke(prompt)
67
+ else:
68
+ state["follow_up_questions"] = "No questions needed"
69
+ return state
70
+
71
+ def identify_agents(state: AgentState) -> AgentState:
72
+ """Identify the agents needed for the system"""
73
+ prompt = f"""
74
+ Domain: {state['domain']}
75
+ Goal: {state['goal']}
76
+ Context: {state.get('follow_up_answers', 'No additional info')}
77
+
78
+ List the agents needed in an agentic system. For each:
79
+ - Name
80
+ - Purpose
81
+ - What it processes or validates
82
+
83
+ Return as a clean markdown list.
84
+ """
85
+ state["agents_needed"] = llm_invoke(prompt)
86
+ return state
87
+
88
+ def generate_code(state: AgentState) -> AgentState:
89
+ """Generate the complete LangGraph application code"""
90
+ prompt = f"""
91
+ You are an expert Python engineer. Based on:
92
+ - Domain: {state['domain']}
93
+ - Goal: {state['goal']}
94
+ - Follow-up Answers: {state.get('follow_up_answers', 'None')}
95
+ - Agents Needed: {state.get('agents_needed', 'None')}
96
+
97
+ Generate a full working LangGraph app using this structure:
98
+ 1. Imports: streamlit, langgraph, together, re, os, csv if needed
99
+ 2. State: TypedDict
100
+ 3. One clean agent function per node
101
+ 4. LangGraph construction with node/edge logic
102
+ 5. Together LLM call helper
103
+ 6. Streamlit UI to collect user input and run graph
104
+ 7. Output final result cleanly
105
+
106
+ Match code style and flow of our health advisory example. Avoid AgentState subclasses. Ensure the system is executable.
107
+ """
108
+ state["code_generator"] = llm_invoke(prompt)
109
+ return state
110
+
111
+ def explain_code(state: AgentState) -> AgentState:
112
+ """Generate explanation for the generated code"""
113
+ if state.get("code_generator"):
114
+ prompt = f"Explain this code simply and clearly:\n\n{state['code_generator']}"
115
+ state["explanation"] = llm_invoke(prompt)
116
+ else:
117
+ state["explanation"] = "No code to explain"
118
+ return state
119
+
120
+ # Graph Construction
121
+ def create_graph():
122
+ """Create and return the compiled graph"""
123
+ graph = StateGraph(AgentState)
124
+
125
+ # Add nodes
126
+ graph.add_node("collect_domain_goal", collect_domain_goal)
127
+ graph.add_node("ask_follow_up_questions", ask_follow_up_questions)
128
+ graph.add_node("identify_agents", identify_agents)
129
+ graph.add_node("generate_code", generate_code)
130
+ graph.add_node("explain_code", explain_code)
131
+
132
+ # Set entry point
133
+ graph.set_entry_point("collect_domain_goal")
134
+
135
+ # Add edges
136
+ graph.add_edge("collect_domain_goal", "ask_follow_up_questions")
137
+ graph.add_edge("ask_follow_up_questions", "identify_agents")
138
+ graph.add_edge("identify_agents", "generate_code")
139
+ graph.add_edge("generate_code", "explain_code")
140
+ graph.add_edge("explain_code", END)
141
+
142
+ return graph.compile()
143
+
144
+ # Initialize the app
145
+ app = create_graph()
146
+
147
+ # Streamlit Interface
148
+ def main():
149
+ st.set_page_config(page_title="Agentic Code Generator", layout="centered")
150
+ st.title("πŸ€– Auto-Build LangGraph App")
151
+
152
+ st.markdown("Enter your **application domain** and a **clear goal** (what you want the app to do).")
153
+
154
+ # Input fields
155
+ domain = st.text_input("Domain (e.g. finance, warranty claims, medical):")
156
+ goal = st.text_area("System Goal (be detailed, include what data is needed):", height=150)
157
+
158
+ # Initialize session state
159
+ if "state" not in st.session_state:
160
+ st.session_state.state = {
161
+ "domain": "",
162
+ "goal": "",
163
+ "follow_up_questions": None,
164
+ "follow_up_answers": None,
165
+ "agents_needed": None,
166
+ "code_generator": None,
167
+ "explanation": None
168
+ }
169
+
170
+ if "step" not in st.session_state:
171
+ st.session_state.step = "initial"
172
+
173
+ # Generate button
174
+ if st.button("πŸš€ Generate Agentic App") and domain and goal:
175
+ st.session_state.state.update({"domain": domain, "goal": goal})
176
+ st.session_state.step = "processing"
177
+
178
+ with st.spinner("Thinking like an architect..."):
179
+ try:
180
+ result = app.invoke(st.session_state.state)
181
+ st.session_state.state.update(result)
182
+
183
+ # Check if follow-up questions are needed
184
+ if (st.session_state.state.get("follow_up_questions") and
185
+ st.session_state.state["follow_up_questions"] != "No questions needed"):
186
+ st.session_state.step = "follow_up"
187
+ else:
188
+ st.session_state.step = "complete"
189
+
190
+ except Exception as e:
191
+ st.error(f"Error processing request: {str(e)}")
192
+ st.session_state.step = "error"
193
+
194
+ # Handle follow-up questions
195
+ if st.session_state.step == "follow_up":
196
+ st.subheader("πŸ” Follow-Up Questions")
197
+ if st.session_state.state.get("follow_up_questions"):
198
+ st.markdown(st.session_state.state["follow_up_questions"])
199
+
200
+ answers = st.text_area("Your answers to the above:", height=150, key="follow_up_answers")
201
+
202
+ if st.button("Continue with those answers"):
203
+ st.session_state.state["follow_up_answers"] = answers
204
+ st.session_state.step = "processing_final"
205
+
206
+ with st.spinner("Building your LangGraph app..."):
207
+ try:
208
+ # Re-run the graph with the follow-up answers
209
+ final_result = app.invoke(st.session_state.state)
210
+ st.session_state.state.update(final_result)
211
+ st.session_state.step = "complete"
212
+ except Exception as e:
213
+ st.error(f"Error in final processing: {str(e)}")
214
+ st.session_state.step = "error"
215
+
216
+ # Display results
217
+ if st.session_state.step == "complete" and st.session_state.state.get("code_generator"):
218
+ st.subheader("🎯 Identified Agents")
219
+ if st.session_state.state.get("agents_needed"):
220
+ st.markdown(st.session_state.state["agents_needed"])
221
+
222
+ st.subheader("βœ… Generated Code")
223
+ st.code(st.session_state.state["code_generator"], language="python")
224
+
225
+ st.subheader("🧠 Code Explanation")
226
+ if st.session_state.state.get("explanation"):
227
+ st.markdown(st.session_state.state["explanation"])
228
+
229
+ # Download button
230
+ if st.session_state.state.get("code_generator"):
231
+ st.download_button(
232
+ label="πŸ“₯ Download Generated Code",
233
+ data=st.session_state.state["code_generator"],
234
+ file_name="generated_langgraph_app.py",
235
+ mime="text/python"
236
+ )
237
+
238
+ # Reset button
239
+ if st.button("πŸ”„ Reset"):
240
+ st.session_state.clear()
241
+ st.experimental_rerun()
242
+
243
+ if __name__ == "__main__":
244
+ main()
245
+
246
+