Pin reproducible runtime dependencies and checkpoint-specific export settings
Browse files- README.md +2 -2
- SHA256SUMS +6 -5
- convert_decoder.py +6 -3
- coreai_decoder.py +4 -0
- requirements.txt +8 -0
- runtime-smoke.json +15 -1
- smoke_decoder.py +7 -1
README.md
CHANGED
|
@@ -6,11 +6,11 @@ tags: [coreai, core-ai, apple, aimodel, decisions, vision]
|
|
| 6 |
|
| 7 |
# amos-1-small — Apple Core AI
|
| 8 |
|
| 9 |
-
Independent AMOS-1 conversion with **bidirectional full attention** preserved. Text backbone, 255-code readout, vision tower, span head, region head and trained box head execute through Core AI. Original prompt formatting, temperatures and quote decoding are retained. This is a decision model, not a text generator.
|
| 10 |
|
| 11 |
## Use
|
| 12 |
|
| 13 |
-
Requires macOS 27 and the Core AI Python runtime. Tested with `coreai-torch==0.4.3`, PyTorch 2.14.0, Transformers 5.
|
| 14 |
|
| 15 |
```python
|
| 16 |
import asyncio
|
|
|
|
| 6 |
|
| 7 |
# amos-1-small — Apple Core AI
|
| 8 |
|
| 9 |
+
Independent AMOS-1 conversion with its checkpoint's **bidirectional full attention** preserved. Text backbone, 255-code readout, vision tower, span head, region head and trained box head execute through Core AI. Original prompt formatting, temperatures and quote decoding are retained. This is a decision model, not a text generator.
|
| 10 |
|
| 11 |
## Use
|
| 12 |
|
| 13 |
+
Requires macOS 27 and the Core AI Python runtime. Tested with `coreai-torch==0.4.3`, PyTorch 2.14.0, Transformers 5.19 development, NumPy and Pillow. Exact dependencies are in `requirements.txt`. The converter warns that this PyTorch version exceeds its validated range. Host preprocessing/decoding uses PyTorch tensors; it loads no PyTorch neural weights.
|
| 14 |
|
| 15 |
```python
|
| 16 |
import asyncio
|
SHA256SUMS
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE
|
| 2 |
-
|
| 3 |
9f25e439543c4493b66f609c2a4c57a3d97c11194ac247c3c043f4657725911e SOURCE.json
|
| 4 |
19dd2e174b2f7468407243220912947feb04a9260f347223021f880b532439a1 bf16-attempt.json
|
| 5 |
5865684cabaa8e1a23243db7d9d32569a57c7b5011bf47ed95814b9813af57dd bf16-comparison.json
|
| 6 |
f9ca221eceeea6dc52774885a8c50ad727bb8c269a7ff4fbb439131d2f5be0f2 calibration.json
|
| 7 |
2636cc2d838bc7395655ebb3d2ba933b186a43b13ce134c9a441ee8ba45a9d0d config.json
|
| 8 |
-
|
| 9 |
-
|
| 10 |
3708c801947fd75c057ff534edc404aacb4cc0acc9e653c12f09207e0d848d37 heads.aimodel/main.hash
|
| 11 |
132384c42c3a5c6269a79862d6540a5a6834b532674ba847d83a5b181f85a860 heads.aimodel/main.mlirb
|
| 12 |
3284600a3ad7c8e378bbe228ce3eb967d5da56bb40959aba7e56b177a3fc928a heads.aimodel/metadata.json
|
|
@@ -19,7 +19,8 @@ aa7582a6b90dc3711049d293d985e549f2b22c0c4e5ad11b9272a03c6294886e model/tokenize
|
|
| 19 |
8c54bd45ef2fc821a711502da04af1bff020fe02c2207117c7ffdbf1866e6e25 model/tokenizer_config.json
|
| 20 |
7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13 model/video_preprocessor_config.json
|
| 21 |
d7910a3390f8073d95908f3301c0ea0e2df4551699546430003bc8226373c2bc qwen_export_helpers.py
|
| 22 |
-
|
|
|
|
| 23 |
9e17531efd289cf720a36688d943197f9baf9db7c4f743aa4951f6b6f7dbafda serve/README.md
|
| 24 |
0579eb845ee7af463ec88cf627d99dd636466f2c12d840a7cbe183d8f17044fd serve/amos/__init__.py
|
| 25 |
ba094d9eaedd229a99b2bdcd35a371ffdeb9aaee258a342524cc19e2f85ec421 serve/amos/calibrate.py
|
|
@@ -33,7 +34,7 @@ b0523591c320a074a0ec0751b68ebc205aeedd090ff5e7ca10bda3fb94a07ef8 serve/amos/ser
|
|
| 33 |
133d1e29cc64e371f5df1f0cb0328fd77b8b9093d8465319580cf5ea4af5d081 serve/amos/vision.py
|
| 34 |
bea3f98882a5d12c891aae4a5d75eda8c5a5436e88889d94b6a7d3d648d126f2 serve/pyproject.toml
|
| 35 |
0d43aa4e58fe6131f4ed1f4bbcbcaa4a0815f8b1fe5331c7e96489700681136b serve/sources.json
|
| 36 |
-
|
| 37 |
bfe4ef23e8e7bb5041f9e10a769b5c2169b26225ffdd7016e9062c689e593932 text.aimodel/main.hash
|
| 38 |
1c469415a143a1d9d75486ed48dd9b32c1033f1854a6bfc394ae9eb08caa8c72 text.aimodel/main.mlirb
|
| 39 |
a678dc0dcb7ff0a16708ee3e534460d0ba3c0679c9f43fac4c003b4d68d17b35 text.aimodel/metadata.json
|
|
|
|
| 1 |
cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE
|
| 2 |
+
0d23fe60eca8ac2b5bea70064493eb05edd8d4a12ebdeaaa044898368489a7ed README.md
|
| 3 |
9f25e439543c4493b66f609c2a4c57a3d97c11194ac247c3c043f4657725911e SOURCE.json
|
| 4 |
19dd2e174b2f7468407243220912947feb04a9260f347223021f880b532439a1 bf16-attempt.json
|
| 5 |
5865684cabaa8e1a23243db7d9d32569a57c7b5011bf47ed95814b9813af57dd bf16-comparison.json
|
| 6 |
f9ca221eceeea6dc52774885a8c50ad727bb8c269a7ff4fbb439131d2f5be0f2 calibration.json
|
| 7 |
2636cc2d838bc7395655ebb3d2ba933b186a43b13ce134c9a441ee8ba45a9d0d config.json
|
| 8 |
+
910e2baa29daa433c9dbf4120c4848da3898d94ff8a0d899e82484308690d347 convert_decoder.py
|
| 9 |
+
90ac2b10e3cd3bd9e043ba5db597d69fc84c17e0e84bb1014bc97a93d10015e3 coreai_decoder.py
|
| 10 |
3708c801947fd75c057ff534edc404aacb4cc0acc9e653c12f09207e0d848d37 heads.aimodel/main.hash
|
| 11 |
132384c42c3a5c6269a79862d6540a5a6834b532674ba847d83a5b181f85a860 heads.aimodel/main.mlirb
|
| 12 |
3284600a3ad7c8e378bbe228ce3eb967d5da56bb40959aba7e56b177a3fc928a heads.aimodel/metadata.json
|
|
|
|
| 19 |
8c54bd45ef2fc821a711502da04af1bff020fe02c2207117c7ffdbf1866e6e25 model/tokenizer_config.json
|
| 20 |
7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13 model/video_preprocessor_config.json
|
| 21 |
d7910a3390f8073d95908f3301c0ea0e2df4551699546430003bc8226373c2bc qwen_export_helpers.py
|
| 22 |
+
d4e1bf42e2598b84d5800323fdec87fbf338613e8e866e6bb5ce11ed628c8cb2 requirements.txt
|
| 23 |
+
a30fd0562851fa48ecf66caef27326fffd6c66f342dc0a346434e95af3046f46 runtime-smoke.json
|
| 24 |
9e17531efd289cf720a36688d943197f9baf9db7c4f743aa4951f6b6f7dbafda serve/README.md
|
| 25 |
0579eb845ee7af463ec88cf627d99dd636466f2c12d840a7cbe183d8f17044fd serve/amos/__init__.py
|
| 26 |
ba094d9eaedd229a99b2bdcd35a371ffdeb9aaee258a342524cc19e2f85ec421 serve/amos/calibrate.py
|
|
|
|
| 34 |
133d1e29cc64e371f5df1f0cb0328fd77b8b9093d8465319580cf5ea4af5d081 serve/amos/vision.py
|
| 35 |
bea3f98882a5d12c891aae4a5d75eda8c5a5436e88889d94b6a7d3d648d126f2 serve/pyproject.toml
|
| 36 |
0d43aa4e58fe6131f4ed1f4bbcbcaa4a0815f8b1fe5331c7e96489700681136b serve/sources.json
|
| 37 |
+
b9ab562bd0e3f3dd74882b1fe7fd86268c09c75db77a984f56446c21f770b978 smoke_decoder.py
|
| 38 |
bfe4ef23e8e7bb5041f9e10a769b5c2169b26225ffdd7016e9062c689e593932 text.aimodel/main.hash
|
| 39 |
1c469415a143a1d9d75486ed48dd9b32c1033f1854a6bfc394ae9eb08caa8c72 text.aimodel/main.mlirb
|
| 40 |
a678dc0dcb7ff0a16708ee3e534460d0ba3c0679c9f43fac4c003b4d68d17b35 text.aimodel/metadata.json
|
convert_decoder.py
CHANGED
|
@@ -7,12 +7,15 @@ from qwen_export_helpers import DecisionVision
|
|
| 7 |
|
| 8 |
class Text(torch.nn.Module):
|
| 9 |
def __init__(self,model,letters):
|
| 10 |
-
super().__init__();self.language_model=model.model.language_model
|
| 11 |
self.register_buffer('readout',model.get_output_embeddings().weight[letters].detach().float().clone())
|
| 12 |
def forward(self,input_ids,attention_mask,position_ids,visual_embeddings,visual_mask):
|
| 13 |
emb=self.language_model.embed_tokens(input_ids)
|
| 14 |
emb=torch.where(visual_mask,visual_embeddings.to(emb.dtype),emb)
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
| 16 |
return h.float(),h.float()@self.readout.T
|
| 17 |
|
| 18 |
class Heads(torch.nn.Module):
|
|
@@ -41,6 +44,6 @@ def main():
|
|
| 41 |
print('Exporting text',flush=True);outputs=save(Text(model,codec.letters).eval(),inputs,out/'text.aimodel')
|
| 42 |
print('Exporting vision',flush=True);visual=model.model.visual;vo=save(DecisionVision(visual).eval(),(torch.zeros(196,1536),),out/'vision.aimodel')
|
| 43 |
print('Exporting heads',flush=True);ho=save(Heads(heads).eval(),(torch.zeros(d),torch.zeros(L,d),torch.zeros(49,d)),out/'heads.aimodel')
|
| 44 |
-
(out/'manifest.json').write_text(json.dumps({'sequence_length':L,'hidden_size':d,'outputs':outputs,'vision_output':vo[0],'head_outputs':ho,'precision':a.precision,'echo':codec.echo,'kinds':heads.kinds,'keep':heads.keep,'has_box':heads.box is not None,'image_side':224},indent=2))
|
| 45 |
print('Saved',flush=True)
|
| 46 |
if __name__=='__main__':main()
|
|
|
|
| 7 |
|
| 8 |
class Text(torch.nn.Module):
|
| 9 |
def __init__(self,model,letters):
|
| 10 |
+
super().__init__();self.language_model=model.model.language_model;self.noncausal=bool(getattr(model.config,'amos_noncausal',False))
|
| 11 |
self.register_buffer('readout',model.get_output_embeddings().weight[letters].detach().float().clone())
|
| 12 |
def forward(self,input_ids,attention_mask,position_ids,visual_embeddings,visual_mask):
|
| 13 |
emb=self.language_model.embed_tokens(input_ids)
|
| 14 |
emb=torch.where(visual_mask,visual_embeddings.to(emb.dtype),emb)
|
| 15 |
+
mask=attention_mask[:,None,None,:].bool()
|
| 16 |
+
if not self.noncausal:
|
| 17 |
+
width=input_ids.shape[1];idx=torch.arange(width,device=input_ids.device);mask=mask&(idx[:,None]>=idx[None,:])[None,None]
|
| 18 |
+
h=self.language_model(inputs_embeds=emb,attention_mask={'full_attention':mask,'linear_attention':None},position_ids=position_ids,use_cache=False).last_hidden_state
|
| 19 |
return h.float(),h.float()@self.readout.T
|
| 20 |
|
| 21 |
class Heads(torch.nn.Module):
|
|
|
|
| 44 |
print('Exporting text',flush=True);outputs=save(Text(model,codec.letters).eval(),inputs,out/'text.aimodel')
|
| 45 |
print('Exporting vision',flush=True);visual=model.model.visual;vo=save(DecisionVision(visual).eval(),(torch.zeros(196,1536),),out/'vision.aimodel')
|
| 46 |
print('Exporting heads',flush=True);ho=save(Heads(heads).eval(),(torch.zeros(d),torch.zeros(L,d),torch.zeros(49,d)),out/'heads.aimodel')
|
| 47 |
+
(out/'manifest.json').write_text(json.dumps({'sequence_length':L,'hidden_size':d,'outputs':outputs,'vision_output':vo[0],'head_outputs':ho,'precision':a.precision,'echo':codec.echo,'kinds':heads.kinds,'keep':heads.keep,'has_box':heads.box is not None,'image_side':224,'noncausal':bool(getattr(model.config,'amos_noncausal',False))},indent=2))
|
| 48 |
print('Saved',flush=True)
|
| 49 |
if __name__=='__main__':main()
|
coreai_decoder.py
CHANGED
|
@@ -23,6 +23,10 @@ class AmosDecoder:
|
|
| 23 |
|
| 24 |
async def raw(self,state,questions,images=()):
|
| 25 |
from amos.decoder import expand
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
flat,owner=expand(questions)
|
| 27 |
ids,at,extra=self.codec.encode_case(state,flat,images)
|
| 28 |
n=len(ids);L=self.manifest['sequence_length'];d=self.manifest['hidden_size']
|
|
|
|
| 23 |
|
| 24 |
async def raw(self,state,questions,images=()):
|
| 25 |
from amos.decoder import expand
|
| 26 |
+
from PIL import Image
|
| 27 |
+
def resize(im):return im.convert('RGB').resize((224,224),Image.Resampling.BICUBIC)
|
| 28 |
+
images=[resize(im) for im in images]
|
| 29 |
+
questions=[{**q,'options':[resize(o) if isinstance(o,Image.Image) else o for o in q['options']]} if 'options' in q else q for q in questions]
|
| 30 |
flat,owner=expand(questions)
|
| 31 |
ids,at,extra=self.codec.encode_case(state,flat,images)
|
| 32 |
n=len(ids);L=self.manifest['sequence_length'];d=self.manifest['hidden_size']
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
coreai-core==1.0.0b3
|
| 2 |
+
coreai-torch==0.4.3
|
| 3 |
+
torch==2.14.0
|
| 4 |
+
transformers @ git+https://github.com/huggingface/transformers.git@536ecc007387a50e77603bb5d92100e9b07514cc
|
| 5 |
+
numpy==2.4.6
|
| 6 |
+
Pillow==12.3.0
|
| 7 |
+
huggingface_hub==1.33.0
|
| 8 |
+
tokenizers==0.23.3
|
runtime-smoke.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"passed": true,
|
| 3 |
"pytorch_neural_execution_disabled": true,
|
|
|
|
| 4 |
"result": {
|
| 5 |
"answers": {
|
| 6 |
"refund": {
|
|
@@ -8,5 +9,18 @@
|
|
| 8 |
"noul": 0.9714967012405396
|
| 9 |
}
|
| 10 |
}
|
| 11 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"passed": true,
|
| 3 |
"pytorch_neural_execution_disabled": true,
|
| 4 |
+
"capacity_guard": true,
|
| 5 |
"result": {
|
| 6 |
"answers": {
|
| 7 |
"refund": {
|
|
|
|
| 9 |
"noul": 0.9714967012405396
|
| 10 |
}
|
| 11 |
}
|
| 12 |
+
},
|
| 13 |
+
"image_result": [
|
| 14 |
+
{
|
| 15 |
+
"type": "region",
|
| 16 |
+
"cell": 47,
|
| 17 |
+
"box": [
|
| 18 |
+
0.0318,
|
| 19 |
+
0.0241,
|
| 20 |
+
1.0,
|
| 21 |
+
1.0
|
| 22 |
+
],
|
| 23 |
+
"p": 0.9999998807907104
|
| 24 |
+
}
|
| 25 |
+
]
|
| 26 |
}
|
smoke_decoder.py
CHANGED
|
@@ -8,6 +8,12 @@ async def main(name):
|
|
| 8 |
root=Path('bundles')/(name+'-CoreAI');m=await AmosDecoder.load(root)
|
| 9 |
out=await m.request({'state':'Please refund the duplicate charge.','questions':{'refund':{'type':'noul','instructions':'Is a refund requested?'}}})
|
| 10 |
assert out['answers']['refund']['noul']>0.5,out
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
if __name__=='__main__':
|
| 13 |
p=argparse.ArgumentParser();p.add_argument('name');a=p.parse_args();asyncio.run(main(a.name))
|
|
|
|
| 8 |
root=Path('bundles')/(name+'-CoreAI');m=await AmosDecoder.load(root)
|
| 9 |
out=await m.request({'state':'Please refund the duplicate charge.','questions':{'refund':{'type':'noul','instructions':'Is a refund requested?'}}})
|
| 10 |
assert out['answers']['refund']['noul']>0.5,out
|
| 11 |
+
from PIL import Image
|
| 12 |
+
image_result=await m.predict('A red image.',[{'type':'region','text':'Point to the red area.'}],[Image.new('RGB',(360,240),'red')])
|
| 13 |
+
assert image_result[0]['type']=='region'
|
| 14 |
+
try:await m.predict('word '*1000,[{'type':'noul','text':'Is there text?'}])
|
| 15 |
+
except ValueError:capacity_guard=True
|
| 16 |
+
else:raise AssertionError('Over-capacity request was accepted')
|
| 17 |
+
(root/'runtime-smoke.json').write_text(json.dumps({'passed':True,'pytorch_neural_execution_disabled':True,'capacity_guard':capacity_guard,'result':out,'image_result':image_result},indent=2));print(out)
|
| 18 |
if __name__=='__main__':
|
| 19 |
p=argparse.ArgumentParser();p.add_argument('name');a=p.parse_args();asyncio.run(main(a.name))
|