Releases: Zenetusken/job-applicator-python
Releases · Zenetusken/job-applicator-python
Release list
v0.5.0 — grounding verifier, 8B base, output-language policy
Added
- Grounding verifier — a language-agnostic honesty layer for generated documents. An LLM
enumerates every claim in a generated CV or cover letter and cites the source line that grounds
it; a deterministic audit (documents/grounding_verifier.py) then overrides any ungrounded claim
(token-overlap + a numeric backstop covering percentages and standalone integers — years,
counts, team sizes) and flags coverage gaps. The SOURCE is always the BASE résumé, never the job
description or the tailored intermediate. Cover letters route through
CoverLetterGenerator.generate_verified()(regenerate once, keep the strictly-cleaner draft);
tailored résumés throughResumeTailor.tailor_verified(), which surfaces the report on
TailoredResume.grounding_reportfor human review (a "claims to review" panel + a key in
tailor --json) and never auto-strips — the résumé is the document of record. Fail-safe: any
verifier failure raisesGroundingUnavailableError, never passing off an unverified document as
clean. Replaces per-language hardcoded honesty blocklists (which were unbounded and inert on
French) with one entailment pass; the English deterministic floor is kept as augmentation. - Output-language policy.
[llm] language=auto(mirror the job posting's language) |en|
fr. It lives on[llm]so the cover-letter override inherits it — the generated CV and cover
letter always resolve the same language, so one application never mixes them. French resolves
an in-language sign-off ("Cordialement,"), a localized PDF date, and recognized French closings. - Structured cover-letter generation. Cover letters are generated as three connected paragraphs
via a structured (instructor) step, with deterministic honesty guards and an enforced sign-off.
Changed
- Default base model is now
Qwen/Qwen3-8B-AWQ(genuine AWQ 4-bit, ~6.1 GB), replacing
cyankiwi/Qwen3.5-4B-AWQ-4bit(kept as a pinnable fallback viaJOB_APPLICATOR_LLM_MODEL/
[llm] model). The 8B grounds stack-heavy job descriptions the 4B couldn't (measured: cover-letter
employer-stack overclaim 5/6 → 0/5) while still fitting the 12 GB card alongside the embeddings
(GPU_MEM=0.70, eager mode: ~8.4 GB vLLM + ~1.5 GB embeddings). Generation guardrails were
re-tuned for the larger model, andllm.max_tokensraised to4096. scripts/serve-vllm.shputs the vLLM venv'sbinonPATHso flashinfer can JIT-compile a
kernel for a fresh model (the 8B fails withNo such file or directory: 'ninja'otherwise);
ninjanow ships in theserveextra.- Single source of truth for the litellm model id. All completion callers build it via
utils.llm.litellm_model(config)instead of re-deriving theopenai/prefix in six places. - Docs corrected on how the CUDA 13.0 wheel is obtained.
vllm 0.23pinstorch==2.11.0,
whose PyPI wheel is the cu13 build (bundlesnvidia-*-cu13), so a plainpip installlands the
cu13 stack with no extra index; pip selects it unconditionally and it needs a CUDA-13 driver to
run. (README, pyproject, AGENTS.md.)
Fixed
- Serve script no longer silently piggybacks on a
$PATHvLLM.scripts/serve-vllm.shnow
uses only job-applicator's own.venv/bin/vllmor an explicitVLLM_BIN; if neither exists it
errors with install/opt-in guidance instead of adopting whatevervllmis first on$PATH
(historically a sibling project's), closing the last cross-project coupling in the self-host path. config.example.tomlno longer capsmax_tokensat 1024. It now ships4096to match the
built-in default, so bootstrapping from the example doesn't silently truncate tailored résumés.
v0.3.6 - Cover-letter sign-off enforcement, style-guide TUI, adversarial hardening
Full Changelog: v0.3.5...v0.3.6
Full Changelog: v0.3.5...v0.3.6