实现单篇和多篇论文的对比总结

This commit is contained in:
yehongyu
2026-07-20 15:22:40 +08:00
parent 50fd043a2d
commit c46d247665
23 changed files with 2710 additions and 268 deletions
+65 -31
View File
@@ -1,5 +1,6 @@
import type { ChatMessage } from "../llm/types";
import { getSummaryPrompt, getSystemPrompt } from "../llm/prompts";
import { assemblePaperChatMessages } from "../llm/history";
import {
buildMetadataBlock,
extractPdfContext,
@@ -10,6 +11,7 @@ export interface BuiltContext {
messages: ChatMessage[];
extract: ExtractResult;
warning?: string;
ready: boolean;
}
export async function buildChatMessages(options: {
@@ -23,55 +25,87 @@ export async function buildChatMessages(options: {
const warnings: string[] = [];
if (!extract.text) {
return {
messages: [],
extract,
warning:
extract.error ||
"未能提取 PDF 文本(可能是扫描版或尚无文本层)。请检查附件后重试。",
ready: false,
};
}
const rawInfo =
extract.rawLength && extract.rawLength !== extract.text.length
? `(原文 ${extract.rawLength} → 提交 ${extract.text.length}`
: "";
if (extract.truncated) {
warnings.push(
"未能提取 PDF 文本(可能是扫描版或尚无文本层)。请检查附件后重试。",
`已智能截断并优先保留正文${rawInfo},来源 ${extract.source}${
extract.pageCount ? ` · ${extract.pageCount}` : ""
}`,
);
} else {
warnings.push(
`已载入论文文本 ${extract.text.length} 字符(${extract.source}${
extract.pageCount ? ` · ${extract.pageCount}` : ""
})。`,
);
} else if (extract.truncated) {
warnings.push("论文较长,已按设置截断上下文。");
}
const meta = extract.parentItem
? buildMetadataBlock(extract.parentItem)
: "";
const systemParts = [getSystemPrompt()];
if (meta) {
systemParts.push(`论文元数据:\n${meta}`);
}
if (extract.text) {
systemParts.push(
`论文正文(页之间可能以换页符分隔):\n${extract.text}`,
);
}
const messages: ChatMessage[] = [
{ role: "system", content: systemParts.join("\n\n") },
];
// Keep recent history (exclude old system)
const history = options.history
.filter((m) => m.role !== "system")
.slice(-20);
messages.push(...history);
const paperBlock = [
meta ? `【论文元数据】\n${meta}` : "",
`论文正文】\n${extract.text}`,
]
.filter(Boolean)
.join("\n\n");
let taskBlock: string;
if (options.mode === "summary") {
const summaryAsk = getSummaryPrompt();
messages.push({
role: "user",
content: summaryAsk,
});
taskBlock = `【任务】
请直接基于本会话开头已提供的【论文正文】完成结构化总结。
严禁回复「请提供论文」「文本不完整无法总结」等推脱话术;信息不足时也请基于已有正文尽力总结,并简要注明局限。
${getSummaryPrompt()}`;
} else {
let content = options.userText.trim();
let question = options.userText.trim();
if (options.selection?.trim()) {
content =
`【选中原文】\n${options.selection.trim()}\n\n【问题】\n${content}`;
question = `【选中原文】\n${options.selection.trim()}\n\n【问题】\n${question}`;
} else {
question = `【问题】\n${question}`;
}
messages.push({ role: "user", content });
taskBlock = `【任务】
请直接基于本会话开头已提供的论文材料回答。
严禁要求用户再次提供论文全文。
${question}`;
}
const system = `${getSystemPrompt()}
硬性规则(必须遵守):
1. 论文材料已在本会话首条用户消息中提供(【论文正文】);后续每一轮提问仍以该材料为准。
2. 绝对禁止说「请提供论文文本」「只有引用/片段无法总结」之类的话。
3. 若正文有截断标记,仍须基于已给出的章节作答,并可选一句说明「部分中间内容经抽样」。
4. 结合此前对话继续深入回答,不要假装这是全新的、没有论文的会话。
5. 不要把参考文献列表误判为「没有正文」。`;
const messages = assemblePaperChatMessages({
system,
paperBlock,
taskBlock,
history: options.history,
});
return {
messages,
extract,
warning: warnings.length ? warnings.join(" ") : undefined,
ready: true,
};
}