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

Closed
opened 2026-06-08 12:39:23 +00:00 by claude · 0 comments
Member

Problem

Three related bugs prevent ejobs.ro and bestjobs.eu from returning job matches:

  1. Stage 2 anchor filter too strict - HtmlJobSearcher rejects anchors whose text doesn't contain a CV keyword. Romanian job titles rarely contain abstract LLM keywords like 'leadership' or 'microservices', so every result is dropped (Grafana: 74 anchors found, 26 passed href filter, 0 passed keyword filter).

  2. LLM extracts abstract keywords, not job-board search terms - The prompt produces concepts like '.NET leadership cloud microservices DevOps' that are poor search terms. Better: concise role + tech (e.g. 'Senior .NET Developer', 'C#', 'Azure').

  3. No location filtering - All providers search without a city filter so LinkedIn returns jobs from any country.

Fix 1 - Per-provider RequireKeywordInAnchor flag

  • Add RequireKeywordInAnchor bool to JobProviderConfig and JobProviderEntity (default true)
  • Skip Stage 2 in HtmlJobSearcher when flag is false
  • Migration: set false for ejobs.ro and bestjobs.eu (search URL already filters server-side)

Fix 2 - Better keyword extraction

  • Update ai.cv-match.system-prompt (en + ro) to instruct the LLM to extract concise job-board-friendly terms: role title + key technologies, not abstract concepts

Fix 3 - Location extraction and URL filtering

  • Add location to LLM JSON schema; propagate through JobMatchResponse -> token -> session
  • Add {location} / {location-slug} substitution in HtmlJobSearcher
  • Updated provider URL templates:
    • linkedin.com: ?keywords={keywords}&location={location}
    • bestjobs.eu: /ro/locuri-de-munca-in-{location-slug}?keywords={keywords}
    • ejobs.ro: /locuri-de-munca/{location-slug}?q={keywords}

Files to change

  • Apis/cv-matcher-api-models/Responses/JobMatchResponse.cs
  • Apis/cv-matcher-api-models/Requests/CreateJobSearchTokenRequest.cs
  • Apis/cv-matcher-api-models/Settings/JobSearchSettings.cs (JobProviderConfig)
  • Apis/cv-search-data/Data/Entities/JobProviderEntity.cs
  • Apis/cv-search-data/Data/Entities/JobSearchTokenEntity.cs
  • Apis/cv-search-data/Data/Entities/JobSearchSessionEntity.cs
  • Apis/cv-matcher-api/Services/JobTokenService.cs
  • Jobs/cv-search-job/Services/HtmlJobSearcher.cs
  • Jobs/cv-search-job/Tasks/CvSearchJobTask.cs
  • New migrations: ImproveKeywordsAndAddLocation, AddRequireKeywordInAnchorAndLocation, AddLocationToProviders
## Problem Three related bugs prevent ejobs.ro and bestjobs.eu from returning job matches: 1. **Stage 2 anchor filter too strict** - HtmlJobSearcher rejects anchors whose text doesn't contain a CV keyword. Romanian job titles rarely contain abstract LLM keywords like 'leadership' or 'microservices', so every result is dropped (Grafana: 74 anchors found, 26 passed href filter, 0 passed keyword filter). 2. **LLM extracts abstract keywords, not job-board search terms** - The prompt produces concepts like '.NET leadership cloud microservices DevOps' that are poor search terms. Better: concise role + tech (e.g. 'Senior .NET Developer', 'C#', 'Azure'). 3. **No location filtering** - All providers search without a city filter so LinkedIn returns jobs from any country. ## Fix 1 - Per-provider RequireKeywordInAnchor flag - Add RequireKeywordInAnchor bool to JobProviderConfig and JobProviderEntity (default true) - Skip Stage 2 in HtmlJobSearcher when flag is false - Migration: set false for ejobs.ro and bestjobs.eu (search URL already filters server-side) ## Fix 2 - Better keyword extraction - Update ai.cv-match.system-prompt (en + ro) to instruct the LLM to extract concise job-board-friendly terms: role title + key technologies, not abstract concepts ## Fix 3 - Location extraction and URL filtering - Add location to LLM JSON schema; propagate through JobMatchResponse -> token -> session - Add {location} / {location-slug} substitution in HtmlJobSearcher - Updated provider URL templates: - linkedin.com: ?keywords={keywords}&location={location} - bestjobs.eu: /ro/locuri-de-munca-in-{location-slug}?keywords={keywords} - ejobs.ro: /locuri-de-munca/{location-slug}?q={keywords} ## Files to change - Apis/cv-matcher-api-models/Responses/JobMatchResponse.cs - Apis/cv-matcher-api-models/Requests/CreateJobSearchTokenRequest.cs - Apis/cv-matcher-api-models/Settings/JobSearchSettings.cs (JobProviderConfig) - Apis/cv-search-data/Data/Entities/JobProviderEntity.cs - Apis/cv-search-data/Data/Entities/JobSearchTokenEntity.cs - Apis/cv-search-data/Data/Entities/JobSearchSessionEntity.cs - Apis/cv-matcher-api/Services/JobTokenService.cs - Jobs/cv-search-job/Services/HtmlJobSearcher.cs - Jobs/cv-search-job/Tasks/CvSearchJobTask.cs - New migrations: ImproveKeywordsAndAddLocation, AddRequireKeywordInAnchorAndLocation, AddLocationToProviders
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: AI/myAi#41