Used main branch as base branch in the last time
This commit is contained in:
193
src/components/AIDetection.tsx
Normal file
193
src/components/AIDetection.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
import Image from "next/image";
|
||||
import clsx from "clsx";
|
||||
import RadialProgressBar from "./RadialProgressBar";
|
||||
import { AIDetectionAttributes } from "@/interfaces/exam";
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import SegmentedProgressBar from "./SegmentedProgressBar";
|
||||
|
||||
|
||||
// Colors and texts scrapped from gpt's zero react bundle
|
||||
const AIDetection: React.FC<AIDetectionAttributes> = ({ predicted_class, confidence_category, class_probabilities, sentences }) => {
|
||||
const probabilityTooltipContent = `
|
||||
GTP's Zero deep learning model predicts the <br/>
|
||||
probability this text has been entirely <br/>
|
||||
generated by AI. For instance, a 40% AI <br/>
|
||||
probability does not indicate that the text<br/>
|
||||
contains 40% AI-written content. Rather, it<br/>
|
||||
indicates the text is more likely to be partially<br/>
|
||||
human written than be entirely AI-written.
|
||||
`;
|
||||
const confidenceTooltipContent = `
|
||||
Confidence scores are a safeguard to better<br/>
|
||||
understand AI identification results. GTP Zero<br/>
|
||||
trained it's deep learning model on a diverse<br/>
|
||||
dataset of millions of human and AI-written<br/>
|
||||
documents. Green scores indicate that you can scan<br/>
|
||||
with confidence that the model has classified<br/>
|
||||
many similar documents with high accuracy.<br/>
|
||||
Red scores indicate that this text is dissimilar<br/>
|
||||
to the ones in their training set, which can impact<br/>
|
||||
the model's accuracy, and to proceed with caution.
|
||||
`;
|
||||
const confidenceKeywords = ["moderately", "highly", "confident", "uncertain"];
|
||||
var confidence = {
|
||||
low: {
|
||||
ai: "GPT Zero is uncertain about this text. If GPT Zero had to classify it, it would be considered",
|
||||
human: "GPT Zero is uncertain about this text. If GPT Zero had to classify it, it would likely be considered",
|
||||
mixed: "GPT Zero is uncertain about this text. If GPT Zero had to classify it, it would likely be a"
|
||||
},
|
||||
medium: {
|
||||
ai: "GPT Zero is moderately confident this text was",
|
||||
human: "GPT Zero is moderately confident this text is entirely",
|
||||
mixed: "GPT Zero is moderately confident this text is a"
|
||||
},
|
||||
high: {
|
||||
ai: "GPT Zero is highly confident this text was",
|
||||
human: "GPT Zero is highly confident this text is entirely",
|
||||
mixed: "GPT Zero is highly confident this text is a"
|
||||
}
|
||||
}
|
||||
var classPrediction = {
|
||||
ai: {
|
||||
background: "bg-ai-detection-result-ai-bg",
|
||||
color: "text-ai-detection-result-ai",
|
||||
text: "ai generated"
|
||||
},
|
||||
mixed: {
|
||||
background: "bg-ai-detection-result-mixed-bg",
|
||||
color: "text-ai-detection-result-mixed",
|
||||
text: "mix of ai and human"
|
||||
},
|
||||
human: {
|
||||
background: "bg-ai-detection-result-human-bg",
|
||||
color: "text-ai-detection-result-human",
|
||||
text: "human"
|
||||
}
|
||||
}
|
||||
const segments = [
|
||||
{ percentage: Math.round(class_probabilities["human"] * 100), subtitle: 'human', color: "ai-detection-result-human" },
|
||||
{ percentage: Math.round(class_probabilities["mixed"] * 100), subtitle: 'mixed', color: "ai-detection-result-mixed" },
|
||||
{ percentage: Math.round(class_probabilities["ai"] * 100), subtitle: 'ai', color: "ai-detection-result-ai" }
|
||||
];
|
||||
const styleConfidenceText = (text: string): [string, string[]] => {
|
||||
const keywords: string[] = [];
|
||||
const styledText = text.split(" ").map(word => {
|
||||
if (confidenceKeywords.includes(word)) {
|
||||
keywords.push(word);
|
||||
return `<span style="font-weight: 500; text-decoration: underline;">${word}</span>`;
|
||||
}
|
||||
return word
|
||||
}).join(" ");
|
||||
return [styledText, keywords];
|
||||
};
|
||||
const confidenceText = confidence[confidence_category][predicted_class];
|
||||
const [styledText, keywords] = styleConfidenceText(confidenceText);
|
||||
const tooltipStyle = {
|
||||
"backgroundColor": "rgb(255, 255, 255)",
|
||||
"color": "#8992B1",
|
||||
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
|
||||
borderRadius: '0.125rem'
|
||||
}
|
||||
const highestProbability = Math.max(class_probabilities["ai"], class_probabilities["human"], class_probabilities["mixed"]);
|
||||
const spanTextColor = highestProbability === class_probabilities["ai"]
|
||||
? "#f4bf4f"
|
||||
: highestProbability === class_probabilities["human"]
|
||||
? "#50c08a"
|
||||
: "#93aafb";
|
||||
let spanClassName = highestProbability === class_probabilities["ai"]
|
||||
? "text-ai-detection-result-ai"
|
||||
: highestProbability === class_probabilities["human"]
|
||||
? "text-ai-detection-result-human"
|
||||
: "text-ai-detection-result-mixed";
|
||||
spanClassName = `${spanClassName} font-bold text-lg`
|
||||
const percentage = Math.round(highestProbability * 100)
|
||||
const hasHighlightedForAI = sentences.some(item => item.highlight_sentence_for_ai);
|
||||
return (
|
||||
<>
|
||||
<Tooltip id="probability-tooltip" className="z-50 bg-white shadow-md rounded-sm" style={tooltipStyle} />
|
||||
<Tooltip id="confidence-tooltip" className="z-50 bg-white shadow-md rounded-sm" style={tooltipStyle} />
|
||||
<div className="flex flex-col bg-white p-6 rounded-lg shadow-lg gap-16">
|
||||
<h1 className="text-lg font-semibold">GPT Zero AI Detection Results</h1>
|
||||
<div className="flex flex-row -md:flex-col -lg:gap-0 -xl:gap-10 gap-20 items-stretch -md:items-center">
|
||||
<div className="flex -md:w-5/6 w-1/2 justify-center">
|
||||
<div className="flex flex-col border rounded-xl">
|
||||
<h1 className="border-b p-6 font-medium">Text Classification</h1>
|
||||
<div className="flex flex-row gap-8 items-center p-6">
|
||||
<RadialProgressBar
|
||||
percentage={percentage}
|
||||
text={predicted_class}
|
||||
color={spanTextColor}
|
||||
spanClassName={spanClassName}
|
||||
/>
|
||||
<div className="flex flex-col gap-1 text-sm">
|
||||
<div className="flex flex-row items-center">
|
||||
<span className="mr-2 text-ai-detection-result-ai-text font-semibold text-xl">
|
||||
{`${Math.round(class_probabilities["ai"] * 100)}%`}
|
||||
</span>
|
||||
<span className="text-sm -md:text-xs text-ai-detection-text">Probability AI generated</span>
|
||||
<a data-tooltip-id="probability-tooltip" data-tooltip-html={probabilityTooltipContent} className='ml-1 flex items-center justify-center'>
|
||||
<Image src="/mat-icon-info.svg" width={24} height={24} alt="Probability Tooltip" />
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
<div className={clsx(
|
||||
"rounded-full w-3 h-3",
|
||||
confidence_category == 'low' ?
|
||||
"bg-ai-detection-confidence-low border border-ai-detection-confidence-border" : "bg-ai-detection-confidence-low-transparent"
|
||||
)}></div>
|
||||
<div className={clsx(
|
||||
"rounded-full w-3 h-3",
|
||||
confidence_category == 'medium' ?
|
||||
"bg-ai-detection-confidence-medium border border-ai-detection-confidence-border" : "bg-ai-detection-confidence-medium-transparent"
|
||||
)}></div>
|
||||
<div className={clsx(
|
||||
"rounded-full w-3 h-3 mr-2",
|
||||
confidence_category == 'high' ?
|
||||
"bg-ai-detection-confidence-high border border-ai-detection-confidence-border" : "bg-ai-detection-confidence-high-transparent"
|
||||
)}></div>
|
||||
<span className="text-sm -md:text-xs text-ai-detection-text">{keywords.join(' ')}</span>
|
||||
<a data-tooltip-id="confidence-tooltip" data-tooltip-html={confidenceTooltipContent} className='ml-1 flex items-center justify-center'>
|
||||
<Image src="/mat-icon-info.svg" width={24} height={24} alt="Probability Tooltip" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col border rounded-xl -md:w-5/6 w-2/6">
|
||||
<h1 className="border-b p-6 font-medium">Probability Breakdown</h1>
|
||||
<div className="flex items-center w-full h-full">
|
||||
<SegmentedProgressBar segments={segments} className="w-full px-8 -md:py-8 text-ai-detection-text" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-row items-center">
|
||||
<div dangerouslySetInnerHTML={{ __html: styledText }} className="mr-2"></div>
|
||||
<div className={clsx(
|
||||
"flex items-center justify-center p-2 rounded",
|
||||
classPrediction[predicted_class]['color'],
|
||||
classPrediction[predicted_class]['background']
|
||||
)}>
|
||||
<span className="text-sm">{classPrediction[predicted_class]['text']}</span>
|
||||
</div>
|
||||
</div>
|
||||
{(hasHighlightedForAI && <div>
|
||||
Sentences that are likely written by AI are <span className="font-semibold bg-ai-detection-highlight">highlighted</span>.
|
||||
</div>)}
|
||||
</div>
|
||||
</div >
|
||||
<div>
|
||||
{sentences.map((item, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className={item.highlight_sentence_for_ai ? 'bg-ai-detection-highlight' : ''}
|
||||
>
|
||||
{item.sentence}{' '}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default AIDetection;
|
||||
Reference in New Issue
Block a user