ICAS03 commited on
Commit
27a6243
·
1 Parent(s): 3aca5a7

- Dynamic Rendering FIX !

Browse files
Files changed (4) hide show
  1. Project.py +30 -65
  2. app.py +69 -60
  3. event_handler.py +13 -45
  4. prompt_configs.py +1 -1
Project.py CHANGED
@@ -204,34 +204,13 @@ class Project:
204
  }
205
  )
206
 
207
- def _clean_json_response(self, text):
208
- """Helper method to clean JSON responses from LLM outputs"""
209
- # If the response contains a code block with JSON
210
- if "```json" in text:
211
- text = text.split("```json")[1].split("```")[0].strip()
212
- elif "```" in text:
213
- text = text.split("```")[1].split("```")[0].strip()
214
-
215
- # Additional cleaning for common JSON formatting issues
216
- # Remove any leading/trailing whitespace
217
- text = text.strip()
218
-
219
- # If the text starts with a markdown comment or explanation, try to find the JSON part
220
- if not text.startswith('{') and not text.startswith('['):
221
- # Look for the first occurrence of { or [
222
- json_start = min(
223
- text.find('{') if text.find('{') != -1 else float('inf'),
224
- text.find('[') if text.find('[') != -1 else float('inf')
225
- )
226
- if json_start != float('inf'):
227
- text = text[json_start:]
228
-
229
- return text
230
-
231
  ## Generate PRD and components from project details ##
232
- def generate_prd_and_components(self, progress=gr.Progress()):
233
- results = set()
234
- print("\nGenerating PRD...")
 
 
 
235
  prd_response = self.execute_prompt(
236
  "generate_prd",
237
  {
@@ -241,19 +220,18 @@ class Project:
241
 
242
  # Parse the PRD JSON response
243
  try:
244
- # Clean the JSON response first
245
- cleaned_prd = self._clean_json_response(prd_response)
246
- prd_json = json.loads(cleaned_prd)
247
  self.generated_prd = prd_json.get("detailed_breakdown", "")
248
  except json.JSONDecodeError:
249
  print("Warning: Could not parse PRD as JSON, using raw response")
250
  self.generated_prd = prd_response
251
 
252
- # Store PRD in results as a tuple
253
  results.add(("generate_prd", self.generated_prd))
 
254
 
255
  try:
256
- print("\nAnalyzing configuration with component agent...")
257
  configuration_output = self.execute_prompt(
258
  "component_agent",
259
  {
@@ -261,55 +239,42 @@ class Project:
261
  }
262
  )
263
 
264
- # Print the raw configuration output for debugging
265
- print("\nRaw configuration output:")
266
- print(configuration_output)
267
-
268
- # Store component agent output in results as a tuple
269
  results.add(("component_agent", configuration_output))
 
270
 
271
- # Try to parse configuration output
272
  try:
273
- cleaned_output = self._clean_json_response(configuration_output)
 
 
 
 
 
274
  config = json.loads(cleaned_output)
275
  selected_functions = config[0]["selected_functions"]
276
- print(f"\nSelected functions: {selected_functions}")
277
 
278
  except (json.JSONDecodeError, KeyError, IndexError) as e:
279
- print(f"Warning: Could not parse configuration output ({str(e)}),")
280
- print(f"Attempted to parse: {cleaned_output}")
281
- return results
282
 
283
  except Exception as e:
284
- print(f"Error in analyzing configuration: {str(e)}")
285
- return results
286
 
287
- # Execute each function and yield results one by one
288
- for function_name in selected_functions:
289
  try:
290
- print(f"\nExecuting {function_name}...")
291
  result = self.execute_prompt(function_name)
292
-
293
- # Clean and parse the result if it's JSON
294
- try:
295
- cleaned_result = self._clean_json_response(result)
296
- json_result = json.loads(cleaned_result)
297
- # If parsing succeeds, convert back to a formatted JSON string
298
- result = json.dumps(json_result, indent=2)
299
- except json.JSONDecodeError:
300
- # If it's not valid JSON, keep the original result
301
- pass
302
-
303
- # Store the result in the results set as a tuple
304
  results.add((function_name, result))
305
- print(f"Successfully generated result for {function_name}")
306
 
307
  except Exception as e:
308
- print(f"Error executing {function_name}: {str(e)}")
309
  continue
310
-
311
- return results
312
-
313
 
314
 
315
 
 
204
  }
205
  )
206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  ## Generate PRD and components from project details ##
208
+ def generate_prd_and_components(self, progress=gr.Progress()):
209
+ """Generate PRD and components from project details, streaming results"""
210
+ results = set()
211
+
212
+ # Generate PRD
213
+ yield "Generating PRD...", results
214
  prd_response = self.execute_prompt(
215
  "generate_prd",
216
  {
 
220
 
221
  # Parse the PRD JSON response
222
  try:
223
+ prd_json = json.loads(prd_response)
 
 
224
  self.generated_prd = prd_json.get("detailed_breakdown", "")
225
  except json.JSONDecodeError:
226
  print("Warning: Could not parse PRD as JSON, using raw response")
227
  self.generated_prd = prd_response
228
 
229
+ # Add PRD to results and yield update
230
  results.add(("generate_prd", self.generated_prd))
231
+ yield "PRD generation complete", results
232
 
233
  try:
234
+ yield "Analyzing configuration with component agent...", results
235
  configuration_output = self.execute_prompt(
236
  "component_agent",
237
  {
 
239
  }
240
  )
241
 
 
 
 
 
 
242
  results.add(("component_agent", configuration_output))
243
+ yield "Component analysis complete", results
244
 
245
+ # Parse configuration output
246
  try:
247
+ cleaned_output = configuration_output
248
+ if "```json" in cleaned_output:
249
+ cleaned_output = cleaned_output.split("```json")[1].split("```")[0].strip()
250
+ elif "```" in cleaned_output:
251
+ cleaned_output = cleaned_output.split("```")[1].split("```")[0].strip()
252
+
253
  config = json.loads(cleaned_output)
254
  selected_functions = config[0]["selected_functions"]
255
+ yield f"Selected {len(selected_functions)} components to generate", results
256
 
257
  except (json.JSONDecodeError, KeyError, IndexError) as e:
258
+ yield f"Warning: Could not parse configuration output ({str(e)})", results
259
+ return
 
260
 
261
  except Exception as e:
262
+ yield f"Error in analyzing configuration: {str(e)}", results
263
+ return
264
 
265
+ # Execute each function and stream results
266
+ for i, function_name in enumerate(selected_functions, 1):
267
  try:
268
+ yield f"Generating component {i}/{len(selected_functions)}: {function_name}...", results
269
  result = self.execute_prompt(function_name)
 
 
 
 
 
 
 
 
 
 
 
 
270
  results.add((function_name, result))
271
+ yield f"Successfully generated {function_name}", results
272
 
273
  except Exception as e:
274
+ yield f"Error executing {function_name}: {str(e)}", results
275
  continue
276
+
277
+ yield "All components generated successfully!", results
 
278
 
279
 
280
 
app.py CHANGED
@@ -2,7 +2,7 @@ from typing import Tuple
2
  import gradio as gr
3
  from Project import *
4
  from common_functions_v4 import *
5
- from event_handler import setup_all_handlers
6
  from google_drive import *
7
  from notion import *
8
  from state import state
@@ -168,9 +168,7 @@ def create_quotation_generator_section():
168
  page_notes_box = None
169
  page_save_quotation_btn = None
170
  project_name = None
171
-
172
- # Initialize generation_results at the beginning
173
- generation_results = gr.State(value=set())
174
 
175
  with gr.Tab(label="Quotation Generator"):
176
  with gr.Row():
@@ -200,6 +198,7 @@ def create_quotation_generator_section():
200
 
201
  if step not in step_outputs:
202
  step_outputs[step] = {}
 
203
 
204
  if sub_step:
205
  if sub_step not in step_outputs[step]:
@@ -215,7 +214,7 @@ def create_quotation_generator_section():
215
 
216
  # Create main step accordions
217
  for step_name, sub_steps in step_outputs.items():
218
- with gr.Accordion(step_name, open=False) :
219
  # Create button for this step
220
  try:
221
  if ' : ' in step_name:
@@ -227,63 +226,77 @@ def create_quotation_generator_section():
227
 
228
  step_buttons[step_name] = gr.Button(f"✅ Generate {button_label}")
229
 
230
- # Create a container for dynamic results inside each step accordion
231
- with gr.Column() as dynamic_results_container:
 
232
  gr.Markdown("## Generated Results")
233
-
234
- # Use gr.render to dynamically create components based on results
235
  @gr.render(inputs=[generation_results])
236
  def render_results(results):
237
  if not results:
238
- gr.Markdown("No results generated yet.")
239
- return
240
-
241
- # Iterate through results and create components for each
242
- for function_name, result in results:
243
- # Get the output name from function name
244
- output_name = function_name.replace("generate_", "")
245
-
246
- # Find the corresponding prompt config
247
- prompt_config = None
248
- for config in PROMPTS.values():
249
- if function_name in config.outputs:
250
- prompt_config = config
251
- break
252
 
253
- # Create a section for this result
254
- with gr.Group():
255
- gr.Markdown(f"### {prompt_config.description if prompt_config else function_name}")
256
-
257
- with gr.Row():
258
- with gr.Column(scale=1):
259
- # Text component
260
- gr.Textbox(
261
- value=result,
262
- label=f"{output_name} Text Output",
263
- lines=10,
264
- interactive=True,
265
- )
266
-
267
- with gr.Column(scale=1):
268
- # Markdown component
269
- gr.Markdown(
270
- value=result,
271
- show_copy_button=True,
272
- elem_classes=["scrollable-markdown"]
273
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
 
 
 
 
 
 
 
 
 
275
  with gr.Column(scale=1):
276
- with gr.Row():
277
- with gr.Column(scale=2):
278
- project_name = gr.Textbox(
279
- placeholder="Please enter a project name to be saved in Google Drive and Notion",
280
- label="Project Name",
281
- lines=1.5,
282
- interactive=True
283
- )
284
- with gr.Column(scale=1):
285
- page_upload_drive_btn = gr.Button("📁 Upload to Google Drive")
286
- page_upload_notion_btn = gr.Button("📝 Upload to Notion")
287
 
288
  # Add system prompts tab
289
  with gr.Tab(label="System Prompts"):
@@ -304,8 +317,6 @@ def create_quotation_generator_section():
304
  else:
305
  all_components[prompt_key] = components
306
 
307
- # Setup event handlers
308
- # Pass the existing generation_results to setup_all_handlers
309
  setup_all_handlers(
310
  step_buttons,
311
  all_components,
@@ -315,7 +326,7 @@ def create_quotation_generator_section():
315
  page_upload_drive_btn,
316
  page_upload_notion_btn,
317
  project_name,
318
- generation_results # Pass the generation_results here
319
  )
320
 
321
  return (all_components, step_buttons,
@@ -439,8 +450,6 @@ with gr.Blocks(title="Quotation Chatbot (with SOW)", css=custom_css) as page_int
439
  current_session_display,
440
  ]
441
  )
442
-
443
- setup_all_handlers(step_buttons, all_components, page_progress_update, quotation_cost , page_recalc_btn , page_upload_drive_btn , page_upload_notion_btn , project_name)
444
 
445
  # Call setup_event_handlers after all components are created
446
  setup_event_handlers()
 
2
  import gradio as gr
3
  from Project import *
4
  from common_functions_v4 import *
5
+ from event_handler import generate_content, setup_all_handlers
6
  from google_drive import *
7
  from notion import *
8
  from state import state
 
168
  page_notes_box = None
169
  page_save_quotation_btn = None
170
  project_name = None
171
+ generation_results = gr.State(set())
 
 
172
 
173
  with gr.Tab(label="Quotation Generator"):
174
  with gr.Row():
 
198
 
199
  if step not in step_outputs:
200
  step_outputs[step] = {}
201
+ step_outputs[step][prompt_key] = prompt_config
202
 
203
  if sub_step:
204
  if sub_step not in step_outputs[step]:
 
214
 
215
  # Create main step accordions
216
  for step_name, sub_steps in step_outputs.items():
217
+ with gr.Accordion(step_name, open=False):
218
  # Create button for this step
219
  try:
220
  if ' : ' in step_name:
 
226
 
227
  step_buttons[step_name] = gr.Button(f"✅ Generate {button_label}")
228
 
229
+ # Create a unique results container for this step
230
+ results_container = gr.Column(visible=False)
231
+ with results_container:
232
  gr.Markdown("## Generated Results")
233
+
234
+ def create_render_results(step):
235
  @gr.render(inputs=[generation_results])
236
  def render_results(results):
237
  if not results:
238
+ return gr.Markdown("No results generated yet.")
239
+
240
+ components = []
241
+ relevant_results = [
242
+ (fname, res) for fname, res in results
243
+ if PROMPTS.get(fname) and PROMPTS[fname].step == step
244
+ ]
245
+
246
+ if not relevant_results:
247
+ return gr.Markdown("No results generated for this step.")
248
+
249
+ for function_name, result in relevant_results:
250
+ prompt_config = PROMPTS.get(function_name)
 
251
 
252
+ components.extend([
253
+ gr.Group([
254
+ gr.Markdown(f"### {prompt_config.description if prompt_config else function_name}"),
255
+ gr.Row([
256
+ gr.Column([
257
+ gr.Textbox(
258
+ value=result,
259
+ label=f"{function_name} Text Output",
260
+ lines=10,
261
+ interactive=True
262
+ )
263
+ ], scale=1),
264
+ gr.Column([
265
+ gr.Markdown(
266
+ value=result,
267
+ show_copy_button=True,
268
+ elem_classes=["scrollable-markdown"]
269
+ )
270
+ ], scale=1)
271
+ ])
272
+ ])
273
+ ])
274
+
275
+ return components
276
+
277
+ return render_results
278
+
279
+ step_buttons[str(step_name)].click(
280
+ fn=generate_content,
281
+ outputs=[page_progress_update, generation_results],
282
+ queue=True
283
+ ).then(
284
+ fn=create_render_results(step_name),
285
+ inputs=[generation_results]
286
+ )
287
 
288
+ with gr.Column(scale=1):
289
+ with gr.Row():
290
+ with gr.Column(scale=2):
291
+ project_name = gr.Textbox(
292
+ placeholder="Please enter a project name to be saved in Google Drive and Notion",
293
+ label="Project Name",
294
+ lines=1.5,
295
+ interactive=True
296
+ )
297
  with gr.Column(scale=1):
298
+ page_upload_drive_btn = gr.Button("📁 Upload to Google Drive")
299
+ page_upload_notion_btn = gr.Button("📝 Upload to Notion")
 
 
 
 
 
 
 
 
 
300
 
301
  # Add system prompts tab
302
  with gr.Tab(label="System Prompts"):
 
317
  else:
318
  all_components[prompt_key] = components
319
 
 
 
320
  setup_all_handlers(
321
  step_buttons,
322
  all_components,
 
326
  page_upload_drive_btn,
327
  page_upload_notion_btn,
328
  project_name,
329
+ generation_results
330
  )
331
 
332
  return (all_components, step_buttons,
 
450
  current_session_display,
451
  ]
452
  )
 
 
453
 
454
  # Call setup_event_handlers after all components are created
455
  setup_event_handlers()
event_handler.py CHANGED
@@ -5,54 +5,22 @@ from state import state
5
  import gradio as gr
6
  import json
7
  from prompt_configs import PROMPTS
8
- import pandas as pd
9
- from io import StringIO
10
 
11
- def start_generation():
12
- """Initial function to start the generation process"""
13
- return "Starting generation..."
14
-
15
- def generate_content():
16
- """Generate content and return results"""
17
  try:
18
- # Initialize state project if not already done
19
- if not hasattr(state, 'quotation_project') or state.quotation_project is None:
20
- state.quotation_project = Project("quotation")
21
-
22
- # Get the results from the project one by one
23
- results = state.quotation_project.generate_prd_and_components()
24
-
25
- # Store results in state for access by render function
26
- state.generation_results = results
27
-
28
- # Return the progress update and results
29
- return "Generation complete!", results
30
-
31
  except Exception as e:
32
- print(f"Error in generate_content: {str(e)}")
33
- return f"Error: {str(e)}", {}
34
 
35
  def setup_all_handlers(step_buttons, all_components, progress_update, quotation_cost=None, recalc_btn=None, upload_drive_btn=None, upload_notion_btn=None, project_name=None, generation_results=None):
36
  """Set up all step handlers with the provided UI components"""
37
-
38
- # Store components for use in handlers
39
- global components
40
- components = all_components
41
-
42
- # Use the provided generation_results or create a new one if not provided
43
- if generation_results is None:
44
- generation_results = gr.State(value=set())
45
-
46
- # Set up handlers for each step button
47
- for step_name, button in step_buttons.items():
48
- if "Step 1" in step_name:
49
- # First update the progress message, then generate content
50
- button.click(
51
- fn=start_generation,
52
- outputs=[progress_update]
53
- ).then(
54
- fn=generate_content,
55
- outputs=[progress_update, generation_results]
56
- )
57
-
58
- return generation_results
 
5
  import gradio as gr
6
  import json
7
  from prompt_configs import PROMPTS
8
+ from typing import Generator, Tuple
 
9
 
10
+ def generate_content(progress=gr.Progress()) -> Generator[Tuple[str, set] , Any , None]:
11
+ """Generate content using the Project instance"""
 
 
 
 
12
  try:
13
+ # Generate PRD and components, yielding results as they're generated
14
+ for status_msg, result in state.quotation_project.generate_prd_and_components(progress):
15
+ # Yield both the status message and current results
16
+ yield status_msg, result
17
+
 
 
 
 
 
 
 
 
18
  except Exception as e:
19
+ print(f"Error during generation: {str(e)}") # Add debug print
20
+ yield f"Error during generation: {str(e)}", set()
21
 
22
  def setup_all_handlers(step_buttons, all_components, progress_update, quotation_cost=None, recalc_btn=None, upload_drive_btn=None, upload_notion_btn=None, project_name=None, generation_results=None):
23
  """Set up all step handlers with the provided UI components"""
24
+ # Modified button click chain
25
+ return generation_results
26
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
prompt_configs.py CHANGED
@@ -128,7 +128,7 @@ PROMPTS = {
128
  """,
129
  inputs=['generated_prd'],
130
  outputs=["configuration_type"],
131
- step="Analyze Configuration Type",
132
  model=ModelType.O1_MINI,
133
  description="Component Agent",
134
  ),
 
128
  """,
129
  inputs=['generated_prd'],
130
  outputs=["configuration_type"],
131
+ step="Step 1 : Scope & Components",
132
  model=ModelType.O1_MINI,
133
  description="Component Agent",
134
  ),