jevy-graph 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jevy_graph-0.1.0/.env.example +2 -0
- jevy_graph-0.1.0/.github/workflows/ci.yml +23 -0
- jevy_graph-0.1.0/.github/workflows/release.yml +36 -0
- jevy_graph-0.1.0/.gitignore +15 -0
- jevy_graph-0.1.0/CHANGELOG.md +16 -0
- jevy_graph-0.1.0/LICENSE +21 -0
- jevy_graph-0.1.0/PKG-INFO +253 -0
- jevy_graph-0.1.0/README.md +213 -0
- jevy_graph-0.1.0/demo/app.js +480 -0
- jevy_graph-0.1.0/demo/index.html +54 -0
- jevy_graph-0.1.0/demo/styles.css +238 -0
- jevy_graph-0.1.0/launch/LAUNCH_CHECKLIST.md +47 -0
- jevy_graph-0.1.0/launch/RELEASE_NOTES.md +30 -0
- jevy_graph-0.1.0/pyproject.toml +38 -0
- jevy_graph-0.1.0/scripts/benchmark.py +118 -0
- jevy_graph-0.1.0/src/jevy_graph/__init__.py +13 -0
- jevy_graph-0.1.0/src/jevy_graph/__main__.py +4 -0
- jevy_graph-0.1.0/src/jevy_graph/cli.py +94 -0
- jevy_graph-0.1.0/src/jevy_graph/compiler.py +87 -0
- jevy_graph-0.1.0/src/jevy_graph/config.py +16 -0
- jevy_graph-0.1.0/src/jevy_graph/demo_server.py +200 -0
- jevy_graph-0.1.0/src/jevy_graph/extract.py +2056 -0
- jevy_graph-0.1.0/src/jevy_graph/jev.py +666 -0
- jevy_graph-0.1.0/src/jevy_graph/models.py +51 -0
- jevy_graph-0.1.0/src/jevy_graph/normalize.py +112 -0
- jevy_graph-0.1.0/src/jevy_graph/rdf.py +131 -0
- jevy_graph-0.1.0/src/jevy_graph/structured.py +742 -0
- jevy_graph-0.1.0/tests/__init__.py +0 -0
- jevy_graph-0.1.0/tests/test_compiler.py +65 -0
- jevy_graph-0.1.0/tests/test_demo_server.py +97 -0
- jevy_graph-0.1.0/tests/test_extract.py +97 -0
- jevy_graph-0.1.0/tests/test_jev.py +238 -0
- jevy_graph-0.1.0/tests/test_rdf.py +94 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- run: python -m pip install .
|
|
22
|
+
- run: python -m unittest discover -s tests -q
|
|
23
|
+
- run: printf 'Alice founded Acme.' | jevy-graph --no-verify > /dev/null
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.13"
|
|
18
|
+
- run: python -m pip install --upgrade build
|
|
19
|
+
- run: python -m build
|
|
20
|
+
- uses: actions/upload-artifact@v4
|
|
21
|
+
with:
|
|
22
|
+
name: python-package-distributions
|
|
23
|
+
path: dist/
|
|
24
|
+
|
|
25
|
+
publish:
|
|
26
|
+
needs: build
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
environment: pypi
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/download-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: python-package-distributions
|
|
35
|
+
path: dist/
|
|
36
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-09-22
|
|
4
|
+
|
|
5
|
+
Initial public release.
|
|
6
|
+
|
|
7
|
+
- Deterministic extraction of bounded subject/predicate/object candidates from
|
|
8
|
+
prose, lists, tables, equations, and measurements.
|
|
9
|
+
- Jev-backed candidate selection and independent support and entity-boundary
|
|
10
|
+
verification.
|
|
11
|
+
- Source-grounded RDF/Turtle output with evidence, provenance, polarity, and
|
|
12
|
+
calibrated scores.
|
|
13
|
+
- Dependency-free Python API and CLI.
|
|
14
|
+
- Local streaming graph demo with PDF, DOCX, Markdown, CSV, and text uploads.
|
|
15
|
+
- Cancellation-aware parallel batching and compact processing for large
|
|
16
|
+
documents.
|
jevy_graph-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sai Venna
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: jevy-graph
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small, source-grounded text-to-RDF compiler verified by Jev.
|
|
5
|
+
Project-URL: Homepage, https://github.com/saivivekvenna/jevy-graph
|
|
6
|
+
Project-URL: Issues, https://github.com/saivivekvenna/jevy-graph/issues
|
|
7
|
+
Project-URL: Source, https://github.com/saivivekvenna/jevy-graph
|
|
8
|
+
Project-URL: Changelog, https://github.com/saivivekvenna/jevy-graph/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Sai Venna
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Sai Venna
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: information-extraction,jev,knowledge-graph,rdf
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
38
|
+
Requires-Python: >=3.11
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Jevy Graph
|
|
42
|
+
|
|
43
|
+
[](https://github.com/saivivekvenna/jevy-graph/actions/workflows/ci.yml)
|
|
44
|
+
|
|
45
|
+
Jevy Graph compiles documents into source-grounded RDF. It discovers atomic
|
|
46
|
+
relations locally, asks [Jev](https://typesafe.ai/) to resolve ambiguous entity
|
|
47
|
+
boundaries and predicates, verifies every selected claim, and emits Turtle with
|
|
48
|
+
evidence and provenance.
|
|
49
|
+
|
|
50
|
+
The compiler is designed for high-recall extraction from ordinary prose,
|
|
51
|
+
scientific papers, legal text, tables, measurements, and equations. It does not
|
|
52
|
+
require an ontology or a document-specific schema.
|
|
53
|
+
|
|
54
|
+
## 19-second demo
|
|
55
|
+
|
|
56
|
+
[](https://github.com/saivivekvenna/jevy-graph/blob/main/assets/jevy-graph-launch.mp4)
|
|
57
|
+
|
|
58
|
+
Click the preview for the short version, or watch the
|
|
59
|
+
[full 72-second demo](https://github.com/saivivekvenna/jevy-graph/blob/main/assets/jevy-graph-demo.mp4).
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
- Multiple atomic claims from one sentence, clause, list, or table row
|
|
64
|
+
- Normalized entities and stable predicates without external entity linking
|
|
65
|
+
- Modality, negation, conditions, sections, pages, and evidence spans preserved
|
|
66
|
+
- Jev selection and verification streamed in parallel batches
|
|
67
|
+
- RDF statements with calibrated support and entity-quality scores
|
|
68
|
+
- CLI, Python API, and a real-time Cytoscape demo
|
|
69
|
+
- No runtime Python dependencies
|
|
70
|
+
|
|
71
|
+
## How it works
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
document
|
|
75
|
+
-> deterministic clause, table, equation, and measurement extraction
|
|
76
|
+
-> bounded subject / predicate / object candidates
|
|
77
|
+
-> Jev candidate selection
|
|
78
|
+
-> Jev support and boundary verification
|
|
79
|
+
-> thresholding and deduplication
|
|
80
|
+
-> source-grounded RDF/Turtle
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Jev never invents free-form graph text. It chooses among candidates generated
|
|
84
|
+
from the document, then independently scores the selected relationship. Frames
|
|
85
|
+
with one valid interpretation skip the selection call but are still verified.
|
|
86
|
+
|
|
87
|
+
## Quick start
|
|
88
|
+
|
|
89
|
+
Jevy Graph requires Python 3.11 or newer and a TypeSafe API key.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/saivivekvenna/jevy-graph.git
|
|
93
|
+
cd jevy-graph
|
|
94
|
+
python3 -m venv .venv
|
|
95
|
+
source .venv/bin/activate
|
|
96
|
+
python -m pip install -e .
|
|
97
|
+
cp .env.example .env
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Add your key to `.env`:
|
|
101
|
+
|
|
102
|
+
```dotenv
|
|
103
|
+
TYPESAFE_API_KEY=your-key-here
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Compile UTF-8 text to Turtle:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
jevy-graph document.txt -o graph.ttl
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For a local-only extraction smoke test that does not call Jev:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
printf 'Alice founded Acme. Acme is located in Toronto.' \
|
|
116
|
+
| jevy-graph --no-verify
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Demo
|
|
120
|
+
|
|
121
|
+
The demo accepts PDF, DOCX, Markdown, CSV, and plain-text files. Normal uploads
|
|
122
|
+
stream verified claims as their Jev batches finish. Documents that produce at
|
|
123
|
+
least 2,000 relation frames use larger compute batches and mount the completed
|
|
124
|
+
graph once. Selection and verification overlap across batches; every emitted
|
|
125
|
+
claim still passes both support and entity-boundary checks. Large uploads send
|
|
126
|
+
fixed candidate fields once per question instead of repeating them in every
|
|
127
|
+
option. No candidate options are removed by this encoding.
|
|
128
|
+
|
|
129
|
+
Starting a new upload cancels the previous request. Already running Jev calls
|
|
130
|
+
may finish, but pending batches stop when the server detects the disconnect.
|
|
131
|
+
The final API event includes Jev-reported token usage and request/retry counts.
|
|
132
|
+
|
|
133
|
+
An elapsed timer measures upload through backend completion, excluding final
|
|
134
|
+
graph layout. Hover over an edge or leaf node to read its source text and triple
|
|
135
|
+
in the labeled footer without highlighting or hiding the rest of the graph.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
jevy-graph-demo
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Open <http://localhost:8080/demo/>. PDF support requires `pdftotext`, available
|
|
142
|
+
from Poppler (`brew install poppler` on macOS or `apt install poppler-utils` on
|
|
143
|
+
Debian and Ubuntu).
|
|
144
|
+
|
|
145
|
+
The API key stays on the server and is never sent to the browser.
|
|
146
|
+
|
|
147
|
+
## Python API
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import os
|
|
151
|
+
|
|
152
|
+
from jevy_graph import Thresholds, compile_text
|
|
153
|
+
from jevy_graph.jev import JevClient
|
|
154
|
+
|
|
155
|
+
client = JevClient(os.environ["TYPESAFE_API_KEY"])
|
|
156
|
+
result = compile_text(
|
|
157
|
+
"Alice founded Acme.",
|
|
158
|
+
client=client,
|
|
159
|
+
thresholds=Thresholds(support=0.45, entity=0.10, joint=0.70),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
print(result.turtle)
|
|
163
|
+
print(result.accepted)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Omit `client` for deterministic, unverified extraction.
|
|
167
|
+
|
|
168
|
+
## RDF model
|
|
169
|
+
|
|
170
|
+
Each accepted positive relationship is emitted as a direct semantic edge and
|
|
171
|
+
as an `rdf:Statement` carrying its provenance:
|
|
172
|
+
|
|
173
|
+
```turtle
|
|
174
|
+
<urn:jevy:entity:alice-...> <urn:jevy:relation:founded> <urn:jevy:entity:acme-...> .
|
|
175
|
+
|
|
176
|
+
<urn:jevy:claim:...> a rdf:Statement ;
|
|
177
|
+
rdf:subject <urn:jevy:entity:alice-...> ;
|
|
178
|
+
rdf:predicate <urn:jevy:relation:founded> ;
|
|
179
|
+
rdf:object <urn:jevy:entity:acme-...> ;
|
|
180
|
+
jevy:evidence "Alice founded Acme." ;
|
|
181
|
+
jevy:support "0.950000"^^xsd:decimal ;
|
|
182
|
+
jevy:entityQuality "0.910000"^^xsd:decimal .
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Negative claims are reified with `jevy:polarity "negative"` without asserting
|
|
186
|
+
the positive edge. Numeric values are emitted as typed literals when possible.
|
|
187
|
+
|
|
188
|
+
## Scope
|
|
189
|
+
|
|
190
|
+
The CLI reads UTF-8 text. The demo additionally converts PDF and DOCX uploads.
|
|
191
|
+
The extractor handles ordinary prose, legal lists, scientific sections,
|
|
192
|
+
layout-preserving tables, assignments, equations, and measurements.
|
|
193
|
+
|
|
194
|
+
External knowledge-base linking, ontology alignment, OCR, and scanned PDFs are
|
|
195
|
+
out of scope. Entity normalization is intentionally conservative unless the
|
|
196
|
+
document explicitly declares an alias.
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
python -m unittest discover -s tests -q
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Pull requests should include a focused regression test for behavior changes.
|
|
205
|
+
Keep extraction deterministic and keep API credentials out of fixtures, logs,
|
|
206
|
+
and commits.
|
|
207
|
+
|
|
208
|
+
### Performance checks
|
|
209
|
+
|
|
210
|
+
Use a new process to measure a first upload. No graph layout or browser rendering
|
|
211
|
+
is included; extraction, Jev processing, and final filtering are timed separately.
|
|
212
|
+
The benchmark writes source-grounded claims and metrics to the ignored `out/`
|
|
213
|
+
directory. `--live` makes paid API calls; without it only extraction is measured.
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
PYTHONPATH=src python scripts/benchmark.py document.pdf \
|
|
217
|
+
--live --compact --workers 12 --batch-size 48 --output out/benchmark.json
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Use `--sample 512` for a bounded comparison, or `--reference` to run selection
|
|
221
|
+
for all frames before verification. Frame and candidate hashes allow checking
|
|
222
|
+
that an optimization preserves the entire deterministic candidate set.
|
|
223
|
+
|
|
224
|
+
Measured locally on September 21, 2026 (first upload, Python 3.14):
|
|
225
|
+
|
|
226
|
+
| Document / configuration | Accepted claims | Compute time | Reported input tokens |
|
|
227
|
+
| --- | ---: | ---: | ---: |
|
|
228
|
+
| Odyssey PDF, original implementation | ~5,150 | ~75.3s | Not recorded |
|
|
229
|
+
| Odyssey PDF, pipelined, original question format | 5,164 | 49.1s | 21,417,219 |
|
|
230
|
+
| Odyssey PDF, compact fixed fields and paced requests | 5,123 | 45.3s | 19,178,128 |
|
|
231
|
+
| Constitution PDF, normal streaming configuration | 449 | 3.84s | 1,221,971 |
|
|
232
|
+
|
|
233
|
+
All Odyssey configurations used 14,881 frames. The optimized extractor produced
|
|
234
|
+
identical frame and candidate hashes to the original. The 45.3s run included
|
|
235
|
+
23 rate-limit retries, so network conditions and account limits materially
|
|
236
|
+
affect timing. Model decisions vary between calls: claim counts are a regression
|
|
237
|
+
signal, not proof of complete coverage or correctness. The full uncompressed and
|
|
238
|
+
compact runs shared 3,950 exact claims, so matching volumes should not be read as
|
|
239
|
+
identical outputs. Ten-second processing of
|
|
240
|
+
the full Odyssey has not been demonstrated with verification preserved.
|
|
241
|
+
|
|
242
|
+
## Privacy and security
|
|
243
|
+
|
|
244
|
+
The demo binds to `127.0.0.1` by default and is intended for local use. Document
|
|
245
|
+
text used in Jev decisions is sent to TypeSafe's API. Review TypeSafe's policies
|
|
246
|
+
before processing sensitive material, and add authentication plus upload
|
|
247
|
+
hardening before exposing the demo server publicly.
|
|
248
|
+
|
|
249
|
+
Never commit `.env`; it is ignored by Git.
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Jevy Graph
|
|
2
|
+
|
|
3
|
+
[](https://github.com/saivivekvenna/jevy-graph/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Jevy Graph compiles documents into source-grounded RDF. It discovers atomic
|
|
6
|
+
relations locally, asks [Jev](https://typesafe.ai/) to resolve ambiguous entity
|
|
7
|
+
boundaries and predicates, verifies every selected claim, and emits Turtle with
|
|
8
|
+
evidence and provenance.
|
|
9
|
+
|
|
10
|
+
The compiler is designed for high-recall extraction from ordinary prose,
|
|
11
|
+
scientific papers, legal text, tables, measurements, and equations. It does not
|
|
12
|
+
require an ontology or a document-specific schema.
|
|
13
|
+
|
|
14
|
+
## 19-second demo
|
|
15
|
+
|
|
16
|
+
[](https://github.com/saivivekvenna/jevy-graph/blob/main/assets/jevy-graph-launch.mp4)
|
|
17
|
+
|
|
18
|
+
Click the preview for the short version, or watch the
|
|
19
|
+
[full 72-second demo](https://github.com/saivivekvenna/jevy-graph/blob/main/assets/jevy-graph-demo.mp4).
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- Multiple atomic claims from one sentence, clause, list, or table row
|
|
24
|
+
- Normalized entities and stable predicates without external entity linking
|
|
25
|
+
- Modality, negation, conditions, sections, pages, and evidence spans preserved
|
|
26
|
+
- Jev selection and verification streamed in parallel batches
|
|
27
|
+
- RDF statements with calibrated support and entity-quality scores
|
|
28
|
+
- CLI, Python API, and a real-time Cytoscape demo
|
|
29
|
+
- No runtime Python dependencies
|
|
30
|
+
|
|
31
|
+
## How it works
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
document
|
|
35
|
+
-> deterministic clause, table, equation, and measurement extraction
|
|
36
|
+
-> bounded subject / predicate / object candidates
|
|
37
|
+
-> Jev candidate selection
|
|
38
|
+
-> Jev support and boundary verification
|
|
39
|
+
-> thresholding and deduplication
|
|
40
|
+
-> source-grounded RDF/Turtle
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Jev never invents free-form graph text. It chooses among candidates generated
|
|
44
|
+
from the document, then independently scores the selected relationship. Frames
|
|
45
|
+
with one valid interpretation skip the selection call but are still verified.
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
Jevy Graph requires Python 3.11 or newer and a TypeSafe API key.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git clone https://github.com/saivivekvenna/jevy-graph.git
|
|
53
|
+
cd jevy-graph
|
|
54
|
+
python3 -m venv .venv
|
|
55
|
+
source .venv/bin/activate
|
|
56
|
+
python -m pip install -e .
|
|
57
|
+
cp .env.example .env
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Add your key to `.env`:
|
|
61
|
+
|
|
62
|
+
```dotenv
|
|
63
|
+
TYPESAFE_API_KEY=your-key-here
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Compile UTF-8 text to Turtle:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
jevy-graph document.txt -o graph.ttl
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For a local-only extraction smoke test that does not call Jev:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
printf 'Alice founded Acme. Acme is located in Toronto.' \
|
|
76
|
+
| jevy-graph --no-verify
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Demo
|
|
80
|
+
|
|
81
|
+
The demo accepts PDF, DOCX, Markdown, CSV, and plain-text files. Normal uploads
|
|
82
|
+
stream verified claims as their Jev batches finish. Documents that produce at
|
|
83
|
+
least 2,000 relation frames use larger compute batches and mount the completed
|
|
84
|
+
graph once. Selection and verification overlap across batches; every emitted
|
|
85
|
+
claim still passes both support and entity-boundary checks. Large uploads send
|
|
86
|
+
fixed candidate fields once per question instead of repeating them in every
|
|
87
|
+
option. No candidate options are removed by this encoding.
|
|
88
|
+
|
|
89
|
+
Starting a new upload cancels the previous request. Already running Jev calls
|
|
90
|
+
may finish, but pending batches stop when the server detects the disconnect.
|
|
91
|
+
The final API event includes Jev-reported token usage and request/retry counts.
|
|
92
|
+
|
|
93
|
+
An elapsed timer measures upload through backend completion, excluding final
|
|
94
|
+
graph layout. Hover over an edge or leaf node to read its source text and triple
|
|
95
|
+
in the labeled footer without highlighting or hiding the rest of the graph.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
jevy-graph-demo
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Open <http://localhost:8080/demo/>. PDF support requires `pdftotext`, available
|
|
102
|
+
from Poppler (`brew install poppler` on macOS or `apt install poppler-utils` on
|
|
103
|
+
Debian and Ubuntu).
|
|
104
|
+
|
|
105
|
+
The API key stays on the server and is never sent to the browser.
|
|
106
|
+
|
|
107
|
+
## Python API
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import os
|
|
111
|
+
|
|
112
|
+
from jevy_graph import Thresholds, compile_text
|
|
113
|
+
from jevy_graph.jev import JevClient
|
|
114
|
+
|
|
115
|
+
client = JevClient(os.environ["TYPESAFE_API_KEY"])
|
|
116
|
+
result = compile_text(
|
|
117
|
+
"Alice founded Acme.",
|
|
118
|
+
client=client,
|
|
119
|
+
thresholds=Thresholds(support=0.45, entity=0.10, joint=0.70),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
print(result.turtle)
|
|
123
|
+
print(result.accepted)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Omit `client` for deterministic, unverified extraction.
|
|
127
|
+
|
|
128
|
+
## RDF model
|
|
129
|
+
|
|
130
|
+
Each accepted positive relationship is emitted as a direct semantic edge and
|
|
131
|
+
as an `rdf:Statement` carrying its provenance:
|
|
132
|
+
|
|
133
|
+
```turtle
|
|
134
|
+
<urn:jevy:entity:alice-...> <urn:jevy:relation:founded> <urn:jevy:entity:acme-...> .
|
|
135
|
+
|
|
136
|
+
<urn:jevy:claim:...> a rdf:Statement ;
|
|
137
|
+
rdf:subject <urn:jevy:entity:alice-...> ;
|
|
138
|
+
rdf:predicate <urn:jevy:relation:founded> ;
|
|
139
|
+
rdf:object <urn:jevy:entity:acme-...> ;
|
|
140
|
+
jevy:evidence "Alice founded Acme." ;
|
|
141
|
+
jevy:support "0.950000"^^xsd:decimal ;
|
|
142
|
+
jevy:entityQuality "0.910000"^^xsd:decimal .
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Negative claims are reified with `jevy:polarity "negative"` without asserting
|
|
146
|
+
the positive edge. Numeric values are emitted as typed literals when possible.
|
|
147
|
+
|
|
148
|
+
## Scope
|
|
149
|
+
|
|
150
|
+
The CLI reads UTF-8 text. The demo additionally converts PDF and DOCX uploads.
|
|
151
|
+
The extractor handles ordinary prose, legal lists, scientific sections,
|
|
152
|
+
layout-preserving tables, assignments, equations, and measurements.
|
|
153
|
+
|
|
154
|
+
External knowledge-base linking, ontology alignment, OCR, and scanned PDFs are
|
|
155
|
+
out of scope. Entity normalization is intentionally conservative unless the
|
|
156
|
+
document explicitly declares an alias.
|
|
157
|
+
|
|
158
|
+
## Development
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
python -m unittest discover -s tests -q
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Pull requests should include a focused regression test for behavior changes.
|
|
165
|
+
Keep extraction deterministic and keep API credentials out of fixtures, logs,
|
|
166
|
+
and commits.
|
|
167
|
+
|
|
168
|
+
### Performance checks
|
|
169
|
+
|
|
170
|
+
Use a new process to measure a first upload. No graph layout or browser rendering
|
|
171
|
+
is included; extraction, Jev processing, and final filtering are timed separately.
|
|
172
|
+
The benchmark writes source-grounded claims and metrics to the ignored `out/`
|
|
173
|
+
directory. `--live` makes paid API calls; without it only extraction is measured.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
PYTHONPATH=src python scripts/benchmark.py document.pdf \
|
|
177
|
+
--live --compact --workers 12 --batch-size 48 --output out/benchmark.json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Use `--sample 512` for a bounded comparison, or `--reference` to run selection
|
|
181
|
+
for all frames before verification. Frame and candidate hashes allow checking
|
|
182
|
+
that an optimization preserves the entire deterministic candidate set.
|
|
183
|
+
|
|
184
|
+
Measured locally on September 21, 2026 (first upload, Python 3.14):
|
|
185
|
+
|
|
186
|
+
| Document / configuration | Accepted claims | Compute time | Reported input tokens |
|
|
187
|
+
| --- | ---: | ---: | ---: |
|
|
188
|
+
| Odyssey PDF, original implementation | ~5,150 | ~75.3s | Not recorded |
|
|
189
|
+
| Odyssey PDF, pipelined, original question format | 5,164 | 49.1s | 21,417,219 |
|
|
190
|
+
| Odyssey PDF, compact fixed fields and paced requests | 5,123 | 45.3s | 19,178,128 |
|
|
191
|
+
| Constitution PDF, normal streaming configuration | 449 | 3.84s | 1,221,971 |
|
|
192
|
+
|
|
193
|
+
All Odyssey configurations used 14,881 frames. The optimized extractor produced
|
|
194
|
+
identical frame and candidate hashes to the original. The 45.3s run included
|
|
195
|
+
23 rate-limit retries, so network conditions and account limits materially
|
|
196
|
+
affect timing. Model decisions vary between calls: claim counts are a regression
|
|
197
|
+
signal, not proof of complete coverage or correctness. The full uncompressed and
|
|
198
|
+
compact runs shared 3,950 exact claims, so matching volumes should not be read as
|
|
199
|
+
identical outputs. Ten-second processing of
|
|
200
|
+
the full Odyssey has not been demonstrated with verification preserved.
|
|
201
|
+
|
|
202
|
+
## Privacy and security
|
|
203
|
+
|
|
204
|
+
The demo binds to `127.0.0.1` by default and is intended for local use. Document
|
|
205
|
+
text used in Jev decisions is sent to TypeSafe's API. Review TypeSafe's policies
|
|
206
|
+
before processing sensitive material, and add authentication plus upload
|
|
207
|
+
hardening before exposing the demo server publicly.
|
|
208
|
+
|
|
209
|
+
Never commit `.env`; it is ignored by Git.
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
[MIT](LICENSE)
|