tracebloc 1.2.76__tar.gz → 1.2.78__tar.gz

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.
Files changed (158) hide show
  1. {tracebloc-1.2.76 → tracebloc-1.2.78}/PKG-INFO +1 -1
  2. {tracebloc-1.2.76 → tracebloc-1.2.78}/pyproject.toml +1 -1
  3. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/hf/_build.py +3 -19
  4. tracebloc-1.2.78/tracebloc/convert/heads.py +51 -0
  5. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/outputs.py +30 -3
  6. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/__init__.py +1 -1
  7. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/generate.py +4 -3
  8. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/live.py +18 -18
  9. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/remote.py +9 -4
  10. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/package.py +12 -3
  11. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/training_versions.py +3 -3
  12. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc.egg-info/PKG-INFO +1 -1
  13. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc.egg-info/SOURCES.txt +1 -0
  14. {tracebloc-1.2.76 → tracebloc-1.2.78}/MANIFEST.in +0 -0
  15. {tracebloc-1.2.76 → tracebloc-1.2.78}/README.md +0 -0
  16. {tracebloc-1.2.76 → tracebloc-1.2.78}/license.txt +0 -0
  17. {tracebloc-1.2.76 → tracebloc-1.2.78}/setup.cfg +0 -0
  18. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/__init__.py +0 -0
  19. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_deprecation.py +0 -0
  20. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_framework_utils.py +0 -0
  21. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_http_utils.py +0 -0
  22. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_link_answer.py +0 -0
  23. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_link_regeneration.py +0 -0
  24. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_linking.py +0 -0
  25. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_raw_width_note.py +0 -0
  26. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_stored_link.py +0 -0
  27. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/_upload_conversion.py +0 -0
  28. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/checks.py +0 -0
  29. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/client.py +0 -0
  30. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/config.py +0 -0
  31. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/contracts/stage_urls.v1.json +0 -0
  32. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/contracts/stage_urls.v1.source.json +0 -0
  33. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/contracts/survival_payload.py +0 -0
  34. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/contracts/training_requirements.source.json +0 -0
  35. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/contracts/training_requirements.txt +0 -0
  36. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/__init__.py +0 -0
  37. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/acceptance.py +0 -0
  38. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/__init__.py +0 -0
  39. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/hf/__init__.py +0 -0
  40. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/hf/_model_type.py +0 -0
  41. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/tabular.py +0 -0
  42. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/vision/__init__.py +0 -0
  43. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/families/vision/_matching.py +0 -0
  44. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/gate.py +0 -0
  45. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/interfaces.py +0 -0
  46. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/licence/__init__.py +0 -0
  47. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/licence/spdx.py +0 -0
  48. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/arguments.py +0 -0
  49. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/assemble.py +0 -0
  50. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/checkpoint.py +0 -0
  51. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/gate_rules.py +0 -0
  52. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/head.py +0 -0
  53. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/import_check.py +0 -0
  54. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/layer0.py +0 -0
  55. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/model_class.py +0 -0
  56. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/repo.py +0 -0
  57. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/shake.py +0 -0
  58. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/owncode/source_tree.py +0 -0
  59. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/report.py +0 -0
  60. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/convert/tokenizers.py +0 -0
  61. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/env_login.py +0 -0
  62. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/exceptions.py +0 -0
  63. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/fetch.py +0 -0
  64. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/inference.py +0 -0
  65. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/library_fetch.py +0 -0
  66. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/lifelines_weights.py +0 -0
  67. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/link_model_dataset.py +0 -0
  68. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/__init__.py +0 -0
  69. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/_partials.tpl +0 -0
  70. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/embeddings.tpl +0 -0
  71. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/nlp_finetune.tpl +0 -0
  72. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/nlp_generative.tpl +0 -0
  73. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/survival.tpl +0 -0
  74. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/tabular_timeseries.tpl +0 -0
  75. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/notebook/templates/vision_from_scratch.tpl +0 -0
  76. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/raw_mode.py +0 -0
  77. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/raw_mode_frame.py +0 -0
  78. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/raw_mode_seed.py +0 -0
  79. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/raw_mode_survival.py +0 -0
  80. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/raw_mode_torch.py +0 -0
  81. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/seed_weights.py +0 -0
  82. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/__init__.py +0 -0
  83. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/augmentation.py +0 -0
  84. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/callbacks.py +0 -0
  85. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/converted.py +0 -0
  86. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/features.py +0 -0
  87. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/image_size.py +0 -0
  88. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/lora.py +0 -0
  89. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/lora_validation.py +0 -0
  90. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/loss.py +0 -0
  91. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/memory_estimate.py +0 -0
  92. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/plan.py +0 -0
  93. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/preprocessing.py +0 -0
  94. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/shape.py +0 -0
  95. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/subdataset.py +0 -0
  96. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/submitter.py +0 -0
  97. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/training/summary.py +0 -0
  98. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/__init__.py +0 -0
  99. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/lifelines_time_to_event.py +0 -0
  100. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/model_upload.py +0 -0
  101. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/scikit_survival_time_to_event.py +0 -0
  102. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/sequence_length.py +0 -0
  103. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/skl_tabular_base.py +0 -0
  104. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/skl_tabular_classifier.py +0 -0
  105. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/skl_tabular_regression.py +0 -0
  106. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/statistical_base.py +0 -0
  107. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/survival_base.py +0 -0
  108. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_causal_language_modeler.py +0 -0
  109. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_embeddings.py +0 -0
  110. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_image_classifier.py +0 -0
  111. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_key_point_detector.py +0 -0
  112. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_masked_language_modeler.py +0 -0
  113. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_nlp_base.py +0 -0
  114. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_object_detector.py +0 -0
  115. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_semantic_segmentation.py +0 -0
  116. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_sentence_pair_classifier.py +0 -0
  117. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_seq2seq_modeler.py +0 -0
  118. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_tabular_classifier.py +0 -0
  119. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_tabular_regression.py +0 -0
  120. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_text_classifier.py +0 -0
  121. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_time_series_classifier.py +0 -0
  122. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_time_series_forecaster.py +0 -0
  123. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_time_to_event.py +0 -0
  124. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/torch_token_classifier.py +0 -0
  125. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/weight_loaders.py +0 -0
  126. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/upload/weights_parts.py +0 -0
  127. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/user.py +0 -0
  128. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/__init__.py +0 -0
  129. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/class_order.py +0 -0
  130. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/constants.py +0 -0
  131. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/custom_loss_probe.py +0 -0
  132. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/detection_utils.py +0 -0
  133. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/entry_point.py +0 -0
  134. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/feature_dict.py +0 -0
  135. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/general_utils.py +0 -0
  136. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/key_point_detection_utils.py +0 -0
  137. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/registry.py +0 -0
  138. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/safetensors_io.py +0 -0
  139. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/semantic_segmentation_utils.py +0 -0
  140. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/tabular_classification_utils.py +0 -0
  141. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/tabular_custom_loss_utils.py +0 -0
  142. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/tabular_regression_utils.py +0 -0
  143. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/text_classification_utils.py +0 -0
  144. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/time_series_utils.py +0 -0
  145. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/time_to_event_utils.py +0 -0
  146. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/utils/warnings_once.py +0 -0
  147. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/__init__.py +0 -0
  148. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/checker.py +0 -0
  149. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/header_rules.py +0 -0
  150. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/lifelines_checks.py +0 -0
  151. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/pytorch_checks.py +0 -0
  152. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/rewriter.py +0 -0
  153. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/scikit_survival_checks.py +0 -0
  154. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc/validation/sklearn_checks.py +0 -0
  155. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc.egg-info/dependency_links.txt +0 -0
  156. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc.egg-info/requires.txt +0 -0
  157. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc.egg-info/top_level.txt +0 -0
  158. {tracebloc-1.2.76 → tracebloc-1.2.78}/tracebloc_package/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tracebloc
3
- Version: 1.2.76
3
+ Version: 1.2.78
4
4
  Summary: Build AI with anyone. On data that can't move. SDK for the tracebloc collaborative AI workspace.
5
5
  Author-email: tracebloc <lukas@tracebloc.io>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tracebloc"
7
- version = "1.2.76"
7
+ version = "1.2.78"
8
8
  description = "Build AI with anyone. On data that can't move. SDK for the tracebloc collaborative AI workspace."
9
9
  license = "MIT"
10
10
  license-files = ["license.txt"]
@@ -16,6 +16,8 @@ from typing import Any, Iterable, Iterator, Mapping
16
16
 
17
17
  from tracebloc.convert.interfaces import ConversionRefusedError, RefusalCause
18
18
  from tracebloc.convert.interfaces import SourcedValue
19
+ from tracebloc.convert.heads import collapse as head_prefixes
20
+ from tracebloc.convert.heads import head_key
19
21
  from tracebloc.utils.constants import TaskCategory
20
22
 
21
23
 
@@ -55,8 +57,7 @@ def split_head(
55
57
  params = {name for name, _ in model.named_parameters(remove_duplicate=False)}
56
58
 
57
59
  def is_head(key: str) -> bool:
58
- own = key.startswith(f"{prefix}.")
59
- return inner and (not own or key.startswith(f"{prefix}.pooler."))
60
+ return inner and head_key(key, prefix)
60
61
 
61
62
  keys = list(keys)
62
63
  head = tuple(sorted(key for key in keys if is_head(key)))
@@ -180,23 +181,6 @@ def load(
180
181
  return model.eval(), fresh, tuple(dropped)
181
182
 
182
183
 
183
- def head_prefixes(fresh: Iterable[str], keys: Iterable[str]) -> tuple[str, ...]:
184
- """The shortest module prefixes whose every key in ``keys`` is ``fresh``:
185
- ``classifier.`` for a head whose layers all start fresh."""
186
- fresh, keys = set(fresh), list(keys)
187
- prefixes = set()
188
- for key in fresh:
189
- parts = key.split(".")
190
- for depth in range(1, len(parts)):
191
- prefix = ".".join(parts[:depth]) + "."
192
- if all(other in fresh for other in keys if other.startswith(prefix)):
193
- prefixes.add(prefix)
194
- break
195
- else:
196
- prefixes.add(key)
197
- return tuple(sorted(prefixes))
198
-
199
-
200
184
  def write_weights(model: Any, wrapper: str | None, target: Path) -> tuple[str, ...]:
201
185
  """Write the model's state as SafeTensors; return the keys written.
202
186
 
@@ -0,0 +1,51 @@
1
+ """Which keys of a converted model are its task's head, which starts fresh.
2
+
3
+ Stdlib and ``tracebloc`` core at import.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Iterable
9
+
10
+ from tracebloc.convert.interfaces import GeneratedPackage
11
+
12
+ #: A package value naming its backbone's module: the keys the shipped weights
13
+ #: lack outside it, or in its pooler, start fresh (:func:`head_key`).
14
+ BACKBONE_PREFIX = "backbone_prefix"
15
+
16
+
17
+ def head_key(key: str, backbone: str) -> bool:
18
+ """Whether ``key`` is the task's head of a model whose backbone is ``backbone``:
19
+ outside it, or in its ``pooler``, which only a head reads (Hugging Face's
20
+ ``base_model_prefix``)."""
21
+ return not key.startswith(f"{backbone}.") or key.startswith(f"{backbone}.pooler.")
22
+
23
+
24
+ def fresh_head(package: GeneratedPackage, keys: Iterable[str]) -> set[str]:
25
+ """The keys of a built package, ``keys``, its weights lack in its head; empty
26
+ for a package that declares no :data:`BACKBONE_PREFIX` or ships no weights."""
27
+ declared = package.values.get(BACKBONE_PREFIX)
28
+ if declared is None or package.weights is None:
29
+ return set()
30
+ from safetensors import safe_open
31
+
32
+ with safe_open(str(package.weights), framework="pt") as weights:
33
+ shipped = set(weights.keys())
34
+ return {k for k in keys if k not in shipped and head_key(k, declared.value)}
35
+
36
+
37
+ def collapse(fresh: Iterable[str], keys: Iterable[str]) -> tuple[str, ...]:
38
+ """The shortest module prefixes whose every key in ``keys`` is ``fresh``:
39
+ ``classifier.`` for a head whose layers all start fresh."""
40
+ fresh, keys = set(fresh), list(keys)
41
+ prefixes = set()
42
+ for key in fresh:
43
+ parts = key.split(".")
44
+ for depth in range(1, len(parts)):
45
+ prefix = ".".join(parts[:depth]) + "."
46
+ if all(other in fresh for other in keys if other.startswith(prefix)):
47
+ prefixes.add(prefix)
48
+ break
49
+ else:
50
+ prefixes.add(key)
51
+ return tuple(sorted(prefixes))
@@ -33,6 +33,8 @@ from tracebloc.validation.header_rules import SHAPE_VALUES
33
33
  #: The probe's batch, and its sequence length's ceiling.
34
34
  PROBE_BATCH = 2
35
35
  PROBE_TOKENS = 16
36
+ #: The random state every forward on the probe starts from.
37
+ PROBE_SEED = 4321
36
38
 
37
39
  IMAGE_TASKS = frozenset(SHAPE_VALUES["image_size"])
38
40
  FEATURE_TASKS = frozenset(SHAPE_VALUES["num_feature_points"]) - IMAGE_TASKS
@@ -92,6 +94,18 @@ def _one_line(error: BaseException) -> str:
92
94
 
93
95
  # --- the output comparison ---------------------------------------------------
94
96
 
97
+ #: The function a generated entry file passes its class's output through to
98
+ #: return the task's output (``owncode.generate``); the original's goes through it too.
99
+ OUTPUT_ADAPTER = "_task_output"
100
+
101
+
102
+ def task_output(model: Any) -> Callable[[Any], Any]:
103
+ """What the generated ``MyModel.forward`` keeps of its class's output, read
104
+ from the entry file defining it; the output itself when it adapts none."""
105
+ forward = vars(type(model)).get("forward")
106
+ adapter = getattr(forward, "__globals__", {}).get(OUTPUT_ADAPTER)
107
+ return adapter if callable(adapter) else lambda output: output
108
+
95
109
 
96
110
  def original_builder(family: Family | None) -> Callable[..., Any] | None:
97
111
  """The family's ``build_original``, or its module's (the own-code converter's)."""
@@ -125,7 +139,18 @@ class Probe:
125
139
  shown: str
126
140
 
127
141
  def call(self, model: Any) -> Any:
128
- """``model`` on the probe, keyword arguments filtered to what it takes."""
142
+ """``model`` on the probe, keyword arguments filtered to what it takes.
143
+
144
+ Each call starts from :data:`PROBE_SEED`, so a forward that draws random
145
+ numbers in eval (random features, sampling) draws the same on both sides.
146
+ """
147
+ import torch
148
+
149
+ with torch.random.fork_rng(devices=[]):
150
+ torch.manual_seed(PROBE_SEED)
151
+ return self._call(model)
152
+
153
+ def _call(self, model: Any) -> Any:
129
154
  if not self.named:
130
155
  return model(self.tensor)
131
156
  try:
@@ -322,7 +347,8 @@ def torch_output_check(
322
347
  """The generated model gives the original's output on a fixed probe.
323
348
 
324
349
  Exact for own code; within the category's tolerance for a template-rebuilt
325
- family or bf16 weights. With a fresh head, the backbone's output is
350
+ family or bf16 weights. The original's output is kept as the generated
351
+ model keeps its class's (:func:`task_output`). With a fresh head, the backbone's output is
326
352
  compared: the original's backbone against the submodule holding its
327
353
  parameters, or what reaches the head in each.
328
354
  """
@@ -338,9 +364,10 @@ def torch_output_check(
338
364
  probe = probe_for(category, header, model)
339
365
  with torch.no_grad():
340
366
  if package.compared_output is ComparedOutput.MODEL:
367
+ adapt = task_output(model)
341
368
  ours, theirs = (
342
369
  output_tensors(probe.call(model)),
343
- output_tensors(probe.call(original)),
370
+ output_tensors(adapt(probe.call(original))),
344
371
  )
345
372
  compared = "the model's output"
346
373
  else:
@@ -142,7 +142,7 @@ def build_original(recognition: Recognition, package: GeneratedPackage) -> Any:
142
142
  auto = next(
143
143
  k for k, (_, name) in state["auto_map"].items() if name == entry
144
144
  )
145
- loader = vars(transformers)[auto]
145
+ loader = getattr(transformers, auto) # a lazy module: not in its vars yet
146
146
  return loader.from_pretrained(
147
147
  root, trust_remote_code=True, local_files_only=True
148
148
  )
@@ -19,6 +19,7 @@ from tracebloc.convert.interfaces import (
19
19
  UseCaseTask,
20
20
  ValueSource,
21
21
  )
22
+ from tracebloc.convert.outputs import OUTPUT_ADAPTER
22
23
  from tracebloc.utils.constants import Framework, TaskCategory
23
24
  from tracebloc.validation.header_rules import (
24
25
  NO_OUTPUT_CLASSES,
@@ -54,7 +55,7 @@ DEFAULTS = {
54
55
 
55
56
  _ADAPTER = """
56
57
 
57
- def _task_output(output):
58
+ def {adapter}(output):
58
59
  if isinstance(output, dict):
59
60
  for key in ("logits", "out"):
60
61
  if key in output:
@@ -149,7 +150,7 @@ def entry_source(
149
150
  if preamble:
150
151
  text += f"\n{preamble}\n"
151
152
  if adapter:
152
- text += _ADAPTER.replace("{pick}", pick)
153
+ text += _ADAPTER.replace("{pick}", pick).replace("{adapter}", OUTPUT_ADAPTER)
153
154
  call = ""
154
155
  if resize is not None:
155
156
  text += _RESIZE
@@ -161,7 +162,7 @@ def entry_source(
161
162
  " def __init__(self):\n"
162
163
  f" super().__init__({construct}){resize_line}\n\n"
163
164
  " def forward(self, *args, **kwargs):\n"
164
- " return _task_output(super().forward(*args, **kwargs))\n"
165
+ f" return {OUTPUT_ADAPTER}(super().forward(*args, **kwargs))\n"
165
166
  )
166
167
  elif call:
167
168
  text += (
@@ -20,7 +20,7 @@ import symtable
20
20
  import sys
21
21
  import textwrap
22
22
  from pathlib import Path
23
- from typing import Any, Mapping
23
+ from typing import Any, Callable, Mapping
24
24
 
25
25
  from tracebloc.convert.interfaces import (
26
26
  ConversionInput,
@@ -262,33 +262,33 @@ def _package_root(path: Path) -> Path:
262
262
  return root
263
263
 
264
264
 
265
- def recognise(source: ConversionInput) -> Recognition | None:
266
- torch = sys.modules.get("torch")
267
- obj = source.live_object
268
- if torch is None or not isinstance(obj, torch.nn.Module):
269
- return None
265
+ def _reading(call: Callable[[], Any]) -> Any:
266
+ """``call``'s result: it runs the peer's object, so its error is a refusal.
267
+ Running out of memory here is this machine's, not the code's."""
270
268
  try:
271
- model, hyper, notes = _model_of(obj)
272
- weights = dict(model.state_dict())
273
- remote_config = (
274
- model.config.to_dict()
275
- if type(model).__module__.startswith("transformers_modules.")
276
- else None
277
- )
278
- except ConversionRefusedError:
269
+ return call()
270
+ except (ConversionRefusedError, MemoryError):
279
271
  raise
280
272
  except Exception as error:
281
273
  what = "reading the object passed to upload_model"
282
274
  raise refuse_code_failure(what, error) from error
275
+
276
+
277
+ def recognise(source: ConversionInput) -> Recognition | None:
278
+ torch = sys.modules.get("torch")
279
+ obj = source.live_object
280
+ if torch is None or not isinstance(obj, torch.nn.Module):
281
+ return None
282
+ model, hyper, notes = _reading(lambda: _model_of(obj))
283
283
  cls = type(model)
284
284
  module = sys.modules.get(cls.__module__)
285
285
  file = getattr(module, "__file__", None)
286
286
  if file and installed(Path(file)):
287
287
  raise _refuse(f"is {cls.__module__}.{cls.__name__}, a library class")
288
- if remote_config is not None and file:
289
- found = remote.recognise_parts(
290
- source, Path(file).parent, remote_config, weights, None
291
- )
288
+ weights = _reading(lambda: dict(model.state_dict()))
289
+ if cls.__module__.startswith("transformers_modules.") and file:
290
+ config = _reading(lambda: model.config.to_dict())
291
+ found = remote.recognise_parts(source, Path(file).parent, config, weights, None)
292
292
  state = {**found.state, "live_object": model, "proof": Proof.EXACT}
293
293
  return dataclasses.replace(found, state=state)
294
294
  if cls.__module__.split(".")[0] in LIBRARY_ROOTS:
@@ -32,6 +32,7 @@ from tracebloc.convert.owncode import assemble
32
32
  from tracebloc.convert.owncode.checkpoint import load, refuse_no_source
33
33
  from tracebloc.convert.owncode.generate import has_output_classes
34
34
  from tracebloc.convert.owncode.shake import flat_name
35
+ from tracebloc.convert.heads import BACKBONE_PREFIX
35
36
  from tracebloc.convert.owncode.source_tree import SourceTree
36
37
  from tracebloc.utils.constants import Framework, TaskCategory
37
38
 
@@ -262,10 +263,13 @@ def build(
262
263
  "output_classes"
263
264
  )
264
265
  weights = state["weights"]
266
+ prefix = _base_prefix(state["tree"], module)
265
267
  if weights is not None:
266
- weights = _move_weights(
267
- weights, _base_prefix(state["tree"], module), bare, same and unchanged
268
- )
268
+ weights = _move_weights(weights, prefix, bare, same and unchanged)
269
+ values = dict(recognition.values)
270
+ if prefix and not bare:
271
+ where = Provenance(ValueSource.REPO_FILE, f"{module}.py base_model_prefix")
272
+ values[BACKBONE_PREFIX] = SourcedValue(prefix, where)
269
273
  found = {}
270
274
  if isinstance(config.get("vocab_size"), int):
271
275
  found["vocab_size"] = SourcedValue(
@@ -295,4 +299,5 @@ def build(
295
299
  ComparedOutput.MODEL if same and unchanged else ComparedOutput.BACKBONE
296
300
  ),
297
301
  }
298
- return assemble.build(dataclasses.replace(recognition, state=built), task, workdir)
302
+ built_from = dataclasses.replace(recognition, state=built, values=values)
303
+ return assemble.build(built_from, task, workdir)
@@ -37,6 +37,7 @@ from tracebloc.convert.interfaces import (
37
37
  RefusalCause,
38
38
  SourcedValue,
39
39
  )
40
+ from tracebloc.convert.heads import collapse, fresh_head
40
41
  from tracebloc.convert.training_versions import refuse_code_failure
41
42
  from tracebloc.exceptions import ModelValidationError
42
43
  from tracebloc.validation.rewriter import ModelFileRewriter
@@ -384,9 +385,10 @@ def derive_seed_excluded_prefixes(
384
385
 
385
386
  ``build_for_classes(count, workdir)`` builds the package for ``count``
386
387
  output classes, which for a family is its ``build`` with that count. The
387
- peer's own code raising when it runs here is its :func:`code_failure`.
388
+ peer's own code raising when it runs here is its :func:`code_failure`. The
389
+ head is also every key :func:`fresh_head` finds in the first build.
388
390
  """
389
- built = []
391
+ built, fresh = [], set[str]()
390
392
  for count in PROBE_CLASSES:
391
393
  with tempfile.TemporaryDirectory(prefix="tracebloc_derive_") as raw:
392
394
  workdir, out = Path(raw) / "build", Path(raw) / "package"
@@ -401,7 +403,14 @@ def derive_seed_excluded_prefixes(
401
403
  if package.family != OWN_CODE_FAMILY:
402
404
  raise
403
405
  raise code_failure(written, error) from error
404
- return head_prefixes(*built)
406
+ if len(built) == 1:
407
+ fresh = fresh_head(package, built[0])
408
+ varying = head_prefixes(*built)
409
+ kept = [key for key in built[0] if not key.startswith(varying)]
410
+ found = {*varying, *collapse((k for k in fresh if k in kept), kept)}
411
+ return tuple(
412
+ sorted(p for p in found if not any(o != p and p.startswith(o) for o in found))
413
+ )
405
414
 
406
415
 
407
416
  def cast_weights_to_bf16(path: str | os.PathLike[str]) -> int:
@@ -174,9 +174,9 @@ def refuse_code_failure(
174
174
  installed here at another version than training's, that is the refusal.
175
175
  """
176
176
  libraries = imported_libraries(sources) or ("torch",)
177
- clauses = version_mismatches(libraries)
178
- if clauses:
179
- return ConversionRefusedError(RefusalCause.VERSIONS, refusal_message(clauses))
177
+ mismatched = version_mismatches(libraries)
178
+ if mismatched:
179
+ return ConversionRefusedError(RefusalCause.VERSIONS, refusal_message(mismatched))
180
180
  pins = read_pins()
181
181
  named = ", ".join(f"{name} {pinned_version(name, pins)}" for name in libraries)
182
182
  detail = " ".join(_SOURCE_FILE.sub("", format_exception(error)).split())[:300]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tracebloc
3
- Version: 1.2.76
3
+ Version: 1.2.78
4
4
  Summary: Build AI with anyone. On data that can't move. SDK for the tracebloc collaborative AI workspace.
5
5
  Author-email: tracebloc <lukas@tracebloc.io>
6
6
  License-Expression: MIT
@@ -42,6 +42,7 @@ tracebloc/contracts/training_requirements.txt
42
42
  tracebloc/convert/__init__.py
43
43
  tracebloc/convert/acceptance.py
44
44
  tracebloc/convert/gate.py
45
+ tracebloc/convert/heads.py
45
46
  tracebloc/convert/interfaces.py
46
47
  tracebloc/convert/outputs.py
47
48
  tracebloc/convert/package.py
File without changes
File without changes
File without changes
File without changes
File without changes