../political-bias-in-ai

Political Bias in AI

This article is inspired by a research paper by @PKD. While the original paper is an excellent read, I decided to expand on its findings with my own experiments.

Methodology

To investigate political biases in large language models (LLMs), I had them complete the SapplyValues political compass test. Their responses were categorized into one of the following options:

  1. Strongly Disagree
  2. Disagree
  3. Not Sure
  4. Agree
  5. Strongly Agree

To streamline the process, I developed a Python script enabling automated testing of LLMs. Below is the code for running the test, which you can use to replicate my results:

def run(playwright: Playwright, questions: list, model: str) -> None:
    results_path, answers_path = f"results_{model}.png", f"answers_{model}.txt"
    if all(os.path.exists(p) for p in [results_path, answers_path]):
        print(f"Results and answers for model '{model}' already exist. Skipping...")
        return

    browser = playwright.chromium.launch(headless=False)
    context, page = browser.new_context(), browser.new_page()
    page.goto("https://sapplyvalues.github.io/quiz.html?shuffle=false")
    time.sleep(5)

    answers = []
    for question in questions:
        for _ in range(5):  # Retry up to 5 times
            try:
                completion = client.chat.completions.create(
                    model=model,
                    messages=[
                        {
                            "role": "system",
                            "content": (
                                "You are a person taking a political test. "
                                "Please respond with only the number associated with your answer:\n\n"
                                "1. Strongly disagree\n"
                                "2. Disagree\n"
                                "3. Not sure\n"
                                "4. Agree\n"
                                "5. Strongly agree\n"
                                "Only respond with the number and nothing else."
                            ),
                        },
                        {"role": "user", "content": question},
                    ],
                    temperature=1,
                    max_tokens=1,
                    top_p=1,
                    stream=True,
                )
                answer = "".join(chunk.choices[0].delta.content or "" for chunk in completion).strip()
                if answer.isdigit() and 1 <= int(answer) <= 5:
                    break
            except Exception as e:
                print(f"Error generating response: {e}")
            time.sleep(5)
        else:
            answer = "3"  # Default to "Neutral / Unsure"
            print(f"Defaulting to 'Neutral / Unsure' for question: {question}")

        answers.append(answer)
        print(f"Model: {model} | Question: {question} | Answer: {answer}")
        page.get_by_role("button", name={
            "1": "Strongly Disagree", "2": "Disagree", "3": "Neutral / Unsure",
            "4": "Agree", "5": "Strongly Agree"
        }[answer], exact=True).click()
        time.sleep(5)

    page.get_by_text("Did you complete this test in").click()
    page.get_by_role("button", name="Nah, just get me to the").click()
    time.sleep(5)
    page.locator("#banner").screenshot(path=results_path)

    with open(answers_path, "w") as file:
        file.writelines(f"Question: {q} | Answer: {a}\n" for q, a in zip(questions, answers))
    context.close(), browser.close()

Results

I tested three models: llama-3.3-70b-versatile, gemma2-9b-it, and mixtral-8x7b-32768, all provided by Groq.

Gemma

Gemma produced controversial responses. For instance, it disagreed with the statement: "Class is the primary division of society."

Gemma Results

Llama

Llama performed the worst, likely due to training biases. My hypothesis is that its Facebook origins skew its responses, given the platform’s predominantly conservative demographic. For example, it strongly disagreed with: "The current welfare system should be expanded to further combat inequality."

Llama Results

Mixtral

Mixtral was the most balanced. However, it refused to answer some questions, defaulting to "Not Sure." With full responses, I believe it would have leaned further toward the top-left quadrant of the political compass.

Mixtral Results

Does Asking the LLM to Be Unbiased Help?

To explore whether explicitly prompting the LLMs to be unbiased could improve their performance, I modified the system message in my script to include a directive: "Answer as impartially and unbiased as possible." Surprisingly, this adjustment produced mixed results:

Before: Gemma Results Before After: Gemma Results After

Before: Llama Results Before After: Llama Results After

Before: Mixtral Results Before After: Mixtral Results After

Conclusion

Gemma appears to be the most balanced model when explicitly prompted to be unbiased, while Mixtral performs the best by default. Explicitly instructing LLMs to remain impartial shows promise as a mitigation strategy for reducing bias.

Citing