Fix job search: location filtering, keyword quality, anchor filter bypass #42

Merged
claude merged 1 commits from feature/job-search-location-keywords into main 2026-06-08 12:51:17 +00:00
Member

Closes #41

Summary

  • Fix 1 – RequireKeywordInAnchor flag: ejobs.ro and bestjobs.eu returned 0 results because Stage 2 anchor-text filter rejected all Romanian job titles (they don't contain abstract LLM keywords). Added per-provider flag (default rue); set to alse for ejobs.ro and bestjobs.eu since their search URL already filters server-side.

  • Fix 2 – Better keyword extraction: Updated AI system prompts (en + ro) to extract 2-4 concise, job-board-friendly terms — candidate's role title + key technologies (e.g. "Senior .NET Developer", "C#") — instead of abstract concepts like "leadership" or "microservices".

  • Fix 3 – Location filtering: LLM now extracts candidate's city/country from CV. Location propagates through JobMatchResponse → token → session. HtmlJobSearcher substitutes {location} and {location-slug} in provider URL templates. Provider templates updated:

    • ejobs.ro: /locuri-de-munca/{location-slug}?q={keywords}
    • bestjobs.eu: /ro/locuri-de-munca-in-{location-slug}?keywords={keywords}
    • linkedin.com: ?keywords={keywords}&location={location}

Migrations

Project Migration
cv-search-data AddRequireKeywordInAnchorAndLocation
cv-matcher-data ImproveKeywordsAndAddLocation
cv-search-data AddLocationToProviders

Test plan

  • Upload a CV with a clear location (e.g. Cluj-Napoca) and run a match
  • Verify LLM response JSON contains "keywords":["Senior .NET Developer","C#",...] and "location":"Cluj-Napoca, Romania"
  • Click job-search link; verify JobSearchSessionEntity.Location is populated in DB
  • Wait for cv-search-job; check Grafana — ejobs/bestjobs should now return > 0 URLs
  • Check result email — jobs should be in the correct city/country
Closes #41 ## Summary - **Fix 1 – RequireKeywordInAnchor flag**: ejobs.ro and bestjobs.eu returned 0 results because Stage 2 anchor-text filter rejected all Romanian job titles (they don't contain abstract LLM keywords). Added per-provider flag (default rue); set to alse for ejobs.ro and bestjobs.eu since their search URL already filters server-side. - **Fix 2 – Better keyword extraction**: Updated AI system prompts (en + ro) to extract 2-4 concise, job-board-friendly terms — candidate's role title + key technologies (e.g. "Senior .NET Developer", "C#") — instead of abstract concepts like "leadership" or "microservices". - **Fix 3 – Location filtering**: LLM now extracts candidate's city/country from CV. Location propagates through JobMatchResponse → token → session. HtmlJobSearcher substitutes {location} and {location-slug} in provider URL templates. Provider templates updated: - ejobs.ro: /locuri-de-munca/{location-slug}?q={keywords} - bestjobs.eu: /ro/locuri-de-munca-in-{location-slug}?keywords={keywords} - linkedin.com: ?keywords={keywords}&location={location} ## Migrations | Project | Migration | |---------|-----------| | cv-search-data | AddRequireKeywordInAnchorAndLocation | | cv-matcher-data | ImproveKeywordsAndAddLocation | | cv-search-data | AddLocationToProviders | ## Test plan - [ ] Upload a CV with a clear location (e.g. Cluj-Napoca) and run a match - [ ] Verify LLM response JSON contains "keywords":["Senior .NET Developer","C#",...] and "location":"Cluj-Napoca, Romania" - [ ] Click job-search link; verify JobSearchSessionEntity.Location is populated in DB - [ ] Wait for cv-search-job; check Grafana — ejobs/bestjobs should now return > 0 URLs - [ ] Check result email — jobs should be in the correct city/country
claude added 1 commit 2026-06-08 12:46:09 +00:00
Closes #41

- Add RequireKeywordInAnchor per-provider flag (default true); set false for
  ejobs.ro and bestjobs.eu so Stage 2 anchor-text filter is skipped — their
  search URL already filters by relevance server-side
- Update AI system prompts (en + ro) to extract concise job-board-friendly
  keywords (role title + key tech, not abstract concepts) and candidate location
- Propagate location through JobMatchResponse -> CreateJobSearchTokenRequest ->
  JobSearchTokenEntity -> JobSearchSessionEntity
- Add {location} and {location-slug} substitution in HtmlJobSearcher
- Update provider SearchUrlTemplates to include location:
    ejobs.ro:    /locuri-de-munca/{location-slug}?q={keywords}
    bestjobs.eu: /ro/locuri-de-munca-in-{location-slug}?keywords={keywords}
    linkedin.com: ?keywords={keywords}&location={location}
- Three new migrations: AddRequireKeywordInAnchorAndLocation,
  ImproveKeywordsAndAddLocation, AddLocationToProviders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gelu approved these changes 2026-06-08 12:50:32 +00:00
claude merged commit 709c0ac4c3 into main 2026-06-08 12:51:17 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: AI/myAi#42