Generate conversation titles via LLM instead of truncating first line
- _maybe_set_title sets a quick truncated fallback immediately - Then fires a background thread to ask the LLM for a 5-8 word summary - Background thread doesn't block the streaming response - Title appears in sidebar on first chunk, then upgrades when LLM responds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>cora-start
parent
d771dd5c80
commit
30757b5bcf
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||
import base64
|
||||
import json
|
||||
import logging
|
||||
import threading
|
||||
import uuid
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
|
|
@ -294,19 +295,55 @@ class Agent:
|
|||
self._memory.auto_flush(conv_id)
|
||||
|
||||
def _maybe_set_title(self, conv_id: str, user_input: str):
|
||||
"""Set conversation title from first user message if still 'New Chat'."""
|
||||
"""Set conversation title from first user message if still 'New Chat'.
|
||||
|
||||
Sets a quick truncated fallback immediately, then fires a background
|
||||
thread to generate a proper 5-8 word LLM summary.
|
||||
"""
|
||||
try:
|
||||
current_title = self.db.get_conversation_title(conv_id)
|
||||
if current_title and current_title != "New Chat":
|
||||
return
|
||||
title = user_input.split("\n", 1)[0].strip()
|
||||
if len(title) > 50:
|
||||
title = title[:47] + "..."
|
||||
if title:
|
||||
self.db.update_conversation_title(conv_id, title)
|
||||
# Immediate fallback: first line, truncated
|
||||
fallback = user_input.split("\n", 1)[0].strip()
|
||||
if len(fallback) > 50:
|
||||
fallback = fallback[:47] + "..."
|
||||
if fallback:
|
||||
self.db.update_conversation_title(conv_id, fallback)
|
||||
# Fire background LLM call to generate a better title
|
||||
threading.Thread(
|
||||
target=self._generate_title,
|
||||
args=(conv_id, user_input),
|
||||
daemon=True,
|
||||
).start()
|
||||
except Exception as e:
|
||||
log.warning("Failed to set conversation title: %s", e)
|
||||
|
||||
def _generate_title(self, conv_id: str, user_input: str):
|
||||
"""Background: ask the LLM for a 5-8 word conversation title."""
|
||||
try:
|
||||
prompt = user_input[:500] # cap input to keep it cheap
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": (
|
||||
"Generate a short 5-8 word title summarizing this conversation opener. "
|
||||
"Reply with ONLY the title — no quotes, no punctuation at the end, no explanation."
|
||||
),
|
||||
},
|
||||
{"role": "user", "content": prompt},
|
||||
]
|
||||
parts = []
|
||||
for chunk in self.llm.chat(messages, tools=None, stream=False):
|
||||
if chunk.get("type") == "text":
|
||||
parts.append(chunk["content"])
|
||||
title = "".join(parts).strip().strip('"').strip("'")
|
||||
if title and len(title) <= 60:
|
||||
self.db.update_conversation_title(conv_id, title)
|
||||
log.debug("Generated conversation title: %s", title)
|
||||
except Exception as e:
|
||||
log.warning("Background title generation failed: %s", e)
|
||||
|
||||
def respond_to_prompt(self, prompt: str) -> str:
|
||||
"""Non-streaming response for scheduled tasks / internal use."""
|
||||
result_parts = []
|
||||
|
|
|
|||
Loading…
Reference in New Issue