Improve chat title generation or smth
CI / check (22) (push) Failing after 4m50s
CI / check (24) (push) Failing after 4m51s

This commit is contained in:
2026-10-13 23:40:29 +02:00
parent 42e71fb502
commit b8b06a8a33
4 changed files with 81 additions and 12 deletions
+40 -2
View File
@@ -131,6 +131,33 @@ export function createChatService(repositories, modelService, config, webSearchP
}
});
const generateChatTitle = async (message, model, signal) => {
signal?.throwIfAborted();
try {
const response = await modelService.generateReply(model, [
{role: "system", content: [
"Create a short, useful title for a chat from the user's first message.",
"Capture the main subject or goal, not the wording of the request.",
"Use the same language as the user. Do not answer the message.",
"Return only JSON in the form {\"title\":\"...\"}.",
"The title must be 2 to 8 words and no more than 70 characters. Do not use quotes, markdown, emojis, or a trailing period."
].join("\n")},
{role: "user", content: String(message).slice(0, 6000)}
], {
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(10000)]) : AbortSignal.timeout(10000),
reasoning: false,
generation: {temperature: 0.2, responseLength: 80},
format: {type: "object", properties: {title: {type: "string"}}, required: ["title"], additionalProperties: false}
});
signal?.throwIfAborted();
const title = String(JSON.parse(response)?.title || "").replace(/[\r\n]+/g, " ").replace(/["“”']/g, "").replace(/\s+/g, " ").trim();
if (title && title.length <= 70 && title.split(/\s+/).length <= 8) return title;
} catch (error) {
signal?.throwIfAborted();
}
return "New chat";
};
const persistChatMessageRetryState = ({ chatId, messageId, content, retryVariants, retryActiveIndex, retryRetriesUsed, retryPromptMessageId }) => {
const versioned = repositories.listMessageVersions(messageId).length > 0;
if (versioned) repositories.saveMessageVersion(chatId, messageId, null, retryActiveIndex);
@@ -511,9 +538,9 @@ export function createChatService(repositories, modelService, config, webSearchP
onChunk,
reasoning: useReasoning
})
: onChunk
: onChunk
? modelService.streamReply(effectiveModel, payload.messagesPayload, onChunk, { signal: activeSignal, generation, onThinking: captureThinking, reasoning: useReasoning })
: modelService.generateReply(effectiveModel, payload.messagesPayload, { signal: activeSignal, generation, onThinking: captureThinking, reasoning: useReasoning });
: modelService.generateReply(effectiveModel, payload.messagesPayload, { signal: activeSignal, generation, onThinking: captureThinking, reasoning: useReasoning });
});
if (!fullReply) {
@@ -654,6 +681,17 @@ export function createChatService(repositories, modelService, config, webSearchP
},
persistChatMessageRetryState,
buildMessagesPayload: buildConversationContext,
async generateInitialChatTitle({user, chatId, message, model, signal = null}) {
const session = repositories.getChat(chatId, user);
if (!session) return {error: "Chat not found", status: 404};
if (session.assistant_persona_id || session.title !== "New chat" || repositories.getLatestChatMessage(chatId)) {
return {title: session.title};
}
const {model: effectiveModel} = getGenerationSettings(session, model);
const title = await generateChatTitle(message, effectiveModel, signal);
if (title !== "New chat") repositories.updateChatTitle(chatId, user, title);
return {title};
},
async sendChatMessage({ user, chatId, message, model, attachments = [], userMessageId = null, webSearch = true, reasoning = false, signal = null, requestId = null }) {
return generateChatTurn({ user, chatId, message, model, attachments, userMessageId, webSearch, reasoning, signal, requestId });
},