Spaces:
Sleeping
Sleeping
File size: 23,167 Bytes
c73b203 bef9357 c73b203 010abe9 bef9357 c73b203 bef9357 c73b203 bef9357 c73b203 43cfdee bef9357 43cfdee c73b203 43cfdee bef9357 43cfdee c73b203 bef9357 43cfdee bef9357 43cfdee bef9357 010abe9 bef9357 43cfdee bef9357 43cfdee bef9357 43cfdee bef9357 43cfdee bef9357 43cfdee 010abe9 43cfdee bef9357 43cfdee bef9357 43cfdee bef9357 43cfdee c73b203 bef9357 43cfdee c73b203 bef9357 c73b203 bef9357 43cfdee bef9357 43cfdee c73b203 43cfdee c73b203 43cfdee c73b203 bef9357 43cfdee c73b203 43cfdee 010abe9 43cfdee bef9357 43cfdee bef9357 c73b203 bef9357 | 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 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | import gradio as gr
import json, csv, os, hashlib
from datetime import datetime
ADMIN_HASH = "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" # "admin"
RESULTS = "vysledky.csv"
FEEDBACK = "zpetna_vazba.csv"
for f, cols in [(RESULTS, ['cas','kod','typ','skore','max','procenta','odpovedi']),
(FEEDBACK, ['cas','kod','typ','obt_testu','sroz_testu','uzit_testu','obt_vyuky','sroz_vyuky','uzit_vyuky','komentar'])]:
if not os.path.exists(f):
with open(f, 'w', newline='', encoding='utf-8') as file:
csv.writer(file).writerow(cols)
TESTS = {
"STAFF": {
"nazev": "Test pro administrativní pracovníky (STAFF)",
"questions": [
{
"q": "Jaká je doporučená struktura efektivního promptu pro práci s AI?",
"ctx": "Prompt je instrukce, kterou AI zadáváte. Jeho struktura ovlivňuje kvalitu odpovědí.",
"opts": [
"A) Role + Kontext + Úkol + Formát",
"B) Pouze úkol, ostatní AI domyslí sama",
"C) Poskytnutí jasné role AI zlepšuje kvalitu odpovědí",
"D) Formát výstupu není důležitý",
"E) Kontext pomáhá AI lépe pochopit situaci"
],
"ans": ["A","C","E"]
},
{
"q": "Co přesně znamená termín 'zero-shot prompting'?",
"ctx": "Zero-shot je základní technika práce s AI, kdy modelu poskytujeme pouze instrukci bez dalších příkladů.",
"opts": [
"A) Poskytnutí jednoho vzorového příkladu",
"B) Zadání instrukce bez jakýchkoliv příkladů",
"C) Poskytnutí tří vzorových příkladů",
"D) Nejjednodušší forma práce s AI",
"E) Vždy poskytuje nejlepší výsledky"
],
"ans": ["B","D"]
},
{
"q": "Co je 'answer pressure testing' a k čemu slouží?",
"ctx": "Answer pressure testing je technika, kterou testujeme spolehlivost odpovědí AI a snižujeme riziko chyb.",
"opts": [
"A) Technika pro zrychlení generování odpovědí",
"B) Žádost, aby AI zkontrolovala a zdůvodnila své odpovědi",
"C) Příklad: 'Jsi si tímto výsledkem jistý? Zkontroluj svoje úvahy.'",
"D) Pomáhá odhalit případné halucinace AI",
"E) Snižuje kvalitu odpovědí tím, že AI zmate"
],
"ans": ["B","C","D"]
},
{
"q": "Které z následujících úkolů lze bezpečně řešit pomocí AI v kancelářské práci?",
"ctx": "AI je užitečná pro mnoho úkolů, ale ne všechny jsou pro ni vhodné nebo bezpečné.",
"opts": [
"A) Shrnutí dlouhých dokumentů do kratší formy",
"B) Extrakce konkrétních informací (jména, data, částky) z dokumentů",
"C) Anonymizace osobních údajů v dokumentech",
"D) Fyzická archivace papírových dokumentů",
"E) Překlad textů a změna stylu komunikace"
],
"ans": ["A","B","C","E"]
},
{
"q": "Co přesně jsou 'halucinace' v kontextu AI systémů?",
"ctx": "Halucinace jsou jedním z nejzávažnějších rizik při práci s AI a je důležité jim porozumět.",
"opts": [
"A) AI vymýšlí informace, které vypadají věrohodně, ale jsou nepravdivé",
"B) Halucinace jsou vždy snadno rozpoznatelné",
"C) Je nezbytné vždy ověřovat důležitá fakta z jiných zdrojů",
"D) Answer pressure testing může pomoci odhalit halucinace",
"E) Nové modely AI už halucinace nemají"
],
"ans": ["A","C","D"]
},
{
"q": "Co je 'token' a proč je tento pojem důležitý?",
"ctx": "Token je základní jednotka, se kterou AI systémy pracují. Pochopení tokenů je klíčové pro efektivní práci s AI.",
"opts": [
"A) Token odpovídá přibližně 4 znakům textu",
"B) Token je základní jednotka zpracování textu v AI",
"C) Token je měna pro placení AI služeb",
"D) AI modely mají limit na počet tokenů",
"E) Token je totéž co jedno slovo"
],
"ans": ["A","B","D"]
},
{
"q": "Jak správně pracovat s AI při respektování GDPR?",
"ctx": "GDPR chrání osobní údaje občanů EU. Při práci s AI je nutné dodržovat tyto právní požadavky.",
"opts": [
"A) Anonymizovat všechny osobní údaje před nahráním do AI",
"B) GDPR se na práci s AI nevztahuje",
"C) Nikdy neposílat citlivá data do veřejných AI systémů",
"D) Znát politiku zpracování dat AI platformy",
"E) Osobní údaje lze do AI nahrávat bez omezení"
],
"ans": ["A","C","D"]
},
{
"q": "Jak správně pracovat s češtinou vs. angličtinou při použití AI?",
"ctx": "Volba jazyka ovlivňuje kvalitu odpovědí AI systémů, protože byly trénovány primárně na anglických datech.",
"opts": [
"A) Pro češtinu explicitně uvést 'v češtině'",
"B) AI automaticky rozpozná jazyk vždy správně",
"C) Pro vědu preferovat angličtinu",
"D) Kvalita je stejná pro všechny jazyky",
"E) Lze kombinovat jazyky podle potřeby"
],
"ans": ["A","C","E"]
},
{
"q": "Co znamená 'chain-of-thought prompting' a kdy ho použít?",
"ctx": "Chain-of-thought je pokročilá technika, kdy žádáme AI o postupné vysvětlení jednotlivých kroků řešení.",
"opts": [
"A) Žádost o postupné vysvětlení kroků",
"B) Nejrychlejší způsob generování",
"C) Užitečné pro komplexní analýzy",
"D) Příklad: 'Analyzuj: 1) témata 2) problémy 3) řešení'",
"E) Nevhodné pro analytické úlohy"
],
"ans": ["A","C","D"]
},
{
"q": "Co je 'role-playing' v kontextu práce s AI?",
"ctx": "Role-playing je technika, kdy AI přiřazujeme konkrétní roli či identitu, což ovlivňuje styl a obsah odpovědí.",
"opts": [
"A) AI přiřadíte konkrétní roli",
"B) Příklad: 'Jsi zkušený HR manažer s 20 lety praxe'",
"C) Role nijak neovlivňuje odpovědi",
"D) Role pomáhá přizpůsobit jazyk a odbornost",
"E) Používá se pouze pro zábavu"
],
"ans": ["A","B","D"]
}
]
},
"ACADEMIC": {
"nazev": "Test pro akademické pracovníky (ACADEMIC)",
"questions": [
{
"q": "Jaká je struktura akademického promptu?",
"ctx": "Akademická práce vyžaduje přesnější a rigoróznější strukturu promptů než běžné použití AI.",
"opts": [
"A) Role + Kontext + Úkol + Formát + Omezení",
"B) Pouze úkol",
"C) Požadavek na rozlišení fakta/interpretace",
"D) Žádost o označení míry jistoty",
"E) Formát není důležitý"
],
"ans": ["A","C","D"],
"pts": 1
},
{
"q": "Co je 'answer pressure testing' a proč je v akademii kritický?",
"ctx": "V akademickém kontextu je spolehlivost informací zásadní, proto je answer pressure testing klíčovou technikou.",
"opts": [
"A) Technika systematického zpochybňování",
"B) Příklad: 'Jsi si jistý? Odkud to? Alternativy?'",
"C) Pomáhá odhalit halucinace",
"D) V akademii méně důležitý než v kanceláři",
"E) Nutí AI přiznat nejistotu"
],
"ans": ["A","B","C","E"],
"pts": 1
},
{
"q": "Proč jsou halucinace v akademii zvlášť problematické?",
"ctx": "V akademickém výzkumu může jediná chyba diskreditovat celou práci. Halucinace AI představují závažné riziko.",
"opts": [
"A) Jedna vymyšlená citace diskredituje celou práci",
"B) V nových modelech již vyřešeny",
"C) AI prezentuje vymyšlené info přesvědčivě",
"D) Týkají se především citací a faktů",
"E) Jsou vždy snadno rozpoznatelné"
],
"ans": ["A","C","D"],
"pts": 1
},
{
"q": "Rozdíl mezi 'asistencí' a 'nahrazením úsudku'?",
"ctx": "V akademické práci je klíčové rozlišovat, kdy AI pomáhá a kdy za nás myslí. To má etické i metodologické důsledky.",
"opts": [
"A) Asistence = AI strukturuje MOJE myšlenky",
"B) Nahrazení = AI vytváří závěry které přebírám",
"C) V akademii irelevantní",
"D) Asistence = finální odpovědnost na mně",
"E) Oba postupy stejně přijatelné"
],
"ans": ["A","B","D"],
"pts": 1
},
{
"q": "Jak správně pracovat s AI a GDPR v akademickém výzkumu?",
"ctx": "Akademický výzkum často pracuje s citlivými daty respondentů. GDPR stanovuje přísné požadavky na jejich ochranu.",
"opts": [
"A) Anonymizovat data před nahráním",
"B) Data z výzkumu lze nahrávat bez omezení",
"C) Necitlivá data respondentů do veřejných AI",
"D) Enterprise AI nabízí lepší ochranu",
"E) GDPR se na akademii nevztahuje"
],
"ans": ["A","C","D"],
"pts": 1
},
{
"q": "Proč je pro akademii doporučena angličtina?",
"ctx": "AI modely byly trénovány primárně na anglických akademických textech, což má důsledky pro kvalitu odpovědí.",
"opts": [
"A) AI trénovány primárně na anglických akademických textech",
"B) Kvalita v češtině a angličtině je stejná",
"C) Pro vědu přesnější odpovědi v angličtině",
"D) Pro admin práci lepší čeština",
"E) Angličtina není důležitá"
],
"ans": ["A","C","D"],
"pts": 1
},
{
"q": "Které použití AI je přijatelné a které ne?",
"ctx": "V akademické práci existují jasné hranice mezi přijatelným a nepřijatelným použitím AI. Je klíčové je rozlišovat.",
"opts": [
"A) PŘIJATELNÉ: Návrh struktury mých myšlenek",
"B) PŘIJATELNÉ: Generování závěrů výzkumu",
"C) PŘIJATELNÉ: Identifikace slabých míst argumentace",
"D) NEPŘIJATELNÉ: Auto-psaní sekcí bez kontroly",
"E) PŘIJATELNÉ: Delegování hodnotových soudů"
],
"ans": ["A","C","D"],
"pts": 1.5
},
{
"q": "Jak pracovat s epistemickou nejistotou?",
"ctx": "AI systémy nemají skutečné porozumění a často si nejsou jisté. Musíme s touto nejistotou pracovat systematicky.",
"opts": [
"A) Požadovat explicitní míru jistoty",
"B) Důvěřovat autoritativnímu tónu AI",
"C) Ověřovat tvrzení z primárních zdrojů",
"D) Žádat alternativní interpretace",
"E) AI jako konečný arbitr"
],
"ans": ["A","C","D"],
"pts": 1.5
},
{
"q": "Jak správně pracovat se zdroji a citacemi?",
"ctx": "AI systémy mají tendenci vymýšlet realisticky vypadající citace. To představuje závažné riziko pro akademickou integritu.",
"opts": [
"A) AI často vymýšlí věrohodné citace",
"B) Každou citaci ověřit v databázích",
"C) Answer pressure: 'Odkud? Je DOI platné?'",
"D) Citace z AI spolehlivé pro publikování",
"E) Preferovat: PDF → shrnutí, ne 'cituj studie'"
],
"ans": ["A","B","C","E"],
"pts": 1.5
},
{
"q": "Co musí akademik uvést ohledně použití AI?",
"ctx": "Transparentnost je základem akademické integrity. Použití AI nástrojů musí být jasně deklarováno.",
"opts": [
"A) Neuvádí se",
"B) Transparentně uvést v metodologii",
"C) AI je nástroj, ne autor - ale uvést použití",
"D) Citovat AI podle standardů (APA)",
"E) Závisí na pravidlech instituce"
],
"ans": ["B","C","D","E"],
"pts": 1.5
},
{
"q": "Proč AI nemá 'skutečné porozumění'?",
"ctx": "Pochopení limitů AI je klíčové pro její zodpovědné použití v akademickém kontextu.",
"opts": [
"A) AI je statistický predikční model",
"B) Předpovídá pokračování textu z vzorců",
"C) Když neví, stejně něco vygeneruje",
"D) Nové modely už mají lidské porozumění",
"E) Proto nutná epistemická opatrnost"
],
"ans": ["A","B","C","E"],
"pts": 1.5
},
{
"q": "Jaká je role AI v akademickém výzkumu?",
"ctx": "Je důležité správně definovat roli AI v akademické práci - co může a co nemůže dělat.",
"opts": [
"A) Pomocný nástroj pro strukturování",
"B) Náhrada za odborný úsudek",
"C) Kritický partner pro zpochybňování",
"D) Autoritativní zdroj pravdy",
"E) Nástroj pro podporu, ne nahrazení"
],
"ans": ["A","C","E"],
"pts": 1.5
}
]
}
}
def check(pwd):
return hashlib.sha256(pwd.encode()).hexdigest() == ADMIN_HASH
def score(typ, ans):
correct = sum(q.get("pts",1) for i,q in enumerate(TESTS[typ]["questions"])
if set(ans.get(f"q_{i}",[]))==set(q["ans"]))
total = sum(q.get("pts",1) for q in TESTS[typ]["questions"])
return correct, total
def save_result(kod, typ, sc, mx, ans):
with open(RESULTS, 'a', newline='', encoding='utf-8') as f:
csv.writer(f).writerow([datetime.now().isoformat(), kod, typ, sc, mx,
f"{sc/mx*100:.1f}%", json.dumps(ans, ensure_ascii=False)])
def save_fb(kod, typ, ot, st, ut, ov, sv, uv, kom):
with open(FEEDBACK, 'a', newline='', encoding='utf-8') as f:
csv.writer(f).writerow([datetime.now().isoformat(), kod, typ, ot, st, ut, ov, sv, uv, kom])
def get_file(pwd, which):
if not check(pwd):
return None, "❌ Špatné heslo"
file = RESULTS if which=="r" else FEEDBACK
if not os.path.exists(file):
return None, "📭 Zatím žádná data"
return file, f"✅ {file} připraven ke stažení"
with gr.Blocks(title="Test AI KTF") as app:
gr.Markdown("# 🎓 Test znalostí: Generativní AI\n**Katolická teologická fakulta UK, Praha 2025**")
kod_s, typ_s = gr.State(""), gr.State("")
with gr.Tab("🔐 Start"):
gr.Markdown("### Zahájení testu")
gr.Markdown("Pro zahájení zadejte váš unikátní kód a vyberte typ testu.")
kod = gr.Textbox(label="Váš unikátní kód", placeholder="KTF2025-001", info="Tento kód obdržíte od organizátora")
typ = gr.Radio([
("STAFF - Administrativní pracovníci (10 otázek)", "STAFF"),
("ACADEMIC - Výzkumní pracovníci (12 otázek)", "ACADEMIC")
], label="Typ testu", info="Vyberte test odpovídající vaší roli")
go = gr.Button("Začít test", variant="primary", size="lg")
msg = gr.Markdown("")
with gr.Tab("📝 Test"):
info = gr.Markdown("")
qs = []
for i in range(12):
with gr.Group(visible=False) as g:
qt = gr.Markdown("")
qctx = gr.Markdown("", elem_classes="question-context")
qc = gr.CheckboxGroup(label="⚠️ Vyberte VŠECHNY správné odpovědi")
qs.append((g,qt,qctx,qc))
send = gr.Button("Odeslat test", variant="primary", size="lg", visible=False)
send_msg = gr.Markdown("")
with gr.Tab("📊 Výsledky"):
res = gr.Markdown("")
gr.Markdown("---")
gr.Markdown("### 💬 Zpětná vazba")
gr.Markdown("*Vaše zpětná vazba je anonymní a pomůže nám zlepšit jak test, tak celou výuku.*")
gr.Markdown("#### Hodnocení testu:")
obt_t = gr.Radio(["Příliš snadný", "Přiměřený", "Příliš těžký"], label="Obtížnost testu")
sroz_t = gr.Radio(["Výborná", "Dobrá", "Špatná"], label="Srozumitelnost otázek")
uzit_t = gr.Radio(["Velmi užitečný", "Užitečný", "Málo užitečný"], label="Užitečnost testu pro praxi")
gr.Markdown("#### Hodnocení výuky (kurzu AI):")
obt_v = gr.Radio(["Příliš snadná", "Přiměřená", "Příliš těžká"], label="Obtížnost výuky")
sroz_v = gr.Radio(["Výborná", "Dobrá", "Špatná"], label="Srozumitelnost výkladu")
uzit_v = gr.Radio(["Velmi užitečná", "Užitečná", "Málo užitečná"], label="Užitečnost pro praxi")
kom = gr.Textbox(label="Váš komentář (nepovinné)", placeholder="Sdílejte své postřehy k testu nebo výuce...", lines=3)
fb = gr.Button("Odeslat zpětnou vazbu", variant="secondary")
fb_msg = gr.Markdown("")
with gr.Tab("👨💼 Admin"):
gr.Markdown("### 🔒 Administrátorský přístup")
gr.Markdown("*Pouze pro organizátory kurzu - stahování výsledků*")
pwd = gr.Textbox(label="Admin heslo", type="password", placeholder="Výchozí: admin")
with gr.Row():
dlr = gr.Button("📥 Stáhnout výsledky testů")
dlf = gr.Button("📥 Stáhnout zpětnou vazbu")
dl = gr.File(label="CSV soubor ke stažení")
dlm = gr.Markdown("")
gr.Markdown("*Pro změnu hesla upravte ADMIN_HASH v app.py*")
def start(k, t):
if not k or not t:
return {msg: "❌ Prosím vyplňte kód i typ testu", kod_s: "", typ_s: ""}
test = TESTS[t]
upd = {
msg: f"✅ Test byl zahájen! **→ Přejděte na záložku 'Test'**",
kod_s: k,
typ_s: t,
info: f"## {test['nazev']}\n\n**Počet otázek:** {len(test['questions'])}\n\n⚠️ **Důležité:** U každé otázky označte VŠECHNY správné odpovědi!",
send: gr.update(visible=True),
send_msg: ""
}
for i in range(12):
if i < len(test["questions"]):
q = test["questions"][i]
upd[qs[i][0]] = gr.update(visible=True)
upd[qs[i][1]] = f"### Otázka {i+1}\n\n{q['q']}"
upd[qs[i][2]] = f"*{q.get('ctx', '')}*"
upd[qs[i][3]] = gr.update(choices=q["opts"], value=[])
else:
upd[qs[i][0]] = gr.update(visible=False)
return upd
def submit(k, t, *a):
if not k:
return "❌ Chyba: Test nebyl správně zahájen", ""
ans = {f"q_{i}": a[i] for i in range(len(TESTS[t]["questions"]))}
sc, mx = score(t, ans)
save_result(k, t, sc, mx, ans)
ok = sc >= (7 if t=="STAFF" else 8)
poz = "minimálně 7 bodů" if t=="STAFF" else "minimálně 8 bodů"
result = f"""## {'✅ Gratulujeme! Test úspěšně splněn!' if ok else '❌ Test nesplněn'}
**Váš výsledek:** {sc:.1f} / {mx} bodů ({sc/mx*100:.1f}%)
**Požadavek pro splnění:** {poz}
{'🎉 **Úspěšně jste absolvovali test!**' if ok else '😔 Bohužel jste nedosáhli minimálního počtu bodů. Doporučujeme prostudovat materiály a zkusit test znovu.'}
---
**📊 Podrobnosti:**
- Kód účastníka: {k}
- Typ testu: {t}
- Datum a čas: {datetime.now().strftime('%d.%m.%Y v %H:%M')}
---
### ⬇️ Co dál?
**Prosím, poskytněte nám zpětnou vazbu níže** - pomůžete nám zlepšit jak test, tak celou výuku. Zpětná vazba je anonymní a zabere jen 2 minuty. Děkujeme! 🙏
"""
nav_msg = "# ✅ Test odeslán!\n\n**→ Přejděte na záložku 'Výsledky' pro zobrazení výsledků a zpětnou vazbu**"
return result, nav_msg
go.click(start, [kod,typ],
[msg,kod_s,typ_s,info,send,send_msg]+[x for g in qs for x in g])
send.click(submit, [kod_s,typ_s]+[q[3] for q in qs], [res, send_msg])
fb.click(lambda k,t,ot,st,ut,ov,sv,uv,c: (save_fb(k,t,ot,st,ut,ov,sv,uv,c), "✅ **Děkujeme za zpětnou vazbu!** Vaše připomínky jsou pro nás velmi cenné.")[1] if k else "❌ Nelze odeslat - test nebyl dokončen",
[kod_s,typ_s,obt_t,sroz_t,uzit_t,obt_v,sroz_v,uzit_v,kom], fb_msg)
dlr.click(lambda p: get_file(p,"r"), pwd, [dl,dlm])
dlf.click(lambda p: get_file(p,"f"), pwd, [dl,dlm])
app.launch() |