kamaleswar Mohanta commited on
Commit
60f7bfc
·
1 Parent(s): c9f4fb2
src/langgraphagenticai/graph/__pycache__/graph_builder_blog.cpython-312.pyc CHANGED
Binary files a/src/langgraphagenticai/graph/__pycache__/graph_builder_blog.cpython-312.pyc and b/src/langgraphagenticai/graph/__pycache__/graph_builder_blog.cpython-312.pyc differ
 
src/langgraphagenticai/nodes/__pycache__/blog_generation_node.cpython-312.pyc CHANGED
Binary files a/src/langgraphagenticai/nodes/__pycache__/blog_generation_node.cpython-312.pyc and b/src/langgraphagenticai/nodes/__pycache__/blog_generation_node.cpython-312.pyc differ
 
src/langgraphagenticai/nodes/blog_generation_node.py CHANGED
@@ -172,8 +172,10 @@ class BlogGenerationNode:
172
  return {"initial_draft": initial_draft}
173
 
174
  def feedback_collector(self, state: State) -> dict:
175
- logger.info(f"\n\n----------------:Entered feedback_collector with state:----------------------\n\n{state}")
176
-
 
 
177
  if state.get("messages") and len(state["messages"]) > 0 and isinstance(state["messages"][-1], HumanMessage):
178
  try:
179
  feedback_data = json.loads(state["messages"][-1].content)
@@ -220,11 +222,12 @@ class BlogGenerationNode:
220
  # Conditional edge for feedback loop
221
  def route_feedback(self, state: State):
222
  """Route based on whether draft is approved."""
223
- logger.info(f"route_feedback: draft_approved = {state.get('draft_approved', False)}")
224
- logger.info(f"route_feedback: state[\\'draft_approved\\'] = {state['draft_approved']}")
225
- if state["draft_approved"]== True:
 
226
  logger.info("Draft approved; routing to file_generator")
227
- state["final_report"] = state.get("initial_draft", "")
228
- return "file_generator" # Routes to file_generator if approved
229
- logger.info("Draft not approved; routing back to orchestrator for revision")
230
- return "orchestrator" # Routes back to orchestrator if not approved
 
172
  return {"initial_draft": initial_draft}
173
 
174
  def feedback_collector(self, state: State) -> dict:
175
+ logger.info(f"\n\n----------------:Entered feedback_collector with state:----------------------\n\n{state}")
176
+ logger.info(f"Message count: {len(state.get('messages', []))}")
177
+ logger.info(f"Last message type: {type(state['messages'][-1]) if state.get('messages') else 'None'}")
178
+
179
  if state.get("messages") and len(state["messages"]) > 0 and isinstance(state["messages"][-1], HumanMessage):
180
  try:
181
  feedback_data = json.loads(state["messages"][-1].content)
 
222
  # Conditional edge for feedback loop
223
  def route_feedback(self, state: State):
224
  """Route based on whether draft is approved."""
225
+ draft_approved = state.get('draft_approved', False)
226
+ logger.info(f"route_feedback: draft_approved = {draft_approved}")
227
+
228
+ if draft_approved is True: # Strict comparison
229
  logger.info("Draft approved; routing to file_generator")
230
+ return "file_generator"
231
+ else:
232
+ logger.info("Draft not approved; routing back to orchestrator for revision")
233
+ return "orchestrator"
src/langgraphagenticai/ui/streamlitui/__pycache__/display_result.cpython-312.pyc CHANGED
Binary files a/src/langgraphagenticai/ui/streamlitui/__pycache__/display_result.cpython-312.pyc and b/src/langgraphagenticai/ui/streamlitui/__pycache__/display_result.cpython-312.pyc differ
 
src/langgraphagenticai/ui/streamlitui/__pycache__/display_result_blog.cpython-312.pyc CHANGED
Binary files a/src/langgraphagenticai/ui/streamlitui/__pycache__/display_result_blog.cpython-312.pyc and b/src/langgraphagenticai/ui/streamlitui/__pycache__/display_result_blog.cpython-312.pyc differ
 
src/langgraphagenticai/ui/streamlitui/display_result.py CHANGED
@@ -130,13 +130,35 @@ class DisplayResultStreamlit:
130
  logger.info(f"\n{'*'*20}st.session_state[feedback] is {st.session_state["feedback"]}{'*'*20}\n")
131
  st.rerun() # Trigger rerun to enter the processing_feedback stage
132
 
 
133
  elif st.session_state.current_stage == "processing_feedback":
134
  logger.info(f"\n\n{"="*20}: Entered main Display processing_feedback stage:{"="*20}\n\n")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  st.session_state.current_stage = "processing"
136
- logger.info(f"\n{'*'*20}st.session_state[feedback] is {st.session_state["feedback"]}{'*'*20}\n")
137
- blog_display.process_graph_events(HumanMessage(content=json.dumps({"approved": False, "comments": st.session_state['feedback']})))
138
- st.session_state['feedback_result'] = None # Clear the feedback result
139
  st.rerun()
 
140
  elif st.session_state.current_stage == "complete":
141
  st.success("✅ Blog generation complete!")
142
  if st.session_state.get("blog_content"):
 
130
  logger.info(f"\n{'*'*20}st.session_state[feedback] is {st.session_state["feedback"]}{'*'*20}\n")
131
  st.rerun() # Trigger rerun to enter the processing_feedback stage
132
 
133
+ # In DisplayResultStreamlit.process_user_input() for the "processing_feedback" stage
134
  elif st.session_state.current_stage == "processing_feedback":
135
  logger.info(f"\n\n{"="*20}: Entered main Display processing_feedback stage:{"="*20}\n\n")
136
+
137
+ # Create a proper feedback message
138
+ feedback_message = HumanMessage(content=json.dumps({
139
+ "approved": False,
140
+ "comments": st.session_state['feedback']
141
+ }))
142
+
143
+ # Resume the graph with the stored state and new feedback
144
+ logger.info(f"Resuming graph with feedback: {feedback_message.content}")
145
+
146
+ # Use the stored checkpoint state to resume the graph
147
+ checkpoint_state = st.session_state.get("graph_state")
148
+ if checkpoint_state:
149
+ input_data = {
150
+ "messages": [feedback_message],
151
+ "__checkpoint__": checkpoint_state # Pass the stored checkpoint
152
+ }
153
+ blog_display.process_graph_events_with_checkpoint(input_data)
154
+ else:
155
+ # Fall back to regular processing if no checkpoint available
156
+ blog_display.process_graph_events(feedback_message)
157
+
158
  st.session_state.current_stage = "processing"
159
+ st.session_state['feedback_result'] = None # Clear the feedback result
 
 
160
  st.rerun()
161
+
162
  elif st.session_state.current_stage == "complete":
163
  st.success("✅ Blog generation complete!")
164
  if st.session_state.get("blog_content"):
src/langgraphagenticai/ui/streamlitui/display_result_blog.py CHANGED
@@ -138,85 +138,106 @@ class DisplayBlogResult:
138
 
139
 
140
 
141
- def process_feedback(self):
142
- print("\n\n----blog_display process_feedback function entered----\n\n")
143
- logger.info("---blog_display process_feedback function entered ----\n\n")
144
- st.write("Session State in process_feedback:", st.session_state)
145
- st.markdown("## Stage 3: Feedback")
146
- if st.session_state.get("generated_draft"):
147
- st.markdown("### Drafted Blog Content:")
148
- st.markdown(st.session_state["generated_draft"])
149
- with st.expander("Stage 3: Feedback", expanded=True):
150
- feedback_text = st.text_input(
151
- "Revision comments:",
152
- placeholder="Please explain what changes you would like to see.",
153
- key="revision_comments_area",
154
- value=st.session_state.get("revision_comments_area", "Add some reference to it ")
155
- )
156
- st.session_state["feedback"] = feedback_text # Update session state for graph processing
157
-
158
- col1, col2 = st.columns(2)
159
- with col1:
160
- st.button("✅ Approve Content", on_click=self._handle_approved_click, key="blog_feedback_approve_button")
161
- with col2:
162
- st.button("Submit Revision Request", on_click=self._handle_revised_click, key="blog_feedback_revise_button")
163
- return st.session_state.get('feedback_result')
164
-
165
-
166
  def process_graph_events(self, input_message=None):
167
  try:
168
-
169
  input_data = {"messages": [input_message]} if input_message else None
170
  progress_bar = st.progress(0)
 
 
 
171
 
172
  for i, event in enumerate(self.graph.stream(input_data, self.config)):
173
  logger.info(f"Graph event received: #{i+1}")
174
-
175
  # Update progress indicator
176
- progress_value = min(i * 0.1, 0.9) # Cap at 90% until complete
177
  progress_bar.progress(progress_value)
 
 
 
 
 
 
178
 
179
  # Process event data
180
  for node, state in event.items():
181
- logger.info(f"Processing event for node: {node}, state: {state}")
182
-
183
- # Specifically handle interrupt events
184
  if node == "__interrupt__":
185
  logger.info("Interrupt event received - transitioning to feedback stage")
186
  st.session_state.waiting_for_feedback = True
187
- logger.info("Waiting for feedback from user.")
188
  st.session_state.current_stage = "feedback"
189
- logger.info("Feedback stage initiated.")
190
  st.rerun()
191
- progress_bar.progress(1.0)
192
  return
193
 
194
- if isinstance(state, dict):
195
-
196
- if node == "synthesizer" and "initial_draft" in state and not st.session_state.get('synthesizer_output_processed', False):
197
- logger.info("Draft generated by synthesizer, displaying content")
198
- st.markdown("## Generating Draft")
199
- st.session_state.generated_draft = state["initial_draft"]
200
- st.session_state.content_displayed = True # Ensure this is set
201
- st.session_state.current_stage = "content" # Ensure this is set
202
- st.session_state.synthesizer_output_processed = True #Set the flag.
 
 
203
 
204
- # Check if the file_generator node finished
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  if node == "file_generator":
206
  logger.info("File generator node finished, setting stage to complete.")
207
  st.session_state.blog_generation_complete = True
208
  st.session_state.current_stage = "complete"
209
  st.session_state.processing_complete = True
210
- break # Stop processing events after completion
211
-
212
-
213
-
214
- # Ensure progress completes
215
  progress_bar.progress(1.0)
216
-
217
  except Exception as e:
218
  st.error(f"⚠️ Error processing workflow: {e}")
219
  logger.exception(f"Error in graph streaming: {e}")
220
- # Add recovery mechanism
221
- st.session_state.current_stage = "requirements"
222
- st.warning("There was an error. Please try again.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
 
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  def process_graph_events(self, input_message=None):
142
  try:
 
143
  input_data = {"messages": [input_message]} if input_message else None
144
  progress_bar = st.progress(0)
145
+
146
+ # Store the graph state for resuming later
147
+ checkpoint_state = None
148
 
149
  for i, event in enumerate(self.graph.stream(input_data, self.config)):
150
  logger.info(f"Graph event received: #{i+1}")
151
+
152
  # Update progress indicator
153
+ progress_value = min(i * 0.1, 0.9)
154
  progress_bar.progress(progress_value)
155
+
156
+ # Store the latest checkpoint state for resuming after interrupt
157
+ if "__checkpoint__" in event:
158
+ checkpoint_state = event["__checkpoint__"]
159
+ st.session_state.graph_state = checkpoint_state
160
+ logger.info(f"Checkpoint state stored: {checkpoint_state}")
161
 
162
  # Process event data
163
  for node, state in event.items():
164
+ # Handle interrupt after synthesizer
 
 
165
  if node == "__interrupt__":
166
  logger.info("Interrupt event received - transitioning to feedback stage")
167
  st.session_state.waiting_for_feedback = True
 
168
  st.session_state.current_stage = "feedback"
 
169
  st.rerun()
 
170
  return
171
 
172
+ # Process synthesizer output
173
+ if node == "synthesizer" and "initial_draft" in state:
174
+ logger.info("Draft generated by synthesizer, displaying content")
175
+ st.session_state.generated_draft = state["initial_draft"]
176
+ st.session_state.content_displayed = True
177
+ st.session_state.synthesizer_output_processed = True
178
+
179
+ progress_bar.progress(1.0)
180
+ except Exception as e:
181
+ st.error(f"⚠️ Error processing workflow: {e}")
182
+ logger.exception(f"Error in graph streaming: {e}")
183
 
184
+ def process_graph_events_with_checkpoint(self, input_data):
185
+ """Process graph events with a checkpoint to resume from interrupt"""
186
+ try:
187
+ progress_bar = st.progress(0)
188
+
189
+ # We're resuming from a stored checkpoint
190
+ for i, event in enumerate(self.graph.stream(input_data, self.config)):
191
+ logger.info(f"Graph event received (resuming): #{i+1}")
192
+
193
+ # Update progress indicator
194
+ progress_value = min(i * 0.1, 0.9)
195
+ progress_bar.progress(progress_value)
196
+
197
+ # Store the latest checkpoint state for resuming after interrupt
198
+ if "__checkpoint__" in event:
199
+ st.session_state.graph_state = event["__checkpoint__"]
200
+
201
+ # Process event data (similar to process_graph_events)
202
+ for node, state in event.items():
203
+ if node == "feedback_collector":
204
+ logger.info(f"Feedback collector processing: {state}")
205
+
206
  if node == "file_generator":
207
  logger.info("File generator node finished, setting stage to complete.")
208
  st.session_state.blog_generation_complete = True
209
  st.session_state.current_stage = "complete"
210
  st.session_state.processing_complete = True
211
+ break
212
+
 
 
 
213
  progress_bar.progress(1.0)
 
214
  except Exception as e:
215
  st.error(f"⚠️ Error processing workflow: {e}")
216
  logger.exception(f"Error in graph streaming: {e}")
217
+
218
+ def process_feedback(self):
219
+ """Process user feedback on the generated blog draft."""
220
+ print("\n\n----blog_display process_feedback function entered----\n\n")
221
+ logger.info("---blog_display process_feedback function entered ----\n\n")
222
+
223
+ st.markdown("## Stage 3: Feedback")
224
+ if st.session_state.get("generated_draft"):
225
+ st.markdown("### Drafted Blog Content:")
226
+ st.markdown(st.session_state["generated_draft"])
227
+
228
+ with st.expander("Stage 3: Feedback", expanded=True):
229
+ feedback_text = st.text_input(
230
+ "Revision comments:",
231
+ placeholder="Please explain what changes you would like to see.",
232
+ key="revision_comments_area",
233
+ value=st.session_state.get("revision_comments_area", "Add some reference to it ")
234
+ )
235
+ st.session_state["feedback"] = feedback_text # Update session state for graph processing
236
+
237
+ col1, col2 = st.columns(2)
238
+ with col1:
239
+ st.button("✅ Approve Content", on_click=self._handle_approved_click, key="blog_feedback_approve_button")
240
+ with col2:
241
+ st.button("Submit Revision Request", on_click=self._handle_revised_click, key="blog_feedback_revise_button")
242
+
243
+ return st.session_state.get('feedback_result')