Expose MSR image analysis payload debug
This commit is contained in:
@@ -60,7 +60,22 @@ function resolveCandidateImageUrls(originNode) {
|
|||||||
async function imageInputToDataUrl(node, inputName) {
|
async function imageInputToDataUrl(node, inputName) {
|
||||||
const originNode = getOriginNodeForInput(node, inputName);
|
const originNode = getOriginNodeForInput(node, inputName);
|
||||||
const candidateUrls = resolveCandidateImageUrls(originNode);
|
const candidateUrls = resolveCandidateImageUrls(originNode);
|
||||||
if (!candidateUrls.length) return null;
|
if (!candidateUrls.length) {
|
||||||
|
return {
|
||||||
|
dataUrl: null,
|
||||||
|
debug: {
|
||||||
|
inputName,
|
||||||
|
originNodeId: originNode?.id ?? null,
|
||||||
|
originNodeType: originNode?.type ?? null,
|
||||||
|
candidateUrls: [],
|
||||||
|
selectedUrl: null,
|
||||||
|
mimeType: null,
|
||||||
|
blobBytes: 0,
|
||||||
|
dataUrlLength: 0,
|
||||||
|
error: "No candidate image URLs found",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
for (const imageUrl of candidateUrls) {
|
for (const imageUrl of candidateUrls) {
|
||||||
try {
|
try {
|
||||||
@@ -72,17 +87,44 @@ async function imageInputToDataUrl(node, inputName) {
|
|||||||
if (!blob.type.startsWith("image/")) {
|
if (!blob.type.startsWith("image/")) {
|
||||||
throw new Error(`Unexpected blob type: ${blob.type || "unknown"}`);
|
throw new Error(`Unexpected blob type: ${blob.type || "unknown"}`);
|
||||||
}
|
}
|
||||||
return await new Promise((resolve) => {
|
const dataUrl = await new Promise((resolve) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onloadend = () => resolve(reader.result);
|
reader.onloadend = () => resolve(reader.result);
|
||||||
reader.readAsDataURL(blob);
|
reader.readAsDataURL(blob);
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
dataUrl,
|
||||||
|
debug: {
|
||||||
|
inputName,
|
||||||
|
originNodeId: originNode?.id ?? null,
|
||||||
|
originNodeType: originNode?.type ?? null,
|
||||||
|
candidateUrls,
|
||||||
|
selectedUrl: imageUrl,
|
||||||
|
mimeType: blob.type || null,
|
||||||
|
blobBytes: blob.size || 0,
|
||||||
|
dataUrlLength: typeof dataUrl === "string" ? dataUrl.length : 0,
|
||||||
|
error: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[MSRCharacter] Failed candidate image source", imageUrl, error);
|
console.warn("[MSRCharacter] Failed candidate image source", imageUrl, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return {
|
||||||
|
dataUrl: null,
|
||||||
|
debug: {
|
||||||
|
inputName,
|
||||||
|
originNodeId: originNode?.id ?? null,
|
||||||
|
originNodeType: originNode?.type ?? null,
|
||||||
|
candidateUrls,
|
||||||
|
selectedUrl: null,
|
||||||
|
mimeType: null,
|
||||||
|
blobBytes: 0,
|
||||||
|
dataUrlLength: 0,
|
||||||
|
error: "All candidate image URLs failed",
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWidgetValue(node, widget, value) {
|
function setWidgetValue(node, widget, value) {
|
||||||
@@ -330,11 +372,13 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
|||||||
node.setDirtyCanvas?.(true, true);
|
node.setDirtyCanvas?.(true, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const imageResults = await Promise.all([
|
||||||
|
imageInputToDataUrl(node, "image_1"),
|
||||||
|
imageInputToDataUrl(node, "image_2"),
|
||||||
|
]);
|
||||||
|
const imageDebug = imageResults.map((result) => result?.debug || null).filter(Boolean);
|
||||||
const images = (
|
const images = (
|
||||||
await Promise.all([
|
imageResults.map((result) => result?.dataUrl || null)
|
||||||
imageInputToDataUrl(node, "image_1"),
|
|
||||||
imageInputToDataUrl(node, "image_2"),
|
|
||||||
])
|
|
||||||
).filter(Boolean);
|
).filter(Boolean);
|
||||||
|
|
||||||
if (!images.length) {
|
if (!images.length) {
|
||||||
@@ -348,10 +392,15 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
|||||||
base_url: baseUrlWidget?.value || "",
|
base_url: baseUrlWidget?.value || "",
|
||||||
model: modelWidget?.value || "",
|
model: modelWidget?.value || "",
|
||||||
image_b64: images,
|
image_b64: images,
|
||||||
|
image_debug: imageDebug,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.status !== "success") {
|
if (result.status !== "success") {
|
||||||
|
console.warn("[MSRCharacter] analyze debug", {
|
||||||
|
sentImages: imageDebug,
|
||||||
|
response: result,
|
||||||
|
});
|
||||||
throw new Error(result.message || "Unknown analysis error");
|
throw new Error(result.message || "Unknown analysis error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -549,10 +549,11 @@ def _resolve_provider(data):
|
|||||||
async def analyze_character_endpoint(request):
|
async def analyze_character_endpoint(request):
|
||||||
try:
|
try:
|
||||||
import aiohttp
|
import aiohttp
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
image_b64 = data.get("image_b64", "")
|
image_b64 = data.get("image_b64", "")
|
||||||
char_index = int(data.get("char_index", 0))
|
image_debug = data.get("image_debug") or []
|
||||||
provider, base_url, model_name = _resolve_provider(data)
|
char_index = int(data.get("char_index", 0))
|
||||||
|
provider, base_url, model_name = _resolve_provider(data)
|
||||||
|
|
||||||
if provider == "off":
|
if provider == "off":
|
||||||
return web.json_response({"status": "error", "message": "Analyze is set to Off / Manual."})
|
return web.json_response({"status": "error", "message": "Analyze is set to Off / Manual."})
|
||||||
@@ -639,6 +640,8 @@ async def analyze_character_endpoint(request):
|
|||||||
"status": "error",
|
"status": "error",
|
||||||
"message": "Ollama returned only a truncated analysis response.",
|
"message": "Ollama returned only a truncated analysis response.",
|
||||||
"debug_candidates": debug_candidates,
|
"debug_candidates": debug_candidates,
|
||||||
|
"image_debug": image_debug,
|
||||||
|
"image_lengths": [len(b64) for b64 in cleaned_b64_list],
|
||||||
"description": generated_text,
|
"description": generated_text,
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user