This release is a pre-release and may not be stable for production use.
Context-Fabric
A graph-based corpus engine for annotated text with efficient traversal and search.
Overview
Context-Fabric works with annotated text corpora as graphs: nodes (words, phrases, verses, books, ...) carry feature values, edges relate nodes, and templates search for structural patterns. It reads Text-Fabric datasets and keeps the Text-Fabric API, on a Rust core that serves every query from a memory-mapped compiled cache.
Forked from Dirk Roorda's Text-Fabric.
Installation
pip install context-fabric
Requires Python 3.13 or later. Wheels are built for Linux (x86_64, aarch64), macOS (arm64, x86_64) and Windows (x86_64); other platforms build from the source distribution, which needs a Rust toolchain.
Optional extras:
| Extra | Adds |
|---|---|
context-fabric[numpy] |
NumPy, for F.<feature>.vs_array |
context-fabric[download] |
huggingface_hub, for cfabric.download |
context-fabric[mcp] |
the cfabric-mcp server for AI agents |
context-fabric[benchmarks] |
the cfabric-benchmarks suite |
Quick start
from cfabric import Fabric
CF = Fabric(locations="path/to/tf")
api = CF.loadAll() # or CF.load("sp lex") for selected features
F, L, T, S = api.F, api.L, api.T, api.S
for word in F.otype.s("word")[:5]:
clause = L.u(word, otype="clause")[0]
print(T.sectionFromNode(word), F.sp.v(word), T.text(clause))
for (phrase, word) in S.search("""
phrase function=Pred
word sp=verb
""", limit=5):
print(T.text(phrase))
The first load of a corpus compiles its .tf files into a .cfr cache in
<corpus>/.cfr/4/ (or, when that directory is read-only, under
cfabric.get_cache_dir(): $CFABRIC_CACHE, else the platform cache
directory). Later loads map the cache and are near-instant; the cache is
rebuilt when a .tf file changes or a release changes the cache format.
Core API
- N (Nodes): walk nodes in canonical order
- F (Features): node feature values
- E (Edges): edge feature values
- L (Locality): embedders, embeddees, neighbours of nodes
- T (Text): text formats, sections, structure
- S (Search): search templates
- C (Computed): precomputed data (levels, order, rank, levUp, levDown, ...)
Text-Fabric compatibility
Context-Fabric keeps the tf.core API: Fabric (also importable as
cfabric.fabric.Fabric), the api object with its aliases (Feature, Fs,
AllFeatures, TF, ...), and the F/E/C/L/N/T/S members keep Text-Fabric's
names, signatures, and return types; tests/python/test_tf_api_surface.py
checks this against Text-Fabric 13. Search templates parse as in Text-Fabric,
and .tf files written by TF.save load in Text-Fabric. On BHSA, the 34
reference ETCBC queries return Text-Fabric's result sets.
Differences from Text-Fabric
- Result order: search results come in a deterministic order that can differ from Text-Fabric's (which depends on its search strategy); results match as sets. Within a result tuple, nodes follow the template's atoms.
- Bad search templates raise
cfabric.SearchTemplateError(aValueError) carrying Text-Fabric's messages, where Text-Fabric prints them and returns no results;S.studyrecords them onS.exeas Text-Fabric does. Quantifier sub-templates are checked with the template rather than when the quantifier runs. Regular expressions follow Rust'sregexsyntax (no look-around or backreferences). S.search/S.fetchwithout a limit return a lazySearchResultIteratorwhere Text-Fabric returns a generator; results stop at Text-Fabric's fail limit (4 * maxNode) with its cut-off message as aUserWarning, and Ctrl-C interrupts a running search. A feature repeated within one atom applies every condition (Text-Fabric keeps the last).S.count()returns the count.- Node lists:
N.sortNodes,N.walk(nodes=...)and searchsets=raiseIndexErrorfor a number that is not a node (1tomaxNode). silentand progress options are accepted; only theTF.info/warning/errormessages honorsilent.C.levUp/C.levDownare lazy sequences indexed like Text-Fabric's tuples;row(n)reads one node's row.- Slot and level rows (
E.oslots.s,E.oslots.data,C.levDown.data,C.rank.data) are tuples where Text-Fabric hasarray('I'). T.nodeFromSectionmatches section values regardless of str/int type (Text-Fabric needs the feature's type);T.nodeFromHeadingis type-exact.TF.featuresentries describe the feature files but carry nodata; feature data is read throughF/E/C.- Additions:
F.otype.freqList,E.oslots.f/t/b,E.oslots.dataInv, and the batch callsF.<feature>.vs/vs_array,L.u_many/L.d_many,T.text_many. - Out of scope: volumes/works and MQL.
Performance
Measured on BHSA (Hebrew Bible, 1.4M nodes, 109 features) against Text-Fabric
13.0.19 on the same machine with cfabric_benchmarks.perf_gate
(libs/benchmarks/baselines/cf_0.6.0_record.json and bhsa_tf.json):
| Text-Fabric | Context-Fabric | |
|---|---|---|
| Load (compiled) | 4.3 s | 0.003 s |
| Memory added by loading | 6.1 GB | 8 MB |
| Peak memory after the gate workload | 6.3 GB | 262 MB |
| 12 gate queries, total | 2.36 s | 0.19 s |
| First load (compiles the cache) | ~38 s | ~30 s |
| Cache on disk | 138 MB | 614 MB |
Steady-state latency per call, µs:
| Call | Text-Fabric | Context-Fabric |
|---|---|---|
F.sp.v |
0.064 | 0.028 |
E.mother.f |
0.033 | 0.031 |
E.mother.t |
0.044 | 0.029 |
L.u |
0.115 | 0.144 |
L.d |
0.608 | 0.153 |
L.n / L.p |
0.250 / 0.212 | 0.113 / 0.099 |
L.i |
5.25 | 0.75 |
T.sectionFromNode |
5.68 | 0.51 |
T.text (verse) |
9.35 | 1.64 |
T.nodeFromSection |
0.223 | 0.202 |
L.u and a full N.walk() (17 ms vs 11 ms) build fresh Python ints where
Text-Fabric returns pre-built tuples. Because the corpus stays memory-mapped,
worker processes share its pages instead of each holding a copy, which suits
multi-worker API deployments.
Run the gate (from outside the repository root):
pip install "context-fabric[benchmarks]"
python -m cfabric_benchmarks.perf_gate --engine cf --assert --strict
Versioning
Cargo.toml is the single source of truth for the release version (SemVer, e.g.
0.6.0-rc.1). Maturin publishes the wheel under its PEP 440 rendering (0.6.0rc1;
pyproject.toml declares version as dynamic), and build.rs exports the same
rendering to the Rust core, so cfabric.VERSION, cfabric.__version__, and the
banner always equal importlib.metadata.version("context-fabric"). Bump the
version in Cargo.toml only.
Development
See TESTING.md for building and testing, and the changelog.
Authors
- Cody Kingham
- Dirk Roorda
License
MIT License - see LICENSE for details.
Metadata
Release files for context-fabric 0.6.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| context_fabric-0.6.0rc1.tar.gz | 296.1 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| context_fabric-0.6.0rc1-cp313-abi3-win_amd64.whl | CPython 3.13 | abi3 | Windows x86-64 | Details |
| context_fabric-0.6.0rc1-cp313-abi3-win32.whl | CPython 3.13 | abi3 | Windows x86-32 | Details |
| context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_x86_64.whl | CPython 3.13 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_aarch64.whl | CPython 3.13 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_x86_64.whl | CPython 3.13 | abi3 | macOS 11.0+ x86-64 | Details |
| context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_arm64.whl | CPython 3.13 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 11.5 MB
Release files / context_fabric-0.6.0rc1.tar.gz
| Download URL | context_fabric-0.6.0rc1.tar.gz |
|---|---|
| Size | 296.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
849443c5869063122a4ac173dc807fb3dc8e54d8d05fde5898ea99e387a234a7
|
|
BLAKE2b-256 checksum How to use checksums |
3de7b441cb22094657743acfeb2dacd12d43742b13702ad65bac86e10cc4edc2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-win_amd64.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-win_amd64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.13 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
3a90aabaa11b291e7ad79df8fa6cf49c97ffeb41c2e07872b96f2efc3e26a94a
|
|
BLAKE2b-256 checksum How to use checksums |
3a6d0b3e600aa7c7d82d12f4e0c5d17deac8033d4bf6240660ef6539751b284b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-win32.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-win32.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.13 Windows x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
ee9453c54d4b311f2a0a1d80f0a21193b3ff611aa3da2b2b99cbb9f15f190eb3
|
|
BLAKE2b-256 checksum How to use checksums |
7c0882212498f9ce22548475d9ef31bb42542ec62b80c32c30cdda91720560dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_x86_64.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
f3b541ce488e8ea445bf11d047cba5f112c8635ca03adfab9cef721954c5074d
|
|
BLAKE2b-256 checksum How to use checksums |
78c52c27aa27b1621e12ca1f58abedeb74f1a6955f0c1bb634f5ac0aeb1803d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_aarch64.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
117b0f76d7e47ec26626058a61bf45e4ca0a3c3689b28ded6838e2bced349d7e
|
|
BLAKE2b-256 checksum How to use checksums |
36eb7f931f994ecf56155e002bed5525a851669bec886bc63d9513489eed1b09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_x86_64.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_x86_64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.13 abi3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
3f1eb66827ca7030e943864e73a0d538fe7ef5da64a4f0b263290c15c05d69d5
|
|
BLAKE2b-256 checksum How to use checksums |
1594bc74cafe09d146e9e2d94d04148f3a6cad516b7675f040bd55888cedf3cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_arm64.whl
| Download URL | context_fabric-0.6.0rc1-cp313-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.13 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
83d40ccc4b92c758de9b4afebe1218dfd82b2d0c901929140122b0e18507c064
|
|
BLAKE2b-256 checksum How to use checksums |
15f3d32e490fa1e0f06086df09695df4ce01facd15292872c487ba0b99ff6828
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|