ddupont commited on
Commit
f54adbf
Β·
verified Β·
1 Parent(s): 0134275

Document the safetensors checkpoint as the canonical format; .pt kept as legacy

Browse files
Files changed (1) hide show
  1. README.md +125 -106
README.md CHANGED
@@ -1,106 +1,125 @@
1
- ---
2
- license: mit
3
- tags:
4
- - jev
5
- - system-one
6
- - computer-use
7
- - form-filling
8
- - option-attention
9
- base_model: []
10
- pipeline_tag: other
11
- ---
12
-
13
- # cua-s1-forms
14
-
15
- A small, jev-like ("System One") one-pass option scorer for GUI form filling, trained to
16
- work as the decision layer behind [cua-driver](https://github.com/trycua/cua/tree/main/libs/cua-driver).
17
-
18
- Unlike an autoregressive LLM, this model does not generate text. Given a UI element and a
19
- list of typed options (one option per document entity, plus `check` / `click` / `skip`), it
20
- returns one probability per option in a single forward pass β€” the same input/output
21
- contract as TypeSafe's [Jev](https://typesafe.ai/blog/introducing-system-one-models-and-jev).
22
- Every actionable element on a form is scored independently and in parallel in one batch;
23
- execution order (fills, then checkboxes, then the one submit click) is decided by
24
- downstream code, not the model.
25
-
26
- Full writeup, training code, synthetic data generator and live Cua Driver integration:
27
- https://github.com/trycua/cua/tree/main/libs/cua-s1.
28
-
29
- ## Architecture
30
-
31
- - Byte-level embedding + 2-layer Transformer encoder (width 128, 4 heads) over the context
32
- and, separately, over each option's text
33
- - jevlike's `AttentionHead`: each option becomes a query against the context tokens,
34
- producing an attended context vector, then a shared dot product turns each
35
- (option, attended-context) pair into one logit; softmax over the live option count
36
- - 706,048 trainable parameters, 2.8 MB checkpoint (`state_dict` + `config` + training
37
- history + best validation metrics)
38
-
39
- ## Input / output
40
-
41
- Context (one per element, byte-truncated to 224 bytes):
42
- ```
43
- TASK fill the form from the document, then submit
44
- FORM Northwind Clinic - New Patient Registration
45
- ELEMENT Edit "Phone number" value=""
46
- ```
47
- Options (one per document entity, plus the three fixed actions, byte-truncated to 96 bytes
48
- each): `fill Tel: (503) 555-0142`, `fill DOB: 03/14/1987`, ..., `check`, `click`, `skip`.
49
-
50
- Output: one probability per option. The executor picks the argmax, looks up the entity by
51
- index if the action is `fill`, and orders the resulting actions before sending them to
52
- cua-driver (`set_value` / `click`).
53
-
54
- ## Training
55
-
56
- - 10,000 synthetic episodes (`cua_s1/synth.py`): random form (2–16 fields from a 55-concept
57
- catalogue with form-label/document-label synonyms), random person, random document with
58
- distractor entities and forced look-alike confuser pairs (e.g. `email` vs `street`,
59
- `phone` vs `emergency contact phone`, `state` vs `university`), random window-title
60
- suffixes and 20% title dropout
61
- - Splits are disjoint by exact form field signature β€” a test form's field set never appears
62
- in training
63
- - AdamW, cosine schedule with warmup, 6 epochs, batch size 128, cross-entropy over the live
64
- option count
65
-
66
- ## Results (see the repo's `docs/RESULTS.md` for the full ladder)
67
-
68
- | split | top-1 | notes |
69
- | --- | ---: | --- |
70
- | synthetic test (form-disjoint, ~15k decisions) | 99.95% | hard confuser pairs forced in |
71
- | real demo eval (3 real forms + 3 real PDFs, 196 decisions, nothing synthetic) | 100% | |
72
- | shuffled-context control | 37% | confirms the model reads the element, not option statistics |
73
-
74
- Head-to-head against the real hosted Jev API (`jev-latest`, zero fine-tuning, same task):
75
- 99.7% for this model vs 83.6% for hosted Jev overall; 96% for hosted Jev on decisions that
76
- require real judgment (fill vs check vs click) and 74% on recognizing an already-filled
77
- field as a no-op β€” a convention this model was trained on and hosted Jev was not. Full
78
- numbers in the repo.
79
-
80
- ## Usage
81
-
82
- ```python
83
- import torch
84
- from cua_s1.model import load_checkpoint
85
- from cua_s1.model import select_device
86
-
87
- device = select_device("auto")
88
- model, collator, config = load_checkpoint("cua-s1-forms.pt", device)
89
- ```
90
-
91
- See [`cua_s1/planner.py`](https://github.com/trycua/cua/tree/main/libs/cua-s1/python/src/cua_s1/planner.py)
92
- for the full snapshot β†’ score β†’ order β†’ execute loop against a live Cua Driver session.
93
-
94
- ## Limitations
95
-
96
- - Only ever chooses among entities a PDF/document extractor already found as `Label: value`
97
- pairs; it cannot invent a value.
98
- - Trained entirely on synthetic forms plus a small (196-decision) real eval; not validated
99
- on arbitrary real-world forms outside the demo set.
100
- - Byte-level encoder, English-centric label vocabulary.
101
- - Not calibrated with TypeSafe's RLCD method β€” this is an independent research checkpoint,
102
- not a reproduction of Jev.
103
-
104
- ## License
105
-
106
- MIT.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - jev
5
+ - system-one
6
+ - computer-use
7
+ - form-filling
8
+ - option-attention
9
+ base_model: []
10
+ pipeline_tag: other
11
+ ---
12
+
13
+ # cua-s1-forms
14
+
15
+ A small, jev-like ("System One") one-pass option scorer for GUI form filling, trained to
16
+ work as the decision layer behind [cua-driver](https://github.com/trycua/cua/tree/main/libs/cua-driver).
17
+
18
+ Unlike an autoregressive LLM, this model does not generate text. Given a UI element and a
19
+ list of typed options (one option per document entity, plus `check` / `click` / `skip`), it
20
+ returns one probability per option in a single forward pass β€” the same input/output
21
+ contract as TypeSafe's [Jev](https://typesafe.ai/blog/introducing-system-one-models-and-jev).
22
+ Every actionable element on a form is scored independently and in parallel in one batch;
23
+ execution order (fills, then checkboxes, then the one submit click) is decided by
24
+ downstream code, not the model.
25
+
26
+ Full writeup, training code, synthetic data generator and live Cua Driver integration:
27
+ https://github.com/trycua/cua/tree/main/libs/cua-s1.
28
+
29
+ ## Architecture
30
+
31
+ - Byte-level embedding + 2-layer Transformer encoder (width 128, 4 heads) over the context
32
+ and, separately, over each option's text
33
+ - jevlike's `AttentionHead`: each option becomes a query against the context tokens,
34
+ producing an attended context vector, then a shared dot product turns each
35
+ (option, attended-context) pair into one logit; softmax over the live option count
36
+ - 706,048 trainable parameters, 2.8 MB checkpoint (`state_dict` + `config` + training
37
+ history + best validation metrics)
38
+
39
+ ## Input / output
40
+
41
+ Context (one per element, byte-truncated to 224 bytes):
42
+ ```
43
+ TASK fill the form from the document, then submit
44
+ FORM Northwind Clinic - New Patient Registration
45
+ ELEMENT Edit "Phone number" value=""
46
+ ```
47
+ Options (one per document entity, plus the three fixed actions, byte-truncated to 96 bytes
48
+ each): `fill Tel: (503) 555-0142`, `fill DOB: 03/14/1987`, ..., `check`, `click`, `skip`.
49
+
50
+ Output: one probability per option. The executor picks the argmax, looks up the entity by
51
+ index if the action is `fill`, and orders the resulting actions before sending them to
52
+ cua-driver (`set_value` / `click`).
53
+
54
+ ## Training
55
+
56
+ - 10,000 synthetic episodes (`cua_s1/synth.py`): random form (2–16 fields from a 55-concept
57
+ catalogue with form-label/document-label synonyms), random person, random document with
58
+ distractor entities and forced look-alike confuser pairs (e.g. `email` vs `street`,
59
+ `phone` vs `emergency contact phone`, `state` vs `university`), random window-title
60
+ suffixes and 20% title dropout
61
+ - Splits are disjoint by exact form field signature β€” a test form's field set never appears
62
+ in training
63
+ - AdamW, cosine schedule with warmup, 6 epochs, batch size 128, cross-entropy over the live
64
+ option count
65
+
66
+ ## Results (see the repo's `docs/RESULTS.md` for the full ladder)
67
+
68
+ | split | top-1 | notes |
69
+ | --- | ---: | --- |
70
+ | synthetic test (form-disjoint, ~15k decisions) | 99.95% | hard confuser pairs forced in |
71
+ | real demo eval (3 real forms + 3 real PDFs, 196 decisions, nothing synthetic) | 100% | |
72
+ | shuffled-context control | 37% | confirms the model reads the element, not option statistics |
73
+
74
+ Head-to-head against the real hosted Jev API (`jev-latest`, zero fine-tuning, same task):
75
+ 99.7% for this model vs 83.6% for hosted Jev overall; 96% for hosted Jev on decisions that
76
+ require real judgment (fill vs check vs click) and 74% on recognizing an already-filled
77
+ field as a no-op β€” a convention this model was trained on and hosted Jev was not. Full
78
+ numbers in the repo.
79
+
80
+ ## Files
81
+
82
+ - `cua-s1-forms.safetensors` + `cua-s1-forms.json` β€” the checkpoint in the format
83
+ `cua_s1.checkpoint` expects: tensors only in safetensors, everything else (architecture
84
+ config, a SHA-256 signature over the tensors, free-form metadata) in a plain JSON
85
+ sidecar. This is the format to use; `cua_s1`'s own loader rejects pickled `.pt`/`.pth`
86
+ files by design (arbitrary pickle is a code-execution risk for a public checkpoint).
87
+ - `cua-s1-forms.pt` β€” the original PyTorch pickle checkpoint, kept only for anyone still
88
+ loading it directly with `torch.load(..., weights_only=False)` outside `cua_s1`. New code
89
+ should use the safetensors pair above.
90
+
91
+ Both encode the exact same weights; converted with a script that reimplements
92
+ `cua_s1.checkpoint.save_checkpoint_files`'s exact document/signature format, and verified to
93
+ produce bit-for-bit identical model output against the original `.pt`.
94
+
95
+ ## Usage
96
+
97
+ ```python
98
+ from pathlib import Path
99
+ from huggingface_hub import hf_hub_download
100
+ from cua_s1.model import load_checkpoint, select_device
101
+
102
+ repo = "cua-ai/cua-s1-forms"
103
+ weights = Path(hf_hub_download(repo, "cua-s1-forms.safetensors"))
104
+ hf_hub_download(repo, "cua-s1-forms.json", local_dir=weights.parent) # sits next to the weights
105
+
106
+ # validates format, version and SHA-256 tensor signature before returning
107
+ model, collator, config = load_checkpoint(weights, select_device("auto"))
108
+ ```
109
+
110
+ See [`cua_s1/planner.py`](https://github.com/trycua/cua/tree/main/libs/cua-s1/python/src/cua_s1/planner.py)
111
+ for the full snapshot β†’ score β†’ order β†’ execute loop against a live Cua Driver session.
112
+
113
+ ## Limitations
114
+
115
+ - Only ever chooses among entities a PDF/document extractor already found as `Label: value`
116
+ pairs; it cannot invent a value.
117
+ - Trained entirely on synthetic forms plus a small (196-decision) real eval; not validated
118
+ on arbitrary real-world forms outside the demo set.
119
+ - Byte-level encoder, English-centric label vocabulary.
120
+ - Not calibrated with TypeSafe's RLCD method β€” this is an independent research checkpoint,
121
+ not a reproduction of Jev.
122
+
123
+ ## License
124
+
125
+ MIT.