"Sift the signal from the noise."
🌍 Language: 🇬🇧 English · 🇦🇿 Azərbaycan dili
Sift is a premium, high-speed, and intelligent news search and analysis platform built for the Neurotime Hackathon Challenge. It enables users to perform natural language semantic, keyword, and date-aware search across a dataset of ~20,915 multilingual news articles (Azerbaijani, Russian, and English) from May 10–15, 2026.
Sift features a premium, warm editorial paper design system with displays of Instrument Serif italics, custom hairline borders, a signal accent of orange, and is powered by a hybrid retrieval engine utilizing Supabase (pgvector) and OpenAI APIs.
- Framework: Next.js 15 (App Router, TypeScript strict mode)
- Styling: Tailwind CSS v4 + Framer Motion (Premium micro-animations)
- Database: Supabase (PostgreSQL +
pgvectorextension) - AI Integrations: OpenAI API only
- Embeddings:
text-embedding-3-small(1536-dimensional, cheap and fast) - Reasoning/Chat:
gpt-4o-mini(High intelligence, low-latency, budget-friendly)
- Embeddings:
- Data Parsing:
xlsx(Excel parsing) - Concurrency Control:
p-limit(OpenAI rate-limit protection)
To deliver precise results, Sift combines dense vector retrieval (semantic search) with sparse term matching (keyword search) inside the PostgreSQL engine via a custom Database RPC function (match_articles).
The hybrid score is calculated mathematically as:
Where:
-
Semantic Score: Derived using cosine similarity (calculated as
1 - (embedding <=> query_embedding)). Ranged from-1.0to1.0(typically0.3to0.8for standard matches). -
Keyword Score: Derived using Postgres GIN-indexed full-text search (
ts_rank_cd). The rank is capped at1.0using the SQLleast()function to prevent keyword-stuffing anomalies from overpowering semantic intelligence. -
Weights:
-
$w_{\text{semantic}} = 0.7$ (Focus on conceptual understanding and natural language intent) -
$w_{\text{keyword}} = 0.3$ (Ensures exact names, numbers, or specific words are matched reliably)
-
The RPC also handles optional metadata-level filtering for categories, sources, and date ranges (date-aware retrieval) before computing ranks, making queries extremely fast.
Clone the .env.example file and create .env.local (ensure .env.local is never committed to Git):
cp .env.example .env.localPopulate the following variables:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_public_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_high_privilege_service_role_key
OPENAI_API_KEY=your_openai_api_key
TELEGRAM_BOT_TOKEN=your_telegram_bot_tokenExecute the SQL statements inside supabase_schema.sql within your Supabase SQL Editor. This will:
- Enable the
vectorextension. - Create the
articlestable. - Establish indices for embeddings (
hnswhigh-speed cosine distance), GIN full-text index (search_tsv), category, source, and date indexes. - Establish the automated
tsvectorupdate trigger. - Create the
match_articleshybrid search RPC.
pnpm installPlace news_data.xlsx inside the root directory of this project.
To ingest data, run the TS ingestion script. The script includes automatic batching (100 rows per OpenAI call, 100 rows per Supabase insert) for complete resilience, a rate limit backoff retry handler, a chunked database wipe routine to avoid timeouts, and visual cost/progress tracking.
For a small safe test-run (50 rows):
npx tsx scripts/ingest.ts --limit 50For the full 20,915-row ingestion:
npx tsx scripts/ingest.tsTo wipe existing database rows and re-ingest:
npx tsx scripts/ingest.ts --resetTo run in development mode:
pnpm devTo build and check production compiles:
npx next build-
Multilingual FTS Configuration: PostgreSQL's Full Text Search is configured using the
'simple'dictionary. Because the dataset contains mixed Azerbaijani, Russian, and English articles, a stemmed language-specific index (likeenglishorrussian) would fail to stem Azerbaijani Latin terms correctly. The'simple'configuration splits terms uniformly without language bias, which is highly robust for hybrid searches when paired with semantic vectors. - Category Standardization: Category names are cleaned by removing leading/trailing spaces and collapsing extra space/tab characters. However, overlapping semantic categories (e.g. "Siyasət" and "Politics") are currently treated as separate categories unless unified at query time.
-
OpenAI Cost Limits: Ingesting the full dataset costs less than
$0.15for embeddings (20,915 articles × ~300 tokens each = ~6.3M tokens at$0.02 / 1Mtokens). A telemetric cost report is printed at the end of the ingestion run. -
Excel Date Representation: Ingestion assumes dates in
news_data.xlsxare either standard Excel date numbers or ISO string representations in thecreated_atcolumn, falling back gracefully to the current date if parsing errors are encountered.
Sift features a highly optimized multilingual proper-noun extraction and classification engine that works across Azerbaijani, Russian, and English articles.
- Tokenization: Parses the article title + content, cleans punctuation, and preserves special letters (
ə,ı,ö,ğ,ü,ç,ş+ Cyrillic/English characters). - N-Grams: Extracts both unigrams and bigrams (to catch names like "Mərkəzi Bank" or "İlham Əliyev").
- Multilingual Stopwords: Filters out standard grammar noise across all three languages, plus general numbers and news filler words (e.g.
xəbər,sayt,фото). - Capitalization Boosting: Proper nouns in Azerbaijani, Russian, and English are capitalized. Words or bigram sequences starting with uppercase letters (excluding sentence-starting positions) receive a 2.5x weight boost.
Rather than executing slow, expensive LLM calls for every single article, Sift uses a hybrid frequency + refinement model:
- The fast tokenizer aggregates candidate frequencies across the targeted corpus and selects the top ~80 candidates.
- A single, highly structured JSON call to
gpt-4o-miniis issued to classify these proper nouns into four strict types:ORG(Organization),PERSON(People),LOCATION(Places), orTOPIC(Concepts/Keywords), standardize casing, and merge duplicates (e.g.socarandsocar-ın->SOCAR). - Counts from the tokenizer are mapped back and summed for any merged variations.
- Global View: Precomputes entities across the entire database into
entity_statsusing our CLI script:npx tsx scripts/compute-entities.ts
- Live Search View: Live-tokenizes search results inside
/api/entities/resultusing the fast frequency tokenizer (<10ms), inheriting precomputed types dynamically. - Insights Page (
/insights): A dedicated analytics dashboard presenting precomputed proper-noun cards sorted by type, linking directly back to search on click.
Sift features a fully integrated Telegram Bot built using the Grammy framework. It reuses the core search and entity extraction engines of the platform, enabling users to interact with Sift's ~20,915 articles using plain, natural language.
- Conversational Natural Language Interface:
- No rigid slash-commands are required for searches. Users can type queries in plain language (Azerbaijani, Russian, or English), e.g. "AccessBank news from May 11 to 14" or "What's happening with SOCAR in Russian?".
- A date-aware OpenAI parser interprets the user's intent, isolates dates, categories, and sources, and maps them to fast metadata filters automatically.
- Premium HTML Response Cards:
- Results are styled as highly readable HTML cards in Telegram, containing:
- Clickable headline links.
- Badges for source domains, language, and precise publication times.
- Highly visible relevance percentages (hybrid scores).
- Condensed text snippets (with HTML tags stripped).
- Results are styled as highly readable HTML cards in Telegram, containing:
- Cyberpunk Glassmorphic Inline Buttons:
🏷️ Top entities: Performs live proper-noun tokenization on the retrieved results and lists the top 8 extracted proper nouns and their mention counts instantly (<10ms).📄 More results: Standard pagination is supported. Clicking this button dynamically performs a paginated query and displays results 6–10, 11–15, etc.🔁 New search: Prompts the user on starting a new search inquiry.
- Stateless Pagination Protocol:
- Telegram callback buttons are strictly capped at a 64-byte payload limit. Sift solves this by encoding a regenerative callback pattern (e.g.,
more:1:AccessBankandents:AccessBank), which dynamically re-fetches and tokenizes search results on-click rather than storing heavy state payloads.
- Telegram callback buttons are strictly capped at a 64-byte payload limit. Sift solves this by encoding a regenerative callback pattern (e.g.,
- Open Telegram and search for the official
@BotFather. - Send the
/newbotcommand and follow the instructions to name your bot and choose a username. - BotFather will provide your API Access Token (e.g.
123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ).
Open your .env.local file and add the Telegram Token:
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_hereDuring development or local evaluation, you can launch the bot in long-polling mode. Run the script:
npx tsx scripts/bot.tsThe console will output:
----------------------------------------------------
SIFT TELEGRAM BOT ENGINE
----------------------------------------------------
Starting Sift bot local long-polling...
Telegram Bot Polling has started successfully. Listening for chats...
Now, open Telegram and click Start (or send /start) to begin searching interactively!
For production deployments (e.g. Vercel or custom cloud platforms), Sift includes a built-in webhook receiver route at app/api/telegram/route.ts which uses Grammy's standard HTTP adapter.
- Deploy Sift to your public URL (e.g.
https://sift-neurotime.vercel.app). - Set your Telegram webhook by visiting the following URL in your web browser (replacing
<TOKEN>and<DOMAIN>):https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://<DOMAIN>/api/telegram - Sift will now process all incoming Telegram messages serverlessly!
For a complete, step-by-step 4–5 minute presentation script with exact talking points and emergency backup screenshots, see the DEMO_SCRIPT.md file.
Here is a quick summary of what to demonstrate:
- Brand Impression: Open the homepage. Highlight the elegant warm editorial paper styling, display serif italics, signal orange accents, custom hairline borders, and smooth micro-animations.
- AccessBank (Hybrid Scoring): Search for "AccessBank" to demonstrate hybrid relevance scores (combining cosine vector similarity and PostgreSQL GIN full-text index) and rule-based matching reasons (e.g. Exact text match).
- SOCAR on May 14 (Date-Awareness): Search for "SOCAR news on May 14". Show how the GPT-4o-mini intent-router parses dates dynamically and highlights them in the green Interpretation Pill, filtering results to that exact day.
- Financial Regulation (Semantic Matching): Search for "financial regulation". Prove semantic retrieval by showing how Sift matches articles containing concepts of risk management, banking, and insurance compliance without requiring the literal word "regulation".
- Entity Intelligence: Go to the Insights Page (
/insights) to view precomputed Organizations, People, and Locations. Click "Mərkəzi Bank" to instantly trigger a new semantic search. - Telegram Bot (
@SiftNBot): Send conversational queries to the Grammy-powered bot. Tap🏷️ Top entitiesto calculate real-time frequencies and📄 More resultsto trigger stateless, state-regenerating paginations under Telegram's 64-byte callback limit.