@ww_nero/skills 2.2.14 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -597,17 +597,30 @@ def create_slide(prs):
597
597
  """深度学习的崛起(1990-2017)"""
598
598
  slide = prs.slides.add_slide(prs.slide_layouts[6])
599
599
 
600
- # 背景渐变 (#1a237e -> #0d1b60)
600
+ # SVG: <linearGradient id="bgGrad"><stop offset="0%" stop-color="#1a237e"/><stop offset="100%" stop-color="#0d1b60"/></linearGradient>
601
+ # SVG: <rect width="100%" height="100%" fill="url(#bgGrad)"/>
601
602
  set_slide_background_gradient(slide, "1a237e", "0d1b60")
602
603
 
603
- # 图片占位符位置插入图片 (左侧时间线区域右侧)
604
+ # SVG: <rect id="image-placeholder" x="420" y="340" width="180" height="120" .../>
604
605
  image_path = os.path.join(os.path.dirname(__file__), "demo.jpg")
605
606
  add_image(slide, image_path, 420, 340, 180, 120)
606
607
 
607
- # 圆形图片占位符 (右上角头像)
608
+ # SVG: <circle id="image-placeholder-circle" cx="1150" cy="120" r="50" .../>
608
609
  add_circular_image(slide, image_path, 1150, 120, 50)
609
610
 
610
- # 右侧装饰性神经网络背景
611
+ # SVG: <g opacity="0.1" stroke="#ffffff" stroke-width="1">
612
+ # <line x1="800" y1="200" x2="900" y2="300"/>
613
+ # <line x1="900" y1="300" x2="850" y2="450"/>
614
+ # <line x1="850" y1="450" x2="750" y2="400"/>
615
+ # <line x1="750" y1="400" x2="800" y2="200"/>
616
+ # <line x1="800" y1="200" x2="650" y2="250"/>
617
+ # <line x1="650" y1="250" x2="750" y2="400"/>
618
+ # <circle cx="800" cy="200" r="4" fill="#fff"/>
619
+ # <circle cx="900" cy="300" r="4" fill="#fff"/>
620
+ # <circle cx="850" cy="450" r="4" fill="#fff"/>
621
+ # <circle cx="750" cy="400" r="4" fill="#fff"/>
622
+ # <circle cx="650" cy="250" r="4" fill="#fff"/>
623
+ # </g>
611
624
  add_line(slide, 800, 200, 900, 300, "#ffffff", 1, 0.1)
612
625
  add_line(slide, 900, 300, 850, 450, "#ffffff", 1, 0.1)
613
626
  add_line(slide, 850, 450, 750, 400, "#ffffff", 1, 0.1)
@@ -620,45 +633,63 @@ def create_slide(prs):
620
633
  add_circle(slide, 750, 400, 4, "#ffffff", opacity=0.1)
621
634
  add_circle(slide, 650, 250, 4, "#ffffff", opacity=0.1)
622
635
 
623
- # 标题部分
636
+ # SVG: <g transform="translate(60, 80)">
637
+ # <text font-size="48" font-weight="bold" fill="#ffffff">深度学习的崛起(1990-2017)</text>
638
+ # <rect x="0" y="20" width="100" height="4" fill="url(#accentGrad)" rx="2"/>
639
+ # <line x1="0" y1="22" x2="1160" y2="22" stroke="#ffffff" stroke-width="1" opacity="0.2"/>
640
+ # </g>
624
641
  add_text_box(slide, "深度学习的崛起(1990-2017)", 60, 80, 800, 60, 48, "#ffffff", bold=True, anchor='start', valign='top')
625
642
  add_gradient_rectangle(slide, 60, 100, 100, 4, "#00e5ff", 1.0, "#2979ff", 1.0, 0, rx=2)
626
643
  add_line(slide, 60, 102, 1220, 102, "#ffffff", 1, 0.2)
627
644
 
628
- # 中间分隔虚线
645
+ # SVG: <line x1="640" y1="180" x2="640" y2="630" stroke="#00e5ff" stroke-width="1" stroke-dasharray="4 4" opacity="0.3"/>
629
646
  add_line(slide, 640, 180, 640, 630, "#00e5ff", 1, 0.3, dash=True)
630
647
 
631
- # 左侧:技术突破
648
+ # SVG: <text font-size="28" fill="#00e5ff" font-weight="bold">技术突破</text>
632
649
  add_text_box(slide, "技术突破", 60, 180, 200, 40, 28, "#00e5ff", bold=True, anchor='start', valign='top')
633
650
 
634
- # 时间线主线
651
+ # SVG: <line x1="20" y1="50" x2="20" y2="480" stroke="#b3e5fc" stroke-width="2" opacity="0.3"/>
635
652
  add_line(slide, 80, 230, 80, 660, "#b3e5fc", 2, 0.3)
636
653
 
637
- # 1998
654
+ # SVG: <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
655
+ # <text font-size="24" fill="#ffffff" font-weight="bold">1998</text>
656
+ # <text font-size="20" fill="#b3e5fc">LeNet-5,CNN开创性工作</text>
638
657
  add_circle(slide, 80, 250, 6, "#1a237e", stroke_color="#00e5ff", stroke_width=2)
639
658
  add_text_box(slide, "1998", 105, 240, 100, 30, 24, "#ffffff", bold=True, anchor='start', valign='top')
640
659
  add_text_box(slide, "LeNet-5,CNN开创性工作", 105, 270, 350, 30, 20, "#b3e5fc", anchor='start', valign='top')
641
660
 
642
- # 2012
661
+ # SVG: <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
662
+ # <text font-size="24" fill="#ffffff" font-weight="bold">2012</text>
663
+ # <text font-size="20" fill="#b3e5fc">AlexNet赢得ImageNet竞赛</text>
643
664
  add_circle(slide, 80, 350, 6, "#1a237e", stroke_color="#00e5ff", stroke_width=2)
644
665
  add_text_box(slide, "2012", 105, 340, 100, 30, 24, "#ffffff", bold=True, anchor='start', valign='top')
645
666
  add_text_box(slide, "AlexNet赢得ImageNet竞赛", 105, 370, 350, 30, 20, "#b3e5fc", anchor='start', valign='top')
646
667
 
647
- # 2014
668
+ # SVG: <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
669
+ # <text font-size="24" fill="#ffffff" font-weight="bold">2014</text>
670
+ # <text font-size="20" fill="#b3e5fc">GAN生成对抗网络</text>
648
671
  add_circle(slide, 80, 450, 6, "#1a237e", stroke_color="#00e5ff", stroke_width=2)
649
672
  add_text_box(slide, "2014", 105, 440, 100, 30, 24, "#ffffff", bold=True, anchor='start', valign='top')
650
673
  add_text_box(slide, "GAN生成对抗网络", 105, 470, 350, 30, 20, "#b3e5fc", anchor='start', valign='top')
651
674
 
652
- # 2015
675
+ # SVG: <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
676
+ # <text font-size="24" fill="#ffffff" font-weight="bold">2015</text>
677
+ # <text font-size="20" fill="#b3e5fc">ResNet残差网络</text>
653
678
  add_circle(slide, 80, 550, 6, "#1a237e", stroke_color="#00e5ff", stroke_width=2)
654
679
  add_text_box(slide, "2015", 105, 540, 100, 30, 24, "#ffffff", bold=True, anchor='start', valign='top')
655
680
  add_text_box(slide, "ResNet残差网络", 105, 570, 350, 30, 20, "#b3e5fc", anchor='start', valign='top')
656
681
 
657
- # 右侧:关键人物
682
+ # SVG: <text font-size="28" fill="#00e5ff" font-weight="bold">关键人物</text>
683
+ # <text font-size="16" fill="#b3e5fc" opacity="0.7">Turing Award Winners ("Godfathers of AI")</text>
658
684
  add_text_box(slide, "关键人物", 688, 180, 200, 40, 28, "#00e5ff", bold=True, anchor='start', valign='top')
659
685
  add_text_box(slide, "Turing Award Winners (\"Godfathers of AI\")", 688, 215, 400, 25, 16, "#b3e5fc", anchor='start', valign='top')
660
686
 
661
- # 人物卡片1: Hinton (切角矩形: 左上和右下切角10px)
687
+ # SVG: <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
688
+ # <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
689
+ # <text font-size="24" fill="#ffffff" font-weight="bold">Geoffrey Hinton</text>
690
+ # <text font-size="16" fill="#b3e5fc">Backpropagation, Deep Belief Nets</text>
691
+ # <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
692
+ # <circle cx="340" cy="50" r="8" fill="#00e5ff" opacity="0.8"/>
662
693
  add_freeform_path(slide, [(688, 260), (698, 250), (1068, 250), (1068, 340), (1058, 350), (688, 350)],
663
694
  fill_color="#ffffff", stroke_color="#00e5ff", stroke_width=1, opacity=0.05, closed=True)
664
695
  add_freeform_path(slide, [(688, 270), (688, 260), (698, 250), (708, 250)], stroke_color="#00e5ff", stroke_width=2)
@@ -667,7 +698,12 @@ def create_slide(prs):
667
698
  add_circle(slide, 1028, 300, 20, stroke_color="#00e5ff", stroke_width=1, opacity=0.5)
668
699
  add_circle(slide, 1028, 300, 8, "#00e5ff", opacity=0.8)
669
700
 
670
- # 人物卡片2: LeCun
701
+ # SVG: <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
702
+ # <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
703
+ # <text font-size="24" fill="#ffffff" font-weight="bold">Yann LeCun</text>
704
+ # <text font-size="16" fill="#b3e5fc">CNN (Convolutional Neural Networks)</text>
705
+ # <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
706
+ # <rect x="332" y="42" width="16" height="16" fill="#00e5ff" opacity="0.8"/>
671
707
  add_freeform_path(slide, [(688, 380), (698, 370), (1068, 370), (1068, 460), (1058, 470), (688, 470)],
672
708
  fill_color="#ffffff", stroke_color="#00e5ff", stroke_width=1, opacity=0.05, closed=True)
673
709
  add_freeform_path(slide, [(688, 390), (688, 380), (698, 370), (708, 370)], stroke_color="#00e5ff", stroke_width=2)
@@ -676,7 +712,12 @@ def create_slide(prs):
676
712
  add_circle(slide, 1028, 420, 20, stroke_color="#00e5ff", stroke_width=1, opacity=0.5)
677
713
  add_rectangle(slide, 1020, 412, 16, 16, "#00e5ff", opacity=0.8)
678
714
 
679
- # 人物卡片3: Bengio
715
+ # SVG: <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
716
+ # <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
717
+ # <text font-size="24" fill="#ffffff" font-weight="bold">Yoshua Bengio</text>
718
+ # <text font-size="16" fill="#b3e5fc">Sequence Modeling, GANs</text>
719
+ # <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
720
+ # <polygon points="340,38 352,58 328,58" fill="#00e5ff" opacity="0.8"/>
680
721
  add_freeform_path(slide, [(688, 500), (698, 490), (1068, 490), (1068, 580), (1058, 590), (688, 590)],
681
722
  fill_color="#ffffff", stroke_color="#00e5ff", stroke_width=1, opacity=0.05, closed=True)
682
723
  add_freeform_path(slide, [(688, 510), (688, 500), (698, 490), (708, 490)], stroke_color="#00e5ff", stroke_width=2)
@@ -685,14 +726,19 @@ def create_slide(prs):
685
726
  add_circle(slide, 1028, 540, 20, stroke_color="#00e5ff", stroke_width=1, opacity=0.5)
686
727
  add_triangle(slide, 1028, 548, 20, "#00e5ff", opacity=0.8, rotation=180)
687
728
 
688
- # 底部装饰
729
+ # SVG: <rect x="0" y="0" width="1280" height="48" fill="#0d1b60" opacity="0.8"/>
730
+ # <text font-size="12" fill="#b3e5fc" opacity="0.5">NEURAL NETWORKS RENAISSANCE | AI HISTORY SERIES</text>
731
+ # <circle cx="1206" cy="24" r="2"/><circle cx="1216" cy="24" r="2"/><circle cx="1226" cy="24" r="2"/>
689
732
  add_rectangle(slide, 0, 672, 1280, 48, "#0d1b60", opacity=0.8)
690
733
  add_text_box(slide, "NEURAL NETWORKS RENAISSANCE | AI HISTORY SERIES", 60, 702, 500, 20, 12, "#b3e5fc", anchor='start', valign='top')
691
734
  add_circle(slide, 1206, 696, 2, "#00e5ff", opacity=0.5)
692
735
  add_circle(slide, 1216, 696, 2, "#00e5ff", opacity=0.5)
693
736
  add_circle(slide, 1226, 696, 2, "#00e5ff", opacity=0.5)
694
737
 
695
- # Icon 元素示例:复杂的 SVG 图标先转为小 PNG 再插入
738
+ # SVG: <g id="icon-placeholder" transform="translate(1100, 650)">
739
+ # <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"
740
+ # stroke="#00e5ff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
741
+ # </g>
696
742
  icon_svg = '''<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"
697
743
  stroke="#00e5ff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>'''
698
744
  add_icon(slide, icon_svg, 1100, 650, 24, 24)
package/index.js CHANGED
@@ -8,6 +8,59 @@ const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontext
8
8
 
9
9
  const ASSETS_ROOT = path.join(__dirname, 'assets');
10
10
 
11
+ const convertPath = (filePath) => {
12
+ const wslMatch = filePath.match(/^\/mnt\/([a-zA-Z])\/(.*)$/);
13
+ if (wslMatch) {
14
+ const drive = wslMatch[1].toUpperCase();
15
+ const rest = wslMatch[2].replace(/\//g, '\\');
16
+ return `${drive}:\\${rest}`;
17
+ }
18
+
19
+ const winMatch = filePath.match(/^([a-zA-Z]):\\(.*)$/);
20
+ if (winMatch) {
21
+ const drive = winMatch[1].toLowerCase();
22
+ const rest = winMatch[2].replace(/\\/g, '/');
23
+ return `/mnt/${drive}/${rest}`;
24
+ }
25
+
26
+ return null;
27
+ };
28
+
29
+ const resolveExistingPath = (inputPath) => {
30
+ if (fs.existsSync(inputPath)) {
31
+ return inputPath;
32
+ }
33
+
34
+ const converted = convertPath(inputPath);
35
+ if (converted && fs.existsSync(converted)) {
36
+ return converted;
37
+ }
38
+
39
+ return null;
40
+ };
41
+
42
+ const resolveWorkingDirectory = (rawPath) => {
43
+ if (!rawPath || typeof rawPath !== 'string') {
44
+ throw new Error('必须提供 working_directory');
45
+ }
46
+
47
+ if (!path.isAbsolute(rawPath)) {
48
+ throw new Error('working_directory 必须是绝对路径');
49
+ }
50
+
51
+ const resolved = resolveExistingPath(rawPath);
52
+ if (!resolved) {
53
+ throw new Error('工作目录不存在,请确认路径是否正确');
54
+ }
55
+
56
+ const stats = fs.statSync(resolved);
57
+ if (!stats.isDirectory()) {
58
+ throw new Error('working_directory 必须是文件夹路径');
59
+ }
60
+
61
+ return resolved;
62
+ };
63
+
11
64
  const resolveAsset = (relativePath) => {
12
65
  const target = path.resolve(ASSETS_ROOT, relativePath);
13
66
  const rel = path.relative(ASSETS_ROOT, target);
@@ -57,9 +110,6 @@ const SNIPPETS = {
57
110
  title: 'SVG 转 PPTX',
58
111
  description: '把 SVG 转化成在 PPTX 中创建可操作的元素。',
59
112
  codeFile: 'svg_to_pptx.py',
60
- extraFiles: [
61
- { label: '示例 HTML(ppt_slide.html)', file: 'ppt_slide.html', language: 'html' }
62
- ],
63
113
  notes: [
64
114
  '【Icon 元素处理】对于复杂的 SVG 图标(如 <g id="icon-*"> 元素或包含 path 的小图标),应先将其独立保存为小的 PNG 图片,再插入到 PPTX 中。**不能遗漏任何图标**。',
65
115
  '【文本颜色丢失】python-pptx 设置字体名称时会添加 a:latin/a:ea 等元素,如果颜色填充放在 rPr 末尾会被 PowerPoint 忽略。解决:用 rPr.insert(0, solidFill/gradFill) 将颜色填充插入到 rPr 开头,确保优先级最高。',
@@ -152,39 +202,28 @@ const GUIDES = {
152
202
  }
153
203
  };
154
204
 
155
- const buildSnippet = (title) => {
205
+ const buildSnippet = (title, workingDirectory) => {
156
206
  const entry = SNIPPETS[title];
157
207
  if (!entry) {
158
208
  const supported = Object.keys(SNIPPETS).join(', ');
159
209
  throw new Error(`title 仅支持: ${supported}`);
160
210
  }
161
211
 
162
- const lines = [];
163
- lines.push(`【${entry.title}】参考脚本`);
164
- if (entry.description) lines.push(entry.description);
165
-
166
- if (entry.notes?.length) {
167
- lines.push('要点:');
168
- entry.notes.forEach((note) => lines.push(`- ${note}`));
169
- }
212
+ const workingDir = resolveWorkingDirectory(workingDirectory);
213
+ const code = loadText(entry.codeFile);
214
+ const outputPath = path.join(workingDir, entry.codeFile);
215
+ fs.writeFileSync(outputPath, code);
170
216
 
171
- if (entry.extraFiles?.length) {
172
- entry.extraFiles.forEach((extra) => {
173
- const content = loadText(extra.file).trimEnd();
174
- lines.push(extra.label || '配套文件');
175
- const lang = extra.language || path.extname(extra.file).replace('.', '') || '';
176
- lines.push(`\`\`\`${lang}`);
177
- lines.push(content);
178
- lines.push('```');
217
+ const lines = [];
218
+ lines.push(`文件名: ${entry.codeFile}`);
219
+ if (entry.notes && entry.notes.length > 0) {
220
+ lines.push('');
221
+ lines.push('注意事项:');
222
+ entry.notes.forEach((note, idx) => {
223
+ lines.push(`${idx + 1}. ${note}`);
179
224
  });
180
225
  }
181
226
 
182
- const code = loadText(entry.codeFile).trimEnd();
183
- lines.push('示例代码:');
184
- lines.push('```python');
185
- lines.push(code);
186
- lines.push('```');
187
-
188
227
  return lines.join('\n');
189
228
  };
190
229
 
@@ -206,17 +245,21 @@ const listTools = () => ({
206
245
  tools: [
207
246
  {
208
247
  name: 'snippet',
209
- description: '返回常见文件转换的 Python 参考脚本及要点说明',
248
+ description: '将常见文件转换的 Python 参考脚本保存到工作目录下(可直接作为工具模块使用),返回文件名和注意事项',
210
249
  inputSchema: {
211
250
  type: 'object',
212
251
  properties: {
252
+ working_directory: {
253
+ type: 'string',
254
+ description: '工作目录的绝对路径,生成的脚本文件将保存到此目录'
255
+ },
213
256
  title: {
214
257
  type: 'string',
215
258
  description: '示例类型,可选: html_to_png | pdf_to_png | pptx_to_pdf | svg_to_pptx',
216
259
  enum: Object.keys(SNIPPETS)
217
260
  }
218
261
  },
219
- required: ['title']
262
+ required: ['working_directory', 'title']
220
263
  }
221
264
  },
222
265
  {
@@ -237,7 +280,7 @@ const listTools = () => ({
237
280
  ]
238
281
  });
239
282
 
240
- const server = new Server({ name: 'skills', version: '2.2.14' }, { capabilities: { tools: {} } });
283
+ const server = new Server({ name: 'skills', version: '2.4.0' }, { capabilities: { tools: {} } });
241
284
 
242
285
  server.setRequestHandler(ListToolsRequestSchema, async () => listTools());
243
286
 
@@ -246,9 +289,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
246
289
 
247
290
  try {
248
291
  if (name === 'snippet') {
249
- const title = args?.title;
250
- const payload = buildSnippet(title);
251
- return { content: [{ type: 'text', text: payload }] };
292
+ const { working_directory, title } = args || {};
293
+ if (!working_directory || !title) {
294
+ throw new Error('必须同时提供 working_directory title 参数');
295
+ }
296
+ const result = buildSnippet(title, working_directory);
297
+ return { content: [{ type: 'text', text: result }] };
252
298
  }
253
299
 
254
300
  if (name === 'guide') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ww_nero/skills",
3
- "version": "2.2.14",
3
+ "version": "2.4.0",
4
4
  "description": "MCP server that returns Python reference snippets and skill guides",
5
5
  "main": "index.js",
6
6
  "bin": {
package/assets/demo.jpg DELETED
Binary file
@@ -1,165 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>大模型发展历程 - 神经网络复兴时期</title>
7
- </head>
8
- <body>
9
- <svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg">
10
- <defs>
11
- <!-- Background Gradient -->
12
- <linearGradient id="bgGrad" x1="0%" y1="0%" x2="0%" y2="100%">
13
- <stop offset="0%" stop-color="#1a237e"/>
14
- <stop offset="100%" stop-color="#0d1b60"/>
15
- </linearGradient>
16
-
17
- <!-- Accent Gradient for Tech Elements -->
18
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="0%">
19
- <stop offset="0%" stop-color="#00e5ff"/>
20
- <stop offset="100%" stop-color="#2979ff"/>
21
- </linearGradient>
22
-
23
- <!-- Glow Effect -->
24
- <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
25
- <feGaussianBlur stdDeviation="2" result="blur"/>
26
- <feComposite in="SourceGraphic" in2="blur" operator="over"/>
27
- </filter>
28
-
29
- </defs>
30
-
31
- <!-- Background -->
32
- <rect width="100%" height="100%" fill="url(#bgGrad)"/>
33
-
34
- <!-- Decorative Neural Network Background (Right Side) -->
35
- <g opacity="0.1" stroke="#ffffff" stroke-width="1">
36
- <line x1="800" y1="200" x2="900" y2="300" />
37
- <line x1="900" y1="300" x2="850" y2="450" />
38
- <line x1="850" y1="450" x2="750" y2="400" />
39
- <line x1="750" y1="400" x2="800" y2="200" />
40
- <line x1="800" y1="200" x2="650" y2="250" />
41
- <line x1="650" y1="250" x2="750" y2="400" />
42
- <circle cx="800" cy="200" r="4" fill="#fff"/>
43
- <circle cx="900" cy="300" r="4" fill="#fff"/>
44
- <circle cx="850" cy="450" r="4" fill="#fff"/>
45
- <circle cx="750" cy="400" r="4" fill="#fff"/>
46
- <circle cx="650" cy="250" r="4" fill="#fff"/>
47
- </g>
48
-
49
- <!-- Image Placeholder - rect (左侧时间线区域右侧) -->
50
- <rect id="image-placeholder" x="420" y="340" width="180" height="120" fill="rgba(255,255,255,0.1)" stroke="#00e5ff" stroke-width="2" stroke-dasharray="8 4"/>
51
-
52
- <!-- Image Placeholder - circle (圆形头像占位) -->
53
- <circle id="image-placeholder-circle" cx="1150" cy="120" r="50" fill="rgba(255,255,255,0.1)" stroke="#00e5ff" stroke-width="2" stroke-dasharray="8 4"/>
54
-
55
- <!-- Icon Placeholder (图标占位符,转换时会先保存为小PNG再插入) -->
56
- <g id="icon-placeholder" transform="translate(1100, 650)">
57
- <rect x="0" y="0" width="24" height="24" fill="none"/>
58
- <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" stroke="#00e5ff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
59
- </g>
60
-
61
- <!-- Header Section -->
62
- <g transform="translate(60, 80)">
63
- <text x="0" y="0" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="48" font-weight="bold" fill="#ffffff" letter-spacing="1">深度学习的崛起(1990-2017)</text>
64
- <rect x="0" y="20" width="100" height="4" fill="url(#accentGrad)" rx="2"/>
65
- <line x1="0" y1="22" x2="1160" y2="22" stroke="#ffffff" stroke-width="1" opacity="0.2" />
66
- </g>
67
-
68
- <!-- Layout Divider -->
69
- <line x1="640" y1="180" x2="640" y2="630" stroke="#00e5ff" stroke-width="1" stroke-dasharray="4 4" opacity="0.3" />
70
-
71
- <!-- Left Column: Technology Breakthroughs -->
72
- <g transform="translate(60, 180)">
73
- <text x="0" y="0" font-family="sans-serif" font-size="28" fill="#00e5ff" font-weight="bold">技术突破</text>
74
-
75
- <!-- Timeline Line -->
76
- <line x1="20" y1="50" x2="20" y2="480" stroke="#b3e5fc" stroke-width="2" opacity="0.3"/>
77
-
78
- <!-- 1998 Item -->
79
- <g transform="translate(0, 70)">
80
- <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
81
- <text x="45" y="0" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold" alignment-baseline="middle">1998</text>
82
- <text x="45" y="30" font-family="sans-serif" font-size="20" fill="#b3e5fc" alignment-baseline="middle">LeNet-5,CNN开创性工作</text>
83
- </g>
84
-
85
- <!-- 2012 Item -->
86
- <g transform="translate(0, 190)">
87
- <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
88
- <text x="45" y="0" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold" alignment-baseline="middle">2012</text>
89
- <text x="45" y="30" font-family="sans-serif" font-size="20" fill="#b3e5fc" alignment-baseline="middle">AlexNet赢得ImageNet竞赛</text>
90
- </g>
91
-
92
- <!-- 2014 Item -->
93
- <g transform="translate(0, 310)">
94
- <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
95
- <text x="45" y="0" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold" alignment-baseline="middle">2014</text>
96
- <text x="45" y="30" font-family="sans-serif" font-size="20" fill="#b3e5fc" alignment-baseline="middle">GAN生成对抗网络</text>
97
- </g>
98
-
99
- <!-- 2015 Item -->
100
- <g transform="translate(0, 430)">
101
- <circle cx="20" cy="0" r="6" fill="#1a237e" stroke="#00e5ff" stroke-width="2"/>
102
- <text x="45" y="0" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold" alignment-baseline="middle">2015</text>
103
- <text x="45" y="30" font-family="sans-serif" font-size="20" fill="#b3e5fc" alignment-baseline="middle">ResNet残差网络</text>
104
- </g>
105
- </g>
106
-
107
- <!-- Right Column: Key Figures -->
108
- <g transform="translate(688, 180)">
109
- <text x="0" y="0" font-family="sans-serif" font-size="28" fill="#00e5ff" font-weight="bold">关键人物</text>
110
- <text x="0" y="35" font-family="sans-serif" font-size="16" fill="#b3e5fc" opacity="0.7">Turing Award Winners ("Godfathers of AI")</text>
111
-
112
- <!-- Card Container Styles -->
113
- <defs>
114
- <path id="cardShape" d="M0 10 L10 0 L380 0 L380 90 L370 100 L0 100 Z" />
115
- </defs>
116
-
117
- <!-- Person 1: Hinton -->
118
- <g transform="translate(0, 70)">
119
- <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
120
- <!-- Decorative corner -->
121
- <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
122
- <!-- Content -->
123
- <text x="30" y="40" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold">Geoffrey Hinton</text>
124
- <text x="30" y="70" font-family="sans-serif" font-size="16" fill="#b3e5fc">Backpropagation, Deep Belief Nets</text>
125
- <!-- Tech Icon -->
126
- <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
127
- <circle cx="340" cy="50" r="8" fill="#00e5ff" opacity="0.8"/>
128
- </g>
129
-
130
- <!-- Person 2: LeCun -->
131
- <g transform="translate(0, 190)">
132
- <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
133
- <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
134
- <text x="30" y="40" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold">Yann LeCun</text>
135
- <text x="30" y="70" font-family="sans-serif" font-size="16" fill="#b3e5fc">CNN (Convolutional Neural Networks)</text>
136
- <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
137
- <rect x="332" y="42" width="16" height="16" fill="#00e5ff" opacity="0.8"/>
138
- </g>
139
-
140
- <!-- Person 3: Bengio -->
141
- <g transform="translate(0, 310)">
142
- <use href="#cardShape" fill="rgba(255,255,255,0.05)" stroke="rgba(0,229,255,0.3)" stroke-width="1"/>
143
- <path d="M0 20 L0 10 L10 0 L20 0" fill="none" stroke="#00e5ff" stroke-width="2"/>
144
- <text x="30" y="40" font-family="sans-serif" font-size="24" fill="#ffffff" font-weight="bold">Yoshua Bengio</text>
145
- <text x="30" y="70" font-family="sans-serif" font-size="16" fill="#b3e5fc">Sequence Modeling, GANs</text>
146
- <circle cx="340" cy="50" r="20" stroke="#00e5ff" stroke-width="1" fill="none" opacity="0.5"/>
147
- <polygon points="340,38 352,58 328,58" fill="#00e5ff" opacity="0.8"/>
148
- </g>
149
- </g>
150
-
151
- <!-- Footer Decor -->
152
- <g transform="translate(0, 672)">
153
- <rect x="0" y="0" width="1280" height="48" fill="#0d1b60" opacity="0.8"/>
154
- <text x="60" y="30" font-family="sans-serif" font-size="12" fill="#b3e5fc" opacity="0.5">NEURAL NETWORKS RENAISSANCE | AI HISTORY SERIES</text>
155
-
156
- <!-- Decorative dots footer -->
157
- <g fill="#00e5ff" opacity="0.5">
158
- <circle cx="1206" cy="24" r="2"/>
159
- <circle cx="1216" cy="24" r="2"/>
160
- <circle cx="1226" cy="24" r="2"/>
161
- </g>
162
- </g>
163
- </svg>
164
- </body>
165
- </html>