惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - Franky
WordPress大学
WordPress大学
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Fortinet All Blogs
博客园 - 【当耐特】
IT之家
IT之家
G
Google Developers Blog
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
V
Visual Studio Blog
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
GbyAI
GbyAI
雷峰网
雷峰网

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built an AI résumé tool that refuses to lie about your ...
jaberoma · 2026-05-26 · via DEV Community

Most AI résumé tools have the same flaw: they hallucinate. Ask them to tailor your résumé for a job requiring "Rust experience" and they'll happily invent a Rust project you never worked on. It reads great — until the technical interview.

I wanted the opposite. So I built Citevault: a local-first résumé tailoring tool where every claim is either grounded in your own evidence, or refused and flagged as a gap.

No fabrication. No API keys. Runs entirely on your laptop. (Model weights are pulled from Hugging Face once on first boot; after that, no outbound connections.)


The core idea: claim-level grounding

Every bullet in your résumé starts as a claim. Citevault processes each one through a pipeline:

  1. Retrieve — hybrid BM25 + dense embedding search over your indexed evidence (master résumé, project READMEs, blog posts, anything you upload)
  2. Re-rank — BGE cross-encoder scores the top candidates for relevance
  3. Verify — Gemma 4 reads the claim alongside the retrieved span and gives a verdict: SUPPORTS, PARTIAL, UNCLEAR, or CONTRADICTS
  4. Rewrite or refuseSUPPORTS → the claim is verified and cited; PARTIAL → rewritten to match only what the evidence actually says; UNCLEAR → a rewrite is attempted, and if it still can't be grounded, refused and gap-reported; CONTRADICTS → refused immediately and gap-reported

Tailoring running — real-time SSE stream showing retrieval and SUPPORTS verdicts as each claim is verified

The result is a résumé where every bullet has a [^sp-...] footnote traceable back to a specific span in your source material.


The wow demo: Naive Comparison Mode

Toggle "Compare with naive AI" before starting a tailoring run. Citevault runs its grounded pipeline and a second single-pass run — same model, same evidence, same task description, no verification loop. The only difference is the grounded pipeline checks every claim against its source before including it.

The diff is striking:

  • Grounded résumé: seven bullets, every one backed by a citation footnote traceable to a source span
  • Naive résumé: longer, more confident-sounding — and full of placeholders like [Candidate Name] and invented achievements that never appeared in the evidence

Tailoring result — verified grounded claims with citation footnotes; every bullet traces back to a source span

Diff view — Citevault grounded output (left) vs naive AI ungrounded output (right); the naive résumé invents structure and fills in placeholders the model fabricated


The AI stack (all local, no API keys)

Component Role
Gemma 4 E4B (gemma4:e4b) via Ollama Claim drafting, verification, cover letter composition
BGE-small-en-v1.5 Dense embeddings for semantic retrieval
BGE cross-encoder Re-ranking retrieved candidates
BM25 + SQLite FTS5 Keyword retrieval (hybrid RAG)
sqlite-vec Vector store — no external database required

Gemma 4 E4B was chosen specifically for this role: it is instruction-tuned well enough to return consistent structured JSON verdicts, small enough to run on CPU without a GPU, and open-weight so no API key or data exposure is involved. The e4b tag is the Q4_K_M quantised build — the best size/quality tradeoff for local inference via Ollama.

The entire stack runs on CPU. Measured on a 4-core/8-thread laptop with 32 GB RAM and no discrete GPU: 3–8 tokens/second generation speed, 20–30 minutes per tailoring run; add another 10–20 minutes if naive comparison is enabled. Slower than a cloud API, but zero cost, zero data exposure, and no dependency on an upstream service staying alive.


What I learned building this

Structured generation is the hard part. Getting Gemma 4 to consistently return structured JSON verdicts from the verifier took more prompt iteration than anything else. The final verifier prompt is tightly constrained: it gives the model a specific rubric, a strict output format, and a worked example. It still occasionally returns malformed output — those claims are logged and omitted from the output rather than silently passed through.

Hybrid RAG matters. Pure dense search misses exact keyword matches. Pure BM25 misses semantic similarity. On the five-case golden eval set, the hybrid combination recovered ~15 percentage points in first-pass grounding rate over either retrieval strategy alone — enough to tip borderline claims from UNCLEAR to SUPPORTS.

Eval-driven development pays off. I built a golden evaluation set of five synthetic candidates and ran the pipeline against it after every significant change. The final first-pass grounding rate is 98.2% — but more importantly, I caught two regressions that looked fine in manual testing.

Local-first is a real constraint, not a marketing line. Your career data is sensitive. Résumés contain salary history, reasons for leaving, private project details. I didn't want to be a data controller. Building local-first forced specific architectural decisions — no cloud storage, no async job queue, no third-party embedding API.


Try it

docker compose up -d ollama
docker compose exec ollama ollama pull gemma4:e4b
docker compose up -d
# Then open http://localhost:5173/admin in your browser

Enter fullscreen mode Exit fullscreen mode

Upload your evidence, paste a job posting, and watch the grounding happen in real time via SSE stream.

Heads up — this runs on CPU. On a 4-core laptop without a GPU, expect 20–30 minutes per tailoring run. With naive comparison enabled, add another 10–20 minutes for the second pass. It is slow by cloud-API standards, but fully offline and costs nothing after the first model pull.

The best test: pick a role where you have a genuine skill gap — that is where the gap report is most useful.

The full architecture (hexagonal layout, RAG pipeline, Docker Compose stack) is documented in docs/architecture.md in the repo.

The code is on GitHub: github.com/jaberoma/citevault — MIT licensed, no account required, runs on any laptop with Docker.

Citevault's contract is simple: every claim in your résumé either links to a source span in your own evidence, or it does not appear. No exceptions.