Text Classification
syfox
decision-engine
decision-making
decision-model
structured-prediction
system-one
si-substrate
intent-classification
routing
abstention
uncertainty-quantification
selective-prediction
hebbian
energy-based-model
associative-memory
no-transformer
no-neural-network
no-pattern-matching
moderation
spam-detection
multilingual
Build instructions: BUILDING.md + make sync-so
Browse filesFull build/test/run/rebuild instructions, verified by running each command. Adds a make sync-so target that builds the shared library AND copies it to the repo-root build/ dir the ctypes bridge actually loads -- the stale-library trap that broke from_pretrained is now impossible to miss.
- .gitattributes +0 -5
- BUILDING.md +193 -0
- README.md +12 -0
- engine/Makefile +13 -0
.gitattributes
CHANGED
|
@@ -1,7 +1,2 @@
|
|
| 1 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 2 |
model/*/substrate.bin filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
build/libsyfox_core.so filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
engine/build/libsyfox_core.so filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
engine/build/rebuild_sem filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
engine/build/syfox filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
engine/build/syfox-test filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 2 |
model/*/substrate.bin filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BUILDING.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Building SyFox
|
| 2 |
+
|
| 3 |
+
The decision engine is **C++17 with no runtime dependencies** beyond a C++
|
| 4 |
+
compiler. There is no neural network, no transformer, and no Python needed for
|
| 5 |
+
inference from the CLI.
|
| 6 |
+
|
| 7 |
+
```
|
| 8 |
+
engine/ the C++ SI-substrate core (core/*.hpp + src/*.cpp) + its Makefile
|
| 9 |
+
server/ optional HTTP bridge (FastAPI) and the ctypes bridge
|
| 10 |
+
inference.py thin python wrapper over the bridge
|
| 11 |
+
model/ the fabrics (prebuilt substrates, no training required to use them)
|
| 12 |
+
```
|
| 13 |
+
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
## 1. Build the core
|
| 17 |
+
|
| 18 |
+
```bash
|
| 19 |
+
cd engine
|
| 20 |
+
make all # -> build/syfox, build/syfox-test, build/libsyfox_core.so,
|
| 21 |
+
# build/rebuild_sem
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
Requires `g++` (C++17) and `make`. On Debian/Ubuntu:
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
sudo apt-get install build-essential
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
There is **no top-level `Makefile`** β the `cd engine` is required, not optional.
|
| 31 |
+
|
| 32 |
+
## 2. Run the tests
|
| 33 |
+
|
| 34 |
+
```bash
|
| 35 |
+
cd engine
|
| 36 |
+
make test # builds and runs build/syfox-test
|
| 37 |
+
./build/syfox-test # expected: "all tests passed"
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
## 3. Build the Python bridge library β **read this**
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
cd engine
|
| 44 |
+
make sync-so # builds the .so AND copies it to ../build/
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
`server/syfox_bridge.py` loads the shared library with `ctypes` from the
|
| 48 |
+
**repo-root** `build/` directory:
|
| 49 |
+
|
| 50 |
+
```python
|
| 51 |
+
_LIB = ... / "build" / "libsyfox_core.so" # NOT engine/build/
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
So if you only run `make all`, the CLI and the test suite pass while
|
| 55 |
+
`from inference import SyFox` fails with:
|
| 56 |
+
|
| 57 |
+
```
|
| 58 |
+
AttributeError: ... undefined symbol: syfox_engine_set_semantics
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
That happens because the bridge keeps loading an **older** `build/` copy that
|
| 62 |
+
happens to be present. A prebuilt `build/libsyfox_core.so` ships in this repo,
|
| 63 |
+
so it will look like everything works β right up until it silently uses the
|
| 64 |
+
stale core. `make sync-so` exists so this cannot be forgotten.
|
| 65 |
+
|
| 66 |
+
For a clean environment, delete it first so the failure is loud:
|
| 67 |
+
|
| 68 |
+
```bash
|
| 69 |
+
rm -f build/libsyfox_core.so && cd engine && make sync-so
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
## 4. Optional: OpenMP build
|
| 73 |
+
|
| 74 |
+
Parallel settle, deterministic by construction (fixed reduction order) and
|
| 75 |
+
bit-identical to the sequential build:
|
| 76 |
+
|
| 77 |
+
```bash
|
| 78 |
+
cd engine && make build/syfox-omp
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
## 5. Run it
|
| 82 |
+
|
| 83 |
+
**CLI** β no Python needed:
|
| 84 |
+
|
| 85 |
+
```bash
|
| 86 |
+
./engine/build/syfox stats --model model/sst2
|
| 87 |
+
|
| 88 |
+
./engine/build/syfox decide --model model/sst2 \
|
| 89 |
+
--state "a hollow, inert picture that never risks anything" \
|
| 90 |
+
--questions '{"q":{"type":"choice","instructions":"sentiment",
|
| 91 |
+
"criteria":{"negative":"negative","positive":"positive"}}}'
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
Every response carries `choice`, `confidence`, `deferred`, `probabilities`, and
|
| 95 |
+
a `reason` when it abstains. **`deferred: true` is the engine declining to
|
| 96 |
+
answer, not an error** β see [Abstention](#abstention-is-a-feature).
|
| 97 |
+
|
| 98 |
+
**Python**:
|
| 99 |
+
|
| 100 |
+
```bash
|
| 101 |
+
pip install fastapi uvicorn # only needed for the HTTP server
|
| 102 |
+
python -c "
|
| 103 |
+
from inference import SyFox
|
| 104 |
+
m = SyFox()
|
| 105 |
+
r = m.decide('I was charged twice on my last invoice, please refund.')
|
| 106 |
+
print(r['answers']['domain'])"
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
**HTTP server** (the HuggingFace Spaces entrypoint):
|
| 110 |
+
|
| 111 |
+
```bash
|
| 112 |
+
python server/app.py --model model/giant --lang auto --energy-norm \
|
| 113 |
+
--host 0.0.0.0 --port 7860
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
## 6. Docker / Spaces
|
| 117 |
+
|
| 118 |
+
The `Dockerfile` builds the core in a throwaway stage and copies only the
|
| 119 |
+
stripped `.so` into a slim runtime image β it handles the `sync-so` step for
|
| 120 |
+
you. It serves on port **7860**, which Spaces expects.
|
| 121 |
+
|
| 122 |
+
```bash
|
| 123 |
+
docker build -t syfox .
|
| 124 |
+
docker run -p 7860:7860 syfox
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
## 7. Retraining a fabric
|
| 128 |
+
|
| 129 |
+
Not needed to *use* the models. To train your own:
|
| 130 |
+
|
| 131 |
+
```bash
|
| 132 |
+
./engine/build/syfox learn --model my-model --examples train.jsonl \
|
| 133 |
+
--energy-norm --ngrams on
|
| 134 |
+
./engine/build/syfox calibrate --model my-model --examples cal.jsonl \
|
| 135 |
+
--energy-norm --ngrams on
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
+
Always calibrate on a split the model never trained on, and score **once** on a
|
| 139 |
+
held-out split. Fabric size grows with lesson count: ~4,200 rows β ~78k nodes /
|
| 140 |
+
~949k lanes / ~23 MB.
|
| 141 |
+
|
| 142 |
+
### Admission gate
|
| 143 |
+
|
| 144 |
+
A model should be checked on handcrafted novel questions before publishing,
|
| 145 |
+
because held-out accuracy shares its generator with training and rewards
|
| 146 |
+
memorising n-grams:
|
| 147 |
+
|
| 148 |
+
```bash
|
| 149 |
+
python tools/novel_gate.py --sweep path/to/candidate/dir
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
Probes live in `datasets/novel_probes/`. A model is admitted only if it clears
|
| 153 |
+
both the majority baseline and uniform chance + 0.15, with no single class
|
| 154 |
+
answering more than 60% of probes.
|
| 155 |
+
|
| 156 |
+
---
|
| 157 |
+
|
| 158 |
+
## Platform support
|
| 159 |
+
|
| 160 |
+
**The prebuilt `build/libsyfox_core.so` is linux-x86_64.** On macOS or ARM
|
| 161 |
+
(Apple Silicon, ARM servers) it will not load β rebuild instead:
|
| 162 |
+
|
| 163 |
+
```bash
|
| 164 |
+
cd engine && make clean && make sync-so
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
That produces a library for *your* machine. Do not ship it to users on other
|
| 168 |
+
platforms; the repository copy is a convenience for linux-x86_64 only.
|
| 169 |
+
|
| 170 |
+
## Troubleshooting
|
| 171 |
+
|
| 172 |
+
| symptom | cause | fix |
|
| 173 |
+
|---|---|---|
|
| 174 |
+
| `undefined symbol: syfox_engine_set_*` on import | bridge loaded a stale `.so` | `cd engine && make sync-so` |
|
| 175 |
+
| `command not found: make` | no toolchain | `apt-get install build-essential` |
|
| 176 |
+
| `make: *** No rule to make target` | wrong directory | you are in the repo root, not `engine/` |
|
| 177 |
+
| CLI and tests pass but Python fails | see row 1 | stale `.so` |
|
| 178 |
+
| every answer has `deferred: true` | honesty gate firing, working as designed | inspect `reason` in the response |
|
| 179 |
+
|
| 180 |
+
## Abstention is a feature
|
| 181 |
+
|
| 182 |
+
SyFox returns `deferred: true` with a `reason` rather than guessing. Reported
|
| 183 |
+
accuracy is always meaningless without the paired defer rate β the honest
|
| 184 |
+
metric is `accuracy Γ answered/total`. See
|
| 185 |
+
[docs/HONEST_TOTAL.md](../docs/HONEST_TOTAL.md) in the upstream project for the
|
| 186 |
+
protocol, and `docs/ENGINE_PORT.md` for what changed in the v3.9.1 port.
|
| 187 |
+
|
| 188 |
+
## Related
|
| 189 |
+
|
| 190 |
+
- [`docs/ENGINE_PORT.md`](ENGINE_PORT.md) β the v3.2.0 β v3.9.1 port, ABI
|
| 191 |
+
verification, and the stale-numbers caveat
|
| 192 |
+
- [`docs/EVALUATION.md`](EVALUATION.md) β measured evaluation
|
| 193 |
+
- [`docs/ZEROSHOT.md`](ZEROSHOT.md) β zero-shot and coverage probes
|
README.md
CHANGED
|
@@ -154,6 +154,18 @@ examples/ JSON payloads + curl + python usage
|
|
| 154 |
Dockerfile HuggingFace Spaces (builds engine, serves on 7860)
|
| 155 |
```
|
| 156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
## Usage (python)
|
| 158 |
|
| 159 |
```python
|
|
|
|
| 154 |
Dockerfile HuggingFace Spaces (builds engine, serves on 7860)
|
| 155 |
```
|
| 156 |
|
| 157 |
+
## Build
|
| 158 |
+
|
| 159 |
+
```bash
|
| 160 |
+
cd engine && make all && make sync-so && cd ..
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
`make sync-so` is **required** for the Python bridge: it loads
|
| 164 |
+
`build/libsyfox_core.so` from the **repo root**, not `engine/build/`, so a
|
| 165 |
+
plain `make all` leaves a stale library in place and `from inference import
|
| 166 |
+
SyFox` fails with `undefined symbol`. Full instructions, Docker, retraining
|
| 167 |
+
and troubleshooting: **[BUILDING.md](BUILDING.md)**.
|
| 168 |
+
|
| 169 |
## Usage (python)
|
| 170 |
|
| 171 |
```python
|
engine/Makefile
CHANGED
|
@@ -5,6 +5,19 @@ BUILD := build
|
|
| 5 |
|
| 6 |
all: build/syfox build/syfox-test build/libsyfox_core.so build/rebuild_sem
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
build:
|
| 9 |
mkdir -p build
|
| 10 |
|
|
|
|
| 5 |
|
| 6 |
all: build/syfox build/syfox-test build/libsyfox_core.so build/rebuild_sem
|
| 7 |
|
| 8 |
+
# Copy the shared library to the REPO-ROOT build/ dir, which is where
|
| 9 |
+
# server/syfox_bridge.py looks for it (ctypes: ../build/libsyfox_core.so).
|
| 10 |
+
# Skipping this is the single most common setup failure: the CLI and the tests
|
| 11 |
+
# pass, then `from inference import SyFox` dies with
|
| 12 |
+
# undefined symbol: syfox_engine_set_*
|
| 13 |
+
# because the bridge silently keeps loading a stale core.
|
| 14 |
+
sync-so: build/libsyfox_core.so
|
| 15 |
+
mkdir -p ../build
|
| 16 |
+
cp $< ../build/libsyfox_core.so
|
| 17 |
+
@echo "synced -> ../build/libsyfox_core.so"
|
| 18 |
+
|
| 19 |
+
.PHONY: sync-so
|
| 20 |
+
|
| 21 |
build:
|
| 22 |
mkdir -p build
|
| 23 |
|