fix title gen
This commit is contained in:
parent
1e9fc14b37
commit
fae7798119
3 changed files with 152 additions and 2 deletions
|
|
@ -96,3 +96,31 @@ export const createAndAddMessage = mutation({
|
|||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const updateTitle = mutation({
|
||||
args: {
|
||||
conversation_id: v.id('conversations'),
|
||||
title: v.string(),
|
||||
session_token: v.string(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const session = await ctx.runQuery(api.betterAuth.publicGetSession, {
|
||||
session_token: args.session_token,
|
||||
});
|
||||
|
||||
if (!session) {
|
||||
throw new Error('Unauthorized');
|
||||
}
|
||||
|
||||
// Verify the conversation belongs to the user
|
||||
const conversation = await ctx.db.get(args.conversation_id);
|
||||
if (!conversation || conversation.user_id !== session.userId) {
|
||||
throw new Error('Conversation not found or unauthorized');
|
||||
}
|
||||
|
||||
await ctx.db.patch(args.conversation_id, {
|
||||
title: args.title,
|
||||
updated_at: Date.now(),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,6 +41,111 @@ function log(message: string, startTime: number): void {
|
|||
|
||||
const client = new ConvexHttpClient(PUBLIC_CONVEX_URL);
|
||||
|
||||
async function generateConversationTitle({
|
||||
conversationId,
|
||||
session,
|
||||
startTime,
|
||||
keyResultPromise,
|
||||
userMessage
|
||||
}: {
|
||||
conversationId: string;
|
||||
session: SessionObj;
|
||||
startTime: number;
|
||||
keyResultPromise: ResultAsync<string | null, string>;
|
||||
userMessage: string;
|
||||
}) {
|
||||
log('Starting conversation title generation', startTime);
|
||||
|
||||
const keyResult = await keyResultPromise;
|
||||
|
||||
if (keyResult.isErr()) {
|
||||
log(`Title generation: API key error: ${keyResult.error}`, startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const key = keyResult.value;
|
||||
if (!key) {
|
||||
log('Title generation: No API key found', startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only generate title if conversation currently has default title
|
||||
const conversationResult = await ResultAsync.fromPromise(
|
||||
client.query(api.conversations.get, {
|
||||
session_token: session.token,
|
||||
}),
|
||||
(e) => `Failed to get conversations: ${e}`
|
||||
);
|
||||
|
||||
if (conversationResult.isErr()) {
|
||||
log(`Title generation: Failed to get conversation: ${conversationResult.error}`, startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const conversations = conversationResult.value;
|
||||
const conversation = conversations.find(c => c._id === conversationId);
|
||||
|
||||
if (!conversation || !conversation.title.includes('Untitled')) {
|
||||
log('Title generation: Conversation not found or already has custom title', startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const openai = new OpenAI({
|
||||
baseURL: 'https://openrouter.ai/api/v1',
|
||||
apiKey: key,
|
||||
});
|
||||
|
||||
// Create a prompt for title generation using only the first user message
|
||||
const titlePrompt = `Based on this user request, generate a concise, specific title (max 4-5 words):
|
||||
|
||||
${userMessage}
|
||||
|
||||
Generate only the title based on what the user is asking for, nothing else:`;
|
||||
|
||||
const titleResult = await ResultAsync.fromPromise(
|
||||
openai.chat.completions.create({
|
||||
model: 'mistralai/ministral-8b',
|
||||
messages: [{ role: 'user', content: titlePrompt }],
|
||||
max_tokens: 20,
|
||||
temperature: 0.3,
|
||||
}),
|
||||
(e) => `Title generation API call failed: ${e}`
|
||||
);
|
||||
|
||||
if (titleResult.isErr()) {
|
||||
log(`Title generation: OpenAI call failed: ${titleResult.error}`, startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const titleResponse = titleResult.value;
|
||||
const rawTitle = titleResponse.choices[0]?.message?.content?.trim();
|
||||
|
||||
if (!rawTitle) {
|
||||
log('Title generation: No title generated', startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Strip surrounding quotes if present
|
||||
const generatedTitle = rawTitle.replace(/^["']|["']$/g, '');
|
||||
|
||||
// Update the conversation title
|
||||
const updateResult = await ResultAsync.fromPromise(
|
||||
client.mutation(api.conversations.updateTitle, {
|
||||
conversation_id: conversationId as Id<'conversations'>,
|
||||
title: generatedTitle,
|
||||
session_token: session.token,
|
||||
}),
|
||||
(e) => `Failed to update conversation title: ${e}`
|
||||
);
|
||||
|
||||
if (updateResult.isErr()) {
|
||||
log(`Title generation: Failed to update title: ${updateResult.error}`, startTime);
|
||||
return;
|
||||
}
|
||||
|
||||
log(`Title generation: Successfully updated title to "${generatedTitle}"`, startTime);
|
||||
}
|
||||
|
||||
async function generateAIResponse({
|
||||
conversationId,
|
||||
session,
|
||||
|
|
@ -177,6 +282,7 @@ async function generateAIResponse({
|
|||
`Background stream processing completed. Processed ${chunkCount} chunks, final content length: ${content.length}`,
|
||||
startTime
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
log(`Background stream processing error: ${error}`, startTime);
|
||||
}
|
||||
|
|
@ -262,6 +368,19 @@ export const POST: RequestHandler = async ({ request }) => {
|
|||
|
||||
conversationId = convMessageResult.value.conversationId;
|
||||
log('New conversation and message created', startTime);
|
||||
|
||||
// Generate title for new conversation in background
|
||||
waitUntil(
|
||||
generateConversationTitle({
|
||||
conversationId,
|
||||
session,
|
||||
startTime,
|
||||
keyResultPromise,
|
||||
userMessage: args.message
|
||||
}).catch((error) => {
|
||||
log(`Background title generation error: ${error}`, startTime);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
log('Using existing conversation', startTime);
|
||||
const userMessageResult = await ResultAsync.fromPromise(
|
||||
|
|
|
|||
|
|
@ -131,14 +131,17 @@
|
|||
<div class="relative overflow-clip">
|
||||
<p
|
||||
class={[
|
||||
' rounded-lg py-2 pl-3',
|
||||
' truncate rounded-lg py-2 pr-4 pl-3 whitespace-nowrap',
|
||||
isActive ? 'bg-sidebar-accent' : 'group-hover:bg-sidebar-accent ',
|
||||
]}
|
||||
>
|
||||
<span>{conversation.title}</span>
|
||||
</p>
|
||||
<div
|
||||
class=" to-sidebar-accent pointer-events-none absolute inset-y-0.5 right-0 flex translate-x-full items-center gap-2 rounded-r-lg bg-gradient-to-r from-transparent pr-2 transition group-hover:pointer-events-auto group-hover:translate-0"
|
||||
class={[
|
||||
'pointer-events-none absolute inset-y-0.5 right-0 flex translate-x-full items-center gap-2 rounded-r-lg pr-2 pl-6 transition group-hover:pointer-events-auto group-hover:translate-0',
|
||||
'to-sidebar-accent via-sidebar-accent bg-gradient-to-r from-transparent from-10% via-21% ',
|
||||
]}
|
||||
>
|
||||
<Tooltip>
|
||||
{#snippet trigger(tooltip)}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue