feat: comprehensive documentation and demo updates
- Update READMEs and docs across multiple languages - Enhance interactive demos for Agent, LLM, VLM, Audio, Image Gen, Terminal, and Web Basics - Add new appendix sections for Database and IDE intros - Update VitePress config, theme, and utility scripts - Clean up unused assets and components
This commit is contained in:
@@ -7,7 +7,12 @@
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-steps :active="activeStep" align-center finish-status="success" class="steps">
|
||||
<el-steps
|
||||
:active="activeStep"
|
||||
align-center
|
||||
finish-status="success"
|
||||
class="steps"
|
||||
>
|
||||
<el-step title="音频信号" description="连续波形" />
|
||||
<el-step title="切片 (Chunking)" description="20ms/帧" />
|
||||
<el-step title="量化 (Quantization)" description="查字典" />
|
||||
@@ -18,8 +23,15 @@
|
||||
<!-- Stage 0: Audio -->
|
||||
<div v-if="activeStep === 0" class="stage-content audio-stage">
|
||||
<div class="waveform-viz">
|
||||
<div class="wave-bar" v-for="n in 20" :key="n"
|
||||
:style="{ height: (30 + Math.random() * 50) + '%', animationDelay: n * 0.1 + 's' }"></div>
|
||||
<div
|
||||
class="wave-bar"
|
||||
v-for="n in 20"
|
||||
:key="n"
|
||||
:style="{
|
||||
height: 30 + Math.random() * 50 + '%',
|
||||
animationDelay: n * 0.1 + 's'
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
<div class="stage-desc">原始的连续模拟信号或高采样率数字信号</div>
|
||||
</div>
|
||||
@@ -28,26 +40,41 @@
|
||||
<div v-if="activeStep === 1" class="stage-content chunks-stage">
|
||||
<div class="chunks-container">
|
||||
<div class="chunk-item" v-for="n in 5" :key="n">
|
||||
<span class="chunk-label">Frame {{n}}</span>
|
||||
<span class="chunk-label">Frame {{ n }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stage-desc">将音频切分为固定长度的小片段(例如 20ms)</div>
|
||||
<div class="stage-desc">
|
||||
将音频切分为固定长度的小片段(例如 20ms)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stage 2: Codebook -->
|
||||
<div v-if="activeStep === 2" class="stage-content codebook-stage">
|
||||
<div class="codebook-grid">
|
||||
<div class="codebook-entry" v-for="n in 9" :key="n" :class="{ 'highlight': n === currentMatch }">
|
||||
<div
|
||||
class="codebook-entry"
|
||||
v-for="n in 9"
|
||||
:key="n"
|
||||
:class="{ highlight: n === currentMatch }"
|
||||
>
|
||||
{{ 1024 + n * 50 }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stage-desc">在预训练的"声音字典"中寻找最接近的特征向量</div>
|
||||
<div class="stage-desc">
|
||||
在预训练的"声音字典"中寻找最接近的特征向量
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stage 3: Tokens -->
|
||||
<div v-if="activeStep === 3" class="stage-content token-stage">
|
||||
<div class="token-list">
|
||||
<el-tag v-for="(token, index) in tokens" :key="index" effect="dark" size="large" class="token-tag">
|
||||
<el-tag
|
||||
v-for="(token, index) in tokens"
|
||||
:key="index"
|
||||
effect="dark"
|
||||
size="large"
|
||||
class="token-tag"
|
||||
>
|
||||
{{ token }}
|
||||
</el-tag>
|
||||
</div>
|
||||
@@ -83,7 +110,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
|
||||
<el-alert
|
||||
title="为什么要做 Tokenization?"
|
||||
type="warning"
|
||||
@@ -108,29 +135,29 @@ const playDemo = async () => {
|
||||
if (isPlaying.value) return
|
||||
isPlaying.value = true
|
||||
activeStep.value = 0
|
||||
|
||||
|
||||
// Step 0 -> 1
|
||||
await wait(1000)
|
||||
activeStep.value = 1
|
||||
|
||||
|
||||
// Step 1 -> 2
|
||||
await wait(1500)
|
||||
activeStep.value = 2
|
||||
|
||||
|
||||
// Simulate codebook matching
|
||||
for (let i = 0; i < 5; i++) {
|
||||
currentMatch.value = Math.floor(Math.random() * 9) + 1
|
||||
await wait(200)
|
||||
}
|
||||
currentMatch.value = 0
|
||||
|
||||
|
||||
// Step 2 -> 3
|
||||
activeStep.value = 3
|
||||
|
||||
|
||||
isPlaying.value = false
|
||||
}
|
||||
|
||||
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms))
|
||||
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -186,8 +213,15 @@ const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
@keyframes wave {
|
||||
0%, 100% { height: 30%; opacity: 0.5; }
|
||||
50% { height: 100%; opacity: 1; }
|
||||
0%,
|
||||
100% {
|
||||
height: 30%;
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
height: 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chunks Stage */
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
<div class="step-box">
|
||||
<div class="label">🔢 数字化</div>
|
||||
<div class="digital-visual">
|
||||
<div v-for="n in 8" :key="n" class="bit">{{ Math.floor(Math.random() * 2) }}</div>
|
||||
<div v-for="n in 8" :key="n" class="bit">
|
||||
{{ Math.floor(Math.random() * 2) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc">PCM 数据</div>
|
||||
</div>
|
||||
@@ -43,8 +45,9 @@
|
||||
<div class="explanation">
|
||||
<p>
|
||||
<span class="icon">💡</span>
|
||||
计算机无法直接处理连续的声波,需要把它转换成数字。
|
||||
这个过程叫<strong>模数转换 (ADC)</strong>:每隔一小段时间测量一次声音的强度,记录成数字。
|
||||
计算机无法直接处理连续的声波,需要把它转换成数字。 这个过程叫<strong
|
||||
>模数转换 (ADC)</strong
|
||||
>:每隔一小段时间测量一次声音的强度,记录成数字。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
<div class="ar-comparison">
|
||||
<el-card shadow="never">
|
||||
<div class="controls">
|
||||
<el-button type="primary" @click="playDemo" :loading="isPlaying" icon="VideoPlay">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="playDemo"
|
||||
:loading="isPlaying"
|
||||
icon="VideoPlay"
|
||||
>
|
||||
开始对比演示
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -20,10 +25,10 @@
|
||||
<div class="visual-area">
|
||||
<div class="token-stream">
|
||||
<transition-group name="list">
|
||||
<el-tag
|
||||
v-for="(token, i) in displayedArTokens"
|
||||
:key="i"
|
||||
type="danger"
|
||||
<el-tag
|
||||
v-for="(token, i) in displayedArTokens"
|
||||
:key="i"
|
||||
type="danger"
|
||||
class="token-item"
|
||||
effect="plain"
|
||||
>
|
||||
@@ -34,7 +39,9 @@
|
||||
</div>
|
||||
<div class="stats">
|
||||
<el-descriptions :column="1" size="small" border>
|
||||
<el-descriptions-item label="生成方式">串行 (Serial)</el-descriptions-item>
|
||||
<el-descriptions-item label="生成方式"
|
||||
>串行 (Serial)</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="速度">
|
||||
<el-tag type="danger" size="small">慢 (Slow)</el-tag>
|
||||
</el-descriptions-item>
|
||||
@@ -54,17 +61,29 @@
|
||||
<div class="method-body">
|
||||
<div class="visual-area">
|
||||
<div class="flow-field" :style="{ opacity: flowProgress }">
|
||||
<div v-for="n in 20" :key="n" class="flow-bar"
|
||||
:style="{ height: flowProgress * (30 + Math.random() * 70) + '%', transitionDelay: n * 0.02 + 's' }"></div>
|
||||
<div
|
||||
v-for="n in 20"
|
||||
:key="n"
|
||||
class="flow-bar"
|
||||
:style="{
|
||||
height: flowProgress * (30 + Math.random() * 70) + '%',
|
||||
transitionDelay: n * 0.02 + 's'
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
<div class="flow-overlay" v-if="flowProgress < 1 && flowProgress > 0">
|
||||
<div
|
||||
class="flow-overlay"
|
||||
v-if="flowProgress < 1 && flowProgress > 0"
|
||||
>
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
<span>Denoising...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats">
|
||||
<el-descriptions :column="1" size="small" border>
|
||||
<el-descriptions-item label="生成方式">并行 (Parallel)</el-descriptions-item>
|
||||
<el-descriptions-item label="生成方式"
|
||||
>并行 (Parallel)</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="速度">
|
||||
<el-tag type="success" size="small">极快 (Fast)</el-tag>
|
||||
</el-descriptions-item>
|
||||
@@ -76,17 +95,14 @@
|
||||
|
||||
<el-divider />
|
||||
|
||||
<el-alert
|
||||
title="技术演进"
|
||||
type="success"
|
||||
:closable="false"
|
||||
show-icon
|
||||
>
|
||||
<el-alert title="技术演进" type="success" :closable="false" show-icon>
|
||||
<template #default>
|
||||
<p>
|
||||
<strong>自回归</strong> (如 VALL-E) 像人说话一样,必须说完上一个字才能说下一个字,所以很慢。
|
||||
<br>
|
||||
<strong>流匹配</strong> (如 F5-TTS) 像画画一样,可以同时在画布的所有角落开始上色,效率提升了 10-20 倍。
|
||||
<strong>自回归</strong> (如 VALL-E)
|
||||
像人说话一样,必须说完上一个字才能说下一个字,所以很慢。
|
||||
<br />
|
||||
<strong>流匹配</strong> (如 F5-TTS)
|
||||
像画画一样,可以同时在画布的所有角落开始上色,效率提升了 10-20 倍。
|
||||
</p>
|
||||
</template>
|
||||
</el-alert>
|
||||
@@ -108,9 +124,9 @@ const playDemo = async () => {
|
||||
isPlaying.value = true
|
||||
displayedArTokens.value = []
|
||||
flowProgress.value = 0
|
||||
|
||||
|
||||
// Start Flow Matching (Fast)
|
||||
const flowPromise = new Promise(resolve => {
|
||||
const flowPromise = new Promise((resolve) => {
|
||||
let p = 0
|
||||
const interval = setInterval(() => {
|
||||
p += 0.05
|
||||
@@ -121,16 +137,16 @@ const playDemo = async () => {
|
||||
}
|
||||
}, 50) // Total ~1s
|
||||
})
|
||||
|
||||
|
||||
// Start AR (Slow)
|
||||
const arPromise = new Promise(async resolve => {
|
||||
const arPromise = new Promise(async (resolve) => {
|
||||
for (const token of arTokensSource) {
|
||||
await new Promise(r => setTimeout(r, 400)) // 400ms per token
|
||||
await new Promise((r) => setTimeout(r, 400)) // 400ms per token
|
||||
displayedArTokens.value.push(token)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
|
||||
|
||||
await Promise.all([flowPromise, arPromise])
|
||||
isPlaying.value = false
|
||||
}
|
||||
@@ -220,7 +236,7 @@ const playDemo = async () => {
|
||||
|
||||
.flow-bar {
|
||||
flex: 1;
|
||||
background: linear-gradient(to top, #67C23A, #95d475);
|
||||
background: linear-gradient(to top, #67c23a, #95d475);
|
||||
border-radius: 2px 2px 0 0;
|
||||
transition: height 0.5s ease;
|
||||
}
|
||||
@@ -231,7 +247,7 @@ const playDemo = async () => {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255,255,255,0.5);
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -10,8 +10,15 @@
|
||||
</div>
|
||||
<div class="viz-content waveform-container">
|
||||
<div class="wave-bars">
|
||||
<div v-for="n in 30" :key="n" class="wave-bar"
|
||||
:style="{ height: 20 + Math.random() * 60 + '%', animationDelay: n * 0.05 + 's' }"></div>
|
||||
<div
|
||||
v-for="n in 30"
|
||||
:key="n"
|
||||
class="wave-bar"
|
||||
:style="{
|
||||
height: 20 + Math.random() * 60 + '%',
|
||||
animationDelay: n * 0.05 + 's'
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
<div class="axis-label x-axis">时间 (Time) →</div>
|
||||
<div class="axis-label y-axis">振幅 (Amplitude) ↑</div>
|
||||
@@ -50,13 +57,18 @@
|
||||
<template #default>
|
||||
<div class="legend">
|
||||
<div class="legend-item">
|
||||
<div class="color-box low"></div> 低能量 (安静)
|
||||
<div class="color-box low"></div>
|
||||
低能量 (安静)
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="color-box high"></div> 高能量 (响亮)
|
||||
<div class="color-box high"></div>
|
||||
高能量 (响亮)
|
||||
</div>
|
||||
</div>
|
||||
<p>频谱图将一维的声音信号变成了二维图像,这样我们就可以用 <strong>CNN (卷积神经网络)</strong> 等图像模型来处理声音了!</p>
|
||||
<p>
|
||||
频谱图将一维的声音信号变成了二维图像,这样我们就可以用
|
||||
<strong>CNN (卷积神经网络)</strong> 等图像模型来处理声音了!
|
||||
</p>
|
||||
</template>
|
||||
</el-alert>
|
||||
</el-card>
|
||||
@@ -90,10 +102,10 @@ const drawSpectrogram = () => {
|
||||
const baseEnergy = normalizedY * 0.8
|
||||
const noise = Math.random() * 0.2
|
||||
const timeVar = Math.sin(x * 0.1) * 0.2 // Time variation
|
||||
|
||||
|
||||
let intensity = baseEnergy + noise + timeVar
|
||||
intensity = Math.max(0, Math.min(1, intensity))
|
||||
|
||||
|
||||
const hue = 240 - intensity * 240 // Blue (low) to Red (high)
|
||||
ctx.fillStyle = `hsl(${hue}, 80%, 50%)`
|
||||
ctx.fillRect(x, height - y - 4, 4, 4)
|
||||
@@ -165,8 +177,15 @@ const drawSpectrogram = () => {
|
||||
}
|
||||
|
||||
@keyframes wave {
|
||||
0%, 100% { height: 20%; opacity: 0.6; }
|
||||
50% { height: 90%; opacity: 1; }
|
||||
0%,
|
||||
100% {
|
||||
height: 20%;
|
||||
opacity: 0.6;
|
||||
}
|
||||
50% {
|
||||
height: 90%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.transform-arrow {
|
||||
|
||||
Reference in New Issue
Block a user