Skip to content

sessions-graph: extract each session under its user's adopted ontology version - #445

Merged
antejavor merged 2 commits into
mainfrom
feat/431-ontology-versions
Oct 7, 2026
Merged

antejavor merged 2 commits into
mainfrom
feat/431-ontology-versions

Conversation

@antejavor

Copy link
Copy Markdown
Contributor

Stacked on #444, which is stacked on #441. Merge order: #441 → #444 → this. Retarget each one to main after its base merges, before merging it.

Build step 2 of map #431, "An ontology that learns from the user's sessions". This PR adds the version chain and the user-supplied schema path. sessions-graph derive, the step that produces learned versions, comes next.

What

  • Versions in the graph (decided in Grill: how a derivation run aggregates into the previous model #434).
    • One (:OntologyVersion {user_id, version, status, source, derive, model, pinned, source_hash}) node per version, with the model stored as JSON. NEXT chains the versions. (:User)-[:ADOPTED]-> moves to the new version in a single query, so readers never see two adopted versions or none.
    • A uniqueness constraint covers (user_id, version).
    • A user with no stored version is on version 0, hygm.default_model(), which is never stored.
  • Reconcile uses the adopted version. reconcile_session extracts with GLiNER2 over the session user's adopted model, keeping one backend per distinct model, all sharing one loaded checkpoint. It records the version used as Session.ontology_version. An explicit extraction_backend still overrides this; ontology_version is then left null.
  • Supplied schemas (decided in Grill: the default ontology and a user-supplied one #436). supply() turns a schema into the user's next version, with its types pinned:
    • derive="extend" adds the fixed core, and carries forward types derivation learned on the current version, unless one clashes with a supplied label.
    • derive="off" uses the schema exactly as given.
    • Supplied schemas go through validate_model() only.
  • CLI: sessions-graph ontology load --file … [--user] [--derive extend|off] and sessions-graph ontology show [--user]. --user defaults to identity.user_id.
  • Config file: a new [ontology] section with path and derive, set via agent-context-graph config set ontology.path|ontology.derive. It survives config set and bootstrap rewrites, the same way [recall] does.
    • Each sessions-graph reconcile applies the file to the configured user when its content hash or derive mode has changed.
    • A file that fails validation is reported, and the current version is kept.
  • hygm: model_from_mapping / model_to_mapping, split out of ManualStrategy, so a version's JSON goes through the same validation as a YAML file. Error messages for files are unchanged.

One deviation from the decision

#436 wrote the config section as [sessions_graph.ontology]. Here it is [ontology], to match the file's existing flat sections ([recall], [reconcile]). It's easy to rename if you'd rather keep the decision's spelling.

Tests

All run against a real Memgraph:

  • test_e2e_ontology.py (10 tests):
    • a user with no version is on the default;
    • extend adds the core and pins the schema's types; off uses it as given;
    • new versions supersede and chain after the last;
    • an invalid schema writes nothing;
    • sync adopts only on a content or mode change;
    • learned types carry forward unless they clash;
    • the CLI load/show and its no-user error;
    • reconcile applies the configured file and survives a broken one.
  • Reconcile: a session is extracted under the user's supplied version and records ontology_version = 1.
  • Config: [ontology] round-trips through config set, survives bootstrap, and rejects an invalid derive value.
Suite Result
sessions-graph 106 passed
agent-context-graph 165 passed
hygm 43 passed
unstructured2graph 145 passed
context-graph-eval 187 passed

ruff and ty check . are clean. agent-context-graph failed 3 tests once and then passed 9 runs in a row; I couldn't reproduce the failure.

@antejavor

Copy link
Copy Markdown
Contributor Author

Added after this description: hygm.model_from_mapping(..., validate=False). It reads back a store of types that is never extracted against: a derived version's pool of retired relations can name types the pool doesn't hold. Found by a real learned-ontology BEAM run.

@antejavor
antejavor force-pushed the feat/431-ontology-versions branch from 43d3c3b to bfd0f9e Compare October 7, 2026 12:51
@antejavor
antejavor force-pushed the feat/gliner2-default branch from 0ea048c to 4354e48 Compare October 7, 2026 13:02
…y version

- (:OntologyVersion) nodes hold a user's models as JSON, chained by NEXT,
  with (:User)-[:ADOPTED]-> moved in one transaction (#434). A user with no
  version is on version 0, hygm.default_model(). Sessions record the
  ontology_version they were extracted under.
- A supplied schema becomes the next version with its types pinned:
  derive = "extend" adds the fixed core and carries learned types that don't
  clash; "off" uses it as given (#436).
- `sessions-graph ontology load|show`, and reconcile applies the config
  file's [ontology] path to the configured user when its content or derive
  mode changes. A schema that fails validation is reported and the adopted
  version kept.
- agent-context-graph reads [ontology] path/derive, keeps the section across
  config rewrites, and exposes ontology.path/ontology.derive to config set.
- hygm: model_from_mapping/model_to_mapping, split out of ManualStrategy, so a
  version's JSON parses through the same validation as a YAML file.
…isn't extracted against

A pool of retired relations keeps their endpoints, which may name types the
pool doesn't hold, so it fails the model gate; reading an adopted version
back failed with it, and every re-extraction under that version.
@antejavor
antejavor force-pushed the feat/431-ontology-versions branch from bfd0f9e to a232381 Compare October 7, 2026 13:10
@antejavor
antejavor changed the base branch from feat/gliner2-default to main October 7, 2026 13:10
@antejavor antejavor closed this Oct 7, 2026
@antejavor antejavor reopened this Oct 7, 2026
@antejavor
antejavor merged commit 377bd91 into main Oct 7, 2026
34 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant