xiaohy commited on
Commit
4272ed3
·
verified ·
1 Parent(s): f637360

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -153
app.py CHANGED
@@ -202,10 +202,10 @@ def cb_sample(src):
202
  pool=member_data if src=="成员数据(训练集)" else non_member_data
203
  s=pool[np.random.randint(len(pool))]; m=s['metadata']
204
  tm={'calculation':'基础计算','word_problem':'应用题','concept':'概念问答','error_correction':'错题订正'}
205
- md=("| 字段 (Field) | 记录(Value) |\n|---|---|\n| 👤 姓名 | "+clean_text(str(m.get('name','')))+
206
- " |\n| 🆔 学号 | "+clean_text(str(m.get('student_id','')))+
207
- " |\n| 🏫 班级 | "+clean_text(str(m.get('class','')))+
208
- " |\n| 💯 成绩 | "+clean_text(str(m.get('score','')))+" 分 |\n| 📝 类型 | "+tm.get(s.get('task_type',''),'')+" |\n")
209
  return md, clean_text(s.get('question','')), clean_text(s.get('answer',''))
210
 
211
 
@@ -243,16 +243,16 @@ def cb_attack(idx, src, target):
243
  pl,pc=("训练成员","🔴") if pred else ("非训练成员","🟢")
244
  al,ac=("训练成员","🔴") if is_mem else ("非训练成员","🟢")
245
  if correct and pred and is_mem:
246
- v="⚠️ **攻击成功:隐私泄露**\n\n> 模型对该样本过于熟悉(Loss < 阈值),攻击者成功判定为训练数据。"
247
  elif correct:
248
- v="✅ **判定正确:边界安全**\n\n> 攻击者的判定与真实身份一致,符合安全预期。"
249
  else:
250
- v="🛡️ **防御成功:干扰生效**\n\n> 攻击者的判定发生错误,防御策略起到了保护作用。"
251
- res=(v+"\n\n**🎯 攻击目标**: `"+lbl+"` | **📊 AUC风险值**: `"+f"{auc_v:.4f}"+"`\n\n"
252
- "| 指标 | 攻击者推测 | 系统真实身份 |\n|---|---|---|\n"
253
  "| 身份 | "+pc+" "+pl+" | "+ac+" "+al+" |\n"
254
- "| 核心参数 | Loss: `"+f"{loss:.4f}"+"` | 判定阈值: `"+f"{thr:.4f}"+"` |\n")
255
- qtxt="**📝 样本题号 #"+str(idx)+"**\n\n"+clean_text(sample.get('question',''))[:500]
256
  return qtxt, gauge, res
257
 
258
 
@@ -266,21 +266,19 @@ def cb_eval(model):
266
  k=EVAL_KEY.get(model,"baseline"); acc=EVAL_ACC.get(model,bl_acc)
267
  q=EVAL_POOL[np.random.randint(len(EVAL_POOL))]; ok=q.get(k,q.get('baseline',False))
268
  ic="✅ 正确" if ok else "❌ 错误"
269
- note="\n\n> 💡 输出扰动不改变模型结构参数,准确率与基线完全一致。" if u"\u03c3" in model else ""
270
- return ("**🖥️ 模型**: `"+model+"` | **准确率**: `"+f"{acc:.1f}%"+"`\n\n"
271
- "| 测试项目 | 内容 |\n|---|---|\n"
272
- "| 🏷️ 类型 | "+q['type_cn']+" |\n| 题目 | "+q['question']+" |\n"
273
- "| 🎯 答案 | "+q['answer']+" |\n| 🤖 判定 | "+ic+" |"+note)
274
 
275
 
276
- # ══════════════ 全新科技 + 等宽高 CSS 皮肤 ══════════════
277
 
278
  CSS = """
279
- /* 1. 带有科技网格全局背景 */
280
  body {
281
  background-color: #f1f5f9 !important;
282
- background-image: radial-gradient(#cbd5e1 1px, transparent 1px) !important;
283
- background-size: 24px 24px !important;
284
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
285
  }
286
  .gradio-container {
@@ -288,14 +286,14 @@ body {
288
  margin: 40px auto !important;
289
  }
290
 
291
- /* 2. 科技感悬浮 Title 面板 */
292
  .title-area {
293
  background: #ffffff;
294
- padding: 28px 40px;
295
  border-radius: 12px;
296
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
297
- margin-bottom: 24px;
298
- border-left: 6px solid #2563eb; /* 克莱因蓝修��线 */
299
  text-align: left;
300
  }
301
  .title-area h1 {
@@ -314,27 +312,27 @@ body {
314
 
315
  /* 3. 核心大招:死死锁住所有标签页的大小,防止跳动 */
316
  .tabitem {
317
- background: rgba(255, 255, 255, 0.98) !important;
318
  border-radius: 0 0 12px 12px !important;
319
  border: 1px solid #e2e8f0 !important;
320
  border-top: none !important;
321
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05) !important;
322
  padding: 32px 40px !important;
323
 
324
- /* 让所有面高度一致的魔法参数 */
325
  height: 760px !important;
326
  max-height: 760px !important;
327
  overflow-y: auto !important;
328
  overflow-x: hidden !important;
329
  }
330
 
331
- /* 优雅隐藏式滚动条 */
332
  .tabitem::-webkit-scrollbar { width: 6px; }
333
  .tabitem::-webkit-scrollbar-track { background: transparent; }
334
  .tabitem::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; }
335
  .tabitem::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
336
 
337
- /* 4. Tab 导航栏拟设计 */
338
  .tab-nav {
339
  border-bottom: none !important;
340
  gap: 4px !important;
@@ -345,7 +343,7 @@ body {
345
  padding: 12px 24px !important;
346
  font-weight: 600 !important;
347
  color: #64748b !important;
348
- background: #e2e8f0 !important;
349
  border: 1px solid #e2e8f0 !important;
350
  border-bottom: none !important;
351
  border-radius: 10px 10px 0 0 !important;
@@ -363,7 +361,7 @@ body {
363
  box-shadow: 0 -4px 6px -2px rgba(0,0,0,0.02) !important;
364
  }
365
 
366
- /* 5. 内部标题排版与修饰 */
367
  .prose h2 {
368
  font-size: 1.3rem !important;
369
  color: #0f172a !important;
@@ -379,7 +377,7 @@ body {
379
  margin-top: 1.5em !important;
380
  }
381
 
382
- /* 6. 高级数据表格 (斑马纹) */
383
  .prose table {
384
  width: 100% !important;
385
  border-collapse: separate !important;
@@ -406,7 +404,7 @@ body {
406
  .prose tr:last-child td { border-bottom: none !important; }
407
  .prose tr:hover td { background: #f0f9ff !important; }
408
 
409
- /* 7. 纯色科技感按钮 */
410
  button.primary {
411
  background: #2563eb !important;
412
  color: white !important;
@@ -423,7 +421,7 @@ button.primary:hover {
423
  box-shadow: 0 6px 10px -1px rgba(37, 99, 235, 0.3) !important;
424
  }
425
 
426
- /* 8. 提示/警报框 (突出显示) */
427
  .prose blockquote {
428
  border-left: 4px solid #3b82f6 !important;
429
  background: #eff6ff !important;
@@ -434,161 +432,165 @@ button.primary:hover {
434
  margin: 1.5em 0 !important;
435
  }
436
 
 
437
  footer { display: none !important; }
438
  """
439
 
440
  with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Base(), css=CSS) as demo:
441
 
442
  gr.HTML("""<div class="title-area">
443
- <h1>🎓 教育大模型中的成员推理攻击及其防御研究</h1>
444
- <p>Membership Inference Attack & Defense on Educational LLM Dashboard</p>
445
  </div>""")
446
 
447
- # ═══════ Tab 1: 实验总览 ═══════
448
- with gr.Tab("📊 实验总览"):
449
- with gr.Row():
450
- with gr.Column(scale=1):
451
- gr.Markdown(
452
- "## 📌 研究背景目标\n\n"
453
- "大语言模型在教育领域应用日益广泛(如AI数学辅导),模型训练不可避免地接触学生敏感数据。"
454
- "**成员推理攻击 (MIA)** 可判断某条数据是否参与了训练,构成隐私威胁。\n\n"
455
- "本研究基于 **" + model_name + "** 微调的数学辅导模型,验证MIA风险的存在性,"
456
- "并探索 **签平滑**(训练期)与 **输出扰动**(推理期)两类防御策略的有效性及其对模型效用的影响。\n\n"
457
- "## 🚀 实验流程\n\n"
458
- "| 阶段 | 内容 | 方法 |\n|---|---|---|\n"
459
- "| 1. 数据准备 | 2000条数学辅导对话 | 模板化生成,含姓名/学号/成绩 |\n"
460
- "| 2. 基线训练 | " + model_name + " + LoRA | 标准微调(r=8, alpha=16, 10 epochs) |\n"
461
- "| 3. 防御训练 | " + u"\u03b5=0.02 / \u03b5=0.2" + " | 两组标签平滑参数分别训练 |\n"
462
- "| 4. 攻击测试 | 3个模型 + 3组扰动 | Loss阈值判定,AUC评估 |\n"
463
- "| 5. 效用评估 | 300道数学题 | 6种配置分别测试准确率 |\n"
464
- )
465
- with gr.Column(scale=1):
466
- gr.Markdown("## 📈 实验核心指标\n")
467
- gr.Markdown(
468
- "| 🛡️ 策略配置 | 📊 AUC | 🎯 准确率 | 💡 说明 |\n|---|---|---|---|\n"
469
- "| **基线(无防御)** | **" + f"{bl_auc:.4f}" + "** | " + f"{bl_acc:.1f}%" + " | 攻击风险基准 |\n"
470
- "| " + u"LS(\u03b5=0.02)" + " | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | 训练期防御 |\n"
471
- "| " + u"LS(\u03b5=0.2)" + " | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | 训练期防御 |\n"
472
- "| " + u"OP(\u03c3=0.01)" + " | " + f"{op001_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n"
473
- "| " + u"OP(\u03c3=0.015)" + " | " + f"{op0015_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n"
474
- "| " + u"OP(\u03c3=0.02)" + " | " + f"{op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n\n"
475
- "> 💡 **指标提示**: AUC越接近0.5 = 防御越有效;准确率越高 = 模型效用越好。"
476
- )
477
-
478
- # ═══════ Tab 2: 数据与模型 (双列修复版) ═══════
479
- with gr.Tab("📁 数据与模型"):
480
- with gr.Row():
481
- with gr.Column():
482
- gr.Markdown(
483
- "## 📦 实验数据集概况\n\n"
484
- "| 数据 | 量 | 用途 | 说明 |\n|---|---|---|---|\n"
485
- "| 🔴 成员数据 | 1000条 | 模型训练 | 模型会\"记住\",Loss偏低 |\n"
486
- "| 🟢 非成员数据 | 1000条 | 攻击对照 | 模型\"没见过\",Loss偏高 |\n\n"
487
- "> ⚠️ 两组数据格式完全相同(均含隐私字段),这是MIA实验的标准设置——攻击者无法从格式区分成员与否。"
488
- )
489
- with gr.Column():
490
- gr.Markdown(
491
- "## 🗂️ 任务类型分布\n\n"
492
- "| 任务类别 | 数据数量 | 占比权重 |\n|---|---|---|\n"
493
- "| 🧮 基础计算 | 800 | 40% |\n| 📝 应用题 | 600 | 30% |\n| 🧠 概念问答 | 400 | 20% |\n| ✍️ 错题订正 | 200 | 10% |\n"
494
- )
495
- gr.Markdown("## 🔍 数据样例浏览提取")
496
  with gr.Row(equal_height=True):
497
  with gr.Column(scale=2):
498
- d_src = gr.Radio(["成员数据(训练集)","非成员数据(测试集)"], value="成员数据(训练集)", label="选择靶向数据来源")
499
- d_btn = gr.Button("🎲 随机提取样本", variant="primary")
500
  d_meta = gr.Markdown()
501
  with gr.Column(scale=3):
502
- d_q = gr.Textbox(label="🧑‍🎓 学生提问 (Prompt)", lines=4, interactive=False)
503
- d_a = gr.Textbox(label="🤖 标准回答 (Ground Truth)", lines=4, interactive=False)
504
  d_btn.click(cb_sample, [d_src], [d_meta, d_q, d_a])
505
 
506
- # ═══════ Tab 3: 攻击与防御验证 ═══════
507
- with gr.Tab("🎯 攻击验证"):
508
- gr.Markdown("## 🕵️ 成员推理攻击交互演示\n\n"
509
- "配置攻击目标实体与数据源,系统将执行 Loss 计算并映射攻击边界,以此判定数据归属。")
510
  with gr.Row(equal_height=True):
511
  with gr.Column(scale=2):
512
  a_target = gr.Radio([u"基线模型 (Baseline)",u"标签平滑 (\u03b5=0.02)",u"标签平滑 (\u03b5=0.2)",
513
  u"输出扰动 (\u03c3=0.01)",u"输出扰动 (\u03c3=0.015)",u"输出扰动 (\u03c3=0.02)"],
514
- value=u"基线模型 (Baseline)", label="选择攻击目标")
515
  a_src = gr.Radio(["成员数据(训练集)","非成员数据(测试集)"], value="成员数据(训练集)", label="数据来源")
516
- a_idx = gr.Slider(0, 999, step=1, value=12, label="定位样本 ID")
517
- a_btn = gr.Button("执行成员推理攻击", variant="primary", size="lg")
518
  a_qtxt = gr.Markdown()
519
  with gr.Column(scale=3):
520
- a_gauge = gr.Plot(label="Loss位置判定 (Decision Boundary)")
521
  a_res = gr.Markdown()
522
  a_btn.click(cb_attack, [a_idx, a_src, a_target], [a_qtxt, a_gauge, a_res])
523
 
524
- # ═══════ Tab 4: 防御效果分析 ═══════
525
- with gr.Tab("🛡️ 防御分析"):
526
- with gr.Row():
527
- with gr.Column():
528
- gr.Markdown("## 📉 MIA攻击AUC全局对比\n\n> 柱子越矮 = AUC越低 = 攻击越难成功 = 防御越有效")
529
- gr.Plot(value=fig_auc_bar())
530
- with gr.Column():
531
- gr.Markdown(
532
- "## ⚙️ 防御机制技术说明\n\n"
533
- "| 维度 | 标签平滑 (Label Smoothing) | 输出扰动 (Output Perturbation) |\n|---|---|---|\n"
534
- "| **阶段** | 训练期 | 推理期 |\n"
535
- "| **原理** | 软化标签降低记忆 | Loss加噪遮蔽信号 |\n"
536
- "| **需重训** | 是 | 否 |\n"
537
- "| **效用** | 取决于参数 | 无损耗 |\n"
538
- "| **部署** | 训练时介入 | 即插即用 API |\n\n"
539
- "**标签平滑公式**: `y_smooth = (1 - ε) * y_onehot + ε / V`\n\n"
540
- "**输出扰动公式**: `L_perturbed = L_original + N(0, σ²)`\n"
541
- )
542
-
543
- gr.Markdown("## 🏔️ Loss分布形态对比\n### 1. 三个模型(训练期防御效果)\n\n> 蓝色=成员,红色=非成员。两色重叠(Overlap)越多 = 攻击者越难区分")
544
  gr.Plot(value=fig_loss_dist())
545
- gr.Markdown("### 2. 输出扰动效果(推理期防御)\n\n> 在基线模型Loss上加噪声,随噪声方差(σ)增大,双侧分布交融程度")
546
  gr.Plot(value=fig_perturb_dist())
547
 
548
- # ═══════ Tab 5: 效用评估 ═══════
549
- with gr.Tab("⚖️ 效用评估"):
550
- gr.Markdown("## 🎯 数学效用基测试\n\n> 抽取300道复杂数学测试题,评估各安全策略对模型实际解题能力的影响。")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  with gr.Row(equal_height=True):
552
  with gr.Column(): gr.Plot(value=fig_acc_bar())
553
  with gr.Column(): gr.Plot(value=fig_tradeoff())
554
- gr.Markdown("## 🎮 在线效用抽样演示\n\n从测试题库中随机抽取,流式验证不同模型/策略的保留作答情况。")
555
  with gr.Row(equal_height=True):
556
  with gr.Column(scale=1):
557
  e_model = gr.Radio([u"基线模型",u"标签平滑 (\u03b5=0.02)",u"标签平滑 (\u03b5=0.2)",
558
- u"输出扰动 (\u03c3=0.01)",u"输出扰动 (\u03c3=0.015)",u"输出扰动 (\u03c3=0.02)"], value=u"基线模型", label="选择验证模型")
559
- e_btn = gr.Button("🧪 随机抽题测试", variant="primary")
560
  with gr.Column(scale=2):
561
  e_res = gr.Markdown()
562
  e_btn.click(cb_eval, [e_model], [e_res])
563
 
564
- # ═══════ Tab 6: 研究结论 (双列修复版) ═══════
565
- with gr.Tab("📝 研究结论"):
566
- gr.Markdown("## 💡 核心研究发现与最佳实践\n\n---")
567
- with gr.Row():
568
- with gr.Column():
569
- gr.Markdown(
570
- "### 🚨 一、教育大模型存在强MIA风险\n\n"
571
- "基线模型 AUC = **" + f"{bl_auc:.4f}" + "** > 0.5,成员均Loss (" + f"{bl_m_mean:.4f}"
572
- + ") 显著低于非成员 (" + f"{bl_nm_mean:.4f}" + ")。实验铁证表明,模型对训练数据存在极强的可利用记忆效应,教育隐私面临直接威胁。\n\n"
573
- "### 🛡️ 二、标签平滑(训练期防御\n\n"
574
- "| 参数 | AUC | ���确率 | 分析结论 |\n|---|---|---|---|\n"
575
- "| **基线** | " + f"{bl_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 防御裸奔 |\n"
576
- "| **" + u"\u03b5=0.02" + "** | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | 正则化提升泛化红利 |\n"
577
- "| **" + u"\u03b5=0.2" + "** | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | 进入强力防御深水区 |\n\n"
578
- )
579
- with gr.Column():
580
- gr.Markdown(
581
- "### 🎛️ 三、输出扰动(推理防御)\n\n"
582
- "| 参数 | 最终 AUC | AUC 降幅 | 模型准确率 |\n|---|---|---|---|\n"
583
- "| **" + u"\u03c3=0.01" + "** | " + f"{op001_auc:.4f}" + " | " + f"{bl_auc-op001_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n"
584
- "| **" + u"\u03c3=0.015" + "** | " + f"{op0015_auc:.4f}" + " | " + f"{bl_auc-op0015_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n"
585
- "| **" + u"\u03c3=0.02" + "** | " + f"{op002_auc:.4f}" + " | " + f"{bl_auc-op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n\n"
586
- "**结论**: 零效用损失,适合已部署系统的无痛后期加固。\n\n"
587
- "### ⚖️ 四、隐私-效用权衡总结\n\n"
588
- "两类策略机制完美互补:\n"
589
- "1. **标签平滑**:从训练阶段物理阻断模型记忆,且微量平滑具有正向效用收益。\n"
590
- "2. **输出扰动**:从推理阶段统计遮蔽外部嗅探信号,零损耗即插即用。\n"
591
- "> **架构建议**: 业务生产环境中,建议组合使用这两层屏障,构建立体防御体系。"
592
- )
593
 
594
  demo.launch()
 
202
  pool=member_data if src=="成员数据(训练集)" else non_member_data
203
  s=pool[np.random.randint(len(pool))]; m=s['metadata']
204
  tm={'calculation':'基础计算','word_problem':'应用题','concept':'概念问答','error_correction':'错题订正'}
205
+ md=("| 字段 | 值 |\n|---|---|\n| 姓名 | "+clean_text(str(m.get('name','')))+
206
+ " |\n| 学号 | "+clean_text(str(m.get('student_id','')))+
207
+ " |\n| 班级 | "+clean_text(str(m.get('class','')))+
208
+ " |\n| 成绩 | "+clean_text(str(m.get('score','')))+" 分 |\n| 类型 | "+tm.get(s.get('task_type',''),'')+" |\n")
209
  return md, clean_text(s.get('question','')), clean_text(s.get('answer',''))
210
 
211
 
 
243
  pl,pc=("训练成员","🔴") if pred else ("非训练成员","🟢")
244
  al,ac=("训练成员","🔴") if is_mem else ("非训练成员","🟢")
245
  if correct and pred and is_mem:
246
+ v="⚠️ **攻击成功:隐私泄露**\n\n模型对该样本过于熟悉(Loss < 阈值),攻击者成功判定为训练数据。"
247
  elif correct:
248
+ v="✅ **判定正确**\n\n攻击者的判定与真实身份一致。"
249
  else:
250
+ v="🛡️ **防御成功**\n\n攻击者的判定错误,防御起到了保护作用。"
251
+ res=(v+"\n\n**攻击目标**: "+lbl+" | **AUC**: "+f"{auc_v:.4f}"+"\n\n"
252
+ "| | 攻击者判定 | 真实身份 |\n|---|---|---|\n"
253
  "| 身份 | "+pc+" "+pl+" | "+ac+" "+al+" |\n"
254
+ "| Loss | "+f"{loss:.4f}"+" | 阈值: "+f"{thr:.4f}"+" |\n")
255
+ qtxt="**样本 #"+str(idx)+"**\n\n"+clean_text(sample.get('question',''))[:500]
256
  return qtxt, gauge, res
257
 
258
 
 
266
  k=EVAL_KEY.get(model,"baseline"); acc=EVAL_ACC.get(model,bl_acc)
267
  q=EVAL_POOL[np.random.randint(len(EVAL_POOL))]; ok=q.get(k,q.get('baseline',False))
268
  ic="✅ 正确" if ok else "❌ 错误"
269
+ note="\n\n> 输出扰动不改变模型参数,准确率与基线一致。" if u"\u03c3" in model else ""
270
+ return ("**"+model+"** (准确率: "+f"{acc:.1f}%"+")\n\n"
271
+ "| 项目 | 内容 |\n|---|---|\n"
272
+ "| 类型 | "+q['type_cn']+" |\n| 题目 | "+q['question']+" |\n"
273
+ "| 正确答案 | "+q['answer']+" |\n| 判定 | "+ic+" |"+note)
274
 
275
 
276
+ # ══════════════ 极致干净、度统一的 CSS 皮肤 ══════════════
277
 
278
  CSS = """
279
+ /* 1. 干净的背景与字体体系 */
280
  body {
281
  background-color: #f1f5f9 !important;
 
 
282
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
283
  }
284
  .gradio-container {
 
286
  margin: 40px auto !important;
287
  }
288
 
289
+ /* 2. 抛弃深蓝渐变,采用清爽的色主标题面板 */
290
  .title-area {
291
  background: #ffffff;
292
+ padding: 30px 40px;
293
  border-radius: 12px;
294
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
295
+ margin-bottom: 20px;
296
+ border-left: 6px solid #2563eb; /* 左侧科技蓝修线 */
297
  text-align: left;
298
  }
299
  .title-area h1 {
 
312
 
313
  /* 3. 核心大招:死死锁住所有标签页的大小,防止跳动 */
314
  .tabitem {
315
+ background: #ffffff !important;
316
  border-radius: 0 0 12px 12px !important;
317
  border: 1px solid #e2e8f0 !important;
318
  border-top: none !important;
319
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
320
  padding: 32px 40px !important;
321
 
322
+ /* 就是这两行代码,你的每一大小绝对一致 */
323
  height: 760px !important;
324
  max-height: 760px !important;
325
  overflow-y: auto !important;
326
  overflow-x: hidden !important;
327
  }
328
 
329
+ /* 美化内页的滚动条,让它看起来更高级 */
330
  .tabitem::-webkit-scrollbar { width: 6px; }
331
  .tabitem::-webkit-scrollbar-track { background: transparent; }
332
  .tabitem::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; }
333
  .tabitem::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
334
 
335
+ /* 4. Tab 导航栏的极简设计 */
336
  .tab-nav {
337
  border-bottom: none !important;
338
  gap: 4px !important;
 
343
  padding: 12px 24px !important;
344
  font-weight: 600 !important;
345
  color: #64748b !important;
346
+ background: #f1f5f9 !important;
347
  border: 1px solid #e2e8f0 !important;
348
  border-bottom: none !important;
349
  border-radius: 10px 10px 0 0 !important;
 
361
  box-shadow: 0 -4px 6px -2px rgba(0,0,0,0.02) !important;
362
  }
363
 
364
+ /* 5. 内部排版(去掉默认的黑粗体,改为高级灰黑) */
365
  .prose h2 {
366
  font-size: 1.3rem !important;
367
  color: #0f172a !important;
 
377
  margin-top: 1.5em !important;
378
  }
379
 
380
+ /* 6. 高级数据表格 */
381
  .prose table {
382
  width: 100% !important;
383
  border-collapse: separate !important;
 
404
  .prose tr:last-child td { border-bottom: none !important; }
405
  .prose tr:hover td { background: #f0f9ff !important; }
406
 
407
+ /* 7. 纯色扁平化高级按钮 */
408
  button.primary {
409
  background: #2563eb !important;
410
  color: white !important;
 
421
  box-shadow: 0 6px 10px -1px rgba(37, 99, 235, 0.3) !important;
422
  }
423
 
424
+ /* 8. 提示/警报框 */
425
  .prose blockquote {
426
  border-left: 4px solid #3b82f6 !important;
427
  background: #eff6ff !important;
 
432
  margin: 1.5em 0 !important;
433
  }
434
 
435
+ /* 隐藏底部水印 */
436
  footer { display: none !important; }
437
  """
438
 
439
  with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Base(), css=CSS) as demo:
440
 
441
  gr.HTML("""<div class="title-area">
442
+ <h1>教育大模型中的成员推理攻击及其防御研究</h1>
443
+ <p>Membership Inference Attack & Defense on Educational LLM</p>
444
  </div>""")
445
 
446
+ # ═══════ Tab 1 ═══════
447
+ with gr.Tab("实验总览"):
448
+ gr.Markdown(
449
+ "## 研究背景与目标\n\n"
450
+ "大语言模型在教育领域的应用日益广泛(如AI数学辅导),模型训练不可避免地接触学生敏感数据。"
451
+ "**成员推理攻击 (MIA)** 可判断某条数据是否参了训练,构成隐私威胁。\n\n"
452
+ "本研究基于 **" + model_name + "** 微调的数学辅导模型,验证MIA风险的存在性,"
453
+ "并探索 **标签平滑**训练期)与 **输出扰动**(推理期)两类防御策略的有效性及其对模型效用的影响。\n\n---")
454
+
455
+ gr.Markdown("## 实验核心指标\n")
456
+ gr.Markdown(
457
+ "| 策略 | AUC | 准确率 | 说明 |\n|---|---|---|---|\n"
458
+ "| **基线(无防御)** | **" + f"{bl_auc:.4f}" + "** | " + f"{bl_acc:.1f}%" + " | 攻击风险基准 |\n"
459
+ "| " + u"LS(\u03b5=0.02)" + " | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | 训练期防御 |\n"
460
+ "| " + u"LS(\u03b5=0.2)" + " | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | 训练期防御 |\n"
461
+ "| " + u"OP(\u03c3=0.01)" + " | " + f"{op001_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n"
462
+ "| " + u"OP(\u03c3=0.015)" + " | " + f"{op0015_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n"
463
+ "| " + u"OP(\u03c3=0.02)" + " | " + f"{op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 推理期防御 |\n\n"
464
+ "> AUC越接近0.5 = 防御越有效 | 准确率越高 = 模型效用越好\n\n---")
465
+
466
+ gr.Markdown(
467
+ "## 实验流程\n\n"
468
+ "| 阶段 | 内容 | 方法 |\n|---|---|---|\n"
469
+ "| 1. 数据准备 | 2000条数学辅导对话 | 模板化生成,含姓名/学号/成绩 |\n"
470
+ "| 2. 基线训练 | " + model_name + " + LoRA | 标准微调(r=8, alpha=16, 10 epochs) |\n"
471
+ "| 3. 防御训练 | " + u"\u03b5=0.02 / \u03b5=0.2" + " | 两组标签平滑参数分别训练 |\n"
472
+ "| 4. 攻击测试 | 3个模型 + 3组扰动 | Loss阈值判定,AUC评估 |\n"
473
+ "| 5. 效用评估 | 300道数学题 | 6种配置分别测试准确率 |\n"
474
+ "| 6. 综合分析 | 隐私-效用权衡 | 定量对比与可视化 |\n")
475
+
476
+ # ═══════ Tab 2 ═══════
477
+ with gr.Tab("数据与模型"):
478
+ gr.Markdown(
479
+ "## 实验数据集\n\n"
480
+ "| 数据组 | 数量 | 用途 | 说明 |\n|---|---|---|---|\n"
481
+ "| 成员数据 | 1000条 | 模型训练 | 模型会\"记住\",Loss偏低 |\n"
482
+ "| 非成员数据 | 1000条 | 攻击对照 | 模型\"没见过\",Loss偏高 |\n\n"
483
+ "> 组数据格式完全相同(均含隐私字段),这是MIA实验的标准设置——攻击者无法从格式区分\n\n"
484
+ "| 任务类型 | 数量 | 占比 |\n|---|---|---|\n"
485
+ "| 基础计算 | 800 | 40% |\n| 应用题 | 600 | 30% |\n| 概念问答 | 400 | 20% |\n| 错题订正 | 200 | 10% |\n")
486
+ gr.Markdown("### 数据样例浏览")
 
 
 
 
 
 
 
 
487
  with gr.Row(equal_height=True):
488
  with gr.Column(scale=2):
489
+ d_src = gr.Radio(["成员数据(训练集)","非成员数据(测试集)"], value="成员数据(训练集)", label="数据来源")
490
+ d_btn = gr.Button("随机提取样本", variant="primary")
491
  d_meta = gr.Markdown()
492
  with gr.Column(scale=3):
493
+ d_q = gr.Textbox(label="学生提问", lines=4, interactive=False)
494
+ d_a = gr.Textbox(label="标准回答", lines=4, interactive=False)
495
  d_btn.click(cb_sample, [d_src], [d_meta, d_q, d_a])
496
 
497
+ # ═══════ Tab 3 ═══════
498
+ with gr.Tab("攻击与防御验证"):
499
+ gr.Markdown("## 成员推理攻击交互演示\n\n"
500
+ "选择攻击目标数据源,系统实时计算Loss并判定成员身份通过切换不同目标形成对照实验。")
501
  with gr.Row(equal_height=True):
502
  with gr.Column(scale=2):
503
  a_target = gr.Radio([u"基线模型 (Baseline)",u"标签平滑 (\u03b5=0.02)",u"标签平滑 (\u03b5=0.2)",
504
  u"输出扰动 (\u03c3=0.01)",u"输出扰动 (\u03c3=0.015)",u"输出扰动 (\u03c3=0.02)"],
505
+ value=u"基线模型 (Baseline)", label="攻击目标")
506
  a_src = gr.Radio(["成员数据(训练集)","非成员数据(测试集)"], value="成员数据(训练集)", label="数据来源")
507
+ a_idx = gr.Slider(0, 999, step=1, value=12, label="样本 ID")
508
+ a_btn = gr.Button("执行成员推理攻击", variant="primary", size="lg")
509
  a_qtxt = gr.Markdown()
510
  with gr.Column(scale=3):
511
+ a_gauge = gr.Plot(label="Loss位置判定")
512
  a_res = gr.Markdown()
513
  a_btn.click(cb_attack, [a_idx, a_src, a_target], [a_qtxt, a_gauge, a_res])
514
 
515
+ # ═══════ Tab 4 ═══════
516
+ with gr.Tab("防御效果分析"):
517
+ gr.Markdown("## MIA攻击AUC对比\n\n> 柱子越矮 = AUC越低 = 攻击越难成功 = 防御越有效")
518
+ gr.Plot(value=fig_auc_bar())
519
+
520
+ gr.Markdown("## Loss分布对比\n### 三个模型(训练期防御效果)\n\n> 蓝色=成员,红色=非成员。两色重叠越多 = 攻击者越难区分")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
  gr.Plot(value=fig_loss_dist())
522
+ gr.Markdown("### 输出扰动效果(推理期防御)\n\n> 在基线模型Loss上加噪声,随噪声增大分布重叠")
523
  gr.Plot(value=fig_perturb_dist())
524
 
525
+ gr.Markdown(
526
+ "## 完整实验数据\n\n"
527
+ "| 策略 | 类 | AUC | 确率 | AUC变化 |\n|---|---|---|---|---|\n"
528
+ "| 基线 | — | " + f"{bl_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | — |\n"
529
+ "| " + u"LS(\u03b5=0.02)" + " | 训练期 | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | " + f"{s002_auc-bl_auc:+.4f}" + " |\n"
530
+ "| " + u"LS(\u03b5=0.2)" + " | 训练期 | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | " + f"{s02_auc-bl_auc:+.4f}" + " |\n"
531
+ "| " + u"OP(\u03c3=0.01)" + " | 推理期 | " + f"{op001_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | " + f"{op001_auc-bl_auc:+.4f}" + " |\n"
532
+ "| " + u"OP(\u03c3=0.015)" + " | 推理期 | " + f"{op0015_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | " + f"{op0015_auc-bl_auc:+.4f}" + " |\n"
533
+ "| " + u"OP(\u03c3=0.02)" + " | 推理期 | " + f"{op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | " + f"{op002_auc-bl_auc:+.4f}" + " |\n\n"
534
+ "## 防御机制说明\n\n"
535
+ "| 维度 | 标签平滑 | 输出扰动 |\n|---|---|---|\n"
536
+ "| 阶段 | 训练期 | 推理期 |\n"
537
+ "| 原理 | 软化标签降低记忆 | Loss加噪遮蔽信号 |\n"
538
+ "| 需重训 | 是 | 否 |\n"
539
+ "| 效用影响 | 取决于参数 | 无 |\n"
540
+ "| 部署 | 训练时介入 | 即插即用 |\n\n"
541
+ "**标签平滑**: y_smooth = (1 - " + u"\u03b5" + ") * y_onehot + " + u"\u03b5" + " / V\n\n"
542
+ "**输出扰动**: L_perturbed = L_original + N(0, " + u"\u03c3" + u"\u00b2" + ")\n")
543
+
544
+ for fn, cap in [("fig1_loss_distribution_comparison.png","Loss分布对比"),
545
+ ("fig2_privacy_utility_tradeoff_fixed.png","隐私-效用权衡"),
546
+ ("fig3_defense_comparison_bar.png","防御策略AUC对比")]:
547
+ p = os.path.join(BASE_DIR,"figures",fn)
548
+ if os.path.exists(p):
549
+ gr.Markdown("### "+cap); gr.Image(value=p, show_label=False, height=420)
550
+
551
+ # ═══════ Tab 5 ═══════
552
+ with gr.Tab("效用评估"):
553
+ gr.Markdown("## 模型效用测试\n\n> 基于300道数学测试题评估各策略对模型实际能力的影响")
554
  with gr.Row(equal_height=True):
555
  with gr.Column(): gr.Plot(value=fig_acc_bar())
556
  with gr.Column(): gr.Plot(value=fig_tradeoff())
557
+ gr.Markdown("### 在线效用演示\n\n从测试题库中随机抽取,查看不同模型/策略的作答情况。")
558
  with gr.Row(equal_height=True):
559
  with gr.Column(scale=1):
560
  e_model = gr.Radio([u"基线模型",u"标签平滑 (\u03b5=0.02)",u"标签平滑 (\u03b5=0.2)",
561
+ u"输出扰动 (\u03c3=0.01)",u"输出扰动 (\u03c3=0.015)",u"输出扰动 (\u03c3=0.02)"], value=u"基线模型", label="选择模型")
562
+ e_btn = gr.Button("随机抽题测试", variant="primary")
563
  with gr.Column(scale=2):
564
  e_res = gr.Markdown()
565
  e_btn.click(cb_eval, [e_model], [e_res])
566
 
567
+ # ═══════ Tab 6 ═══════
568
+ with gr.Tab("研究结论"):
569
+ gr.Markdown(
570
+ "## 核心研究发现\n\n---\n\n"
571
+ "### 一、教育大模型存在可量化的MIA风险\n\n"
572
+ "基线模型 AUC = **" + f"{bl_auc:.4f}" + "** > 0.5,成员平均Loss (" + f"{bl_m_mean:.4f}"
573
+ + ") < 非成员 (" + f"{bl_nm_mean:.4f}" + "),模型对训练数据存在可利用的记忆效应。\n\n---\n\n"
574
+ "### 二、标签滑(训练期防御)\n\n"
575
+ "| 参数 | AUC | 准确率 | 分析 |\n|---|---|---|---|\n"
576
+ "| 基线 | " + f"{bl_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 无防御 |\n"
577
+ "| " + u"\u03b5=0.02" + " | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | 正则化提升泛化 |\n"
578
+ "| " + u"\u03b5=0.2" + " | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | 防御增强 |\n\n---\n\n"
579
+ "### 三、输出扰动(推理期防御)\n\n"
580
+ "| 参数 | AUC | AUC降幅 | 准确率 |\n|---|---|---|---|\n"
581
+ "| " + u"\u03c3=0.01" + " | " + f"{op001_auc:.4f}" + " | " + f"{bl_auc-op001_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n"
582
+ "| " + u"\u03c3=0.015" + " | " + f"{op0015_auc:.4f}" + " | " + f"{bl_auc-op0015_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n"
583
+ "| " + u"OP(\u03c3=0.02)" + " | " + f"{op002_auc:.4f}" + " | " + f"{bl_auc-op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " |\n\n"
584
+ "零效用损失,适合已部署系统的后加固。\n\n---\n\n"
585
+ "### 四、隐私-效用权衡总结\n\n"
586
+ "| 策略 | AUC | 准确率 | 隐私 | 效用 |\n|---|---|---|---|---|\n"
587
+ "| 基线 | " + f"{bl_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 风险最高 | 基准 |\n"
588
+ "| " + u"LS(\u03b5=0.02)" + " | " + f"{s002_auc:.4f}" + " | " + f"{s002_acc:.1f}%" + " | 降低 | 提升 |\n"
589
+ "| " + u"LS(\u03b5=0.2)" + " | " + f"{s02_auc:.4f}" + " | " + f"{s02_acc:.1f}%" + " | 显著降低 | 可接受 |\n"
590
+ "| " + u"OP(\u03c3=0.02)" + " | " + f"{op002_auc:.4f}" + " | " + f"{bl_acc:.1f}%" + " | 显著降低 | 不变 |\n\n"
591
+ "两类策略机制互补:标签平滑从训练阶段降低记忆,输出扰动从推理阶段遮蔽信号。可根据实际需求灵活选择。\n")
592
+
593
+ gr.HTML("<div style='text-align:center;color:#94a3b8;font-size:.82rem;padding:16px 0 8px'>"
594
+ "</div>")
 
595
 
596
  demo.launch()