AI Duplicate Event Detection
Problem
Section titled “Problem”ParentConnect lets users submit their own events. The same event frequently gets submitted multiple times — different parents find the same school fair, the same library program, the same weekend festival. Exact title matching doesn’t catch these because each person describes the event differently: “Spring Fair at Lincoln Elementary” vs “Lincoln Elementary’s Annual Spring Festival.”
The system needs to detect semantic duplicates, not just string matches, while handling the fact that the same event name can be legitimate on different dates or in different cities.
Approach
Section titled “Approach”
A Firebase callable Cloud Function runs when a user submits a new event. It takes the event’s title, description, start date, zip code, and state, then checks for duplicates in two phases.
Candidate narrowing
Rather than scanning every event in the database, candidates are narrowed by zip code and date. The date matching is timezone-aware — a state-to-timezone lookup (e.g. NV → America/Los_Angeles, UT → America/Denver) converts the local event date to UTC boundaries using date-fns-tz, ensuring the Firestore query covers the correct UTC day window for that state.
Phase 1: AI semantic similarity
The new event’s title and description are sent to Vertex AI text-embedding-004 to generate an embedding. This is compared against stored embeddings on each candidate event via cosine similarity.
Because candidates are already filtered to the same zip code and date, a match at this stage means the events share both meaning and context. The similarity score gets a +0.15 boost to reflect this location/date alignment, capped at 1.0. Events scoring above the aiSemantic threshold (default 0.75) are flagged as duplicates.
Phase 2: String similarity fallback
If Vertex AI is unavailable — API error, timeout, quota exhaustion — the function falls back to string-based comparison. It runs four methods and takes the highest score:
- Exact match (normalized)
- Containment ratio (shorter string within longer)
- Word overlap (Jaccard coefficient)
- Bigram Dice coefficient (character-level 2-gram similarity)
Title and description are weighted (50% / 30%) with a 20% base for sharing the same zip and date. Events above the stringSimilarity threshold (default 0.3) are flagged.
Response
Each match includes the similarity score and which method detected it (ai_semantic or string_similarity), so the client can communicate confidence to the user. The response also includes aiEnabled: true/false so the admin dashboard can see whether AI was used.
Threshold configuration
Both thresholds are read from a Firestore config document (app_config/main) with a 1-hour in-memory cache. Tuning the sensitivity is a single field update — no deploy needed.
Results
Section titled “Results”- Users get real-time feedback during event submission: “This looks similar to an existing event” — with the matching event shown
- Semantic duplicates are caught even when titles differ significantly (“Kids Art Workshop at the Library” vs “Free Children’s Art Class — Public Library”)
- Timezone-aware date matching prevents false positives between events on different local dates that share a UTC date
- When Vertex AI is down, the system still detects obvious duplicates via string fallback — no outage, just lower accuracy
- Thresholds tuneable live from Firestore without redeployment