修复连续改图变糊:历史图优先原始上传并提升默认清晰度
This commit is contained in:
parent
20c9f6d821
commit
3db32eceb0
@ -955,53 +955,82 @@ export async function POST(request: Request) {
|
||||
// 逻辑:只要用户在对话中没有附上新图片,就默认继续处理之前的图片
|
||||
if (!hasImage && smartAutoHistoryMessagesFromDb.length > 0) {
|
||||
console.log("[Smart Auto Mode] 🔍 No image in current message, auto-searching history...");
|
||||
|
||||
// 从历史消息中倒序查找最近一轮包含图片的消息
|
||||
// 收集该消息中的所有图片(支持多图融合编辑)
|
||||
|
||||
const explicitFollowLatestResult = /(上一张|上一轮|刚生成|最新生成|这个结果|该结果|按这个结果|继续在这张|基于这张结果|延续上一次结果)/i.test(
|
||||
textContent
|
||||
);
|
||||
|
||||
const latestAssistantImages: string[] = [];
|
||||
const latestUserImages: string[] = [];
|
||||
const pushUniqueUrl = (bucket: string[], maybeUrl?: string) => {
|
||||
if (!maybeUrl || typeof maybeUrl !== "string") return;
|
||||
const normalized = maybeUrl.trim();
|
||||
if (!/^https?:\/\//i.test(normalized)) return;
|
||||
if (!bucket.includes(normalized)) {
|
||||
bucket.push(normalized);
|
||||
}
|
||||
};
|
||||
|
||||
// 从历史消息中倒序查找最近的“AI生成图”和“用户上传图”
|
||||
for (let i = smartAutoHistoryMessagesFromDb.length - 1; i >= 0; i--) {
|
||||
const msg = smartAutoHistoryMessagesFromDb[i];
|
||||
const parts = msg.parts as any[];
|
||||
|
||||
|
||||
if (!parts) continue;
|
||||
|
||||
// 查找AI生成的图片(从Markdown中提取所有图片)
|
||||
if (msg.role === "assistant") {
|
||||
|
||||
if (msg.role === "assistant" && latestAssistantImages.length === 0) {
|
||||
for (const part of parts) {
|
||||
if (part.type === "text" && part.text) {
|
||||
// 从 markdown 中优先提取原图 URL,避免把缩略图当作下一轮输入导致画质下降
|
||||
const parsedImageUrls = extractOriginalImageUrlsFromText(part.text);
|
||||
for (const parsedUrl of parsedImageUrls) {
|
||||
if (!smartAutoHistoryImages.includes(parsedUrl)) {
|
||||
smartAutoHistoryImages.push(parsedUrl);
|
||||
}
|
||||
pushUniqueUrl(latestAssistantImages, parsedUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果在这条assistant消息中找到了图片,就停止搜索(使用最近一轮的结果)
|
||||
if (smartAutoHistoryImages.length > 0) {
|
||||
console.log("[Smart Auto Mode] 🖼️ Found AI-generated images:", smartAutoHistoryImages.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 查找用户上传的图片(收集该消息中的所有图片)
|
||||
if (msg.role === "user" && smartAutoHistoryImages.length === 0) {
|
||||
|
||||
if (msg.role === "user" && latestUserImages.length === 0) {
|
||||
for (const part of parts) {
|
||||
if ((part.type === "file" || part.type === "image") && part.url) {
|
||||
if (!smartAutoHistoryImages.includes(part.url)) {
|
||||
smartAutoHistoryImages.push(part.url);
|
||||
pushUniqueUrl(latestUserImages, part.url);
|
||||
}
|
||||
if (part.type === "image_url" && part.image_url?.url) {
|
||||
pushUniqueUrl(latestUserImages, part.image_url.url);
|
||||
}
|
||||
if (part.type === "text" && part.text) {
|
||||
const parsedImageUrls = extractOriginalImageUrlsFromText(part.text);
|
||||
for (const parsedUrl of parsedImageUrls) {
|
||||
pushUniqueUrl(latestUserImages, parsedUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果在这条user消息中找到了图片,就停止搜索
|
||||
if (smartAutoHistoryImages.length > 0) {
|
||||
console.log("[Smart Auto Mode] 🖼️ Found user-uploaded images:", smartAutoHistoryImages.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (latestAssistantImages.length > 0 && latestUserImages.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找到了历史图片,标记为有图片
|
||||
|
||||
if (explicitFollowLatestResult && latestAssistantImages.length > 0) {
|
||||
smartAutoHistoryImages = latestAssistantImages.slice(0, 4);
|
||||
console.log(
|
||||
"[Smart Auto Mode] 🖼️ Using latest generated image(s) by explicit instruction:",
|
||||
smartAutoHistoryImages.length
|
||||
);
|
||||
} else if (latestUserImages.length > 0) {
|
||||
smartAutoHistoryImages = latestUserImages.slice(0, 4);
|
||||
console.log(
|
||||
"[Smart Auto Mode] 🖼️ Using latest user-uploaded image(s) to avoid iterative blur:",
|
||||
smartAutoHistoryImages.length
|
||||
);
|
||||
} else if (latestAssistantImages.length > 0) {
|
||||
smartAutoHistoryImages = latestAssistantImages.slice(0, 4);
|
||||
console.log(
|
||||
"[Smart Auto Mode] 🖼️ Fallback to latest generated image(s):",
|
||||
smartAutoHistoryImages.length
|
||||
);
|
||||
}
|
||||
|
||||
if (smartAutoHistoryImages.length > 0) {
|
||||
hasImage = true;
|
||||
imageUrls = smartAutoHistoryImages;
|
||||
@ -1201,6 +1230,11 @@ export async function POST(request: Request) {
|
||||
hasUserCustomSettings: hasUserCustomImageParams,
|
||||
})
|
||||
: requestBody.imageParams;
|
||||
const defaultImageQualityParams = {
|
||||
aspectRatio: "auto",
|
||||
imageSize: smartAutoDetectedIntent === "image_edit" ? "4K" : "2K",
|
||||
imageCount: 1,
|
||||
} as const;
|
||||
|
||||
if (shouldApplyAgentImageParams) {
|
||||
console.log("[Smart Auto Mode] 🎯 Effective image params:", {
|
||||
@ -1564,7 +1598,11 @@ export async function POST(request: Request) {
|
||||
// 调用 doGenerate 获取图片(如果是备用模型,传入 overrideModelId)
|
||||
const result = await (languageModel as any).doGenerate({
|
||||
messages: modelMessages,
|
||||
imageParams: effectiveImageParams || { aspectRatio: "auto", imageSize: "2K" },
|
||||
imageParams:
|
||||
effectiveImageParams || {
|
||||
aspectRatio: defaultImageQualityParams.aspectRatio,
|
||||
imageSize: defaultImageQualityParams.imageSize,
|
||||
},
|
||||
overrideModelId: isRetry ? modelIdToUse : undefined, // 🆕 使用备用模型 ID
|
||||
});
|
||||
|
||||
@ -1930,7 +1968,12 @@ export async function POST(request: Request) {
|
||||
// 调用 doGenerate 获取图片,传递模型显示名称
|
||||
const result = await (languageModel as any).doGenerate({
|
||||
messages: modelMessages,
|
||||
imageParams: effectiveImageParams || { aspectRatio: "auto", imageSize: "2K", imageCount: 1 },
|
||||
imageParams:
|
||||
effectiveImageParams || {
|
||||
aspectRatio: defaultImageQualityParams.aspectRatio,
|
||||
imageSize: defaultImageQualityParams.imageSize,
|
||||
imageCount: defaultImageQualityParams.imageCount,
|
||||
},
|
||||
modelDisplayName, // 🆕 传递模型显示名称
|
||||
overrideModelId: isRetry ? modelIdToUse : undefined,
|
||||
});
|
||||
@ -2028,7 +2071,12 @@ export async function POST(request: Request) {
|
||||
|
||||
const candidateResult = await (candidateLanguageModel as any).doGenerate({
|
||||
messages: candidateMessages,
|
||||
imageParams: effectiveImageParams || { aspectRatio: "auto", imageSize: "2K", imageCount: 1 },
|
||||
imageParams:
|
||||
effectiveImageParams || {
|
||||
aspectRatio: defaultImageQualityParams.aspectRatio,
|
||||
imageSize: defaultImageQualityParams.imageSize,
|
||||
imageCount: defaultImageQualityParams.imageCount,
|
||||
},
|
||||
modelDisplayName: candidate.model.displayName,
|
||||
overrideModelId: candidate.model.modelId,
|
||||
});
|
||||
@ -2274,7 +2322,12 @@ export async function POST(request: Request) {
|
||||
const tryGenerateImage = async (modelIdToUse: string, isRetry: boolean) => {
|
||||
const result = await (languageModel as any).doGenerate({
|
||||
messages: modelMessages,
|
||||
imageParams: effectiveImageParams || { aspectRatio: "auto", imageSize: "2K", imageCount: 1 },
|
||||
imageParams:
|
||||
effectiveImageParams || {
|
||||
aspectRatio: defaultImageQualityParams.aspectRatio,
|
||||
imageSize: defaultImageQualityParams.imageSize,
|
||||
imageCount: defaultImageQualityParams.imageCount,
|
||||
},
|
||||
overrideModelId: isRetry ? modelIdToUse : undefined,
|
||||
});
|
||||
if (result?.finishReason === "error") {
|
||||
@ -2366,7 +2419,12 @@ export async function POST(request: Request) {
|
||||
|
||||
const candidateResult = await (candidateLanguageModel as any).doGenerate({
|
||||
messages: candidateMessages,
|
||||
imageParams: effectiveImageParams || { aspectRatio: "auto", imageSize: "2K", imageCount: 1 },
|
||||
imageParams:
|
||||
effectiveImageParams || {
|
||||
aspectRatio: defaultImageQualityParams.aspectRatio,
|
||||
imageSize: defaultImageQualityParams.imageSize,
|
||||
imageCount: defaultImageQualityParams.imageCount,
|
||||
},
|
||||
modelDisplayName: candidate.model.displayName,
|
||||
overrideModelId: candidate.model.modelId,
|
||||
});
|
||||
|
||||
@ -171,7 +171,7 @@ export function ImagePreview({
|
||||
};
|
||||
|
||||
const { thumbnail, original, maxWidth, is4K } = parseImageUrls();
|
||||
const preferOriginalForPreview = maxWidth >= 380 && original && original !== thumbnail;
|
||||
const preferOriginalForPreview = Boolean(original && original !== thumbnail);
|
||||
const previewSrc = preferOriginalForPreview ? original : thumbnail;
|
||||
const previewSrcSet = original
|
||||
? `${thumbnail} 1x, ${original} 2x`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user