How to Configure Salary Benchmarking with Custom Data in AI-Job-Search
Place a salary_data.json file at the repository root and run salary_lookup.py to enable personalized salary comparisons during job applications.
The AI-Job-Search repository by MadsLorentzen includes a dedicated salary benchmarking system that lets you compare job offers against proprietary data. This guide explains how to configure salary benchmarking with custom data using the built-in salary_lookup.py utility and optional conversion tools.
Required File Structure
The system expects a single JSON file at a specific location:
- File:
salary_data.json - Location: Repository root (same directory as
salary_lookup.py) - Discovery path:
Path(__file__).parent / "salary_data.json"in [salary_lookup.pyline 27](https://github.com/MadsLorentzen/ai-job-search/blob/master/salary_lookup.py#L27)
If the file is missing, the tool exits gracefully and the /apply workflow skips salary comparison entirely.
Creating Your Custom Salary Data
Option 1: Manual JSON Creation
Create salary_data.json with this structure:
{
"metadata": {
"source": "My Union Statistics 2025",
"index_baseline": 100,
"index_label": "Index",
"baseline_description": "Index 100 = median salary for private sector"
},
"companies": [
{
"company": "Novo Nordisk A/S",
"city": "Bagsværd",
"categories": {
"all_employees": { "count": 500, "index": 108.5 },
"engineering": { "count": 120, "index": 112.3 }
}
},
{
"company": "Ørsted A/S",
"city": "Fredericia",
"categories": {
"all_employees": { "count": 200, "index": 105.2 }
}
}
]
}
Required fields:
metadata.index_baseline— numeric baseline for percentage calculationscompanies[].company— full legal name (normalization handles suffixes)companies[].categories— object with numericindexand optionalcount
Option 2: Convert from Excel
Use the helper script to transform spreadsheet data:
pip install openpyxl
python3 tools/convert_salary_excel.py path/to/salary-data.xlsx \
--source "My Salary Data 2025" \
--baseline 100 \
--baseline-desc "Index 100 = median salary"
The script in [tools/convert_salary_excel.py line 295](https://github.com/MadsLorentzen/ai-job-search/blob/master/tools/convert_salary_excel.py#L295) auto-detects company/city columns and outputs salary_data.json to the repository root.
Validating Your Configuration
Before using your data, verify its structure:
python3 salary_lookup.py --validate
The validation logic in collect_validation_issues() checks:
- Metadata object presence
- Companies array structure
- Required field completeness
- Numeric type consistency
Hard errors trigger fail_data_error() and abort execution; warnings print but allow continuation.
Querying Your Custom Benchmarks
CLI Usage
# Human-readable table (default)
python3 salary_lookup.py "Novo Nordisk"
# Machine-readable JSON
python3 salary_lookup.py "Ørsted" --json
How Fuzzy Matching Works
The search_company() function in [salary_lookup.py lines 63-89](https://github.com/MadsLorentzen/ai-job-search/blob/master/salary_lookup.py#L63-L89) implements:
- Normalization: Lower-casing, stripping legal suffixes, removing non-alphanumerics via
normalize()(lines 64-70) - Anglicization: Character substitutions via
anglicize()(lines 73-78) - Scoring:
match_score_optimized()with pre-calculated query representations - Filtering: Results with score ≥ 30 are retained
Programmatic Access
from salary_lookup import load_data, search_company
data = load_data() # validates & reads salary_data.json
matches = search_company(data, "COWI") # returns ranked list of matches
print(matches[0]["categories"]["engineering"]["index"])
Integration with Job Applications
When salary_data.json exists, the /apply command automatically:
- Extracts company name from the job posting
- Calls
search_company()for fuzzy matching - Injects formatted results into the application report via
format_entry()
If no match exists, the workflow continues without salary data—no blocking errors.
Key Implementation Files
| File | Purpose | Critical Functions |
|---|---|---|
salary_lookup.py |
Core engine | load_data(), search_company(), validate_data() |
tools/convert_salary_excel.py |
Excel→JSON conversion | Autodetection logic at line 263 |
tools/README_SALARY_TOOL.md |
Format documentation | Schema examples and field descriptions |
tests/test_salary_lookup.py |
Behavior reference | Edge cases and validation scenarios |
Summary
- Place
salary_data.jsonat the repository root to activate custom benchmarking - Create data manually or convert from Excel using
tools/convert_salary_excel.py - Validate with
python3 salary_lookup.py --validatebefore deployment - Query via CLI or Python API; fuzzy matching tolerates naming variations
- Integrate automatically with
/applyworkflow when file is present
Frequently Asked Questions
What happens if I don't create salary_data.json?
The AI-Job-Search tool exits cleanly with an informative message, and the /apply workflow proceeds without salary comparison. No application errors occur.
How does the fuzzy matching handle company name variations?
The normalize() function strips legal suffixes like "A/S" and "Inc.", converts to lowercase, and removes special characters. The anglicize() function further standardizes international characters. Scores below 30 are filtered out automatically.
Can I use multiple data sources or update the file dynamically?
The system reads salary_data.json once per invocation. You can replace or modify the file between runs; no caching persists. To merge multiple sources, consolidate them into a single JSON file before placement.
What Excel formats does convert_salary_excel.py support?
The script uses openpyxl for .xlsx files. Column headers should include "company" and optionally "city"; remaining numeric columns become category indices. Run with --help to see all CLI options for baseline configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →