core/apps/webapp/app/jobs/conversation/create-title.logic.ts
2025-10-24 23:35:46 +05:30

97 lines
2.3 KiB
TypeScript

import { LLMMappings } from "@core/types";
import { generate } from "~/trigger/chat/stream-utils";
import { conversationTitlePrompt } from "~/trigger/conversation/prompt";
import { prisma } from "~/trigger/utils/prisma";
import { logger } from "~/services/logger.service";
export interface CreateConversationTitlePayload {
conversationId: string;
message: string;
}
export interface CreateConversationTitleResult {
success: boolean;
title?: string;
error?: string;
}
/**
* Core business logic for creating conversation titles
* This is shared between Trigger.dev and BullMQ implementations
*/
export async function processConversationTitleCreation(
payload: CreateConversationTitlePayload,
): Promise<CreateConversationTitleResult> {
try {
let conversationTitleResponse = "";
const gen = generate(
[
{
role: "user",
content: conversationTitlePrompt.replace(
"{{message}}",
payload.message,
),
},
],
false,
() => {},
undefined,
"",
LLMMappings.GPT41,
);
for await (const chunk of gen) {
if (typeof chunk === "string") {
conversationTitleResponse += chunk;
} else if (chunk && typeof chunk === "object" && chunk.message) {
conversationTitleResponse += chunk.message;
}
}
const outputMatch = conversationTitleResponse.match(
/<output>(.*?)<\/output>/s,
);
logger.info(`Conversation title data: ${JSON.stringify(outputMatch)}`);
if (!outputMatch) {
logger.error("No output found in recurrence response");
throw new Error("Invalid response format from AI");
}
const jsonStr = outputMatch[1].trim();
const conversationTitleData = JSON.parse(jsonStr);
if (conversationTitleData) {
await prisma.conversation.update({
where: {
id: payload.conversationId,
},
data: {
title: conversationTitleData.title,
},
});
return {
success: true,
title: conversationTitleData.title,
};
}
return {
success: false,
error: "No title generated",
};
} catch (error: any) {
logger.error(
`Error creating conversation title for ${payload.conversationId}:`,
error,
);
return {
success: false,
error: error.message,
};
}
}