Skip to content

Commit 4dcd827

Browse files
Added chat history title generation code changes
1 parent 20c1666 commit 4dcd827

6 files changed

Lines changed: 236 additions & 16 deletions

File tree

content-gen/src/app/frontend/src/App.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import ContosoLogo from './styles/images/contoso.svg';
2020

2121
function App() {
2222
const [conversationId, setConversationId] = useState<string>(() => uuidv4());
23+
const [conversationTitle, setConversationTitle] = useState<string | null>(null);
2324
const [userId, setUserId] = useState<string>('');
2425
const [userName, setUserName] = useState<string>('');
2526
const [messages, setMessages] = useState<ChatMessage[]>([]);
@@ -104,6 +105,7 @@ function App() {
104105
if (response.ok) {
105106
const data = await response.json();
106107
setConversationId(selectedConversationId);
108+
setConversationTitle(null); // Will use title from conversation list
107109
const loadedMessages: ChatMessage[] = (data.messages || []).map((msg: { role: string; content: string; timestamp?: string; agent?: string }, index: number) => ({
108110
id: `${selectedConversationId}-${index}`,
109111
role: msg.role as 'user' | 'assistant',
@@ -175,6 +177,7 @@ function App() {
175177
// Handle starting a new conversation
176178
const handleNewConversation = useCallback(() => {
177179
setConversationId(uuidv4());
180+
setConversationTitle(null);
178181
setMessages([]);
179182
setPendingBrief(null);
180183
setAwaitingClarification(false);
@@ -216,6 +219,9 @@ function App() {
216219

217220
setGenerationStatus('Updating creative brief...');
218221
const parsed = await parseBrief(refinementPrompt, conversationId, userId, signal);
222+
if (parsed.generated_title && !conversationTitle) {
223+
setConversationTitle(parsed.generated_title);
224+
}
219225
if (parsed.brief) {
220226
setPendingBrief(parsed.brief);
221227
}
@@ -428,6 +434,11 @@ function App() {
428434
setGenerationStatus('Analyzing creative brief...');
429435
const parsed = await parseBrief(content, conversationId, userId, signal);
430436

437+
// Set conversation title from generated title
438+
if (parsed.generated_title && !conversationTitle) {
439+
setConversationTitle(parsed.generated_title);
440+
}
441+
431442
// Check if request was blocked due to harmful content
432443
if (parsed.rai_blocked) {
433444
// Show the refusal message without any brief UI
@@ -799,6 +810,7 @@ function App() {
799810
<div className="history-panel">
800811
<ChatHistory
801812
currentConversationId={conversationId}
813+
currentConversationTitle={conversationTitle}
802814
currentMessages={messages}
803815
onSelectConversation={handleSelectConversation}
804816
onNewConversation={handleNewConversation}

content-gen/src/app/frontend/src/components/ChatHistory.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ interface ConversationSummary {
3737

3838
interface ChatHistoryProps {
3939
currentConversationId: string;
40+
currentConversationTitle?: string | null;
4041
currentMessages?: { role: string; content: string }[]; // Current session messages
4142
onSelectConversation: (conversationId: string) => void;
4243
onNewConversation: () => void;
@@ -46,6 +47,7 @@ interface ChatHistoryProps {
4647

4748
export function ChatHistory({
4849
currentConversationId,
50+
currentConversationTitle,
4951
currentMessages = [],
5052
onSelectConversation,
5153
onNewConversation,
@@ -152,13 +154,14 @@ export function ChatHistory({
152154
}, [refreshTrigger]);
153155

154156
// Build the current session conversation summary if it has messages
155-
const currentSessionConversation: ConversationSummary | null = currentMessages.length > 0 ? {
156-
id: currentConversationId,
157-
title: currentMessages.find(m => m.role === 'user')?.content?.substring(0, 50) || 'Current Conversation',
158-
lastMessage: currentMessages[currentMessages.length - 1]?.content?.substring(0, 100) || '',
159-
timestamp: new Date().toISOString(),
160-
messageCount: currentMessages.length,
161-
} : null;
157+
const currentSessionConversation: ConversationSummary | null =
158+
currentMessages.length > 0 && currentConversationTitle ? {
159+
id: currentConversationId,
160+
title: currentConversationTitle,
161+
lastMessage: currentMessages[currentMessages.length - 1]?.content?.substring(0, 100) || '',
162+
timestamp: new Date().toISOString(),
163+
messageCount: currentMessages.length,
164+
} : null;
162165

163166
// Merge current session with saved conversations, updating the current one with live data
164167
const displayConversations = (() => {

content-gen/src/app/frontend/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export interface ParsedBriefResponse {
9292
rai_blocked?: boolean;
9393
message: string;
9494
conversation_id?: string;
95+
generated_title?: string;
9596
}
9697

9798
export interface GeneratedContent {

content-gen/src/backend/app.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from orchestrator import get_orchestrator
2222
from services.cosmos_service import get_cosmos_service
2323
from services.blob_service import get_blob_service
24+
from services.title_service import get_title_service
2425
from api.admin import admin_bp
2526

2627
# In-memory task storage for generation tasks
@@ -106,14 +107,25 @@ async def chat():
106107
# Try to save to CosmosDB but don't fail if it's unavailable
107108
try:
108109
cosmos_service = await get_cosmos_service()
110+
111+
generated_title = None
112+
existing_conversation = await cosmos_service.get_conversation(conversation_id, user_id)
113+
existing_metadata = existing_conversation.get("metadata", {}) if existing_conversation else {}
114+
has_existing_title = bool(existing_metadata.get("custom_title") or existing_metadata.get("generated_title"))
115+
116+
if not has_existing_title:
117+
title_service = get_title_service()
118+
generated_title = await title_service.generate_title(message)
119+
109120
await cosmos_service.add_message_to_conversation(
110121
conversation_id=conversation_id,
111122
user_id=user_id,
112123
message={
113124
"role": "user",
114125
"content": message,
115126
"timestamp": datetime.now(timezone.utc).isoformat()
116-
}
127+
},
128+
generated_title=generated_title
117129
)
118130
except Exception as e:
119131
logger.warning(f"Failed to save message to CosmosDB: {e}")
@@ -187,22 +199,35 @@ async def parse_brief():
187199
if not brief_text:
188200
return jsonify({"error": "Brief text is required"}), 400
189201

202+
orchestrator = get_orchestrator()
203+
generated_title = None
204+
190205
# Save the user's brief text as a message to CosmosDB
191206
try:
192207
cosmos_service = await get_cosmos_service()
208+
209+
# Generate title for new conversations
210+
existing_conversation = await cosmos_service.get_conversation(conversation_id, user_id)
211+
existing_metadata = existing_conversation.get("metadata", {}) if existing_conversation else {}
212+
has_existing_title = bool(existing_metadata.get("custom_title") or existing_metadata.get("generated_title"))
213+
214+
if not has_existing_title:
215+
title_service = get_title_service()
216+
generated_title = await title_service.generate_title(brief_text)
217+
193218
await cosmos_service.add_message_to_conversation(
194219
conversation_id=conversation_id,
195220
user_id=user_id,
196221
message={
197222
"role": "user",
198223
"content": brief_text,
199224
"timestamp": datetime.now(timezone.utc).isoformat()
200-
}
225+
},
226+
generated_title=generated_title
201227
)
202228
except Exception as e:
203229
logger.warning(f"Failed to save brief message to CosmosDB: {e}")
204230

205-
orchestrator = get_orchestrator()
206231
parsed_brief, clarifying_questions, rai_blocked = await orchestrator.parse_brief(brief_text)
207232

208233
# Check if request was blocked due to harmful content
@@ -228,6 +253,7 @@ async def parse_brief():
228253
"requires_clarification": False,
229254
"requires_confirmation": False,
230255
"conversation_id": conversation_id,
256+
"generated_title": generated_title,
231257
"message": clarifying_questions
232258
})
233259

@@ -255,6 +281,7 @@ async def parse_brief():
255281
"requires_confirmation": False,
256282
"clarifying_questions": clarifying_questions,
257283
"conversation_id": conversation_id,
284+
"generated_title": generated_title,
258285
"message": clarifying_questions
259286
})
260287

@@ -279,6 +306,7 @@ async def parse_brief():
279306
"requires_clarification": False,
280307
"requires_confirmation": True,
281308
"conversation_id": conversation_id,
309+
"generated_title": generated_title,
282310
"message": "Please review and confirm the parsed creative brief"
283311
})
284312

content-gen/src/backend/services/cosmos_service.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,13 +343,27 @@ async def save_conversation(
343343
"""
344344
await self.initialize()
345345

346+
# Get existing conversation to preserve important metadata fields
347+
existing = await self.get_conversation(conversation_id, user_id)
348+
existing_metadata = existing.get("metadata", {}) if existing else {}
349+
350+
# Merge metadata - preserve generated_title and custom_title from existing
351+
merged_metadata = {}
352+
if existing_metadata.get("generated_title"):
353+
merged_metadata["generated_title"] = existing_metadata["generated_title"]
354+
if existing_metadata.get("custom_title"):
355+
merged_metadata["custom_title"] = existing_metadata["custom_title"]
356+
# Add new metadata on top
357+
if metadata:
358+
merged_metadata.update(metadata)
359+
346360
item = {
347361
"id": conversation_id,
348362
"userId": user_id, # Partition key field (matches container definition /userId)
349363
"user_id": user_id, # Keep for backward compatibility
350364
"messages": messages,
351365
"brief": brief.model_dump() if brief else None,
352-
"metadata": metadata or {},
366+
"metadata": merged_metadata,
353367
"generated_content": generated_content,
354368
"updated_at": datetime.now(timezone.utc).isoformat()
355369
}
@@ -401,7 +415,8 @@ async def add_message_to_conversation(
401415
self,
402416
conversation_id: str,
403417
user_id: str,
404-
message: dict
418+
message: dict,
419+
generated_title: Optional[str] = None
405420
) -> dict:
406421
"""
407422
Add a message to an existing conversation.
@@ -422,6 +437,12 @@ async def add_message_to_conversation(
422437
# Ensure userId is set (for partition key) - migrate old documents
423438
if not conversation.get("userId"):
424439
conversation["userId"] = conversation.get("user_id") or user_id
440+
conversation["metadata"] = conversation.get("metadata", {})
441+
if generated_title:
442+
has_custom_title = bool(conversation["metadata"].get("custom_title"))
443+
has_generated_title = bool(conversation["metadata"].get("generated_title"))
444+
if not has_custom_title and not has_generated_title:
445+
conversation["metadata"]["generated_title"] = generated_title
425446
conversation["messages"].append(message)
426447
conversation["updated_at"] = datetime.now(timezone.utc).isoformat()
427448
else:
@@ -430,6 +451,7 @@ async def add_message_to_conversation(
430451
"userId": user_id, # Partition key field
431452
"user_id": user_id, # Keep for backward compatibility
432453
"messages": [message],
454+
"metadata": {"generated_title": generated_title} if generated_title else {},
433455
"updated_at": datetime.now(timezone.utc).isoformat()
434456
}
435457

@@ -494,16 +516,21 @@ async def get_user_conversations(
494516
custom_title = metadata.get("custom_title") if metadata else None
495517
if custom_title:
496518
title = custom_title
519+
elif metadata and metadata.get("generated_title"):
520+
title = metadata.get("generated_title")
497521
elif brief and brief.get("overview"):
498-
title = brief["overview"][:50]
522+
overview_words = brief["overview"].split()[:4]
523+
title = " ".join(overview_words) if overview_words else "New Conversation"
499524
elif messages:
500-
title = "Untitled Conversation"
525+
title = "New Conversation"
501526
for msg in messages:
502527
if msg.get("role") == "user":
503-
title = msg.get("content", "")[:50]
528+
content = msg.get("content", "")
529+
words = content.split()[:4]
530+
title = " ".join(words) if words else "New Conversation"
504531
break
505532
else:
506-
title = "Untitled Conversation"
533+
title = "New Conversation"
507534

508535
# Get last message preview
509536
last_message = ""

0 commit comments

Comments
 (0)