Add ReflectionEngine
This commit is contained in:
82
src/timmy/reflection.py
Normal file
82
src/timmy/reflection.py
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
import logging
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import List, Optional
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from dashboard.models.database import SessionLocal
|
||||
from dashboard.models.calm import Task, JournalEntry
|
||||
from dashboard.models.reflection import Reflection
|
||||
from integrations.llm.ollama import query_ollama
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ReflectionEngine:
|
||||
"""Engine for Timmy's self-reflection loop."""
|
||||
|
||||
async def reflect_once(self) -> Optional[Reflection]:
|
||||
"""Review recent activity and generate a reflection."""
|
||||
logger.info("Starting self-reflection cycle...")
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# 1. Gather context
|
||||
now = datetime.now(UTC)
|
||||
since = now - timedelta(hours=24)
|
||||
|
||||
recent_tasks = db.query(Task).filter(Task.updated_at >= since).all()
|
||||
recent_journal = db.query(JournalEntry).filter(JournalEntry.created_at >= since).first()
|
||||
|
||||
# 2. Build prompt
|
||||
context = f"Recent Tasks: {[t.title for t in recent_tasks]}\n"
|
||||
if recent_journal:
|
||||
context += f"Journal: {recent_journal.evening_reflection}\n"
|
||||
|
||||
prompt = f"""
|
||||
You are Timmy, an AI agent. Review your recent activity and provide a short, insightful self-reflection.
|
||||
Focus on what you've achieved, what you've missed, and how you're feeling about your current progress.
|
||||
|
||||
Context:
|
||||
{context}
|
||||
|
||||
Output format:
|
||||
Reflection: [Your reflection text]
|
||||
Sentiment: [positive/neutral/negative]
|
||||
Focus Area: [e.g., Productivity, Health, Learning]
|
||||
"""
|
||||
|
||||
# 3. Query LLM
|
||||
response = await query_ollama(prompt)
|
||||
|
||||
# 4. Parse and save
|
||||
reflection_text = ""
|
||||
sentiment = "neutral"
|
||||
focus_area = "General"
|
||||
|
||||
for line in response.split("\n"):
|
||||
if line.startswith("Reflection:"):
|
||||
reflection_text = line.replace("Reflection:", "").strip()
|
||||
elif line.startswith("Sentiment:"):
|
||||
sentiment = line.replace("Sentiment:", "").strip().lower()
|
||||
elif line.startswith("Focus Area:"):
|
||||
focus_area = line.replace("Focus Area:", "").strip()
|
||||
|
||||
if reflection_text:
|
||||
reflection = Reflection(
|
||||
content=reflection_text,
|
||||
sentiment=sentiment,
|
||||
focus_area=focus_area
|
||||
)
|
||||
db.add(reflection)
|
||||
db.commit()
|
||||
db.refresh(reflection)
|
||||
logger.info("Self-reflection saved: %s", reflection_text[:50])
|
||||
return reflection
|
||||
|
||||
except Exception as exc:
|
||||
logger.error("Reflection error: %s", exc)
|
||||
finally:
|
||||
db.close()
|
||||
return None
|
||||
|
||||
reflection_engine = ReflectionEngine()
|
||||
Reference in New Issue
Block a user