Files
Breehavior-Monitor/scripts/migrate_notes_to_profiles.py
2026-02-26 12:59:03 -05:00

79 lines
2.4 KiB
Python

"""One-time migration: convert existing timestamped UserNotes into profile summaries.
Run with: python scripts/migrate_notes_to_profiles.py
Requires .env with DB_CONNECTION_STRING and LLM env vars.
"""
import asyncio
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from dotenv import load_dotenv
load_dotenv()
from utils.database import Database
from utils.llm_client import LLMClient
async def main():
db = Database()
if not await db.init():
print("Database not available.")
return
llm = LLMClient(
base_url=os.getenv("LLM_BASE_URL", ""),
model=os.getenv("LLM_MODEL", "gpt-4o-mini"),
api_key=os.getenv("LLM_API_KEY", "not-needed"),
)
states = await db.load_all_user_states()
migrated = 0
for state in states:
notes = state.get("user_notes", "")
if not notes or not notes.strip():
continue
# Check if already looks like a profile (no timestamps)
if not any(line.strip().startswith("[") for line in notes.split("\n")):
print(f" User {state['user_id']}: already looks like a profile, skipping.")
continue
print(f" User {state['user_id']}: migrating notes...")
print(f" Old: {notes[:200]}")
# Ask LLM to summarize notes into a profile
result = await llm.extract_memories(
conversation=[{"role": "user", "content": f"Here are observation notes about a user:\n{notes}"}],
username="unknown",
current_profile="",
)
if result and result.get("profile_update"):
profile = result["profile_update"]
print(f" New: {profile[:200]}")
await db.save_user_state(
user_id=state["user_id"],
offense_count=state["offense_count"],
immune=state["immune"],
off_topic_count=state["off_topic_count"],
baseline_coherence=state.get("baseline_coherence", 0.85),
user_notes=profile,
warned=state.get("warned", False),
last_offense_at=state.get("last_offense_at"),
)
migrated += 1
else:
print(f" No profile generated, keeping existing notes.")
await llm.close()
await db.close()
print(f"\nMigrated {migrated}/{len(states)} user profiles.")
if __name__ == "__main__":
asyncio.run(main())