-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdermagent.html
More file actions
737 lines (698 loc) · 41.2 KB
/
Copy pathdermagent.html
File metadata and controls
737 lines (698 loc) · 41.2 KB
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
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DermAgent Demo | 皮肤科多Agent诊断系统</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M50 88C25 68 5 50 5 32 5 16 18 5 32 5c9 0 14 5 18 10 4-5 9-10 18-10 14 0 27 11 27 27 0 18-20 36-45 56z' fill='%2327ae60'/%3E%3Cpolyline points='10,50 25,50 32,30 40,70 48,50 55,50 62,35 70,50 90,50' fill='none' stroke='white' stroke-width='6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #1a3a5f;
--primary-dark: #0d2a47;
--secondary: #27ae60;
--accent: #2980b9;
--light: #f8f9fa;
--dark: #212529;
--gray-900: #212529;
--gray-700: #495057;
--gray-600: #6c757d;
--gray-500: #adb5bd;
--shadow: 0 4px 12px rgba(0,0,0,0.08);
--radius: 12px;
--terminal-bg: #1a1b26;
--terminal-green: #9ece6a;
--terminal-cyan: #7dcfff;
--terminal-yellow: #e0af68;
--terminal-red: #f7768e;
--terminal-magenta: #bb9af7;
--terminal-white: #c0caf5;
--terminal-dim: #565f89;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif;
line-height: 1.6;
color: var(--gray-900);
background-color: #fff;
background-image: linear-gradient(135deg, rgba(26,58,95,0.03) 0%, rgba(39,174,96,0.02) 100%);
}
.container { width: 90%; max-width: 1200px; margin: 0 auto; padding: 0 20px; }
/* Nav */
.navbar {
background: white; box-shadow: var(--shadow);
position: sticky; top: 0; z-index: 1000;
padding: 15px 0;
}
.nav-container { display: flex; justify-content: space-between; align-items: center; }
.logo { display: flex; align-items: center; font-size: 1.6rem; font-weight: 800; color: var(--primary); text-decoration: none; }
.logo i { margin-right: 10px; color: var(--secondary); font-size: 1.8rem; }
.nav-links { display: flex; list-style: none; align-items: center; }
.nav-links li { margin-left: 25px; }
.nav-links a { text-decoration: none; color: var(--gray-900); font-weight: 500; font-size: 1.05rem; transition: color 0.3s; }
.nav-links a:hover { color: var(--secondary); }
.btn {
display: inline-block; padding: 12px 28px; border-radius: 50px;
font-weight: 600; text-decoration: none; transition: all 0.3s;
border: 2px solid var(--primary); cursor: pointer; color: var(--gray-900);
}
.btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { background: var(--primary-dark); transform: translateY(-2px); box-shadow: var(--shadow); }
.btn-outline { background: transparent; color: var(--primary); }
.btn-outline:hover { background: var(--light); transform: translateY(-2px); }
.nav-links .btn { padding: 8px 20px; font-size: 0.95rem; line-height: 1.4; }
.mobile-menu-btn { display: none; background: none; border: none; font-size: 1.5rem; color: var(--primary); cursor: pointer; padding: 8px; }
/* Hero */
.hero {
text-align: center; padding: 100px 0 60px;
background: linear-gradient(135deg, rgba(26,58,95,0.05) 0%, rgba(39,174,96,0.03) 100%);
}
.hero h1 { font-size: 3.2rem; margin: 20px 0; color: var(--primary); line-height: 1.2; }
.hero .subtitle { font-size: 1.3rem; color: var(--gray-700); max-width: 800px; margin: 20px auto 35px; }
.hero-links { display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; }
.badge { display: inline-block; background: var(--secondary); color: white; padding: 5px 15px; border-radius: 30px; font-weight: 600; margin-top: 15px; }
/* Terminal Demo */
.demo-section { padding: 80px 0; background: var(--light); }
.section-title { text-align: center; margin-bottom: 50px; }
.section-title h2 { font-size: 2.2rem; color: var(--primary); margin-bottom: 12px; }
.section-title p { color: var(--gray-700); max-width: 700px; margin: 0 auto; }
.case-selector { display: flex; justify-content: center; gap: 15px; margin-bottom: 30px; flex-wrap: wrap; }
.case-btn {
padding: 12px 24px; border-radius: 10px; border: 2px solid #ddd;
background: white; cursor: pointer; font-size: 0.95rem; font-weight: 500;
color: var(--gray-700); transition: all 0.3s; text-align: left; max-width: 280px;
}
.case-btn:hover { border-color: var(--secondary); transform: translateY(-2px); box-shadow: var(--shadow); }
.case-btn.active { border-color: var(--secondary); background: rgba(39,174,96,0.05); }
.case-btn .case-title { font-weight: 700; color: var(--primary); margin-bottom: 4px; }
.case-btn .case-desc { font-size: 0.85rem; color: var(--gray-600); }
.terminal-wrapper {
max-width: 900px; margin: 0 auto; border-radius: var(--radius);
overflow: hidden; box-shadow: 0 8px 30px rgba(0,0,0,0.2);
}
.terminal-bar {
background: #2d2e3f; padding: 10px 16px;
display: flex; align-items: center; gap: 8px;
}
.terminal-dot { width: 12px; height: 12px; border-radius: 50%; }
.terminal-dot.red { background: #ff5f57; }
.terminal-dot.yellow { background: #febc2e; }
.terminal-dot.green { background: #28c840; }
.terminal-title { margin-left: 12px; color: var(--terminal-dim); font-size: 0.85rem; font-family: monospace; }
.terminal {
background: var(--terminal-bg); padding: 20px 24px;
font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
font-size: 0.88rem; line-height: 1.7; min-height: 500px;
max-height: 650px; overflow-y: auto; color: var(--terminal-white);
}
.terminal::-webkit-scrollbar { width: 6px; }
.terminal::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 3px; }
.term-line { opacity: 0; transform: translateY(5px); transition: opacity 0.3s, transform 0.3s; margin: 2px 0; white-space: pre-wrap; word-break: break-all; }
.term-line.visible { opacity: 1; transform: translateY(0); }
.term-line .green { color: var(--terminal-green); }
.term-line .cyan { color: var(--terminal-cyan); }
.term-line .yellow { color: var(--terminal-yellow); }
.term-line .red { color: var(--terminal-red); }
.term-line .magenta { color: var(--terminal-magenta); }
.term-line .dim { color: var(--terminal-dim); }
.term-line .bold { font-weight: 700; }
.term-line .bar-fill { color: var(--terminal-green); }
.term-line .bar-empty { color: var(--terminal-dim); }
.term-spinner { display: inline-block; }
.term-spinner::after { content: ''; animation: spin 1s linear infinite; display: inline-block; }
@keyframes spin {
0% { content: '⠋'; }
16% { content: '⠙'; }
33% { content: '⠹'; }
50% { content: '⠸'; }
66% { content: '⠼'; }
83% { content: '⠴'; }
100% { content: '⠦'; }
}
.demo-hint { text-align: center; color: var(--gray-600); margin-top: 15px; font-size: 0.9rem; }
/* Architecture */
.arch-section { padding: 80px 0; background: var(--light); }
.flow-diagram {
max-width: 850px; margin: 0 auto; padding: 30px;
display: flex; flex-direction: column; align-items: center; gap: 0;
}
.flow-node {
padding: 12px 28px; border-radius: 8px; font-weight: 600;
font-size: 0.95rem; text-align: center; min-width: 220px;
transition: transform 0.3s, box-shadow 0.3s; position: relative;
}
.flow-node:hover { transform: scale(1.05); box-shadow: 0 4px 15px rgba(0,0,0,0.15); }
.flow-node.start { background: var(--secondary); color: white; border-radius: 30px; }
.flow-node.process { background: white; color: var(--primary); border: 2px solid var(--accent); }
.flow-node.memory { background: var(--primary); color: white; }
.flow-node.decision { background: #fff3cd; color: #856404; border: 2px solid #ffc107; transform: rotate(0deg); }
.flow-node.end { background: var(--secondary); color: white; border-radius: 30px; }
.flow-node .node-desc { font-weight: 400; font-size: 0.8rem; opacity: 0.85; margin-top: 2px; }
.flow-arrow { color: var(--gray-500); font-size: 1.2rem; margin: 6px 0; }
.flow-branch { display: flex; gap: 20px; align-items: flex-start; justify-content: center; flex-wrap: wrap; margin: 6px 0; }
.flow-branch-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.flow-branch-label { font-size: 0.75rem; color: var(--gray-600); font-weight: 600; }
/* Features */
.features-section { padding: 80px 0; }
.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 30px; }
.feature-card {
background: white; padding: 35px; border-radius: var(--radius);
box-shadow: var(--shadow); transition: transform 0.3s; border: 1px solid #eee;
}
.feature-card:hover { transform: translateY(-8px); box-shadow: 0 12px 25px rgba(0,0,0,0.12); }
.feature-card i { font-size: 2.8rem; color: var(--accent); margin-bottom: 18px; }
.feature-card h3 { font-size: 1.3rem; color: var(--primary); margin-bottom: 10px; }
.feature-card p { color: var(--gray-700); font-size: 0.95rem; }
/* Knowledge */
.kb-section { padding: 80px 0; background: white; }
.kb-stats { display: flex; justify-content: center; gap: 40px; margin: 40px 0; flex-wrap: wrap; }
.kb-stat { text-align: center; }
.kb-stat .number { font-size: 3rem; font-weight: 800; color: var(--primary); line-height: 1; }
.kb-stat .label { color: var(--gray-600); font-size: 0.95rem; margin-top: 5px; }
.tools-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 30px; }
.tool-item { background: white; padding: 15px; border-radius: 8px; border: 1px solid #eee; display: flex; align-items: center; gap: 10px; }
.tool-item i { color: var(--secondary); font-size: 1.1rem; }
.tool-item span { font-size: 0.9rem; color: var(--gray-700); }
/* Footer */
footer { background: var(--dark); color: rgba(255,255,255,0.85); padding: 50px 0 25px; }
.footer-content { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px; }
.footer-left p { color: rgba(255,255,255,0.7); margin-top: 8px; font-size: 0.9rem; }
.footer-links { display: flex; gap: 20px; align-items: center; }
.footer-links a { color: rgba(255,255,255,0.85); text-decoration: none; transition: color 0.3s; }
.footer-links a:hover { color: var(--secondary); }
.copyright { text-align: center; padding-top: 25px; margin-top: 25px; border-top: 1px solid rgba(255,255,255,0.15); color: rgba(255,255,255,0.7); font-size: 0.9rem; }
/* Responsive */
@media (max-width: 768px) {
.mobile-menu-btn { display: block; }
.nav-links { display: none; width: 100%; margin-top: 20px; flex-direction: column; align-items: center; }
.nav-links.show { display: flex; }
.nav-links li { margin: 10px 0; }
.hero h1 { font-size: 2.4rem; }
.terminal { font-size: 0.78rem; min-height: 400px; padding: 16px; }
.flow-diagram { padding: 15px; }
.flow-node { min-width: 160px; padding: 10px 16px; font-size: 0.85rem; }
.flow-branch { flex-direction: column; align-items: center; }
.kb-stats { gap: 25px; }
.kb-stat .number { font-size: 2.2rem; }
}
</style>
</head>
<body>
<!-- Nav -->
<nav class="navbar">
<div class="container nav-container">
<a href="index.html" class="logo">
<i class="fas fa-heartbeat"></i>
<span>Agentic-CliniAI</span>
</a>
<button class="mobile-menu-btn" id="menuToggle"><i class="fas fa-bars"></i></button>
<ul class="nav-links" id="navLinks">
<li><a href="index.html">主页</a></li>
<li><a href="#demo">Demo</a></li>
<li><a href="#features">特性</a></li>
<li><a href="https://github.com/agentic-cliniai/dermagent" target="_blank" class="btn btn-outline">
<i class="fab fa-github"></i> GitHub
</a></li>
</ul>
</div>
</nav>
<!-- Hero -->
<section class="hero">
<div class="container">
<div class="badge"><i class="fas fa-microscope"></i> 皮肤科诊断智能体</div>
<h1>DermAgent</h1>
<p class="subtitle">皮肤科多Agent诊断系统 — 迭代追问 + 多模态感知 + 468疾病知识库</p>
<div class="hero-links">
<a href="#demo" class="btn btn-primary"><i class="fas fa-terminal"></i> 体验 Demo</a>
<a href="https://github.com/agentic-cliniai/dermagent" target="_blank" class="btn btn-outline"><i class="fab fa-github"></i> 查看源码</a>
</div>
</div>
</section>
<!-- Interactive Demo -->
<section class="demo-section" id="demo">
<div class="container">
<p style="text-align:center; color:var(--gray-700); margin-bottom:30px;">选择一个预设病例,观看 DermAgent 的完整诊断流程动画</p>
<div class="case-selector">
<button class="case-btn active" data-case="sle" onclick="selectCase('sle')">
<div class="case-title">面部红斑3周</div>
<div class="case-desc">SLE(系统性红斑狼疮)— 自身免疫性疾病</div>
</button>
<button class="case-btn" data-case="psoriasis" onclick="selectCase('psoriasis')">
<div class="case-title">全身银白色鳞屑斑块2月</div>
<div class="case-desc">银屑病 — 慢性炎症性皮肤病</div>
</button>
<button class="case-btn" data-case="pemphigus" onclick="selectCase('pemphigus')">
<div class="case-title">反复松弛性水疱伴黏膜糜烂</div>
<div class="case-desc">天疱疮 — 自身免疫性水疱病</div>
</button>
</div>
<div class="terminal-wrapper">
<div class="terminal-bar">
<div class="terminal-dot red"></div>
<div class="terminal-dot yellow"></div>
<div class="terminal-dot green"></div>
<span class="terminal-title">DermAgent — python main.py</span>
</div>
<div class="terminal" id="terminal"></div>
</div>
<p class="demo-hint"><i class="fas fa-info-circle"></i> 此为预录 Demo 动画,展示真实诊断流程。点击不同病例切换。</p>
</div>
</section>
<!-- Knowledge Base -->
<section class="kb-section" id="knowledge">
<div class="container">
<div class="section-title">
<h2><i class="fas fa-book-medical"></i> 知识库与工具链</h2>
<p>11 个知识检索工具,覆盖从本地知识库到全球医学数据库的完整检索链路</p>
</div>
<div class="kb-stats">
<div class="kb-stat"><div class="number">468</div><div class="label">皮肤病种</div></div>
<div class="kb-stat"><div class="number">35+</div><div class="label">ICD-10 类别</div></div>
<div class="kb-stat"><div class="number">11</div><div class="label">检索工具</div></div>
<div class="kb-stat"><div class="number">4</div><div class="label">感知模态</div></div>
</div>
<div class="tools-grid">
<div class="tool-item"><i class="fas fa-book"></i> <span>Disease KB(468种)</span></div>
<div class="tool-item"><i class="fas fa-search"></i> <span>Web Search</span></div>
<div class="tool-item"><i class="fas fa-dna"></i> <span>HPO 表型映射</span></div>
<div class="tool-item"><i class="fas fa-hospital"></i> <span>Orphanet 罕见病</span></div>
<div class="tool-item"><i class="fas fa-dna"></i> <span>OMIM 遗传数据</span></div>
<div class="tool-item"><i class="fas fa-stethoscope"></i> <span>DermNet 皮肤科</span></div>
<div class="tool-item"><i class="fas fa-file-alt"></i> <span>PubMed 文献</span></div>
<div class="tool-item"><i class="fas fa-user-md"></i> <span>PubCaseFinder</span></div>
<div class="tool-item"><i class="fas fa-brain"></i> <span>Phenobrain</span></div>
<div class="tool-item"><i class="fas fa-image"></i> <span>BiomedCLIP 图像</span></div>
<div class="tool-item"><i class="fas fa-clone"></i> <span>相似病例检索</span></div>
</div>
</div>
</section>
<!-- Features -->
<section class="features-section" id="features">
<div class="container">
<div class="section-title">
<h2><i class="fas fa-star"></i> 核心特性</h2>
<p>相比 DeepRare 的三大扩展,赋予系统更强的临床诊断能力</p>
</div>
<div class="features-grid">
<div class="feature-card">
<i class="fas fa-comments"></i>
<h3>迭代追问循环</h3>
<p>当信息不足时自动路由回 Investigation 节点,生成新的追问和检查建议,模拟真实临床问诊过程(最多5轮迭代)</p>
</div>
<div class="feature-card">
<i class="fas fa-eye"></i>
<h3>多模态感知</h3>
<p>皮肤镜、组织病理、检验、体格检查 4 个感知模型并行采集证据,抽象基类设计便于后续替换为真实模型</p>
</div>
<div class="feature-card">
<i class="fas fa-database"></i>
<h3>自适应知识检索</h3>
<p>随诊断轮数递增,从本地468疾病知识库逐步引入 Web、HPO、DermNet、Orphanet、OMIM、PubMed 等外部知识源</p>
</div>
<div class="feature-card">
<i class="fas fa-brain"></i>
<h3>两阶段记忆架构</h3>
<p>Memory 1 融合所有知识源生成初步诊断,Check_Agent 并行验证,Memory 2 综合反思生成最终精炼诊断报告</p>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer>
<div class="container">
<div class="footer-content">
<div class="footer-left">
<div class="logo" style="color:white;font-size:1.4rem;">
<i class="fas fa-heartbeat"></i> Agentic-CliniAI
</div>
<p>构建可信、安全、开源的临床智能工具</p>
</div>
<div class="footer-links">
<a href="index.html"><i class="fas fa-home"></i> 主页</a>
<a href="https://github.com/agentic-cliniai/dermagent" target="_blank"><i class="fab fa-github"></i> GitHub</a>
</div>
</div>
<div class="copyright">
<p>© 2026 Agentic-CliniAI. 致谢 DeepRare (CC BY-NC 4.0)。仅供研究用途。</p>
<p style="margin-top:6px;font-size:0.85rem;opacity:0.8;">Disclaimer: 本工具为辅助决策支持,不替代专业医疗判断。</p>
</div>
</div>
</footer>
<script>
// Mobile menu
document.getElementById('menuToggle').addEventListener('click', function() {
document.getElementById('navLinks').classList.toggle('show');
});
// Smooth scroll
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const id = this.getAttribute('href');
if (id === '#') return;
const el = document.querySelector(id);
if (el) {
window.scrollTo({ top: el.offsetTop - 80, behavior: 'smooth' });
document.getElementById('navLinks').classList.remove('show');
}
});
});
// Case data
const CASES = {
sle: {
title: 'DermAgent — 皮肤科诊断Agent系统',
chief: '面部红斑3周',
stages: [
{ type: 'header', text: 'DermAgent — 皮肤科诊断Agent系统\nMulti-agent diagnostic system for dermatology' },
{ type: 'input', label: '主诉', text: '面部红斑3周' },
{ type: 'input', label: '年龄', text: '20' },
{ type: 'input', label: '性别', text: '女' },
{ type: 'stage', name: '主诉分析', detail: '初始印象: 接触性皮炎, 脂溢性皮炎, 玫瑰痤疮, SLE' },
{ type: 'sub', items: [
{ text: '▪ 接触性皮炎', color: 'cyan' },
{ text: '▪ 脂溢性皮炎', color: 'cyan' },
{ text: '▪ 玫瑰痤疮', color: 'cyan' },
{ text: '▪ 系统性红斑狼疮', color: 'cyan' },
{ text: '? 需确认分布区域、光敏感、接触史、全身症状', color: 'dim' },
]},
{ type: 'stage', name: '追问与检查规划 迭代#1', detail: '4 个追问 · 4 项检查' },
{ type: 'sub', items: [
{ text: 'Q1: 红斑分布在面部哪些区域?是否对称? → 两边脸颊和鼻梁,对称,边界不清,有脱皮和小疙瘩', color: 'default' },
{ text: 'Q2: 有无瘙痒灼热?是否日晒后加重? → 有发烫发痒和紧绷感,晒太阳和吃火锅后明显加重', color: 'default' },
{ text: 'Q3: 发病前是否换过护肤品?有无过度日晒? → 最近换了新防晒霜和洗面奶', color: 'default' },
{ text: 'Q4: 有无口腔溃疡、脱发、关节痛、发热? → 没有溃疡和关节痛,但感觉累,有时下午低烧', color: 'default' },
{ text: '检查: 皮肤镜, ANA+dsDNA抗体, 皮肤病理, 斑贴试验', color: 'yellow' },
]},
{ type: 'stage', name: '多模态证据采集', detail: '1 项检查完成' },
{ type: 'sub', items: [
{ text: '[physical] 皮肤散在皮疹; 未见特征性分布模式; 需结合辅助检查进一步评估', color: 'magenta' },
{ text: ' 置信度: 0.4 — 非特异性', color: 'dim' },
]},
{ type: 'stage', name: '知识检索', detail: '本地知识库 + Web Search + DermNet' },
{ type: 'sub', items: [
{ text: 'LLM诊断: 系统性红斑狼疮, 光变应性接触性皮炎, 玫瑰痤疮, 无肌病性皮肌炎', color: 'cyan' },
{ text: '知识: 检索到光变应性接触性皮炎、脂溢性皮炎、口周皮炎相关知识', color: 'dim' },
]},
{ type: 'stage', name: 'Memory 1 · 知识融合', detail: '融合完成' },
{ type: 'sub', items: [
{ text: ' #1 光变应性接触性皮炎 — 近期更换护肤品+日晒后加重+湿疹样改变', color: 'dim' },
{ text: ' #2 系统性红斑狼疮 — 青年女性蝶形红斑+光敏感+乏力低热', color: 'dim' },
{ text: ' #3 亚急性皮肤红斑狼疮(丘疹鳞屑型) — 光敏感丘疹鳞屑性皮疹', color: 'dim' },
{ text: ' #4 无肌病性皮肌炎 — 面部对称性红斑+乏力低热', color: 'dim' },
{ text: ' #5 玫瑰痤疮 — 面颊鼻部红斑丘疹+辛辣食物后加重', color: 'dim' },
]},
{ type: 'stage', name: 'Check_Agent · 疾病验证', detail: '验证 5 个诊断' },
{ type: 'sub', items: [
{ text: '✘ 光变应性接触性皮炎 核心皮损停用后仍持续,伴系统症状不符', color: 'red' },
{ text: '✘ 系统性红斑狼疮 毛细血管扩张和丘疹更符合玫瑰痤疮,缺少ANA等血清学证据', color: 'red' },
{ text: '✘ 亚急性皮肤红斑狼疮 待更多检查支持', color: 'red' },
]},
{ type: 'stage', name: '信息充分性评估', detail: '路由: → 追加追问' },
{ type: 'sub', items: [
{ text: '? 信息不足,需进一步追问补充关键鉴别点', color: 'yellow' },
]},
{ type: 'stage', name: '追问与检查规划 迭代#2', detail: '5 个追问 · 3 项检查' },
{ type: 'sub', items: [
{ text: 'Q5: 停用新护肤品后症状有无减轻? → 灼热发痒稍减轻,但红斑和脱皮没完全消', color: 'default' },
{ text: 'Q6: 头皮眉毛鼻唇沟是否油腻发红? → 没有,不油也不红', color: 'default' },
{ text: 'Q7: 手指遇冷有无变白变紫(雷诺现象)? → 没有', color: 'default' },
{ text: 'Q8: 能否看到扩张的红血丝?受热时更明显? → 能看到细红血丝,一热就更明显', color: 'default' },
{ text: 'Q9: 家族中有无自身免疫病? → 没有', color: 'default' },
{ text: '检查: 皮肤镜, ANA+dsDNA+ENA抗体谱, 补体C3/C4+血常规+尿常规', color: 'yellow' },
]},
{ type: 'stage', name: '知识检索 搜索深度:2', detail: '+ DermNet + Orphanet + OMIM' },
{ type: 'sub', items: [
{ text: 'LLM诊断: 系统性红斑狼疮, 光变应性接触性皮炎, 玫瑰痤疮', color: 'cyan' },
]},
{ type: 'stage', name: 'Memory 1 · 知识融合', detail: '融合完成 (迭代#2)' },
{ type: 'stage', name: 'Check_Agent · 疾病验证', detail: '验证 5 个诊断' },
{ type: 'sub', items: [
{ text: '✘ 光变应性接触性皮炎 持续皮损+系统症状无法解释', color: 'red' },
{ text: '✘ 系统性红斑狼疮 毛细血管扩张+丘疹更似玫瑰痤疮,缺少血清学证据', color: 'red' },
]},
{ type: 'stage', name: '信息充分性评估', detail: '路由: → 生成最终诊断' },
{ type: 'stage', name: 'Memory 2 · 最终诊断', detail: '生成 5 个鉴别诊断' },
{ type: 'sub', items: [
{ text: '#1 系统性红斑狼疮 (SLE) █████████░ 90%', color: 'default', bold: true },
{ text: ' 青年女性+蝶形红斑+光敏感+乏力低热 → 符合ACR标准中的蝶形红斑与光过敏', color: 'dim' },
{ text: '#2 系统性红斑狼疮 (SLE) ███████░░░ 75%', color: 'default' },
{ text: '#3 玫瑰痤疮 ██████░░░░ 60%', color: 'default' },
{ text: '#4 亚急性皮肤型红斑狼疮 ████░░░░░░ 45%', color: 'default' },
{ text: '#5 亚急性皮肤型红斑狼疮 ███░░░░░░░ 30%', color: 'default' },
]},
{ type: 'stage', name: '报告生成', detail: '报告已生成' },
{ type: 'sub', items: [
{ text: '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', color: 'dim' },
{ text: '【临床诊断报告】', color: 'bold cyan' },
{ text: '', color: 'default' },
{ text: '患者信息: 20岁女性', color: 'default' },
{ text: '主诉: 面部红斑伴瘙痒、灼热3周', color: 'default' },
{ text: '', color: 'default' },
{ text: '病史: 双颊及鼻梁对称性红斑,边界不清,表面细薄鳞屑及丘疹', color: 'default' },
{ text: ' 日晒及辛辣食物后加重。发病前有更换护肤品史', color: 'default' },
{ text: ' 停用后灼热瘙痒减轻但红斑未消。伴乏力、午后低热', color: 'default' },
{ text: '', color: 'default' },
{ text: '【主要诊断】系统性红斑狼疮 (SLE) 置信度: 80%', color: 'bold green' },
{ text: '依据: 青年女性蝶形红斑+光敏感+毛细血管扩张+乏力低热', color: 'default' },
{ text: ' 需ANA、dsDNA、补体等血清学检查进一步确诊', color: 'default' },
{ text: '', color: 'default' },
{ text: '建议: 严格防晒 + 转诊风湿免疫科 → 完善 ANA+dsDNA+补体+皮肤活检', color: 'yellow' },
{ text: '', color: 'default' },
{ text: '迭代次数: 2, 搜索深度: 2', color: 'dim' },
{ text: '诊断记录已保存', color: 'dim' },
]},
]
},
psoriasis: {
title: 'DermAgent — 皮肤科诊断Agent系统',
chief: '全身银白色鳞屑斑块2月',
stages: [
{ type: 'header', text: 'DermAgent — 皮肤科诊断Agent系统\nMulti-agent diagnostic system for dermatology' },
{ type: 'input', label: '主诉', text: '全身银白色鳞屑斑块2月' },
{ type: 'input', label: '年龄', text: '50' },
{ type: 'input', label: '性别', text: '男' },
{ type: 'stage', name: '主诉分析', detail: '初始印象: 寻常型银屑病, 副银屑病, 脂溢性皮炎, 二期梅毒疹' },
{ type: 'sub', items: [
{ text: '▪ 寻常型银屑病', color: 'cyan' },
{ text: '▪ 副银屑病', color: 'cyan' },
{ text: '▪ 脂溢性皮炎', color: 'cyan' },
{ text: '▪ 二期梅毒疹', color: 'cyan' },
{ text: '? 需确认Auspitz征、Koebner现象、甲改变、关节症状', color: 'dim' },
]},
{ type: 'stage', name: '追问与检查规划 迭代#1', detail: '4 个追问 · 4 项检查' },
{ type: 'sub', items: [
{ text: 'Q1: 鳞屑斑块主要在哪些部位? → 头皮和两个胳膊肘外面,背上也有', color: 'default' },
{ text: 'Q2: 刮除鳞屑后有无薄膜和点状出血? → 刮掉白皮后有一层亮薄皮,再刮有出血点', color: 'default' },
{ text: 'Q3: 有无关节肿痛、指甲凹陷? → 手指关节肿痛,指甲有小坑洼', color: 'default' },
{ text: 'Q4: 有无不洁接触史? → 没有', color: 'default' },
{ text: '检查: 皮肤镜, 梅毒血清学, 皮屑真菌镜检, 皮肤病理', color: 'yellow' },
]},
{ type: 'stage', name: '多模态证据采集', detail: '体格检查完成' },
{ type: 'sub', items: [
{ text: '[physical] 皮肤散在皮疹; 非特异性分布 (置信度: 0.4)', color: 'magenta' },
]},
{ type: 'stage', name: '追问与检查规划 迭代#2', detail: '追加 5 个追问' },
{ type: 'sub', items: [
{ text: 'Q5: Auspitz征? → 刮掉白皮后露出发亮薄膜,再刮冒出小血点', color: 'default' },
{ text: 'Q6: Koebner现象? → 抓破的地方后来也长出了带白皮的红斑', color: 'default' },
{ text: 'Q7: 甲凹点? → 指甲表面有针尖大小的小坑', color: 'default' },
{ text: 'Q8: 束状发? → 头发一缕缕黏在白皮上,梳子梳不开', color: 'default' },
{ text: 'Q9: 家族史? → 父亲年轻时就有牛皮癣', color: 'default' },
]},
{ type: 'stage', name: '知识检索 搜索深度:2', detail: '本地知识库 + Web Search + DermNet' },
{ type: 'sub', items: [
{ text: 'LLM诊断: 关节病型银屑病, 大斑块型副银屑病, 毛发红糠疹', color: 'cyan' },
]},
{ type: 'stage', name: 'Memory 1 · 知识融合', detail: '融合完成' },
{ type: 'stage', name: 'Check_Agent · 疾病验证', detail: '验证 5 个诊断' },
{ type: 'sub', items: [
{ text: '✔ 关节病型银屑病 完全符合(Auspitz征+Koebner现象+甲凹点+束状发+关节肿痛+家族史)', color: 'green' },
{ text: '✘ 大斑块型副银屑病 不符合(无Auspitz征、伴关节炎)', color: 'red' },
{ text: '✘ 毛发红糠疹 不符合(缺少毛囊角化丘疹和橘黄掌跖)', color: 'red' },
]},
{ type: 'stage', name: 'Memory 2 · 最终诊断', detail: '生成 5 个鉴别诊断' },
{ type: 'sub', items: [
{ text: '#1 关节病型银屑病(银屑病性关节炎) █████████░ 90%', color: 'default', bold: true },
{ text: ' Auspitz征+Koebner现象+甲凹点+束状发+对称性关节炎+晨僵+家族史', color: 'dim' },
{ text: '#2 大斑块型副银屑病 ███████░░░ 75%', color: 'default' },
{ text: '#3 毛发红糠疹 ██████░░░░ 60%', color: 'default' },
{ text: '#4 蕈样肉芽肿(斑块期) ████░░░░░░ 45%', color: 'default' },
{ text: '#5 反应性关节炎 ███░░░░░░░ 30%', color: 'default' },
]},
{ type: 'stage', name: '报告生成', detail: '报告已生成' },
{ type: 'sub', items: [
{ text: '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', color: 'dim' },
{ text: '【临床诊断报告】', color: 'bold cyan' },
{ text: '', color: 'default' },
{ text: '患者信息: 50岁男性', color: 'default' },
{ text: '主诉: 全身泛发银白色鳞屑性红斑、斑块伴瘙痒2月', color: 'default' },
{ text: '', color: 'default' },
{ text: '【主要诊断】关节病型银屑病(银屑病性关节炎) 置信度: 90%', color: 'bold green' },
{ text: '诊断依据: 银白色鳞屑+Auspitz征+Koebner现象+甲凹点+束状发+对称性关节炎+晨僵+家族史', color: 'default' },
{ text: '建议: 皮肤科+风湿免疫科联合就诊,完善关节X线、CRP/ESR/RF/抗CCP、皮肤活检', color: 'yellow' },
{ text: '', color: 'default' },
{ text: '迭代次数: 1, 搜索深度: 2', color: 'dim' },
{ text: '诊断记录已保存', color: 'dim' },
]},
]
},
pemphigus: {
title: 'DermAgent — 皮肤科诊断Agent系统',
chief: '反复松弛性水疱伴黏膜糜烂',
stages: [
{ type: 'header', text: 'DermAgent — 皮肤科诊断Agent系统\nMulti-agent diagnostic system for dermatology' },
{ type: 'input', label: '主诉', text: '反复松弛性水疱伴黏膜糜烂' },
{ type: 'input', label: '年龄', text: '30' },
{ type: 'input', label: '性别', text: '女' },
{ type: 'stage', name: '主诉分析', detail: '初始印象: 寻常型天疱疮, 副肿瘤性天疱疮, 线状IgA大疱病, 大疱性类天疱疮' },
{ type: 'sub', items: [
{ text: '▪ 寻常型天疱疮', color: 'cyan' },
{ text: '▪ 副肿瘤性天疱疮', color: 'cyan' },
{ text: '▪ 线状IgA大疱病', color: 'cyan' },
{ text: '▪ 大疱性类天疱疮', color: 'cyan' },
{ text: '? 需确认Nikolsky征、黏膜受累范围、既往检查结果', color: 'dim' },
]},
{ type: 'stage', name: '追问与检查规划', detail: '4 个追问 · 5 项检查' },
{ type: 'sub', items: [
{ text: 'Q1: 水疱和糜烂分布在哪些部位? → 嘴里烂得最厉害,眼睛和下面也有糜烂,身上起松弛水疱', color: 'default' },
{ text: 'Q2: 水疱是否容易破裂?有无Nikolsky征? → 一碰就破,轻轻搓一下皮就整片脱落', color: 'default' },
{ text: 'Q3: 有无发热、体重下降、吞咽困难? → 喉咙疼得厉害,咽东西像吞刀片', color: 'default' },
{ text: 'Q4: 既往检查? → 做过活检和Dsg1/Dsg3抗体,确诊天疱疮,用过泼尼松和吗替麦考酚酯', color: 'default' },
{ text: '检查: 皮肤病理+DIF, 抗Dsg1/Dsg3抗体, 抗BP180/BP230, 胸腹盆腔CT', color: 'yellow' },
]},
{ type: 'stage', name: '多模态证据采集', detail: '体格检查完成' },
{ type: 'sub', items: [
{ text: '[physical] 皮肤散在皮疹; 非特异性分布 (置信度: 0.4)', color: 'magenta' },
]},
{ type: 'stage', name: '知识检索', detail: '本地知识库 + Web Search' },
{ type: 'sub', items: [
{ text: 'LLM诊断: 寻常型天疱疮, 副肿瘤性天疱疮, 增殖型天疱疮, IgA天疱疮, 瘢痕性类天疱疮', color: 'cyan' },
]},
{ type: 'stage', name: 'Memory 1 · 知识融合', detail: '融合完成' },
{ type: 'sub', items: [
{ text: ' #1 副肿瘤性天疱疮 — 严重多黏膜糜烂+吞咽痛+治疗反应不佳', color: 'dim' },
{ text: ' #2 寻常型天疱疮 — 松弛性水疮+Nikolsky征+Dsg抗体阳性', color: 'dim' },
]},
{ type: 'stage', name: 'Check_Agent · 疾病验证', detail: '验证 5 个诊断' },
{ type: 'sub', items: [
{ text: '✘ 副肿瘤性天疱疮 不符合(无潜在肿瘤证据,Dsg抗体模式符合寻常型)', color: 'red' },
{ text: '✔ 寻常型天疱疮 完全符合(松弛性水疮+Nikolsky征+Dsg1/Dsg3阳性+活检确诊)', color: 'green' },
]},
{ type: 'stage', name: 'Memory 2 · 最终诊断', detail: '生成 5 个鉴别诊断' },
{ type: 'sub', items: [
{ text: '#1 副肿瘤性天疱疮 █████████░ 90%', color: 'default', bold: true },
{ text: '#2 寻常型天疱疮 ██████░░░░ 45%', color: 'default' },
{ text: '#3 增殖型天疱疮 ███░░░░░░░ 30%', color: 'default' },
{ text: '#4 IgA天疱疮 ██░░░░░░░░ 15%', color: 'default' },
{ text: '#5 瘢痕性类天疱疮 █░░░░░░░░░ 8%', color: 'default' },
]},
{ type: 'stage', name: '报告生成', detail: '报告已生成' },
{ type: 'sub', items: [
{ text: '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', color: 'dim' },
{ text: '【临床诊断报告】', color: 'bold cyan' },
{ text: '', color: 'default' },
{ text: '患者信息: 30岁女性', color: 'default' },
{ text: '主诉: 反复松弛性水疱伴黏膜糜烂', color: 'default' },
{ text: '', color: 'default' },
{ text: '【主要诊断】寻常型天疱疮(活动期,治疗反应不佳) 置信度: 高', color: 'bold green' },
{ text: '依据: 松弛性水疮+Nikolsky征(+)+Dsg1/Dsg3(+)+活检确诊+多黏膜糜烂', color: 'default' },
{ text: '待排: 副肿瘤性天疱疮(需完善胸腹盆腔CT排查潜在肿瘤)', color: 'yellow' },
{ text: '建议: 调整免疫抑制方案,评估利妥昔单抗;加强黏膜护理;耳鼻喉科评估咽喉受累', color: 'yellow' },
{ text: '', color: 'default' },
{ text: '迭代次数: 0, 搜索深度: 1', color: 'dim' },
{ text: '诊断记录已保存', color: 'dim' },
]},
]
}
};
let currentCase = 'sle';
let animationTimers = [];
function selectCase(caseId) {
currentCase = caseId;
document.querySelectorAll('.case-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.case === caseId);
});
runDemo();
}
function clearTimers() {
animationTimers.forEach(t => clearTimeout(t));
animationTimers = [];
}
function addLine(html) {
const term = document.getElementById('terminal');
const div = document.createElement('div');
div.className = 'term-line';
div.innerHTML = html;
term.appendChild(div);
requestAnimationFrame(() => {
requestAnimationFrame(() => div.classList.add('visible'));
});
term.scrollTop = term.scrollHeight;
return div;
}
function colorSpan(text, color) {
if (!color || color === 'default') return escapeHtml(text);
const cls = color === 'bold' ? 'bold' : color;
return `<span class="${cls}">${escapeHtml(text)}</span>`;
}
function escapeHtml(str) {
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
function runDemo() {
clearTimers();
const term = document.getElementById('terminal');
term.innerHTML = '';
const caseData = CASES[currentCase];
let delay = 200;
caseData.stages.forEach((stage, si) => {
if (stage.type === 'header') {
animationTimers.push(setTimeout(() => {
addLine(colorSpan('╭──────────────────────────────────────────────╮', 'dim'));
const lines = stage.text.split('\n');
lines.forEach(l => {
addLine(colorSpan('│ ', 'dim') + colorSpan(l, 'cyan'));
});
addLine(colorSpan('╰──────────────────────────────────────────────╯', 'dim'));
addLine('');
}, delay));
delay += 300;
}
else if (stage.type === 'input') {
animationTimers.push(setTimeout(() => {
addLine(colorSpan(`\n${stage.label}:`, 'yellow') + escapeHtml(stage.text));
}, delay));
delay += 400;
}
else if (stage.type === 'stage') {
animationTimers.push(setTimeout(() => {
addLine(colorSpan(' ✔ ', 'green') + colorSpan(stage.name, 'bold') + colorSpan(` — ${stage.detail}`, 'dim'));
}, delay));
delay += 350;
}
else if (stage.type === 'sub') {
stage.items.forEach(item => {
animationTimers.push(setTimeout(() => {
let html = '';
if (item.color === 'green') html = colorSpan(item.text, 'green');
else if (item.color === 'red') html = colorSpan(item.text, 'red');
else if (item.color === 'yellow') html = colorSpan(item.text, 'yellow');
else if (item.color === 'magenta') html = colorSpan(item.text, 'magenta');
else if (item.color === 'cyan') html = colorSpan(item.text, 'cyan');
else if (item.color === 'dim') html = colorSpan(item.text, 'dim');
else if (item.color === 'bold cyan') html = colorSpan(item.text, 'bold') + colorSpan('', 'cyan');
else html = escapeHtml(item.text);
if (item.bold) {
html = `<span class="bold">${html}</span>`;
}
addLine(` ${html}`);
}, delay));
delay += 120;
});
delay += 150;
}
});
}
// Auto-start
runDemo();
</script>
</body>
</html>