Allow custom character analyze prompts
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
const { app } = window.comfyAPI.app;
|
const { app } = window.comfyAPI.app;
|
||||||
const { api } = window.comfyAPI.api;
|
const { api } = window.comfyAPI.api;
|
||||||
|
const DEFAULT_ANALYZE_PROMPT = "Describe the character's physical appearance in two concise sentences. Specify their hair color/style, face details, and their clothing type/color. Keep the entire response very brief.";
|
||||||
|
|
||||||
function findWidget(node, name) {
|
function findWidget(node, name) {
|
||||||
return (node.widgets || []).find((widget) => widget.name === name);
|
return (node.widgets || []).find((widget) => widget.name === name);
|
||||||
@@ -369,15 +370,19 @@ function buildCharacterUi(node) {
|
|||||||
const providerWidget = findWidget(node, "analyze_provider");
|
const providerWidget = findWidget(node, "analyze_provider");
|
||||||
const baseUrlWidget = findWidget(node, "analyze_base_url");
|
const baseUrlWidget = findWidget(node, "analyze_base_url");
|
||||||
const modelWidget = findWidget(node, "analyze_model");
|
const modelWidget = findWidget(node, "analyze_model");
|
||||||
|
const promptWidget = findWidget(node, "analyze_prompt");
|
||||||
const provider = window.prompt("Analyze provider: ollama, lmstudio, custom, off", providerWidget?.value || "ollama");
|
const provider = window.prompt("Analyze provider: ollama, lmstudio, custom, off", providerWidget?.value || "ollama");
|
||||||
if (provider == null) return;
|
if (provider == null) return;
|
||||||
const baseUrl = window.prompt("Analyze base URL (blank = default)", baseUrlWidget?.value || "");
|
const baseUrl = window.prompt("Analyze base URL (blank = default)", baseUrlWidget?.value || "");
|
||||||
if (baseUrl == null) return;
|
if (baseUrl == null) return;
|
||||||
const model = window.prompt("Analyze model (blank = provider default)", modelWidget?.value || "");
|
const model = window.prompt("Analyze model (blank = provider default)", modelWidget?.value || "");
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
|
const prompt = window.prompt("Analyze prompt (blank = default)", promptWidget?.value || DEFAULT_ANALYZE_PROMPT);
|
||||||
|
if (prompt == null) return;
|
||||||
setWidgetValue(node, providerWidget, provider.trim() || "ollama");
|
setWidgetValue(node, providerWidget, provider.trim() || "ollama");
|
||||||
setWidgetValue(node, baseUrlWidget, baseUrl.trim());
|
setWidgetValue(node, baseUrlWidget, baseUrl.trim());
|
||||||
setWidgetValue(node, modelWidget, model.trim());
|
setWidgetValue(node, modelWidget, model.trim());
|
||||||
|
setWidgetValue(node, promptWidget, prompt.trim());
|
||||||
syncFormFromWidgets(node);
|
syncFormFromWidgets(node);
|
||||||
node.setDirtyCanvas?.(true, true);
|
node.setDirtyCanvas?.(true, true);
|
||||||
});
|
});
|
||||||
@@ -461,6 +466,7 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
|||||||
const providerWidget = findWidget(node, "analyze_provider");
|
const providerWidget = findWidget(node, "analyze_provider");
|
||||||
const baseUrlWidget = findWidget(node, "analyze_base_url");
|
const baseUrlWidget = findWidget(node, "analyze_base_url");
|
||||||
const modelWidget = findWidget(node, "analyze_model");
|
const modelWidget = findWidget(node, "analyze_model");
|
||||||
|
const promptWidget = findWidget(node, "analyze_prompt");
|
||||||
|
|
||||||
buttonWidget.label = "Analyzing...";
|
buttonWidget.label = "Analyzing...";
|
||||||
if (node._msrAnalyzeButton) {
|
if (node._msrAnalyzeButton) {
|
||||||
@@ -489,6 +495,7 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
|||||||
provider: providerWidget?.value || "ollama",
|
provider: providerWidget?.value || "ollama",
|
||||||
base_url: baseUrlWidget?.value || "",
|
base_url: baseUrlWidget?.value || "",
|
||||||
model: modelWidget?.value || "",
|
model: modelWidget?.value || "",
|
||||||
|
prompt: promptWidget?.value || "",
|
||||||
image_b64: images,
|
image_b64: images,
|
||||||
image_debug: imageDebug,
|
image_debug: imageDebug,
|
||||||
}),
|
}),
|
||||||
@@ -560,6 +567,9 @@ app.registerExtension({
|
|||||||
if (!findWidget(this, "analyze_model")) {
|
if (!findWidget(this, "analyze_model")) {
|
||||||
this.addWidget("text", "analyze_model", "");
|
this.addWidget("text", "analyze_model", "");
|
||||||
}
|
}
|
||||||
|
if (!findWidget(this, "analyze_prompt")) {
|
||||||
|
this.addWidget("text", "analyze_prompt", DEFAULT_ANALYZE_PROMPT);
|
||||||
|
}
|
||||||
|
|
||||||
if (!this._msrPreviewWidget) {
|
if (!this._msrPreviewWidget) {
|
||||||
const previewContainer = buildCharacterUi(this);
|
const previewContainer = buildCharacterUi(this);
|
||||||
@@ -587,7 +597,7 @@ app.registerExtension({
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
["alias", "description", "analyze_provider", "analyze_base_url", "analyze_model"].forEach((widgetName) => {
|
["alias", "description", "analyze_provider", "analyze_base_url", "analyze_model", "analyze_prompt"].forEach((widgetName) => {
|
||||||
hideNodeWidget(findWidget(this, widgetName));
|
hideNodeWidget(findWidget(this, widgetName));
|
||||||
});
|
});
|
||||||
hideNodeWidget((this.widgets || []).find((widget) => widget.msrAnalyze));
|
hideNodeWidget((this.widgets || []).find((widget) => widget.msrAnalyze));
|
||||||
|
|||||||
@@ -512,6 +512,11 @@ _ANALYZE_PROMPT = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_analyze_prompt(data: dict) -> str:
|
||||||
|
prompt = (data.get("prompt") or "").strip()
|
||||||
|
return prompt or _ANALYZE_PROMPT
|
||||||
|
|
||||||
|
|
||||||
def _extract_ollama_generated_text(resp_json: dict) -> str:
|
def _extract_ollama_generated_text(resp_json: dict) -> str:
|
||||||
if not isinstance(resp_json, dict):
|
if not isinstance(resp_json, dict):
|
||||||
return ""
|
return ""
|
||||||
@@ -621,6 +626,7 @@ async def analyze_character_endpoint(request):
|
|||||||
image_debug = data.get("image_debug") or []
|
image_debug = data.get("image_debug") or []
|
||||||
char_index = int(data.get("char_index", 0))
|
char_index = int(data.get("char_index", 0))
|
||||||
provider, base_url, model_name = _resolve_provider(data)
|
provider, base_url, model_name = _resolve_provider(data)
|
||||||
|
analyze_prompt = _resolve_analyze_prompt(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."})
|
||||||
@@ -652,7 +658,7 @@ async def analyze_character_endpoint(request):
|
|||||||
payload = {
|
payload = {
|
||||||
"model": model_name,
|
"model": model_name,
|
||||||
"system": _ANALYZE_SYSTEM_PROMPT,
|
"system": _ANALYZE_SYSTEM_PROMPT,
|
||||||
"prompt": _ANALYZE_PROMPT,
|
"prompt": analyze_prompt,
|
||||||
"images": analysis_images,
|
"images": analysis_images,
|
||||||
"stream": False,
|
"stream": False,
|
||||||
"keep_alive": 0,
|
"keep_alive": 0,
|
||||||
@@ -691,7 +697,7 @@ async def analyze_character_endpoint(request):
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": _ANALYZE_PROMPT,
|
"content": analyze_prompt,
|
||||||
"images": analysis_images,
|
"images": analysis_images,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -720,7 +726,7 @@ async def analyze_character_endpoint(request):
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
# OpenAI-compatible vision chat (LM Studio / Custom).
|
# OpenAI-compatible vision chat (LM Studio / Custom).
|
||||||
content = [{"type": "text", "text": _ANALYZE_PROMPT}]
|
content = [{"type": "text", "text": analyze_prompt}]
|
||||||
for b64 in cleaned_b64_list:
|
for b64 in cleaned_b64_list:
|
||||||
content.append({"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}})
|
content.append({"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}})
|
||||||
payload = {
|
payload = {
|
||||||
|
|||||||
Reference in New Issue
Block a user