Avocet by Circuit Forge LLC — email classifier training tool: multi-account IMAP fetch, card-stack labeling UI, benchmark harness
Find a file
pyr0ball 2891606765 feat(cloud_session): add session resolution + forward user_id to cf-orch imitate
app/cloud_session.py:
- Thin wrapper around cf_core.cloud_session.CloudSessionFactory
- BYOK detection reads ~/.config/circuitforge/llm.yaml (same path as other products)
- get_session: FastAPI dependency, returns CloudUser (user_id, tier, has_byok)
- require_tier: dependency factory for tier-gated routes

app/imitate.py:
- _run_cftext gains user_id: str | None param; non-None values included in
  the cf-orch ServiceAllocateRequest so premium users get their custom models
- run_imitate injects session via Depends(_get_imitate_session); extracts user_id,
  filters out local/anon sessions (they get the shared catalog), passes real
  cloud user_id to the ThreadPoolExecutor fanout
- _get_imitate_session wraps get_session with a try/except so imitate keeps
  working in envs where cloud_session deps aren't installed
2026-04-24 16:41:45 -07:00
app feat(cloud_session): add session resolution + forward user_id to cf-orch imitate 2026-04-24 16:41:45 -07:00
config feat(models): extended model registry + manage.sh benchmark subcommands 2026-04-24 14:56:24 -07:00
data feat: initial avocet repo — email classifier training tool 2026-02-27 14:07:38 -08:00
scripts chore: add README + gather_corpus.py script 2026-04-24 15:29:26 -07:00
tests feat(models): extended model registry + manage.sh benchmark subcommands 2026-04-24 14:56:24 -07:00
web feat(models): extended model registry + manage.sh benchmark subcommands 2026-04-24 14:56:24 -07:00
.env.example feat(#10): env var LLM config + cf-orch coordinator auth 2026-04-09 12:26:44 -07:00
.gitignore chore: retire Streamlit app, scaffold sft branch 2026-04-08 06:18:12 -07:00
environment.yml feat(#10): env var LLM config + cf-orch coordinator auth 2026-04-09 12:26:44 -07:00
manage.sh feat(models): extended model registry + manage.sh benchmark subcommands 2026-04-24 14:56:24 -07:00
PRIVACY.md docs: add privacy policy reference 2026-03-05 20:59:37 -08:00
pytest.ini feat: initial avocet repo — email classifier training tool 2026-02-27 14:07:38 -08:00
README.md chore: add README + gather_corpus.py script 2026-04-24 15:29:26 -07:00
requirements.txt fix(avocet): store original item in _last_action; add requirements.txt 2026-03-03 15:16:54 -08:00

Avocet — Email Classifier Training Tool

Part of the CircuitForge LLC internal infrastructure suite.

Status: Internal beta — label tool and benchmark harness complete. Used to build training data for Peregrine's email classifier.


What it does

Avocet is the data pipeline for building and benchmarking email classifiers. It has two layers:

No LLM required. Avocet uses zero-shot HuggingFace classification models — no API key, no cloud inference, no GPU required for the label tool. The benchmark harness can optionally export LLM-labeled emails from a Peregrine staging DB, but human labeling via the card-stack UI is the primary workflow.

Layer 1 — Label tool Card-stack UI for building ground-truth classifier benchmark data. Fetch emails from one or more IMAP accounts (with targeted date-range and sender/subject filters), review them card-by-card, and label each with a job-search category. Labeled output feeds the benchmark harness.

Layer 2 — Benchmark harness Scores HuggingFace zero-shot classification models against the labeled dataset. Supports slow/large model inclusion, visual side-by-side comparison on live emails, and export of LLM-labeled emails from a Peregrine staging DB.


Labels

Label Key
interview_scheduled 1
offer_received 2
rejected 3
positive_response 4
survey_received 5
neutral 6
event_rescheduled 7
unrelated 8
digest 9

Stack

Layer Tech
Label UI Streamlit (port 8503, auto-increments on collision)
Benchmark Python + HuggingFace Transformers
Email fetch IMAP (multi-account, targeted date/sender/subject filter)
Data JSONL (data/email_label_queue.jsonl, data/email_score.jsonl)
Config config/label_tool.yaml (gitignored — see .example)

Conda environments:

  • job-seeker — label tool UI
  • job-seeker-classifiers — benchmark harness (separate env for heavy deps)

Running

./manage.sh start              # start label tool UI (port collision-safe from 8503)
./manage.sh stop               # stop
./manage.sh restart            # restart
./manage.sh status             # show running state and port
./manage.sh logs               # tail label tool log
./manage.sh open               # open in browser

Benchmark:

./manage.sh benchmark --list-models    # list available zero-shot models
./manage.sh score                      # score models against labeled JSONL
./manage.sh score --include-slow       # include large/slow models
./manage.sh compare --limit 30         # visual comparison on live IMAP emails

Dev:

./manage.sh test               # run pytest suite

Data flow

IMAP accounts → fetch (targeted or wide) → email_label_queue.jsonl
→ label tool card UI → email_score.jsonl
→ benchmark harness → model rankings
→ best model → Peregrine classifier adapter

Targeted fetch: date range + sender/subject filter for pulling historical emails on specific senders or topics without flooding the queue.

Discard: removes an email from the queue without writing to the score file — for emails that don't belong in the training set.


Classifier adapters

app/classifier_adapters.py provides a common interface for swapping classifier backends. Falls back to the label name when no LABEL_DESCRIPTIONS entry is configured for a label (RerankerAdapter).


License

BSL 1.1 — internal tool, not user-facing.

© 2026 Circuit Forge LLC