尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A LangGraph RAG agent that grades its own retrieval, rewrites failed queries and refuses rather than guessing, plus an evaluation harness that measures each of those decisions, not just the final answer.
Live demo: https://polygraph-agentic-rag.vercel.app. Click a "trick question" to watch it refuse instead of guessing.
The knowledge base is 242 pages of the Docker documentation (Engine, Compose, Build, Desktop), giving an IT-support / DevOps assistant. Everything runs on free tiers: Groq for LLMs, local sentence-transformers for embeddings and reranking, and Vercel for hosting.
flowchart LR
Q([question]) --> R[retrieve<br/>BM25 + dense → RRF<br/>→ cross-encoder rerank]
R --> G{grade_context<br/>structured verdict:<br/>relevant? reason, chunk ids}
G -- relevant --> A[generate<br/>answer only from context,<br/>inline chunk citations]
G -- "not relevant &<br/>rewrites < MAX" --> W[rewrite_query]
W --> R
G -- "not relevant &<br/>rewrites = MAX" --> X[refuse<br/>'I couldn't find this<br/>in the knowledge base']
A --> T[(trace: steps, verdicts,<br/>rewrites, ids, latency,<br/>tokens, cost)]
X --> T
Every node writes a structured decision record. One run returns a Trace, and that trace is what the
evaluation scores and what the demo's Agent trace panel shows.
| Component | Choice |
|---|---|
| Orchestration | LangGraph StateGraph (src/rag_agent/graph.py) |
| Generator | openai/gpt-oss-120b on Groq |
| Grader and query rewriter | openai/gpt-oss-20b on Groq (small and fast) |
| Eval judge | qwen/qwen3.8-27b on Groq: a different model family from the generator, to reduce self-preference bias |
| Embeddings | BAAI/bge-small-en-v1.5 (local, CPU) in ChromaDB |
| Lexical retrieval | rank_bm25, fused with dense results via Reciprocal Rank Fusion (k = 60) |
| Reranker | cross-encoder/ms-marco-MiniLM-L-6-v2 (local, CPU) |
| Answer metrics | Ragas (faithfulness, answer relevancy) and DeepEval G-Eval (correctness), both routed through Groq |
| Tracing | Langfuse (optional; a no-op when its keys are absent) |
All behaviour is set by environment variables (src/rag_agent/config.py): RETRIEVAL_MODE=dense|bm25|hybrid,
USE_RERANKER, USE_REFLECTION, MAX_REWRITES and TOP_K. The ablations are just different settings of these.
Generated by eval/make_report.py from eval/results/ (golden set: ai_reviewed; 70 items per config).
| Metric | baseline | hybrid | hybrid_rerank | full |
|---|---|---|---|---|
| Agent decisions | ||||
| Grader precision (set) | — | — | — | 96.0% |
| Grader recall (set) | — | — | — | 98.0% |
| Grader precision (chunk) | — | — | — | 76.4% |
| Grader recall (chunk) | — | — | — | 90.2% |
| Correct-refusal rate (unanswerable) | 85.0% | 85.0% | 85.0% | 95.0% |
| False-refusal rate (answerable) | 8.0% | 4.0% | 4.0% | 2.0% |
| Rewrite success rate | — | — | — | 40.0% |
| Rewrites (answerable items) | 0 | 0 | 0 | 5 |
| Steps / query (mean) | 2.00 | 2.00 | 2.00 | 4.84 |
| Steps / query (p95) | 2.0 | 2.0 | 2.0 | 9.0 |
| Loop rate (hit MAX_REWRITES) | 0.0% | 0.0% | 0.0% | 30.0% |
| Retrieval |
— means not computed for that config (Ragas runs on baseline and full only; grader and rewrite metrics exist only when reflection is on). Full details, failure examples and traces: eval/results/ABLATIONS.md.
Agent decisions (the core of the project):
grade_context step is one prediction. Positive means the
retrieved context contains at least one gold chunk. The chunk-level variant scores every graded chunk
against relevant_chunk_ids.MAX_REWRITES.Retrieval: Recall@k and MRR@k, computed on the first retrieval (the original question).
Answers:
Ops: latency p50/p95 per query and per node, tokens per query, and cost per query at Groq list prices. The free tier isn't billed. When a call is served from the disk cache, it's charged its originally measured latency.
eval/draft_golden.py) from seed chunks sampled across all four doc
sections:
relevant_chunk_ids: labelled by a different model (qwen3.8-27b) over a TREC-style pool, the top-5
dense plus top-5 BM25 hits for each question. The grader being evaluated never labels its own gold.eval/ai_review_proposals.json:
--golden-source ai_reviewed). A human can
confirm or override every proposal with eval/review_golden.py --proposals ...; the runner then reports on
--golden-source verified instead.eval/judge_calibration.py) needs 30 human correct/incorrect labels to compute accuracy
and Cohen's κ against the G-Eval judge. It hasn't been done, so the correctness numbers come from an
uncalibrated LLM judge.refuse node guarantees the generator never answers from bad context.
The cost is false refusals when the grader is too strict, which the false-refusal rate measures directly.daemon.json, --memory, error
strings) that BM25 matches well, and paraphrased symptoms that dense retrieval matches well. RRF combines the
two without tuning score scales.relevant, reason, relevant_chunk_ids) replaces free-text parsing. The chunk ids make chunk-level grader
metrics possible at no extra cost.retry-after.scripts/usage_today.py).baseline and full, to fit the judge's 200K-tokens/day
budget.src/rag_agent/onnx_models.py), so the function fits Vercel's size limit. On the
golden set, its first-retrieval Recall@4 (0.867) and MRR@4 (0.870) match the evaluated full config exactly.eval/results/ABLATIONS.md lists up to five failure cases from the full config. Each has its trace and a
diagnosis: grader false negative, retrieval miss, generation error, grader false positive or rewrite loop. That
file is generated from the same results as the table above.
git clone https://github.com/Swastigit2005/Polygraph-An-Evaluation-Framework-for-Agentic && cd Polygraph-An-Evaluation-Framework-for-Agentic
uv venv -p 3.11 .venv && uv pip install -p .venv -r requirements-full.txt -r requirements-dev.txt -e .
cp .env.example .env # add GROQ_API_KEY (free at console.groq.com)
.venv/bin/python scripts/list_groq_models.py # see which models your key can use; set them in .env
.venv/bin/python scripts/dev_server.py # web demo at http://localhost:8000
.venv/bin/pytest -q # offline unit tests (no network)
requirements.txt is the light web-demo runtime (ONNX, no PyTorch); requirements-full.txt adds what indexing and
the evaluation harness need. Use .venv/bin/python explicitly if your shell aliases python to a system interpreter.
.venv/bin/python eval/run_eval.py --config full --golden-source ai_reviewed --limit 5 # quick check
nohup .venv/bin/python eval/run_all.py > eval/results/run_all.log 2>&1 & # all ablations
.venv/bin/python scripts/usage_today.py # Groq free-tier usage today
.venv/bin/python eval/make_report.py # rebuild ABLATIONS.md and this README's results section
A full ablation sweep (4 configs × 70 items, plus judges) needs more than one day of Groq free-tier quota.
run_all.py waits out the daily quota and resumes where it stopped.
CI (.github/workflows/ci.yml) runs ruff and the unit tests on every push. The eval gate runs on manual
dispatch, or on PRs labelled run-evals: it evaluates the full config on a fixed 20-item subset
(eval/ci_subset.json) and fails if any metric falls below eval/thresholds.json. The thresholds come from the
first full run, minus 0.10. The gate needs a GROQ_API_KEY repository secret.
The demo is a static page (public/) plus one Python function (api/ask.py) that runs the agent.
npx vercel login, then npx vercel link in the repo root.npx vercel env add GROQ_API_KEY production.
Non-secret settings come from config/demo.env.npx vercel deploy --prod. You can also import the GitHub repo at vercel.com, which redeploys on every push.When the index or the eval results change, refresh the page's data with
.venv/bin/python scripts/export_demo_data.py. Add --record to also re-record the example runs that the page
plays back when the live API is busy. The ONNX models (models/) and their index vectors
(data/index/embeddings_onnx.npy) are rebuilt with python -m rag_agent.onnx_models --download and
MODEL_BACKEND=onnx python -m rag_agent.ingest --onnx-vectors.
6cf1b1c, Oct 2026). Answers can go stale as Docker changes.This project's code is MIT-licensed (LICENSE). Corpus files keep their Apache-2.0 license.
| Recall@k (first retrieval) | 77.2% | 86.7% | 86.7% | 86.7% |
| MRR@k (first retrieval) | 0.763 | 0.870 | 0.870 | 0.870 |
| Answer quality |
| Faithfulness (Ragas) | 0.862 | — | — | 0.870 |
| Answer relevancy (Ragas) | 0.927 | — | — | 0.913 |
| Correctness (G-Eval, answered) | 0.954 | 0.979 | 0.979 | 0.980 |
| End-to-end accuracy (answerable) | 88.0% | 94.0% | 94.0% | 96.0% |
| Ops |
| Latency p50 (s) | 0.89 | 1.29 | 1.29 | 2.42 |
| Latency p95 (s) | 1.79 | 2.89 | 2.89 | 6.77 |
| Tokens / query (mean) | 1,010 | 1,068 | 1,068 | 2,840 |
| Cost / query (USD, list price) | $0.00023 | $0.00023 | $0.00023 | $0.00038 |
| Items evaluated | 70 | 70 | 70 | 70 |