abhlash commited on
Commit
999d8ef
·
1 Parent(s): 42da68f

updated reflextion

Browse files
Files changed (1) hide show
  1. app.py +106 -53
app.py CHANGED
@@ -3,6 +3,7 @@ import os
3
  from groq import Groq
4
  from dotenv import load_dotenv
5
  import logging
 
6
 
7
  # Configure logging
8
  logging.basicConfig(
@@ -25,27 +26,39 @@ if not GROQ_API_KEY:
25
 
26
  client = Groq(api_key=GROQ_API_KEY)
27
 
28
- # Define the Reflexion system prompt with formatted user variables
29
- SYSTEM_PROMPT = (
30
- "You are an advanced AI agent leveraging the Reflexion framework to iteratively improve ideas and responses through up to {reflection_cycles} cycles of reflection. "
31
  "Your goal is to provide the most meaningful, relevant, and impactful results while autonomously managing the process. Follow the structured workflow below:\n\n"
32
  "Instructions:\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  "Initial Response:\n"
34
- "Begin with the {user_input} and provide a well-considered, thoughtful initial answer. Ensure clarity, relevance, and creativity in addressing the query.\n\n"
35
- "Reflection Cycles (Up to {reflection_cycles}):\n"
 
36
  "After each response, perform a critical reflection, considering the following:\n"
37
- "Alignment: Does the answer align with the user's intent?\n"
38
- "Feasibility: Are the ideas or solutions practical and actionable?\n"
39
- "Depth: Are there gaps, ambiguities, or missed perspectives?\n"
40
- "Impact: How meaningful and beneficial is the response to the user?\n"
41
- "Use the feedback from this reflection to refine the response, document insights in a temporary memory buffer, and iterate the process.\n\n"
42
- "Continue refining and evolving the response for up to {reflection_cycles} cycles or until you reach a well-optimized conclusion.\n\n"
43
- "Episodic Memory Storage:\n"
44
- "Maintain a temporary memory buffer to track reflections and refinements. Use this to avoid redundant steps and ensure improvements are based on accumulated insights.\n\n"
45
  "Final Output:\n"
46
- "Deliver a final, polished answer that is thoughtful, comprehensive, and fully addresses the user's query.\n"
47
- "Provide a summary of the ideation journey, highlighting key outcomes and how the response evolved over the iterations."
48
- ).format(reflection_cycles=reflection_cycles, user_input="{user_input}")
49
 
50
  # Initialize Streamlit app
51
  st.title("Reflexion AI Agent")
@@ -58,10 +71,13 @@ if "messages" not in st.session_state:
58
  def summarize_input(user_input):
59
  return user_input
60
 
 
 
61
  # Function to generate responses using the Groq API
62
  def generate_response(user_input, reflection_memory):
63
  try:
64
- combined_length = len(SYSTEM_PROMPT) + len(user_input)
 
65
  reflection_memory_content = [msg["content"] for msg in reflection_memory[-3:]]
66
  reflection_memory_length = len(" ".join(reflection_memory_content))
67
  context_limit = 8192
@@ -69,46 +85,68 @@ def generate_response(user_input, reflection_memory):
69
  logging.debug(f"Combined length of system prompt and user input: {combined_length}")
70
  logging.debug(f"Reflection memory length: {reflection_memory_length}")
71
 
72
- if combined_length + reflection_memory_length > context_limit:
73
- user_input = summarize_input(user_input)
74
- combined_length = len(SYSTEM_PROMPT) + len(user_input)
75
- logging.debug(f"Summarized input length: {len(user_input)}")
76
- logging.debug(f"New combined length: {combined_length + reflection_memory_length}")
77
 
 
78
  chat_completion = client.chat.completions.create(
79
  model="llama3-8b-8192",
80
  messages=[
81
- {"role": "system", "content": SYSTEM_PROMPT},
82
  {"role": "user", "content": user_input},
83
  {"role": "assistant", "content": " ".join(reflection_memory_content)}
84
  ],
85
- max_tokens=1024,
86
- temperature=0.6,
87
  top_p=0.9,
88
  )
89
 
90
  logging.debug(f"Full API Response: {chat_completion}")
91
 
92
- if chat_completion.choices and len(chat_completion.choices) > 0:
93
- content = chat_completion.choices[0].message.content
94
- if content:
95
- # Extract the "Final Output" section if it exists, otherwise use the entire content
96
- final_output_start = content.find("Final Output:")
97
- if final_output_start != -1:
98
- final_output = content[final_output_start:].strip()
99
- else:
100
- final_output = content.strip()
101
- return final_output
102
- else:
103
- logging.warning("Received empty content in API response.")
104
- return None
105
- else:
106
  raise ValueError("Invalid response format: No choices found.")
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  except Exception as e:
109
  logging.error(f"Error generating response: {e}", exc_info=True)
110
- st.error(f"Error generating response: {e}")
111
- return None
 
 
 
 
112
 
113
  # Display chat messages from history on app rerun
114
  for message in st.session_state.messages:
@@ -116,20 +154,35 @@ for message in st.session_state.messages:
116
  st.markdown(message["content"])
117
 
118
  # Accept user input
119
- if user_input := st.chat_input("You: "):
 
 
 
120
  # Display user message in chat message container
121
  st.chat_message("user").markdown(user_input)
122
  # Add user message to chat history
123
  st.session_state.messages.append({"role": "user", "content": user_input})
124
 
125
- # Generate and display assistant response
126
- last_valid_response = None
127
- for _ in range(reflection_cycles):
128
- bot_response = generate_response(user_input, st.session_state.messages)
129
- if bot_response:
130
- last_valid_response = bot_response
131
-
132
- # Display only the final output
133
- if last_valid_response:
134
- st.chat_message("assistant").markdown(last_valid_response)
135
- st.session_state.messages.append({"role": "assistant", "content": last_valid_response})
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from groq import Groq
4
  from dotenv import load_dotenv
5
  import logging
6
+ import json
7
 
8
  # Configure logging
9
  logging.basicConfig(
 
26
 
27
  client = Groq(api_key=GROQ_API_KEY)
28
 
29
+ # Define the Reflexion system prompt template
30
+ SYSTEM_PROMPT_TEMPLATE = (
31
+ "You are an advanced AI agent leveraging the Reflexion framework to iteratively improve ideas and responses through up to {} cycles of reflection. "
32
  "Your goal is to provide the most meaningful, relevant, and impactful results while autonomously managing the process. Follow the structured workflow below:\n\n"
33
  "Instructions:\n\n"
34
+ "Output the entire response in the following JSON structure:\n"
35
+ "{{\n"
36
+ " \"initial_response\": \"<Provide the initial response here as a string>\",\n"
37
+ " \"reflection_cycles\": [\n"
38
+ " {{\n"
39
+ " \"cycle\": {{cycle}},\n"
40
+ " \"alignment\": \"{{Reflection on alignment}}\",\n"
41
+ " \"feasibility\": \"{{Reflection on feasibility}}\",\n"
42
+ " \"depth\": \"{{Reflection on depth}}\",\n"
43
+ " \"impact\": \"{{Reflection on impact}}\",\n"
44
+ " \"refined_response\": \"{{Refined response after this reflection cycle}}\"\n"
45
+ " }}\n"
46
+ " ],\n"
47
+ " \"final_output\": \"{{Final, polished response}}\"\n"
48
+ "}}\n\n"
49
  "Initial Response:\n"
50
+ "Begin with the following input and provide a well-considered, thoughtful initial answer:\n\n"
51
+ "{}\n\n"
52
+ "Reflection Cycles (Up to {}):\n"
53
  "After each response, perform a critical reflection, considering the following:\n"
54
+ "- Alignment: Does the answer align with the user's intent?\n"
55
+ "- Feasibility: Are the ideas or solutions practical and actionable?\n"
56
+ "- Depth: Are there gaps, ambiguities, or missed perspectives?\n"
57
+ "- Impact: How meaningful and beneficial is the response to the user?\n"
58
+ "Use the feedback from this reflection to refine the response and document it in the JSON structure.\n\n"
 
 
 
59
  "Final Output:\n"
60
+ "Provide a final, polished response as the \"final_output\" field in the JSON. The response should be thoughtful, comprehensive, and fully address the user's query.\n"
61
+ )
 
62
 
63
  # Initialize Streamlit app
64
  st.title("Reflexion AI Agent")
 
71
  def summarize_input(user_input):
72
  return user_input
73
 
74
+ # Function to generate responses using the Groq API
75
+ # Function to generate responses using the Groq API
76
  # Function to generate responses using the Groq API
77
  def generate_response(user_input, reflection_memory):
78
  try:
79
+ # Prepare lengths for context management
80
+ combined_length = len(SYSTEM_PROMPT_TEMPLATE) + len(user_input)
81
  reflection_memory_content = [msg["content"] for msg in reflection_memory[-3:]]
82
  reflection_memory_length = len(" ".join(reflection_memory_content))
83
  context_limit = 8192
 
85
  logging.debug(f"Combined length of system prompt and user input: {combined_length}")
86
  logging.debug(f"Reflection memory length: {reflection_memory_length}")
87
 
88
+ # Format the SYSTEM_PROMPT with actual user input and reflection cycles
89
+ formatted_prompt = SYSTEM_PROMPT_TEMPLATE.format(reflection_cycles, user_input, reflection_cycles)
 
 
 
90
 
91
+ # Send request to Groq API
92
  chat_completion = client.chat.completions.create(
93
  model="llama3-8b-8192",
94
  messages=[
95
+ {"role": "system", "content": formatted_prompt},
96
  {"role": "user", "content": user_input},
97
  {"role": "assistant", "content": " ".join(reflection_memory_content)}
98
  ],
99
+ max_tokens=2048,
100
+ temperature=0.7,
101
  top_p=0.9,
102
  )
103
 
104
  logging.debug(f"Full API Response: {chat_completion}")
105
 
106
+ # Ensure choices exist in the response
107
+ if not chat_completion.choices or len(chat_completion.choices) == 0:
 
 
 
 
 
 
 
 
 
 
 
 
108
  raise ValueError("Invalid response format: No choices found.")
109
 
110
+ content = chat_completion.choices[0].message.content
111
+ if not content:
112
+ logging.warning("Received empty content in API response.")
113
+ return None
114
+
115
+ # Parse the JSON output
116
+ try:
117
+ # Clean and preprocess the content
118
+ content = content.strip()
119
+ if not content.startswith('{'):
120
+ start_idx = content.find('{')
121
+ if start_idx != -1:
122
+ content = content[start_idx:]
123
+ if not content.endswith('}'):
124
+ end_idx = content.rfind('}')
125
+ if end_idx != -1:
126
+ content = content[:end_idx + 1]
127
+
128
+ # Parse the JSON content
129
+ parsed_json = json.loads(content)
130
+ logging.debug(f"Parsed JSON Response: {parsed_json}")
131
+ return parsed_json
132
+ except json.JSONDecodeError as e:
133
+ logging.error(f"JSON parsing error: {e}\nContent: {content}")
134
+
135
+ # Return fallback response with raw content
136
+ return {
137
+ "initial_response": "Error parsing response",
138
+ "reflection_cycles": [],
139
+ "final_output": content,
140
+ }
141
+
142
  except Exception as e:
143
  logging.error(f"Error generating response: {e}", exc_info=True)
144
+ return {
145
+ "initial_response": "Error occurred",
146
+ "reflection_cycles": [],
147
+ "final_output": f"An error occurred: {str(e)}",
148
+ }
149
+
150
 
151
  # Display chat messages from history on app rerun
152
  for message in st.session_state.messages:
 
154
  st.markdown(message["content"])
155
 
156
  # Accept user input
157
+ user_input = st.chat_input("You: ")
158
+
159
+ # Check if user input is submitted via Enter
160
+ if user_input:
161
  # Display user message in chat message container
162
  st.chat_message("user").markdown(user_input)
163
  # Add user message to chat history
164
  st.session_state.messages.append({"role": "user", "content": user_input})
165
 
166
+ # Generate and display assistant response with a loading spinner
167
+ with st.spinner("Generating response..."):
168
+ response = generate_response(user_input, st.session_state.messages)
169
+ # Display refined responses dynamically
170
+ if response:
171
+ try:
172
+ reflection_cycles = response.get("reflection_cycles", [])
173
+
174
+ if reflection_cycles:
175
+ st.markdown("### Refined Responses")
176
+ for cycle in reflection_cycles:
177
+ refined_response = cycle.get("refined_response", None)
178
+ if refined_response:
179
+ st.chat_message("assistant").markdown(refined_response)
180
+ # Add to session state
181
+ st.session_state.messages.append({"role": "assistant", "content": refined_response})
182
+ else:
183
+ logging.warning("Refined response missing in cycle.")
184
+ else:
185
+ st.warning("No reflection cycles found in the response.")
186
+ except Exception as e:
187
+ logging.error(f"Error processing response: {e}")
188
+ st.error("Failed to process the response.")