修复连续对话误用缩略图导致画质下降

This commit is contained in:
Your Name 2026-02-08 23:10:58 +08:00
parent 75993d98af
commit 35d50973db

View File

@ -367,29 +367,13 @@ async function convertMessagesWithImages(messages: ChatMessage[], providerType:
return convertedMessages; return convertedMessages;
} }
/** function parseImageAltMetadata(altText: string, thumbnailUrl: string): {
* 解析生图 Markdown 并保存图片记录到数据库 originalUrl: string;
* 支持三种格式:thumb|||url|||size、thumb$$url$$size、thumb|url|size imageSize: string;
*/ } {
async function saveGeneratedImages(
imageMarkdown: string,
userId: string,
chatId: string,
messageId: string,
prompt: string,
modelId: string
): Promise<void> {
// 匹配 Markdown 图片格式: ![alt](url)
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
const matches = [...imageMarkdown.matchAll(imageRegex)];
for (const match of matches) {
const altText = match[1] || "";
const thumbnailUrl = match[2];
let originalUrl = thumbnailUrl; let originalUrl = thumbnailUrl;
let imageSize = "2K"; let imageSize = "2K";
// 解析 alt 中的原图 URL 和尺寸
// 格式1: thumb|||originalUrl|||size (新格式) // 格式1: thumb|||originalUrl|||size (新格式)
if (altText.includes("thumb|||")) { if (altText.includes("thumb|||")) {
const content = altText.substring(altText.indexOf("thumb|||") + 8); const content = altText.substring(altText.indexOf("thumb|||") + 8);
@ -421,14 +405,69 @@ async function saveGeneratedImages(
} else if (thumbnailUrl.includes("volcano-thumb-")) { } else if (thumbnailUrl.includes("volcano-thumb-")) {
originalUrl = thumbnailUrl.replace("volcano-thumb-", "volcano-orig-"); originalUrl = thumbnailUrl.replace("volcano-thumb-", "volcano-orig-");
} else if (thumbnailUrl.includes("alibaba-image-thumb-")) { } else if (thumbnailUrl.includes("alibaba-image-thumb-")) {
// 🆕 阿里生图模型
originalUrl = thumbnailUrl.replace("alibaba-image-thumb-", "alibaba-image-orig-"); originalUrl = thumbnailUrl.replace("alibaba-image-thumb-", "alibaba-image-orig-");
} else if (thumbnailUrl.includes("ruxa-image-thumb-")) { } else if (thumbnailUrl.includes("ruxa-image-thumb-")) {
// 🆕 RUXA 生图模型
originalUrl = thumbnailUrl.replace("ruxa-image-thumb-", "ruxa-image-orig-"); originalUrl = thumbnailUrl.replace("ruxa-image-thumb-", "ruxa-image-orig-");
} }
} }
return { originalUrl, imageSize };
}
function extractOriginalImageUrlsFromText(text: string): string[] {
const imageRegex = /!\[([^\]]*)\]\((https?:\/\/[^\s)]+)\)/g;
const imageUrls: string[] = [];
const added = new Set<string>();
let hasMarkdownImages = false;
let match: RegExpExecArray | null;
while ((match = imageRegex.exec(text)) !== null) {
hasMarkdownImages = true;
const altText = match[1] || "";
const thumbnailUrl = match[2];
const { originalUrl } = parseImageAltMetadata(altText, thumbnailUrl);
const finalUrl = originalUrl || thumbnailUrl;
if (finalUrl && /^https?:\/\//i.test(finalUrl) && !added.has(finalUrl)) {
added.add(finalUrl);
imageUrls.push(finalUrl);
}
}
if (!hasMarkdownImages) {
const urlRegex = /https?:\/\/[^\s"'<>]+\.(?:jpg|jpeg|png|gif|webp|bmp|svg)(?:\?[^\s"'<>]*)?/gi;
const matchedUrls = text.match(urlRegex) || [];
for (const url of matchedUrls) {
if (!added.has(url)) {
added.add(url);
imageUrls.push(url);
}
}
}
return imageUrls;
}
/**
* 解析生图 Markdown 并保存图片记录到数据库
* 支持三种格式:thumb|||url|||size、thumb$$url$$size、thumb|url|size
*/
async function saveGeneratedImages(
imageMarkdown: string,
userId: string,
chatId: string,
messageId: string,
prompt: string,
modelId: string
): Promise<void> {
// 匹配 Markdown 图片格式: ![alt](url)
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
const matches = [...imageMarkdown.matchAll(imageRegex)];
for (const match of matches) {
const altText = match[1] || "";
const thumbnailUrl = match[2];
const { originalUrl, imageSize } = parseImageAltMetadata(altText, thumbnailUrl);
try { try {
await db.insert(generatedImage).values({ await db.insert(generatedImage).values({
userId, userId,
@ -595,11 +634,11 @@ export async function POST(request: Request) {
if (msg.role === "assistant") { if (msg.role === "assistant") {
for (const part of parts) { for (const part of parts) {
if (part.type === "text" && part.text) { if (part.type === "text" && part.text) {
// 匹配所有Markdown图片格式: ![alt](url) // 从 markdown 中优先提取原图 URL,避免把缩略图当作下一轮输入导致画质下降
const imgMatches = part.text.matchAll(/!\[.*?\]\((https?:\/\/[^\s)]+)\)/g); const parsedImageUrls = extractOriginalImageUrlsFromText(part.text);
for (const match of imgMatches) { for (const parsedUrl of parsedImageUrls) {
if (match[1] && !smartAutoHistoryImages.includes(match[1])) { if (!smartAutoHistoryImages.includes(parsedUrl)) {
smartAutoHistoryImages.push(match[1]); smartAutoHistoryImages.push(parsedUrl);
} }
} }
} }