Skip to main content

internal/infra/pg/ontology.go

internal/infra/pg · 102 lines · 3 declarations · source

Declarations

func LoadOntology

func LoadOntology(ctx context.Context, pool *pgxpool.Pool, schema Schema) (domain.Ontology, error)

LoadOntology reads a tenant's relation vocabulary.

Why it is read rather than declared in Go

`fact.predicate` references the `predicate` table, so the database is what actually closes the set. A Go list beside it would be a second definition of a closed set, and the one that drifts is always the one no constraint enforces — at which point the extractor is told a vocabulary the database will refuse, and the failure surfaces as a foreign key violation on a claim that looked fine.

Why per tenant

A tenant is a schema, so the vocabulary is a copy per tenant. That is the cost of the hard boundary, and it is also what makes a tenant-specific vocabulary possible later without changing how anything reads it.

Read once and held, not per extraction: it is forty rows that change when a migration runs.

source

const selectOntologySQL

const selectOntologySQL = `
SELECT predicate, semantic_type, cardinality, object_kind, description, event
FROM {schema}.predicate
ORDER BY predicate`

Ordered by name rather than by insertion, so the list a prompt is built from is the same list on every deployment. A prompt whose vocabulary arrives in a different order is a different prompt, and extraction quality cannot be compared across runs that were not asked the same question.

source

func LoadVocabulary

func LoadVocabulary(ctx context.Context, pool *pgxpool.Pool, schema Schema) (domain.Vocabulary, error)

LoadVocabulary reads both closed sets an extractor needs.

One call rather than two, because they are read together on the same path and a caller that loaded one and forgot the other would get an extractor whose refusals silently stop happening — which looks like the model improving.

source