allow agent multi image generation
This commit is contained in:
parent
e0c277c76a
commit
599abc5021
@ -905,11 +905,17 @@ export const Response = ({
|
||||
),
|
||||
};
|
||||
|
||||
const renderImagePreview = (src: string, alt: string | undefined, key: string) => (
|
||||
const renderImagePreview = (
|
||||
src: string,
|
||||
alt: string | undefined,
|
||||
key: string,
|
||||
compactGrid = false
|
||||
) => (
|
||||
<ImagePreview
|
||||
key={key}
|
||||
src={src}
|
||||
alt={alt}
|
||||
compactGrid={compactGrid}
|
||||
onImageEdit={onImageEdit}
|
||||
onDrawingComplete={onDrawingComplete}
|
||||
onImageEnhance={onImageEnhance}
|
||||
@ -925,6 +931,49 @@ export const Response = ({
|
||||
/>
|
||||
);
|
||||
|
||||
const renderImageGrid = (
|
||||
images: Array<{ alt?: string; src: string }>,
|
||||
keyPrefix: string
|
||||
) => {
|
||||
if (images.length === 0) return null;
|
||||
if (images.length === 1) {
|
||||
const image = images[0];
|
||||
return renderImagePreview(
|
||||
image.src,
|
||||
image.alt,
|
||||
`${image.src}-${processingKey}-${keyPrefix}-single`
|
||||
);
|
||||
}
|
||||
|
||||
const gridClassName =
|
||||
images.length === 2
|
||||
? "grid-cols-2 sm:max-w-[640px]"
|
||||
: images.length === 3
|
||||
? "grid-cols-2 sm:grid-cols-3 sm:max-w-[780px]"
|
||||
: "grid-cols-2 sm:grid-cols-4 sm:max-w-[920px]";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"not-prose my-3 grid w-full gap-1.5 overflow-hidden rounded-lg",
|
||||
gridClassName
|
||||
)}
|
||||
key={`${keyPrefix}-image-grid`}
|
||||
>
|
||||
{images.map((image, index) => (
|
||||
<div className="min-w-0" key={`${image.src}-${index}`}>
|
||||
{renderImagePreview(
|
||||
image.src,
|
||||
image.alt,
|
||||
`${image.src}-${processingKey}-${keyPrefix}-grid-${index}`,
|
||||
true
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTextSegment = (text: string, keyPrefix: string): ReactNode => {
|
||||
if (!text.trim()) return null;
|
||||
|
||||
@ -937,20 +986,31 @@ export const Response = ({
|
||||
const hasImageSegments = segments.some((segment) => segment.type === "image");
|
||||
|
||||
if (hasImageSegments) {
|
||||
return segments.map((segment, index) => {
|
||||
const nodes: ReactNode[] = [];
|
||||
let pendingImages: Array<{ alt?: string; src: string }> = [];
|
||||
const flushImages = (index: number) => {
|
||||
if (pendingImages.length === 0) return;
|
||||
nodes.push(
|
||||
renderImageGrid(pendingImages, `${keyPrefix}-images-${index}`)
|
||||
);
|
||||
pendingImages = [];
|
||||
};
|
||||
|
||||
segments.forEach((segment, index) => {
|
||||
if (segment.type === "image") {
|
||||
return renderImagePreview(
|
||||
segment.src,
|
||||
segment.alt,
|
||||
`${segment.src}-${processingKey}-${keyPrefix}-${index}`
|
||||
);
|
||||
pendingImages.push({
|
||||
alt: segment.alt,
|
||||
src: segment.src,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!segment.value.trim()) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
flushImages(index);
|
||||
nodes.push(
|
||||
<Streamdown
|
||||
className={streamdownClassName}
|
||||
components={streamdownComponents}
|
||||
@ -960,6 +1020,8 @@ export const Response = ({
|
||||
</Streamdown>
|
||||
);
|
||||
});
|
||||
flushImages(segments.length);
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,8 @@ export function ImagePreview({
|
||||
isProcessingExtend,
|
||||
isProcessingAngleEdit,
|
||||
isProcessingWatermarkRemove,
|
||||
imageIndex
|
||||
imageIndex,
|
||||
compactGrid = false
|
||||
}: {
|
||||
src: string;
|
||||
alt?: string;
|
||||
@ -64,6 +65,7 @@ export function ImagePreview({
|
||||
isProcessingAngleEdit?: boolean;
|
||||
isProcessingWatermarkRemove?: boolean;
|
||||
imageIndex?: number;
|
||||
compactGrid?: boolean;
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isAnnotationMode, setIsAnnotationMode] = useState(false);
|
||||
@ -293,16 +295,26 @@ export function ImagePreview({
|
||||
return (
|
||||
<>
|
||||
{/* 缩略图(显示压缩后的缩略图)*/}
|
||||
<div className="group relative inline-block max-w-full mr-3 mb-3">
|
||||
<div
|
||||
className={
|
||||
compactGrid
|
||||
? "group relative block aspect-[3/4] w-full overflow-hidden rounded-lg"
|
||||
: "group relative inline-block max-w-full mr-3 mb-3"
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={previewSrc}
|
||||
alt="Generated Image"
|
||||
className="cursor-pointer rounded-lg transition-opacity hover:opacity-90"
|
||||
className={
|
||||
compactGrid
|
||||
? "h-full w-full cursor-pointer rounded-lg object-cover transition-opacity hover:opacity-90"
|
||||
: "cursor-pointer rounded-lg transition-opacity hover:opacity-90"
|
||||
}
|
||||
style={{
|
||||
maxWidth: `${maxWidth}px`,
|
||||
height: "auto",
|
||||
maxWidth: compactGrid ? "none" : `${maxWidth}px`,
|
||||
height: compactGrid ? "100%" : "auto",
|
||||
width: "100%",
|
||||
objectFit: "contain"
|
||||
objectFit: compactGrid ? "cover" : "contain"
|
||||
}}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
|
||||
@ -169,15 +169,23 @@ export async function executeDirectAgentImageGeneration(
|
||||
params.imageParams?.imageSize || params.defaultImageQualityParams?.imageSize;
|
||||
const imageCount =
|
||||
params.imageParams?.imageCount || params.defaultImageQualityParams?.imageCount;
|
||||
const shouldIgnoreModelMaxImages =
|
||||
typeof imageCount === "number" && Number.isFinite(imageCount) && imageCount > 1;
|
||||
const result = await generateCanvasImage({
|
||||
prompt,
|
||||
negativePrompt: params.imageParams?.negativePrompt,
|
||||
model: params.finalModelId,
|
||||
ownerKey: params.userId,
|
||||
debugLabel: "direct-agent-image-generation",
|
||||
debugMeta: {
|
||||
agentIgnoreModelMaxImages: shouldIgnoreModelMaxImages,
|
||||
requestedAgentImageCount: imageCount ?? null,
|
||||
},
|
||||
aspectRatio:
|
||||
params.imageParams?.aspectRatio || params.defaultImageQualityParams?.aspectRatio,
|
||||
imageSize,
|
||||
imageCount,
|
||||
ignoreModelMaxImages: shouldIgnoreModelMaxImages,
|
||||
referenceImages: params.referenceImageUrls,
|
||||
});
|
||||
|
||||
|
||||
@ -116,6 +116,7 @@ export interface CanvasGenerateImageRequest {
|
||||
ownerKey?: string;
|
||||
debugLabel?: string;
|
||||
debugMeta?: Record<string, unknown>;
|
||||
ignoreModelMaxImages?: boolean;
|
||||
localEditComposite?: CanvasLocalEditCompositeConfig;
|
||||
scaleAdjustPatchComposite?: CanvasScaleAdjustPatchCompositeConfig;
|
||||
scaleAdjustVerification?: CanvasScaleAdjustVerificationConfig;
|
||||
@ -3167,12 +3168,14 @@ function normalizeCanvasImageParamsByModel(params: {
|
||||
imageCount: number;
|
||||
imageSize: string;
|
||||
imageGenConfig: CanvasImageGenConfig | null | undefined;
|
||||
ignoreModelMaxImages?: boolean;
|
||||
}) {
|
||||
const maxImages =
|
||||
const configuredMaxImages =
|
||||
typeof params.imageGenConfig?.maxImages === "number" &&
|
||||
Number.isFinite(params.imageGenConfig.maxImages)
|
||||
? Math.max(1, Math.floor(params.imageGenConfig.maxImages))
|
||||
: 12;
|
||||
const maxImages = params.ignoreModelMaxImages ? 12 : configuredMaxImages;
|
||||
const imageCount = Math.max(1, Math.min(maxImages, Math.floor(params.imageCount)));
|
||||
|
||||
const requestedSize = normalizeCanvasImageSizeValue(params.imageSize);
|
||||
@ -3635,6 +3638,7 @@ export async function generateCanvasImage(
|
||||
imageCount: requestedImageCount,
|
||||
imageSize: requestedImageSize,
|
||||
imageGenConfig: selectedModel.model.imageGenConfig as CanvasImageGenConfig | null | undefined,
|
||||
ignoreModelMaxImages: request.ignoreModelMaxImages === true,
|
||||
});
|
||||
const imageSize = normalizedImageParams.imageSize;
|
||||
const imageCount =
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user