Files
test-repo/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue
T
sanbuphy 73f4788d7e 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
2026-01-16 19:10:51 +08:00

671 lines
15 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>