TruthLens-Backend / services /analysis /bias_detector.py
Gargi Monga
Deploy backend
c8b1fd7
Raw
History Blame Contribute Delete
4.17 kB
import json
from typing import Dict, Any
from ai.sarvam_client import generate_response, extract_json
import spacy
from transformers import pipeline
try:
nlp = spacy.load("en_core_web_sm")
except OSError:
raise OSError("spaCy model not found. Run: python -m spacy download en_core_web_sm")
sentiment_classifier = pipeline("sentiment-analysis",model="cardiffnlp/twitter-roberta-base-sentiment-latest")
def extract_context(text: str) -> Dict[str, list]:
doc = nlp(text)
entities = list(set(ent.text for ent in doc.ents))
keywords = []
for token in doc:
if (
token.is_stop
or token.is_punct
or token.is_space
):
continue
if len(token.text) <= 2:
continue
keywords.append(token.lemma_.lower())
keywords = list(set(keywords))
return {
"entities": entities,
"keywords": keywords
}
def get_sentiment_signal(text: str) -> Dict[str, Any]:
result = sentiment_classifier(text)[0]
return {
"label": result["label"],
"score": round(
result["score"],
4
)
}
def create_bias_prompt(text: str) -> str:
context = extract_context(text)
sentiment = get_sentiment_signal(text)
prompt = f"""
You are an expert media bias analyst.
Analyze the following content and determine:
1. Whether political bias is present.
2. Whether ideological bias is present.
3. Whether reporting is balanced or one-sided.
4. Bias intensity from 0.0 to 1.0.
5. Provide a short explanation.
Definitions:
Political bias:
Favoring or criticizing a political party,
government, politician, or political viewpoint.
Ideological bias:
Favoring or criticizing a belief system,
such as liberalism, conservatism,
nationalism, socialism, or similar ideologies.
Reporting style:
Balanced = multiple viewpoints presented.
One-sided = primarily one viewpoint presented.
Bias intensity:
0.0 = no noticeable bias.
1.0 = extremely biased.
Detected Entities:
{context["entities"]}
Detected Keywords:
{context["keywords"]}
Transformer Sentiment Signal:
{sentiment}
Do not include markdown, code blocks, explanations, or additional text outside the JSON object.
Return ONLY valid JSON:
{{
"political_bias": false,
"ideological_bias": false,
"reporting_style": "Balanced",
"bias_intensity": 0.0,
"explanation": "Short explanation."
}}
Text:
{text}
"""
return prompt
def get_bias_from_model(text: str) -> str:
prompt = create_bias_prompt(text)
return generate_response(prompt)
def parse_model_response(response: str) -> Dict[str, Any]:
if response is None:
return {
"political_bias": False,
"ideological_bias": False,
"reporting_style": "Unknown",
"bias_intensity": 0.0,
"explanation": "No response received from Sarvam AI."
}
parsed = extract_json(response)
if parsed is None:
return {
"political_bias": False,
"ideological_bias": False,
"reporting_style": "Unknown",
"bias_intensity": 0.0,
"explanation": "Could not parse model response."
}
return parsed
def analyze_bias(text: str) -> Dict[str, Any]:
if not text or not text.strip():
return {
"political_bias": False,
"ideological_bias": False,
"reporting_style": "Unknown",
"bias_intensity": 0.0,
"explanation": "Empty input text."
}
raw_response = get_bias_from_model(text)
return parse_model_response(raw_response)
if __name__ == "__main__":
sample_text = """
The government has completely failed and only
one political party can save the country.
"""
print(analyze_bias(sample_text))