feat: adapt image tuning by engine
This commit is contained in:
@@ -13,12 +13,31 @@ import type { PromptMaterial } from "@/lib/prompt/assembler";
|
||||
type GenerateMode = "image" | "video";
|
||||
type StudioMode = GenerateMode | ImageEditMode;
|
||||
type MaterialKind = PromptMaterial["type"];
|
||||
type ImageGenerateEngine = "jimeng" | "evolink";
|
||||
|
||||
type MentionState = {
|
||||
start: number;
|
||||
query: string;
|
||||
};
|
||||
|
||||
type HealthCapability = {
|
||||
id: string;
|
||||
engine?: string;
|
||||
};
|
||||
|
||||
const jimengInfluenceOptions = [
|
||||
{ id: "creative", label: "创意 35", scale: 35 },
|
||||
{ id: "balanced", label: "均衡 50", scale: 50 },
|
||||
{ id: "precise", label: "贴合 70", scale: 70 },
|
||||
{ id: "strict", label: "严格 85", scale: 85 }
|
||||
];
|
||||
|
||||
const evolinkQualityOptions = [
|
||||
{ id: "low", label: "快速", quality: "low" },
|
||||
{ id: "medium", label: "标准", quality: "medium" },
|
||||
{ id: "high", label: "精细", quality: "high" }
|
||||
];
|
||||
|
||||
const imageSizePresets = [
|
||||
{ label: "1:1", width: 2048, height: 2048 },
|
||||
{ label: "4:3", width: 2304, height: 1728 },
|
||||
@@ -41,7 +60,9 @@ export function CreateStudio({ initialMode = "image" }: { initialMode?: StudioMo
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [notice, setNotice] = useState<string | null>(null);
|
||||
const [imageSize, setImageSize] = useState(imageSizePresets[0]);
|
||||
const [imageScale, setImageScale] = useState(50);
|
||||
const [imageEngine, setImageEngine] = useState<ImageGenerateEngine>("jimeng");
|
||||
const [jimengInfluence, setJimengInfluence] = useState(jimengInfluenceOptions[1].id);
|
||||
const [evolinkQuality, setEvolinkQuality] = useState(evolinkQualityOptions[1].id);
|
||||
const [forceSingle, setForceSingle] = useState(true);
|
||||
const [videoRatio, setVideoRatio] = useState("9:16");
|
||||
const [videoDuration, setVideoDuration] = useState(VIDEO_DURATION_DEFAULT);
|
||||
@@ -59,6 +80,8 @@ export function CreateStudio({ initialMode = "image" }: { initialMode?: StudioMo
|
||||
const isImageEditMode = mode === "inpaint" || mode === "upscale";
|
||||
const generateMode: GenerateMode = mode === "video" ? "video" : "image";
|
||||
const prompt = promptByMode[generateMode];
|
||||
const selectedJimengInfluence = jimengInfluenceOptions.find((option) => option.id === jimengInfluence) || jimengInfluenceOptions[1];
|
||||
const selectedEvolinkQuality = evolinkQualityOptions.find((option) => option.id === evolinkQuality) || evolinkQualityOptions[1];
|
||||
const visibleMaterials = pageItems(materials, materialPage, MATERIAL_PAGE_SIZE);
|
||||
const materialPageOffset = (clampPage(materialPage, materials.length, MATERIAL_PAGE_SIZE) - 1) * MATERIAL_PAGE_SIZE;
|
||||
const mentionSuggestions = useMemo(() => {
|
||||
@@ -90,6 +113,20 @@ export function CreateStudio({ initialMode = "image" }: { initialMode?: StudioMo
|
||||
if (materialBoardRef.current) revealChildren(materialBoardRef.current, ".material-card");
|
||||
}, [materials.length, materialPage]);
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
void fetch("/api/health")
|
||||
.then((response) => response.ok ? response.json() : null)
|
||||
.then((payload: { capabilities?: HealthCapability[] } | null) => {
|
||||
const engine = payload?.capabilities?.find((capability) => capability.id === "image.generate")?.engine;
|
||||
if (active && (engine === "evolink" || engine === "jimeng")) setImageEngine(engine);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
function setPrompt(value: string) {
|
||||
setPromptByMode((items) => ({ ...items, [generateMode]: value }));
|
||||
}
|
||||
@@ -229,7 +266,9 @@ export function CreateStudio({ initialMode = "image" }: { initialMode?: StudioMo
|
||||
materials: materials.filter((material) => material.type === "image"),
|
||||
width: imageSize.width,
|
||||
height: imageSize.height,
|
||||
scale: imageScale,
|
||||
...(imageEngine === "evolink"
|
||||
? { quality: selectedEvolinkQuality.quality }
|
||||
: { scale: selectedJimengInfluence.scale }),
|
||||
force_single: forceSingle
|
||||
}
|
||||
: {
|
||||
@@ -432,9 +471,17 @@ export function CreateStudio({ initialMode = "image" }: { initialMode?: StudioMo
|
||||
{imageSizePresets.map((preset) => <option key={preset.label}>{preset.label}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<div className="field inline-field range-field">
|
||||
<label htmlFor="imageScale">文本影响 {imageScale}</label>
|
||||
<input id="imageScale" type="range" min="1" max="100" value={imageScale} onChange={(event) => setImageScale(Number(event.target.value))} />
|
||||
<div className="field inline-field">
|
||||
<label htmlFor="imageEngineTuning">{imageEngine === "evolink" ? "生成质量" : "文本影响"}</label>
|
||||
{imageEngine === "evolink" ? (
|
||||
<select id="imageEngineTuning" value={evolinkQuality} onChange={(event) => setEvolinkQuality(event.target.value)}>
|
||||
{evolinkQualityOptions.map((option) => <option key={option.id} value={option.id}>{option.label}</option>)}
|
||||
</select>
|
||||
) : (
|
||||
<select id="imageEngineTuning" value={jimengInfluence} onChange={(event) => setJimengInfluence(event.target.value)}>
|
||||
{jimengInfluenceOptions.map((option) => <option key={option.id} value={option.id}>{option.label}</option>)}
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
<label className="toggle-line">
|
||||
<input type="checkbox" checked={forceSingle} onChange={(event) => setForceSingle(event.target.checked)} />
|
||||
|
||||
Reference in New Issue
Block a user