PhonoCommand-ASR / publish_models.py
humoiww's picture
Publish 20261023-native-r1 asr
f75155d verified
Raw History Blame Contribute Delete
2.41 kB
"""Publisher: upload reviewed staging folders, then atomically publish pair lock.
Authentication: use `hf auth login`; never put a token into this file.
Each folder must contain a complete MANIFEST.json produced for this release.
"""
import argparse
import json
from pathlib import Path
import tempfile
from huggingface_hub import HfApi
from sync_models import read,verify,sha
REPOS={'asr':'humoiww/PhonoCommand-ASR','llm':'humoiww/PhonoCommand-LLM-0.8B'}
def publish(asr,llm,release_id,record):
api=HfApi();lock={'schema':1,'release_id':release_id,'components':{}}
for component,folder in [('asr',Path(asr)),('llm',Path(llm))]:
manifest=read(folder/'MANIFEST.json')
if manifest['release_id']!=release_id:raise ValueError('Release ID mismatch')
verify(folder,manifest['files'])
repo=REPOS[component]
api.create_repo(repo_id=repo,repo_type='model',private=False,exist_ok=True)
if api.model_info(repo).private:raise ValueError('Expected public repository: '+repo)
commit=api.upload_folder(repo_id=repo,folder_path=folder,
allow_patterns=[*manifest['files'],'MANIFEST.json'],
commit_message='Publish '+release_id+' '+component)
lock['components'][component]={'repo_id':repo,'revision':commit.oid,
'manifest_sha256':sha(folder/'MANIFEST.json'),
'files':[*manifest['files'],'MANIFEST.json']}
print(component,commit.oid,flush=True)
# One pointer file changes only after both immutable component uploads pass.
with tempfile.TemporaryDirectory() as temporary:
path=Path(temporary)/'release_set.json';path.write_text(json.dumps(lock,indent=2)+'\n')
commit=api.upload_file(repo_id=REPOS['asr'],path_or_fileobj=path,
path_in_repo='release_set.json',commit_message='Activate paired release '+release_id)
record=Path(record);record.parent.mkdir(parents=True,exist_ok=True)
record.write_text(json.dumps({'lock':lock,'pointer_commit':commit.oid},indent=2)+'\n')
print('Published pair',release_id,flush=True)
return lock
if __name__=='__main__':
p=argparse.ArgumentParser();p.add_argument('--asr',type=Path,required=True)
p.add_argument('--llm',type=Path,required=True);p.add_argument('--release-id',required=True)
p.add_argument('--record',type=Path,required=True)
a=p.parse_args();publish(a.asr,a.llm,a.release_id,a.record)