feat(i18n): add AI history components internationalization support

- Add useI18n composable and ai-history locale files
- Refactor 10 AI history Vue components to support i18n (GPTEvolutionDemo, AIErasComparisonDemo, AiEvolutionDemo, etc.)
- Add English version of AI history appendix article
- Add English translations for stage-1 appendix-articles:
  - vibe-coding-tools-snake-game-tutorial.md
  - vibe-coding-tools-build-website-with-ai-coding-and-design-agents.md
- Use relative paths to reference Chinese version images
- Update appendix sidebar config to use English AI history link
This commit is contained in:
sanbuphy
2026-02-26 09:33:06 +08:00
parent d2809706e5
commit de86489421
17 changed files with 1451 additions and 140 deletions
@@ -2,28 +2,28 @@
<div class="demo-card">
<div class="era-container">
<div class="era-header">
🌟 AI 发展阶段与核心范式全景对比
{{ t('erasComparison.header') }}
</div>
<div class="era-grid">
<div v-for="era in eras" :key="era.name" class="era-item" :style="{ borderTopColor: era.color }">
<div class="e-icon" :style="{ background: era.color }">{{ era.icon }}</div>
<div class="e-name" :style="{ color: era.color }">{{ era.name }}</div>
<div v-for="(era, i) in localEras" :key="i" class="era-item" :style="{ borderTopColor: eraStyles[i]?.color }">
<div class="e-icon" :style="{ background: eraStyles[i]?.color }">{{ eraStyles[i]?.icon }}</div>
<div class="e-name" :style="{ color: eraStyles[i]?.color }">{{ era.name }}</div>
<div class="e-time">{{ era.time }}</div>
<div class="e-section">
<div class="e-label">驱动方式</div>
<div class="e-label">{{ t('erasComparison.driverLabel') }}</div>
<div class="e-value">{{ era.driver }}</div>
</div>
<div class="e-section">
<div class="e-label">核心机制</div>
<div class="e-label">{{ t('erasComparison.mechanismLabel') }}</div>
<div class="e-value">
<span class="highlight">{{ era.mechanism }}</span>
</div>
</div>
<div class="e-section">
<div class="e-label">典型代表</div>
<div class="e-label">{{ t('erasComparison.examplesLabel') }}</div>
<div class="e-tags">
<span v-for="tag in era.examples" :key="tag" class="e-tag">{{ tag }}</span>
</div>
@@ -35,52 +35,19 @@
</template>
<script setup>
const eras = [
{
name: '规则系统时代',
time: '1960s - 1980s',
icon: '📜',
color: '#059669', // emerald
driver: '人类硬编码知识',
mechanism: 'If-Then 逻辑推演',
examples: ['Dendral', '深蓝 (Deep Blue)']
},
{
name: '传统机器学习',
time: '1990s - 2000s',
icon: '📊',
color: '#d97706', // amber
driver: '人工特征工程 + 统计学',
mechanism: '寻找数学决策边界',
examples: ['支持向量机 (SVM)', '随机森林']
},
{
name: '深度学习革命',
time: '2010s',
icon: '🧠',
color: '#dc2626', // red
driver: '大数据 + 算力爬升',
mechanism: '神经网络自动提取特征',
examples: ['AlexNet (CNN)', 'AlphaGo (RL)']
},
{
name: '大语言模型 (LLM)',
time: '2018 - 至今',
icon: '💬',
color: '#7c3aed', // violet
driver: '海量无标注数据 + 暴力计算',
mechanism: '预测下一个词 + 涌现常识',
examples: ['GPT-4', 'Claude 3']
},
{
name: '智能体 (Agentic AI)',
time: '现在 - 未来',
icon: '🤖',
color: '#0284c7', // light blue
driver: '大模型大脑 + 环境感知',
mechanism: '自主规划 + 工具调用',
examples: ['AI 程序员', '具身智能']
}
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const localEras = computed(() => messages.value.erasComparison?.eras ?? [])
const eraStyles = [
{ icon: '📜', color: '#059669' },
{ icon: '📊', color: '#d97706' },
{ icon: '🧠', color: '#dc2626' },
{ icon: '💬', color: '#7c3aed' },
{ icon: '🤖', color: '#0284c7' },
]
</script>
@@ -1,29 +1,36 @@
<template>
<div class="demo-card">
<div class="timeline-visual">
<div v-for="era in eras" :key="era.label" class="era" :style="{ flex: era.flex, background: era.bg }">
<div class="era-label">{{ era.label }}</div>
<div class="era-years">{{ era.years }}</div>
<div v-for="(era, i) in eras" :key="i" class="era" :style="{ flex: era.flex, background: era.bg }">
<div class="era-label">{{ localeEras[i]?.label ?? era.label }}</div>
<div class="era-years">{{ localeEras[i]?.years ?? era.years }}</div>
</div>
</div>
<div class="legend">
<span class="legend-item"><span class="dot" style="background:#059669"></span>技术浪潮</span>
<span class="legend-item"><span class="dot" style="background:#94a3b8"></span> AI 寒冬</span>
<span class="legend-item"><span class="dot" style="background:#7c3aed"></span>大模型时代</span>
<span class="legend-item"><span class="dot" style="background:#059669"></span>{{ t('aiEvolution.legend.wave') }}</span>
<span class="legend-item"><span class="dot" style="background:#94a3b8"></span>{{ t('aiEvolution.legend.winter') }}</span>
<span class="legend-item"><span class="dot" style="background:#7c3aed"></span>{{ t('aiEvolution.legend.llm') }}</span>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const localeEras = computed(() => messages.value.aiEvolution?.eras ?? [])
const eras = [
{ label: '理论奠基', years: '1940s-50s', flex: 1.5, bg: 'linear-gradient(135deg, #dbeafe, #bfdbfe)' },
{ label: '第一次浪潮', years: '1960s-70s', flex: 1.5, bg: 'linear-gradient(135deg, #d1fae5, #a7f3d0)' },
{ label: '❄️ 寒冬 I', years: '1974-80', flex: 0.7, bg: 'linear-gradient(135deg, #e2e8f0, #cbd5e1)' },
{ label: '第二次浪潮', years: '1980s', flex: 1, bg: 'linear-gradient(135deg, #d1fae5, #a7f3d0)' },
{ label: '❄️ 寒冬 II', years: '1987-93', flex: 0.7, bg: 'linear-gradient(135deg, #e2e8f0, #cbd5e1)' },
{ label: 'ML 崛起', years: '1990s-2000s', flex: 1.5, bg: 'linear-gradient(135deg, #d1fae5, #6ee7b7)' },
{ label: '深度学习', years: '2010s', flex: 1.2, bg: 'linear-gradient(135deg, #a7f3d0, #34d399)' },
{ label: '大模型时代', years: '2018+', flex: 1.2, bg: 'linear-gradient(135deg, #c4b5fd, #a78bfa)' },
{ flex: 1.5, bg: 'linear-gradient(135deg, #dbeafe, #bfdbfe)' },
{ flex: 1.5, bg: 'linear-gradient(135deg, #d1fae5, #a7f3d0)' },
{ flex: 0.7, bg: 'linear-gradient(135deg, #e2e8f0, #cbd5e1)' },
{ flex: 1, bg: 'linear-gradient(135deg, #d1fae5, #a7f3d0)' },
{ flex: 0.7, bg: 'linear-gradient(135deg, #e2e8f0, #cbd5e1)' },
{ flex: 1.5, bg: 'linear-gradient(135deg, #d1fae5, #6ee7b7)' },
{ flex: 1.2, bg: 'linear-gradient(135deg, #a7f3d0, #34d399)' },
{ flex: 1.2, bg: 'linear-gradient(135deg, #c4b5fd, #a78bfa)' },
]
</script>
@@ -2,7 +2,7 @@
<div class="demo-card">
<div class="attention-layout">
<div class="sentence-col">
<div class="col-label">处理<strong></strong>时的注意力分配</div>
<div class="col-label" v-html="colLabel"></div>
<div class="sentence-box">
<span v-for="(word, i) in sentence" :key="i" class="word-token" :class="{ focus: i === focusIdx }">{{ word }}</span>
</div>
@@ -18,16 +18,26 @@
</div>
</div>
<div class="caption">
虽在句中间模型却把 65% 注意力精准投向句首的小明跨越距离识别代词指代
{{ t('attention.caption') }}
</div>
</div>
</template>
<script setup>
const sentence = ['小明', '把', '苹果', '给了', '他', '的', '母亲']
const focusIdx = 4
const attn = [0.65, 0.05, 0.10, 0.10, 0.05, 0.03, 0.02]
const weights = sentence.map((word, i) => ({ word, w: attn[i] }))
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const attnData = computed(() => messages.value.attention ?? {})
const sentence = computed(() => attnData.value.sentence ?? [])
const focusIdx = computed(() => attnData.value.focusIdx ?? 4)
const rawWeights = computed(() => attnData.value.weights ?? [])
const weights = computed(() => sentence.value.map((word, i) => ({ word, w: rawWeights.value[i] ?? 0 })))
const focusWord = computed(() => sentence.value[focusIdx.value] ?? '')
const colLabel = computed(() => (attnData.value.colLabel ?? '').replace('{word}', focusWord.value))
const barColor = (v) => v > 0.5 ? '#dc2626' : v > 0.15 ? '#d97706' : v > 0.06 ? '#059669' : 'var(--vp-c-divider)'
</script>
@@ -1,15 +1,15 @@
<template>
<div class="demo-card">
<div class="bp-flow">
<div v-for="(step, i) in steps" :key="i" class="step-block" :style="{ borderTopColor: step.color }">
<div class="step-num" :style="{ background: step.color }">{{ i + 1 }}</div>
<div v-for="(step, i) in localSteps" :key="i" class="step-block" :style="{ borderTopColor: stepColors[i] }">
<div class="step-num" :style="{ background: stepColors[i] }">{{ i + 1 }}</div>
<div class="step-icon">{{ step.icon }}</div>
<div class="step-name">{{ step.name }}</div>
<div class="step-desc">{{ step.desc }}</div>
</div>
</div>
<div class="loss-visual">
<div class="loss-label">Loss误差随训练轮次下降</div>
<div class="loss-label">{{ t('backprop.lossLabel') }}</div>
<svg viewBox="0 0 320 130" class="loss-svg">
<!-- Axes -->
<line x1="40" y1="110" x2="300" y2="110" stroke="var(--vp-c-text-3)" stroke-width="1.5" />
@@ -21,12 +21,12 @@
<polygon points="37,15 40,10 43,15" fill="var(--vp-c-text-3)" />
<!-- Y Label -->
<text x="30" y="25" text-anchor="end" class="ax-text"></text>
<text x="30" y="105" text-anchor="end" class="ax-text"></text>
<text x="30" y="25" text-anchor="end" class="ax-text">{{ t('backprop.axisHigh') }}</text>
<text x="30" y="105" text-anchor="end" class="ax-text">{{ t('backprop.axisLow') }}</text>
<text x="20" y="65" text-anchor="middle" transform="rotate(-90 20 65)" class="ax-title">Loss</text>
<!-- X Label -->
<text x="300" y="125" text-anchor="end" class="ax-title">训练轮次 (Epochs)</text>
<text x="300" y="125" text-anchor="end" class="ax-title">{{ t('backprop.axisEpochs') }}</text>
<!-- Loss 曲线 -->
<polyline :points="lossPoints" fill="none" stroke="var(--vp-c-brand)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
@@ -36,12 +36,14 @@
</template>
<script setup>
const steps = [
{ icon: '➡️', name: '前向传播', desc: '数据流过网络,得出预测', color: '#3b82f6' },
{ icon: '📐', name: '计算误差', desc: '预测值 vs 正确答案,算 Loss', color: '#d97706' },
{ icon: '⬅️', name: '反向传播', desc: '逐层追溯每个权重的"责任"', color: '#dc2626' },
{ icon: '⚙️', name: '更新权重', desc: '按责任微调,减少下次误差', color: '#059669' },
]
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const localSteps = computed(() => messages.value.backprop?.steps ?? [])
const stepColors = ['#3b82f6', '#d97706', '#dc2626', '#059669']
const lossPoints = (() => {
const pts = []
for (let i = 0; i <= 50; i++) {
@@ -1,24 +1,31 @@
<template>
<div class="demo-card">
<div class="schools-grid">
<div v-for="s in schools" :key="s.name" class="school-card" :style="{ borderTopColor: s.color }">
<div v-for="(s, i) in schoolStyles" :key="i" class="school-card" :style="{ borderTopColor: s.color }">
<div class="card-head">
<span class="school-icon">{{ s.icon }}</span>
<span class="school-name" :style="{ color: s.color }">{{ s.name }}</span>
<span class="school-name" :style="{ color: s.color }">{{ localeItems[i]?.name }}</span>
</div>
<div class="school-idea">{{ s.idea }}</div>
<div class="school-rep">代表{{ s.rep }}</div>
<div class="school-status">{{ s.status }}</div>
<div class="school-idea">{{ localeItems[i]?.idea }}</div>
<div class="school-rep">{{ t('schools.repLabel') }}{{ localeItems[i]?.rep }}</div>
<div class="school-status">{{ localeItems[i]?.status }}</div>
</div>
</div>
</div>
</template>
<script setup>
const schools = [
{ name: '符号主义', icon: '📜', color: '#059669', idea: '智能 = 符号推理 / If-Then 规则', rep: '专家系统、深蓝', status: '→ 与连接主义融合(神经符号 AI)' },
{ name: '连接主义', icon: '🧠', color: '#7c3aed', idea: '智能 = 神经元网络 + 海量数据', rep: 'AlphaGo、GPT 系列', status: '→ 主导大模型时代,当前主流' },
{ name: '行为主义', icon: '🎮', color: '#d97706', idea: '智能 = 与环境互动 / 强化学习', rep: 'AlphaGoRL 部分)', status: '→ 与连接主义融合(深度强化学习)' },
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const localeItems = computed(() => messages.value.schools?.items ?? [])
const schoolStyles = [
{ icon: '📜', color: '#059669' },
{ icon: '🧠', color: '#7c3aed' },
{ icon: '🎮', color: '#d97706' },
]
</script>
@@ -1,18 +1,27 @@
<template>
<div class="demo-card">
<div class="demo-label">符号主义的核心思路 把知识写成规则</div>
<div class="demo-label">{{ t('foundation.label') }}</div>
<div class="code-block">
<div class="code-line"><span class="kw">IF</span> 体温 &gt; 38.5°C <span class="kw">AND</span> 白细胞计数 &gt; 11000</div>
<div class="code-line indent"><span class="kw">THEN</span> 诊断 = <span class="str">"细菌感染"</span></div>
<div class="code-line"><span class="kw">IF</span> 诊断 = <span class="str">"细菌感染"</span> <span class="kw">AND</span> 对青霉素不过敏</div>
<div class="code-line indent"><span class="kw">THEN</span> 治疗方案 = <span class="str">"青霉素 400mg / 每日两次"</span></div>
<div class="code-line comment">// 早期医疗专家系统(MYCIN,1977)就是由 450+ 条这样的规则组成的</div>
<div v-for="(line, i) in foundationLines" :key="i" class="code-line" :class="{ indent: line.indent }">
<template v-for="(p, j) in line.parts" :key="j">
<span v-if="p.kw" class="kw">{{ p.kw }}</span>
<span v-else-if="p.str" class="str">{{ p.str }}</span>
<template v-else>{{ p.text }}</template>
</template>
</div>
<div class="code-line comment">{{ t('foundation.comment') }}</div>
</div>
<div class="demo-caption">人类专家把经验翻译成一条条 IF-THEN 规则机器逐条匹配执行</div>
<div class="demo-caption">{{ t('foundation.caption') }}</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const foundationLines = computed(() => messages.value.foundation?.lines ?? [])
</script>
<style scoped>
@@ -1,14 +1,14 @@
<template>
<div class="demo-card">
<div class="gpt-grid">
<div v-for="m in models" :key="m.name" class="gpt-card" :style="{ borderTopColor: m.color }">
<div v-for="(m, i) in models" :key="i" class="gpt-card" :style="{ borderTopColor: modelColors[i] }">
<div class="card-top">
<span class="gpt-name" :style="{ color: m.color }">{{ m.name }}</span>
<span class="gpt-name" :style="{ color: modelColors[i] }">{{ m.name }}</span>
<span class="gpt-year">{{ m.year }}</span>
</div>
<div class="param-val">{{ m.params }}</div>
<div class="param-bar-bg">
<div class="param-bar" :style="{ width: m.barWidth, background: m.color }"></div>
<div class="param-bar" :style="{ width: m.barWidth, background: modelColors[i] }"></div>
</div>
<div class="gpt-key">{{ m.key }}</div>
</div>
@@ -17,12 +17,14 @@
</template>
<script setup>
const models = [
{ name: 'GPT-1', year: '2018', params: '1.17 亿', barWidth: '2%', color: '#94a3b8', key: '预训练+微调范式确立' },
{ name: 'GPT-2', year: '2019', params: '15 亿', barWidth: '6%', color: '#3b82f6', key: 'Zero-shot 零样本泛化' },
{ name: 'GPT-3', year: '2020', params: '1750 亿', barWidth: '45%', color: '#7c3aed', key: '⚡ 涌现!上下文学习' },
{ name: 'GPT-4', year: '2023', params: '~1.8 万亿', barWidth: '100%', color: '#dc2626', key: '多模态 + 复杂推理' },
]
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { messages } = useI18n(aiHistoryLocale)
const models = computed(() => messages.value.gptEvolution ?? [])
const modelColors = ['#94a3b8', '#3b82f6', '#7c3aed', '#dc2626']
</script>
<style scoped>
@@ -7,12 +7,12 @@
<g v-for="layer in layers" :key="layer.idx">
<circle v-for="n in layer.nodes" :key="n.id" :cx="n.x" :cy="n.y" r="15" :fill="layer.fill" :stroke="layer.stroke" stroke-width="2" />
</g>
<text v-for="layer in layers" :key="'l-'+layer.idx" :x="layer.x" y="194" text-anchor="middle" :fill="layer.stroke" class="lbl">{{ layer.name }}</text>
<text v-for="(layer, i) in layers" :key="'l-'+layer.idx" :x="layer.x" y="194" text-anchor="middle" :fill="layer.stroke" class="lbl">{{ localLayers[i]?.name }}</text>
</svg>
</div>
<div class="layer-cards">
<div v-for="info in layerInfo" :key="info.name" class="layer-card" :style="{ borderLeftColor: info.color }">
<div class="lc-title" :style="{ color: info.color }">{{ info.name }}</div>
<div v-for="(info, i) in localLayers" :key="i" class="layer-card" :style="{ borderLeftColor: layerColors[i]?.color }">
<div class="lc-title" :style="{ color: layerColors[i]?.color }">{{ info.name }}</div>
<div class="lc-desc">{{ info.desc }}</div>
</div>
</div>
@@ -21,27 +21,33 @@
</template>
<script setup>
import { computed } from 'vue'
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { messages } = useI18n(aiHistoryLocale)
const localLayers = computed(() => messages.value.neuralNet?.layers ?? [])
const W = 380, H = 185
const layerDef = [
{ name: '输入层', count: 3, xFrac: 0.13, color: '#3b82f6', fill: '#dbeafe' },
{ name: '隐藏层', count: 4, xFrac: 0.5, color: '#7c3aed', fill: '#ede9fe' },
{ name: '输出层', count: 2, xFrac: 0.87, color: '#059669', fill: '#d1fae5' },
const layerColors = [
{ color: '#3b82f6', fill: '#dbeafe' },
{ color: '#7c3aed', fill: '#ede9fe' },
{ color: '#059669', fill: '#d1fae5' },
]
const layers = layerDef.map((l, idx) => {
const x = l.xFrac * W
const gap = Math.min(46, (H - 36) / (l.count - 1 || 1))
const startY = (H - gap * (l.count - 1)) / 2
return { idx, x, name: l.name, fill: l.fill, stroke: l.color, nodes: Array.from({ length: l.count }, (_, i) => ({ id: `${idx}-${i}`, x, y: startY + i * gap })) }
const layerCounts = [3, 4, 2]
const xFracs = [0.13, 0.5, 0.87]
const layers = layerColors.map((l, idx) => {
const x = xFracs[idx] * W
const count = layerCounts[idx]
const gap = Math.min(46, (H - 36) / (count - 1 || 1))
const startY = (H - gap * (count - 1)) / 2
return { idx, x, fill: l.fill, stroke: l.color, nodes: Array.from({ length: count }, (_, i) => ({ id: `${idx}-${i}`, x, y: startY + i * gap })) }
})
const connections = []
for (let li = 0; li < layers.length - 1; li++) {
layers[li].nodes.forEach(a => { layers[li + 1].nodes.forEach(b => { connections.push({ id: `${a.id}-${b.id}`, x1: a.x, y1: a.y, x2: b.x, y2: b.y }) }) })
}
const layerInfo = [
{ name: '输入层', desc: '原始像素 / 数值信号', color: '#3b82f6' },
{ name: '隐藏层(可叠加多层)', desc: '底层识别边缘 → 中层识别形状 → 高层识别语义概念', color: '#7c3aed' },
{ name: '输出层', desc: '最终分类或预测结果', color: '#059669' },
]
</script>
<style scoped>
@@ -2,13 +2,13 @@
<div class="demo-card">
<div class="perceptron-layout">
<div class="inputs-col">
<div v-for="inp in inputs" :key="inp.label" class="input-node">
<div v-for="(inp, i) in inputs" :key="i" class="input-node">
<span class="node-circle">{{ inp.val }}</span>
<span class="node-label">{{ inp.label }}</span>
<span class="node-label">{{ featureLabels[i] }}</span>
</div>
</div>
<div class="weights-col">
<div v-for="inp in inputs" :key="inp.label" class="weight-arrow">
<div v-for="(inp, i) in inputs" :key="i" class="weight-arrow">
<span class="arrow"></span>
<span class="w-tag">×{{ inp.weight }}</span>
</div>
@@ -18,7 +18,7 @@
<div class="n-sym">Σ</div>
<div class="n-val">{{ sum }}</div>
</div>
<span class="bias-tag">偏置 {{ bias }}</span>
<span class="bias-tag">{{ t('perceptron.biasLabel') }} {{ bias }}</span>
</div>
<div class="act-col">
<span class="arrow big"></span>
@@ -28,19 +28,23 @@
<div class="output-col">
<div class="output-node" :class="{ on: output === 1 }">
<span class="out-val">{{ output }}</span>
<span class="out-lbl">{{ output ? '激活' : '静默' }}</span>
<span class="out-lbl">{{ output ? t('perceptron.activated') : t('perceptron.silent') }}</span>
</div>
</div>
</div>
<div class="caption">
输入特征&emsp; 乘以权重重要性&emsp; 求和 + 偏置&emsp; 超过阈值就激活输出 1否则输出 0
</div>
<div class="caption">{{ t('perceptron.caption') }}</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
const inputs = [{ label: '特征 x₁', val: 1, weight: 0.6 }, { label: '特征 x₂', val: 0, weight: 0.4 }]
import { useI18n } from '../../../composables/useI18n.js'
import { aiHistoryLocale } from '../../../locales/ai-history/index.js'
const { t, messages } = useI18n(aiHistoryLocale)
const featureLabels = computed(() => messages.value.perceptron?.features ?? [])
const inputs = [{ val: 1, weight: 0.6 }, { val: 0, weight: 0.4 }]
const bias = -0.3
const sum = computed(() => Number((inputs.reduce((s, i) => s + i.val * i.weight, 0) + bias).toFixed(2)))
const output = computed(() => sum.value > 0 ? 1 : 0)
@@ -0,0 +1,44 @@
import { computed } from 'vue'
import { useData } from 'vitepress'
const langMap = {
'zh-CN': 'zh-cn',
'en-US': 'en',
'ja-JP': 'ja-jp',
'zh-TW': 'zh-tw',
'ko-KR': 'ko-kr',
'es-ES': 'es-es',
'fr-FR': 'fr-fr',
'de-DE': 'de-de',
'ar-SA': 'ar-sa',
'vi-VN': 'vi-vn'
}
/**
* Lightweight i18n composable for VitePress Vue components.
*
* @param {Record<string, Record<string, any>>} messages
* Locale map, e.g. { 'zh-cn': { title: '标题' }, en: { title: 'Title' } }
* @returns {{ t: (key: string) => any, locale: import('vue').ComputedRef<string> }}
*/
export function useI18n(messages) {
const { lang } = useData()
const locale = computed(() => langMap[lang.value] || 'zh-cn')
const current = computed(
() => messages[locale.value] || messages['zh-cn'] || {}
)
const t = (key) => {
const keys = key.split('.')
let val = current.value
for (const k of keys) {
val = val?.[k]
if (val === undefined) return key
}
return val
}
return { t, locale, messages: current }
}
@@ -0,0 +1,123 @@
// AI History English locale
export default {
// AiEvolutionDemo
aiEvolution: {
eras: [
{ label: 'Foundations', years: '1940s-50s' },
{ label: '1st Wave', years: '1960s-70s' },
{ label: '❄️ Winter I', years: '1974-80' },
{ label: '2nd Wave', years: '1980s' },
{ label: '❄️ Winter II', years: '1987-93' },
{ label: 'ML Rise', years: '1990s-2000s' },
{ label: 'Deep Learning', years: '2010s' },
{ label: 'LLM Era', years: '2018+' }
],
legend: {
wave: 'Tech Wave',
winter: '❄️ AI Winter',
llm: 'LLM Era'
}
},
// DiscriminativeVsGenerativeDemo
schools: {
repLabel: 'Examples',
items: [
{
name: 'Symbolism',
idea: 'Intelligence = symbolic reasoning / If-Then rules',
rep: 'Expert Systems, Deep Blue',
status: '→ Merging with connectionism (neuro-symbolic AI)'
},
{
name: 'Connectionism',
idea: 'Intelligence = neural networks + massive data',
rep: 'AlphaGo, GPT series',
status: '→ Dominates the LLM era, current mainstream'
},
{
name: 'Behaviorism',
idea: 'Intelligence = interaction with environment / RL',
rep: 'AlphaGo (RL component)',
status: '→ Merging with connectionism (deep RL)'
}
]
},
// FoundationDemo
foundation: {
label: 'Core idea of Symbolism — encoding knowledge as rules',
lines: [
{ parts: [{ kw: 'IF' }, { text: ' temperature > 38.5°C ' }, { kw: 'AND' }, { text: ' WBC count > 11000' }] },
{ indent: true, parts: [{ kw: 'THEN' }, { text: ' diagnosis = ' }, { str: '"bacterial infection"' }] },
{ parts: [{ kw: 'IF' }, { text: ' diagnosis = ' }, { str: '"bacterial infection"' }, { text: ' ' }, { kw: 'AND' }, { text: ' no penicillin allergy' }] },
{ indent: true, parts: [{ kw: 'THEN' }, { text: ' treatment = ' }, { str: '"penicillin 400mg / twice daily"' }] }
],
comment: '// The early medical expert system MYCIN (1977) consisted of 450+ rules like these',
caption: 'Human experts translate experience into IF-THEN rules; the machine matches and executes them one by one'
},
// PerceptronDemo
perceptron: {
features: ['Feature x₁', 'Feature x₂'],
biasLabel: 'Bias',
activated: 'Fire',
silent: 'Silent',
caption: '① Input features\u2003② Multiply by weights (importance)\u2003③ Sum + bias\u2003④ Fires output 1 if above threshold, otherwise 0'
},
// BackpropagationDemo
backprop: {
steps: [
{ icon: '➡️', name: 'Forward Pass', desc: 'Data flows through the network to produce a prediction' },
{ icon: '📐', name: 'Compute Loss', desc: 'Prediction vs. ground truth → calculate loss' },
{ icon: '⬅️', name: 'Backpropagation', desc: 'Trace back each weight\'s "responsibility" layer by layer' },
{ icon: '⚙️', name: 'Update Weights', desc: 'Adjust proportionally to reduce future error' }
],
lossLabel: 'Loss decreases over training epochs:',
axisHigh: 'High',
axisLow: 'Low',
axisEpochs: 'Training Epochs'
},
// NeuralNetworkVisualizationDemo
neuralNet: {
layers: [
{ name: 'Input Layer', desc: 'Raw pixels / numerical signals' },
{ name: 'Hidden Layers (stackable)', desc: 'Low → edges; Mid → shapes; High → semantic concepts' },
{ name: 'Output Layer', desc: 'Final classification or prediction' }
]
},
// AttentionMechanismDemo
attention: {
colLabel: 'Attention distribution when processing "{word}":',
sentence: ['John', 'gave', 'the', 'apple', 'to', 'his', 'mother'],
focusIdx: 5,
weights: [0.62, 0.08, 0.03, 0.10, 0.05, 0.07, 0.05],
caption: '"his" sits mid-sentence, yet the model directs 62% attention to "John" at the start — resolving the pronoun across distance'
},
// GPTEvolutionDemo
gptEvolution: [
{ name: 'GPT-1', year: '2018', params: '117 M', barWidth: '2%', key: 'Pre-train + fine-tune paradigm' },
{ name: 'GPT-2', year: '2019', params: '1.5 B', barWidth: '6%', key: 'Zero-shot generalization' },
{ name: 'GPT-3', year: '2020', params: '175 B', barWidth: '45%', key: '⚡ Emergence! In-context learning' },
{ name: 'GPT-4', year: '2023', params: '~1.8 T', barWidth: '100%', key: 'Multimodal + complex reasoning' }
],
// AIErasComparisonDemo
erasComparison: {
header: '🌟 AI Development Stages & Core Paradigms at a Glance',
driverLabel: 'Driver',
mechanismLabel: 'Core Mechanism',
examplesLabel: 'Key Examples',
eras: [
{ name: 'Rule-Based Era', time: '1960s - 1980s', driver: 'Human-coded knowledge', mechanism: 'If-Then logical deduction', examples: ['Dendral', 'Deep Blue'] },
{ name: 'Classical ML', time: '1990s - 2000s', driver: 'Manual feature engineering + statistics', mechanism: 'Finding mathematical decision boundaries', examples: ['SVM', 'Random Forest'] },
{ name: 'Deep Learning Revolution', time: '2010s', driver: 'Big data + GPU compute', mechanism: 'Neural nets auto-extract features', examples: ['AlexNet (CNN)', 'AlphaGo (RL)'] },
{ name: 'Large Language Models', time: '2018 - present', driver: 'Massive unlabeled data + brute-force compute', mechanism: 'Next-token prediction + emergent knowledge', examples: ['GPT-4', 'Claude 3'] },
{ name: 'Agentic AI', time: 'Now - future', driver: 'LLM brain + environment perception', mechanism: 'Autonomous planning + tool use', examples: ['AI Programmer', 'Embodied AI'] }
]
}
}
@@ -0,0 +1,7 @@
import zhCn from './zh-cn.js'
import en from './en.js'
export const aiHistoryLocale = {
'zh-cn': zhCn,
en
}
@@ -0,0 +1,123 @@
// AI 简史 中文语言包
export default {
// AiEvolutionDemo
aiEvolution: {
eras: [
{ label: '理论奠基', years: '1940s-50s' },
{ label: '第一次浪潮', years: '1960s-70s' },
{ label: '❄️ 寒冬 I', years: '1974-80' },
{ label: '第二次浪潮', years: '1980s' },
{ label: '❄️ 寒冬 II', years: '1987-93' },
{ label: 'ML 崛起', years: '1990s-2000s' },
{ label: '深度学习', years: '2010s' },
{ label: '大模型时代', years: '2018+' }
],
legend: {
wave: '技术浪潮',
winter: '❄️ AI 寒冬',
llm: '大模型时代'
}
},
// DiscriminativeVsGenerativeDemo
schools: {
repLabel: '代表',
items: [
{
name: '符号主义',
idea: '智能 = 符号推理 / If-Then 规则',
rep: '专家系统、深蓝',
status: '→ 与连接主义融合(神经符号 AI)'
},
{
name: '连接主义',
idea: '智能 = 神经元网络 + 海量数据',
rep: 'AlphaGo、GPT 系列',
status: '→ 主导大模型时代,当前主流'
},
{
name: '行为主义',
idea: '智能 = 与环境互动 / 强化学习',
rep: 'AlphaGoRL 部分)',
status: '→ 与连接主义融合(深度强化学习)'
}
]
},
// FoundationDemo
foundation: {
label: '符号主义的核心思路 ── 把知识写成规则',
lines: [
{ parts: [{ kw: 'IF' }, { text: ' 体温 > 38.5°C ' }, { kw: 'AND' }, { text: ' 白细胞计数 > 11000' }] },
{ indent: true, parts: [{ kw: 'THEN' }, { text: ' 诊断 = ' }, { str: '"细菌感染"' }] },
{ parts: [{ kw: 'IF' }, { text: ' 诊断 = ' }, { str: '"细菌感染"' }, { text: ' ' }, { kw: 'AND' }, { text: ' 对青霉素不过敏' }] },
{ indent: true, parts: [{ kw: 'THEN' }, { text: ' 治疗方案 = ' }, { str: '"青霉素 400mg / 每日两次"' }] }
],
comment: '// 早期医疗专家系统(MYCIN,1977)就是由 450+ 条这样的规则组成的',
caption: '人类专家把经验翻译成一条条 IF-THEN 规则,机器逐条匹配执行'
},
// PerceptronDemo
perceptron: {
features: ['特征 x₁', '特征 x₂'],
biasLabel: '偏置',
activated: '激活',
silent: '静默',
caption: '① 输入特征\u2003② 乘以权重(重要性)\u2003③ 求和 + 偏置\u2003④ 超过阈值就激活输出 1,否则输出 0'
},
// BackpropagationDemo
backprop: {
steps: [
{ icon: '➡️', name: '前向传播', desc: '数据流过网络,得出预测' },
{ icon: '📐', name: '计算误差', desc: '预测值 vs 正确答案,算 Loss' },
{ icon: '⬅️', name: '反向传播', desc: '逐层追溯每个权重的"责任"' },
{ icon: '⚙️', name: '更新权重', desc: '按责任微调,减少下次误差' }
],
lossLabel: 'Loss(误差)随训练轮次下降:',
axisHigh: '高',
axisLow: '低',
axisEpochs: '训练轮次 (Epochs)'
},
// NeuralNetworkVisualizationDemo
neuralNet: {
layers: [
{ name: '输入层', desc: '原始像素 / 数值信号' },
{ name: '隐藏层(可叠加多层)', desc: '底层识别边缘 → 中层识别形状 → 高层识别语义概念' },
{ name: '输出层', desc: '最终分类或预测结果' }
]
},
// AttentionMechanismDemo
attention: {
colLabel: '处理「{word}」时的注意力分配:',
sentence: ['小明', '把', '苹果', '给了', '他', '的', '母亲'],
focusIdx: 4,
weights: [0.65, 0.05, 0.10, 0.10, 0.05, 0.03, 0.02],
caption: '「他」虽在句中间,模型却把 65% 注意力精准投向句首的「小明」,跨越距离识别代词指代'
},
// GPTEvolutionDemo
gptEvolution: [
{ name: 'GPT-1', year: '2018', params: '1.17 亿', barWidth: '2%', key: '预训练+微调范式确立' },
{ name: 'GPT-2', year: '2019', params: '15 亿', barWidth: '6%', key: 'Zero-shot 零样本泛化' },
{ name: 'GPT-3', year: '2020', params: '1750 亿', barWidth: '45%', key: '⚡ 涌现!上下文学习' },
{ name: 'GPT-4', year: '2023', params: '~1.8 万亿', barWidth: '100%', key: '多模态 + 复杂推理' }
],
// AIErasComparisonDemo
erasComparison: {
header: '🌟 AI 发展阶段与核心范式全景对比',
driverLabel: '驱动方式',
mechanismLabel: '核心机制',
examplesLabel: '典型代表',
eras: [
{ name: '规则系统时代', time: '1960s - 1980s', driver: '人类硬编码知识', mechanism: 'If-Then 逻辑推演', examples: ['Dendral', '深蓝 (Deep Blue)'] },
{ name: '传统机器学习', time: '1990s - 2000s', driver: '人工特征工程 + 统计学', mechanism: '寻找数学决策边界', examples: ['支持向量机 (SVM)', '随机森林'] },
{ name: '深度学习革命', time: '2010s', driver: '大数据 + 算力爬升', mechanism: '神经网络自动提取特征', examples: ['AlexNet (CNN)', 'AlphaGo (RL)'] },
{ name: '大语言模型 (LLM)', time: '2018 - 至今', driver: '海量无标注数据 + 暴力计算', mechanism: '预测下一个词 + 涌现常识', examples: ['GPT-4', 'Claude 3'] },
{ name: '智能体 (Agentic AI)', time: '现在 - 未来', driver: '大模型大脑 + 环境感知', mechanism: '自主规划 + 工具调用', examples: ['AI 程序员', '具身智能'] }
]
}
}