record progress for gifting meetings

This commit is contained in:
2026-02-18 20:04:14 -07:00
parent 3904e22f72
commit 877df0a0b4
2 changed files with 99 additions and 82 deletions
+85 -82
View File
@@ -29,43 +29,43 @@ We want to enhance this process such that the meeting can be an event where atte
_Note: Build and validate core matching algorithms before UI integration_
- [ ] Implement embedding generation function
- [ ] `generateEmbedding(text)` - call OpenAI API to generate embeddings
- [ ] Handle API keys via environment variables
- [ ] Error handling for API failures
- [ ] Unit tests with real profile descriptions
- [ ] Implement pure JavaScript vector math functions
- [ ] `dotProduct(vec1, vec2)` - multiply and sum vector components
- [ ] `magnitude(vec)` - calculate vector length
- [ ] `cosineSimilarity(vec1, vec2)` - measure similarity (0-1 scale)
- [ ] Unit tests for each function with known inputs/outputs
- [ ] Create test profiles with embeddings
- [ ] Profile 1: Sustainable agriculture focus
- [ ] Profile 2: Similar to Profile 1 (should match highly)
- [ ] Profile 3: Software/tech focus (different from 1 & 2)
- [ ] Profile 4: Community organizing (partial overlap with all)
- [ ] Generate real embeddings from descriptions using OpenAI API
- [ ] Verify embeddings are 1536-dimensional vectors
- [ ] Test similarity calculations
- [ ] Verify high similarity (>0.8) between similar profiles
- [ ] Verify low similarity (<0.5) between dissimilar profiles
- [ ] Verify medium similarity for partial overlaps
- [ ] Test with actual embedding vectors (1536 dimensions)
- [ ] Test basic pairing algorithm
- [ ] 4 people → 2 pairs (highest similarities)
- [ ] 6 people → 3 pairs
- [ ] 5 people → 2 pairs + 1 trio (group of 3)
- [ ] Verify pairs have higher similarity than non-pairs
- [ ] Test constraint handling
- [ ] Exclude specific pairs from matching
- [ ] Exclude individuals from matching pool
- [ ] Multiple rounds with no repeated pairs
- [ ] Test edge cases
- [ ] 2 people (minimum viable)
- [ ] 3 people (one trio)
- [ ] All identical profiles (any pairing is equally good)
- [ ] Empty/minimal profile handling
- [ ] Automated Testing
- [x] Implement embedding generation function
- [x] `generateEmbedding(text)` - call OpenAI API to generate embeddings
- [x] Handle API keys via environment variables
- [x] Error handling for API failures
- [x] Unit tests with real profile descriptions
- [x] Implement pure JavaScript vector math functions
- [x] `dotProduct(vec1, vec2)` - multiply and sum vector components
- [x] `magnitude(vec)` - calculate vector length
- [x] `cosineSimilarity(vec1, vec2)` - measure similarity (0-1 scale)
- [x] Unit tests for each function with known inputs/outputs
- [x] Create test profiles with embeddings
- [x] Profile 1: Sustainable agriculture focus
- [x] Profile 2: Similar to Profile 1 (should match highly)
- [x] Profile 3: Software/tech focus (different from 1 & 2)
- [x] Profile 4: Community organizing (partial overlap with all)
- [x] Generate real embeddings from descriptions using OpenAI API
- [x] Verify embeddings are 1536-dimensional vectors
- [x] Test similarity calculations
- [x] Verify high similarity (>0.8) between similar profiles
- [x] Verify low similarity (<0.5) between dissimilar profiles
- [x] Verify medium similarity for partial overlaps
- [x] Test with actual embedding vectors (1536 dimensions)
- [x] Test basic pairing algorithm
- [x] 4 people → 2 pairs (highest similarities)
- [x] 6 people → 3 pairs
- [x] 5 people → 2 pairs + 1 trio (group of 3) _Note: Changed to require even numbers_
- [x] Verify pairs have higher similarity than non-pairs
- [x] Test constraint handling
- [x] Exclude specific pairs from matching
- [x] Exclude individuals from matching pool
- [x] Multiple rounds with no repeated pairs
- [x] Test edge cases
- [x] 2 people (minimum viable)
- [x] 3 people (one trio) _Note: Changed to throw error for odd numbers_
- [x] All identical profiles (any pairing is equally good)
- [x] Empty/minimal profile handling
- [x] Automated Testing
**Validation:** All tests pass showing effective profile matching based on semantic similarity
@@ -138,20 +138,32 @@ npm run test:generate-embeddings
_Note: Profile storage already exists in endorser-ch partner-api as a simple text field_
Phase 1.1:
- [x] Allow users to create labels to attach to their contacts
- [x] The labels can be created on the edit-user screen
- [x] Show the labels on each user on the DID view contact-details screen
- [x] Show the labels at the top of the contacts page, and only show those contacts if the users clicks that label
Phase 1.2:
- [x] Create flag for permissioned profiles
- [x] Allow a back-end (endorser-ch) flag to tag individuals as always generating embedding vectors
- [x] Add an admin user array, set via environment variable or .env file
- [x] Add tests that only allow an admin to set the generateEmbeddings flag. Allow it for a user who has a profile and also for for a user that does not.
- [x] For any admin user, put a button on the DID view contact screen on the front-end (crowd-funder-pwa) that allows the admin user to tag the user DID to always generate embedding vectors
Phase 1.3:
- [ ] Verify existing profile field supports matching use case
- [ ] Confirm profile text field can hold interests, skills, and goals together
- [ ] Check field length limits are adequate for detailed descriptions
- [ ] Create simple profile creation/edit form
- [ ] Single text area for users to describe interests/skills/goals
- [ ] Character limit indicator (if applicable)
- [ ] Connect to existing partner-api endpoints
- [ ] Profile prompt on meeting join
- [ ] Check if attendee has matching-ready profile (has interests)
- [ ] Show profile creation/update modal if needed
- [ ] Allow skipping if not participating in matching
- [ ] Check if attendee has profile
- [ ] Show profile creation/update modal if needed, but allow them to cancel
- [ ] Image prompt on meeting join
- [ ] Show image creation/update modal if needed, but allow them to cancel
Phase 1.4:
- [ ] Display profiles to other attendees
- [ ] Basic read-only profile cards
- [ ] Fetch from partner-api.endorser.ch
- [ ] In the list of attendees, link to profile for each user if it's known
- [ ] Automated Testing
**Validation:** Attendees can see all attendee profiles after they join
@@ -161,22 +173,26 @@ _Note: Profile storage already exists in endorser-ch partner-api as a simple tex
### Phase 2: AI-Powered Profile Matching
**Goal:** Implement core semantic matching algorithm
- [ ] Set up AI/LLM integration
- [ ] Choose LLM provider (OpenAI, Anthropic, etc.)
- [ ] Configure API keys and rate limits
- [ ] Create embeddings service for profile text
- [X] Set up AI/LLM integration
- [X] Use OpenAI with the text-embedding-3-small model
- [X] Configure API keys and rate limits
- [X] Create embeddings service for profile text
- [X] Store in a new partner table named profile_embedding with the profile ID and with the embeddings as a comma-separated vector string
- [X] For anyone with the generateEmbeddings flag on their profile: call to OpenAI to get their embedding vector when the flag is set, and also when a profile with that flag is changed.
- [X] Allow blank value for embedding and hard-code their vector as the "data.empty.embedding" value from the test/embedding-empty-string.json file
- [ ] Implement matching algorithm
- [ ] Generate embeddings for each profile
- [X] Meeting organizer can trigger a pairing session
- [ ] Allow attendees to be excluded
- [ ] Calculate similarity scores between all pairs
- [ ] Create pairing algorithm (maximize total similarity)
- [ ] For an odd number, include 3 people in one of the groups
- [x] Pairing data is saved in the DB
- [x] Calculate similarity scores between all pairs
- [x] Create pairing algorithm (maximize total similarity)
- [ ] Create "do not pair" groups
- [ ] Basic matching endpoint
- [ ] POST endpoint for organizer to trigger matching
- [ ] Return list of pairs with similarity scores
- [ ] Simple results display
- [ ] Show matched pairs to attendees
- [ ] Assign numbers to each pair
- [x] POST endpoint for organizer to trigger matching
- [x] Return list of pairs with similarity scores
- [x] Simple results display
- [x] Show matched pairs to attendees
- [x] Assign numbers to each pair
- [ ] Automated Testing
**Validation:** Organizer can trigger matching, and all attendees can see AI-generated pairs with reasonable similarity
@@ -189,13 +205,13 @@ _Note: Profile storage already exists in endorser-ch partner-api as a simple tex
- [ ] Enhance organizer matching interface
- [ ] Visual display of pairs (cards, grid, or list)
- [ ] Show pair numbers prominently
- [ ] Display similarity reasoning (why these people matched)
- [ ] Create a new screen that lists all the attendees, along with their profile (if it's visible to the organizer) -- truncated, but allowed to be expanded
- [ ] Participant view of matches
- [ ] Show participants their assigned pair
- [x] Show participants their assigned pair
- [ ] Display partner's profile information
- [ ] Show pair number
- [x] Show pair number
- [ ] Real-time updates
- [ ] WebSocket or polling for match announcements
- [x] WebSocket or polling for match announcements
- [ ] Notify participants when matching is triggered
- [ ] Allow easy adding of notes onto the contact of the matched person
- [ ] Allow easy adding of an offer to the matched person
@@ -210,15 +226,14 @@ _Note: Profile storage already exists in endorser-ch partner-api as a simple tex
- [ ] Exclusion groups
- [ ] UI for organizer to select people
- [ ] Create "do not pair" groups
- [ ] Persist exclusion rules across rounds
- [ ] Exclude non-participants
- [ ] Option to mark organizer or others as excluded
- [ ] Ensure excluded people don't appear in matching pool
- [ ] Multiple matching rounds
- [ ] Track previous pairs in meeting state
- [ ] Constraint: don't repeat previous pairs
- [ ] Calculate when no more unique pairs possible
- [x] Track previous pairs in meeting state
- [x] Constraint: don't repeat previous pairs
- [x] Calculate when no more unique pairs possible
- [ ] Show organizer "rounds remaining" indicator
- [ ] Round history
- [ ] Store all previous rounds
@@ -233,13 +248,12 @@ _Note: Profile storage already exists in endorser-ch partner-api as a simple tex
### Phase 5: Post-Event Features and Polish
**Goal:** Enable long-term value and edge case handling
- [ ] Allow a back-end (endorser-ch) flag to mark users with admin permission, so they can tag individuals as always generating embedding vectors
- [ ] Post-event attendee list
- [ ] Persist attendee relationships after meeting deletion
- [ ] Create "past event" view showing all attendees
- [ ] Link to profiles even after event expires
- [ ] Meeting expiration handling
- [ ] Archive meeting data (don't delete attendee info)
- [ ] Maintain contact visibility permissions
- [ ] Archive meeting data on client side
- [ ] Analytics and insights
- [ ] Show match quality scores to organizer
- [ ] Track which pairs connected post-event
@@ -254,7 +268,7 @@ _Note: Profile storage already exists in endorser-ch partner-api as a simple tex
- [ ] Support for very small (2-3 people) or large (50+) groups
- [ ] Handle profile updates mid-matching
- [ ] Performance optimization
- [ ] Cache embeddings to avoid regeneration
- [x] Cache embeddings to avoid regeneration
- [ ] Optimize matching algorithm for large groups
- [ ] Add loading states and progress indicators
- [ ] Automated Testing
@@ -325,14 +339,3 @@ _Note: This is an optional enhancement that could significantly improve onboardi
- Start with greedy pairing (highest similarity pairs first)
- Could evolve to weighted bipartite matching for optimal global solution
- Need to handle constraints efficiently (exclusions, previous pairs)
**Data Model:**
- Profile: `{ userId, description: string, embedding: vector }` (description field already exists in partner-api)
- Meeting: extend to include `{ profileUserIds: string[], rounds: Round[], exclusionGroups: string[][] }`
- Round: `{ number: int, pairs: Pair[], timestamp: datetime }`
- Pair: `{ userIds: [string, string], similarityScore: float, pairNumber: int }`
**Privacy:**
- Attendees should consent to AI processing of their profiles
- Consider allowing profile visibility controls
- Meeting password security for sensitive gatherings is ensured by current features