Question-bank pipeline: qbank/ (~2,500 questions, checked in, scales to 10k+) - #4
Merged
Conversation
qbank/ builds questions_db.json (~2,500 questions, 10 topics, checked in) from three inputs and normalizes / classifies / fuzzy-dedupes them: - qbank/curated/*.txt — ~1,700 questions hand-written for this repo, one per line, filed by the topic in the file name - qbank/sources.py — 4 public GitHub lists, each with a format parser returning (question, category_hint); hints map to canonical topics via CATEGORY_MAP, unlabelled/unclassifiable rows are dropped as noise - qbank/taxonomy.py + qbank/expand.py — opt-in LLM expansion per (topic, subtopic), cached and resumable; `--expand` takes it to 10k+ build.py orchestrates: normalize -> route -> global dedupe -> bucket. dedup.py is blocked (bucket by rarest tokens, then Jaccard >= 0.85) so it stays ~linear. classify.py is an ordered-regex heuristic, labelled as such. fetch.py caches downloads with a certifi TLS context. - questions_db.json is now committed; rag.ipynb is a 2-cell wrapper over `python -m qbank.build`; corpus.py docstring updated - tests/test_qbank.py: 38 hermetic tests (parsers, normalize, classify, dedup, expand with a fake LLM, full offline build with fixture Markdown) - 99 tests total; README/DESIGN updated
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the one-off
rag.ipynbscrape (single GitHub README → 1,715 questions, ~27 of the source's own labels, transcription noise and all) withqbank/, a real build pipeline.questions_db.jsonis now a checked-in build artifact (~2,500 questions, 10 canonical topics) so the app runs with no build step.Three inputs, one shape
{topic: [question]}qbank/curated/*.txtOOP.txt,OOP.2.txt→OOP)qbank/sources.py(question, category_hint)qbank/taxonomy.py+--expand(topic, subtopic), cached & resumable — takes the bank past 10kbuild.pyorchestrationnormalize(strip numbering/markdown/glued answers; reject headings & boilerplate) →_routeto a canonical topic (source hint viaCATEGORY_MAP, else the keyword classifier, else drop — unlabelled + unclassifiable is almost always noise, which is why the committed bank is ~2,500 not the ~3,300 raw) → globaldedupe→ bucket by topic.dedup.pyis blocked, not O(n²): exact pass on a punctuation-insensitive key, then bucket each question by its 3 rarest tokens and drop any whose token-set Jaccard with a kept one is ≥ 0.85. Question stop words (difference,between,vs,java, …) are stripped first so "difference between X and Y" and "X vs Y in Java" collide.classify.pyis an ordered-regex heuristic (most specific topic first),Java Corefallback, andbuild._routeonly trusts it when a rule actually fired.expand.pytakes any.invoke(str) -> .contentobject (fake in tests,ChatGroqinbuild.py); per-subtopic cache underqbank/.cache/expand/; a flaky call yields[]for that subtopic instead of aborting.fetch.pycaches downloads with acertifiTLS context (macOS system Python often can't verify GitHub otherwise).Wiring
questions_db.jsoncommitted; removed from.gitignore;qbank/.cache/ignored.rag.ipynb→ 2 cells that shell out topython -m qbank.build.corpus.pydocstring updated; no code change to the retrieval path.Tests / CI
tests/test_qbank.py— 38 hermetic tests: normalize, classify, blocked-fuzzy dedup, all 4 source parsers,_route, expansion against a fake LLM (+ cache hit), and a full offlinebuild.build()with fixture Markdown monkeypatched overqbank.fetch.fetch. Needs onlypytest. 99 tests total.Verify
uv run pytest tests/→ 99 passed.python -m qbank.build→ 2,558 questions across 10 topics.python -m qbank.build --statsworks.Note
Licensing of the scraped repos is unclear (no LICENSE files) — documented in
qbank/SOURCES.md, questions are used as a heavily-transformed seed with attribution, and the build still works with the scraped sources removed (curated +--expandonly).