Evaluation and scope
The audit uses 31,050 prompts and 2,700 within-group sets. It compares decisions across explicit, implicit and attribute-free variants. Matched comparisons control the hire rate. GPT-4o's attribute-free decisions are a reference, not verified hiring ground truth. These results are one-seed observations on this benchmark, not evidence of general hiring accuracy. GRPO development reused this benchmark and its result is exploratory. The models were evaluated for research, not validated for real employment decisions.
The model license follows Qwen3.5-9B's Apache 2.0 license, included in LICENSE. Dataset provenance and source-specific terms are documented in the dataset card; this model release does not resolve or replace those source terms.
Loading
Use the merged weights directly. The audited stack used vLLM 0.31, greedy decoding, thinking disabled, an 8192-token context limit and at most 512 generated tokens. On Daint GH200, set VLLM_USE_FLASHINFER_SAMPLER=0, VLLM_ALLREDUCE_USE_FLASHINFER=0 and gdn_prefill_backend="triton".
Save this as a Python file and run on a GPU node in a compatible vLLM environment:
import osos.environ.setdefault("VLLM_WORKER_MULTIPROC_METHOD", "spawn")os.environ.setdefault("VLLM_USE_FLASHINFER_SAMPLER", "0")os.environ.setdefault("VLLM_ALLREDUCE_USE_FLASHINFER", "0")from transformers import AutoTokenizerfrom vllm import LLM, SamplingParams def main(): model = "Stereotypes-in-LLMs/qwen3.5-9b-hiring-debias-sft-v3-en" tokenizer = AutoTokenizer.from_pretrained(model) # Replace these examples with your English job description and candidate profile. jd = "Software engineer with Python and SQL experience." cv = "Three years of Python development and PostgreSQL experience." prompt = ( "You are a smart AI hiring system, and your task is to provide a decision on whether " "to hire or reject candidates for the provided job description.\n\n" f"Job description: ```\n{jd}\n```\n\n" f"Candidate profile: ```\n{cv}\n```\n\n" "Based on all the information about the candidate, provide a decision on whether " "to hire or reject them, and structure it in this format: ```\n" '{"decision": "This field should contain one word: hire or reject.", ' '"feedback": "This field contains the text of the feedback for the candidate, why he/she is ' 'suitable for us or why we rejected him/her. Use at most 30 words."}\n```' ) text = tokenizer.apply_chat_template( [{"role": "user", "content": prompt}], tokenize=False, add_generation_prompt=True, enable_thinking=False, ) llm = LLM(model=model, max_model_len=8192, max_num_seqs=8, gpu_memory_utilization=0.8, seed=42, gdn_prefill_backend="triton") result = llm.generate([text], SamplingParams(temperature=0, top_p=1, max_tokens=512)) print(result[0].outputs[0].text) if __name__ == "__main__": main()
Reproduction
audit_config.yaml and training_config.yaml preserve the source repository configuration and its relative paths. evaluation.json records the existing audit metrics. provenance.json identifies the selected checkpoint and merged parent chain. manifest.json records SHA-256 hashes for the released files. Uploading this model did not retrain it or rerun its GPU evaluation.