Inspiration
Looking up basic stuff about a neighborhood is a pain. Population is in one Census table, the boundaries are in a different file, and what the county wants to do about housing is somewhere in a planning PDF that's a few hundred pages long. If you just ask a chatbot, it'll answer confidently even when it has no idea. We wanted something where every answer shows you where it came from, and says so when it can't answer.
We started with Fenton Village in downtown Silver Spring because it's small enough that we could check everything by hand.
What it does
Pick an area on the map, either all of Silver Spring or the two Census block groups around Fenton Village, and it shows the 2020 population and housing unit counts with a link to the Census source.
You can also type a question. Counts come straight from the data. For planning questions it searches the 2022 Silver Spring plan, and Gemini summarizes what it found and cites the page. If the data doesn't cover the question, like "will population double next year?", it says so instead of guessing.
How we built it
React and Leaflet on the front, FastAPI on the back. The Census data comes from TIGERweb and gets cleaned up by a script. The plan PDF is split into chunks by page with pypdf and searched with BM25. Gemini 3.6 Flash only gets the passages we pull out, and we check its answer against them before showing it. It all runs with Docker Compose, and there are 54 backend tests plus some Playwright ones.
Challenges we ran into
Geography. The Census numbers cover Silver Spring as a whole and two block groups inside it, and the plan uses its own boundary that doesn't match either. You also can't add them up, since the block groups are already part of the bigger area. So every number and passage is labeled with the area it covers.
Getting the model to say no was the other one. We gave it irrelevant passages, and a document with a fake instruction hidden in it, and it refused both times. If Gemini times out you still get the raw passages.
Accomplishments that we're proud of
Answers link back to a page. We checked the demo ones against page 104 of the plan by hand. The "not enough evidence" case works too.
What we learned
Trust turned out to be mostly a data problem. Once the source and the geography were fields in the API, instead of something the prompt was supposed to handle, most of it got easier.
What's next
Right now only population and housing units are real data. The income, age and business planning stuff in the UI is marked Preview and uses placeholder numbers. Next is real income and ACS data, comparing two variables, and indexing more of the plan. Only three passages are indexed so far.
Built With
- bm25
- census-bureau
- docker
- docker-compose
- fastapi
- gemini-api
- geojson
- github-actions
- google-gemini
- leaflet.js
- openapi
- openstreetmap
- playwright
- pydantic
- pypdf
- pytest
- python
- rag
- react
- tigerweb
- typescript
- vite
Log in or sign up for Devpost to join the conversation.