File size: 11,589 Bytes
1abfa24
 
20ab5a9
 
 
 
 
 
1abfa24
20ab5a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
---
license: apache-2.0
language: en
tags:
  - finance
  - structured-generation
  - rule-based
  - finir
---

# Model Card: FinIR-Intent (baseline v0.1.0)

**This is a deterministic structured-output baseline, not a trained language model.**
It maps a natural-language financial instruction to the canonical **FinIR Intent
Contract** (a versioned JSON envelope) using a fixed, fully offline rule set. There
are no neural weights in this repository.

## What FinIR is

[FinIR](https://github.com/Olyxee/finir) is a financial intermediate representation
and incremental execution runtime for AI systems: a finance-typed computation graph
that is validated, compiled, and evaluated with dependency-aware incremental reuse.
It is published on PyPI (`pip install finir`, runtime `0.1.0`).

## What FinIR-Intent is

FinIR-Intent is the natural-language layer:

```
natural-language financial request  ->  FinIR-Intent  ->  canonical FinIR Intent Contract (v1.0)
```

It performs **no financial computation**. Interpretation and execution are strictly
separated: FinIR-Intent only produces the envelope; the FinIR runtime validates and
executes it (`finir.intent.execute_intent` / `FinancialModel.apply_intent`).

## The problem it solves

Letting an AI system "just compute" a financial what-if invites silently invented
numbers and unit/currency errors. FinIR-Intent constrains the language model's job
to emitting a **typed, validated intent**; the runtime is the single authority on
whether that intent is executable and what it computes. Vague language becomes an
explicit `ambiguous` status instead of a fabricated percentage.

## What it is / is not

- **Is**: a small, dependency-free, offline pattern-matching compiler
  (`src/finir_intent/baseline.py`) — no network, no external LLM/API calls, fully
  reproducible. It implements the same `finir.intent.IntentCompiler` seam a future
  LLM-backed compiler would, so it is a drop-in baseline to measure against.
- **Is not**: a trained/fine-tuned Transformer. Per the workstream brief, "the first
  milestone is not model training… only after the baseline is measured should we
  decide whether fine-tuning a small open model provides a meaningful improvement."
  This baseline exists to make that measurement possible.

## Hugging Face artifact type

Because v0.1.0 ships **code, not weights**, the natural representation is a
**model repository that contains the baseline package plus this card** — a
code/inference repo, not a weight checkpoint. The companion benchmark ships as a
**Datasets** repo, and a **Space** demonstrates the end-to-end flow against the real
runtime. The page makes explicit that this is a baseline compiler, not neural
weights. (See `../release/huggingface/` for the export layout.)

## Schema / runtime compatibility

- **FinIR Intent schema version:** `1.0`
- **Compatible FinIR runtime:** `>=0.1.0,<0.2.0` (verified against the public PyPI
  `finir==0.1.0`)
- **FinIR-Intent baseline version:** `0.1.0`
- The canonical contract is owned by the core `finir` package
  (`finir.intent.json_schema()`, `schemas/finir-intent-v1.schema.json`). This
  package **consumes** it and never redefines it.

## Supported operations

| operation | meaning |
|---|---|
| `relative_change` | `new = current × (1 + value)` (dimensionless decimal; `-0.08` = −8%) |
| `set` | `new = value` (with optional `unit` / `currency`) |
| `absolute_change` | `new = current + value` (with optional `unit` / `currency`) |
| `range` | sweep `target` over `[min, max]` in `steps` (sole op) |
| `scenarios` | named scenarios, each a simultaneous operation set |

## Supported targets

Raw model-input node names (no canonical ontology; alias resolution happens in this
package only, never in the contract): `revenue`, `cogs`, `opex`, `payment_terms`,
`accounts_payable`, `inventory`, `capex`, `debt`, `interest_rate`, `cash`, `price`,
`volume`.

## Ambiguity / unsupported / invalid behavior

- **Ambiguous** — a target with no parseable quantity, or vague language → `status:
  "ambiguous"`, empty operations. **No number is ever invented.** Conflicting
  operations on one target (e.g. "increase revenue by 5% and also cut revenue by
  10%") also map to `ambiguous` rather than silently picking one.
- **Unsupported** — clearly out-of-domain (acquisitions, mergers, hiring/layoffs,
  IPOs/going public, litigation, buybacks, bankruptcy) → `status: "unsupported"`.
- **Invalid (semantic)** — a structurally valid but semantically wrong instruction
  (a currency the target does not use, a `days` unit on a money target) is
  **transcribed faithfully, never "corrected"**; the FinIR runtime rejects it at
  execution. This package performs no semantic check itself (no duplicated execution
  logic).

## Evaluation methodology

Reproduce (deterministic; no network, no LLM):

```bash
pip install finir==0.1.0
cd finir_intent
pip install -e ".[dev]"        # or: PYTHONPATH=src, plus jsonschema
python eval/evaluate.py        # writes eval/results/latest.json
```

`eval/evaluate.py` runs the baseline over every
`intentbench/examples/intentbench_v1.jsonl` example, validates each prediction
against `finir.intent.json_schema()` (the canonical schema), scores it against the
paired **ground-truth** expected intent, and — for every executable prediction —
actually executes it against a small reference `FinancialModel`
(`src/finir_intent/reference_model.py`) via the real `finir.intent.execute_intent`.
Every number below is computed from that run; none is hand-typed.

### Benchmark split (anti-leakage)

FinIR-IntentBench is split into **core** (in-distribution phrasing the rule set is
built to support) and a held-out **stress** subset (paraphrases the baseline was
**not** tuned against — unlisted verbs, fractions, magnitude suffixes, idioms). The
baseline was deliberately **not** modified to pass stress cases, so the stress
numbers are an honest measure of the rule set's real coverage gap, not a tuned
score.

## Evaluation results

Produced by an actual run of `python eval/evaluate.py` on
`intentbench_v1.jsonl` (183 examples: 143 core, 40 stress). Full per-example output,
including every prediction and its execution outcome against the real runtime, is in
`eval/results/latest.json`. **Re-run the command above to reproduce** if the code has
changed.

| metric | overall (n=183) | core (n=143) | stress (n=40) |
|---|---|---|---|
| schema validity | 1.0000 | 1.0000 | 1.0000 |
| status accuracy | 0.9344 | 1.0000 | 0.7000 |
| operation accuracy | 0.9515 | 1.0000 | 0.7500 |
| target accuracy | 0.9515 | 1.0000 | 0.7500 |
| value accuracy | 0.9363 | 1.0000 | 0.5833 |
| unit accuracy | 1.0000 | 1.0000 | 1.0000 |
| currency accuracy | 1.0000 | 1.0000 | 1.0000 |
| ambiguity precision | 0.8409 | 1.0000 | 0.5333 |
| ambiguity recall | 0.9737 | 1.0000 | 0.8889 |
| ambiguity F1 | 0.9024 | 1.0000 | 0.6666 |
| multi-operation exact-match | 0.9000 | 1.0000 | 0.0000 |
| scenario exact-match | 1.0000 | 1.0000 | n/a |
| runtime execution success (executable preds) | 1.0000 | 1.0000 | 1.0000 |
| semantic-rejection correctness | 1.0000 | 1.0000 | 1.0000 |

**Do not read the overall numbers as a headline score.** They are a blend of a
saturated core set and a deliberately hard stress set. The core row shows what the
baseline reliably does; the stress row shows where a fixed rule set breaks.

## Known failure cases (from the stress subset)

Every current stress failure is one of two kinds — and **11 of 12 are conservative
refusals, never an invented number**:

- **Refuses (safe):** `valid → ambiguous` on phrasing outside the rule set —
  fractions/idioms ("Reduce COGS by a fifth", "Double the unit price", "Halve
  inventory"), an unlisted-target reference ("Increase AP by R2,000,000", "Reduce
  the wage bill by 6%"), and an unlisted additive idiom ("Add R5,000,000 to opex").
- **Refuses (safe):** `unsupported → ambiguous` on out-of-domain phrasing the
  vocabulary does not list ("Spin off the retail division", "Issue new equity",
  "Relocate the head office", "Replace the CEO").
- **Value errors (status still valid):** an unlisted direction verb defaults the
  sign to positive ("Slash opex by 12%" is parsed as +12%), and a magnitude suffix
  on a digit is not expanded ("Increase opex by R5m" is parsed as R5, not R5m).
- **The one genuinely unsafe failure:** "Grow cogs by 4% but also reduce cogs by 2%"
  is parsed as a single +4% change because `but also` is not a clause separator, so
  the conflicting second operation is dropped instead of triggering `ambiguous`.
  This is the only stress case where the baseline commits to a number it should have
  refused; it is tracked for a future fix.

## Limitations

This is a fixed rule set — a hand-authored alias table, a small number-word
vocabulary, keyword-anchored regexes — **not** a trained model. Any phrasing outside
what is enumerated in `src/finir_intent/baseline.py` falls back to `ambiguous`
rather than being guessed. It does not handle: fractional/idiomatic magnitudes ("a
fifth", "double", "halve"), magnitude suffixes on digits (`R5m`, `$2m`, `R1.2bn`),
unlisted direction verbs (slash/shave/ramp/shrink…), unlisted target aliases,
period/time scoping (forbidden by the v1.0 contract), or conflicting operations
joined by connectives other than `and`/`,`/`;`. Growing FinIR-IntentBench with new
adversarial paraphrases (as the stress subset does) is the honest way to keep
measuring this gap rather than hide it.

## Fixed parser issues (regression-tested)

- **Word-boundary matching** for direction and unsupported words: naive substring
  checks previously false-positived on ordinary English ("up" inside
  "supplier"/"group" flipped a decrease's sign; "merge" inside "emergency" and "sue"
  inside "issue" misclassified valid instructions as `unsupported`).
- **`set <money-target> to N%`** now refuses (`ambiguous`) instead of silently
  becoming a relative change.
- **Spelled-out numbers** ("five percent", "five million rand") parse via a small
  fixed number-word vocabulary.
- **`trim`/`trims`** added to the down-direction words ("trim cogs by 4 percent" →
  −4%).
- **`boost`/`boosts`, `raises`** added to the up-direction words.
- **Layoff/going-public phrasings with a number or filler between the trigger
  words** ("fire 100 employees", "take the company public") are now correctly
  `unsupported`, anchored to headcount/listing nouns so "fire up the pipeline" is not
  a false positive.

All are covered by unit tests in `tests/test_baseline.py` and by dataset entries.

## License

Apache-2.0, matching the core FinIR repository. The benchmark is entirely synthetic;
no real company or personal data.

## Repository & dependency

- Source & docs: https://github.com/Olyxee/finir (workstream under `finir_intent/`)
- Runtime dependency: `finir>=0.1.0,<0.2.0` — `pip install finir`
- Intent Contract spec: `docs/intent-contract.md`, `docs/huggingface-intent-handoff.md`

## Attribution

The FinIR-Intent Hugging Face workstream (baseline, benchmark, evaluation, Space) was
contributed by **Alisha Fatima** ([@AlishaFatima16](https://github.com/AlishaFatima16)).
The core FinIR runtime and the canonical FinIR Intent Contract are maintained by
Olyxee.


## Links

- **FinIR runtime (PyPI):** https://pypi.org/project/finir/ — `pip install finir`
- **FinIR source (GitHub):** https://github.com/Olyxee/finir
- **FinIR-IntentBench (dataset):** https://huggingface.co/datasets/Olyxee/FinIR-IntentBench
- **FinIR Space (demo):** https://huggingface.co/spaces/Olyxee/FinIR-Intent-Demo