Skip to content

Commit 4aec9d5

Browse files
committed
Include today's plan tasks in daily prompt generation
- Accept optional todays_plan in generate_daily_prompts and read today's plan in generate_prompts_for_date (entry_type="plan"). - Extract "## Action Items" from plan content (regex), parse markdown task lines, and categorize completed (- [x]) vs incomplete (- [ ]) tasks. - Add plan context to LLM input and dynamically inject instructions so at least one question addresses tasks using celebratory language for completed tasks and curious/exploratory language for incomplete tasks. - Improve LLM-response handling/logging: log parsed prompt count and include original count when padding. - Add re import and remove unused logging_config import.
1 parent d3a3e64 commit 4aec9d5

File tree

1 file changed

+76
-13
lines changed

1 file changed

+76
-13
lines changed

brain_core/template_generator.py

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""Generate AI prompts based on recent diary entries."""
22
from datetime import date
3-
from typing import List
3+
from typing import List, Optional
44
import logging
55
import time
6+
import re
67
from .entry_manager import DiaryEntry, EntryManager
78
from .llm_client import LLMClient
89
from .llm_analysis import _truncate_text
9-
from .logging_config import log_operation_timing
1010
from .constants import (
1111
DAILY_PROMPT_COUNT,
1212
WEEKLY_PROMPT_COUNT,
@@ -60,17 +60,20 @@ def is_sunday(entry_date: date) -> bool:
6060
def generate_daily_prompts(
6161
recent_entries: List[DiaryEntry],
6262
llm_client: LLMClient,
63-
target_date: date
63+
target_date: date,
64+
todays_plan: Optional[DiaryEntry] = None
6465
) -> List[str]:
65-
"""Generate 3 daily reflection prompts based on recent entries.
66+
"""Generate 3 daily reflection prompts based on recent entries and today's plan.
6667
67-
Uses LLM to analyze recent diary entries and create personalized,
68-
diverse reflection questions that reference specific past entries.
68+
Uses LLM to analyze recent diary entries and today's plan tasks to create
69+
personalized, diverse reflection questions that reference specific past entries
70+
and encourage reflection on task completion.
6971
7072
Args:
7173
recent_entries: List of recent diary entries for context (typically 3 days)
7274
llm_client: LLM client for prompt generation
7375
target_date: The date for which prompts are being generated
76+
todays_plan: Optional plan entry for today to reflect on task completion
7477
7578
Returns:
7679
List of 3 reflection prompt strings with [[YYYY-MM-DD]] backlinks
@@ -90,21 +93,61 @@ def generate_daily_prompts(
9093
if preview:
9194
context_parts.append(f"[[{date_str}]]: {preview}")
9295

96+
# Include today's plan tasks if available, categorized by completion status
97+
completed_tasks = []
98+
incomplete_tasks = []
99+
if todays_plan and todays_plan.content:
100+
date_str = target_date.isoformat()
101+
# Extract Action Items section from plan
102+
action_items_match = re.search(
103+
r"## Action Items\n(.*?)(?=\n##|$)",
104+
todays_plan.content,
105+
re.DOTALL
106+
)
107+
if action_items_match:
108+
tasks_text = action_items_match.group(1).strip()
109+
# Parse individual tasks and their completion status
110+
for line in tasks_text.split('\n'):
111+
if '- [x]' in line.lower() or '- [X]' in line.lower():
112+
# Completed task
113+
task = re.sub(r'- \[[xX]\]\s*', '', line).strip()
114+
if task:
115+
completed_tasks.append(task)
116+
elif '- [ ]' in line:
117+
# Incomplete task
118+
task = re.sub(r'- \[ \]\s*', '', line).strip()
119+
if task:
120+
incomplete_tasks.append(task)
121+
122+
# Add categorized tasks to context
123+
if completed_tasks or incomplete_tasks:
124+
plan_context = f"Today's Plan [[{date_str}]]:"
125+
if completed_tasks:
126+
plan_context += "\nCompleted: " + "; ".join(completed_tasks)
127+
if incomplete_tasks:
128+
plan_context += "\nNot completed: " + "; ".join(incomplete_tasks)
129+
context_parts.append(plan_context)
130+
93131
context = "\n\n".join(context_parts)
94132

95133
logger.debug(f"Generating daily prompts with {len(recent_entries)} recent entries")
96134

97135
system_prompt = """You are a thoughtful journaling assistant. Generate 3 reflective questions
98-
based on the user's recent diary entries. Questions should:
136+
based on the user's recent diary entries and today's plan tasks. Questions should:
99137
- MUST reference at least one specific entry using [[YYYY-MM-DD]] format in each question
100138
- Build on themes, questions, or situations mentioned in the referenced entries
139+
- If today's plan tasks are provided, include at least ONE question about tasks
101140
- Encourage deeper reflection
102141
- Be personal and specific (not generic)
103142
- Do NOT use emojis in your questions
104143
- Use plain text only
105144
145+
TASK-SPECIFIC LANGUAGE:
146+
- For COMPLETED tasks: Use celebratory/reflective language (e.g., "How did completing X feel?", "What did you learn from X?", "What went well with X?")
147+
- For INCOMPLETE tasks: Use curious/exploratory language (e.g., "What prevented you from completing X?", "Do you still want to pursue X?", "What would help you complete X?")
148+
106149
CRITICAL: Each of the 3 questions MUST address DIFFERENT topics from the entries.
107-
- Question 1: Focus on one theme/topic
150+
- Question 1: Focus on one theme/topic (can be about today's tasks if provided)
108151
- Question 2: Focus on a DIFFERENT theme/topic
109152
- Question 3: Focus on yet ANOTHER distinct theme/topic
110153
@@ -114,11 +157,25 @@ def generate_daily_prompts(
114157
115158
Format each question on a new line, numbered 1-3. Be concise."""
116159

117-
user_prompt = f"""Based on these recent diary entries, generate 3 thoughtful reflection prompts:
160+
has_plan = todays_plan and "Today's Plan" in context
161+
has_completed = completed_tasks and has_plan
162+
has_incomplete = incomplete_tasks and has_plan
163+
164+
plan_instruction = ""
165+
if has_plan:
166+
if has_completed and has_incomplete:
167+
plan_instruction = "\n\nIMPORTANT: Today's plan includes both completed and incomplete tasks. Generate at least ONE question that:\n- Uses CELEBRATORY language for completed tasks (e.g., 'How did completing X feel from [[date]]?', 'What did you learn from finishing X from [[date]]?')\n- Uses CURIOUS language for incomplete tasks (e.g., 'What prevented you from completing X from [[date]]?', 'Do you still want to pursue X from [[date]]?')"
168+
elif has_completed:
169+
plan_instruction = "\n\nIMPORTANT: Today's plan tasks were completed. Generate at least ONE question using CELEBRATORY language (e.g., 'How did completing X feel from [[date]]?', 'What did you learn from finishing X from [[date]]?', 'What went well with X from [[date]]?')."
170+
elif has_incomplete:
171+
plan_instruction = "\n\nIMPORTANT: Today's plan tasks were not completed. Generate at least ONE question using CURIOUS/EXPLORATORY language (e.g., 'What prevented you from completing X from [[date]]?', 'Do you still want to pursue X from [[date]]?', 'What would help you complete X from [[date]]?')."
172+
173+
user_prompt = f"""Based on these recent diary entries{' and today\'s plan tasks' if has_plan else ''}, generate 3 thoughtful reflection prompts:
118174
119175
{context}
120176
121177
STEP 1: Scan ALL topics mentioned across the entries. List distinct themes like:
178+
- Today's planned tasks/goals (if provided - focus on completion/progress)
122179
- Professional work (teaching, projects, sessions)
123180
- Personal relationships (partner, family, friends, colleagues)
124181
- Health & wellness (sleep, diet, exercise, mental health)
@@ -130,7 +187,7 @@ def generate_daily_prompts(
130187
STEP 3: Generate 1 question for EACH of those 3 different themes.
131188
132189
Example of GOOD diversity:
133-
- Q1: About teaching/work [[date]]
190+
- Q1: About task completion from today's plan [[date]]
134191
- Q2: About relationship with partner [[date]]
135192
- Q3: About sleep/health habits [[date]]
136193
@@ -139,7 +196,7 @@ def generate_daily_prompts(
139196
- Q2: About Spanish office hours [[date]] ← Same topic area!
140197
- Q3: About teaching community [[date]] ← Same topic area!
141198
142-
Each prompt MUST include at least one [[YYYY-MM-DD]] backlink."""
199+
Each prompt MUST include at least one [[YYYY-MM-DD]] backlink.{plan_instruction}"""
143200

144201
try:
145202
start_time = time.time()
@@ -155,16 +212,19 @@ def generate_daily_prompts(
155212

156213
# Parse prompts from response
157214
prompts = _parse_prompts_from_response(response, DAILY_PROMPT_COUNT)
215+
216+
logger.debug(f"Parsed {len(prompts)} prompts from LLM response")
158217

159218
# Ensure we have exactly the right number of prompts
160219
if len(prompts) >= DAILY_PROMPT_COUNT:
161220
logger.debug(f"Generated {DAILY_PROMPT_COUNT} daily prompts in {elapsed:.2f}s")
162221
return prompts[:DAILY_PROMPT_COUNT]
163222
elif prompts:
164223
# If we got some but not enough, pad with generic ones
224+
original_count = len(prompts)
165225
while len(prompts) < DAILY_PROMPT_COUNT:
166226
prompts.append("What else is on your mind?")
167-
logger.debug(f"Generated {len(prompts)} daily prompts (padded) in {elapsed:.2f}s")
227+
logger.debug(f"Generated {original_count} daily prompts, padded to {len(prompts)} in {elapsed:.2f}s")
168228
return prompts
169229
else:
170230
# Fall back to generic prompts if parsing failed
@@ -321,11 +381,14 @@ def generate_prompts_for_date(
321381
past_dates = entry_manager.get_past_calendar_days(target_date, PROMPT_CONTEXT_DAYS)
322382
recent_entries = entry_manager.get_entries_for_dates(past_dates)
323383

384+
# Try to read today's plan for task completion reflection
385+
todays_plan = entry_manager.read_entry(target_date, entry_type="plan")
386+
324387
# Sunday gets weekly prompts, other days get daily prompts
325388
if is_sunday(target_date):
326389
# For Sunday, look back for weekly context
327390
past_week_dates = entry_manager.get_past_calendar_days(target_date, WEEKLY_CONTEXT_DAYS)
328391
week_entries = entry_manager.get_entries_for_dates(past_week_dates)
329392
return generate_weekly_prompts(week_entries, llm_client, target_date)
330393
else:
331-
return generate_daily_prompts(recent_entries, llm_client, target_date)
394+
return generate_daily_prompts(recent_entries, llm_client, target_date, todays_plan)

0 commit comments

Comments
 (0)