Skip to content

Semantic entity resolution at 0.85 cosine falsely merges distinct organizations #53

Description

@DarrenZal

Summary

knowledge_router.py:1252 accepts a semantic match at confidence >= 0.85:

if resolved_uri and confidence >= 0.85:

For institutional names — which share heavy lexical and semantic structure (Government of X, Ministry of Y, Canadian Z Association) — 0.85 on text-embedding-3-large is far too permissive. A bulk ingest on 2026-08-24 (279 people, ~1,000 organizations from victoriaforum.ca) produced 28 false merges attributable to that single run, out of 318 semantic resolutions in the window (~9%).

Confirmed false merges

requested name bound to confidence
Government of Singapore government-of-british-columbia
Government of Alberta government-of-british-columbia
Government of Nunavut government-of-british-columbia
Ministry of Foreign Affairs ministry-of-education
Ministry of Energy and Climate Solutions ministry-of-education
Department of National Defence department-of-fisheries-and-oceans
Canadian Bar Association canadian-standards-association
National Bank of Canada national-research-council-canada
University of Texas at Austin university-of-illinois-at-urbana-champaign
Order of St. John order-of-ontario
Global Centre for Pluralism global-centre-of-indigenomics 0.87
David Hughes (Person) david-hutchens 0.94
John Richardson (Person) john-rich 0.92

Elsewhere in the same log window (other ingests): Poland → portland, China → chinatown, Artin → martin, Groupoid → group.

Why it matters

This is silent corruption of pre-existing entities, not just a new-entity naming annoyance.

David Hutchens is a real, distinct person in the graph — author of Circle of the 9 Muses, with his own facts. The 0.94 match dumped 17 facts belonging to David Hughes (President & CEO of Generate Canada, a Victoria Forum speaker) onto him. Nothing surfaced this: the write succeeded, the log line reads like a successful resolution, and both people now read as one.

Same shape for Global Centre for PluralismGlobal Centre of Indigenomics: two unrelated organizations, one of which already carried a real affiliation fact.

Reproduce

grep "multi-tier resolved" <koi stderr log> \
  | grep -oP "resolved '\K[^']+|entity:\K[a-z0-9-]+"

Flag any resolution where the target URI slug shares no distinctive token with the requested name (after stripping stopwords like the/of/university/institute/canadian/government).

Suggested directions

  1. Raise the floor for Organization/Location. These names are compositional; embedding similarity is a poor discriminator. 0.85 is defensible for freeform Concepts, not for institutions.
  2. Gate semantic acceptance behind a lexical check. Require at least one shared distinctive token (or a Jaro-Winkler floor) between requested name and matched name before accepting a tier-2 match. This alone kills every row in the table above.
  3. Treat a numeric/proper-noun mismatch as disqualifyingAlberta vs British Columbia, Singapore vs British Columbia, Texas vs Illinois are distinguishing tokens, not noise.
  4. Log louder. skipped create_new currently reads as success. A resolution that overrode an explicit entity_type hint or matched below a stricter secondary check deserves a WARNING and ideally a review queue.

POST /register-entity with exact_only: true is an effective workaround for callers who know the name is canonical, and was used to repair all 31 bad merges from this run.

Context

Found while indexing victoriaforum.ca into personal-koi. Repair path used: pre-create with exact_only, retract the mis-pointed facts, rewrite so they resolve tier-1 exact.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mo9wkRCWcZJ33k7QWZw5uz

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions