feat: save current work to dev branch
This commit is contained in:
@@ -0,0 +1,630 @@
|
||||
<template>
|
||||
<div class="agent-context-flow">
|
||||
<div class="flow-controls">
|
||||
<button class="control-btn" @click="startSimulation" :disabled="running">
|
||||
🚀 开始演示
|
||||
</button>
|
||||
<button class="control-btn reset" @click="reset" v-if="completed">
|
||||
🔄 重新演示
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flow-visualization">
|
||||
<div class="user-input">
|
||||
<div class="input-icon">👤</div>
|
||||
<div class="input-content">
|
||||
<div class="input-label">用户输入</div>
|
||||
<div class="input-text">{{ userInput }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down">↓</div>
|
||||
|
||||
<div class="context-window" :class="{ active: step >= 1 }">
|
||||
<div class="window-header">
|
||||
<span class="window-title">上下文窗口</span>
|
||||
<span class="window-size">{{ contextTokens }} tokens</span>
|
||||
</div>
|
||||
<div class="window-content">
|
||||
<div
|
||||
v-for="(item, index) in contextItems"
|
||||
:key="index"
|
||||
class="context-item"
|
||||
:class="{ cached: item.cached, active: item.active }"
|
||||
>
|
||||
<div class="item-type">{{ item.type }}</div>
|
||||
<div class="item-content">{{ item.content }}</div>
|
||||
<div class="item-tokens">{{ item.tokens }} tokens</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down">↓</div>
|
||||
|
||||
<div class="agent-decision" :class="{ active: step >= 2 }">
|
||||
<div class="decision-icon">🤖</div>
|
||||
<div class="decision-content">
|
||||
<div class="decision-label">Agent 决策</div>
|
||||
<div class="decision-text">{{ currentAction }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down">↓</div>
|
||||
|
||||
<div class="tool-execution" :class="{ active: step >= 3 }">
|
||||
<div class="tool-icon">🔧</div>
|
||||
<div class="tool-content">
|
||||
<div class="tool-label">工具执行</div>
|
||||
<div class="tool-name">{{ currentTool }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down">↓</div>
|
||||
|
||||
<div class="observation" :class="{ active: step >= 4 }">
|
||||
<div class="obs-icon">👁️</div>
|
||||
<div class="obs-content">
|
||||
<div class="obs-label">观察结果</div>
|
||||
<div class="obs-text">{{ observation }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-down">↓</div>
|
||||
|
||||
<div class="context-update" :class="{ active: step >= 5 }">
|
||||
<div class="update-icon">📝</div>
|
||||
<div class="update-content">
|
||||
<div class="update-label">更新上下文</div>
|
||||
<div class="update-text">动作 + 结果被追加到上下文</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metrics">
|
||||
<div class="metric-card">
|
||||
<div class="metric-title">KV 缓存命中率</div>
|
||||
<div class="metric-value">{{ cacheHitRate }}%</div>
|
||||
<div class="metric-desc">
|
||||
节省成本: {{ (costSavings * 100).toFixed(0) }}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric-card">
|
||||
<div class="metric-title">上下文长度</div>
|
||||
<div class="metric-value">{{ contextTokens }}</div>
|
||||
<div class="metric-desc">
|
||||
迭代: {{ iteration }} 步
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric-card">
|
||||
<div class="metric-title">已用工具</div>
|
||||
<div class="metric-value">{{ toolsUsed.length }}</div>
|
||||
<div class="metric-desc">
|
||||
{{ toolsUsed.join(', ') || '无' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="explanation" v-if="explanationText">
|
||||
<div class="exp-title">💡 当前步骤说明</div>
|
||||
<div class="exp-content">{{ explanationText }}</div>
|
||||
</div>
|
||||
|
||||
<div class="principles">
|
||||
<div class="principle-title">🎯 Agent 上下文工程核心原则</div>
|
||||
<div class="principle-list">
|
||||
<div class="principle-item">
|
||||
<div class="principle-icon">1️⃣</div>
|
||||
<div class="principle-content">
|
||||
<strong>保持前缀稳定</strong>
|
||||
<br>
|
||||
系统提示和工具定义不要频繁变化,提高 KV 缓存命中率
|
||||
</div>
|
||||
</div>
|
||||
<div class="principle-item">
|
||||
<div class="principle-icon">2️⃣</div>
|
||||
<div class="principle-content">
|
||||
<strong>只追加不修改</strong>
|
||||
<br>
|
||||
上下文应该只追加新的动作和观察,不修改历史内容
|
||||
</div>
|
||||
</div>
|
||||
<div class="principle-item">
|
||||
<div class="principle-icon">3️⃣</div>
|
||||
<div class="principle-content">
|
||||
<strong>遮蔽而非移除</strong>
|
||||
<br>
|
||||
不动态添加/删除工具,而是通过 logits 掩码控制可用工具
|
||||
</div>
|
||||
</div>
|
||||
<div class="principle-item">
|
||||
<div class="principle-icon">4️⃣</div>
|
||||
<div class="principle-content">
|
||||
<strong>文件系统作为外部记忆</strong>
|
||||
<br>
|
||||
大型内容(网页、PDF)写入文件,上下文只保留路径
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const userInput = ref('帮我搜索最新的 AI 技术文章')
|
||||
const running = ref(false)
|
||||
const completed = ref(false)
|
||||
const step = ref(0)
|
||||
const iteration = ref(0)
|
||||
const contextTokens = ref(0)
|
||||
const currentAction = ref('')
|
||||
const currentTool = ref('')
|
||||
const observation = ref('')
|
||||
const toolsUsed = ref([])
|
||||
|
||||
const contextItems = ref([
|
||||
{ type: '系统提示', content: '你是一个 AI 助手,可以使用搜索和文件工具', tokens: 150, cached: true, active: false },
|
||||
{ type: '工具定义', content: 'search: 搜索网络信息', tokens: 80, cached: true, active: false },
|
||||
{ type: '工具定义', content: 'write_file: 写入文件', tokens: 75, cached: true, active: false }
|
||||
])
|
||||
|
||||
const steps = [
|
||||
{
|
||||
step: 1,
|
||||
action: '分析用户需求',
|
||||
tool: '',
|
||||
obs: '',
|
||||
explanation: 'Agent 首先解析用户的请求,决定需要采取什么行动。系统提示和工具定义从缓存读取(绿色),节省成本!',
|
||||
addTokens: 50
|
||||
},
|
||||
{
|
||||
step: 2,
|
||||
action: '选择工具: search',
|
||||
tool: 'search',
|
||||
obs: '',
|
||||
explanation: 'Agent 根据用户需求选择合适的工具。注意:工具定义在缓存中,不需要重新计算!',
|
||||
addTokens: 30
|
||||
},
|
||||
{
|
||||
step: 3,
|
||||
action: '执行搜索',
|
||||
tool: 'search',
|
||||
obs: '找到 5 篇相关文章',
|
||||
explanation: '工具执行完成,返回观察结果。结果会被追加到上下文中。',
|
||||
addTokens: 100
|
||||
},
|
||||
{
|
||||
step: 4,
|
||||
action: '决定保存摘要',
|
||||
tool: 'write_file',
|
||||
obs: '文件已保存',
|
||||
explanation: 'Agent 将搜索结果写入文件,而不是在上下文中保留所有内容。这样上下文保持精简!',
|
||||
addTokens: 60
|
||||
},
|
||||
{
|
||||
step: 5,
|
||||
action: '完成任务',
|
||||
tool: '',
|
||||
obs: '已保存到 summary.md',
|
||||
explanation: '任务完成!整个过程中,系统提示和工具定义只缓存一次,每次迭代只追加新的动作和观察结果。',
|
||||
addTokens: 40
|
||||
}
|
||||
]
|
||||
|
||||
const cacheHitRate = computed(() => {
|
||||
const cachedTokens = contextItems.value.filter(item => item.cached).reduce((sum, item) => sum + item.tokens, 0)
|
||||
const totalTokens = contextTokens.value
|
||||
return totalTokens > 0 ? ((cachedTokens / totalTokens) * 100).toFixed(1) : 0
|
||||
})
|
||||
|
||||
const costSavings = computed(() => {
|
||||
return cacheHitRate.value > 0 ? (cacheHitRate.value / 100) * 0.9 : 0
|
||||
})
|
||||
|
||||
const explanationText = computed(() => {
|
||||
if (step.value === 0) return '点击"开始演示"查看 Agent 如何管理上下文'
|
||||
const currentStepData = steps[step.value - 1]
|
||||
return currentStepData ? currentStepData.explanation : ''
|
||||
})
|
||||
|
||||
const startSimulation = () => {
|
||||
running.value = true
|
||||
completed.value = false
|
||||
step.value = 0
|
||||
iteration.value = 0
|
||||
contextTokens.value = 305
|
||||
toolsUsed.value = []
|
||||
|
||||
let currentStepIndex = 0
|
||||
const interval = setInterval(() => {
|
||||
if (currentStepIndex < steps.length) {
|
||||
const stepData = steps[currentStepIndex]
|
||||
step.value = stepData.step
|
||||
currentAction.value = stepData.action
|
||||
currentTool.value = stepData.tool
|
||||
observation.value = stepData.obs
|
||||
|
||||
if (stepData.tool) {
|
||||
toolsUsed.value.push(stepData.tool)
|
||||
}
|
||||
|
||||
// 追加新的上下文项
|
||||
if (stepData.obs) {
|
||||
contextItems.value.push({
|
||||
type: '观察结果',
|
||||
content: stepData.obs,
|
||||
tokens: stepData.addTokens,
|
||||
cached: false,
|
||||
active: true
|
||||
})
|
||||
} else {
|
||||
contextItems.value.push({
|
||||
type: '思考',
|
||||
content: stepData.action,
|
||||
tokens: stepData.addTokens,
|
||||
cached: false,
|
||||
active: true
|
||||
})
|
||||
}
|
||||
|
||||
contextTokens.value += stepData.addTokens
|
||||
iteration.value++
|
||||
currentStepIndex++
|
||||
} else {
|
||||
clearInterval(interval)
|
||||
running.value = false
|
||||
completed.value = true
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
running.value = false
|
||||
completed.value = false
|
||||
step.value = 0
|
||||
iteration.value = 0
|
||||
contextTokens.value = 0
|
||||
currentAction.value = ''
|
||||
currentTool.value = ''
|
||||
observation.value = ''
|
||||
toolsUsed.value = []
|
||||
contextItems.value = [
|
||||
{ type: '系统提示', content: '你是一个 AI 助手,可以使用搜索和文件工具', tokens: 150, cached: true, active: false },
|
||||
{ type: '工具定义', content: 'search: 搜索网络信息', tokens: 80, cached: true, active: false },
|
||||
{ type: '工具定义', content: 'write_file: 写入文件', tokens: 75, cached: true, active: false }
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.agent-context-flow {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.flow-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 25px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
padding: 12px 24px;
|
||||
background: var(--vp-c-brand);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.control-btn:hover:not(:disabled) {
|
||||
background: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.control-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.control-btn.reset {
|
||||
background: #22c55e;
|
||||
}
|
||||
|
||||
.control-btn.reset:hover {
|
||||
background: #16a34a;
|
||||
}
|
||||
|
||||
.flow-visualization {
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.user-input,
|
||||
.agent-decision,
|
||||
.tool-execution,
|
||||
.observation,
|
||||
.context-update {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
padding: 15px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid var(--vp-c-divider);
|
||||
margin-bottom: 15px;
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.user-input.active,
|
||||
.agent-decision.active,
|
||||
.tool-execution.active,
|
||||
.observation.active,
|
||||
.context-update.active {
|
||||
opacity: 1;
|
||||
border-left-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.user-input {
|
||||
border-left-color: #3b82f6;
|
||||
}
|
||||
|
||||
.agent-decision {
|
||||
border-left-color: #8b5cf6;
|
||||
}
|
||||
|
||||
.tool-execution {
|
||||
border-left-color: #f59e0b;
|
||||
}
|
||||
|
||||
.observation {
|
||||
border-left-color: #10b981;
|
||||
}
|
||||
|
||||
.context-update {
|
||||
border-left-color: #ef4444;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.input-icon,
|
||||
.decision-icon,
|
||||
.tool-icon,
|
||||
.obs-icon,
|
||||
.update-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.input-content,
|
||||
.decision-content,
|
||||
.tool-content,
|
||||
.obs-content,
|
||||
.update-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.input-label,
|
||||
.decision-label,
|
||||
.tool-label,
|
||||
.obs-label,
|
||||
.update-label {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-3);
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.input-text,
|
||||
.decision-text,
|
||||
.tool-name,
|
||||
.obs-text,
|
||||
.update-text {
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-1);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
color: var(--vp-c-text-3);
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.context-window {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.context-window.active {
|
||||
opacity: 1;
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.window-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.window-title {
|
||||
font-size: 0.9rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.window-size {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-brand);
|
||||
font-family: monospace;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.context-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
background: var(--vp-c-bg);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.context-item.cached {
|
||||
border-left: 3px solid #22c55e;
|
||||
}
|
||||
|
||||
.context-item.active {
|
||||
border-left: 3px solid var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.item-type {
|
||||
font-size: 0.75rem;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
background: var(--vp-c-divider);
|
||||
color: var(--vp-c-text-3);
|
||||
font-weight: 600;
|
||||
min-width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.item-tokens {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-3);
|
||||
font-family: monospace;
|
||||
min-width: 60px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 15px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.metrics {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
border-left: 4px solid var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.metric-title {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-3);
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-brand);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.metric-desc {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.explanation {
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
border-left: 4px solid var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.exp-title {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.exp-content {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.principles {
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.principle-title {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.principle-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.principle-item {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
padding: 15px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.principle-icon {
|
||||
font-size: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.principle-content {
|
||||
flex: 1;
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.8;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div class="context-window-demo">
|
||||
<div class="window-comparison">
|
||||
<!-- Short Context -->
|
||||
<div class="model-card">
|
||||
<div class="model-header">
|
||||
<span class="model-icon">📱</span>
|
||||
<span class="model-title">短上下文模型</span>
|
||||
</div>
|
||||
<div class="model-body">
|
||||
<div class="window-visual">
|
||||
<div class="window-bar">
|
||||
<div class="window-label">上下文窗口: 4K tokens</div>
|
||||
<div class="window-size">
|
||||
<div class="size-fill short" :style="{ width: '20%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-preview">
|
||||
<div class="content-item system">系统提示词</div>
|
||||
<div class="content-item user">用户消息</div>
|
||||
<div class="content-item assistant">助手回复</div>
|
||||
<div class="content-item warning">⚠️ 只能处理短文档</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="model-info">
|
||||
<div class="info-item">
|
||||
<span class="label">窗口大小:</span>
|
||||
<span>4K tokens (~3000 字)</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">适用场景:</span>
|
||||
<span>问答、摘要、对话</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">代表模型:</span>
|
||||
<span>GPT-3.5, Claude 2</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Long Context -->
|
||||
<div class="model-card highlight">
|
||||
<div class="model-header">
|
||||
<span class="model-icon">📚</span>
|
||||
<span class="model-title">长上下文模型</span>
|
||||
</div>
|
||||
<div class="model-body">
|
||||
<div class="window-visual">
|
||||
<div class="window-bar">
|
||||
<div class="window-label">上下文窗口: 200K tokens</div>
|
||||
<div class="window-size">
|
||||
<div class="size-fill long" :style="{ width: '100%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-preview">
|
||||
<div class="content-item system">系统提示词</div>
|
||||
<div class="content-item user">用户消息</div>
|
||||
<div class="content-item docs">📄 完整技术文档</div>
|
||||
<div class="content-item docs">📄 代码库文件</div>
|
||||
<div class="content-item assistant">助手回复</div>
|
||||
<div class="content-item success">✅ 可处理长文档</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="model-info">
|
||||
<div class="info-item">
|
||||
<span class="label">窗口大小:</span>
|
||||
<span>200K tokens (~15 万字)</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">适用场景:</span>
|
||||
<span>长文档分析、代码审查</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">代表模型:</span>
|
||||
<span>GPT-4, Claude 3, Gemini</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tips">
|
||||
<div class="tip">
|
||||
<span class="tip-icon">💡</span>
|
||||
<span><strong>选择合适的模型</strong>:短对话用短上下文模型(更快更便宜),
|
||||
长文档分析用长上下文模型(避免信息丢失)</span>
|
||||
</div>
|
||||
<div class="tip">
|
||||
<span class="tip-icon">📏</span>
|
||||
<span><strong>注意 Token 计算</strong>:1 Token ≈ 0.75 个英文单词 或 0.5-1 个汉字。
|
||||
100K tokens 大约等于一本 300 页的书</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.context-window-demo {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.window-comparison {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.window-comparison {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.model-card {
|
||||
background: var(--vp-c-bg);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.model-card.highlight {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.model-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 15px;
|
||||
background: var(--vp-c-bg-mute);
|
||||
}
|
||||
|
||||
.model-card.highlight .model-header {
|
||||
background: rgba(var(--vp-c-brand-rgb), 0.1);
|
||||
}
|
||||
|
||||
.model-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.model-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.model-body {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.window-visual {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.window-bar {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.window-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-3);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.window-size {
|
||||
height: 8px;
|
||||
background: var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.size-fill {
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
.size-fill.short {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.size-fill.long {
|
||||
background: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.content-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.content-item {
|
||||
font-size: 0.8rem;
|
||||
padding: 6px 10px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.content-item.system {
|
||||
background: rgba(59, 130, 246, 0.2);
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
.content-item.user {
|
||||
background: rgba(34, 197, 94, 0.2);
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.content-item.assistant {
|
||||
background: rgba(168, 85, 247, 0.2);
|
||||
color: #a855f7;
|
||||
}
|
||||
|
||||
.content-item.docs {
|
||||
background: rgba(251, 191, 36, 0.2);
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
.content-item.warning {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.content-item.success {
|
||||
background: rgba(34, 197, 94, 0.2);
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.model-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.info-item .label {
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.info-item span:last-child {
|
||||
color: var(--vp-c-text-1);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
background: var(--vp-c-bg);
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,266 @@
|
||||
<template>
|
||||
<div class="rag-pipeline-demo">
|
||||
<div class="pipeline-title">🔄 RAG (检索增强生成) 工作流程</div>
|
||||
|
||||
<div class="pipeline-flow">
|
||||
<!-- Step 1: Query -->
|
||||
<div class="flow-step">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-content">
|
||||
<div class="step-icon">❓</div>
|
||||
<div class="step-title">用户提问</div>
|
||||
<div class="step-desc">"什么是 RAG?"</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-arrow">→</div>
|
||||
|
||||
<!-- Step 2: Retrieve -->
|
||||
<div class="flow-step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-content">
|
||||
<div class="step-icon">🔍</div>
|
||||
<div class="step-title">检索相关文档</div>
|
||||
<div class="step-desc">从知识库找到最相关的 3-5 篇文章</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-arrow">→</div>
|
||||
|
||||
<!-- Step 3: Augment -->
|
||||
<div class="flow-step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-content">
|
||||
<div class="step-icon">📝</div>
|
||||
<div class="step-title">增强提示词</div>
|
||||
<div class="step-desc">将文档内容插入到提示词中</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-arrow">→</div>
|
||||
|
||||
<!-- Step 4: Generate -->
|
||||
<div class="flow-step highlight">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-content">
|
||||
<div class="step-icon">🤖</div>
|
||||
<div class="step-title">生成回答</div>
|
||||
<div class="step-desc">基于检索到的信息生成答案</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="example">
|
||||
<div class="example-header">📄 增强后的提示词示例</div>
|
||||
<div class="example-content">
|
||||
<div class="example-section">
|
||||
<span class="section-label">系统提示:</span>
|
||||
<span class="section-text">你是一个技术助手。</span>
|
||||
</div>
|
||||
<div class="example-section">
|
||||
<span class="section-label">检索到的文档:</span>
|
||||
<div class="retrieved-docs">
|
||||
<div class="doc-item">📄 Doc 1: "RAG 是一种结合检索和生成的技术..."</div>
|
||||
<div class="doc-item">📄 Doc 2: "RAG 的优势是减少幻觉、提高准确性..."</div>
|
||||
<div class="doc-item">📄 Doc 3: "常见的 RAG 框架包括 LangChain..."</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="example-section">
|
||||
<span class="section-label">用户问题:</span>
|
||||
<span class="section-text">什么是 RAG?</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="benefits">
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">✅</span>
|
||||
<span><strong>减少幻觉</strong>:基于真实文档回答,不瞎编</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">📚</span>
|
||||
<span><strong>知识更新</strong>:无需重新训练,只需更新文档库</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">🎯</span>
|
||||
<span><strong>答案可溯源</strong>:可以知道答案来自哪篇文档</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">💰</span>
|
||||
<span><strong>降低成本</strong>:不需要频繁微调模型</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.rag-pipeline-demo {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.pipeline-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pipeline-flow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 25px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flow-step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: var(--vp-c-bg-mute);
|
||||
color: var(--vp-c-text-1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.flow-step.highlight .step-number {
|
||||
background: var(--vp-c-brand);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.flow-step.highlight .step-content {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: rgba(var(--vp-c-brand-rgb), 0.1);
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-1);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-3);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.flow-arrow {
|
||||
font-size: 1.5rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.example {
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.example-header {
|
||||
font-size: 0.9rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.example-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.example-section {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
color: var(--vp-c-brand);
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.retrieved-docs {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.doc-item {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-3);
|
||||
padding: 6px;
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 3px;
|
||||
border-left: 3px solid #fbbf24;
|
||||
}
|
||||
|
||||
.benefits {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.benefits {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.benefit-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
background: var(--vp-c-bg);
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user