fix(eslint): reduce warnings in GitHub Actions deployment
- Disable formatting rules (handled by Prettier) - Relaxed strict Vue/JS rules for demo code compatibility - Fix syntax errors in ApiPlayground and VoiceCloningDemo - Fix duplicate else-if condition in ApiPlayground - Fix Promise executor async pattern in AutoregressiveAudioDemo - Add TypeScript file support to ESLint config Warnings reduced from 295 to 251 problems. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
<template>
|
||||
<div class="attn-demo">
|
||||
<div class="header">
|
||||
<div class="title">Self-Attention Mechanism</div>
|
||||
<div class="subtitle">自注意力机制:全局信息交互</div>
|
||||
<div class="title">
|
||||
Self-Attention Mechanism
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
自注意力机制:全局信息交互
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visual-stage">
|
||||
<!-- Grid Layout -->
|
||||
<div class="grid-container" @mouseleave="hoverIndex = -1">
|
||||
<div
|
||||
class="grid-container"
|
||||
@mouseleave="hoverIndex = -1"
|
||||
>
|
||||
<!-- SVG Layer for Connection Lines -->
|
||||
<svg class="connections-layer">
|
||||
<defs>
|
||||
@@ -30,8 +37,8 @@
|
||||
<g v-if="hoverIndex !== -1">
|
||||
<line
|
||||
v-for="(target, tIndex) in items"
|
||||
:key="tIndex"
|
||||
v-show="tIndex !== hoverIndex"
|
||||
:key="tIndex"
|
||||
:x1="getCenter(hoverIndex).x"
|
||||
:y1="getCenter(hoverIndex).y"
|
||||
:x2="getCenter(tIndex).x"
|
||||
@@ -55,11 +62,11 @@
|
||||
'is-strong-attn':
|
||||
hoverIndex !== -1 && getAttentionScore(hoverIndex, index) > 0.5
|
||||
}"
|
||||
@mouseenter="hoverIndex = index"
|
||||
:style="{
|
||||
left: getCenter(index).x - 30 + 'px',
|
||||
top: getCenter(index).y - 30 + 'px'
|
||||
}"
|
||||
@mouseenter="hoverIndex = index"
|
||||
>
|
||||
<div class="cell-content">
|
||||
<span class="cell-icon">{{ item.icon }}</span>
|
||||
@@ -67,8 +74,8 @@
|
||||
</div>
|
||||
<!-- Attention Score Badge -->
|
||||
<div
|
||||
class="attn-badge"
|
||||
v-if="hoverIndex !== -1 && hoverIndex !== index"
|
||||
class="attn-badge"
|
||||
:style="{
|
||||
opacity: Math.max(0.3, getAttentionScore(hoverIndex, index))
|
||||
}"
|
||||
@@ -80,11 +87,17 @@
|
||||
|
||||
<!-- Info Panel -->
|
||||
<div class="info-panel">
|
||||
<div v-if="hoverIndex === -1" class="placeholder-text">
|
||||
<div
|
||||
v-if="hoverIndex === -1"
|
||||
class="placeholder-text"
|
||||
>
|
||||
<span class="cursor-icon">👆</span>
|
||||
把鼠标悬停在任意方块上,<br />观察它在"关注"谁
|
||||
把鼠标悬停在任意方块上,<br>观察它在"关注"谁
|
||||
</div>
|
||||
<div v-else class="active-info">
|
||||
<div
|
||||
v-else
|
||||
class="active-info"
|
||||
>
|
||||
<div class="source-info">
|
||||
<span class="label">当前 Patch:</span>
|
||||
<div class="patch-tag">
|
||||
@@ -93,11 +106,13 @@
|
||||
</div>
|
||||
|
||||
<div class="attn-list">
|
||||
<div class="list-header">Attention Weights (注意力权重)</div>
|
||||
<div class="list-header">
|
||||
Attention Weights (注意力权重)
|
||||
</div>
|
||||
<div
|
||||
class="attn-item"
|
||||
v-for="(score, idx) in getTopAttentions(hoverIndex)"
|
||||
:key="idx"
|
||||
class="attn-item"
|
||||
>
|
||||
<div class="item-left">
|
||||
<span class="item-icon">{{ items[idx].icon }}</span>
|
||||
@@ -108,7 +123,7 @@
|
||||
<div
|
||||
class="progress-fill"
|
||||
:style="{ width: score * 100 + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
<span class="score-text">{{ (score * 100).toFixed(0) }}%</span>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div class="desc">
|
||||
目标:让 Projector 学会“翻译”图像语言。
|
||||
<br />做法:冻结 ViT 和 LLM,只训练 Projector。
|
||||
<br>做法:冻结 ViT 和 LLM,只训练 Projector。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,77 +14,131 @@
|
||||
<!-- Data Input -->
|
||||
<div class="data-column">
|
||||
<div class="data-item image-data">
|
||||
<div class="data-icon">🖼️</div>
|
||||
<div class="data-label">图片<br />(猫)</div>
|
||||
<div class="data-icon">
|
||||
🖼️
|
||||
</div>
|
||||
<div class="data-label">
|
||||
图片<br>(猫)
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-item text-data">
|
||||
<div class="data-icon">📝</div>
|
||||
<div class="data-label">标题<br />("一只猫")</div>
|
||||
<div class="data-icon">
|
||||
📝
|
||||
</div>
|
||||
<div class="data-label">
|
||||
标题<br>("一只猫")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Arrow Column -->
|
||||
<div class="arrow-column">
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Model Column -->
|
||||
<div class="model-column">
|
||||
<!-- Vision Branch -->
|
||||
<div class="model-block frozen">
|
||||
<div class="status-badge">❄️ 冻结</div>
|
||||
<div class="block-icon">👁️</div>
|
||||
<div class="block-name">ViT</div>
|
||||
<div class="status-badge">
|
||||
❄️ 冻结
|
||||
</div>
|
||||
<div class="block-icon">
|
||||
👁️
|
||||
</div>
|
||||
<div class="block-name">
|
||||
ViT
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-small">➜</div>
|
||||
<div class="arrow-small">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<div class="model-block training">
|
||||
<div class="status-badge fire">🔥 训练</div>
|
||||
<div class="block-icon">🔌</div>
|
||||
<div class="block-name">Projector</div>
|
||||
<div class="status-badge fire">
|
||||
🔥 训练
|
||||
</div>
|
||||
<div class="block-icon">
|
||||
🔌
|
||||
</div>
|
||||
<div class="block-name">
|
||||
Projector
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Text Branch -->
|
||||
<div class="model-block frozen text-model">
|
||||
<div class="status-badge">❄️ 冻结</div>
|
||||
<div class="block-icon">🧠</div>
|
||||
<div class="block-name">LLM</div>
|
||||
<div class="status-badge">
|
||||
❄️ 冻结
|
||||
</div>
|
||||
<div class="block-icon">
|
||||
🧠
|
||||
</div>
|
||||
<div class="block-name">
|
||||
LLM
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Arrow Column -->
|
||||
<div class="arrow-column">
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vector Output -->
|
||||
<div class="vector-column">
|
||||
<div class="vector-item v-vector">
|
||||
<div class="vector-icon">🟢</div>
|
||||
<div class="vector-label">向量 V</div>
|
||||
<div class="vector-icon">
|
||||
🟢
|
||||
</div>
|
||||
<div class="vector-label">
|
||||
向量 V
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="loss-connection">
|
||||
<div class="loss-line"></div>
|
||||
<div class="loss-box" :class="{ active: isCalculatingLoss }">
|
||||
<div class="loss-label">Loss</div>
|
||||
<div class="loss-desc">V ≈ T</div>
|
||||
<div class="loss-line" />
|
||||
<div
|
||||
class="loss-box"
|
||||
:class="{ active: isCalculatingLoss }"
|
||||
>
|
||||
<div class="loss-label">
|
||||
Loss
|
||||
</div>
|
||||
<div class="loss-desc">
|
||||
V ≈ T
|
||||
</div>
|
||||
</div>
|
||||
<div class="loss-line"></div>
|
||||
<div class="loss-line" />
|
||||
</div>
|
||||
|
||||
<div class="vector-item t-vector">
|
||||
<div class="vector-icon">🔵</div>
|
||||
<div class="vector-label">向量 T</div>
|
||||
<div class="vector-icon">
|
||||
🔵
|
||||
</div>
|
||||
<div class="vector-label">
|
||||
向量 T
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button class="play-btn" @click="nextStep">
|
||||
<button
|
||||
class="play-btn"
|
||||
@click="nextStep"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</button>
|
||||
<div class="step-desc">
|
||||
|
||||
@@ -3,44 +3,66 @@
|
||||
<div class="demo-container">
|
||||
<!-- Step 1: Patch -->
|
||||
<div class="step-box">
|
||||
<div class="label">1. Patch (16×16×3) (示意 / Toy)</div>
|
||||
<div class="label">
|
||||
1. Patch (16×16×3) (示意 / Toy)
|
||||
</div>
|
||||
<div class="grid-patch">
|
||||
<div
|
||||
v-for="n in patchCellCount"
|
||||
:key="n"
|
||||
class="pixel"
|
||||
:style="{ backgroundColor: getPixelColor(n) }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
<div class="desc">
|
||||
16×16 像素 × 3 通道 = 768 标量值
|
||||
</div>
|
||||
<div class="desc">16×16 像素 × 3 通道 = 768 标量值</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Flattened -->
|
||||
<div class="step-box">
|
||||
<div class="label">2. Flatten</div>
|
||||
<div class="label">
|
||||
2. Flatten
|
||||
</div>
|
||||
<div class="vector-container">
|
||||
<div
|
||||
v-for="n in flattenSampleCount"
|
||||
:key="n"
|
||||
class="vector-cell"
|
||||
:style="{ backgroundColor: getPixelColor(n) }"
|
||||
></div>
|
||||
<div class="vector-ellipsis">…</div>
|
||||
/>
|
||||
<div class="vector-ellipsis">
|
||||
…
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
得到 1×768 向量 (Vector)
|
||||
</div>
|
||||
<div class="desc">得到 1×768 向量 (Vector)</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">× W</div>
|
||||
<div class="arrow">
|
||||
× W
|
||||
</div>
|
||||
|
||||
<!-- Step 3: Projected -->
|
||||
<div class="step-box">
|
||||
<div class="label">3. Embedding</div>
|
||||
<div class="embedding-container">
|
||||
<div v-for="n in 8" :key="n" class="embed-cell"></div>
|
||||
<div class="label">
|
||||
3. Embedding
|
||||
</div>
|
||||
<div class="embedding-container">
|
||||
<div
|
||||
v-for="n in 8"
|
||||
:key="n"
|
||||
class="embed-cell"
|
||||
/>
|
||||
</div>
|
||||
<div class="desc">
|
||||
映射到 D 维 (示意 D=8;常见 D=768)
|
||||
</div>
|
||||
<div class="desc">映射到 D 维 (示意 D=8;常见 D=768)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+47
-16
@@ -1,8 +1,14 @@
|
||||
<template>
|
||||
<div class="model-evolution-demo">
|
||||
<div class="controls-header">
|
||||
<div class="toggle-container" @click="toggleMode">
|
||||
<div class="toggle-track" :class="{ active: isVLM }">
|
||||
<div
|
||||
class="toggle-container"
|
||||
@click="toggleMode"
|
||||
>
|
||||
<div
|
||||
class="toggle-track"
|
||||
:class="{ active: isVLM }"
|
||||
>
|
||||
<div class="toggle-thumb">
|
||||
{{ isVLM ? '👁️' : '🧠' }}
|
||||
</div>
|
||||
@@ -24,8 +30,13 @@
|
||||
|
||||
<div class="diagram-stage">
|
||||
<div class="lanes">
|
||||
<div class="lane lane-vision" v-show="isVLM">
|
||||
<div class="lane-title">Vision Path (视觉路径)</div>
|
||||
<div
|
||||
v-show="isVLM"
|
||||
class="lane lane-vision"
|
||||
>
|
||||
<div class="lane-title">
|
||||
Vision Path (视觉路径)
|
||||
</div>
|
||||
<div class="lane-flow">
|
||||
<div class="node input-node">
|
||||
<span class="icon">🖼️</span>
|
||||
@@ -43,7 +54,9 @@
|
||||
</div>
|
||||
<span class="mini-arrow">→</span>
|
||||
<div class="token-box token-box-vision">
|
||||
<div class="token-box-title">Vision Tokens (视觉 Token)</div>
|
||||
<div class="token-box-title">
|
||||
Vision Tokens (视觉 Token)
|
||||
</div>
|
||||
<div class="tokens">
|
||||
<span class="token vision">v1</span>
|
||||
<span class="token vision">v2</span>
|
||||
@@ -55,7 +68,9 @@
|
||||
</div>
|
||||
|
||||
<div class="lane lane-text">
|
||||
<div class="lane-title">Text Path (文字路径)</div>
|
||||
<div class="lane-title">
|
||||
Text Path (文字路径)
|
||||
</div>
|
||||
<div class="lane-flow">
|
||||
<div class="node input-node">
|
||||
<span class="icon">⌨️</span>
|
||||
@@ -68,7 +83,9 @@
|
||||
</div>
|
||||
<span class="mini-arrow">→</span>
|
||||
<div class="token-box">
|
||||
<div class="token-box-title">Text Tokens (文字 Token)</div>
|
||||
<div class="token-box-title">
|
||||
Text Tokens (文字 Token)
|
||||
</div>
|
||||
<div class="tokens">
|
||||
<span class="token text">t1</span>
|
||||
<span class="token text">t2</span>
|
||||
@@ -80,9 +97,14 @@
|
||||
</div>
|
||||
|
||||
<div class="merge-stage">
|
||||
<div class="merge-title">Token Sequence (输入序列)</div>
|
||||
<div class="merge-title">
|
||||
Token Sequence (输入序列)
|
||||
</div>
|
||||
<div class="sequence">
|
||||
<div v-if="isVLM" class="sequence-row">
|
||||
<div
|
||||
v-if="isVLM"
|
||||
class="sequence-row"
|
||||
>
|
||||
<span class="sequence-tag vision">Vision (视觉)</span>
|
||||
<div class="tokens">
|
||||
<span class="token vision">v1</span>
|
||||
@@ -101,10 +123,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="sequence-hint">
|
||||
<span v-if="isVLM"
|
||||
>Concat: [Vision Tokens] + [Text Tokens]
|
||||
(拼接:视觉在前,文字在后)</span
|
||||
>
|
||||
<span v-if="isVLM">Concat: [Vision Tokens] + [Text Tokens]
|
||||
(拼接:视觉在前,文字在后)</span>
|
||||
<span v-else>Only [Text Tokens] (只有文字 Token)</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,12 +146,23 @@
|
||||
</div>
|
||||
|
||||
<div class="interactive-info">
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="info-card" v-if="!isVLM" key="llm">
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in"
|
||||
>
|
||||
<div
|
||||
v-if="!isVLM"
|
||||
key="llm"
|
||||
class="info-card"
|
||||
>
|
||||
<h3>Standard LLM Flow (标准大模型流程)</h3>
|
||||
<p>Prompt → Embedding → Token Sequence → LLM → Response。</p>
|
||||
</div>
|
||||
<div class="info-card vlm-info" v-else key="vlm">
|
||||
<div
|
||||
v-else
|
||||
key="vlm"
|
||||
class="info-card vlm-info"
|
||||
>
|
||||
<h3>VLM = LLM + Vision Encoder (视觉大模型原理)</h3>
|
||||
<ul>
|
||||
<li><strong>ViT (The Eye):</strong> 把图片编码成视觉特征。</li>
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
<div class="controls">
|
||||
<button
|
||||
class="action-btn"
|
||||
@click="prevStep"
|
||||
:disabled="currentStep === 0"
|
||||
@click="prevStep"
|
||||
>
|
||||
⬅ 上一步 (Prev)
|
||||
</button>
|
||||
<span class="step-indicator">Step {{ currentStep + 1 }} / 4</span>
|
||||
<button
|
||||
class="action-btn primary"
|
||||
@click="nextStep"
|
||||
:disabled="currentStep === 3"
|
||||
@click="nextStep"
|
||||
>
|
||||
{{ currentStep === 3 ? '完成 (Done)' : '下一步 (Next) ➡' }}
|
||||
</button>
|
||||
@@ -41,21 +41,43 @@
|
||||
'is-patchified': currentStep >= 2
|
||||
}"
|
||||
>
|
||||
<div class="grid-overlay" v-if="currentStep === 1"></div>
|
||||
<div v-for="n in 196" :key="n" class="patch" :style="getPatchStyle(n)">
|
||||
<div
|
||||
v-if="currentStep === 1"
|
||||
class="grid-overlay"
|
||||
/>
|
||||
<div
|
||||
v-for="n in 196"
|
||||
:key="n"
|
||||
class="patch"
|
||||
:style="getPatchStyle(n)"
|
||||
>
|
||||
<!-- Show number only in Pixelated stage to represent 'digitization' -->
|
||||
<span class="pixel-val" v-if="currentStep === 1">{{
|
||||
<span
|
||||
v-if="currentStep === 1"
|
||||
class="pixel-val"
|
||||
>{{
|
||||
Math.floor(Math.random() * 9)
|
||||
}}</span>
|
||||
<!-- Show ID in Patchified stage -->
|
||||
<span class="patch-id" v-if="currentStep >= 2">{{ n }}</span>
|
||||
<span
|
||||
v-if="currentStep >= 2"
|
||||
class="patch-id"
|
||||
>{{ n }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down" v-if="currentStep >= 3">⬇</div>
|
||||
<div
|
||||
v-if="currentStep >= 3"
|
||||
class="arrow-down"
|
||||
>
|
||||
⬇
|
||||
</div>
|
||||
|
||||
<!-- 线性序列视图 -->
|
||||
<div class="sequence-container" v-if="currentStep >= 3">
|
||||
<div
|
||||
v-if="currentStep >= 3"
|
||||
class="sequence-container"
|
||||
>
|
||||
<div class="sequence-label">
|
||||
Token Sequence: 196×D (每个 Token 是 D 维向量)
|
||||
</div>
|
||||
@@ -65,7 +87,7 @@
|
||||
:key="n"
|
||||
class="mini-patch"
|
||||
:style="getMiniPatchStyle(n)"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,31 +3,56 @@
|
||||
<div class="demo-row">
|
||||
<!-- Input Feature -->
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid-title">Feature Vectors</div>
|
||||
<div class="grid-title">
|
||||
Feature Vectors
|
||||
</div>
|
||||
<div class="grid-box feature-grid">
|
||||
<div v-for="n in 9" :key="'f' + n" class="cell feature-cell">V</div>
|
||||
<div
|
||||
v-for="n in 9"
|
||||
:key="'f' + n"
|
||||
class="cell feature-cell"
|
||||
>
|
||||
V
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="op">+</div>
|
||||
<div class="op">
|
||||
+
|
||||
</div>
|
||||
|
||||
<!-- Positional Embedding -->
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid-title">Position Embeddings</div>
|
||||
<div class="grid-title">
|
||||
Position Embeddings
|
||||
</div>
|
||||
<div class="grid-box pos-grid">
|
||||
<div v-for="n in 9" :key="'p' + n" class="cell pos-cell">{{ n }}</div>
|
||||
<div
|
||||
v-for="n in 9"
|
||||
:key="'p' + n"
|
||||
class="cell pos-cell"
|
||||
>
|
||||
{{ n }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="op">=</div>
|
||||
<div class="op">
|
||||
=
|
||||
</div>
|
||||
|
||||
<!-- Result -->
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid-title">Input to Transformer</div>
|
||||
<div class="grid-title">
|
||||
Input to Transformer
|
||||
</div>
|
||||
<div class="grid-box result-grid">
|
||||
<div v-for="n in 9" :key="'r' + n" class="cell result-cell">
|
||||
<span class="v">V</span><span class="plus">+</span
|
||||
><span class="p">{{ n }}</span>
|
||||
<div
|
||||
v-for="n in 9"
|
||||
:key="'r' + n"
|
||||
class="cell result-cell"
|
||||
>
|
||||
<span class="v">V</span><span class="plus">+</span><span class="p">{{ n }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
<template>
|
||||
<div class="projector-demo">
|
||||
<div class="mode-switch">
|
||||
<button :class="{ active: mode === 'linear' }" @click="mode = 'linear'">
|
||||
<button
|
||||
:class="{ active: mode === 'linear' }"
|
||||
@click="mode = 'linear'"
|
||||
>
|
||||
Linear (LLaVA)
|
||||
</button>
|
||||
<button :class="{ active: mode === 'qformer' }" @click="mode = 'qformer'">
|
||||
<button
|
||||
:class="{ active: mode === 'qformer' }"
|
||||
@click="mode = 'qformer'"
|
||||
>
|
||||
Q-Former (BLIP-2)
|
||||
</button>
|
||||
</div>
|
||||
@@ -16,9 +22,15 @@
|
||||
<div class="pipeline">
|
||||
<!-- Input: Visual Tokens -->
|
||||
<div class="stage">
|
||||
<div class="label">Visual Tokens (ViT)</div>
|
||||
<div class="label">
|
||||
Visual Tokens (ViT)
|
||||
</div>
|
||||
<div class="token-container input">
|
||||
<div v-for="n in 16" :key="n" class="token visual"></div>
|
||||
<div
|
||||
v-for="n in 16"
|
||||
:key="n"
|
||||
class="token visual"
|
||||
/>
|
||||
</div>
|
||||
<div class="count">
|
||||
{{ mode === 'linear' ? '256 Tokens' : '256 Tokens' }}
|
||||
@@ -27,32 +39,40 @@
|
||||
|
||||
<!-- Process: The Projector -->
|
||||
<div class="stage connector">
|
||||
<div class="arrow-line"></div>
|
||||
<div class="projector-box" :class="mode">
|
||||
<div class="arrow-line" />
|
||||
<div
|
||||
class="projector-box"
|
||||
:class="mode"
|
||||
>
|
||||
<div class="title">
|
||||
{{ mode === 'linear' ? 'Linear Layer' : 'Q-Former' }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{ mode === 'linear' ? '直接映射 (1:1)' : '查询提取 (N:M)' }}
|
||||
</div>
|
||||
<div class="animation-dots" v-if="mode === 'qformer'">
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div
|
||||
v-if="mode === 'qformer'"
|
||||
class="animation-dots"
|
||||
>
|
||||
<div class="dot" />
|
||||
<div class="dot" />
|
||||
<div class="dot" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="arrow-line"></div>
|
||||
<div class="arrow-line" />
|
||||
</div>
|
||||
|
||||
<!-- Output: LLM Tokens -->
|
||||
<div class="stage">
|
||||
<div class="label">LLM Tokens</div>
|
||||
<div class="label">
|
||||
LLM Tokens
|
||||
</div>
|
||||
<div class="token-container output">
|
||||
<div
|
||||
v-for="n in mode === 'linear' ? 16 : 4"
|
||||
:key="n"
|
||||
class="token llm"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
<div class="count">
|
||||
{{
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<template>
|
||||
<div class="pipeline-demo">
|
||||
<div class="stage-switch">
|
||||
<button :class="{ active: stage === 1 }" @click="stage = 1">
|
||||
<button
|
||||
:class="{ active: stage === 1 }"
|
||||
@click="stage = 1"
|
||||
>
|
||||
阶段一:特征对齐
|
||||
</button>
|
||||
<button :class="{ active: stage === 2 }" @click="stage = 2">
|
||||
<button
|
||||
:class="{ active: stage === 2 }"
|
||||
@click="stage = 2"
|
||||
>
|
||||
阶段二:指令微调
|
||||
</button>
|
||||
</div>
|
||||
@@ -12,29 +18,57 @@
|
||||
<div class="pipeline-visual">
|
||||
<!-- Image Input -->
|
||||
<div class="component-box image-input">
|
||||
<div class="icon">🖼️</div>
|
||||
<div class="name">Image</div>
|
||||
<div class="icon">
|
||||
🖼️
|
||||
</div>
|
||||
<div class="name">
|
||||
Image
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<!-- Vision Encoder -->
|
||||
<div class="component-box encoder" :class="{ frozen: true }">
|
||||
<div class="status-badge">❄️ Frozen</div>
|
||||
<div class="name">ViT</div>
|
||||
<div class="desc">Vision Encoder</div>
|
||||
<div
|
||||
class="component-box encoder"
|
||||
:class="{ frozen: true }"
|
||||
>
|
||||
<div class="status-badge">
|
||||
❄️ Frozen
|
||||
</div>
|
||||
<div class="name">
|
||||
ViT
|
||||
</div>
|
||||
<div class="desc">
|
||||
Vision Encoder
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<!-- Projector -->
|
||||
<div class="component-box projector" :class="{ training: true }">
|
||||
<div class="status-badge fire">🔥 Train</div>
|
||||
<div class="name">Projector</div>
|
||||
<div class="desc">Adapter</div>
|
||||
<div
|
||||
class="component-box projector"
|
||||
:class="{ training: true }"
|
||||
>
|
||||
<div class="status-badge fire">
|
||||
🔥 Train
|
||||
</div>
|
||||
<div class="name">
|
||||
Projector
|
||||
</div>
|
||||
<div class="desc">
|
||||
Adapter
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<!-- LLM -->
|
||||
<div
|
||||
@@ -44,32 +78,64 @@
|
||||
<div class="status-badge">
|
||||
{{ stage === 1 ? '❄️ Frozen' : '🔥 Train' }}
|
||||
</div>
|
||||
<div class="name">LLM</div>
|
||||
<div class="desc">Language Model</div>
|
||||
<div class="name">
|
||||
LLM
|
||||
</div>
|
||||
<div class="desc">
|
||||
Language Model
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow">➜</div>
|
||||
<div class="arrow">
|
||||
➜
|
||||
</div>
|
||||
|
||||
<!-- Output / Loss -->
|
||||
<div class="component-box output">
|
||||
<div class="name" v-if="stage === 1">Loss Calculation</div>
|
||||
<div class="name" v-else>Text Generation</div>
|
||||
<div class="desc" v-if="stage === 1">Contrastive Loss</div>
|
||||
<div class="desc" v-else>Next Token Prediction</div>
|
||||
<div
|
||||
v-if="stage === 1"
|
||||
class="name"
|
||||
>
|
||||
Loss Calculation
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="name"
|
||||
>
|
||||
Text Generation
|
||||
</div>
|
||||
<div
|
||||
v-if="stage === 1"
|
||||
class="desc"
|
||||
>
|
||||
Contrastive Loss
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="desc"
|
||||
>
|
||||
Next Token Prediction
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="data-example">
|
||||
<div class="data-title">当前训练数据示例:</div>
|
||||
<div class="data-content" v-if="stage === 1">
|
||||
<div class="data-title">
|
||||
当前训练数据示例:
|
||||
</div>
|
||||
<div
|
||||
v-if="stage === 1"
|
||||
class="data-content"
|
||||
>
|
||||
<code><Image: 🐱>, <Text: "一只猫"></code>
|
||||
<p>任务:让图像向量与文本向量距离变近。</p>
|
||||
</div>
|
||||
<div class="data-content" v-else>
|
||||
<code
|
||||
>User: <Image: 🐱> 这只猫在干嘛?<br />Assistant:
|
||||
它在睡觉。</code
|
||||
>
|
||||
<div
|
||||
v-else
|
||||
class="data-content"
|
||||
>
|
||||
<code>User: <Image: 🐱> 这只猫在干嘛?<br>Assistant:
|
||||
它在睡觉。</code>
|
||||
<p>任务:根据图像和问题生成回答。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,26 +9,46 @@
|
||||
<div class="messages">
|
||||
<!-- User Message -->
|
||||
<div class="message user">
|
||||
<div class="avatar">👤</div>
|
||||
<div class="avatar">
|
||||
👤
|
||||
</div>
|
||||
<div class="bubble">
|
||||
<div class="image-upload">
|
||||
<div class="placeholder-img">🐱</div>
|
||||
<div class="placeholder-img">
|
||||
🐱
|
||||
</div>
|
||||
</div>
|
||||
<div class="text">
|
||||
这只猫在做什么?
|
||||
</div>
|
||||
<div class="text">这只猫在做什么?</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Assistant Message -->
|
||||
<div class="message assistant" v-if="step > 0">
|
||||
<div class="avatar">🤖</div>
|
||||
<div
|
||||
v-if="step > 0"
|
||||
class="message assistant"
|
||||
>
|
||||
<div class="avatar">
|
||||
🤖
|
||||
</div>
|
||||
<div class="bubble">
|
||||
<div v-if="step === 1" class="thinking">
|
||||
<div
|
||||
v-if="step === 1"
|
||||
class="thinking"
|
||||
>
|
||||
<span class="icon">👁️</span> 正在观察图片...
|
||||
</div>
|
||||
<div v-else-if="step === 2" class="thinking">
|
||||
<div
|
||||
v-else-if="step === 2"
|
||||
class="thinking"
|
||||
>
|
||||
<span class="icon">🧠</span> 正在思考...
|
||||
</div>
|
||||
<div v-else class="content type-writer">
|
||||
<div
|
||||
v-else
|
||||
class="content type-writer"
|
||||
>
|
||||
{{ typedText }}<span class="cursor">|</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</div>
|
||||
|
||||
<div class="arrow-section">
|
||||
<div class="arrow-line"></div>
|
||||
<div class="arrow-line" />
|
||||
<div class="arrow-text">
|
||||
Reshape for View: Grid ⇄ Sequence (重排显示:网格⇄序列)
|
||||
</div>
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
<!-- 2. Feature Vector Sequence -->
|
||||
<div class="stage">
|
||||
<div class="stage-label">2. Output Token Sequence (N×D) (输出序列)</div>
|
||||
<div class="stage-label">
|
||||
2. Output Token Sequence (N×D) (输出序列)
|
||||
</div>
|
||||
<div class="vector-sequence">
|
||||
<div
|
||||
v-for="(item, index) in items"
|
||||
@@ -42,25 +44,27 @@
|
||||
<div
|
||||
class="v-cell"
|
||||
:style="{ opacity: 0.9, background: item.color }"
|
||||
></div>
|
||||
/>
|
||||
<div
|
||||
class="v-cell"
|
||||
:style="{ opacity: 0.7, background: item.color }"
|
||||
></div>
|
||||
/>
|
||||
<div
|
||||
class="v-cell"
|
||||
:style="{ opacity: 0.5, background: item.color }"
|
||||
></div>
|
||||
/>
|
||||
<div
|
||||
class="v-cell"
|
||||
:style="{ opacity: 0.8, background: item.color }"
|
||||
></div>
|
||||
/>
|
||||
<div
|
||||
class="v-cell"
|
||||
:style="{ opacity: 0.6, background: item.color }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
<div class="vector-idx">
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
<div class="vector-idx">{{ index + 1 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,21 +72,28 @@
|
||||
|
||||
<!-- 3. Semantic Panel -->
|
||||
<div class="semantic-panel">
|
||||
<div v-if="activeIndex !== -1" class="semantic-content">
|
||||
<div class="header" :style="{ borderColor: items[activeIndex].color }">
|
||||
<div
|
||||
v-if="activeIndex !== -1"
|
||||
class="semantic-content"
|
||||
>
|
||||
<div
|
||||
class="header"
|
||||
:style="{ borderColor: items[activeIndex].color }"
|
||||
>
|
||||
<span class="large-icon">{{ items[activeIndex].icon }}</span>
|
||||
<div class="title-group">
|
||||
<span class="title"
|
||||
>Token #{{ activeIndex + 1 }}:
|
||||
{{ items[activeIndex].label }}</span
|
||||
>
|
||||
<span class="title">Token #{{ activeIndex + 1 }}:
|
||||
{{ items[activeIndex].label }}</span>
|
||||
<span class="subtitle">Type: {{ items[activeIndex].type }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
<div class="vector-repr">
|
||||
<span class="label">Vector Value:</span>
|
||||
<span class="code" :style="{ color: items[activeIndex].color }">
|
||||
<span
|
||||
class="code"
|
||||
:style="{ color: items[activeIndex].color }"
|
||||
>
|
||||
[0.{{ (Math.random() * 99).toFixed(0) }}, -0.{{
|
||||
(Math.random() * 99).toFixed(0)
|
||||
}}, 1.{{ (Math.random() * 99).toFixed(0) }}, ...]
|
||||
@@ -94,11 +105,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="placeholder">
|
||||
<div
|
||||
v-else
|
||||
class="placeholder"
|
||||
>
|
||||
<span class="hint-icon">👆</span>
|
||||
<span class="hint-text"
|
||||
>悬停在上方方块或向量上,查看 ViT 输出的“语义特征”</span
|
||||
>
|
||||
<span class="hint-text">悬停在上方方块或向量上,查看 ViT 输出的“语义特征”</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<template>
|
||||
<div class="vlm-quick-start">
|
||||
<div class="header">
|
||||
<div class="title">👁️ VLM 初体验:不只是看图说话</div>
|
||||
<div class="subtitle">选择不同场景,体验多模态模型的多种能力。</div>
|
||||
<div class="title">
|
||||
👁️ VLM 初体验:不只是看图说话
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
选择不同场景,体验多模态模型的多种能力。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scenario-tabs">
|
||||
@@ -24,22 +28,39 @@
|
||||
class="image-placeholder"
|
||||
:class="{ loaded: hasImage, 'receipt-bg': currentScenario === 'ocr' }"
|
||||
>
|
||||
<div v-if="!hasImage" class="upload-prompt">
|
||||
<div class="icon">🖼️</div>
|
||||
<button class="upload-btn" @click="loadImage">
|
||||
<div
|
||||
v-if="!hasImage"
|
||||
class="upload-prompt"
|
||||
>
|
||||
<div class="icon">
|
||||
🖼️
|
||||
</div>
|
||||
<button
|
||||
class="upload-btn"
|
||||
@click="loadImage"
|
||||
>
|
||||
上传图片 (模拟)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="image-content">
|
||||
<div
|
||||
v-else
|
||||
class="image-content"
|
||||
>
|
||||
<!-- Chat: Landscape -->
|
||||
<div
|
||||
v-if="currentScenario === 'chat'"
|
||||
class="real-image-container landscape"
|
||||
>
|
||||
<div class="real-image">🏔️</div>
|
||||
<div class="sun">☀️</div>
|
||||
<div class="tree">🌲</div>
|
||||
<div class="real-image">
|
||||
🏔️
|
||||
</div>
|
||||
<div class="sun">
|
||||
☀️
|
||||
</div>
|
||||
<div class="tree">
|
||||
🌲
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detection: Fruits -->
|
||||
@@ -73,24 +94,42 @@
|
||||
v-else-if="currentScenario === 'analysis'"
|
||||
class="factory-image"
|
||||
>
|
||||
<div class="safety-sign">⚠️ 安全生产</div>
|
||||
<div class="safety-sign">
|
||||
⚠️ 安全生产
|
||||
</div>
|
||||
<div class="worker-container">
|
||||
<span class="worker">👷</span>
|
||||
<span class="helmet" v-if="true">⛑️</span>
|
||||
<span
|
||||
v-if="true"
|
||||
class="helmet"
|
||||
>⛑️</span>
|
||||
</div>
|
||||
<div class="machinery">
|
||||
⚙️
|
||||
</div>
|
||||
<div class="machinery">⚙️</div>
|
||||
</div>
|
||||
|
||||
<!-- OCR: Receipt -->
|
||||
<div v-else class="receipt-image">
|
||||
<div class="receipt-header">🧾 RECEIPT</div>
|
||||
<div
|
||||
v-else
|
||||
class="receipt-image"
|
||||
>
|
||||
<div class="receipt-header">
|
||||
🧾 RECEIPT
|
||||
</div>
|
||||
<div class="receipt-body">
|
||||
<div class="line"><span>Coffee</span><span>$4.50</span></div>
|
||||
<div class="line"><span>Bagel</span><span>$3.00</span></div>
|
||||
<div class="line">
|
||||
<span>Coffee</span><span>$4.50</span>
|
||||
</div>
|
||||
<div class="line">
|
||||
<span>Bagel</span><span>$3.00</span>
|
||||
</div>
|
||||
<div class="line total">
|
||||
<span>TOTAL</span><span>$7.50</span>
|
||||
</div>
|
||||
<div class="line date"><span>2023-10-24</span></div>
|
||||
<div class="line date">
|
||||
<span>2023-10-24</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -103,8 +142,14 @@
|
||||
|
||||
<!-- Chat Area -->
|
||||
<div class="chat-area">
|
||||
<div class="messages" ref="messagesRef">
|
||||
<div v-if="messages.length === 0" class="empty-text">
|
||||
<div
|
||||
ref="messagesRef"
|
||||
class="messages"
|
||||
>
|
||||
<div
|
||||
v-if="messages.length === 0"
|
||||
class="empty-text"
|
||||
>
|
||||
{{ hasImage ? '图片已就绪,请选择指令' : '请先上传图片' }}
|
||||
</div>
|
||||
<div
|
||||
@@ -114,38 +159,51 @@
|
||||
:class="msg.role"
|
||||
>
|
||||
<div class="content">
|
||||
<div v-if="msg.isJson" class="json-content">
|
||||
<div
|
||||
v-if="msg.isJson"
|
||||
class="json-content"
|
||||
>
|
||||
<pre>{{ msg.content }}</pre>
|
||||
</div>
|
||||
<span v-else>{{ msg.content }}</span>
|
||||
<span
|
||||
v-if="
|
||||
msg.role === 'assistant' &&
|
||||
isGenerating &&
|
||||
index === messages.length - 1
|
||||
isGenerating &&
|
||||
index === messages.length - 1
|
||||
"
|
||||
class="cursor"
|
||||
>|</span
|
||||
>
|
||||
>|</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-area">
|
||||
<div class="quick-actions" v-if="hasImage && !isGenerating">
|
||||
<div
|
||||
v-if="hasImage && !isGenerating"
|
||||
class="quick-actions"
|
||||
>
|
||||
<button
|
||||
v-for="q in currentQuestions"
|
||||
:key="q"
|
||||
@click="ask(q)"
|
||||
class="action-btn"
|
||||
@click="ask(q)"
|
||||
>
|
||||
{{ q }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="status-text" v-else-if="isGenerating">
|
||||
<div
|
||||
v-else-if="isGenerating"
|
||||
class="status-text"
|
||||
>
|
||||
AI 正在观察图片并思考...
|
||||
</div>
|
||||
<div class="status-text" v-else>等待图片上传...</div>
|
||||
<div
|
||||
v-else
|
||||
class="status-text"
|
||||
>
|
||||
等待图片上传...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user