Spaces:
Runtime error
Runtime error
File size: 8,919 Bytes
0e7dd0f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | import sys
import random
import requests
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datasets import load_dataset
from sklearn.metrics import classification_report, accuracy_score, confusion_matrix, roc_curve, auc
# --- KONFIGURACJA ---
API_URL = "http://127.0.0.1:8000" # Adres Twojego backendu FastAPI
TEST_GUILD_ID = "eval_test_guild" # Testowa gildia
SAMPLE_SIZE = 250 # Liczba pr贸bek na klas臋 (50 FAKE i 50 REAL = 100 test贸w)
# ---------------------
def setup_test_guild():
"""Wysy艂a 偶膮danie konfiguracji gildii testowej, aby zapobiec SetupRequiredError."""
print(f"[*] Konfigurowanie testowej gildii '{TEST_GUILD_ID}' na backendzie...")
setup_payload = {
"active_text_model": "bibbbu/multilingual-ai-human-detector_xlm-roberta-base", # Model, kt贸ry chcemy przetestowa膰
"active_image_model": "none",
"log_channel_id": None,
"multi_model_workflow": False
}
try:
r = requests.post(f"{API_URL}/guilds/{TEST_GUILD_ID}/setup", json=setup_payload)
if r.status_code == 200:
print("[+] Testowa gildia skonfigurowana pomy艣lnie.")
else:
print(f"[-] B艂膮d konfiguracji gildii: {r.status_code} - {r.text}")
sys.exit(1)
except Exception as e:
print(f"[-] Brak po艂膮czenia z FastAPI pod adresem {API_URL}. Upewnij si臋, 偶e serwer dzia艂a. B艂膮d: {e}")
sys.exit(1)
def prepare_dataset(sample_size):
"""Pobiera zbi贸r HC3 z Hugging Face i tworzy zbalansowany zbi贸r testowy."""
print("[*] Pobieranie zbioru Hello-SimpleAI/HC3 z Hugging Face...")
try:
# Pobieranie bezpiecznej wersji Parquet
ds = load_dataset(
"Hello-SimpleAI/HC3",
"default",
revision="refs/convert/parquet",
split="train"
)
except Exception as e:
print(f"[-] Nie uda艂o si臋 pobra膰 zbioru z Hugging Face: {e}")
sys.exit(1)
human_texts = []
ai_texts = []
print("[*] Filtrowanie i przygotowywanie pr贸bek tekstowych...")
for item in ds:
# human_answers i chatgpt_answers s膮 listami string贸w
for ans in item.get("human_answers", []):
# Filtrujemy teksty: min 50 znak贸w (wym贸g FastAPI), maks 1000 znak贸w dla szybko艣ci
if 50 <= len(ans) <= 1000:
human_texts.append(ans)
for ans in item.get("chatgpt_answers", []):
if 50 <= len(ans) <= 1000:
ai_texts.append(ans)
# Losowanie zbalansowanej pr贸bki z ziarnem losowo艣ci (powtarzalno艣膰 testu)
random.seed(42)
human_selected = random.sample(human_texts, min(sample_size, len(human_texts)))
ai_selected = random.sample(ai_texts, min(sample_size, len(ai_texts)))
test_set = []
for text in human_selected:
test_set.append({"text": text, "is_fake_ground_truth": False})
for text in ai_selected:
test_set.append({"text": text, "is_fake_ground_truth": True})
random.shuffle(test_set)
return test_set # <-- TA LINIA MUSI BY膯 NA KO艃CU FUNKCJI
def run_evaluation(test_set):
"""Przeprowadza testy wysy艂aj膮c zapytania do endpointu FastAPI."""
raw_results = []
total = len(test_set)
print(f"[*] Rozpoczynanie wysy艂ki {total} 偶膮da艅 do FastAPI...")
for i, item in enumerate(test_set):
payload = {
"guild_id": TEST_GUILD_ID,
"user_id": f"eval_user_{i}", # Obej艣cie limitera (unikalny u偶ytkownik na zapytanie)
"text": item["text"],
"content_type": "text"
}
try:
r = requests.post(f"{API_URL}/analyze", json=payload)
if r.status_code == 200:
data = r.json()
is_deepfake_pred = data["is_deepfake"]
confidence = data["confidence"]
analysis_time = data["analysis_time"]
used_model = data["used_model"]
raw_results.append({
"id": i,
"text_snippet": item["text"][:60].replace("\n", " ") + "...",
"ground_truth": item["is_fake_ground_truth"],
"predicted": is_deepfake_pred,
"confidence": confidence,
"analysis_time": analysis_time,
"used_model": used_model,
"status": "SUCCESS"
})
print(f"[{i+1}/{total}] OK | GT: {item['is_fake_ground_truth']} | PRED: {is_deepfake_pred} | Conf: {confidence:.2f}")
else:
print(f"[{i+1}/{total}] B艂膮d API ({r.status_code}): {r.text}")
raw_results.append({"id": i, "status": f"API_ERROR_{r.status_code}", "ground_truth": item["is_fake_ground_truth"]})
except Exception as e:
print(f"[{i+1}/{total}] B艂膮d po艂膮czenia: {e}")
raw_results.append({"id": i, "status": "CONNECTION_ERROR", "ground_truth": item["is_fake_ground_truth"]})
return raw_results
def process_and_save_results(raw_results):
"""Wylicza metryki, zapisuje raporty oraz generuje wykresy."""
df_all = pd.DataFrame(raw_results)
df_all.to_csv("evaluation_raw_results.csv", index=False, encoding="utf-8")
print("[+] Zapisano surowe wyniki do: evaluation_raw_results.csv")
# Filtrujemy tylko pomy艣lne wykonania do wyliczenia statystyk
df_success = df_all[df_all["status"] == "SUCCESS"].copy()
if df_success.empty:
print("[-] Brak pomy艣lnych wynik贸w analizy. Wykresy i raporty nie zostan膮 wygenerowane.")
return
y_true = df_success["ground_truth"].astype(bool).tolist()
y_pred = df_success["predicted"].astype(bool).tolist()
# Obliczamy ci膮g艂e prawdopodobie艅stwo przynale偶no艣ci do klasy FAKE (potrzebne do krzywej ROC)
# Je艣li model przewidzia艂 FAKE (True): prawdopodobie艅stwo FAKE to 'confidence'
# Je艣li model przewidzia艂 REAL (False): prawdopodobie艅stwo FAKE to '1.0 - confidence'
y_prob_fake = []
for _, row in df_success.iterrows():
conf = row["confidence"]
pred = row["predicted"]
y_prob_fake.append(conf if pred else 1.0 - conf)
acc = accuracy_score(y_true, y_pred)
report = classification_report(y_true, y_pred, target_names=["REAL (Human)", "FAKE (AI)"])
avg_time = df_success["analysis_time"].mean()
# 1. Zapisywanie raportu tekstowego
report_filename = "evaluation_summary_report.txt"
with open(report_filename, "w", encoding="utf-8") as f:
f.write("==================================================\n")
f.write(" RAPORT JAKO艢CI US艁UGI DETEKCJI TEKSTU \n")
f.write("==================================================\n")
f.write(f"Zanalizowano pomy艣lnie pr贸bki: {len(df_success)} / {len(df_all)}\n")
f.write(f"Og贸lna dok艂adno艣膰 (Accuracy): {acc:.2%}\n")
f.write(f"艢redni czas analizy: {avg_time:.3f} sekundy\n\n")
f.write("Szczeg贸艂owe metryki klasyfikacji:\n")
f.write(report)
f.write("==================================================\n")
print(f"[+] Zapisano tekstowy raport ko艅cowy do: {report_filename}")
# Wy艣wietlenie raportu w konsoli
print("\n" + "="*50 + "\n" + f"DOK艁ADNO艢膯 SYSTEMU: {acc:.2%}" + "\n" + "="*50)
print(report)
# 2. Wykres: Macierz Pomy艂ek (Confusion Matrix)
cm = confusion_matrix(y_true, y_pred)
plt.figure(figsize=(6, 5))
sns.heatmap(
cm, annot=True, fmt="d", cmap="Blues",
xticklabels=["REAL (Human)", "FAKE (AI)"],
yticklabels=["REAL (Human)", "FAKE (AI)"]
)
plt.title("Macierz Pomy艂ek (Confusion Matrix)")
plt.ylabel("Warto艣膰 Rzeczywista")
plt.xlabel("Warto艣膰 Przewidziana")
plt.tight_layout()
plt.savefig("confusion_matrix.png")
print("[+] Wygenerowano wykres: confusion_matrix.png")
plt.close()
# 3. Wykres: Krzywa ROC
fpr, tpr, _ = roc_curve(y_true, y_prob_fake)
roc_auc = auc(fpr, tpr)
plt.figure(figsize=(6, 5))
plt.plot(fpr, tpr, color="darkorange", lw=2, label=f"Krzywa ROC (AUC = {roc_auc:.2f})")
plt.plot([0, 1], [0, 1], color="navy", lw=2, linestyle="--")
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel("False Positive Rate (1 - Specyficzno艣膰)")
plt.ylabel("True Positive Rate (Czu艂o艣膰 / Recall)")
plt.title("Krzywa ROC (Receiver Operating Characteristic)")
plt.legend(loc="lower right")
plt.tight_layout()
plt.savefig("roc_curve.png")
print("[+] Wygenerowano wykres: roc_curve.png")
plt.close()
if __name__ == "__main__":
setup_test_guild()
test_set = prepare_dataset(SAMPLE_SIZE)
raw_results = run_evaluation(test_set)
process_and_save_results(raw_results) |