6 Commits

Author SHA1 Message Date
b96e0e0008 slimming before fastapi refactor 2026-01-02 22:10:13 -07:00
06b6340731 Merge pull request 'implemented offline cache' (#1) from caching into master
Reviewed-on: #1
2026-01-03 04:46:16 +00:00
e4292478a1 remove unused imports and function 2026-01-02 21:45:45 -07:00
16eaceb70a Readme tweaks and testing 2026-01-02 21:23:04 -07:00
5e89e730ee full pool filling working 2026-01-02 21:18:26 -07:00
e42b749baf move file write to display of most recent 2026-01-02 20:37:31 -07:00
14 changed files with 451 additions and 720 deletions

View File

@@ -62,7 +62,6 @@ A Python tool that uses OpenAI-compatible AI endpoints to generate creative writ
daily-journal-prompt/
├── README.md # This documentation
├── generate_prompts.py # Main Python script with rich interface
├── simple_generate.py # Lightweight version without rich dependency
├── run.sh # Convenience bash script
├── test_project.py # Test suite for the project
├── requirements.txt # Python dependencies
@@ -78,7 +77,6 @@ daily-journal-prompt/
### File Descriptions
- **generate_prompts.py**: Main Python script with interactive mode, rich formatting, and full features
- **simple_generate.py**: Lightweight version without rich dependency for basic usage
- **run.sh**: Convenience bash script for easy execution
- **test_project.py**: Test suite to verify project setup
- **requirements.txt**: Python dependencies (openai, python-dotenv, rich)
@@ -102,8 +100,6 @@ chmod +x run.sh
# Interactive mode with rich interface
./run.sh --interactive
# Simple version without rich dependency
./run.sh --simple
# Show statistics
./run.sh --stats
@@ -132,8 +128,6 @@ python generate_prompts.py --interactive
# Show statistics
python generate_prompts.py --stats
# Simple version (no rich dependency needed)
python simple_generate.py
```
### Testing Your Setup
@@ -175,7 +169,7 @@ python generate_prompts.py --help
### Interactive Mode Options
1. **Draw prompts from pool (no API call)**: Displays prompts from the pool file
1. **Draw prompts from pool (no API call)**: Displays and consumes prompts from the pool file
2. **Fill prompt pool using API**: Generates new prompts using AI and adds them to pool
3. **View pool statistics**: Shows pool size, target size, and available sessions
4. **View history statistics**: Shows historic prompt count and capacity

View File

@@ -4,15 +4,14 @@ Payload:
The previous 60 prompts have been provided as a JSON array for reference.
Guidelines:
Topics can be diverse.
Please generate 6 writing prompts in English with a few guidelines.
Please generate some number of individual writing prompts in English following these guidelines.
Topics can be diverse, and the whole batch should have no outright repetition.
These are meant to inspire one to two pages of writing in a journal as exercise.
The prompts should be between 500 and 1000 characters in length.
Prompt History:
The provided history brackets two mechanisms.
The history will allow for reducing repetition, however some thematic overlap is acceptable. Try harder to avoid overlap with lower indices in the array.
As the user discards prompts, the themes will be very slowly steered, so it's okay to take some inspiration from it.
As the user discards prompts, the themes will be very slowly steered, so it's okay to take some inspiration from the history.
Expected Output:
Output as a JSON list with the requested number of elements.

View File

@@ -9,9 +9,7 @@ import json
import sys
import argparse
import configparser
from datetime import datetime
from typing import List, Dict, Any, Optional
from pathlib import Path
from openai import OpenAI
from dotenv import load_dotenv
@@ -75,7 +73,8 @@ class JournalPromptGenerator:
self.settings = {
'min_length': 500,
'max_length': 1000,
'num_prompts': 6
'num_prompts': 6,
'cached_pool_volume': 20 # Default value
}
try:
@@ -96,6 +95,12 @@ class JournalPromptGenerator:
if 'num_prompts' in prompts_section:
self.settings['num_prompts'] = int(prompts_section['num_prompts'])
# Load cached_pool_volume from prefetch section
if 'prefetch' in config:
prefetch_section = config['prefetch']
if 'cached_pool_volume' in prefetch_section:
self.settings['cached_pool_volume'] = int(prefetch_section['cached_pool_volume'])
except FileNotFoundError:
self.console.print("[yellow]Warning: settings.cfg not found, using default values[/yellow]")
except ValueError as e:
@@ -104,24 +109,10 @@ class JournalPromptGenerator:
self.console.print(f"[yellow]Warning: Error reading settings.cfg: {e}, using default values[/yellow]")
def _load_prompt_template(self):
"""Load the prompt template from ds_prompt.txt and update with config values."""
"""Load the prompt template from ds_prompt.txt."""
try:
with open("ds_prompt.txt", "r") as f:
template = f.read()
# Replace hardcoded values with config values
template = template.replace(
"between 500 and 1000 characters",
f"between {self.settings['min_length']} and {self.settings['max_length']} characters"
)
# Replace the number of prompts (6) with config value
template = template.replace(
"Please generate 6 writing prompts",
f"Please generate {self.settings['num_prompts']} writing prompts"
)
self.prompt_template = template
self.prompt_template = f.read()
except FileNotFoundError:
self.console.print("[red]Error: ds_prompt.txt not found[/red]")
sys.exit(1)
@@ -205,37 +196,11 @@ class JournalPromptGenerator:
table.add_row("Prompts in pool", str(total_prompts))
table.add_row("Prompts per session", str(self.settings['num_prompts']))
# Get cached_pool_volume from settings if available
cached_pool_volume = 20 # Default
try:
config = configparser.ConfigParser()
config.read('settings.cfg')
if 'prefetch' in config and 'cached_pool_volume' in config['prefetch']:
cached_pool_volume = int(config['prefetch']['cached_pool_volume'])
except:
pass
table.add_row("Target pool size", str(cached_pool_volume))
table.add_row("Target pool size", str(self.settings['cached_pool_volume']))
table.add_row("Available sessions", str(total_prompts // self.settings['num_prompts']))
self.console.print(table)
def _renumber_prompts(self):
"""Renumber all prompts to maintain prompt00-prompt59 range."""
renumbered_prompts = []
for i, prompt_dict in enumerate(self.historic_prompts):
# Get the prompt text from the first key in the dictionary
prompt_key = list(prompt_dict.keys())[0]
prompt_text = prompt_dict[prompt_key]
# Create new prompt with correct numbering
new_prompt_key = f"prompt{i:02d}"
renumbered_prompts.append({
new_prompt_key: prompt_text
})
self.historic_prompts = renumbered_prompts
def add_prompt_to_history(self, prompt_text: str):
"""
@@ -269,16 +234,6 @@ class JournalPromptGenerator:
self.historic_prompts = updated_prompts
self._save_historic_prompts()
def _prepare_prompt(self) -> str:
"""Prepare the full prompt with historic context."""
# Format historic prompts for the AI
if self.historic_prompts:
historic_context = json.dumps(self.historic_prompts, indent=2)
full_prompt = f"{self.prompt_template}\n\nPrevious prompts:\n{historic_context}"
else:
full_prompt = self.prompt_template
return full_prompt
def _parse_ai_response(self, response_content: str) -> List[str]:
"""
@@ -414,12 +369,12 @@ class JournalPromptGenerator:
return content.strip()
def generate_prompts(self) -> List[str]:
"""Generate new journal prompts using AI."""
self.console.print("\n[cyan]Generating new journal prompts...[/cyan]")
def generate_specific_number_of_prompts(self, count: int) -> List[str]:
"""Generate a specific number of journal prompts using AI."""
self.console.print(f"\n[cyan]Generating {count} new journal prompts...[/cyan]")
# Prepare the prompt
full_prompt = self._prepare_prompt()
# Prepare the prompt with specific count
full_prompt = self._prepare_prompt_with_count(count)
# Show progress
with Progress(
@@ -450,18 +405,111 @@ class JournalPromptGenerator:
return []
# Parse the response
new_prompts = self._parse_ai_response(response_content)
new_prompts = self._parse_ai_response_with_count(response_content, count)
if not new_prompts:
self.console.print("[red]Error: Could not parse any prompts from AI response[/red]")
return []
# Note: Prompts are NOT added to historic_prompts here
# They will be added only when the user chooses one in interactive mode
# via the add_prompt_to_history() method
return new_prompts
def _prepare_prompt_with_count(self, count: int) -> str:
"""Prepare the full prompt with historic context and specific count."""
# Start with the base template
template = self.prompt_template
# Add the instruction for the specific number of prompts
# This will be added to the prompt since it's being removed from ds_prompt.txt
prompt_instruction = f"Please generate {count} writing prompts, each between {self.settings['min_length']} and {self.settings['max_length']} characters."
# Format historic prompts for the AI
if self.historic_prompts:
historic_context = json.dumps(self.historic_prompts, indent=2)
full_prompt = f"{template}\n\n{prompt_instruction}\n\nPrevious prompts:\n{historic_context}"
else:
full_prompt = f"{template}\n\n{prompt_instruction}"
return full_prompt
def _parse_ai_response_with_count(self, response_content: str, expected_count: int) -> List[str]:
"""
Parse the AI response to extract new prompts with specific expected count.
"""
# First, try to clean up the response content
cleaned_content = self._clean_ai_response(response_content)
try:
# Try to parse as JSON
data = json.loads(cleaned_content)
# Check if data is a list
if isinstance(data, list):
# Return the list of prompt strings directly
# Ensure we have the correct number of prompts
if len(data) >= expected_count:
return data[:expected_count]
else:
self.console.print(f"[yellow]Warning: AI returned {len(data)} prompts, expected {expected_count}[/yellow]")
return data
elif isinstance(data, dict):
# Fallback for old format: dictionary with newprompt0, newprompt1, etc.
self.console.print("[yellow]Warning: AI returned dictionary format, expected list format[/yellow]")
new_prompts = []
for i in range(expected_count):
key = f"newprompt{i}"
if key in data:
new_prompts.append(data[key])
return new_prompts
else:
self.console.print(f"[yellow]Warning: AI returned unexpected data type: {type(data)}[/yellow]")
return []
except json.JSONDecodeError:
# If not valid JSON, try to extract prompts from text
self.console.print("[yellow]Warning: AI response is not valid JSON, attempting to extract prompts...[/yellow]")
# Look for patterns in the text
lines = response_content.strip().split('\n')
new_prompts = []
for i, line in enumerate(lines[:expected_count]): # Take first N non-empty lines
line = line.strip()
if line and len(line) > 50: # Reasonable minimum length for a prompt
new_prompts.append(line)
return new_prompts
def fill_pool_to_target(self) -> int:
"""Fill the prompt pool to reach cached_pool_volume target with a single API call."""
target_volume = self.settings['cached_pool_volume']
current_pool_size = len(self.pool_prompts)
if current_pool_size >= target_volume:
self.console.print(f"[green]Pool already has {current_pool_size} prompts, target is {target_volume}[/green]")
return 0
prompts_needed = target_volume - current_pool_size
self.console.print(f"[cyan]Current pool size: {current_pool_size}[/cyan]")
self.console.print(f"[cyan]Target pool size: {target_volume}[/cyan]")
self.console.print(f"[cyan]Prompts needed: {prompts_needed}[/cyan]")
# Make a single API call to generate exactly the number of prompts needed
self.console.print(f"\n[cyan]Making single API call to generate {prompts_needed} prompts...[/cyan]")
new_prompts = self.generate_specific_number_of_prompts(prompts_needed)
if new_prompts:
# Add all generated prompts to pool
self.pool_prompts.extend(new_prompts)
total_added = len(new_prompts)
self.console.print(f"[green]Added {total_added} prompts to pool[/green]")
# Save the updated pool
self._save_pool_prompts()
return total_added
else:
self.console.print("[red]Failed to generate prompts[/red]")
return 0
def display_prompts(self, prompts: List[str]):
"""Display generated prompts in a nice format."""
self.console.print("\n" + "="*60)
@@ -502,6 +550,18 @@ class JournalPromptGenerator:
))
while True:
# Display most recent prompt from history if available
if self.historic_prompts:
most_recent_prompt = self.historic_prompts[0] # prompt00 is always first
prompt_key = list(most_recent_prompt.keys())[0]
prompt_text = most_recent_prompt[prompt_key]
self.console.print("\n" + "="*60)
self.console.print("[bold cyan]📝 CURRENT PROMPT 📝[/bold cyan]")
self.console.print("="*60)
self.console.print(f"\n[cyan]{prompt_text}[/cyan]\n")
self.console.print("="*60 + "\n")
self.console.print("\n[bold]Options:[/bold]")
self.console.print("1. Draw prompts from pool (no API call)")
self.console.print("2. Fill prompt pool using API")
@@ -517,40 +577,27 @@ class JournalPromptGenerator:
if drawn_prompts:
self.display_prompts(drawn_prompts)
# Ask if user wants to save a prompt
if Confirm.ask("\nWould you like to save one of these prompts to a file?"):
prompt_num = Prompt.ask(
"Which prompt number would you like to save?",
choices=[str(i) for i in range(1, len(drawn_prompts) + 1)],
default="1"
)
# Ask which prompt to add to history
prompt_num = Prompt.ask(
"\nWhich prompt number would you like to add to history?",
choices=[str(i) for i in range(1, len(drawn_prompts) + 1)],
default="1"
)
prompt_idx = int(prompt_num) - 1
prompt_text = drawn_prompts[prompt_idx]
prompt_idx = int(prompt_num) - 1
prompt_text = drawn_prompts[prompt_idx]
# Save to file
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"journal_prompt_{timestamp}.txt"
with open(filename, "w") as f:
f.write(f"Journal Prompt - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write("="*50 + "\n\n")
f.write(prompt_text)
f.write("\n\n" + "="*50 + "\n")
f.write("Happy writing! ✍️\n")
self.console.print(f"[green]Prompt saved to {filename}[/green]")
# Add the chosen prompt to historic prompts cyclic buffer
self.add_prompt_to_history(prompt_text)
self.console.print(f"[green]Prompt added to history as prompt00[/green]")
# Add the chosen prompt to historic prompts cyclic buffer
self.add_prompt_to_history(prompt_text)
self.console.print(f"[green]Prompt added to history as prompt00[/green]")
elif choice == "2":
# Fill prompt pool using API
new_prompts = self.generate_prompts()
if new_prompts:
self.add_prompts_to_pool(new_prompts)
self.console.print(f"[green]Added {len(new_prompts)} prompts to pool[/green]")
# Fill prompt pool to target volume using API
total_added = self.fill_pool_to_target()
if total_added > 0:
self.console.print(f"[green]Successfully added {total_added} prompts to pool[/green]")
else:
self.console.print("[yellow]No prompts were added to pool[/yellow]")
elif choice == "3":
self.show_pool_stats()
@@ -602,11 +649,12 @@ def main():
elif args.pool_stats:
generator.show_pool_stats()
elif args.fill_pool:
# Fill prompt pool using API
new_prompts = generator.generate_prompts()
if new_prompts:
generator.add_prompts_to_pool(new_prompts)
generator.console.print(f"[green]Added {len(new_prompts)} prompts to pool[/green]")
# Fill prompt pool to target volume using API
total_added = generator.fill_pool_to_target()
if total_added > 0:
generator.console.print(f"[green]Successfully added {total_added} prompts to pool[/green]")
else:
generator.console.print("[yellow]No prompts were added to pool[/yellow]")
elif args.interactive:
generator.interactive_mode()
else:

View File

@@ -1,182 +1,182 @@
[
{
"prompt00": "Observe the sky right now, in this exact moment. Describe its color, cloud formations, light quality, and movement with meticulous attention. Then, let this observation launch you into a reflection on scale and perspective. Consider the atmospheric phenomena occurring beyond your sight\u2014jet streams, weather systems, celestial motions. How does contemplating the vast, impersonal sky make you feel about your current concerns, joys, or plans? Write about the tension between the immediacy of your personal world and the silent, ongoing spectacle above."
"prompt00": "Choose a street you walk down often. Today, walk it with the mission of noticing five things you've never seen before. They can be tiny: a crack in the pavement shaped like a continent, a particular stain on a wall, a hidden doorbell. Document each discovery in detail. Then, reflect on the phenomenon of selective attention. What had you been filtering out, and why? How does this exercise change your sense of the familiar path?"
},
{
"prompt01": "Choose a machine or appliance in your home that has a distinct sound\u2014a refrigerator hum, a heater's click, a fan's whir. Close your eyes and listen to it for a full minute. Describe its rhythm, pitch, and constancy. Now, personify this sound. What is its personality? Is it a loyal guardian, a complaining old friend, a distant observer? Write a monologue from its perspective about the life it monitors within these walls. What has it learned about you from its unchanging post?"
"prompt01": "Imagine you could host a dinner party for three fictional characters from different books, films, or myths. Who would you invite and why? Don't just list them. Set the scene: the table setting, the menu, the lighting. Write the conversation that unfolds. What would they argue about? What surprising common ground might they find? How would their presence challenge or affirm your own worldview? Let the dialogue reveal their core natures."
},
{
"prompt02": "Recall a public space you frequented often in the past but have not visited in years (a library, a park, a diner, a store). Reconstruct it from memory in vivid detail. Then, imagine returning to it today. Describe the inevitable changes\u2014the renovations, the new faces, the faded paint. But also, hunt for the one thing that remains exactly, miraculously the same. How does the coexistence of change and permanence in this space make you feel about the passage of your own time?"
"prompt02": "Describe a taste you loved as a child but have since grown indifferent to or now dislike. Recreate the sensory memory of that taste with precision. What was its context? Who was with you? Now, analyze the shift. Did your palate change, or did the associations sour? Is there a way to reclaim the innocent pleasure of that taste, or is its loss a necessary marker of growing up? Explore the nostalgia and slight grief in outgrowing a flavor."
},
{
"prompt03": "\"newprompt3\": \"Recall a teacher, mentor, or elder who said something to you in passing that you have never forgotten. It might have been a compliment, a criticism, or an offhand observation. Reconstruct the scene. Why did their words carry such weight? How have you turned them over in your mind since? Explore the power of brief, seemingly casual utterances to shape a person's self-concept.\","
"prompt03": "Contemplate the concept of 'waste' in your daily life. Choose one item destined for the trash or recycling. Trace its journey backwards from your hand to its origins as raw material. Then, project its journey forward after it leaves your custody. What systems does it touch? What hands might process it? Write a biography of this discarded object, granting it dignity and narrative. How does this perspective alter your sense of responsibility and connection?"
},
{
"prompt04": "\"newprompt0\": \"Write a detailed portrait of a tree you know well\u2014not just its appearance, but its history in that spot, the way its branches move in different winds, the creatures that inhabit it, the shadows it casts at various hours. Imagine its perspective across seasons and years. What has it witnessed? What would it say about change, resilience, or stillness if it could speak? Let the tree become a mirror for your own sense of place and time.\","
"prompt04": "Invent a small, personal ritual you could perform to mark the transition from one part of your day to another (e.g., work to home, waking to activity). Describe each step with deliberate, sensory care. What object is involved? What words, if any, are said? How does your posture change? The goal isn't superstition, but mindfulness. Write about performing this ritual for a week. What subtle shifts in your awareness might it create? How does deliberately carving out a threshold affect your experience of time?"
},
{
"prompt05": "Describe a memory you have that is tied to a specific smell. Don't just tell the story of the event; focus on describing the scent itself in as much detail as possible\u2014its texture, its weight in the air, its nuances. How does conjuring that smell now make you feel in your body? Let the description of the aroma lead you back into the memory's landscape."
"prompt05": "Consider a piece of music that feels like a physical space to you\u2014a song you can walk into. Describe the architecture of this auditory landscape. What is the floor made of? How high is the ceiling? What color is the light? Where are the shadows? What happens to your body and breath as you move through its sections\u2014the verses, the chorus, the bridge? Is it a place of refuge, confrontation, or memory? Explore how sound can build an environment you inhabit, not just hear."
},
{
"prompt06": "Write a letter to your 15-year-old self. Be kind, be blunt, be humorous, or be stern. What do you know now that you desperately needed to hear then? What mystery about your future life could you tantalizingly hint at without giving it all away? Don't just give advice; try to capture the voice and tone you wish an older, wiser person had used with you."
"prompt06": "Describe your ideal sanctuary\u2014not a grand fantasy, but a realistically attainable space you could create. Detail its location, size, lighting, furnishings, and most importantly, its rules (e.g., 'no devices,' 'only music without words,' 'must contain something living'). What specific activities would you do there? What state of mind does this space architecturally encourage? How would visiting it regularly change the rhythm of your weeks?"
},
{
"prompt07": "You find a forgotten door in a place you know well\u2014your home, your workplace, your daily park. It wasn't there yesterday. You open it. Describe what is on the other side using only sensory details: sight, sound, temperature, smell. Do not explain its purpose or origin. Simply document the experience of crossing that threshold."
"prompt07": "Describe a skill or piece of knowledge you possess that you learned in an unconventional, self-taught, or accidental way. Detail the messy, non-linear process of that learning. Who or what were your unlikely teachers? Celebrate the inefficiency and personal quirks of your method. How does this 'uncurated' knowledge differ in feel and application from something you were formally taught?"
},
{
"prompt08": "Make a list of ten tiny, perfect moments from the past month that no one else probably noticed or would remember. The way light fell on a spoon, a stranger's half-smile, the sound of rain stopping. Elaborate on at least three of them, expanding them into full vignettes. Why did these micro-moments stick with you?"
"prompt08": "Think of a skill or piece of knowledge you possess that feels almost instinctual, something you can do without conscious thought (like riding a bike, typing, or a native language's grammar). Deconstruct this automatic competence. Describe the first clumsy attempts to learn it, the plateau of frustration, the moment it 'clicked' into muscle memory. Explore the duality of this knowledge: how it is both a part of you and a separate tool. What does this ingrained ability allow you to forget, and what freedom does that forgetfulness grant?"
},
{
"prompt09": "Invent a mythological creature for a modern urban setting. What does it look like? What is its behavior and habitat (e.g., subway tunnels, server farms, air vents)? What folklore do people whisper about it? What does it symbolize\u2014anxiety, forgotten connections, hope? Describe a recent 'sighting' of this creature in vivid detail."
"prompt09": "Choose a natural element you feel a kinship with\u2014fire, stone, water, wind, or earth. Personify it deeply: give it desires, memories, a voice. Write a monologue from its perspective about its ancient, slow existence and its observations of human brevity and frenzy. Then, write about a moment in your life when you felt most aligned with this element's essence. How does connecting with this primal force alter your sense of time and scale?"
},
{
"prompt10": "Choose an object in your immediate line of sight that is not electronic. Write its biography. Where was it made? Who owned it before you? What conversations has it overheard? What secrets does it hold? What small damages or wear marks does it have, and what story does each tell? Give this ordinary item an epic history."
"prompt10": "Imagine you could preserve one hour from your recent memory in a vial, to be re-experienced fully at a future date. Which hour would you choose? Describe it not just as events, but as a full sensory immersion: the light, the sounds, the emotional texture, the quality of the air. Why is this particular slice of time worth encapsulating? What fears or hopes do you have about opening that vial years from now? Write about the desire to hold onto a fleeting feeling, and the wisdom or melancholy that might come from revisiting it."
},
{
"prompt11": "Describe your current emotional state as a weather system. Is it a still, high-pressure fog? A sudden, sharp hailstorm? A lingering, humid drizzle? Map its boundaries, its intensity, its forecast. What terrain does it move over\u2014the mountains of your responsibilities, the plains of your routine? How does it affect your internal climate?"
"prompt11": "Contemplate the concept of 'enough.' In our culture of more, what does sufficiency feel like in your body and mind? Describe a recent moment when you felt truly, deeply 'enough'\u2014not in lack, not in excess. It could be related to time, accomplishment, possessions, or love. What were the conditions? How did it settle in your posture or breath? Then, contrast this with a sphere of your life where the feeling of 'not enough' persistently hums. Explore the tension between these two states. What would it take to cultivate more of the former?"
},
{
"prompt12": "Recall a time you were deeply embarrassed. Write about it from the perspective of a sympathetic observer who was there\u2014or invent one. How might they have perceived the event? What context or kindness might they have seen that you, in your self-focused shame, completely missed? Reframe the memory through their eyes."
"prompt12": "Recall a piece of bad advice you once received and followed. Who gave it and why did you trust them? Walk through the consequences, large or small. Now, reframe that experience not as a mistake, but as a necessary detour. What did you learn about yourself, about advice, or about the gap between theory and practice that you couldn't have learned any other way? Write the thank-you note you would send to that advisor today, acknowledging the unexpected gift of their misguidance."
},
{
"prompt13": "What skill or craft have you always wanted to learn but haven't? Immerse yourself in a detailed fantasy of mastering it. Describe the feel of the tools in your hands, the initial frustrations, the first small success, the growing muscle memory. What does the final, perfected product of your labor look or feel like? Live in that imagined\u6210\u5c31\u611f."
"prompt13": "You are tasked with composing a guided audio meditation for a stranger experiencing intense anxiety. Write the script. Use your voice to lead them through a physical space\u2014a forest path, a quiet beach, a cozy room. Describe not just visuals, but textures, sounds, temperatures, and the rhythm of breathing. What reassurance would you offer without being trite? What simple, grounding observations would you point out? Craft a verbal sanctuary meant to hold someone's fragile attention."
},
{
"prompt14": "Write a dialogue between two aspects of yourself (e.g., Your Ambitious Self and Your Tired Self; Your Cynical Self and Your Hopeful Self). Give them distinct voices. What are they arguing about, negotiating, or planning? Don't just state positions; let them bicker, persuade, or sit in silence together. See where the conversation goes."
"prompt14": "Recall a piece of clothing you once owned and loved, but have since lost, given away, or worn out. Recreate it stitch by stitch in words\u2014its fabric, its fit, its smell, the way it moved with you. Narrate its life with you: the occasions it witnessed, the stains it earned, the comfort it provided. What did wearing it allow you to feel or project? Write an ode to this second skin, and explore what its absence represents."
},
{
"prompt15": "Describe your childhood home from the perspective of a small animal (a mouse, a squirrel, a bird) that lived there concurrently with you. What did this creature notice about your family's rhythms, the layout, the dangers, and the treasures (crumbs, cozy materials)? How did it perceive you, the giant human child?"
"prompt15": "Test prompt"
},
{
"prompt16": "List five paths your life could have taken if you'd made one different choice. Briefly outline each alternate reality. Then, choose one and dive deep: write a journal entry from that version of you today. What are their worries, joys, and regrets? How is their voice similar to or different from your own?"
"prompt16": "Observe the sky right now, in this exact moment. Describe its color, cloud formations, light quality, and movement with meticulous attention. Then, let this observation launch you into a reflection on scale and perspective. Consider the atmospheric phenomena occurring beyond your sight\u2014jet streams, weather systems, celestial motions. How does contemplating the vast, impersonal sky make you feel about your current concerns, joys, or plans? Write about the tension between the immediacy of your personal world and the silent, ongoing spectacle above."
},
{
"prompt17": "Think of a person you see regularly but do not know (a barista, a neighbor, a commuter). Invent a rich, secret inner life for them. What profound private mission are they on? What hidden talent do they possess? What great sorrow or hope are they carrying today as they serve your coffee or stand on the platform? Write from their perspective."
"prompt17": "Choose a machine or appliance in your home that has a distinct sound\u2014a refrigerator hum, a heater's click, a fan's whir. Close your eyes and listen to it for a full minute. Describe its rhythm, pitch, and constancy. Now, personify this sound. What is its personality? Is it a loyal guardian, a complaining old friend, a distant observer? Write a monologue from its perspective about the life it monitors within these walls. What has it learned about you from its unchanging post?"
},
{
"prompt18": "What is a belief you held strongly five or ten years ago that you have since questioned or abandoned? Trace the evolution of that change. Was it a sudden shattering or a slow erosion? What person, experience, or piece of information was the catalyst? Describe the feeling of the ground shifting under that particular piece of your worldview."
"prompt18": "Recall a public space you frequented often in the past but have not visited in years (a library, a park, a diner, a store). Reconstruct it from memory in vivid detail. Then, imagine returning to it today. Describe the inevitable changes\u2014the renovations, the new faces, the faded paint. But also, hunt for the one thing that remains exactly, miraculously the same. How does the coexistence of change and permanence in this space make you feel about the passage of your own time?"
},
{
"prompt19": "Describe a common, mundane process (making tea, tying your shoes, doing laundry) in extreme, almost absurdly epic detail, as if you were writing a sacred manual or a scientific treatise for an alien civilization. Break down every micro-action, every sensation, every potential variable. Find the profound in the procedural."
"prompt19": "\"newprompt3\": \"Recall a teacher, mentor, or elder who said something to you in passing that you have never forgotten. It might have been a compliment, a criticism, or an offhand observation. Reconstruct the scene. Why did their words carry such weight? How have you turned them over in your mind since? Explore the power of brief, seemingly casual utterances to shape a person's self-concept.\","
},
{
"prompt20": "You are given a suitcase and told you must leave your home in one hour, not knowing if or when you'll return. You can only take what fits in the case. Describe, in real-time, the frantic and deliberate process of choosing. What practical items make the cut? What irreplaceable tokens? What do you leave behind, and what does that feel like?"
"prompt20": "\"newprompt0\": \"Write a detailed portrait of a tree you know well\u2014not just its appearance, but its history in that spot, the way its branches move in different winds, the creatures that inhabit it, the shadows it casts at various hours. Imagine its perspective across seasons and years. What has it witnessed? What would it say about change, resilience, or stillness if it could speak? Let the tree become a mirror for your own sense of place and time.\","
},
{
"prompt21": "Write about water in three different forms: as a memory involving a body of water (ocean, river, bath), as a description of drinking a glass of water right now, and as a metaphor for an emotion. Move seamlessly between these three aspects. Let the fluidity of the theme connect them."
"prompt21": "Describe a memory you have that is tied to a specific smell. Don't just tell the story of the event; focus on describing the scent itself in as much detail as possible\u2014its texture, its weight in the air, its nuances. How does conjuring that smell now make you feel in your body? Let the description of the aroma lead you back into the memory's landscape."
},
{
"prompt22": "What does silence sound like in your current environment? Don't just say 'quiet.' Describe the layers of sound that actually constitute the silence\u2014the hums, ticks, distant rumbles, the sound of your own body. Now, project what this same space sounded like 100 years ago, and what it might sound like 100 years from now."
"prompt22": "Write a letter to your 15-year-old self. Be kind, be blunt, be humorous, or be stern. What do you know now that you desperately needed to hear then? What mystery about your future life could you tantalizingly hint at without giving it all away? Don't just give advice; try to capture the voice and tone you wish an older, wiser person had used with you."
},
{
"prompt23": "Create a recipe for a dish that represents your current life phase. List ingredients (e.g., \"two cups of transition,\" \"a pinch of anxiety,\" \"a steady base of routine\"). Write the instructions, including the method, cooking time, and necessary equipment. Describe the final product's taste, texture, and who it should be shared with."
"prompt23": "You find a forgotten door in a place you know well\u2014your home, your workplace, your daily park. It wasn't there yesterday. You open it. Describe what is on the other side using only sensory details: sight, sound, temperature, smell. Do not explain its purpose or origin. Simply document the experience of crossing that threshold."
},
{
"prompt24": "Recall a dream from the past week, however fragmentary. Don't interpret it. Instead, expand it. Continue the narrative from where it left off. Describe the dream logic, the landscape, the characters. Let it become a story. Where does your dreaming mind take you when given free rein on the page?"
"prompt24": "Make a list of ten tiny, perfect moments from the past month that no one else probably noticed or would remember. The way light fell on a spoon, a stranger's half-smile, the sound of rain stopping. Elaborate on at least three of them, expanding them into full vignettes. Why did these micro-moments stick with you?"
},
{
"prompt25": "Make a list of everything that is blue in your immediate environment. Describe each shade specifically (slate, cobalt, robin's egg, faded denim). Then, choose one blue object and write about its journey to being here, in this blue state, in front of you. How did it get its color? What has it reflected?"
"prompt25": "Invent a mythological creature for a modern urban setting. What does it look like? What is its behavior and habitat (e.g., subway tunnels, server farms, air vents)? What folklore do people whisper about it? What does it symbolize\u2014anxiety, forgotten connections, hope? Describe a recent 'sighting' of this creature in vivid detail."
},
{
"prompt26": "Write a eulogy for something you've lost that isn't a person\u2014a habit, a version of a city, a relationship dynamic, a part of your identity. Acknowledge its virtues and its flaws. Say goodbye properly, with humor, regret, and gratitude. What did it give you? What space has its departure created?"
"prompt26": "Choose an object in your immediate line of sight that is not electronic. Write its biography. Where was it made? Who owned it before you? What conversations has it overheard? What secrets does it hold? What small damages or wear marks does it have, and what story does each tell? Give this ordinary item an epic history."
},
{
"prompt27": "Describe your hands. Not just their appearance, but their capabilities, their scars, their memories. What have they held, built, comforted, or torn down? What do their specific aches and strengths tell you about the life you've lived so far? If your hands could speak, what would they say they want to do next?"
"prompt27": "Describe your current emotional state as a weather system. Is it a still, high-pressure fog? A sudden, sharp hailstorm? A lingering, humid drizzle? Map its boundaries, its intensity, its forecast. What terrain does it move over\u2014the mountains of your responsibilities, the plains of your routine? How does it affect your internal climate?"
},
{
"prompt28": "Imagine you can overhear the conversation of the people at the table next to you in a caf\u00e9, but they are speaking in a language you don't understand. Based on their tone, gestures, pauses, and expressions, invent the dialogue. What crucial, funny, or tragic misunderstanding are they having? What are they *really* talking about?"
"prompt28": "Recall a time you were deeply embarrassed. Write about it from the perspective of a sympathetic observer who was there\u2014or invent one. How might they have perceived the event? What context or kindness might they have seen that you, in your self-focused shame, completely missed? Reframe the memory through their eyes."
},
{
"prompt29": "What is a piece of art (a song, painting, film, book) that fundamentally moved you? Describe the first time you encountered it. Don't just analyze why it's good; describe the physical and emotional reaction it provoked. Has its meaning changed for you over time? How does it live inside you now?"
"prompt29": "What skill or craft have you always wanted to learn but haven't? Immerse yourself in a detailed fantasy of mastering it. Describe the feel of the tools in your hands, the initial frustrations, the first small success, the growing muscle memory. What does the final, perfected product of your labor look or feel like? Live in that imagined\u6210\u5c31\u611f."
},
{
"prompt30": "You have one day completely alone, with no obligations and no possibility of communication. The power and internet are out. How do you spend the hours from waking to sleeping? Detail the rituals, the wanderings, the thoughts, the meals. Do you enjoy the solitude or chafe against it? What arises in the quiet?"
"prompt30": "Write a dialogue between two aspects of yourself (e.g., Your Ambitious Self and Your Tired Self; Your Cynical Self and Your Hopeful Self). Give them distinct voices. What are they arguing about, negotiating, or planning? Don't just state positions; let them bicker, persuade, or sit in silence together. See where the conversation goes."
},
{
"prompt31": "Personify a negative emotion you've been feeling lately (e.g., anxiety, envy, restlessness). Give it a name, a form, a voice. Write a character profile of it. What does it want? What does it fear? What flawed logic does it operate under? Then, write a short scene of you having a cup of tea with it, listening to its perspective."
"prompt31": "Describe your childhood home from the perspective of a small animal (a mouse, a squirrel, a bird) that lived there concurrently with you. What did this creature notice about your family's rhythms, the layout, the dangers, and the treasures (crumbs, cozy materials)? How did it perceive you, the giant human child?"
},
{
"prompt32": "Describe a city you've never been to, based solely on the stories, images, and snippets you've absorbed about it. Build it from imagination and second-hand clues. Then, contrast that with a description of your own street, seen with the hyper-attentive eyes of a first-time visitor. Make the familiar alien, and the alien familiar."
"prompt32": "List five paths your life could have taken if you'd made one different choice. Briefly outline each alternate reality. Then, choose one and dive deep: write a journal entry from that version of you today. What are their worries, joys, and regrets? How is their voice similar to or different from your own?"
},
{
"prompt33": "Think of a crossroads in your past. Now, imagine you see a ghost of your former self standing there, frozen in that moment of decision. What would you want to say to that ghost? Would you offer comfort, a warning, or just silent companionship? Write the encounter. Does the ghost speak back?"
"prompt33": "Think of a person you see regularly but do not know (a barista, a neighbor, a commuter). Invent a rich, secret inner life for them. What profound private mission are they on? What hidden talent do they possess? What great sorrow or hope are they carrying today as they serve your coffee or stand on the platform? Write from their perspective."
},
{
"prompt34": "What is a tradition in your family or community\u2014big or small\u2014that you find meaningful? Describe its sensory details, its rhythms, its players. Now, trace its origin. How did it start? Has it mutated over time? What does its continued practice say about what your family values, fears, or hopes for?"
"prompt34": "What is a belief you held strongly five or ten years ago that you have since questioned or abandoned? Trace the evolution of that change. Was it a sudden shattering or a slow erosion? What person, experience, or piece of information was the catalyst? Describe the feeling of the ground shifting under that particular piece of your worldview."
},
{
"prompt35": "Choose a year from your past. Catalog the soundtrack of that year: songs on the radio, albums you loved, jingles, background music. For each, describe a specific memory or feeling it evokes. How does the music of that time period color your memory of the entire era? What does it sound like to you now?"
"prompt35": "Describe a common, mundane process (making tea, tying your shoes, doing laundry) in extreme, almost absurdly epic detail, as if you were writing a sacred manual or a scientific treatise for an alien civilization. Break down every micro-action, every sensation, every potential variable. Find the profound in the procedural."
},
{
"prompt36": "Write instructions for a stranger on how to be you for a day. Include the essential routines, the internal dialogues to expect, the things to avoid, the small comforts to lean on, and the passwords to your various anxieties. Be brutally honest and surprisingly practical. What would they find hardest to mimic?"
"prompt36": "You are given a suitcase and told you must leave your home in one hour, not knowing if or when you'll return. You can only take what fits in the case. Describe, in real-time, the frantic and deliberate process of choosing. What practical items make the cut? What irreplaceable tokens? What do you leave behind, and what does that feel like?"
},
{
"prompt37": "Describe a moment of unexpected kindness, either given or received. Don't frame it as a grand gesture. Focus on a small, almost invisible act. What were the circumstances? Why was it so potent? How did it ripple out, changing the temperature of your day or your perception of someone?"
"prompt37": "Write about water in three different forms: as a memory involving a body of water (ocean, river, bath), as a description of drinking a glass of water right now, and as a metaphor for an emotion. Move seamlessly between these three aspects. Let the fluidity of the theme connect them."
},
{
"prompt38": "You discover you have a superpower, but it is frustratingly mundane and specific (e.g., the ability to always know exactly what time it is without a clock, to perfectly fold fitted sheets, to find lost buttons). Explore the practical uses, the minor heroics, the unexpected downsides, and the peculiar loneliness of this unique gift."
"prompt38": "What does silence sound like in your current environment? Don't just say 'quiet.' Describe the layers of sound that actually constitute the silence\u2014the hums, ticks, distant rumbles, the sound of your own body. Now, project what this same space sounded like 100 years ago, and what it might sound like 100 years from now."
},
{
"prompt39": "Go to a window. Describe the view in extreme detail, as if painting it with words, for five minutes. Then, close your eyes and describe the view from a window that was significant to you in the past (your childhood bedroom, a previous office, a grandparent's house). Juxtapose the two landscapes on the page."
"prompt39": "Create a recipe for a dish that represents your current life phase. List ingredients (e.g., \"two cups of transition,\" \"a pinch of anxiety,\" \"a steady base of routine\"). Write the instructions, including the method, cooking time, and necessary equipment. Describe the final product's taste, texture, and who it should be shared with."
},
{
"prompt40": "What is a question you are tired of being asked? Write a rant about why it's so irritating, reductive, or painful. Then, flip it: write the question you wish people would ask you instead. Answer that new question fully and generously."
"prompt40": "Recall a dream from the past week, however fragmentary. Don't interpret it. Instead, expand it. Continue the narrative from where it left off. Describe the dream logic, the landscape, the characters. Let it become a story. Where does your dreaming mind take you when given free rein on the page?"
},
{
"prompt41": "Describe a hobby or interest you have from the perspective of someone who finds it utterly baffling and boring. Then, defend it with the passionate zeal of a true devotee. Try to convey its magic and depth to this imagined skeptic. What is the core beauty you see that they miss?"
"prompt41": "Make a list of everything that is blue in your immediate environment. Describe each shade specifically (slate, cobalt, robin's egg, faded denim). Then, choose one blue object and write about its journey to being here, in this blue state, in front of you. How did it get its color? What has it reflected?"
},
{
"prompt42": "List ten things you would do if you were not afraid. They can be grand (quit my job) or small (sing karaoke). Choose one and vividly imagine doing it. Walk through every step, from decision to action to aftermath. How does the air feel different on the other side of that fear?"
"prompt42": "Write a eulogy for something you've lost that isn't a person\u2014a habit, a version of a city, a relationship dynamic, a part of your identity. Acknowledge its virtues and its flaws. Say goodbye properly, with humor, regret, and gratitude. What did it give you? What space has its departure created?"
},
{
"prompt43": "Write about a time you got exactly what you wanted\u2014and it was not what you expected. Describe the desire, the anticipation, the moment of attainment, and the subtle (or not-so-subtle) disappointment or confusion that followed. What did that experience teach you about wanting?"
"prompt43": "Describe your hands. Not just their appearance, but their capabilities, their scars, their memories. What have they held, built, comforted, or torn down? What do their specific aches and strengths tell you about the life you've lived so far? If your hands could speak, what would they say they want to do next?"
},
{
"prompt44": "Personify your favorite season. Give it a personality, a wardrobe, a way of speaking, a scent. Write a monologue from its perspective. What does it think of humans? What is its purpose? What does it love and resent about its place in the yearly cycle? Let it defend itself against its critics."
"prompt44": "Imagine you can overhear the conversation of the people at the table next to you in a caf\u00e9, but they are speaking in a language you don't understand. Based on their tone, gestures, pauses, and expressions, invent the dialogue. What crucial, funny, or tragic misunderstanding are they having? What are they *really* talking about?"
},
{
"prompt45": "Describe a room after a significant emotional event has occurred (a fight, a celebration, a profound conversation), but without mentioning the event or the people. Let the objects, the disarray, the quality of light, the lingering smells tell the story. What is the room holding now?"
"prompt45": "What is a piece of art (a song, painting, film, book) that fundamentally moved you? Describe the first time you encountered it. Don't just analyze why it's good; describe the physical and emotional reaction it provoked. Has its meaning changed for you over time? How does it live inside you now?"
},
{
"prompt46": "What is a rule you live by? It can be profound ('assume good intent') or practical ('never grocery shop hungry'). Explain its origin story. When have you broken it, and what were the consequences? How has following it shaped your life? Argue for its universal adoption."
"prompt46": "You have one day completely alone, with no obligations and no possibility of communication. The power and internet are out. How do you spend the hours from waking to sleeping? Detail the rituals, the wanderings, the thoughts, the meals. Do you enjoy the solitude or chafe against it? What arises in the quiet?"
},
{
"prompt47": "Imagine you can send a message of exactly 100 words into the future, to be read by you in ten years. What do you say? What do you ask? What current worry do you want to soothe, or what current joy do you want future-you to remember? Write the message. Then, write a 100-word message from you-ten-years-ago to present-you."
"prompt47": "Personify a negative emotion you've been feeling lately (e.g., anxiety, envy, restlessness). Give it a name, a form, a voice. Write a character profile of it. What does it want? What does it fear? What flawed logic does it operate under? Then, write a short scene of you having a cup of tea with it, listening to its perspective."
},
{
"prompt48": "Describe a color to someone who has been blind from birth. Use metaphor, texture, temperature, sound, emotion, and memory. Don't rely on sight-based comparisons ('like the sky'). Try to make them *feel* the essence of 'red' or 'blue' or 'gold' in their bones."
"prompt48": "Describe a city you've never been to, based solely on the stories, images, and snippets you've absorbed about it. Build it from imagination and second-hand clues. Then, contrast that with a description of your own street, seen with the hyper-attentive eyes of a first-time visitor. Make the familiar alien, and the alien familiar."
},
{
"prompt49": "Write about a book that changed your mind. Not just one you loved, but one that actively altered your perspective on a topic. Describe your stance before, the unsettling process of reading it, and the new landscape of thought afterwards. What made you vulnerable to its argument?"
"prompt49": "Think of a crossroads in your past. Now, imagine you see a ghost of your former self standing there, frozen in that moment of decision. What would you want to say to that ghost? Would you offer comfort, a warning, or just silent companionship? Write the encounter. Does the ghost speak back?"
},
{
"prompt50": "Catalog the contents of a junk drawer or a cluttered bag\u2014yours or an imagined one. Describe each item with care, as an archaeologist might. Then, construct a biography of the drawer's owner based solely on these artifacts. What story do these mundane relics tell?"
"prompt50": "What is a tradition in your family or community\u2014big or small\u2014that you find meaningful? Describe its sensory details, its rhythms, its players. Now, trace its origin. How did it start? Has it mutated over time? What does its continued practice say about what your family values, fears, or hopes for?"
},
{
"prompt51": "What does your body know how to do that your mind often forgets? (e.g., breathe deeply, relax into sleep, find rhythm in a walk). Write a series of instructions from your body to your mind, teaching it this skill again. Use the language of sensation, not thought."
"prompt51": "Choose a year from your past. Catalog the soundtrack of that year: songs on the radio, albums you loved, jingles, background music. For each, describe a specific memory or feeling it evokes. How does the music of that time period color your memory of the entire era? What does it sound like to you now?"
},
{
"prompt52": "Describe a journey you take every day (commute, walk the dog, trip to the kitchen) as a epic quest. Cast yourself as the hero, the mundane obstacles as trials (the traffic dragon, the staircase mountain), and the destination as a holy grail. Infuse the ordinary with mythic significance."
"prompt52": "Write instructions for a stranger on how to be you for a day. Include the essential routines, the internal dialogues to expect, the things to avoid, the small comforts to lean on, and the passwords to your various anxieties. Be brutally honest and surprisingly practical. What would they find hardest to mimic?"
},
{
"prompt53": "Write a review of today, as if it were a product, a performance, or a restaurant. Give it star ratings in different categories (Productivity, Serendipity, Comfort, Learning). Write the critic's summary. Be witty, be harsh, be fair. What was the highlight? The biggest flaw? Would you recommend today to a friend?"
"prompt53": "Describe a moment of unexpected kindness, either given or received. Don't frame it as a grand gesture. Focus on a small, almost invisible act. What were the circumstances? Why was it so potent? How did it ripple out, changing the temperature of your day or your perception of someone?"
},
{
"prompt54": "Think of a word you love the sound of. Write it at the top of the page. Now, free-associate from that word\u2014not just meanings, but sounds, memories, images. Let it spin a web of connections. Where does it lead you? Try to capture the aesthetic and emotional resonance of the word itself."
"prompt54": "You discover you have a superpower, but it is frustratingly mundane and specific (e.g., the ability to always know exactly what time it is without a clock, to perfectly fold fitted sheets, to find lost buttons). Explore the practical uses, the minor heroics, the unexpected downsides, and the peculiar loneliness of this unique gift."
},
{
"prompt55": "Describe a piece of technology you use daily from the perspective of a person from 200 years ago. Have them stumble upon it and try to deduce its purpose, its magic, and its societal implications from its form and behavior. What would they find beautiful, terrifying, or absurd?"
"prompt55": "Go to a window. Describe the view in extreme detail, as if painting it with words, for five minutes. Then, close your eyes and describe the view from a window that was significant to you in the past (your childhood bedroom, a previous office, a grandparent's house). Juxtapose the two landscapes on the page."
},
{
"prompt56": "Write a gratitude list, but for difficult things. Be specific. Not just 'my job,' but 'the particular frustration of my project that forced me to learn a new skill.' Find the hidden gift in the challenge, the strength forged in the irritation, the clarity born of the sorrow."
"prompt56": "What is a question you are tired of being asked? Write a rant about why it's so irritating, reductive, or painful. Then, flip it: write the question you wish people would ask you instead. Answer that new question fully and generously."
},
{
"prompt57": "You meet a version of yourself from a parallel universe where one key life detail is different (you chose a different career, never moved, stayed with a different partner). Have a conversation with them. What do you envy? What do you pity? What fundamental part of 'you' remains the same?"
"prompt57": "Describe a hobby or interest you have from the perspective of someone who finds it utterly baffling and boring. Then, defend it with the passionate zeal of a true devotee. Try to convey its magic and depth to this imagined skeptic. What is the core beauty you see that they miss?"
},
{
"prompt58": "Describe a taste from your childhood that you can almost, but not quite, recall\u2014a specific candy, a grandparent's dish, a seasonal treat. Try to chase the memory with all your senses. What else was happening when you tasted it? Who was there? Why is it lost? The struggle to remember is the story."
"prompt58": "List ten things you would do if you were not afraid. They can be grand (quit my job) or small (sing karaoke). Choose one and vividly imagine doing it. Walk through every step, from decision to action to aftermath. How does the air feel different on the other side of that fear?"
},
{
"prompt59": "What is a place that feels like a sanctuary to you? Describe it not just physically, but atmospherically. What rules (spoken or unspoken) govern it? What happens to your internal noise when you enter? What would it mean to carry the essence of that place with you into busier, louder realms?"
"prompt59": "Write about a time you got exactly what you wanted\u2014and it was not what you expected. Describe the desire, the anticipation, the moment of attainment, and the subtle (or not-so-subtle) disappointment or confusion that followed. What did that experience teach you about wanting?"
}
]

View File

@@ -1 +1,3 @@
[]
[
"What is something you've been putting off and why?"
]

10
run.sh
View File

@@ -35,7 +35,6 @@ fi
# Parse command line arguments
INTERACTIVE=false
SIMPLE=false
STATS=false
POOL_STATS=false
FILL_POOL=false
@@ -47,10 +46,6 @@ while [[ $# -gt 0 ]]; do
INTERACTIVE=true
shift
;;
-s | --simple)
SIMPLE=true
shift
;;
--stats)
STATS=true
shift
@@ -80,7 +75,6 @@ if [ "$HELP" = true ]; then
echo ""
echo "Options:"
echo " -i, --interactive Run in interactive mode (with rich interface)"
echo " -s, --simple Run simple version (no rich dependency)"
echo " --stats Show prompt history statistics"
echo " --pool-stats Show prompt pool statistics"
echo " --fill-pool Fill prompt pool using AI (makes API call)"
@@ -89,7 +83,6 @@ if [ "$HELP" = true ]; then
echo "Examples:"
echo " ./run.sh # Draw prompts from pool (default)"
echo " ./run.sh -i # Interactive mode"
echo " ./run.sh -s # Simple version"
echo " ./run.sh --stats # Show history statistics"
echo " ./run.sh --pool-stats # Show pool statistics"
echo " ./run.sh --fill-pool # Fill prompt pool using AI"
@@ -108,9 +101,6 @@ elif [ "$FILL_POOL" = true ]; then
elif [ "$INTERACTIVE" = true ]; then
echo "🎮 Starting interactive mode..."
python3 generate_prompts.py --interactive
elif [ "$SIMPLE" = true ]; then
echo "⚡ Running simple version..."
python3 simple_generate.py
else
echo "✨ Drawing prompts from pool..."
python3 generate_prompts.py

View File

@@ -1,12 +1,12 @@
# settings.cfg
# This controls how many prompts are presented, as well as how deep to pre-cache.
# Obviously, the depth causes exponential growth with prompts^days, so be conservative.
# This controls how many prompts are presented and consumed from the pool, as well as how much to pre-cache.
# This is used to maintain functionality offline for some number of iterations.
[prompts]
min_length = 500
max_length = 1000
num_prompts = 4
num_prompts = 3
# Prefetch not yet implmented
# Pool size can affect the prompts if is too high. Default 20.
[prefetch]
cached_pool_volume = 20

View File

@@ -1,319 +0,0 @@
#!/usr/bin/env python3
"""
Simple Daily Journal Prompt Generator
A lightweight version without rich dependency.
"""
import os
import json
import sys
import argparse
import configparser
from datetime import datetime
from typing import List, Dict, Any
from openai import OpenAI
from dotenv import load_dotenv
class SimplePromptGenerator:
"""Simple version without rich dependency."""
def __init__(self, config_path: str = ".env"):
"""Initialize the generator with configuration."""
self.config_path = config_path
self.client = None
self.historic_prompts = []
self.pool_prompts = []
self.prompt_template = ""
self.settings = {}
# Load configuration
self._load_config()
self._load_settings()
# Load data files
self._load_prompt_template()
self._load_historic_prompts()
self._load_pool_prompts()
def _load_config(self):
"""Load configuration from environment file."""
load_dotenv(self.config_path)
# Get API key
self.api_key = os.getenv("DEEPSEEK_API_KEY") or os.getenv("OPENAI_API_KEY")
if not self.api_key:
print("Error: No API key found in .env file")
print("Please add DEEPSEEK_API_KEY or OPENAI_API_KEY to your .env file")
sys.exit(1)
# Get API base URL (default to DeepSeek)
self.base_url = os.getenv("API_BASE_URL", "https://api.deepseek.com")
# Get model (default to deepseek-chat)
self.model = os.getenv("MODEL", "deepseek-chat")
# Initialize OpenAI client
self.client = OpenAI(
api_key=self.api_key,
base_url=self.base_url
)
def _load_settings(self):
"""Load settings from settings.cfg configuration file."""
config = configparser.ConfigParser()
# Set default values
self.settings = {
'min_length': 500,
'max_length': 1000,
'num_prompts': 6
}
try:
config.read('settings.cfg')
if 'prompts' in config:
prompts_section = config['prompts']
# Load min_length
if 'min_length' in prompts_section:
self.settings['min_length'] = int(prompts_section['min_length'])
# Load max_length
if 'max_length' in prompts_section:
self.settings['max_length'] = int(prompts_section['max_length'])
# Load num_prompts
if 'num_prompts' in prompts_section:
self.settings['num_prompts'] = int(prompts_section['num_prompts'])
except FileNotFoundError:
print("Warning: settings.cfg not found, using default values")
except ValueError as e:
print(f"Warning: Invalid value in settings.cfg: {e}, using default values")
except Exception as e:
print(f"Warning: Error reading settings.cfg: {e}, using default values")
def _load_prompt_template(self):
"""Load the prompt template from ds_prompt.txt and update with config values."""
try:
with open("ds_prompt.txt", "r") as f:
template = f.read()
# Replace hardcoded values with config values
template = template.replace(
"between 500 and 1000 characters",
f"between {self.settings['min_length']} and {self.settings['max_length']} characters"
)
# Replace the number of prompts (6) with config value
template = template.replace(
"Please generate 6 writing prompts",
f"Please generate {self.settings['num_prompts']} writing prompts"
)
self.prompt_template = template
except FileNotFoundError:
print("Error: ds_prompt.txt not found")
sys.exit(1)
def _load_historic_prompts(self):
"""Load historic prompts from JSON file."""
try:
with open("historic_prompts.json", "r") as f:
self.historic_prompts = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
print("Warning: Starting with empty prompt history")
self.historic_prompts = []
def _save_historic_prompts(self):
"""Save historic prompts to JSON file (keeping only last 60)."""
# Keep only the last 60 prompts
if len(self.historic_prompts) > 60:
self.historic_prompts = self.historic_prompts[-60:]
with open("historic_prompts.json", "w") as f:
json.dump(self.historic_prompts, f, indent=2)
def _prepare_prompt(self) -> str:
"""Prepare the full prompt with historic context."""
if self.historic_prompts:
historic_context = json.dumps(self.historic_prompts, indent=2)
full_prompt = f"{self.prompt_template}\n\nPrevious prompts:\n{historic_context}"
else:
full_prompt = self.prompt_template
return full_prompt
def _parse_ai_response(self, response_content: str) -> List[str]:
"""Parse the AI response to extract new prompts."""
try:
# Try to parse as JSON
data = json.loads(response_content)
# Check if data is a list (new format)
if isinstance(data, list):
# Return the list of prompt strings directly
# Ensure we have the correct number of prompts
if len(data) >= self.settings['num_prompts']:
return data[:self.settings['num_prompts']]
else:
print(f"Warning: AI returned {len(data)} prompts, expected {self.settings['num_prompts']}")
return data
elif isinstance(data, dict):
# Fallback for old format: dictionary with newprompt0, newprompt1, etc.
print("Warning: AI returned dictionary format, expected list format")
new_prompts = []
for i in range(self.settings['num_prompts']):
key = f"newprompt{i}"
if key in data:
new_prompts.append(data[key])
return new_prompts
else:
print(f"Warning: AI returned unexpected data type: {type(data)}")
return []
except json.JSONDecodeError:
# If not valid JSON, try to extract prompts from text
print("Warning: AI response is not valid JSON, attempting to extract prompts...")
# Look for patterns in the text
lines = response_content.strip().split('\n')
new_prompts = []
for i, line in enumerate(lines[:self.settings['num_prompts']]):
line = line.strip()
if line and len(line) > 50:
new_prompts.append(line)
return new_prompts
def generate_prompts(self) -> List[str]:
"""Generate new journal prompts using AI."""
print("\nGenerating new journal prompts...")
# Prepare the prompt
full_prompt = self._prepare_prompt()
try:
# Call the AI API
print("Calling AI API...")
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "You are a creative writing assistant that generates journal prompts. Always respond with valid JSON."},
{"role": "user", "content": full_prompt}
],
temperature=0.7,
max_tokens=2000
)
response_content = response.choices[0].message.content
except Exception as e:
print(f"Error calling AI API: {e}")
return []
# Parse the response
new_prompts = self._parse_ai_response(response_content)
if not new_prompts:
print("Error: Could not parse any prompts from AI response")
return []
# Note: Prompts are NOT added to historic_prompts here
# They will be added only when the user chooses one
return new_prompts
def display_prompts(self, prompts: List[Dict[str, str]]):
"""Display generated prompts in a simple format."""
print("\n" + "="*60)
print("✨ NEW JOURNAL PROMPTS GENERATED ✨")
print("="*60 + "\n")
for i, prompt_dict in enumerate(prompts, 1):
# Extract prompt text
prompt_key = list(prompt_dict.keys())[0]
prompt_text = prompt_dict[prompt_key]
print(f"Prompt #{i}:")
print("-" * 40)
print(prompt_text)
print("-" * 40 + "\n")
def show_history_stats(self):
"""Show statistics about prompt history."""
total_prompts = len(self.historic_prompts)
print("\nPrompt History Statistics:")
print("-" * 30)
print(f"Total prompts in history: {total_prompts}")
print(f"History capacity: 60 prompts")
print(f"Available slots: {max(0, 60 - total_prompts)}")
def save_prompt_to_file(self, prompt_dict: Dict[str, str], filename: str = None):
"""Save a prompt to a text file."""
prompt_key = list(prompt_dict.keys())[0]
prompt_text = prompt_dict[prompt_key]
if not filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"journal_prompt_{timestamp}.txt"
with open(filename, "w") as f:
f.write(f"Journal Prompt - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write("="*50 + "\n\n")
f.write(prompt_text)
f.write("\n\n" + "="*50 + "\n")
f.write("Happy writing! ✍️\n")
print(f"Prompt saved to {filename}")
def main():
"""Main entry point for the simple script."""
parser = argparse.ArgumentParser(description="Generate journal prompts using AI (simple version)")
parser.add_argument(
"--stats", "-s",
action="store_true",
help="Show history statistics"
)
parser.add_argument(
"--save", "-S",
type=int,
help="Save a specific prompt number to file"
)
parser.add_argument(
"--config", "-c",
default=".env",
help="Path to configuration file (default: .env)"
)
args = parser.parse_args()
# Initialize generator
generator = SimplePromptGenerator(config_path=args.config)
if args.stats:
generator.show_history_stats()
else:
# Generate prompts
new_prompts = generator.generate_prompts()
if new_prompts:
generator.display_prompts(new_prompts)
# Save specific prompt if requested
if args.save:
prompt_num = args.save
if 1 <= prompt_num <= len(new_prompts):
generator.save_prompt_to_file(new_prompts[prompt_num - 1])
else:
print(f"Error: Prompt number must be between 1 and {len(new_prompts)}")
if __name__ == "__main__":
main()

View File

@@ -1,55 +0,0 @@
#!/usr/bin/env python3
"""
Test to demonstrate the fix for the AttributeError when API returns list instead of dict.
"""
import json
from generate_prompts import JournalPromptGenerator
def test_original_error_case():
"""Test the exact error case: API returns a list instead of a dict."""
print("Testing the original error case: API returns list instead of dict")
print("="*60)
# Create a mock generator
generator = JournalPromptGenerator()
# Simulate API returning a list (which could happen with null/malformed data)
list_response = json.dumps([]) # Empty list
print("\n1. Testing with empty list []:")
try:
result = generator._parse_ai_response(list_response)
print(f" Result: Successfully parsed {len(result)} prompts (no AttributeError)")
except AttributeError as e:
print(f" ERROR: AttributeError occurred: {e}")
except Exception as e:
print(f" Other error: {type(e).__name__}: {e}")
# Test with list containing dictionaries (another possible malformed response)
list_with_dicts = json.dumps([
{"some_key": "some value"},
{"another_key": "another value"}
])
print("\n2. Testing with list of dictionaries:")
try:
result = generator._parse_ai_response(list_with_dicts)
print(f" Result: Successfully parsed {len(result)} prompts (no AttributeError)")
except AttributeError as e:
print(f" ERROR: AttributeError occurred: {e}")
except Exception as e:
print(f" Other error: {type(e).__name__}: {e}")
# Test with None/null data (worst case)
print("\n3. Testing with None/null data (simulated):")
# We can't directly test None since json.loads would fail, but our code
# handles the case where data might be None after parsing
print("\n" + "="*60)
print("Test complete! The fix prevents AttributeError for list responses.")
if __name__ == "__main__":
test_original_error_case()

View File

@@ -1,91 +0,0 @@
#!/usr/bin/env python3
"""
Test the new format where AI returns a list and keys are generated locally.
"""
import json
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from generate_prompts import JournalPromptGenerator
def test_new_format():
"""Test the new format where AI returns a list and keys are generated locally."""
print("Testing new format: AI returns list, keys generated locally")
print("="*60)
# Create a mock generator
generator = JournalPromptGenerator(config_path=".env")
# Create a mock AI response in the new list format
mock_ai_response = [
"Write about a childhood memory that still makes you smile.",
"Describe your perfect day from start to finish.",
"What is something you've been putting off and why?",
"Imagine you could have a conversation with any historical figure.",
"Write a letter to your future self one year from now.",
"Describe a place that feels like home to you."
]
# Convert to JSON string
json_response = json.dumps(mock_ai_response)
print("\n1. Testing _parse_ai_response with list format:")
result = generator._parse_ai_response(json_response)
print(f" Result type: {type(result)}")
print(f" Number of prompts: {len(result)}")
print(f" First prompt: {result[0][:50]}...")
# Verify it's a list of strings
assert isinstance(result, list), "Result should be a list"
assert all(isinstance(prompt, str) for prompt in result), "All items should be strings"
print("\n2. Testing add_prompts_to_pool with list of strings:")
# Get initial pool size
initial_pool_size = len(generator.pool_prompts)
print(f" Initial pool size: {initial_pool_size}")
# Add prompts to pool
generator.add_prompts_to_pool(result)
# Check new pool size
new_pool_size = len(generator.pool_prompts)
print(f" New pool size: {new_pool_size}")
print(f" Added {new_pool_size - initial_pool_size} prompts")
# Check that prompts in pool have keys
print(f"\n3. Checking that prompts in pool have generated keys:")
for i, prompt_dict in enumerate(generator.pool_prompts[-len(result):]):
prompt_key = list(prompt_dict.keys())[0]
prompt_text = prompt_dict[prompt_key]
print(f" Prompt {i+1}: Key='{prompt_key}', Text='{prompt_text[:30]}...'")
assert prompt_key.startswith("poolprompt"), f"Key should start with 'poolprompt', got '{prompt_key}'"
print("\n4. Testing draw_prompts_from_pool:")
drawn_prompts = generator.draw_prompts_from_pool(count=2)
print(f" Drawn {len(drawn_prompts)} prompts from pool")
print(f" Pool size after drawing: {len(generator.pool_prompts)}")
# Check drawn prompts have keys
for i, prompt_dict in enumerate(drawn_prompts):
prompt_key = list(prompt_dict.keys())[0]
prompt_text = prompt_dict[prompt_key]
print(f" Drawn prompt {i+1}: Key='{prompt_key}', Text='{prompt_text[:30]}...'")
print("\n" + "="*60)
print("✅ All tests passed! New format works correctly.")
print("\nSummary:")
print("- AI returns prompts as a JSON list (no keys)")
print("- _parse_ai_response returns List[str]")
print("- add_prompts_to_pool generates keys locally (poolprompt000, poolprompt001, etc.)")
print("- draw_prompts_from_pool returns List[Dict[str, str]] with generated keys")
return True
if __name__ == "__main__":
test_new_format()

230
test_parsing.py Normal file
View File

@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""
Consolidated test file for parsing AI responses and format handling.
Combines tests from:
- test_final_fix.py (AttributeError fix for list responses)
- test_new_format.py (new list format with locally generated keys)
- test_valid_response.py (valid JSON response handling)
"""
import json
import sys
import os
# Add the current directory to the Python path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from generate_prompts import JournalPromptGenerator
def test_attribute_error_fix():
"""Test the fix for AttributeError when API returns list instead of dict."""
print("\n=== Test: AttributeError fix for list responses ===")
# Create a mock generator
generator = JournalPromptGenerator()
# Test with empty list []
list_response = json.dumps([]) # Empty list
print("\n1. Testing with empty list []:")
try:
result = generator._parse_ai_response(list_response)
print(f" Result: Successfully parsed {len(result)} prompts (no AttributeError)")
except AttributeError as e:
print(f" ERROR: AttributeError occurred: {e}")
return False
except Exception as e:
print(f" Other error: {type(e).__name__}: {e}")
return False
# Test with list containing dictionaries
list_with_dicts = json.dumps([
{"some_key": "some value"},
{"another_key": "another value"}
])
print("\n2. Testing with list of dictionaries:")
try:
result = generator._parse_ai_response(list_with_dicts)
print(f" Result: Successfully parsed {len(result)} prompts (no AttributeError)")
except AttributeError as e:
print(f" ERROR: AttributeError occurred: {e}")
return False
except Exception as e:
print(f" Other error: {type(e).__name__}: {e}")
return False
print("\n✅ AttributeError fix tests passed!")
return True
def test_new_list_format():
"""Test the new format where AI returns a list and keys are generated locally."""
print("\n=== Test: New list format with locally generated keys ===")
# Create a mock generator
generator = JournalPromptGenerator()
# Create a mock AI response in the new list format
mock_ai_response = [
"Write about a childhood memory that still makes you smile.",
"Describe your perfect day from start to finish.",
"What is something you've been putting off and why?",
"Imagine you could have a conversation with any historical figure.",
"Write a letter to your future self one year from now.",
"Describe a place that feels like home to you."
]
# Convert to JSON string
json_response = json.dumps(mock_ai_response)
print("\n1. Testing _parse_ai_response with list format:")
result = generator._parse_ai_response(json_response)
print(f" Result type: {type(result)}")
print(f" Number of prompts: {len(result)}")
print(f" First prompt: {result[0][:50]}...")
# Verify it's a list of strings
assert isinstance(result, list), "Result should be a list"
assert all(isinstance(prompt, str) for prompt in result), "All items should be strings"
print("\n2. Testing add_prompts_to_pool with list of strings:")
# Get initial pool size
initial_pool_size = len(generator.pool_prompts)
print(f" Initial pool size: {initial_pool_size}")
# Add prompts to pool
generator.add_prompts_to_pool(result)
# Check new pool size
new_pool_size = len(generator.pool_prompts)
print(f" New pool size: {new_pool_size}")
print(f" Added {new_pool_size - initial_pool_size} prompts")
print("\n✅ New list format tests passed!")
return True
def test_valid_json_responses():
"""Test with valid JSON responses in various formats."""
print("\n=== Test: Valid JSON response handling ===")
# Create a mock generator
generator = JournalPromptGenerator()
# Create a valid response with 4 prompts as a list (new format)
valid_response = [
"Write about a time when you felt truly at peace.",
"Describe your ideal morning routine in detail.",
"What are three things you're grateful for today?",
"Reflect on a recent challenge and what you learned from it."
]
# Convert to JSON string
json_response = json.dumps(valid_response)
print("\n1. Testing with valid JSON response (list format):")
result = generator._parse_ai_response(json_response)
print(f" Number of prompts extracted: {len(result)}")
print(f" Type of result: {type(result)}")
for i, prompt_text in enumerate(result):
print(f" Prompt {i+1}: {prompt_text[:50]}...")
# Test with backticks
print("\n2. Testing with valid JSON response with backticks:")
backticks_response = f"```json\n{json_response}\n```"
result = generator._parse_ai_response(backticks_response)
print(f" Number of prompts extracted: {len(result)}")
# Test with "json" prefix
print("\n3. Testing with valid JSON response with 'json' prefix:")
json_prefix_response = f"json\n{json_response}"
result = generator._parse_ai_response(json_prefix_response)
print(f" Number of prompts extracted: {len(result)}")
# Test fallback for old dictionary format
print("\n4. Testing fallback for old dictionary format:")
old_format_response = {
"newprompt0": "Write about a time when you felt truly at peace.",
"newprompt1": "Describe your ideal morning routine in detail.",
"newprompt2": "What are three things you're grateful for today?",
"newprompt3": "Reflect on a recent challenge and what you learned from it."
}
json_old_response = json.dumps(old_format_response)
result = generator._parse_ai_response(json_old_response)
print(f" Number of prompts extracted: {len(result)}")
print("\n✅ Valid JSON response tests passed!")
return True
def test_clean_ai_response():
"""Test the _clean_ai_response method."""
print("\n=== Test: _clean_ai_response method ===")
generator = JournalPromptGenerator()
# Test cases
test_cases = [
("```json\n[1, 2, 3]\n```", "[1, 2, 3]"),
("```\n[1, 2, 3]\n```", "[1, 2, 3]"),
("json\n[1, 2, 3]", "[1, 2, 3]"),
("JSON\n[1, 2, 3]", "[1, 2, 3]"),
(" [1, 2, 3] ", "[1, 2, 3]"),
("```json\n{\"a\": 1}\n```", "{\"a\": 1}"),
]
all_passed = True
for i, (input_text, expected) in enumerate(test_cases):
cleaned = generator._clean_ai_response(input_text)
if cleaned == expected:
print(f" Test {i+1} passed: '{input_text[:20]}...' -> '{cleaned}'")
else:
print(f" Test {i+1} FAILED: '{input_text[:20]}...' -> '{cleaned}' (expected: '{expected}')")
all_passed = False
if all_passed:
print("\n✅ _clean_ai_response tests passed!")
return True
else:
print("\n❌ _clean_ai_response tests failed!")
return False
def main():
"""Run all parsing tests."""
print("=" * 60)
print("Running Consolidated Parsing Tests")
print("=" * 60)
all_passed = True
# Run all tests
if not test_attribute_error_fix():
all_passed = False
if not test_new_list_format():
all_passed = False
if not test_valid_json_responses():
all_passed = False
if not test_clean_ai_response():
all_passed = False
print("\n" + "=" * 60)
if all_passed:
print("✅ ALL PARSING TESTS PASSED!")
else:
print("❌ SOME TESTS FAILED!")
print("=" * 60)
return all_passed
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)

View File

@@ -8,7 +8,6 @@ import json
import os
import sys
from unittest.mock import Mock, patch
from datetime import datetime
# Add current directory to path to import our modules
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
@@ -202,7 +201,7 @@ def test_python_scripts():
"""Test that Python scripts are syntactically valid."""
print("\nTesting Python scripts...")
scripts_to_test = ["generate_prompts.py", "simple_generate.py"]
scripts_to_test = ["generate_prompts.py"]
all_valid = True
for script in scripts_to_test:

View File

@@ -5,7 +5,6 @@ Test script to verify the prompt numbering logic.
import json
import configparser
from datetime import datetime
def get_num_prompts():
"""Get the number of prompts from settings.cfg or default."""

View File

@@ -1,65 +0,0 @@
#!/usr/bin/env python3
"""
Test the error handling with a valid response.
"""
import sys
import os
import json
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from generate_prompts import JournalPromptGenerator
def test_valid_response():
"""Test with a valid JSON response."""
# Create a mock generator
generator = JournalPromptGenerator(config_path=".env")
# Create a valid response with 4 prompts as a list (new format)
valid_response = [
"Write about a time when you felt truly at peace.",
"Describe your ideal morning routine in detail.",
"What are three things you're grateful for today?",
"Reflect on a recent challenge and what you learned from it."
]
# Convert to JSON string
json_response = json.dumps(valid_response)
print("\n=== Test: Valid JSON response (list format) ===")
result = generator._parse_ai_response(json_response)
print(f"Number of prompts extracted: {len(result)}")
print(f"Type of result: {type(result)}")
for i, prompt_text in enumerate(result):
print(f"Prompt {i+1}: {prompt_text[:50]}...")
# Test with backticks
print("\n=== Test: Valid JSON response with backticks ===")
backticks_response = f"```json\n{json_response}\n```"
result = generator._parse_ai_response(backticks_response)
print(f"Number of prompts extracted: {len(result)}")
# Test with "json" prefix
print("\n=== Test: Valid JSON response with 'json' prefix ===")
json_prefix_response = f"json\n{json_response}"
result = generator._parse_ai_response(json_prefix_response)
print(f"Number of prompts extracted: {len(result)}")
# Test fallback for old dictionary format
print("\n=== Test: Fallback for old dictionary format ===")
old_format_response = {
"newprompt0": "Write about a time when you felt truly at peace.",
"newprompt1": "Describe your ideal morning routine in detail.",
"newprompt2": "What are three things you're grateful for today?",
"newprompt3": "Reflect on a recent challenge and what you learned from it."
}
json_old_response = json.dumps(old_format_response)
result = generator._parse_ai_response(json_old_response)
print(f"Number of prompts extracted: {len(result)}")
if __name__ == "__main__":
test_valid_response()