Spaces:
Running
Running
Download code/exporters_edit.py from ArthurZ/transformers-triage: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/spaces/ArthurZ/transformers-triage/resolve/main/code/exporters_edit.py
- Command line
-
hf download hf://spaces/ArthurZ/transformers-triage/code/exporters_edit.py
-
curl -L -o exporters_edit.py https://huggingface.co/spaces/ArthurZ/transformers-triage/resolve/main/code/exporters_edit.py
4.53 kB
| import json, re, subprocess, sys | |
| DOC = 'https://huggingface.co/docs/transformers/main/en/exporters' | |
| EXP = f'`transformers.exporters` ({DOC})' | |
| TARGETS = {9784:'issue',12851:'issue',18243:'issue',22221:'issue',22756:'issue',33184:'issue',41838:'issue', | |
| 28781:'issue',29288:'issue',31962:'issue',38917:'issue',40260:'issue',29315:'pr'} | |
| SUBS = [ # (regex, replacement) applied in order | |
| (r'ONNX export (now )?lives in \[Optimum\]\(https://huggingface\.co/docs/optimum/exporters/onnx/overview\)( \(`optimum-cli export onnx --model <id> out/`\))?', f'Export (ONNX included) now goes through [`transformers.exporters`]({DOC})'), | |
| (r'ONNX export is now handled by Optimum \(https://huggingface\.co/docs/transformers/main/en/exporters\)', f'export is now handled by {EXP}'), | |
| (r'(ONNX )?export (is handled by|now lives in) Optimum( now)?', f'export now goes through {EXP}'), | |
| (r'These ONNX exports are used by Transformers\.js / Optimum, so follow-ups belong there\.', f'For exporting, see {EXP}.'), | |
| (r'see the wrappers in `src/transformers/integrations/executorch\.py` as noted above, or Optimum for ONNX', f'see {EXP}'), | |
| (r'exporting to ONNX \(via Optimum\)', f'exporting to ONNX with {EXP}'), | |
| (r'export now goes through torch\.export / optimum', f'export now goes through {EXP}'), | |
| (r'For export, `torch\.export` is the recommended path now\.', f'For export, use {EXP}.'), | |
| (r'For graph capture, `torch\.export` / `torch\.compile` are the supported paths now\.', f'For export, use {EXP}; `torch.compile` covers graph capture for speed.'), | |
| (r'For tracing/export, use `torch\.export` with the static cache', f'For export, use {EXP} with the static cache'), | |
| ] | |
| POINTER = { | |
| 18243: f"The `transformers.onnx` exporter was removed in #41700; export (ONNX included) now goes through {EXP}. Closing; if LongT5 export still fails with `transformers.exporters` on current `main`, please open a new issue with a reproducer.", | |
| 22221: f"This isn't a model request: export (ONNX included) now goes through [`transformers.exporters`]({DOC}). To get separate encoders, export `CLIPTextModelWithProjection` and `CLIPVisionModelWithProjection` on their own.", | |
| 38917: f"On `main`, the new {EXP} API (#41992) is the recommended way to do this: its exporters take forward kwargs including `past_key_values` (a `Cache`) as example inputs, and there is an ONNX backend in `src/transformers/exporters/exporter_onnx.py`. If something is still missing for your use case, a PR extending the exporters would be very welcome (see https://huggingface.co/docs/transformers/main/en/exporters_extend).", | |
| 40260: f"On `main`, export goes through {EXP} (#41992), which supports dynamic shapes; extending it is documented at https://huggingface.co/docs/transformers/main/en/exporters_extend. The legacy helpers in `integrations/executorch.py` are not where new export work should go.", | |
| } | |
| MARK = re.compile(r'(?i)optimum|torch\.export|executorch') | |
| def ours(kind, n): | |
| q = '{repository(owner:"huggingface",name:"transformers"){issueOrPullRequest(number:%d){... on Issue{comments(last:40){nodes{databaseId author{login} createdAt body}}} ... on PullRequest{comments(last:40){nodes{databaseId author{login} createdAt body}}}}}}' % n | |
| r = json.loads(subprocess.run(['gh','api','graphql','-f','query='+q], capture_output=True, text=True).stdout) | |
| return [c for c in r['data']['repository']['issueOrPullRequest']['comments']['nodes'] if (c['author'] or {}).get('login') == 'ArthurZucker' and c['createdAt'] >= '2026-10-20' and MARK.search(c['body'])] | |
| plan = [] | |
| for n, kind in TARGETS.items(): | |
| cs = ours(kind, n) | |
| if not cs: print(f'#{n}: NO matching comment of ours'); continue | |
| c = cs[-1]; body = c['body'] | |
| if n in POINTER: new = POINTER[n] | |
| else: | |
| new = body | |
| for rx, rep in SUBS: new = re.sub(rx, rep, new) | |
| if new == body or re.search(r'(?i)optimum', new): print(f'#{n}: UNCHANGED or still mentions optimum →', body[:160].replace('\n',' ')); continue | |
| plan.append(dict(n=n, id=c['databaseId'], old=body, new=new)) | |
| json.dump(plan, open('exporters_plan.json','w'), indent=1) | |
| print('planned edits:', len(plan)) | |
| for p in plan: print(f"--- #{p['n']}\n{p['new'][:330]}") | |
| if '--apply' in sys.argv: | |
| for i, p in enumerate(plan, 1): | |
| r = subprocess.run(['gh','api','-X','PATCH',f"repos/huggingface/transformers/issues/comments/{p['id']}",'-f','body='+p['new']], capture_output=True, text=True) | |
| print(f"[{i}/{len(plan)}] #{p['n']} {'ok' if r.returncode==0 else 'FAIL '+r.stderr[:120]}", flush=True) | |