Spaces:
Build error
Build error
"""Utility functions for generating conversation summaries.""" | |
from typing import Optional | |
from openhands.core.config import LLMConfig | |
from openhands.core.logger import openhands_logger as logger | |
from openhands.events.action.message import MessageAction | |
from openhands.events.event import EventSource | |
from openhands.events.stream import EventStream | |
from openhands.llm.llm import LLM | |
from openhands.storage.data_models.settings import Settings | |
from openhands.storage.files import FileStore | |
async def generate_conversation_title( | |
message: str, llm_config: LLMConfig, max_length: int = 50 | |
) -> Optional[str]: | |
"""Generate a concise title for a conversation based on the first user message. | |
Args: | |
message: The first user message in the conversation. | |
llm_config: The LLM configuration to use for generating the title. | |
max_length: The maximum length of the generated title. | |
Returns: | |
A concise title for the conversation, or None if generation fails. | |
""" | |
if not message or message.strip() == '': | |
return None | |
# Truncate very long messages to avoid excessive token usage | |
if len(message) > 1000: | |
truncated_message = message[:1000] + '...(truncated)' | |
else: | |
truncated_message = message | |
try: | |
llm = LLM(llm_config) | |
# Create a simple prompt for the LLM to generate a title | |
messages = [ | |
{ | |
'role': 'system', | |
'content': 'You are a helpful assistant that generates concise, descriptive titles for conversations with OpenHands. OpenHands is a helpful AI agent that can interact with a computer to solve tasks using bash terminal, file editor, and browser. Given a user message (which may be truncated), generate a concise, descriptive title for the conversation. Return only the title, with no additional text, quotes, or explanations.', | |
}, | |
{ | |
'role': 'user', | |
'content': f'Generate a title (maximum {max_length} characters) for a conversation that starts with this message:\n\n{truncated_message}', | |
}, | |
] | |
response = llm.completion(messages=messages) | |
title = response.choices[0].message.content.strip() | |
# Ensure the title isn't too long | |
if len(title) > max_length: | |
title = title[: max_length - 3] + '...' | |
return title | |
except Exception as e: | |
logger.error(f'Error generating conversation title: {e}') | |
return None | |
def get_default_conversation_title(conversation_id: str) -> str: | |
""" | |
Generate a default title for a conversation based on its ID. | |
Args: | |
conversation_id: The ID of the conversation | |
Returns: | |
A default title string | |
""" | |
return f'Conversation {conversation_id[:5]}' | |
async def auto_generate_title( | |
conversation_id: str, user_id: str | None, file_store: FileStore, settings: Settings | |
) -> str: | |
""" | |
Auto-generate a title for a conversation based on the first user message. | |
Uses LLM-based title generation if available, otherwise falls back to a simple truncation. | |
Args: | |
conversation_id: The ID of the conversation | |
user_id: The ID of the user | |
Returns: | |
A generated title string | |
""" | |
try: | |
# Create an event stream for the conversation | |
event_stream = EventStream(conversation_id, file_store, user_id) | |
# Find the first user message | |
first_user_message = None | |
for event in event_stream.get_events(): | |
if ( | |
event.source == EventSource.USER | |
and isinstance(event, MessageAction) | |
and event.content | |
and event.content.strip() | |
): | |
first_user_message = event.content | |
break | |
if first_user_message: | |
# Get LLM config from user settings | |
try: | |
if settings and settings.llm_model: | |
# Create LLM config from settings | |
llm_config = LLMConfig( | |
model=settings.llm_model, | |
api_key=settings.llm_api_key, | |
base_url=settings.llm_base_url, | |
) | |
# Try to generate title using LLM | |
llm_title = await generate_conversation_title( | |
first_user_message, llm_config | |
) | |
if llm_title: | |
logger.info(f'Generated title using LLM: {llm_title}') | |
return llm_title | |
except Exception as e: | |
logger.error(f'Error using LLM for title generation: {e}') | |
# Fall back to simple truncation if LLM generation fails or is unavailable | |
first_user_message = first_user_message.strip() | |
title = first_user_message[:30] | |
if len(first_user_message) > 30: | |
title += '...' | |
logger.info(f'Generated title using truncation: {title}') | |
return title | |
except Exception as e: | |
logger.error(f'Error generating title: {str(e)}') | |
return '' | |