careers-llm-extract

This commit is contained in:
ldy
2026-06-17 22:56:04 -04:00
parent 113a4ced36
commit 41037fb2f5
7 changed files with 1350 additions and 28 deletions

View File

@@ -1,12 +1,13 @@
"""find_careers_page(): orchestrate the Stage 2 tier cascade.
Cascade order (return early on first success):
1. ATS detection → ats.detect_and_fetch() confidence 0.95
2. URL patterns → heuristics.probe_url_patterns() 0.80
3. Homepage scan → heuristics.scan_homepage_links() 0.60
4. Sitemap → heuristics.parse_sitemap() 0.50
5. Cheap-LLM → classify_llm (stub, not implemented in this phase)
6. Browser agent → agent_fallback (stub, not implemented in this phase)
1. ATS detection → ats.detect_and_fetch() confidence 0.95
1b. ATS slug-guess → ats.recover_via_slug_guess() confidence 0.90
2. URL patterns → heuristics.probe_url_patterns() confidence 0.80
3. Homepage scan → heuristics.scan_homepage_links() confidence 0.60
4. Sitemap → heuristics.parse_sitemap() confidence 0.50
5. Cheap-LLM → classify_llm.classify_careers_link() confidence 0.55
6. Browser agent → agent_fallback (not implemented in this phase)
Returns a CareersResult with the URL, confidence, method string, and — when
the ATS tier resolves — the first open-position URL for free (Stage-3 shortcut).
@@ -24,6 +25,7 @@ from pydantic import BaseModel
from ..http import build_client, request_with_retries
from . import ats as _ats
from . import classify_llm as _classify_llm
from . import heuristics as _heuristics
logger = logging.getLogger(__name__)
@@ -39,7 +41,7 @@ class CareersResult(BaseModel):
careers_url: str | None = None
confidence: float = 0.0
# method values: "ats:{name}" | "url_pattern" | "homepage_scan" | "sitemap" | "none"
# method values: "ats:{name}" | "url_pattern" | "homepage_scan" | "sitemap" | "llm_classify" | "none"
method: str = "none"
ats_name: str | None = None
# Free Stage-3 shortcut: populated when ATS tier resolves (first open job URL).
@@ -145,8 +147,23 @@ def find_careers_page(
except Exception as exc:
logger.warning("cascade(%s): sitemap tier error: %s", website, exc)
# All deterministic tiers missed.
logger.info("cascade(%s): all deterministic tiers missed", website)
# ------------------------------------------------------------------
# Tier 5 — Cheap-LLM careers-link classification
# ------------------------------------------------------------------
try:
if homepage_html:
anchors = _classify_llm.extract_anchors(homepage_html, website)
res = _classify_llm.classify_careers_link(anchors)
if res:
logger.info(
"cascade(%s): resolved via llm_classify careers_url=%s confidence=%.2f",
website, res.careers_url, res.confidence,
)
return _finalize(res.careers_url, "llm_classify", 0.55, website, client)
except Exception as exc:
logger.warning("cascade(%s): llm_classify tier error: %s", website, exc)
logger.info("cascade(%s): all tiers missed", website)
return CareersResult()
finally: