Canonical ID generation in wordlift_sdk.kg_build.id_generator.CanonicalIdGenerator
is policy-driven and supports both graph styles:
- page-centric roots: configured by
IdPolicy.page_root_types(default:WebPage) - entity-centric roots: configured by
IdPolicy.entity_root_types(default:Product,Service,Brand, withFinancialProductnormalized toProduct)
Nodes are no longer considered page roots only because they have schema:url.
Page scope requires explicit page typing/policy membership.
Multi-typed roots are resolved deterministically using
IdPolicy.root_type_precedence. The first matching type in precedence order
selects the canonical container.
Default precedence:
WebPageProductServiceBrandOfferThing
schema:urlvalues are preserved as canonical external URLs.- IRI rewrites do not rewrite object values of
schema:url. - URL-hash suffixing still uses normalized URLs (sorted query parameters) for deterministic IDs.
Media rewrites are constrained:
schema:imagerewrites only typedImageObjectnodes (or already-local dependent nodes).schema:videorewrites only typedVideoObjectnodes (or already-local dependent nodes).- Arbitrary external IRIs referenced by
schema:image/schema:videoare not rewritten into internal dataset IRIs.
Entity-root canonicalization rewrites all linked schema:offers nodes and all
schema:priceSpecification nodes per offer, preserving graph linkage across
rewrites.
For kg_build callback-emitted graphs, canonicalization now applies a fallback
rewrite pass so every non-blank-node subject IRI is canonicalized into
dataset-rooted paths when needed.
- Existing root/dependent canonicalization rules still run first.
- Subjects already under canonical dataset root prefixes are preserved.
- Non-canonical dataset prefixes (for example
/smallpdf/articles/...) are rewritten to canonical dataset container paths. schema:Actiondependent subjects linked from parents viaschema:potentialAction/schema:actionare nested under the canonical parent IRI path (<parent>/actions/<slug>).- Static template graphs are patched through a separate startup path and are not part of callback graph emission rewriting.
Canonical generation can optionally reuse existing root IRIs through a lookup hook:
- context key:
Context.extensions["kg_build.iri_lookup"] - protocol:
IriLookup.iri_for_subject(graph, subject) -> str | None - builtin dataframe implementation:
wordlift_sdk.kg_build.DataFrameUrlIriLookup(url/iricolumns) kg_buildcallback contexts populate this lookup from the callback URL andexisting_web_page_idwhen the URL source already resolved a URL-mapped IRI.
Behavior:
- lookup is applied only to root candidates (first-level URI subjects)
- dependent nodes are not lookup-remapped and still follow canonical parent-nested rewrite rules
- duplicate URL rows in dataframe lookup resolve to the shortest IRI path depth (tie-break: shorter full IRI, then first row order)
- lookup misses fall back to normal canonical ID generation