Remove settings the user should not have to touch, and make every tooltip plain-language: - knowledge_base path: removed; the Knowledge Base ships in the package, so the path is fixed rather than a prompted input. - prompt_target: removed (reserved; to be replaced in V3). - prompt_separator: removed; always ',' this version. Both keep their compiler defaults, just no longer exposed as node inputs. - analyzer_system_prompt (Configuration) and system_prompt (Scene Analyzer): removed. A user-authored system prompt is not UX-friendly; the built-in analyzer prompt is always used. - Rewrite all node tooltips in plain language reflecting the current nodes. Example workflow and node tests updated; docs/nodes.md refreshed. BREAKING CHANGE: the Configuration node's knowledge_base, prompt_target, prompt_separator, and analyzer_system_prompt inputs and the Scene Analyzer's system_prompt input are removed. Co-authored-by: kunail0804 <kunail0804@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
"""Tests for the Scene Analyzer ComfyUI node (issue #19). No live Ollama."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import nodes
|
|
import nodes.scene_analyzer_node as node_module
|
|
from compiler.common.config import Config
|
|
from compiler.common.message_codes import message
|
|
from compiler.common.result import CompilerResult
|
|
from nodes.scene_analyzer_node import SceneAnalyzerNode
|
|
|
|
|
|
def test_input_types_structure() -> None:
|
|
inputs = SceneAnalyzerNode.INPUT_TYPES()
|
|
# Analyzer settings live on the Configuration node; only the per-run text and
|
|
# the optional config connection remain.
|
|
assert set(inputs["required"]) == {"natural_language"}
|
|
assert set(inputs["optional"]) == {"config"}
|
|
|
|
|
|
def test_node_metadata() -> None:
|
|
assert SceneAnalyzerNode.RETURN_TYPES == ("SCENE", "STRING", "STRING", "STRING")
|
|
assert SceneAnalyzerNode.RETURN_NAMES == ("scene", "warnings", "errors", "raw")
|
|
assert SceneAnalyzerNode.FUNCTION == "run"
|
|
assert SceneAnalyzerNode.CATEGORY == "Scene Compiler"
|
|
|
|
|
|
def test_run_uses_model_from_config(monkeypatch) -> None:
|
|
captured = {}
|
|
|
|
def fake_analyze(description, backend, config):
|
|
captured["description"] = description
|
|
captured["model"] = config.analyzer.model
|
|
return (
|
|
CompilerResult(data="SCENE_MODEL")
|
|
.add_warning(message("SC0001", "unknown concept 'x'"))
|
|
.add_error(message("SC0011", "bad response"))
|
|
)
|
|
|
|
monkeypatch.setattr(node_module, "analyze", fake_analyze)
|
|
|
|
config = Config.from_json({"analyzer": {"model": "mistral"}})
|
|
scene, warnings, errors, *_ = SceneAnalyzerNode().run(
|
|
natural_language="A girl.",
|
|
config=config,
|
|
)
|
|
assert scene == "SCENE_MODEL"
|
|
assert captured["description"] == "A girl."
|
|
assert captured["model"] == "mistral"
|
|
assert "SC0001: unknown concept 'x'" in warnings
|
|
assert "SC0011: bad response" in errors
|
|
|
|
|
|
def test_defaults_apply_without_a_configuration_node(monkeypatch) -> None:
|
|
captured = {}
|
|
|
|
def fake_analyze(description, backend, config):
|
|
captured["model"] = config.analyzer.model
|
|
captured["timeout"] = config.analyzer.timeout
|
|
return CompilerResult(data="S")
|
|
|
|
monkeypatch.setattr(node_module, "analyze", fake_analyze)
|
|
SceneAnalyzerNode().run("A girl.")
|
|
# Falls back to the built-in model with a cold-load-friendly timeout.
|
|
assert captured["model"] == "llama3"
|
|
assert captured["timeout"] == 300
|
|
|
|
|
|
def test_no_messages_yield_empty_strings(monkeypatch) -> None:
|
|
monkeypatch.setattr(node_module, "analyze", lambda d, b, c: CompilerResult(data="S"))
|
|
scene, warnings, errors, *_ = SceneAnalyzerNode().run("x")
|
|
assert (warnings, errors) == ("", "")
|
|
|
|
|
|
def test_registered_for_comfyui() -> None:
|
|
assert nodes.NODE_CLASS_MAPPINGS["SceneCompilerAnalyzer"] is SceneAnalyzerNode
|
|
assert nodes.NODE_DISPLAY_NAME_MAPPINGS["SceneCompilerAnalyzer"] == "Scene Analyzer"
|