diff --git a/README.md b/README.md index 176c194..da13d82 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,9 @@ Natural Language Only the **Scene Analyzer** uses an LLM, and only to understand language — never to produce tags. Every generated tag is looked up deterministically in a -data-only **Knowledge Base** and stays fully traceable: +data-only **Knowledge Base** (Version 1 ships a large Knowledge Base generated +from a real Danbooru tag vocabulary, so the tags are always valid and never +invented) and stays fully traceable: ``` Natural Language → Scene JSON → Knowledge Base Entry → Resolved Tag → Prompt Output @@ -51,7 +53,7 @@ Natural Language → Scene JSON → Knowledge Base Entry → Resolved Tag → Pr ## Key principles -- **Determinism first** — same input + Knowledge Base + config → same output, always. No random seeds anywhere. +- **Determinism first** — the compiler core is deterministic: a given Scene JSON + Knowledge Base + config always produces the same output, with no random seeds. (The one non-deterministic step is the LLM understanding the language up front; everything after it is reproducible.) - **No hallucinations** — if it isn't in the description, it isn't in the output. Unknown concepts are reported, never guessed. - **Knowledge is data** — every concept→tag mapping lives in the Knowledge Base, never in code. - **Traceability** — every tag can be explained back to the sentence it came from. @@ -151,6 +153,9 @@ The complete normative specification is [`MASTER_SPEC.md`](../MASTER_SPEC.md). fallback search, localization, performance — determinism preserved. - **Version 3 — Extensible Compiler Platform**: multi-model Resolvers, a plugin system, multiple Analyzer backends, and a standalone Compiler SDK. +- **Version 4 — Consolidation**: tidy-up and a single unified node that runs the + whole pipeline, since most stage nodes carry little configuration. The granular + nodes stay available for debugging. See the [Roadmap](../../wiki/Roadmap) for details. @@ -165,3 +170,14 @@ guide first. Core rule: **never hardcode knowledge, and never break determinism. ## License See [LICENSE](LICENSE). + +--- + +## A note on AI assistance + +This project — its code, tests, and documentation — is built with heavy help from +AI coding assistants, and is developed and maintained by a solo author. AI makes +mistakes: despite testing and review, parts of this project and its docs may be +inaccurate, out of date, or simply wrong. Please treat it as a good-faith best +effort rather than authoritative truth — **if the docs and the code disagree, the +code wins** — and open an issue when you spot something off. diff --git a/nodes/configuration_node.py b/nodes/configuration_node.py index 32d8efb..6fc0bb0 100644 --- a/nodes/configuration_node.py +++ b/nodes/configuration_node.py @@ -34,12 +34,13 @@ class ConfigurationNode: {"default": 0.0, "min": 0.0, "max": 2.0, "step": 0.1}, ), "analyzer_max_retries": ("INT", {"default": 3, "min": 0, "max": 10}), - "analyzer_timeout": ("INT", {"default": 60, "min": 1, "max": 3600}), + "analyzer_timeout": ("INT", {"default": 300, "min": 1, "max": 3600}), "knowledge_base": ("STRING", {"default": "knowledge_base/"}), "resolver_strict_mode": ("BOOLEAN", {"default": True}), "resolver_allow_aliases": ("BOOLEAN", {"default": True}), "resolver_expansion_enabled": ("BOOLEAN", {"default": True}), "resolver_max_expansion_depth": ("INT", {"default": 8, "min": 1, "max": 32}), + "resolver_include_nsfw": ("BOOLEAN", {"default": False}), "validator_allow_unknown_fields": ("BOOLEAN", {"default": False}), "prompt_target": ("STRING", {"default": "easy_illustrious"}), "prompt_separator": ("STRING", {"default": ","}), @@ -64,6 +65,7 @@ class ConfigurationNode: resolver_allow_aliases: bool, resolver_expansion_enabled: bool, resolver_max_expansion_depth: int, + resolver_include_nsfw: bool, validator_allow_unknown_fields: bool, prompt_target: str, prompt_separator: str, @@ -90,6 +92,7 @@ class ConfigurationNode: "allow_aliases": resolver_allow_aliases, "expansion_enabled": resolver_expansion_enabled, "max_expansion_depth": resolver_max_expansion_depth, + "include_nsfw": resolver_include_nsfw, }, "validator": {"allow_unknown_fields": validator_allow_unknown_fields}, "prompt_builder": { diff --git a/tests/test_configuration_node.py b/tests/test_configuration_node.py index 812b0f0..6c09a2d 100644 --- a/tests/test_configuration_node.py +++ b/tests/test_configuration_node.py @@ -18,6 +18,7 @@ def default_inputs() -> dict: "resolver_allow_aliases": True, "resolver_expansion_enabled": True, "resolver_max_expansion_depth": 8, + "resolver_include_nsfw": False, "validator_allow_unknown_fields": False, "prompt_target": "easy_illustrious", "prompt_separator": ",", @@ -48,6 +49,7 @@ def test_inputs_flow_into_config() -> None: inputs = default_inputs() inputs["analyzer_model"] = "mistral" inputs["resolver_max_expansion_depth"] = 4 + inputs["resolver_include_nsfw"] = True inputs["validator_allow_unknown_fields"] = True inputs["prompt_separator"] = " | " inputs["debug_enabled"] = True @@ -55,6 +57,7 @@ def test_inputs_flow_into_config() -> None: config, _ = ConfigurationNode().run(**inputs) assert config.analyzer.model == "mistral" assert config.resolver.max_expansion_depth == 4 + assert config.resolver.include_nsfw is True assert config.validator.allow_unknown_fields is True assert config.prompt_builder.separator == " | " assert config.debug.enabled is True