77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import type { ChatMessage } from "../llm/types";
|
|
|
|
/** Detect messages that already embed full paper dumps (should not be in UI history). */
|
|
export function isPaperDump(content: string): boolean {
|
|
return (
|
|
content.includes("【论文正文】") ||
|
|
content.includes("【论文 1】") ||
|
|
content.startsWith("【论文元数据】") ||
|
|
content.startsWith("已收到论文内容") ||
|
|
content.includes("【说明】以上为本次会话的论文材料")
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Keep short Q&A turns for the model. Truncate very long assistant replies
|
|
* so paper context + latest question are less likely to be dropped.
|
|
*/
|
|
export function sanitizeChatHistory(
|
|
history: ChatMessage[],
|
|
options?: { maxMessages?: number; maxAssistantChars?: number },
|
|
): ChatMessage[] {
|
|
const maxMessages = options?.maxMessages ?? 10;
|
|
const maxAssistantChars = options?.maxAssistantChars ?? 5000;
|
|
|
|
const cleaned = history
|
|
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
.filter((m) => !isPaperDump(m.content))
|
|
.map((m) => {
|
|
if (
|
|
m.role === "assistant" &&
|
|
m.content &&
|
|
m.content.length > maxAssistantChars
|
|
) {
|
|
return {
|
|
...m,
|
|
content:
|
|
m.content.slice(0, maxAssistantChars) +
|
|
"\n\n…(为保留论文上下文,历史回复已截断)",
|
|
};
|
|
}
|
|
return m;
|
|
});
|
|
|
|
return cleaned.slice(-maxMessages);
|
|
}
|
|
|
|
/**
|
|
* Pin paper corpus near the start of the request, then prior Q&A, then the
|
|
* current task. Avoids stuffing full papers only into the latest message
|
|
* (which providers often truncate under context pressure on turn 2+).
|
|
*/
|
|
export function assemblePaperChatMessages(options: {
|
|
system: string;
|
|
paperBlock: string;
|
|
taskBlock: string;
|
|
history: ChatMessage[];
|
|
}): ChatMessage[] {
|
|
const messages: ChatMessage[] = [
|
|
{ role: "system", content: options.system },
|
|
{
|
|
role: "user",
|
|
content: `${options.paperBlock}
|
|
|
|
【说明】以上为本次会话的论文材料。后续所有问题与分析任务均基于这些论文;无需用户再次提供全文或文本。`,
|
|
},
|
|
{
|
|
role: "assistant",
|
|
content:
|
|
"已收到并理解以上论文材料。请继续提问或下达分析任务,我将基于这些论文作答,不会要求你再次提供全文。",
|
|
},
|
|
];
|
|
|
|
messages.push(...sanitizeChatHistory(options.history));
|
|
messages.push({ role: "user", content: options.taskBlock });
|
|
return messages;
|
|
}
|