An intelligent agent that matches Bluesky posts expressing volunteering intent with NYC volunteering opportunities using AI-powered intent detection and local vector embeddings for semantic search.
The latest version uses OpenAI's GPT-4 for intelligent intent detection:
- ๐ง Smart Intent Detection: Uses GPT-4o-mini to analyze batches of posts
- ๐ฏ Semantic Query Extraction: AI extracts the perfect search query from each post
- ๐ฆ Batch Processing: Analyzes 30 seconds of posts at a time for efficiency
- ๐ Local Vector Matching: Uses local embeddings for fast, offline matching
- ๐ฐ Cost Effective: Batching reduces API calls (~$0.001 per 100 posts)
- ๐จ Higher Precision: Better intent detection than keyword matching
Fully offline version with keyword-based detection:
- ๐ Vectorizes opportunities using local AI model (no API needed!)
- ๐ฏ Keyword-based intent detection
- โก Runs completely offline once embeddings are generated
- Node.js 18+ installed
- OpenAI API key (for OpenAI version)
- ~2GB free disk space (for embedding model on first run)
- Install dependencies:
npm install- Configure API key (for OpenAI version):
cp .env.example .envEdit .env and add your OpenAI API key:
OPENAI_API_KEY=your_openai_api_key_here
OpenAI-powered version (recommended):
node volunteer-matcher-openai.jsLocal-only version:
node volunteer-matcher-local.jsFirst run: The agent will download the embedding model (~90MB) and vectorize all opportunities (~30 seconds)
Subsequent runs: Loads vectors from disk instantly (<1 second)
The agent will:
- Load or create local vector database with all 15 opportunities
- Connect to Bluesky Jetstream
- Collect posts in 30-second batches (OpenAI version) or process in real-time (local version)
- Detect volunteering intent (AI or keywords)
- Match posts with relevant opportunities using vector search
- Save matches to
matches.json
.
โโโ volunteer-matcher-openai.js # OpenAI + local vectors (RECOMMENDED)
โโโ volunteer-matcher-local.js # Fully local with keywords
โโโ volunteer-matcher.js # Alternative: Senso API version
โโโ vector-db.js # Local vector database implementation
โโโ jetstream.js # Standalone Jetstream viewer
โโโ volunteering.json # 15 NYC volunteering opportunities
โโโ vector-db.json # Generated: vectorized opportunities
โโโ matches.json # Generated: matched posts
โโโ package.json # Node.js dependencies
โโโ .env # API keys (create from .env.example)
โโโ README.md # This file
Uses Xenova/all-MiniLM-L6-v2 (a lightweight 80MB embedding model) to convert each opportunity into a 384-dimensional vector:
"City Harvest - Food Rescue & Distribution" โ [0.023, -0.145, 0.891, ...]
The vectors capture semantic meaning, allowing similarity matching even when exact keywords don't match.
- Collects all posts from Jetstream for 30 seconds
- Typical batch size: 50-150 posts per batch
- Batches sent to OpenAI for analysis
OpenAI analyzes the entire batch and for each post:
- Detects volunteering intent with confidence score
- Extracts semantic search query optimized for vector matching
- Returns structured JSON with results for all posts
Example OpenAI output:
{
"results": [
{
"post_index": 0,
"has_volunteering_intent": true,
"search_query": "animal shelter dog walking weekend Manhattan",
"confidence": 0.92
}
]
}For posts with detected intent:
- Use the AI-generated search query (not the original post text)
- Generate embedding for the optimized query
- Calculate cosine similarity with all 15 opportunity vectors
- Return top 3 matches sorted by relevance score
Example:
- Post: "I want to help dogs in NYC"
- Top match: "Animal Haven - Dog Walking" (85% similarity)
Matches are saved with complete metadata:
{
"timestamp": "2025-10-04T19:30:00.000Z",
"post": {
"text": "Looking to volunteer with kids in Brooklyn...",
"author_did": "did:plc:abc123...",
"post_uri": "at://did:plc:abc123.../app.bsky.feed.post/xyz",
"post_url": "https://bsky.app/profile/did:plc:abc123.../post/xyz"
},
"matches": [
{
"title": "826 NYC - Writing & Tutoring",
"organization": "826 NYC",
"category": "Education & Youth",
"borough": "Brooklyn",
"relevance_score": 0.72,
"contact": {...}
}
],
"ai_summary": "Based on your interest, here are relevant volunteering opportunities..."
}The dataset includes opportunities across 5 categories:
- Community & Social Services (6 opportunities)
- Education & Youth (4 opportunities)
- Environment & Parks (3 opportunities)
- Animals & Wildlife (2 opportunities)
- Health & Medical (1 opportunity)
Modify volunteering keywords in volunteer-matcher-local.js:
const VOLUNTEERING_KEYWORDS = [
'volunteer', 'volunteering', 'help out',
// Add your own keywords here
];Adjust match limit in vector-db.js:
async search(queryText, topK = 3) { // Change topK for more/fewer matchesForce re-vectorization (if you update volunteering.json):
rm vector-db.json
node volunteer-matcher-local.js๐ค Volunteer Matching Agent Starting...
================================================================================
๐ง Initializing embedding model...
โ
Embedding model ready!
๐ Loading existing vector database...
โ
Loaded 15 opportunities from disk
๐
Last updated: 2025-10-04T19:15:30.000Z
๐ Connecting to Bluesky Jetstream...
๐ Stats will update every 100 posts
================================================================================
๐ Processed 100 posts | Found 0 volunteering posts
๐ Processed 200 posts | Found 0 volunteering posts
================================================================================
๐ฏ VOLUNTEERING INTENT DETECTED!
================================================================================
๐ค Author: did:plc:xyz789...
๐ Post: I'd love to volunteer at an animal shelter this weekend
๐ URI: at://did:plc:xyz789.../app.bsky.feed.post/abc
๐ URL: https://bsky.app/profile/did:plc:xyz789.../post/abc
๐ Searching for: "I'd love to volunteer at an animal shelter this weekend..."
โ
Found 3 matches
๐ก AI Summary:
Based on your interest, here are relevant volunteering opportunities in
Animals & Wildlife. The best match is "ASPCA - Animal Care Assistance"
with ASPCA in Manhattan.
๐ Top Matches:
1. ASPCA - Animal Care Assistance
๐ข ASPCA
๐ Manhattan | Animals & Wildlife
๐ฏ Relevance: 78.2%
โฐ 4 hours per week, 6-month commitment
๐ง volunteer@aspca.org
2. Animal Haven - Dog Walking & Cat Socialization
๐ข Animal Haven
๐ Manhattan | Animals & Wildlife
๐ฏ Relevance: 75.8%
โฐ 2-3 hours per week
๐ง volunteer@animalhavenshelter.org
3. GrowNYC - Community Garden Support
๐ข GrowNYC
๐ All boroughs | Environment & Parks
๐ฏ Relevance: 42.1%
โฐ 2-4 hours, flexible
๐ง volunteer@grownyc.org
================================================================================
"Command not found: node"
- Install Node.js from nodejs.org
"Connection closed"
- The agent auto-reconnects to Jetstream after 5 seconds
- Check your internet connection
Model download is slow
- First run downloads ~90MB model from HuggingFace
- Subsequent runs use cached model (no download needed)
Getting too many false positives
- Adjust the keyword list to be more specific
- Increase minimum relevance score threshold in the code
@xenova/transformers- Local AI embeddings (runs in Node.js, no GPU needed)ws- WebSocket client for Jetstream
Embedding Model: Xenova/all-MiniLM-L6-v2
- 384-dimensional vectors
- Trained on 1 billion sentence pairs
- Optimized for semantic similarity
- Runs entirely locally (CPU-only, no GPU needed)
Vector Database:
- Simple JSON file storage
- Cosine similarity search
- O(n) search complexity (fine for 15 items)
- For larger datasets, consider using a proper vector DB (Pinecone, Qdrant, etc.)
- Automatic reply bot to post opportunities
- User preference tracking
- Geographic filtering (only match with user's borough)
- Schedule-based filtering (match availability)
- Multi-language support
- Web dashboard for matches
- Upgrade to proper vector DB for scale (Qdrant, Weaviate)
- Fine-tune embedding model on volunteering-specific data
MIT
This is a hackathon project. Feel free to fork and improve!
Built with โค๏ธ for connecting volunteers with NYC opportunities