How it works

Hawker is an AI-powered news search engine that crawls RSS feeds, filters for AI-related content, embeds articles into vector space, and ranks results using a composite of semantic similarity, freshness, and keyword density.

The Pipeline

1

Crawl RSS Feeds

Fetches articles from 24 curated RSS feeds spanning research labs (OpenAI, DeepMind, Meta AI), developer blogs (Hugging Face, PyTorch), AI newsletters, and tech publications (TechCrunch, MIT News, Wired).

Each feed is parsed with feedparser, then full article text is extracted using newspaper3k with 8 parallel workers. Articles older than 7 days and those that have been crawled in previous runs are dropped before extraction to save bandwidth.

2

AI Keyword Filter

Each article is scored against a curated list of ~50 AI-related terms (machine learning, LLM, transformer, computer vision, etc.). Articles matching at least one keyword pass through.

The keyword score — ratio of distinct matched terms to total terms — is saved and later used as one of three ranking signals. Typical pass rate is ~70%.

3

Named Entity Recognition (NER)

Extracts key entities (PERSON, ORG, GPE) using spaCy's en_core_web_sm model from the cleaned article text.

Entities are stored as tags, allowing us to identify the main actors in every story (e.g., 'Sam Altman', 'Google', 'NVIDIA') and use them for topic labeling.

4

Embed & Cluster

Articles are converted into 384-dim vectors with MiniLM-L6-v2 and grouped into clusters using scikit-learn's K-Means.

Clustering groups semantically similar stories into 'Trending Topics'. Topics are dynamically labeled by looking at the most frequent entities inside each cluster.

5

Store in PostgreSQL + pgvector

Normalized embeddings and topic associations are stored in PostgreSQL using the pgvector extension with an HNSW index.

The system supports both vector searching (for queries) and relational filtering (for topic chips), combined into a single performant pipeline.

Composite Ranking

score = 0.50 x semantic_sim + 0.20 x time_decay + 0.30 x keyword_score

Semantic Similarity50%

Cosine similarity between the query embedding and the article embedding. Captures meaning, not just keyword overlap.

Time Decay20%

Exponential freshness score: 2^(-hours / 48). Rewards recent news while slightly penalizing older evergreen content.

Keyword Density30%

Ratio of distinct AI keywords found in the article. Gives a bonus to articles deeply focused on specialist AI topics.

Tech Stack

NER

spaCy (en_core_web_sm)

Clustering

scikit-learn (K-Means)

Embeddings

sentence-transformers (MiniLM-L6-v2, 384-dim)

Vector Search

PostgreSQL + pgvector (HNSW cosine index)

RSS Parsing

feedparser + newspaper3k

Summarization

DistilBART-CNN-12-6 (abstractive, on-demand)

API

FastAPI + Uvicorn

Frontend

Next.js + Tailwind CSS

Database

PostgreSQL + pgvector (Supabase)

Language

Python 3.12 (backend) + TypeScript (frontend)

Architecture

24 RSS Feeds

feedparser + newspaper3k

AI Keyword Filter
NER Extraction
K-Means Clustering

PostgreSQL + pgvector

HNSW index, cosine similarity

Composite Ranker

semantic + filter

Summarizer

DistilBART