Skip to content

Commit 53a1c3b

Browse files
committed
backend files
1 parent 3feff7b commit 53a1c3b

6 files changed

Lines changed: 416 additions & 247 deletions

File tree

backend/app/modules/bias_detection/__init__.py

Whitespace-only changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import os
2+
from groq import Groq
3+
from dotenv import load_dotenv
4+
import json
5+
6+
load_dotenv()
7+
8+
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
9+
10+
11+
def check_bias(text):
12+
try:
13+
print(text)
14+
print(json.dumps(text))
15+
16+
if not text:
17+
raise ValueError("Missing or empty 'cleaned_text'")
18+
19+
chat_completion = client.chat.completions.create(
20+
messages=[
21+
{
22+
"role": "system",
23+
"content": (
24+
"You are an assistant that checks "
25+
"if given article is biased and give"
26+
"score to each based on biasness where 0 is lowest bias and 100 is highest bias"
27+
"Only return a number between 0 to 100 base on bias."
28+
"only return Number No Text"
29+
),
30+
},
31+
{
32+
"role": "user",
33+
"content": (
34+
"Give bias score to the following article "
35+
f"\n\n{text}"
36+
),
37+
},
38+
],
39+
model="gemma2-9b-it",
40+
temperature=0.3,
41+
max_tokens=512,
42+
)
43+
44+
bias_score = chat_completion.choices[0].message.content.strip()
45+
46+
return {
47+
"bias_score": bias_score,
48+
"status": "success",
49+
}
50+
51+
except Exception as e:
52+
print(f"Error in bias_detection: {e}")
53+
return {
54+
"status": "error",
55+
"error_from": "bias_detection",
56+
"message": str(e),
57+
}

backend/app/routes/routes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from app.modules.pipeline import run_scraper_pipeline
44
from app.modules.pipeline import run_langgraph_workflow
55
import json
6+
from app.modules.bias_detection.check_bias import check_bias
67

78
router = APIRouter()
89

@@ -15,6 +16,14 @@ class URlRequest(BaseModel):
1516
async def home():
1617
return {"message": "Perspective API is live!"}
1718

19+
@router.post("/bias")
20+
async def bias_detection(request: URlRequest):
21+
content = run_scraper_pipeline(request.url)
22+
bias_score = check_bias(content)
23+
print(bias_score)
24+
return bias_score
25+
26+
1827

1928
@router.post("/process")
2029
async def run_pipelines(request: URlRequest):

frontend/app/analyze/loading/page.tsx

Lines changed: 106 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
"use client"
1+
"use client";
22

3-
import { useEffect, useState } from "react"
4-
import { useRouter } from "next/navigation"
5-
import { Card } from "@/components/ui/card"
6-
import { Badge } from "@/components/ui/badge"
7-
import { Globe, Brain, Shield, CheckCircle, Database, Sparkles, Zap } from "lucide-react"
8-
import ThemeToggle from "@/components/theme-toggle"
9-
import axios from "axios"
3+
import { useEffect, useState } from "react";
4+
import { useRouter } from "next/navigation";
5+
import { Card } from "@/components/ui/card";
6+
import { Badge } from "@/components/ui/badge";
7+
import {
8+
Globe,
9+
Brain,
10+
Shield,
11+
CheckCircle,
12+
Database,
13+
Sparkles,
14+
Zap,
15+
} from "lucide-react";
16+
import ThemeToggle from "@/components/theme-toggle";
17+
import axios from "axios";
1018

1119
/**
1220
* Displays a multi-step animated loading and progress interface for the article analysis workflow.
@@ -16,10 +24,10 @@ import axios from "axios"
1624
* @remark This component manages its own navigation and redirects based on session state.
1725
*/
1826
export default function LoadingPage() {
19-
const [currentStep, setCurrentStep] = useState(0)
20-
const [progress, setProgress] = useState(0)
21-
const [articleUrl, setArticleUrl] = useState("")
22-
const router = useRouter()
27+
const [currentStep, setCurrentStep] = useState(0);
28+
const [progress, setProgress] = useState(0);
29+
const [articleUrl, setArticleUrl] = useState("");
30+
const router = useRouter();
2331

2432
const steps = [
2533
{
@@ -52,76 +60,85 @@ export default function LoadingPage() {
5260
description: "Creating balanced alternative viewpoints",
5361
color: "from-pink-500 to-rose-500",
5462
},
55-
]
63+
];
5664

5765
useEffect(() => {
58-
const runAnalysis = async () => {
59-
const storedUrl = sessionStorage.getItem("articleUrl")
60-
if (storedUrl) {
61-
setArticleUrl(storedUrl)
66+
const runAnalysis = async () => {
67+
const storedUrl = sessionStorage.getItem("articleUrl");
68+
if (storedUrl) {
69+
setArticleUrl(storedUrl);
6270

63-
try {
64-
const res = await axios.post("https://Thunder1245-perspective-backend.hf.space/api/process", {
65-
url: storedUrl,
66-
})
67-
const bias_score = await axios.post("http://localhost:8000/api/bias",{
68-
url: storedUrl,
69-
})
71+
try {
72+
const [processRes, biasRes] = await Promise.all([
73+
axios.post(
74+
"https://Thunder1245-perspective-backend.hf.space/api/process",
75+
{
76+
url: storedUrl,
77+
}
78+
),
79+
axios.post(
80+
"https://Thunder1245-perspective-backend.hf.space/api/bias",
81+
{
82+
url: storedUrl,
83+
}
84+
),
85+
]);
7086

71-
// Save response to sessionStorage
72-
sessionStorage.setItem("analysisResult", JSON.stringify(res.data))
87+
// Save response to sessionStorage
88+
sessionStorage.setItem(
89+
"analysisResult",
90+
JSON.stringify(processRes.data)
91+
);
7392

74-
console.log("Analysis result saved")
75-
console.log(res)
93+
console.log("Analysis result saved");
94+
console.log(processRes);
7695

77-
sessionStorage.setItem("biasScore", JSON.stringify(bias_score.data))
96+
sessionStorage.setItem("biasScore", JSON.stringify(biasRes.data));
7897

79-
console.log("Bias score saved")
80-
console.log(bias_score)
81-
// optional logging
82-
83-
} catch (err) {
84-
console.error("Failed to process article:", err)
85-
router.push("/analyze") // fallback in case of error
86-
return
87-
}
98+
console.log("Bias score saved");
99+
console.log(biasRes);
100+
// optional logging
101+
} catch (err) {
102+
console.error("Failed to process article:", err);
103+
router.push("/analyze"); // fallback in case of error
104+
return;
105+
}
88106

89-
// Progress and step simulation
90-
const stepInterval = setInterval(() => {
91-
setCurrentStep((prev) => {
92-
if (prev < steps.length - 1) {
93-
return prev + 1
94-
} else {
95-
clearInterval(stepInterval)
96-
setTimeout(() => {
97-
router.push("/analyze/results")
98-
}, 2000)
99-
return prev
100-
}
101-
})
102-
}, 2000)
107+
// Progress and step simulation
108+
const stepInterval = setInterval(() => {
109+
setCurrentStep((prev) => {
110+
if (prev < steps.length - 1) {
111+
return prev + 1;
112+
} else {
113+
clearInterval(stepInterval);
114+
setTimeout(() => {
115+
router.push("/analyze/results");
116+
}, 2000);
117+
return prev;
118+
}
119+
});
120+
}, 2000);
103121

104-
const progressInterval = setInterval(() => {
105-
setProgress((prev) => {
106-
if (prev < 100) {
107-
return prev + 1
108-
}
109-
return prev
110-
})
111-
}, 100)
122+
const progressInterval = setInterval(() => {
123+
setProgress((prev) => {
124+
if (prev < 100) {
125+
return prev + 1;
126+
}
127+
return prev;
128+
});
129+
}, 100);
112130

113-
return () => {
114-
clearInterval(stepInterval)
115-
clearInterval(progressInterval)
131+
return () => {
132+
clearInterval(stepInterval);
133+
clearInterval(progressInterval);
134+
};
135+
} else {
136+
router.push("/analyze");
116137
}
117-
} else {
118-
router.push("/analyze")
119-
}
120-
}
121-
122-
runAnalysis()
123-
}, [router])
138+
};
124139

140+
runAnalysis();
141+
}, [router]);
125142

126143
return (
127144
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50/30 to-indigo-100/50 dark:from-slate-900 dark:via-slate-900/80 dark:to-indigo-950/50 transition-colors duration-300 overflow-hidden">
@@ -171,16 +188,22 @@ export default function LoadingPage() {
171188

172189
{/* Article URL Display */}
173190
<div className="mb-8 md:mb-12 p-3 md:p-4 bg-white/50 dark:bg-slate-800/50 rounded-lg backdrop-blur-sm">
174-
<p className="text-slate-600 dark:text-slate-300 text-xs md:text-sm mb-2">Processing:</p>
175-
<p className="text-blue-600 dark:text-blue-400 font-medium truncate text-sm md:text-base">{articleUrl}</p>
191+
<p className="text-slate-600 dark:text-slate-300 text-xs md:text-sm mb-2">
192+
Processing:
193+
</p>
194+
<p className="text-blue-600 dark:text-blue-400 font-medium truncate text-sm md:text-base">
195+
{articleUrl}
196+
</p>
176197
</div>
177198

178199
{/* Progress Bar */}
179200
<div className="mb-12 md:mb-16">
180201
<div className="w-full bg-slate-200 dark:bg-slate-700 rounded-full h-2 md:h-3 mb-3 md:mb-4 overflow-hidden">
181202
<div
182203
className="h-full bg-gradient-to-r from-blue-600 via-indigo-600 to-purple-600 rounded-full transition-all duration-300 ease-out relative"
183-
style={{ width: `${Math.min(progress, (currentStep + 1) * 20)}%` }}
204+
style={{
205+
width: `${Math.min(progress, (currentStep + 1) * 20)}%`,
206+
}}
184207
>
185208
<div className="absolute inset-0 bg-gradient-to-r from-white/20 to-transparent animate-pulse"></div>
186209
</div>
@@ -199,8 +222,8 @@ export default function LoadingPage() {
199222
index === currentStep
200223
? "bg-white dark:bg-slate-800 shadow-2xl scale-105 ring-2 ring-blue-500/50"
201224
: index < currentStep
202-
? "bg-white/80 dark:bg-slate-800/80 shadow-lg opacity-75"
203-
: "bg-white/40 dark:bg-slate-800/40 shadow-md opacity-50"
225+
? "bg-white/80 dark:bg-slate-800/80 shadow-lg opacity-75"
226+
: "bg-white/40 dark:bg-slate-800/40 shadow-md opacity-50"
204227
}`}
205228
>
206229
<div className="flex items-center space-x-3 md:space-x-4">
@@ -209,8 +232,8 @@ export default function LoadingPage() {
209232
index === currentStep
210233
? `bg-gradient-to-br ${step.color} animate-pulse shadow-lg`
211234
: index < currentStep
212-
? "bg-gradient-to-br from-emerald-500 to-teal-500 shadow-md"
213-
: "bg-slate-200 dark:bg-slate-700"
235+
? "bg-gradient-to-br from-emerald-500 to-teal-500 shadow-md"
236+
: "bg-slate-200 dark:bg-slate-700"
214237
}`}
215238
>
216239
{index < currentStep ? (
@@ -230,13 +253,15 @@ export default function LoadingPage() {
230253
index === currentStep
231254
? "text-blue-600 dark:text-blue-400"
232255
: index < currentStep
233-
? "text-emerald-600 dark:text-emerald-400"
234-
: "text-slate-500 dark:text-slate-400"
256+
? "text-emerald-600 dark:text-emerald-400"
257+
: "text-slate-500 dark:text-slate-400"
235258
}`}
236259
>
237260
{step.title}
238261
</h3>
239-
<p className="text-slate-600 dark:text-slate-300 text-xs md:text-sm">{step.description}</p>
262+
<p className="text-slate-600 dark:text-slate-300 text-xs md:text-sm">
263+
{step.description}
264+
</p>
240265
</div>
241266
{index === currentStep && (
242267
<div className="flex space-x-1">
@@ -271,5 +296,5 @@ export default function LoadingPage() {
271296
</div>
272297
</main>
273298
</div>
274-
)
299+
);
275300
}

0 commit comments

Comments
 (0)