Status Trio
Status Trio는 macOS 메뉴바 앱으로 Wi‑Fi·배터리·볼륨을 하나의 아이콘에 통합합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 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 |