A course project for information retrieval that turns a large podcast transcript corpus into a searchable product. The system combines lexical retrieval, semantic vector search, hybrid ranking, and LLM-assisted result exploration in a single web app.
This system was built as part of the project for the course DD2477 Search Engines and Information Retrieval Systems at KTH.
Podcast transcripts are long, noisy, and difficult to search well with exact keywords alone. This project explores the full retrieval stack:
- lexical search for precision on exact terms,
- vector search for semantic similarity,
- hybrid search to balance precision and recall,
- metadata enrichment to make results easier to scan,
- LLM-powered tools for highlighting, summarization, feedback, and retrieval-augmented question answering.
The result is both a working demo and an evaluation platform for comparing retrieval strategies on the same dataset.
- Full-stack search experience built with Django, HTMX, and Elasticsearch.
- Three retrieval modes exposed directly in the UI: lexical, vector, and hybrid.
- LLM sidebar for asking follow-up questions over retrieved context.
- Highlight extraction, query-aware summaries, and result-quality feedback.
- Offline evaluation for ranking metrics, highlight quality, and embedding model comparisons.
- Presentation deck included in the repository for a concise project walkthrough.
Polished UI & layout. 3 retrieval modes provided to the user:
rec1.mp4
Ask a question to the LLM and get an answer using exclusively the results as context:
ask.mp4
Highlight the phrases that are most relevant to the query in each result:
highlight.mp4
Get feedback on the relevancy of each result to the query, as well as overall relevancy metrics:
feedback.mp4
Generate a query-aware summary of the information in the top results:
summarize.mp4
The main app lives in engine/ and exposes a transcript search interface with live updates. Users can switch search modes, inspect ranked results, and use the LLM panel to explore the retrieved evidence.
The backend supports:
- query parsing and mode selection,
- search execution across lexical, vector, and hybrid pipelines,
- metadata enrichment before rendering,
- highlight extraction from retrieved snippets,
- summary generation for result sets,
- feedback scoring and RAG-style question answering.
engine/contains the Django backend, HTMX frontend, and LLM-assisted UI.indexing/contains the Elasticsearch indexing scripts and embedding benchmarks.evaluation/contains ranking, metric, and highlight evaluation scripts.embedding eval/contains embedding-model evaluation experiments and generated outputs.
Install Docker, then run:
curl -fsSL https://elastic.co/start-local | shThis creates a local Elasticsearch and Kibana setup and an elastic-start-local directory with the credentials needed for the rest of the project.
After installation:
- Elasticsearch: http://localhost:9200
- Kibana: http://localhost:5601
Test the connection with:
cd elastic-start-local/
source .env
curl $ES_LOCAL_URL -H "Authorization: ApiKey ${ES_LOCAL_API_KEY}"From the engine directory:
cd engine
uv sync
uv run python manage.py check
uv run python manage.py runserverOpen the app at:
Create engine/web/services/.env with:
API_KEY=your_elasticsearch_api_key
METADATA_TSV_PATH=/absolute/path/to/metadata.tsv
GEMINI_API_KEY=your_gemini_api_key
GEMINI_MODEL=gemini-2.5-flash-lite
GEMINI_FEEDBACK_MODEL=gemini-3.1-flash-lite-previewFollow the instructions in indexing/README.md to load the podcast transcript corpus into Elasticsearch before using the demo end to end.
This repository includes reproducible evaluation workflows for the retrieval stack:
- ranking evaluation across lexical, vector, and hybrid retrieval,
- highlight-quality evaluation for LLM-generated snippets,
- embedding benchmark scripts,
- LLM-judged embedding retrieval experiments,
- saved metrics and result files for comparison.
Good entry points:
If you want to manage the local Elasticsearch instance manually:
cd elastic-start-local
./start.shTo stop it:
cd elastic-start-local
./stop.shTo uninstall it completely:
cd elastic-start-local
./uninstall.sh