3af119a598
- 新增 Vibe Coding 全栈相关演示组件 (DeveloperSkillShift, FrontendTriad, BackendCore 等) - 新增 RAG 相关组件 (RAGPipeline, ChunkingStrategy, Retrieval 等) - 新增 Embedding & Vector 相关组件 (EmbeddingConcept, VectorSimilarity 等) - 新增 AI Native App 设计组件 (AINativeArch, PromptDesign 等) - 新增 Infrastructure as Code 组件 (IaCConcept, TerraformWorkflow 等) - 新增 DNS & HTTPS 演示组件 (DnsResolution, HttpsHandshake 等) - 新增 Model Finetuning 组件 (FinetuningPipeline 等) - 更新多个章节的 markdown 内容,集成交互式演示
418 lines
12 KiB
Vue
418 lines
12 KiB
Vue
<!--
|
||
RAGArchitectureDemo.vue
|
||
RAG 架构演进交互演示
|
||
|
||
用途:
|
||
展示三种 RAG 架构:Naive RAG、Advanced RAG、Modular RAG
|
||
用户可以切换查看不同架构的流程图和特点。
|
||
|
||
交互功能:
|
||
- 切换三种架构
|
||
- 查看每种架构的流程节点
|
||
- 对比各架构的优劣
|
||
-->
|
||
<template>
|
||
<div class="rag-arch-demo">
|
||
<div class="arch-tabs">
|
||
<button
|
||
v-for="(arch, i) in architectures"
|
||
:key="i"
|
||
:class="['arch-tab', { active: currentArch === i }]"
|
||
@click="currentArch = i"
|
||
>
|
||
<span class="tab-badge">{{ arch.badge }}</span>
|
||
<span class="tab-name">{{ arch.name }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="arch-desc">
|
||
{{ activeArch.desc }}
|
||
</div>
|
||
|
||
<div class="flow-diagram">
|
||
<div
|
||
v-for="(node, j) in activeArch.nodes"
|
||
:key="j"
|
||
class="flow-node-wrapper"
|
||
>
|
||
<div
|
||
:class="['flow-node', node.type]"
|
||
@click="selectedNode = selectedNode === j ? null : j"
|
||
>
|
||
<div class="node-icon">{{ node.icon }}</div>
|
||
<div class="node-label">{{ node.label }}</div>
|
||
</div>
|
||
<div
|
||
v-if="j < activeArch.nodes.length - 1"
|
||
class="flow-connector"
|
||
>
|
||
<span class="connector-arrow">→</span>
|
||
<span
|
||
v-if="node.connectorLabel"
|
||
class="connector-label"
|
||
>{{ node.connectorLabel }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-if="selectedNode !== null"
|
||
class="node-detail"
|
||
>
|
||
<div class="node-detail-title">
|
||
{{ activeArch.nodes[selectedNode].icon }}
|
||
{{ activeArch.nodes[selectedNode].label }}
|
||
</div>
|
||
<div class="node-detail-desc">
|
||
{{ activeArch.nodes[selectedNode].detail }}
|
||
</div>
|
||
</div>
|
||
<div
|
||
v-else
|
||
class="node-hint"
|
||
>
|
||
点击流程节点查看详细说明
|
||
</div>
|
||
|
||
<div class="arch-features">
|
||
<div class="feature-title">架构特点</div>
|
||
<div class="feature-grid">
|
||
<div
|
||
v-for="(f, i) in activeArch.features"
|
||
:key="i"
|
||
class="feature-item"
|
||
>
|
||
<span class="feature-icon">{{ f.icon }}</span>
|
||
<span class="feature-text">{{ f.text }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="evolution-bar">
|
||
<div class="evo-title">架构演进路线</div>
|
||
<div class="evo-track">
|
||
<div
|
||
v-for="(arch, i) in architectures"
|
||
:key="i"
|
||
:class="['evo-node', { active: currentArch >= i }]"
|
||
>
|
||
<div class="evo-dot" />
|
||
<div class="evo-label">{{ arch.name }}</div>
|
||
<div class="evo-year">{{ arch.year }}</div>
|
||
</div>
|
||
<div class="evo-line">
|
||
<div
|
||
class="evo-line-fill"
|
||
:style="{ width: (currentArch / (architectures.length - 1)) * 100 + '%' }"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, watch } from 'vue'
|
||
|
||
const currentArch = ref(0)
|
||
const selectedNode = ref(null)
|
||
|
||
watch(currentArch, () => { selectedNode.value = null })
|
||
|
||
const architectures = [
|
||
{
|
||
name: 'Naive RAG',
|
||
badge: 'v1',
|
||
year: '2023',
|
||
desc: '最基础的 RAG 架构,流程简单直接:索引 → 检索 → 生成。适合快速原型验证,但在复杂场景下效果有限。',
|
||
nodes: [
|
||
{ icon: '📄', label: '文档加载', type: 'input', detail: '将原始文档(PDF、网页、数据库等)加载到系统中,进行基本的文本提取和清洗。', connectorLabel: '' },
|
||
{ icon: '✂️', label: '文本分块', type: 'process', detail: '将长文档按固定大小切分为较小的文本块(chunk),通常 200-500 个 token。', connectorLabel: '' },
|
||
{ icon: '🔢', label: '向量化', type: 'process', detail: '使用嵌入模型将每个文本块转化为向量,存入向量数据库。', connectorLabel: '' },
|
||
{ icon: '🔍', label: '检索', type: 'process', detail: '用户提问时,将问题向量化后在向量数据库中搜索最相似的文本块。', connectorLabel: '' },
|
||
{ icon: '🤖', label: '生成', type: 'output', detail: '将检索到的文本块与问题拼接为 Prompt,交给 LLM 生成回答。' }
|
||
],
|
||
features: [
|
||
{ icon: '✅', text: '实现简单,上手快' },
|
||
{ icon: '✅', text: '适合结构化知识库' },
|
||
{ icon: '⚠️', text: '检索质量依赖分块策略' },
|
||
{ icon: '❌', text: '无法处理复杂查询' }
|
||
]
|
||
},
|
||
{
|
||
name: 'Advanced RAG',
|
||
badge: 'v2',
|
||
year: '2024',
|
||
desc: '在 Naive RAG 基础上增加了查询优化和检索后处理,显著提升检索质量和生成准确性。',
|
||
nodes: [
|
||
{ icon: '💬', label: '用户查询', type: 'input', detail: '接收用户的原始问题。', connectorLabel: '' },
|
||
{ icon: '🔄', label: '查询改写', type: 'enhance', detail: '使用 LLM 对原始查询进行改写、扩展或分解。例如将模糊问题改写为更精确的检索查询,或生成多个子查询。', connectorLabel: '' },
|
||
{ icon: '🔍', label: '混合检索', type: 'process', detail: '同时使用向量检索(语义)和关键词检索(BM25),融合两者的结果,兼顾语义理解和精确匹配。', connectorLabel: '' },
|
||
{ icon: '📊', label: '重排序', type: 'enhance', detail: '使用交叉编码器对检索结果进行精细排序,过滤掉不相关的文档片段。', connectorLabel: '' },
|
||
{ icon: '📋', label: '上下文压缩', type: 'enhance', detail: '从检索到的文档中提取与问题最相关的部分,去除冗余信息,节省上下文窗口。', connectorLabel: '' },
|
||
{ icon: '🤖', label: '生成', type: 'output', detail: '基于优化后的上下文生成高质量回答。' }
|
||
],
|
||
features: [
|
||
{ icon: '✅', text: '查询改写提升检索召回率' },
|
||
{ icon: '✅', text: '混合检索兼顾语义和关键词' },
|
||
{ icon: '✅', text: '重排序显著提升精度' },
|
||
{ icon: '⚠️', text: '流程较长,延迟增加' }
|
||
]
|
||
},
|
||
{
|
||
name: 'Modular RAG',
|
||
badge: 'v3',
|
||
year: '2025',
|
||
desc: '将 RAG 拆解为可插拔的模块,支持灵活组合和路由。可根据查询类型动态选择最优流程。',
|
||
nodes: [
|
||
{ icon: '💬', label: '用户查询', type: 'input', detail: '接收用户的原始问题。', connectorLabel: '' },
|
||
{ icon: '🧭', label: '路由判断', type: 'enhance', detail: '分析查询意图,决定走哪条处理路径:简单问题直接回答,复杂问题走检索流程,多步问题走分解流程。', connectorLabel: '' },
|
||
{ icon: '🔀', label: '查询转换', type: 'enhance', detail: '根据路由结果选择:HyDE(假设文档嵌入)、Step-back(退一步提问)、子问题分解等策略。', connectorLabel: '' },
|
||
{ icon: '🔍', label: '自适应检索', type: 'process', detail: '根据查询特征自动选择检索策略:向量检索、图检索、SQL 检索或多路检索融合。', connectorLabel: '' },
|
||
{ icon: '🔄', label: '自我反思', type: 'enhance', detail: 'LLM 评估检索结果是否充分,不充分则触发二次检索或调整检索策略(Self-RAG / CRAG)。', connectorLabel: '' },
|
||
{ icon: '🤖', label: '生成', type: 'output', detail: '基于充分验证的上下文生成最终回答,并附带置信度评分。' }
|
||
],
|
||
features: [
|
||
{ icon: '✅', text: '模块化设计,灵活可扩展' },
|
||
{ icon: '✅', text: '自适应路由,智能选择策略' },
|
||
{ icon: '✅', text: '自我反思机制提升可靠性' },
|
||
{ icon: '⚠️', text: '系统复杂度高,需要精心调优' }
|
||
]
|
||
}
|
||
]
|
||
|
||
const activeArch = computed(() => architectures[currentArch.value])
|
||
</script>
|
||
|
||
<style scoped>
|
||
.rag-arch-demo {
|
||
border: 1px solid var(--vp-c-divider);
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
margin: 16px 0;
|
||
background: var(--vp-c-bg-soft);
|
||
}
|
||
.arch-tabs {
|
||
display: flex;
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.arch-tab {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 8px 16px;
|
||
border: 2px solid var(--vp-c-divider);
|
||
border-radius: 8px;
|
||
background: var(--vp-c-bg);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
font-size: 13px;
|
||
}
|
||
.arch-tab.active {
|
||
border-color: var(--vp-c-brand-1);
|
||
background: var(--vp-c-brand-soft);
|
||
}
|
||
.tab-badge {
|
||
padding: 1px 6px;
|
||
border-radius: 4px;
|
||
background: var(--vp-c-divider);
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
}
|
||
.arch-tab.active .tab-badge {
|
||
background: var(--vp-c-brand-1);
|
||
color: #fff;
|
||
}
|
||
.tab-name {
|
||
font-weight: 600;
|
||
}
|
||
.arch-desc {
|
||
font-size: 13px;
|
||
color: var(--vp-c-text-2);
|
||
line-height: 1.6;
|
||
margin-bottom: 16px;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
background: var(--vp-c-bg);
|
||
border: 1px solid var(--vp-c-divider);
|
||
}
|
||
.flow-diagram {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0;
|
||
overflow-x: auto;
|
||
padding: 12px 0;
|
||
margin-bottom: 12px;
|
||
}
|
||
.flow-node-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.flow-node {
|
||
padding: 10px 14px;
|
||
border-radius: 8px;
|
||
border: 2px solid var(--vp-c-divider);
|
||
background: var(--vp-c-bg);
|
||
text-align: center;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
min-width: 70px;
|
||
}
|
||
.flow-node:hover {
|
||
border-color: var(--vp-c-brand-1);
|
||
transform: translateY(-2px);
|
||
}
|
||
.flow-node.input {
|
||
border-color: #3b82f6;
|
||
background: #eff6ff;
|
||
}
|
||
.flow-node.output {
|
||
border-color: #10b981;
|
||
background: #ecfdf5;
|
||
}
|
||
.flow-node.enhance {
|
||
border-color: #f59e0b;
|
||
background: #fffbeb;
|
||
}
|
||
.flow-node.process {
|
||
border-color: #8b5cf6;
|
||
background: #f5f3ff;
|
||
}
|
||
.node-icon {
|
||
font-size: 20px;
|
||
margin-bottom: 2px;
|
||
}
|
||
.node-label {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
color: var(--vp-c-text-1);
|
||
}
|
||
.flow-connector {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 0 4px;
|
||
}
|
||
.connector-arrow {
|
||
font-size: 16px;
|
||
color: var(--vp-c-text-3);
|
||
}
|
||
.connector-label {
|
||
font-size: 10px;
|
||
color: var(--vp-c-text-3);
|
||
}
|
||
.node-detail {
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
background: var(--vp-c-bg);
|
||
border: 1px solid var(--vp-c-brand-1);
|
||
margin-bottom: 16px;
|
||
}
|
||
.node-detail-title {
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
color: var(--vp-c-brand-1);
|
||
margin-bottom: 6px;
|
||
}
|
||
.node-detail-desc {
|
||
font-size: 13px;
|
||
color: var(--vp-c-text-2);
|
||
line-height: 1.6;
|
||
}
|
||
.node-hint {
|
||
text-align: center;
|
||
padding: 12px;
|
||
color: var(--vp-c-text-3);
|
||
font-size: 13px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.feature-title {
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.feature-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.feature-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 8px 12px;
|
||
border-radius: 6px;
|
||
background: var(--vp-c-bg);
|
||
font-size: 13px;
|
||
}
|
||
.feature-icon {
|
||
flex-shrink: 0;
|
||
}
|
||
.feature-text {
|
||
color: var(--vp-c-text-2);
|
||
}
|
||
.evolution-bar {
|
||
padding: 16px;
|
||
border-radius: 8px;
|
||
background: var(--vp-c-bg);
|
||
border: 1px solid var(--vp-c-divider);
|
||
}
|
||
.evo-title {
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
margin-bottom: 16px;
|
||
text-align: center;
|
||
}
|
||
.evo-track {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
position: relative;
|
||
padding: 0 20px;
|
||
}
|
||
.evo-node {
|
||
text-align: center;
|
||
z-index: 1;
|
||
opacity: 0.4;
|
||
transition: opacity 0.3s;
|
||
}
|
||
.evo-node.active {
|
||
opacity: 1;
|
||
}
|
||
.evo-dot {
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 50%;
|
||
background: var(--vp-c-divider);
|
||
margin: 0 auto 6px;
|
||
transition: background 0.3s;
|
||
}
|
||
.evo-node.active .evo-dot {
|
||
background: var(--vp-c-brand-1);
|
||
}
|
||
.evo-label {
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
}
|
||
.evo-year {
|
||
font-size: 11px;
|
||
color: var(--vp-c-text-3);
|
||
}
|
||
.evo-line {
|
||
position: absolute;
|
||
top: 6px;
|
||
left: 20px;
|
||
right: 20px;
|
||
height: 2px;
|
||
background: var(--vp-c-divider);
|
||
}
|
||
.evo-line-fill {
|
||
height: 100%;
|
||
background: var(--vp-c-brand-1);
|
||
transition: width 0.5s;
|
||
}
|
||
</style>
|