优化会话标题生成逻辑,增加消息限制与格式处理

This commit is contained in:
2026-05-20 17:51:59 +08:00
parent f24e8109a0
commit 4870e8a577
+32 -11
View File
@@ -4,7 +4,10 @@ import { type OpencodeRuntimeAdapter } from "../runtime/opencode.js";
import { collectTextContent } from "./chatStream.js";
const TITLE_PROMPT_TIMEOUT_MS = 2500;
const TITLE_PROMPT_TIMEOUT_MS = 5000;
const TITLE_CONTEXT_MESSAGE_LIMIT = 40;
const TITLE_CONTEXT_CHAR_LIMIT = 2400;
const TITLE_CONTEXT_MESSAGE_CHAR_LIMIT = 240;
const buildSessionTitle = (message: string) => {
const normalized = message.replace(/\s+/g, " ").trim();
@@ -18,7 +21,7 @@ const buildTitleConversationContext = async (
runtime: OpencodeRuntimeAdapter,
sessionId: string,
) => {
const messages = await runtime.messages(sessionId, 12);
const messages = await runtime.messages(sessionId, TITLE_CONTEXT_MESSAGE_LIMIT);
const recentMessages = messages
.filter(
(message) =>
@@ -26,19 +29,35 @@ const buildTitleConversationContext = async (
)
.map((message) => ({
role: message.info.role,
content: collectTextContent(message.parts).replace(/\s+/g, " ").trim(),
content: collectTextContent(message.parts)
.replace(/\s+/g, " ")
.trim()
.slice(0, TITLE_CONTEXT_MESSAGE_CHAR_LIMIT),
}))
.filter((message) => message.content.length > 0)
.slice(-6);
.filter((message) => message.content.length > 0);
if (recentMessages.length === 0) {
return "";
}
return recentMessages
.map((message) => `${message.role === "user" ? "用户" : "助手"}${message.content}`)
.join("\n")
.slice(0, 2400);
const formattedMessages = recentMessages.map(
(message) => `${message.role === "user" ? "用户" : "助手"}${message.content}`,
);
const fullConversation = formattedMessages.join("\n");
if (fullConversation.length <= TITLE_CONTEXT_CHAR_LIMIT) {
return fullConversation;
}
const headCount = Math.min(4, formattedMessages.length);
const tailCount = Math.min(8, Math.max(0, formattedMessages.length - headCount));
const middleOmitted = formattedMessages.length > headCount + tailCount;
const summary = [
...formattedMessages.slice(0, headCount),
...(middleOmitted ? ["……(中间省略若干轮对话)"] : []),
...formattedMessages.slice(-tailCount),
].join("\n");
return summary.slice(0, TITLE_CONTEXT_CHAR_LIMIT);
};
const normalizeGeneratedTitle = (rawTitle: string, fallback: string) => {
@@ -75,15 +94,17 @@ export const generateSessionTitle = async (
titleSession.id,
[
"你是会话标题生成器。",
"请根据用户问题生成一个 8-16 字中文标题。",
"请根据下面整段多轮对话生成一个 8-16 字中文标题。",
"要求:简洁、可读、避免标点、不要引号、不要解释。",
"请优先概括最近这轮对话的核心任务或结论。",
"先理解完整对话,再概括核心任务或结论。",
"不要直接照抄用户任一条消息原文。",
"只输出标题本身。",
"",
conversation,
].join("\n"),
)
.then(async () => {
await runtime.waitForSessionIdle(titleSession.id, TITLE_PROMPT_TIMEOUT_MS);
const messages = await runtime.messages(titleSession.id, 20);
const assistantMessage = [...messages]
.reverse()