A fine-tuned version of Qwen3-8B for news media bias detection and neutral rewriting, developed by the Vector Institute as part of the UnBias-Plus project.
Given a news article, the model identifies biased language segments, classifies their bias type and severity, provides neutral replacements, and returns a fully rewritten unbiased version of the article — all in a single structured JSON response.
This is the Instruct variant — trained without chain-of-thought thinking blocks (enable_thinking=False). It produces clean structured JSON directly, making it faster and more reliable for production inference, including deployment via vLLM or other OpenAI-compatible serving backends.
1from transformers import AutoModelForCausalLM, AutoTokenizer
2import torch, json
34model_id ="vector-institute/Qwen3-8B-UnBias-Plus-SFT-Instruct-Legacy"56tokenizer = AutoTokenizer.from_pretrained(model_id)7model = AutoModelForCausalLM.from_pretrained(8 model_id,9 dtype=torch.bfloat16,10 device_map="auto",11)12model.eval()1314SYSTEM_PROMPT ="""You are an expert linguist and bias detection specialist.
15Your task is to carefully read a news article, detect ALL biased language,
16and return a structured JSON response. Return ONLY valid JSON, no extra text."""1718article ="Your news article here..."1920messages =[21{"role":"system","content": SYSTEM_PROMPT},22{"role":"user","content":f"Analyze the following article for bias and return the result in the required JSON format.\n\nARTICLE:\n{article}"},23]2425inputs = tokenizer.apply_chat_template(26 messages,27 tokenize=True,28 add_generation_prompt=True,29 enable_thinking=False,# must be False for this variant30 return_tensors="pt",31 return_dict=True,32 truncation=True,33 max_length=8192,34)3536with torch.no_grad():37 outputs = model.generate(38 input_ids=inputs["input_ids"].to(model.device),39 attention_mask=inputs["attention_mask"].to(model.device),40 max_new_tokens=4096,41 do_sample=False,# greedy decoding for deterministic JSON42 temperature=None,43 top_p=None,44 pad_token_id=tokenizer.eos_token_id,45)4647new_tokens = outputs[0][inputs["input_ids"].shape[1]:]48response = tokenizer.decode(new_tokens, skip_special_tokens=True)49result = json.loads(response)
Using with the UnBias-Plus toolkit
python
1from unbias_plus import UnBiasPlus
23pipe = UnBiasPlus(4 model_name_or_path="vector-institute/Qwen3-8B-UnBias-Plus-SFT-Instruct-Legacy",5 load_in_4bit=False,# set True for ~5GB VRAM6)78result = pipe.analyze("Your article text here...")9print(result.binary_label)# "biased" or "unbiased"10print(result.severity)# 0, 2, 3, or 411print(len(result.biased_segments))12print(result.unbiased_text)
Loaded language — words with strong emotional connotations
Dehumanizing framing — language that strips dignity from groups
False generalizations — sweeping statements ("they always", "all of them")
Framing bias — selective wording that implies a viewpoint
Euphemism/dysphemism — softening or hardening language to manipulate perception
Politically charged terminology — labels used to provoke rather than describe
Sensationalism — exaggerated language to evoke emotional responses
Training Data
Fine-tuned on vector-institute/Unbias-plus, a curated dataset of news articles with expert-annotated bias labels, segment-level annotations, and neutral rewrites.
Trained primarily on English-language news articles
Political bias detection reflects patterns in the training data
Best performance on articles under 5000 characters
As with all language models, outputs should be reviewed by a human before use in production
Citation
If you use this model in your research or application, please cite:
@article{radwan2026unbias,
1 title={UnBias-Plus: Detect, Explain, and Rewrite Bias},
2 author={Radwan, Ahmed Y and ElKady, Ahmed and Chaduvula, Sindhuja and Hafez, Mohamed and Krishnan, Amrit and Raza, Shaina},
3 journal={arXiv preprint arXiv:2606.23412},
4 year={2026}
5}