尚未偵測到更新。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 |