fffiloni commited on
Commit
4713767
·
verified ·
1 Parent(s): 6a176b5

Upload 15 files

Browse files
Files changed (3) hide show
  1. src/model_scan.py +211 -2
  2. src/version.py +2 -2
  3. src/worker_payload.py +3 -3
src/model_scan.py CHANGED
@@ -69,6 +69,197 @@ IMAGE_OUTPUT_HINT_RE = re.compile(
69
  r"(\.images\s*\[|generated image|text-to-image|image = pipe\()",
70
  re.IGNORECASE,
71
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
 
74
  def infer_expected_output_type(
@@ -429,13 +620,19 @@ def analyze_model_metadata(
429
  has_diffusers_example = bool(card_signals["has_diffusers_example"])
430
  pipeline_class = str(card_signals["pipeline_class"] or "")
431
  runtime_hints = list(card_signals["runtime_hints"] or [])
432
- expected_output_type = infer_expected_output_type(
433
  pipeline_tag=pipeline_tag,
434
  library_name=library_name,
435
  tags=tags,
436
  pipeline_class=pipeline_class,
437
  readme=readme,
438
  )
 
 
 
 
 
 
439
 
440
  score = 50
441
  good: list[str] = []
@@ -457,8 +654,10 @@ def analyze_model_metadata(
457
  else:
458
  score -= 12
459
  risk.append("No pipeline tag detected; task type may be ambiguous for an autonomous builder.")
 
 
460
  if expected_output_type:
461
- good.append(f"Expected output type inferred: {expected_output_type}.")
462
 
463
  if library_name:
464
  score += 10
@@ -599,6 +798,11 @@ def analyze_model_metadata(
599
  "risk_signals": risk[:10],
600
  "recommendations": recommendations[:6],
601
  "expected_output_type": expected_output_type or "",
 
 
 
 
 
602
  "build_risk": build_risk,
603
  "kernel_strategy": kernel_strategy,
604
  "metadata": {
@@ -616,6 +820,11 @@ def analyze_model_metadata(
616
  "pipeline_class": pipeline_class,
617
  "runtime_hints": runtime_hints,
618
  "expected_output_type": expected_output_type or "",
 
 
 
 
 
619
  "diffusers_standard": bool(is_diffusers and has_model_index and has_safetensors),
620
  "build_risk_level": build_risk["level"],
621
  "recommended_session_minutes": build_risk["recommended_session_minutes"],
 
69
  r"(\.images\s*\[|generated image|text-to-image|image = pipe\()",
70
  re.IGNORECASE,
71
  )
72
+ INPUT_MODALITY_ORDER = ("text", "image", "audio", "video", "file")
73
+ INPUT_MODALITY_HINTS = {
74
+ "text": (
75
+ "text prompt",
76
+ "input prompt",
77
+ "prompt:",
78
+ "prompt=",
79
+ "gr.textbox",
80
+ "textbox",
81
+ ),
82
+ "image": (
83
+ "image_path",
84
+ "input image",
85
+ "image input",
86
+ "source image",
87
+ "reference image",
88
+ "avatar image",
89
+ "person image",
90
+ "gr.image",
91
+ "pil.image",
92
+ "upload image",
93
+ ),
94
+ "audio": (
95
+ "audio_path",
96
+ "input audio",
97
+ "audio input",
98
+ "source audio",
99
+ "speech audio",
100
+ "voice audio",
101
+ "single audio",
102
+ "multi audio",
103
+ "gr.audio",
104
+ ".wav",
105
+ ),
106
+ "video": (
107
+ "video_path",
108
+ "input video",
109
+ "video input",
110
+ "source video",
111
+ "reference video",
112
+ "gr.video",
113
+ ".mp4",
114
+ ),
115
+ "file": (
116
+ "file_path",
117
+ "input file",
118
+ "file input",
119
+ "upload file",
120
+ "gr.file",
121
+ ),
122
+ }
123
+
124
+
125
+ def _ordered_modalities(values: set[str]) -> list[str]:
126
+ return [name for name in INPUT_MODALITY_ORDER if name in values]
127
+
128
+
129
+ def infer_expected_inputs(
130
+ *,
131
+ pipeline_tag: str | None = None,
132
+ tags: list[str] | None = None,
133
+ readme: str | None = None,
134
+ ) -> list[str]:
135
+ modalities: set[str] = set()
136
+ task = (pipeline_tag or "").strip().lower()
137
+ tag_set = {str(t).lower() for t in (tags or [])}
138
+ task_like = {task, *tag_set}
139
+
140
+ for item in task_like:
141
+ if item.startswith("text-to-") or item in {
142
+ "text-generation",
143
+ "text2text-generation",
144
+ "summarization",
145
+ "translation",
146
+ "question-answering",
147
+ "fill-mask",
148
+ "sentence-similarity",
149
+ "token-classification",
150
+ "zero-shot-classification",
151
+ }:
152
+ modalities.add("text")
153
+ if item.startswith("image-to-") or item in {"image-classification", "object-detection", "image-segmentation"}:
154
+ modalities.add("image")
155
+ if item.startswith("audio-to-") or item in {"automatic-speech-recognition", "audio-classification"}:
156
+ modalities.add("audio")
157
+ if item.startswith("video-to-"):
158
+ modalities.add("video")
159
+
160
+ text = (readme or "").lower()
161
+ for modality, hints in INPUT_MODALITY_HINTS.items():
162
+ if any(hint in text for hint in hints):
163
+ modalities.add(modality)
164
+ if re.search(r"\bprompt\b", text) and any(word in text for word in ("pipe(", "generate", "demo", "gradio")):
165
+ modalities.add("text")
166
+
167
+ return _ordered_modalities(modalities)
168
+
169
+
170
+ def infer_output_guess(
171
+ *,
172
+ pipeline_tag: str | None = None,
173
+ library_name: str | None = None,
174
+ tags: list[str] | None = None,
175
+ pipeline_class: str | None = None,
176
+ readme: str | None = None,
177
+ ) -> dict[str, Any]:
178
+ expected = infer_expected_output_type(
179
+ pipeline_tag=pipeline_tag,
180
+ library_name=library_name,
181
+ tags=tags,
182
+ pipeline_class=pipeline_class,
183
+ readme=readme,
184
+ )
185
+ task = (pipeline_tag or "").strip().lower()
186
+ tag_set = {str(t).lower() for t in (tags or [])}
187
+ cls = (pipeline_class or "").strip().lower()
188
+ text = (readme or "").lower()
189
+ library = (library_name or "").strip().lower()
190
+ combined = " ".join([library, cls, " ".join(sorted(tag_set)), text])
191
+ evidence: list[str] = []
192
+ confidence = "low"
193
+ source = "none"
194
+
195
+ if task in TASK_OUTPUT_TYPE_MAP:
196
+ confidence = "high"
197
+ source = "pipeline_tag"
198
+ evidence.append(f"pipeline_tag={task} maps to {TASK_OUTPUT_TYPE_MAP[task]}.")
199
+ elif {"text-to-video", "image-to-video"} & tag_set:
200
+ confidence = "high"
201
+ source = "tags"
202
+ evidence.append("Hub tags include text-to-video or image-to-video.")
203
+ elif {"text-to-image", "image-to-image", "diffusers"} & tag_set and expected == "image":
204
+ confidence = "medium"
205
+ source = "tags"
206
+ evidence.append("Hub tags indicate a Diffusers image workflow.")
207
+ elif {"text-to-audio", "text-to-speech", "audio"} & tag_set and expected == "audio":
208
+ confidence = "medium"
209
+ source = "tags"
210
+ evidence.append("Hub tags indicate an audio generation workflow.")
211
+ elif any(hint in cls for hint in IMAGE_PIPELINE_HINTS) and expected == "image":
212
+ confidence = "medium"
213
+ source = "pipeline_class"
214
+ evidence.append(f"Pipeline class {pipeline_class} looks image-oriented.")
215
+ elif "video" in cls and expected == "video":
216
+ confidence = "high"
217
+ source = "pipeline_class"
218
+ evidence.append(f"Pipeline class {pipeline_class} looks video-oriented.")
219
+ elif "audio" in cls or "speech" in cls:
220
+ confidence = "medium"
221
+ source = "pipeline_class"
222
+ evidence.append(f"Pipeline class {pipeline_class} looks audio-oriented.")
223
+
224
+ if VIDEO_OUTPUT_HINT_RE.search(combined) or re.search(r"\.frames\s*\[", text):
225
+ if expected == "video":
226
+ confidence = "high"
227
+ source = "model_card"
228
+ evidence.append("Model card or library name mentions video/avatar generation markers.")
229
+ elif IMAGE_OUTPUT_HINT_RE.search(text) and expected == "image":
230
+ if confidence == "low":
231
+ confidence = "medium"
232
+ source = "model_card"
233
+ evidence.append("Model card includes image output usage such as pipe(...).images.")
234
+ elif re.search(r"\.audios?\s*\[|generated audio|text-to-speech|soundfile|\.wav", text) and expected == "audio":
235
+ if confidence == "low":
236
+ confidence = "medium"
237
+ source = "model_card"
238
+ evidence.append("Model card includes audio output markers.")
239
+ elif re.search(r"generated_text|tokenizer\.decode|text-generation|response\s*=", text) and expected == "text":
240
+ if confidence == "low":
241
+ confidence = "medium"
242
+ source = "model_card"
243
+ evidence.append("Model card includes text output markers.")
244
+
245
+ if expected == "any":
246
+ confidence = "low"
247
+ if not evidence:
248
+ evidence.append("Custom or ambiguous library without a strong generated-output signal; keeping output flexible.")
249
+ elif not expected:
250
+ evidence.append("No strong generated-output signal found in pre-scan metadata.")
251
+ elif not evidence:
252
+ evidence.append(f"Pre-scan inferred {expected} from weak metadata signals.")
253
+
254
+ return {
255
+ "schema_version": "pre_scan_output_guess.v1",
256
+ "expected_output_type": expected or "",
257
+ "confidence": confidence,
258
+ "source": source,
259
+ "authority": "pre_scan_guess",
260
+ "final_authority": "runtime_contract_or_gradio_schema",
261
+ "evidence": evidence[:6],
262
+ }
263
 
264
 
265
  def infer_expected_output_type(
 
620
  has_diffusers_example = bool(card_signals["has_diffusers_example"])
621
  pipeline_class = str(card_signals["pipeline_class"] or "")
622
  runtime_hints = list(card_signals["runtime_hints"] or [])
623
+ output_guess = infer_output_guess(
624
  pipeline_tag=pipeline_tag,
625
  library_name=library_name,
626
  tags=tags,
627
  pipeline_class=pipeline_class,
628
  readme=readme,
629
  )
630
+ expected_output_type = output_guess["expected_output_type"] or None
631
+ expected_inputs = infer_expected_inputs(
632
+ pipeline_tag=pipeline_tag,
633
+ tags=tags,
634
+ readme=readme,
635
+ )
636
 
637
  score = 50
638
  good: list[str] = []
 
654
  else:
655
  score -= 12
656
  risk.append("No pipeline tag detected; task type may be ambiguous for an autonomous builder.")
657
+ if expected_inputs:
658
+ good.append("Inputs detected by pre-scan: " + ", ".join(expected_inputs) + ".")
659
  if expected_output_type:
660
+ good.append(f"Pre-scan output guess: {expected_output_type} (confidence {output_guess['confidence']}).")
661
 
662
  if library_name:
663
  score += 10
 
798
  "risk_signals": risk[:10],
799
  "recommendations": recommendations[:6],
800
  "expected_output_type": expected_output_type or "",
801
+ "expected_inputs": expected_inputs,
802
+ "output_confidence": output_guess["confidence"],
803
+ "output_authority": output_guess["authority"],
804
+ "output_evidence": output_guess["evidence"],
805
+ "pre_scan_output": output_guess,
806
  "build_risk": build_risk,
807
  "kernel_strategy": kernel_strategy,
808
  "metadata": {
 
820
  "pipeline_class": pipeline_class,
821
  "runtime_hints": runtime_hints,
822
  "expected_output_type": expected_output_type or "",
823
+ "expected_inputs": expected_inputs,
824
+ "output_confidence": output_guess["confidence"],
825
+ "output_authority": output_guess["authority"],
826
+ "output_evidence": output_guess["evidence"],
827
+ "pre_scan_output": output_guess,
828
  "diffusers_standard": bool(is_diffusers and has_model_index and has_safetensors),
829
  "build_risk_level": build_risk["level"],
830
  "recommended_session_minutes": build_risk["recommended_session_minutes"],
src/version.py CHANGED
@@ -1,7 +1,7 @@
1
  from __future__ import annotations
2
 
3
- ASF_APP_VERSION = "v198.26.60"
4
- ASF_RELEASE_NAME = "Agentic Space Factory v198.26.60"
5
 
6
 
7
  def resolve_app_version(value: str | None = None) -> str:
 
1
  from __future__ import annotations
2
 
3
+ ASF_APP_VERSION = "v198.26.61"
4
+ ASF_RELEASE_NAME = "Agentic Space Factory v198.26.61"
5
 
6
 
7
  def resolve_app_version(value: str | None = None) -> str:
src/worker_payload.py CHANGED
@@ -39,8 +39,8 @@ DEFAULT_PREFERRED_SPACE_HARDWARE = "zero-a10g"
39
  DEFAULT_FALLBACK_SPACE_HARDWARE = "a10g-large"
40
  DEFAULT_MODEL_ID = "sshleifer/tiny-gpt2"
41
  MAX_PI_REPAIR_ATTEMPTS = 3
42
- APP_VERSION = "v198.26.60"
43
- app_version = "v198.26.60"
44
 
45
  # Internal agent/recovery files may be needed inside the transient Pi
46
  # workspace, but they should not be published to the generated Space or shown
@@ -18892,7 +18892,7 @@ def smoke_generate(target_space_id: str, token: str, run_dir: Path, events_path:
18892
  # write_json(run_dir / "tests" / "payload_source.json", payload_source_record)
18893
  # write_json(run_dir / "tests" / "replay_source.json", replay_source)
18894
  # write_json(run_dir / "tests" / "validation_preflight.json", validation_preflight)
18895
- app_version = "v198.26.60"
18896
  engine_version = "unified_gradio_validation_harness_v198_25_3"
18897
  parent_build_run_id = os.environ.get("PARENT_BUILD_RUN_ID", "").strip()
18898
  validation_mode = os.environ.get("VALIDATION_MODE") or os.environ.get("SPACE_TEST_POLICY_MODE") or "linked"
 
39
  DEFAULT_FALLBACK_SPACE_HARDWARE = "a10g-large"
40
  DEFAULT_MODEL_ID = "sshleifer/tiny-gpt2"
41
  MAX_PI_REPAIR_ATTEMPTS = 3
42
+ APP_VERSION = "v198.26.61"
43
+ app_version = "v198.26.61"
44
 
45
  # Internal agent/recovery files may be needed inside the transient Pi
46
  # workspace, but they should not be published to the generated Space or shown
 
18892
  # write_json(run_dir / "tests" / "payload_source.json", payload_source_record)
18893
  # write_json(run_dir / "tests" / "replay_source.json", replay_source)
18894
  # write_json(run_dir / "tests" / "validation_preflight.json", validation_preflight)
18895
+ app_version = "v198.26.61"
18896
  engine_version = "unified_gradio_validation_harness_v198_25_3"
18897
  parent_build_run_id = os.environ.get("PARENT_BUILD_RUN_ID", "").strip()
18898
  validation_mode = os.environ.get("VALIDATION_MODE") or os.environ.get("SPACE_TEST_POLICY_MODE") or "linked"