diffusers-workflow 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- diffusers_workflow-0.4.0.dist-info/METADATA +318 -0
- diffusers_workflow-0.4.0.dist-info/RECORD +260 -0
- diffusers_workflow-0.4.0.dist-info/WHEEL +5 -0
- diffusers_workflow-0.4.0.dist-info/entry_points.txt +7 -0
- diffusers_workflow-0.4.0.dist-info/licenses/LICENSE +201 -0
- diffusers_workflow-0.4.0.dist-info/top_level.txt +2 -0
- dw/__init__.py +440 -0
- dw/adapter_compatibility.py +226 -0
- dw/arguments.py +1231 -0
- dw/assessment_rules.py +159 -0
- dw/assets.py +130 -0
- dw/cache_blocks.json +16 -0
- dw/cache_blocks.py +146 -0
- dw/community_pipelines/pipeline_flux_rf_inversion.py +1184 -0
- dw/content_types.py +150 -0
- dw/dissolve_frame_errors.py +121 -0
- dw/docs/ACCELERATION.md +352 -0
- dw/docs/AGENT_LOOP.md +95 -0
- dw/docs/DEPENDENCIES.md +91 -0
- dw/docs/IP_ADAPTER.md +109 -0
- dw/docs/LORAS.md +131 -0
- dw/docs/MCP.md +517 -0
- dw/docs/PROMPT_WEIGHTING.md +78 -0
- dw/docs/QUANTIZATION.md +230 -0
- dw/docs/RECIPES_24GB.md +201 -0
- dw/docs/RELEASING.md +195 -0
- dw/docs/REMOTE.md +140 -0
- dw/docs/REPL_COMMANDS.md +121 -0
- dw/docs/REPL_WORKER_GUIDE.md +51 -0
- dw/docs/SECURITY.md +272 -0
- dw/docs/SECURITY_QUICKREF.md +112 -0
- dw/docs/SERVER.md +679 -0
- dw/docs/TASKS.md +1741 -0
- dw/docs/TESTING.md +71 -0
- dw/docs/WORKFLOW_GUIDE.md +2038 -0
- dw/docs/WORKSPACES.md +316 -0
- dw/download_watch.py +335 -0
- dw/elision.py +306 -0
- dw/events.py +275 -0
- dw/for_each.py +409 -0
- dw/host_memory.py +258 -0
- dw/host_memory_projection.py +230 -0
- dw/hub_cache.py +432 -0
- dw/introspection.py +1228 -0
- dw/kernel_availability.py +208 -0
- dw/locations.py +599 -0
- dw/log_setup.py +45 -0
- dw/loudness.py +82 -0
- dw/media_audio.py +217 -0
- dw/media_frames.py +367 -0
- dw/media_info.py +297 -0
- dw/pipeline_processors/chain.py +821 -0
- dw/pipeline_processors/config_objects.py +237 -0
- dw/pipeline_processors/pipeline.py +2297 -0
- dw/pipeline_processors/remote.py +46 -0
- dw/plan.py +920 -0
- dw/previous_results.py +411 -0
- dw/probe_paths.py +59 -0
- dw/prompt_schema.json +48 -0
- dw/prompt_weighting.py +378 -0
- dw/prompts.py +159 -0
- dw/realize.py +250 -0
- dw/reference_limits.py +215 -0
- dw/reference_names.py +125 -0
- dw/repl.py +338 -0
- dw/repl_commands.py +836 -0
- dw/repl_worker.py +159 -0
- dw/result.py +1720 -0
- dw/result_fps.py +82 -0
- dw/run.py +162 -0
- dw/runs.py +768 -0
- dw/scalar_result_validation.py +97 -0
- dw/schema.py +283 -0
- dw/security.py +1038 -0
- dw/select_validation.py +115 -0
- dw/serve.py +277 -0
- dw/server/__init__.py +2 -0
- dw/server/app.py +4586 -0
- dw/server/assess.py +132 -0
- dw/server/catalog_shape.py +487 -0
- dw/server/enhancers.py +129 -0
- dw/server/exports.py +480 -0
- dw/server/guides.py +257 -0
- dw/server/jobs.py +1561 -0
- dw/server/mcp_mount.py +95 -0
- dw/server/netinfo.py +124 -0
- dw/server/observed_cost.py +379 -0
- dw/server/sysinfo.py +71 -0
- dw/server/ui/assets/abap-08VXUWAP.js +1 -0
- dw/server/ui/assets/apex-BWPQTe0t.js +1 -0
- dw/server/ui/assets/azcli-Bc_sGQ0U.js +1 -0
- dw/server/ui/assets/bat-i0X4ZdIN.js +1 -0
- dw/server/ui/assets/bicep-B5-_aFwp.js +2 -0
- dw/server/ui/assets/cameligo-DMUM7wLl.js +1 -0
- dw/server/ui/assets/clojure-Cm7r79vr.js +1 -0
- dw/server/ui/assets/codicon-Brq4_Ui5.ttf +0 -0
- dw/server/ui/assets/coffee-Ba7i2nA0.js +1 -0
- dw/server/ui/assets/cpp-C7h46wYY.js +1 -0
- dw/server/ui/assets/csharp-BKxtCVv1.js +1 -0
- dw/server/ui/assets/csp-bTuwJoIa.js +1 -0
- dw/server/ui/assets/css-DIMkf-bt.js +3 -0
- dw/server/ui/assets/css.worker-B3ciXF_0.js +93 -0
- dw/server/ui/assets/cssMode-CPznxfY8.js +1 -0
- dw/server/ui/assets/cypher-CVaqCwHa.js +1 -0
- dw/server/ui/assets/dart-onAF5SnQ.js +1 -0
- dw/server/ui/assets/dockerfile-DZFCIeNp.js +1 -0
- dw/server/ui/assets/ecl-D05T4iGw.js +1 -0
- dw/server/ui/assets/editor-jjEx9u7D.css +1 -0
- dw/server/ui/assets/editor.api-CpWcotrd.js +847 -0
- dw/server/ui/assets/editor.worker-q-txB4vs.js +30 -0
- dw/server/ui/assets/elixir-6RTg0lbw.js +1 -0
- dw/server/ui/assets/flow9-C5_-GSwl.js +1 -0
- dw/server/ui/assets/freemarker2-CXtRM8N4.js +3 -0
- dw/server/ui/assets/fsharp-C8Ef5oNN.js +1 -0
- dw/server/ui/assets/go-C-y9NEjX.js +1 -0
- dw/server/ui/assets/graphql-fmXr3nnJ.js +1 -0
- dw/server/ui/assets/handlebars-N7x-6NMY.js +1 -0
- dw/server/ui/assets/hcl-CpzslTdj.js +1 -0
- dw/server/ui/assets/html-PhsdjHSr.js +1 -0
- dw/server/ui/assets/html.worker-C93Ht9o9.js +506 -0
- dw/server/ui/assets/htmlMode-Dgj0SEok.js +1 -0
- dw/server/ui/assets/index-3Vw6WAPW.css +1 -0
- dw/server/ui/assets/index-DgrYhQd9.js +43 -0
- dw/server/ui/assets/ini-sBoK_t0W.js +1 -0
- dw/server/ui/assets/java-BEtHBSE6.js +1 -0
- dw/server/ui/assets/javascript-BJqN9Qhv.js +1 -0
- dw/server/ui/assets/json.worker-B2V3pomh.js +62 -0
- dw/server/ui/assets/jsonMode-DbM4SWSv.js +7 -0
- dw/server/ui/assets/julia-Bri6UV-V.js +1 -0
- dw/server/ui/assets/kotlin-BOotOW0E.js +1 -0
- dw/server/ui/assets/less-B9JPFI3C.js +2 -0
- dw/server/ui/assets/lexon-CfSJPG6W.js +1 -0
- dw/server/ui/assets/liquid-BWr8lEc4.js +1 -0
- dw/server/ui/assets/lspLanguageFeatures-C1iGuDyZ.js +4 -0
- dw/server/ui/assets/lua-CsQS60Ue.js +1 -0
- dw/server/ui/assets/m3-D-oSqn_W.js +1 -0
- dw/server/ui/assets/markdown-Cimd5fb3.js +1 -0
- dw/server/ui/assets/mdx-DAdMi_0p.js +1 -0
- dw/server/ui/assets/mips-CIPQ_RoX.js +1 -0
- dw/server/ui/assets/monaco--ixms01u.css +1 -0
- dw/server/ui/assets/monaco-BGCeEqaw.js +56 -0
- dw/server/ui/assets/msdax-DauUninz.js +1 -0
- dw/server/ui/assets/mysql-SOo6toE5.js +1 -0
- dw/server/ui/assets/objective-c-FvmIjYaQ.js +1 -0
- dw/server/ui/assets/pascal-DrH0SRf2.js +1 -0
- dw/server/ui/assets/pascaligo-D-ptJ9y-.js +1 -0
- dw/server/ui/assets/perl-oz_6vUea.js +1 -0
- dw/server/ui/assets/pgsql-DTj74zXo.js +1 -0
- dw/server/ui/assets/php-nr791fC2.js +1 -0
- dw/server/ui/assets/pla-CopQ2nXW.js +1 -0
- dw/server/ui/assets/postiats-43DmfD33.js +1 -0
- dw/server/ui/assets/powerquery-D3hlyOfw.js +1 -0
- dw/server/ui/assets/powershell-DmHpPYUd.js +1 -0
- dw/server/ui/assets/protobuf-C531GsRP.js +2 -0
- dw/server/ui/assets/pug-Z5eAx3Zn.js +1 -0
- dw/server/ui/assets/python-Bcn70HdC.js +1 -0
- dw/server/ui/assets/qsharp-DkqhCAOL.js +1 -0
- dw/server/ui/assets/r-BwWrilGY.js +1 -0
- dw/server/ui/assets/razor-D1HmNnby.js +1 -0
- dw/server/ui/assets/redis-ClamHrr6.js +1 -0
- dw/server/ui/assets/redshift-DT7zqm-g.js +1 -0
- dw/server/ui/assets/restructuredtext-BYgofb2h.js +1 -0
- dw/server/ui/assets/ruby-DezsRK8O.js +1 -0
- dw/server/ui/assets/rust-DdL9SqIa.js +1 -0
- dw/server/ui/assets/sb-CcwsVR0C.js +1 -0
- dw/server/ui/assets/scala-DHpiXF5c.js +1 -0
- dw/server/ui/assets/scheme-BeGwcela.js +1 -0
- dw/server/ui/assets/scss-gp-XZpBa.js +3 -0
- dw/server/ui/assets/shell-CC2rA5mh.js +1 -0
- dw/server/ui/assets/solidity-BEEn4gHE.js +1 -0
- dw/server/ui/assets/sophia-CRfGWb83.js +1 -0
- dw/server/ui/assets/sparql-D_Lu-MrJ.js +1 -0
- dw/server/ui/assets/sql-NEE52Syq.js +1 -0
- dw/server/ui/assets/st-DbInun42.js +1 -0
- dw/server/ui/assets/swift-Bxkupp3x.js +1 -0
- dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +1 -0
- dw/server/ui/assets/tcl-DISqw1ZD.js +1 -0
- dw/server/ui/assets/ts.worker-D7T1-Ig5.js +67738 -0
- dw/server/ui/assets/tsMode-D6u0XmOW.js +11 -0
- dw/server/ui/assets/twig-De2hgUGE.js +1 -0
- dw/server/ui/assets/typescript-BU6v-LMV.js +1 -0
- dw/server/ui/assets/typespec-B8J7ngcE.js +1 -0
- dw/server/ui/assets/vb-DV3o63ZY.js +1 -0
- dw/server/ui/assets/wgsl-DpFanUEy.js +298 -0
- dw/server/ui/assets/workers-Cn7cTUKr.js +1 -0
- dw/server/ui/assets/xml--0LP2Lwk.js +1 -0
- dw/server/ui/assets/yaml-mpBg9jnt.js +1 -0
- dw/server/ui/index.html +17 -0
- dw/server/updater.py +192 -0
- dw/settings.py +98 -0
- dw/shot_span_preflight.py +116 -0
- dw/shots.py +359 -0
- dw/slice_preflight.py +148 -0
- dw/step.py +187 -0
- dw/step_cache.py +442 -0
- dw/subfolders.py +107 -0
- dw/task_domains.py +307 -0
- dw/tasks/assess.py +826 -0
- dw/tasks/audio_transcription.py +88 -0
- dw/tasks/audio_utils.py +1862 -0
- dw/tasks/background_remover.py +43 -0
- dw/tasks/borders.py +113 -0
- dw/tasks/compose_text.py +74 -0
- dw/tasks/concat_videos.py +300 -0
- dw/tasks/depth_estimator.py +54 -0
- dw/tasks/diffusion_upscale.py +109 -0
- dw/tasks/dissolve_videos.py +342 -0
- dw/tasks/format_messages.py +24 -0
- dw/tasks/gather.py +173 -0
- dw/tasks/grade.py +97 -0
- dw/tasks/image_to_text.py +43 -0
- dw/tasks/image_utils.py +764 -0
- dw/tasks/interpolate_frames.py +252 -0
- dw/tasks/judge.py +68 -0
- dw/tasks/model_cache.py +55 -0
- dw/tasks/pair_audio.py +268 -0
- dw/tasks/qr_code.py +19 -0
- dw/tasks/restore_faces.py +175 -0
- dw/tasks/rife_model.py +192 -0
- dw/tasks/segment.py +121 -0
- dw/tasks/select.py +111 -0
- dw/tasks/speech_generation.py +228 -0
- dw/tasks/stabilize.py +129 -0
- dw/tasks/task.py +920 -0
- dw/tasks/tensor_image.py +57 -0
- dw/tasks/text_generation.py +169 -0
- dw/tasks/text_sections.py +80 -0
- dw/tasks/upscale.py +203 -0
- dw/tasks/video_utils.py +624 -0
- dw/tasks/zoe_depth.py +71 -0
- dw/teacache.py +381 -0
- dw/teacache_models.json +99 -0
- dw/test.py +29 -0
- dw/type_helpers.py +231 -0
- dw/validate.py +68 -0
- dw/variable_constraints.py +444 -0
- dw/variables.py +443 -0
- dw/video_extensions.py +141 -0
- dw/vram_estimate.py +116 -0
- dw/worker.py +764 -0
- dw/workflow.py +2007 -0
- dw/workflow_schema.json +1346 -0
- dw/workflow_sources.py +383 -0
- dw/workflows/h3_context_ir.json +57 -0
- dw/workflows/test.json +31 -0
- dw/workspace.py +730 -0
- dw_mcp/__init__.py +6 -0
- dw_mcp/__main__.py +133 -0
- dw_mcp/assets.py +336 -0
- dw_mcp/authoring.py +114 -0
- dw_mcp/catalog.py +360 -0
- dw_mcp/client.py +486 -0
- dw_mcp/diagnose.py +371 -0
- dw_mcp/exports.py +84 -0
- dw_mcp/guides.py +35 -0
- dw_mcp/media.py +638 -0
- dw_mcp/models.py +97 -0
- dw_mcp/prompts.py +104 -0
- dw_mcp/server.py +1343 -0
- dw_mcp/workspaces.py +212 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""The LoRA a step loads has to be trained for the path that step runs.
|
|
2
|
+
|
|
3
|
+
MiniMax-H3 ships one repository holding two checkpoint partitions -
|
|
4
|
+
`transformer/` for the `t2va` and `fl2va` workflows, `transformer_ref/` for
|
|
5
|
+
`ref2va` - and a separate turbo adapter trained against each. Handing the
|
|
6
|
+
FL2VA adapter to a `ref2va` step is the one H3 misconfiguration that never
|
|
7
|
+
shows up as a failure: a `ref2va` step holds `transformer_ref` alone, so
|
|
8
|
+
diffusers loads whatever it is given straight onto it, the run succeeds, and
|
|
9
|
+
the only symptom is identity retention that quietly is not as good as it
|
|
10
|
+
should be. Four templates carried exactly that mistake and nothing ever
|
|
11
|
+
complained (#149, #155).
|
|
12
|
+
|
|
13
|
+
Everything a pipeline itself would refuse is refused by the pipeline. This
|
|
14
|
+
is the other kind: a request the pipeline accepts and answers wrongly, which
|
|
15
|
+
costs a whole render to discover and cannot be seen in the output. So it is
|
|
16
|
+
checked where it is free - `validation_errors`, so `POST /api/validate` and
|
|
17
|
+
the pre-queue check both refuse it, at the JSON path the value sits at.
|
|
18
|
+
|
|
19
|
+
What is *not* written here: the adapter file names. `lora_weight_name` is a
|
|
20
|
+
free string and a future reference-trained checkpoint cannot be predicted, so
|
|
21
|
+
an unrecognised name is a warning naming the rule rather than a refusal - the
|
|
22
|
+
default inverts from "anything passes" to "the one documented mistake is
|
|
23
|
+
caught", and someone testing `my-new-ref-lora.safetensors` still gets
|
|
24
|
+
through. What *is* written here is a vendor naming convention (`ref2v` /
|
|
25
|
+
`fl2v` in the file name) that no diffusers symbol declares; the workflow
|
|
26
|
+
names and the partition each one denoises against are diffusers' own, and
|
|
27
|
+
`tests/test_h3_adapters.py` pins them to it.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import logging
|
|
31
|
+
|
|
32
|
+
from .for_each import MEMBER_SEPARATOR, render_path
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger("dw")
|
|
35
|
+
|
|
36
|
+
# The `workflow=` values MiniMaxH3Blocks._workflow_map declares, split by the
|
|
37
|
+
# transformer partition each one denoises against - a `ref2va` step loads
|
|
38
|
+
# `transformer_ref` and nothing else, every other H3 workflow loads
|
|
39
|
+
# `transformer`. A workflow name not listed here is not checked
|
|
40
|
+
REFERENCE_WORKFLOWS = frozenset({"ref2va"})
|
|
41
|
+
KEYFRAME_WORKFLOWS = frozenset({"t2va", "fl2va"})
|
|
42
|
+
H3_WORKFLOWS = REFERENCE_WORKFLOWS | KEYFRAME_WORKFLOWS
|
|
43
|
+
|
|
44
|
+
# The token MiniMax puts in an adapter's file name to say which partition it
|
|
45
|
+
# was trained against. `ref2v` first: it is the longer match and a name
|
|
46
|
+
# carrying both is ambiguous rather than a keyframe adapter
|
|
47
|
+
REFERENCE_TOKEN = "ref2v"
|
|
48
|
+
KEYFRAME_TOKEN = "fl2v"
|
|
49
|
+
|
|
50
|
+
LORAS_KEY = "loras"
|
|
51
|
+
WEIGHT_NAME_KEY = "weight_name"
|
|
52
|
+
WORKFLOW_KEY = "workflow"
|
|
53
|
+
FROM_PRETRAINED_KEY = "from_pretrained_arguments"
|
|
54
|
+
VARIABLE_PREFIX = "variable:"
|
|
55
|
+
# Values another pass resolves; one still spelled out here is not this
|
|
56
|
+
# pass's complaint
|
|
57
|
+
_UNRESOLVED_PREFIXES = ("variable:", "item:", "previous_result:", "gather:")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _trained_for(weight_name):
|
|
61
|
+
"""Which partition an adapter's file name says it was trained against -
|
|
62
|
+
'reference', 'keyframe', or None when the name says neither."""
|
|
63
|
+
lowered = weight_name.lower()
|
|
64
|
+
if REFERENCE_TOKEN in lowered:
|
|
65
|
+
return "reference"
|
|
66
|
+
if KEYFRAME_TOKEN in lowered:
|
|
67
|
+
return "keyframe"
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _problem(workflow, weight_name):
|
|
72
|
+
"""(severity, message) for one adapter on one step, or None when the
|
|
73
|
+
pairing is right."""
|
|
74
|
+
trained = _trained_for(weight_name)
|
|
75
|
+
wants = "reference" if workflow in REFERENCE_WORKFLOWS else "keyframe"
|
|
76
|
+
if trained == wants:
|
|
77
|
+
return None
|
|
78
|
+
if trained is None:
|
|
79
|
+
return (
|
|
80
|
+
"warning",
|
|
81
|
+
f"'{weight_name}' names neither '{REFERENCE_TOKEN}' nor "
|
|
82
|
+
f"'{KEYFRAME_TOKEN}', so it cannot be checked against this "
|
|
83
|
+
f"step's '{workflow}' workflow. A '{workflow}' step denoises "
|
|
84
|
+
f"against the "
|
|
85
|
+
f"'{'transformer_ref' if wants == 'reference' else 'transformer'}' "
|
|
86
|
+
f"partition, and an adapter trained against the other one loads "
|
|
87
|
+
f"onto it without error and only degrades the result",
|
|
88
|
+
)
|
|
89
|
+
return (
|
|
90
|
+
"error",
|
|
91
|
+
f"'{weight_name}' is trained against the "
|
|
92
|
+
f"'{'transformer_ref' if trained == 'reference' else 'transformer'}' "
|
|
93
|
+
f"partition and this step runs the '{workflow}' workflow, which "
|
|
94
|
+
f"denoises against "
|
|
95
|
+
f"'{'transformer_ref' if wants == 'reference' else 'transformer'}'. "
|
|
96
|
+
f"MiniMax-H3 loads it anyway and the run succeeds - the only symptom "
|
|
97
|
+
f"is a worse result - so it is refused here. Use an adapter trained "
|
|
98
|
+
f"for this workflow (its name carries "
|
|
99
|
+
f"'{REFERENCE_TOKEN if wants == 'reference' else KEYFRAME_TOKEN}')",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _lora_problems(steps, source_indices, written=None, supplied=()):
|
|
104
|
+
"""Every adapter/workflow mismatch in an expanded step list, as
|
|
105
|
+
(severity, path, message).
|
|
106
|
+
|
|
107
|
+
`written` is the definition as the author wrote it and `supplied` the
|
|
108
|
+
argument names the caller passed: when the value arrived through a
|
|
109
|
+
variable the caller set, the path reported is `arguments.<name>`, where
|
|
110
|
+
they wrote it, rather than the step it landed in.
|
|
111
|
+
"""
|
|
112
|
+
written_steps = (written or {}).get("steps")
|
|
113
|
+
found = []
|
|
114
|
+
for index, step in enumerate(steps):
|
|
115
|
+
if not isinstance(step, dict):
|
|
116
|
+
continue
|
|
117
|
+
pipeline = step.get("pipeline")
|
|
118
|
+
if not isinstance(pipeline, dict):
|
|
119
|
+
continue
|
|
120
|
+
source = (
|
|
121
|
+
source_indices[index]
|
|
122
|
+
if source_indices is not None and index < len(source_indices)
|
|
123
|
+
else index
|
|
124
|
+
)
|
|
125
|
+
from_pretrained = pipeline.get(FROM_PRETRAINED_KEY)
|
|
126
|
+
workflow = (
|
|
127
|
+
from_pretrained.get(WORKFLOW_KEY)
|
|
128
|
+
if isinstance(from_pretrained, dict)
|
|
129
|
+
else None
|
|
130
|
+
)
|
|
131
|
+
if workflow not in H3_WORKFLOWS:
|
|
132
|
+
continue
|
|
133
|
+
loras = pipeline.get(LORAS_KEY)
|
|
134
|
+
if not isinstance(loras, list):
|
|
135
|
+
continue
|
|
136
|
+
name = step.get("name")
|
|
137
|
+
where = (
|
|
138
|
+
f" in member '{name}'"
|
|
139
|
+
if isinstance(name, str) and MEMBER_SEPARATOR in name
|
|
140
|
+
else ""
|
|
141
|
+
)
|
|
142
|
+
for position, lora in enumerate(loras):
|
|
143
|
+
if not isinstance(lora, dict):
|
|
144
|
+
continue
|
|
145
|
+
weight_name = lora.get(WEIGHT_NAME_KEY)
|
|
146
|
+
if not isinstance(weight_name, str) or weight_name.startswith(
|
|
147
|
+
_UNRESOLVED_PREFIXES
|
|
148
|
+
):
|
|
149
|
+
continue
|
|
150
|
+
problem = _problem(workflow, weight_name)
|
|
151
|
+
if problem is None:
|
|
152
|
+
continue
|
|
153
|
+
severity, message = problem
|
|
154
|
+
found.append(
|
|
155
|
+
(
|
|
156
|
+
severity,
|
|
157
|
+
_path_for(written_steps, source, position, supplied)
|
|
158
|
+
or render_path(
|
|
159
|
+
(
|
|
160
|
+
"steps",
|
|
161
|
+
source,
|
|
162
|
+
"pipeline",
|
|
163
|
+
LORAS_KEY,
|
|
164
|
+
position,
|
|
165
|
+
WEIGHT_NAME_KEY,
|
|
166
|
+
)
|
|
167
|
+
),
|
|
168
|
+
message + where,
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
return found
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _path_for(written_steps, source, position, supplied):
|
|
175
|
+
"""`arguments.<name>` when the adapter came from a variable the caller
|
|
176
|
+
set, else None - the value is reported where it was written."""
|
|
177
|
+
if not isinstance(written_steps, list) or source >= len(written_steps):
|
|
178
|
+
return None
|
|
179
|
+
step = written_steps[source]
|
|
180
|
+
pipeline = step.get("pipeline") if isinstance(step, dict) else None
|
|
181
|
+
loras = pipeline.get(LORAS_KEY) if isinstance(pipeline, dict) else None
|
|
182
|
+
if not isinstance(loras, list) or position >= len(loras):
|
|
183
|
+
return None
|
|
184
|
+
entry = loras[position]
|
|
185
|
+
reference = entry.get(WEIGHT_NAME_KEY) if isinstance(entry, dict) else None
|
|
186
|
+
if not isinstance(reference, str) or not reference.startswith(VARIABLE_PREFIX):
|
|
187
|
+
return None
|
|
188
|
+
variable = reference.removeprefix(VARIABLE_PREFIX)
|
|
189
|
+
return f"arguments.{variable}" if variable in (supplied or ()) else None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def adapter_errors(workflow_definition, source_indices=None, written=None, supplied=()):
|
|
193
|
+
"""Every adapter loaded onto the wrong checkpoint partition, as
|
|
194
|
+
[{path, message}]. The definition is the expanded, substituted one, so a
|
|
195
|
+
`for_each` member's own adapter is checked as it will run."""
|
|
196
|
+
return [
|
|
197
|
+
{"path": path, "message": message}
|
|
198
|
+
for severity, path, message in _lora_problems(
|
|
199
|
+
workflow_definition.get("steps") or [], source_indices, written, supplied
|
|
200
|
+
)
|
|
201
|
+
if severity == "error"
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def adapter_warnings(
|
|
206
|
+
workflow_definition, source_indices=None, written=None, supplied=()
|
|
207
|
+
):
|
|
208
|
+
"""Every adapter whose name says nothing about what it was trained for,
|
|
209
|
+
as messages - valid, and said out loud because nothing at run time will."""
|
|
210
|
+
return [
|
|
211
|
+
f"{path}: {message}"
|
|
212
|
+
for severity, path, message in _lora_problems(
|
|
213
|
+
workflow_definition.get("steps") or [], source_indices, written, supplied
|
|
214
|
+
)
|
|
215
|
+
if severity == "warning"
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def warn_adapters(workflow_definition):
|
|
220
|
+
"""Say the unrecognised-adapter warning where whoever asked for the run
|
|
221
|
+
can read it - a run started from the CLI or a rerun never passed through
|
|
222
|
+
the validate route."""
|
|
223
|
+
from .events import emit_warning
|
|
224
|
+
|
|
225
|
+
for message in adapter_warnings(workflow_definition):
|
|
226
|
+
emit_warning(message, kind="adapter_unrecognized")
|