#!/usr/bin/env python3 """ Management command to rename all conversations. - Conversations with >10 messages: renamed to an LLM-generated summary - Conversations with <=10 messages: renamed to a truncation of the first user message """ import argparse import asyncio import os from tortoise import Tortoise from blueprints.conversation.models import Conversation, Speaker from llm import LLMClient async def rename_conversations(dry_run: bool = False): """Rename all conversations based on message count.""" database_url = os.getenv("DATABASE_URL", "sqlite://raggr.db") await Tortoise.init( db_url=database_url, modules={ "models": [ "blueprints.users.models", "blueprints.conversation.models", ] }, ) try: llm = LLMClient() conversations = await Conversation.all().prefetch_related("messages") renamed = 0 skipped = 0 for conversation in conversations: messages = sorted(conversation.messages, key=lambda m: m.created_at) user_messages = [m for m in messages if m.speaker == Speaker.USER] if not user_messages: skipped += 1 continue if len(messages) > 10: # Summarize via LLM message_text = "\n".join( f"{m.speaker.value}: {m.text}" for m in messages[:30] ) new_name = llm.chat( prompt=message_text, system_prompt=( "You are naming a conversation. Given the messages below, " "produce a short, descriptive title (max 8 words). " "Reply with ONLY the title, nothing else." ), ) new_name = new_name.strip().strip('"').strip("'")[:100] else: # Truncate first user message new_name = user_messages[0].text[:100] old_name = conversation.name if old_name == new_name: skipped += 1 continue if dry_run: print(f" [dry-run] '{old_name}' -> '{new_name}'") else: conversation.name = new_name await conversation.save() print(f" '{old_name}' -> '{new_name}'") renamed += 1 print(f"\nRenamed: {renamed} Skipped: {skipped}") if dry_run: print("(dry run — no changes were saved)") finally: await Tortoise.close_connections() if __name__ == "__main__": parser = argparse.ArgumentParser( description="Rename conversations based on message count" ) parser.add_argument( "--dry-run", action="store_true", help="Preview renames without saving", ) args = parser.parse_args() asyncio.run(rename_conversations(dry_run=args.dry_run))