ToPWR Assistant — Knowledge-graph RAG
Polish questions translated into read-only Cypher over a Neo4j knowledge graph, orchestrated with LangGraph and served through an MCP server.
- Role
- Machine Learning Engineer
- Timeline
- 2025 – present
- Status
- Ongoing
- Area
- Backend / retrieval
28 Polish questions about 7 real PWr faculties, each asked in four forms, against the same Neo4j graph.
100%of questions found the right faculty, up from 50%
| Query form | Before | After fix |
|---|---|---|
| Stored spelling | 7/7 | 7/7 |
| Polish diacritics | 7/7 | 7/7 |
| Lowercase | 0/7 | 7/7 |
| Lowercase + diacritics | 0/7 | 7/7 |
| Overall | 14/28 · 50% | 28/28 · 100% |
One question from the run
Pokaż informacje o jednostce "wydział informatyki i telekomunikacji".
- Before
WHERE n.title CONTAINS 'wydzial informatyki i telekomunikacji'→ 0 rows- After fix
WHERE toLower(n.title) CONTAINS toLower('wydzial informatyki i telekomunikacji')→ Wydzial Informatyki i Telekomunikacji
Overview
An assistant for the ToPWR university app, built with the Solvro student group. A React chat UI, a FastAPI layer, an MCP server, and a Neo4j knowledge graph let people ask questions in Polish and get answers backed by structured university data. I’ve had 15 pull requests merged into it so far.
- merged PRs
- 15
- Docker services
- 4
- generated Cypher
- Read-only
Problem
University information is scattered across departments, pages, and systems, which makes it slow to find — and people ask about it in inflected Polish.
Approach
A knowledge-graph retrieval workflow that routes the question, generates Cypher, runs it read-only against the graph, and grades the result before answering.
01
Ask
Question in Polish
02
Route
LangGraph + guardrails
03
Generate
LLM-written Cypher
04
Query
Neo4j, read-only, via MCP
05
Grade
Answer, or “no data”
React, FastAPI, a FastMCP server, and Neo4j run as a 4-service Docker stack. LangGraph orchestrates routing, Cypher generation, and grading with guardrails, while a Prefect flow processes documents and populates the knowledge graph.
Outcomes
- Fixed inflected Polish (“semestrze”) never matching titles stored in the nominative, using a fuzzy full-text fallback and an LLM grader that says “no data” instead of guessing.
- Locked generated Cypher to read-only with query validation and Neo4j READ mode, and capped rows in code rather than in the prompt.
- Built the Prefect ETL that turns PDFs into graph nodes via OCR and LLM-written Cypher, in parallel and idempotently.
Challenges
- Polish inflection: the words people type rarely match how titles are stored.
- Letting an LLM write database queries without letting it write to the database.
- Saying “no data” when the graph doesn’t know, instead of guessing.
Stack
Python · FastAPI · LangGraph · LangChain · FastMCP · Neo4j · Prefect · Docker