diff --git a/backends/apple/coreai/README.md b/backends/apple/coreai/README.md index 36c4bb5c873..ec0fd4856ca 100644 --- a/backends/apple/coreai/README.md +++ b/backends/apple/coreai/README.md @@ -26,9 +26,10 @@ python -m pytest backends/apple/coreai ## Runtime -The delegate manifest describes `.aimodel` source bundles, which require -`inline` packaging, and AOT-compiled `.aimodelc` bundles, which require -`aot_compiled_inline`. Both formats require a `function` name, and ordered +The delegate manifest's `packaging` field names the embedded format: `aimodel` +for a portable `.aimodel` bundle, located by `path`, or `aimodelc` for +AOT-compiled per-architecture `.aimodelc` bundles, located by `archs`. Both +formats require a `function` name, and ordered `input_names` and `output_names` matching the converter's bindings. Dictionary iteration order is not a binding contract. `export_hash` identifies the exported program used to namespace embedded assets. The `files` object maps relative @@ -128,9 +129,9 @@ even though the new complete contents are already visible. Use a local APFS volume; unsupported full-device flushes are reported as errors, not downgraded to `fsync`. -Inline bundles are read through `NamedDataMap` and materialized as unchanged -files under the cache directory. Named data can be supplied externally; inline -packaging does not require all bytes to reside in one physical PTE. The exporter +Embedded bundles are read through `NamedDataMap` and materialized as unchanged +files under the cache directory. Named data can be supplied externally; embedded +bundles do not require all bytes to reside in one physical PTE. computes each bundle digest from all delivered relative filenames and file bytes, not just the SDK's bytecode-only `main.hash`. Each AOT architecture has an independent digest; only the selected architecture is materialized. NDS key names @@ -191,7 +192,7 @@ choose the SDK artifact directory. The backend does not inspect SDK-private files, alter their backup flags, or use an App Group cache. Each selected bundle has a `bundle_identity` derived from its bundle digest, -name, and source/AOT mode. This identifies the delivered bundle independently of +name, and packaging (`aimodel` or `aimodelc`). This identifies the delivered bundle independently of `export_hash`, which namespaces embedded assets. A readable cache key combines that bundle identity with the platform and Core AI device architecture, plus a hash of a versioned diff --git a/backends/apple/coreai/compiler/preprocess.py b/backends/apple/coreai/compiler/preprocess.py index 0bc064f2fbb..1d6b455bd7e 100644 --- a/backends/apple/coreai/compiler/preprocess.py +++ b/backends/apple/coreai/compiler/preprocess.py @@ -78,9 +78,9 @@ class COMPILE_SPEC_KEYS(Enum): class AssetPackaging(str, Enum): # Portable .aimodel embedded in the .pte via NamedDataStore. - INLINE = "inline" + AIMODEL = "aimodel" # AOT-compiled per-arch .aimodelc bundles embedded in the .pte. - AOT_COMPILED_INLINE = "aot_compiled_inline" + AIMODELC = "aimodelc" @dataclass(frozen=True) @@ -213,7 +213,7 @@ def _deliver( **manifest_extra, **metadata, } - if packaging == AssetPackaging.INLINE: + if packaging == AssetPackaging.AIMODEL: manifest["path"] = f"{export_hash}/{manifest['path']}" else: manifest["archs"] = { @@ -520,7 +520,7 @@ def _preprocess_portable( _save_asset(program, Path(tmp) / "model.aimodel", min_os) return _deliver( Path(tmp), - AssetPackaging.INLINE, + AssetPackaging.AIMODEL, { **bindings, # relative path the runtime resolves against its base @@ -538,7 +538,7 @@ def _preprocess_aot_compiled( out = _compile_aot(program, opts, Path(tmp)) return _deliver( out, - AssetPackaging.AOT_COMPILED_INLINE, + AssetPackaging.AIMODELC, { **bindings, "platform": opts["platform"], diff --git a/backends/apple/coreai/runtime/coreai_cache_key.mm b/backends/apple/coreai/runtime/coreai_cache_key.mm index 8f63ce7fd25..784fd803f5b 100644 --- a/backends/apple/coreai/runtime/coreai_cache_key.mm +++ b/backends/apple/coreai/runtime/coreai_cache_key.mm @@ -80,7 +80,7 @@ bool valid_device(NSString* device) { bool aot_compiled) { // Bumping the leading version makes every existing cache entry unreachable. auto encoded = encode_json( - @[ @"1", digest, aot_compiled ? @"aot" : @"source", bundle_name ]); + @[ @"1", digest, aot_compiled ? @"aimodelc" : @"aimodel", bundle_name ]); if (!encoded.ok()) { return encoded.error(); } diff --git a/backends/apple/coreai/runtime/coreai_load_coordinator.mm b/backends/apple/coreai/runtime/coreai_load_coordinator.mm index 3cfe7b42a19..9438dc42bc9 100644 --- a/backends/apple/coreai/runtime/coreai_load_coordinator.mm +++ b/backends/apple/coreai/runtime/coreai_load_coordinator.mm @@ -206,7 +206,7 @@ Error evict_one(id loader, NSData* bookmark) { ET_LOG( Info, "Core AI specialization started: kind=%s, key=%s", - host_bundle.bundle.aot_compiled ? "aot" : "source", + host_bundle.bundle.aot_compiled ? "aimodelc" : "aimodel", cache_key.UTF8String); [loader specializeModelAtURL:url completion:completion]; }); diff --git a/backends/apple/coreai/runtime/coreai_manifest.mm b/backends/apple/coreai/runtime/coreai_manifest.mm index af139c8f09d..007d049b07c 100644 --- a/backends/apple/coreai/runtime/coreai_manifest.mm +++ b/backends/apple/coreai/runtime/coreai_manifest.mm @@ -174,11 +174,11 @@ bool parse_version(id value, NSOperatingSystemVersion& version) { InvalidProgram, "Missing Core AI packaging"); ET_CHECK_OR_RETURN_ERROR( - [packaging isEqualToString:@"inline"] || - [packaging isEqualToString:@"aot_compiled_inline"], + [packaging isEqualToString:@"aimodel"] || + [packaging isEqualToString:@"aimodelc"], NotSupported, - "Unsupported Core AI packaging; expected .aimodel or AOT .aimodelc"); - const bool aot_compiled = [packaging hasPrefix:@"aot_compiled_"]; + "Unsupported Core AI packaging; expected aimodel or aimodelc"); + const bool aot_compiled = [packaging isEqualToString:@"aimodelc"]; NSString* export_hash = dict[@"export_hash"]; NSString* function = dict[@"function"]; NSArray* inputs = dict[@"input_names"]; diff --git a/backends/apple/coreai/runtime/test/coreai_delegate_test.mm b/backends/apple/coreai/runtime/test/coreai_delegate_test.mm index 84530ac9c92..f39c6a7996e 100644 --- a/backends/apple/coreai/runtime/test/coreai_delegate_test.mm +++ b/backends/apple/coreai/runtime/test/coreai_delegate_test.mm @@ -153,7 +153,7 @@ void expect_preflight_rejection( TEST_F(CoreAIDelegateTest, PreflightRejectsFutureDeploymentForSourceAndAot) { @autoreleasepool { for (bool aot : {false, true}) { - SCOPED_TRACE(aot ? "AOT" : "source"); + SCOPED_TRACE(aot ? "aimodelc" : "aimodel"); auto dict = aot ? aot_manifest_dict() : manifest_dict(); dict[@"min_deployment_version"] = @"999999.0"; expect_preflight_rejection( diff --git a/backends/apple/coreai/runtime/test/coreai_manifest_fixture.h b/backends/apple/coreai/runtime/test/coreai_manifest_fixture.h index bf9af55c0bb..8cd2e99a276 100644 --- a/backends/apple/coreai/runtime/test/coreai_manifest_fixture.h +++ b/backends/apple/coreai/runtime/test/coreai_manifest_fixture.h @@ -22,7 +22,7 @@ inline NSString* fixture_identity(char digit) { inline NSMutableDictionary* manifest_dict() { return [@{ - @"packaging" : @"inline", + @"packaging" : @"aimodel", @"export_hash" : @"ab", @"path" : @"ab/model.aimodel", @"function" : @"main", @@ -37,7 +37,7 @@ inline NSMutableDictionary* manifest_dict() { inline NSMutableDictionary* aot_manifest_dict() { auto dict = manifest_dict(); [dict removeObjectForKey:@"path"]; - dict[@"packaging"] = @"aot_compiled_inline"; + dict[@"packaging"] = @"aimodelc"; dict[@"platform"] = @"macOS"; dict[@"archs"] = @{ @"arch_b" : @"ab/model.arch_b.aimodelc", diff --git a/backends/apple/coreai/runtime/test/coreai_source_integrity_test.mm b/backends/apple/coreai/runtime/test/coreai_source_integrity_test.mm index 264042988e7..02596987687 100644 --- a/backends/apple/coreai/runtime/test/coreai_source_integrity_test.mm +++ b/backends/apple/coreai/runtime/test/coreai_source_integrity_test.mm @@ -58,7 +58,7 @@ TEST_F(CoreAISourceTest, RejectsMalformedStoredBundlesWithoutReplacement) { for (bool aot : {false, true}) { - SCOPED_TRACE(aot ? "aot" : "source"); + SCOPED_TRACE(aot ? "aimodelc" : "aimodel"); for (NSString* damage in @[ @"missing-file", @"extra-file", diff --git a/backends/apple/coreai/test/test_preprocess.py b/backends/apple/coreai/test/test_preprocess.py index 2d8b0d39fd5..e81eb75ad58 100644 --- a/backends/apple/coreai/test/test_preprocess.py +++ b/backends/apple/coreai/test/test_preprocess.py @@ -142,7 +142,7 @@ class PortablePreprocessTest(unittest.TestCase): def test_inline_embeds_files_in_nds(self): result = CoreAIBackend.preprocess(_edge_program(), []) manifest = json.loads(result.processed_bytes) - self.assertEqual(manifest["packaging"], "inline") + self.assertEqual(manifest["packaging"], "aimodel") self.assertTrue(manifest["files"], "expected at least one asset file") out = result.data_store_output self.assertIsNotNone(out) @@ -215,7 +215,7 @@ def test_same_program_hash_with_different_metadata_merges(self): (bundle / "metadata.json").write_text( json.dumps({"creationDate": timestamp}) ) - result = _deliver(root, AssetPackaging.INLINE, {"path": bundle.name}) + result = _deliver(root, AssetPackaging.AIMODEL, {"path": bundle.name}) manifest = json.loads(result.processed_bytes) manifests.append(manifest) self.assertEqual( @@ -240,9 +240,7 @@ def test_aot_namespace_covers_every_architecture(self): (bundle / "model.mil").write_bytes(b"original") for payload in (b"original", b"modified"): (root / archs["h16"] / "model.mil").write_bytes(payload) - result = _deliver( - root, AssetPackaging.AOT_COMPILED_INLINE, {"archs": archs} - ) + result = _deliver(root, AssetPackaging.AIMODELC, {"archs": archs}) manifest = json.loads(result.processed_bytes) manifests.append(manifest) for arch, name in archs.items(): @@ -378,7 +376,7 @@ def test_inline_embeds_compiled_bundles(self, _build): [_aot_spec({"platform": "iOS", "architectures": ["h15g", "h16"]})], ) manifest = json.loads(result.processed_bytes) - self.assertEqual(manifest["packaging"], "aot_compiled_inline") + self.assertEqual(manifest["packaging"], "aimodelc") self.assertEqual(manifest["platform"], "iOS") self.assertEqual(sorted(manifest["archs"]), ["h15g", "h16"]) # Compiled bundle contents are embedded (files under a *.aimodelc dir). @@ -400,7 +398,7 @@ def test_defaults_to_all_architectures(self, _build): # Empty architectures => coreai-build decides (our fake yields one). result = CoreAIBackend.preprocess(_edge_program(), [_aot_spec({})]) manifest = json.loads(result.processed_bytes) - self.assertEqual(manifest["packaging"], "aot_compiled_inline") + self.assertEqual(manifest["packaging"], "aimodelc") self.assertEqual(manifest["platform"], "macOS") # default self.assertTrue(manifest["archs"]) @@ -448,7 +446,7 @@ def test_aot_inline_embeds_aimodelc(self): CoreAIPartitioner(aot_compile_config=AOTCompileConfig(platform="macOS")) ) lbm, manifest = _lowered_manifest(lowered) - self.assertEqual(manifest["packaging"], "aot_compiled_inline") + self.assertEqual(manifest["packaging"], "aimodelc") self.assertEqual(manifest["platform"], "macOS") self.assertGreaterEqual(len(manifest["archs"]), 1) self.assertTrue(any(".aimodelc/" in f for f in manifest["files"]))