Liss, Alex (NYC-HUG) commited on
Commit
33f621e
·
1 Parent(s): c74750f

got Feature 0 working

Browse files
docs/Phase 1/Task 1.3 Memory & Persona Implementation.md CHANGED
@@ -189,10 +189,49 @@ The user will execute **one step at a time** and confirm each works before proce
189
 
190
  ---
191
 
192
- ### 7 │ Documentation Update
193
 
194
- * Explain *why* the simple, surgical approach avoided regressions.
195
- * Update project docs to reflect the new persona‑memory workflow.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
  ---
198
 
@@ -234,6 +273,8 @@ The user will execute **one step at a time** and confirm each works before proce
234
  | Rigorous Testing | Test changes immediately after implementation to catch issues early | Ran the application after adding the radio button to verify it works |
235
  | Clear Documentation | Document design decisions and patterns | Added comments explaining why global variables are declared before functions that use them |
236
  | Consistent Logging | Use consistent prefixes for log messages to aid debugging | Added prefixes like "[PERSONA CHANGE]" and "[MEMORY LOAD]" |
 
 
237
 
238
  ---
239
 
 
189
 
190
  ---
191
 
192
+ ### 7 │ Changing App Responses to Provide User Personalization
193
 
194
+ * Review the context provided as Zep memoery in the zep_test.py file
195
+ * create an LLM function to summarize this information into concise and declarative content, e.g. TELL THE 49ers FAN APP how to personalize its outgoing messages to deliver exactly the kind of content and experience this fan is looking for!
196
+ * review the structure of gradio_agent.py and identify where and how the AI agent can receive the instructions to personalize, using the Minimal Surgical Changes rule
197
+ * present the plan to the user and explain your rationale in detail. Prepare to debate and be open to new ideas
198
+ * once a plan has been reviewed and approved, execute along the lines of the Appendix - First Principles in Action
199
+
200
+ **Status Update:**
201
+ ✅ Successfully reviewed the Zep memory contexts for both personas:
202
+ - Casual Fan persona has surface-level knowledge and is motivated by feeling included
203
+ - Super Fan persona has detailed knowledge and is motivated by strategic understanding
204
+ ✅ Created a new `get_persona_instructions()` function in gradio_agent.py to return different instructions based on the current persona
205
+ ✅ Updated prompts.py to include a placeholder for persona-specific instructions
206
+ ✅ Modified generate_response() to incorporate persona instructions into the agent prompt
207
+ ✅ Implemented two surgical changes to enhance persona-specific behavior:
208
+ - Enhanced persona instructions with more directive language and specific examples
209
+ - Added persona tag emphasizers around instructions and in user inputs
210
+
211
+ **Implementation Details:**
212
+ 1. **Made Instructions More Direct and Prescriptive**:
213
+ - Rewritten instructions using "YOU MUST" language instead of suggestions
214
+ - Added numbered lists of specific behaviors to exhibit for each persona
215
+ - Included concrete examples of how responses should look for each persona
216
+ - Added "do/don't" sections to clarify expectations
217
+
218
+ 2. **Enhanced Instruction Visibility in the Agent Context**:
219
+ - Added emphasis tags around persona instructions: `[ACTIVE PERSONA: {current_persona}]`
220
+ - Added persona-specific prefix to user inputs: `[RESPOND AS {current_persona.upper()}]:`
221
+ - These small but effective changes helped ensure the instructions weren't lost in context
222
+
223
+ **Results:**
224
+ ✅ Successfully implemented personalization with distinctly different responses for each persona:
225
+ - **Casual Fan responses** became shorter, used inclusive "we/our" language, included excitement markers (exclamation points), and focused on big moments and star players
226
+ - **Super Fan responses** became more detailed, used technical terminology, included structured analysis, and referenced role players alongside stars
227
+ - Example: When asked about draft news, the casual fan received a brief, excited summary focusing on star players and big moments, while the super fan received a detailed, categorized analysis with specific prospect evaluations
228
+
229
+ **Future Improvements (Backlog):**
230
+ - Further enhance personalization by integrating more facts from the Zep memory context into responses
231
+ - Create a more sophisticated prompt that explicitly references relevant facts based on the current query
232
+ - Add a mechanism to track and adapt to the user's knowledge level over time
233
+ - Implement a feedback loop where users can indicate if responses are appropriately personalized
234
+ - Explore ways to make persona-specific language settings persistent across sessions
235
 
236
  ---
237
 
 
273
  | Rigorous Testing | Test changes immediately after implementation to catch issues early | Ran the application after adding the radio button to verify it works |
274
  | Clear Documentation | Document design decisions and patterns | Added comments explaining why global variables are declared before functions that use them |
275
  | Consistent Logging | Use consistent prefixes for log messages to aid debugging | Added prefixes like "[PERSONA CHANGE]" and "[MEMORY LOAD]" |
276
+ | Sequential Approval Workflow | Present detailed plans, wait for explicit approval on each component, implement one change at a time, and provide clear explanations of data flows | Explained how the persona instructions flow from selection to prompt generation before implementing changes |
277
+ | Surgical Diff Principle | Show only the specific changes being made rather than reprinting entire code blocks | Highlighted just the 2 key modifications to implement personalization rather than presenting a large code block |
278
 
279
  ---
280
 
gradio_agent.py CHANGED
@@ -155,6 +155,51 @@ def get_memory(session_id):
155
  # No memory_type parameter
156
  )
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  # Create the agent prompt
159
  agent_prompt = PromptTemplate.from_template(AGENT_SYSTEM_PROMPT)
160
 
@@ -226,20 +271,47 @@ def generate_response(user_input, session_id=None):
226
  Returns:
227
  dict: The full response object from the agent
228
  """
229
- print('Starting generate_response function...')
230
- print(f'User input: {user_input}')
231
- print(f'Session ID: {session_id}')
 
232
 
233
  if not session_id:
234
  session_id = get_session_id()
235
- print(f'Generated new session ID: {session_id}')
236
 
237
  # Initialize memory with Zep history
238
  memory = initialize_memory_from_zep(session_id)
239
 
240
- # Create an agent executor with memory for this session
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  session_agent_executor = AgentExecutor(
242
- agent=agent,
243
  tools=tools,
244
  verbose=True,
245
  memory=memory, # Use the memory we initialized
@@ -253,7 +325,9 @@ def generate_response(user_input, session_id=None):
253
  try:
254
  print('Invoking session agent executor...')
255
  # The agent will now have access to the loaded history
256
- response = session_agent_executor.invoke({"input": user_input})
 
 
257
 
258
  # Extract the output and format it for Streamlit
259
  if isinstance(response, dict):
 
155
  # No memory_type parameter
156
  )
157
 
158
+ # New function to generate persona-specific instructions
159
+ def get_persona_instructions():
160
+ """Generate personalized instructions based on current persona"""
161
+ if current_persona == "Casual Fan":
162
+ return """
163
+ PERSONA DIRECTIVE: CASUAL FAN MODE - YOU MUST FOLLOW THESE RULES
164
+
165
+ YOU MUST speak to a casual 49ers fan with surface-level knowledge. This means you MUST:
166
+ 1. Keep explanations BRIEF and under 3-4 sentences whenever possible
167
+ 2. Use EVERYDAY LANGUAGE instead of technical football terms
168
+ 3. EMPHASIZE exciting plays, scoring, and player personalities
169
+ 4. FOCUS on "big moments" and "highlight-reel plays" in your examples
170
+ 5. AVOID detailed strategic analysis or technical football concepts
171
+ 6. CREATE a feeling of inclusion by using "we" and "our team" language
172
+ 7. INCLUDE at least one exclamation point in longer responses to convey excitement!
173
+
174
+ Casual fans don't know or care about: blocking schemes, defensive alignments, or salary cap details.
175
+ Casual fans DO care about: star players, touchdowns, big hits, and feeling connected to the team.
176
+
177
+ EXAMPLE RESPONSE FOR CASUAL FAN (about the draft):
178
+ "The 49ers did a great job finding exciting new players in the draft! They picked up a speedy receiver who could make some highlight-reel plays for us next season. The team focused on adding talent that can make an immediate impact, which is exactly what we needed!"
179
+ """
180
+ elif current_persona == "Super Fan":
181
+ return """
182
+ PERSONA DIRECTIVE: SUPER FAN MODE - YOU MUST FOLLOW THESE RULES
183
+
184
+ YOU MUST speak to a die-hard 49ers super fan with detailed football knowledge. This means you MUST:
185
+ 1. Provide DETAILED analysis that goes beyond surface-level information
186
+ 2. Use SPECIFIC football terminology and scheme concepts confidently
187
+ 3. REFERENCE role players and their contributions, not just star players
188
+ 4. ANALYZE strategic elements of plays, drafts, and team construction
189
+ 5. COMPARE current scenarios to historical team contexts when relevant
190
+ 6. INCLUDE specific stats, metrics, or technical details in your analysis
191
+ 7. ACKNOWLEDGE the complexity of football decisions rather than simplifying
192
+
193
+ Super fans expect: scheme-specific analysis, salary cap implications, and detailed player evaluations.
194
+ Super fans value: strategic insights, historical context, and acknowledgment of role players.
195
+
196
+ EXAMPLE RESPONSE FOR SUPER FAN (about the draft):
197
+ "The 49ers' draft strategy reflected their commitment to Shanahan's outside zone running scheme while addressing defensive depth issues. Their 3rd round selection provides versatility in the secondary with potential for both slot corner and safety roles, similar to how they've historically valued positional flexibility. The late-round offensive line selections show a continuing emphasis on athletic linemen who excel in zone blocking rather than power schemes, though they'll need development in pass protection techniques to become three-down players."
198
+ """
199
+ else:
200
+ # Default case - should not happen, but provides a fallback
201
+ return ""
202
+
203
  # Create the agent prompt
204
  agent_prompt = PromptTemplate.from_template(AGENT_SYSTEM_PROMPT)
205
 
 
271
  Returns:
272
  dict: The full response object from the agent
273
  """
274
+ print('[RESPONSE GEN] Starting generate_response function...')
275
+ print(f'[RESPONSE GEN] User input: {user_input}')
276
+ print(f'[RESPONSE GEN] Session ID: {session_id}')
277
+ print(f'[RESPONSE GEN] Current persona: {current_persona}')
278
 
279
  if not session_id:
280
  session_id = get_session_id()
281
+ print(f'[RESPONSE GEN] Generated new session ID: {session_id}')
282
 
283
  # Initialize memory with Zep history
284
  memory = initialize_memory_from_zep(session_id)
285
 
286
+ # DEBUG: Print conversation memory content
287
+ print(f"[DEBUG MEMORY] Memory type: {type(memory)}")
288
+ if hasattr(memory, 'chat_memory') and hasattr(memory.chat_memory, 'messages'):
289
+ print(f"[DEBUG MEMORY] Number of messages: {len(memory.chat_memory.messages)}")
290
+ for idx, msg in enumerate(memory.chat_memory.messages):
291
+ print(f"[DEBUG MEMORY] Message {idx}: {msg.type} - {msg.content[:100]}...")
292
+
293
+ # Get persona-specific instructions for the prompt
294
+ persona_instructions = get_persona_instructions()
295
+ print(f'[RESPONSE GEN] Using persona instructions for: {current_persona}')
296
+
297
+ # DEBUG: Print the persona instructions being used
298
+ print(f"[DEBUG INSTRUCTIONS] Persona instructions:\n{persona_instructions}")
299
+
300
+ # Create a personalized prompt by modifying the template with the current persona instructions
301
+ # Keep the original prompt format but insert the persona instructions at the appropriate place
302
+ persona_tag = f"[ACTIVE PERSONA: {current_persona}]"
303
+ highlighted_instructions = f"{persona_tag}\n\n{persona_instructions}\n\n{persona_tag}"
304
+ agent_system_prompt_with_persona = AGENT_SYSTEM_PROMPT.replace(
305
+ "{persona_instructions}", highlighted_instructions
306
+ )
307
+ personalized_prompt = PromptTemplate.from_template(agent_system_prompt_with_persona)
308
+
309
+ # Create a personalized agent with the updated prompt
310
+ personalized_agent = create_react_agent(agent_llm, tools, personalized_prompt)
311
+
312
+ # Create an agent executor with memory for this session and personalized prompt
313
  session_agent_executor = AgentExecutor(
314
+ agent=personalized_agent,
315
  tools=tools,
316
  verbose=True,
317
  memory=memory, # Use the memory we initialized
 
325
  try:
326
  print('Invoking session agent executor...')
327
  # The agent will now have access to the loaded history
328
+ persona_prefix = f"[RESPOND AS {current_persona.upper()}]: "
329
+ augmented_input = f"{persona_prefix}{user_input}"
330
+ response = session_agent_executor.invoke({"input": augmented_input})
331
 
332
  # Extract the output and format it for Streamlit
333
  if isinstance(response, dict):
prompts.py CHANGED
@@ -6,6 +6,8 @@ Do not answer any questions that do not relate to the 49ers, players, or fans.
6
 
7
  Do not answer any questions using your pre-trained knowledge, only use the information provided in the context.
8
 
 
 
9
  **IMPORTANT RESPONSE FORMATTING:**
10
  - When you use a tool that generates a visual component (like "Game Recap" or "Player Information Search"), your final text answer should *only* contain the summary text.
11
  - Do NOT include Markdown for images (like `![...](...)`), links, or other elements that are already visually represented by the component. The visual component will be displayed separately.
 
6
 
7
  Do not answer any questions using your pre-trained knowledge, only use the information provided in the context.
8
 
9
+ {persona_instructions}
10
+
11
  **IMPORTANT RESPONSE FORMATTING:**
12
  - When you use a tool that generates a visual component (like "Game Recap" or "Player Information Search"), your final text answer should *only* contain the summary text.
13
  - Do NOT include Markdown for images (like `![...](...)`), links, or other elements that are already visually represented by the component. The visual component will be displayed separately.
z_utils/zep_test.py CHANGED
@@ -4,6 +4,7 @@ This follows step 2 of Task 1.3 Memory & Persona Implementation.
4
  """
5
  import os
6
  import json
 
7
  from dotenv import load_dotenv
8
  from zep_cloud.client import Zep
9
  from langchain_core.messages import HumanMessage, AIMessage
@@ -19,11 +20,6 @@ if not ZEP_API_KEY:
19
  # Initialize Zep client
20
  zep = Zep(api_key=ZEP_API_KEY)
21
 
22
- # Use one of the session IDs from the task document
23
- # Casual fan: 241b3478c7634492abee9f178b5341cb
24
- # Super fan: dedcf5cb0d71475f976f4f66d98d6400
25
- SESSION_ID = "241b3478c7634492abee9f178b5341cb" # Using Casual fan session ID
26
-
27
  def retrieve_chat_history(session_id):
28
  """
29
  Retrieve chat history for a specific session from Zep.
@@ -71,10 +67,19 @@ def get_zep_history(session_id):
71
  return []
72
 
73
  def main():
74
- print(f"Retrieving chat history for session ID: {SESSION_ID}")
 
 
 
 
 
 
 
 
 
75
 
76
  # Get the memory for the session
77
- memory = retrieve_chat_history(SESSION_ID)
78
 
79
  if memory:
80
  print("\n===== MEMORY CONTEXT =====")
 
4
  """
5
  import os
6
  import json
7
+ import argparse
8
  from dotenv import load_dotenv
9
  from zep_cloud.client import Zep
10
  from langchain_core.messages import HumanMessage, AIMessage
 
20
  # Initialize Zep client
21
  zep = Zep(api_key=ZEP_API_KEY)
22
 
 
 
 
 
 
23
  def retrieve_chat_history(session_id):
24
  """
25
  Retrieve chat history for a specific session from Zep.
 
67
  return []
68
 
69
  def main():
70
+ # Set up command line argument parsing
71
+ parser = argparse.ArgumentParser(description='Retrieve chat history from Zep')
72
+ parser.add_argument('--session_id', type=str,
73
+ default="241b3478c7634492abee9f178b5341cb",
74
+ help='Session ID to retrieve (default: Casual Fan)')
75
+ args = parser.parse_args()
76
+
77
+ session_id = args.session_id
78
+
79
+ print(f"Retrieving chat history for session ID: {session_id}")
80
 
81
  # Get the memory for the session
82
+ memory = retrieve_chat_history(session_id)
83
 
84
  if memory:
85
  print("\n===== MEMORY CONTEXT =====")