Files
test-repo/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceDemo.vue
T
sanbuphy 0eba9e87e9 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>
2026-02-18 17:38:10 +08:00

396 lines
9.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
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.
<!--
* Component: MemoryPalaceDemo.vue
* Description: Visualizes the "Memory Palace" 4-layer context structure.
* Features:
* - Step-by-step assembly of the context layers
* - Visual distinction between Static (Cached) and Dynamic parts
* - Explains the purpose of each layer
-->
<script setup>
import { ref, computed } from 'vue'
const currentStep = ref(0)
const steps = [
{
id: 'base',
title: '第一层:地基 (System)',
desc: '系统设定、身份、原则',
detail: '✅ 永远不变,利用 KV Cache 实现 0 成本背诵',
color: 'var(--vp-c-brand)',
icon: '🏛️'
},
{
id: 'task',
title: '第二层:支柱 (Task)',
desc: '当前任务目标、用户画像',
detail: '📌 任务期内“钉死”,保证方向不偏',
color: '#8e44ad',
icon: '📌'
},
{
id: 'chat',
title: '第三层:客厅 (Chat)',
desc: '最近 5-10 轮对话',
detail: '🔄 滑动窗口,旧的自动腾出空间',
color: '#e67e22',
icon: '💬'
},
{
id: 'rag',
title: '第四层:图书馆 (RAG)',
desc: '按需检索的知识',
detail: '📚 不占脑子,用时再查,无限扩展',
color: '#27ae60',
icon: '🔍'
}
]
const nextStep = () => {
if (currentStep.value < 4) {
currentStep.value++
} else {
currentStep.value = 0
}
}
const isComplete = computed(() => currentStep.value === 4)
</script>
<template>
<div class="memory-palace-demo">
<!-- Visual Area -->
<div class="palace-container">
<div class="palace-stack">
<!-- Layer 4: RAG (Top/Side) -->
<div
class="layer-block rag-layer"
:class="{ visible: currentStep >= 4 }"
>
<div class="layer-content">
<span class="icon">{{ steps[3].icon }}</span>
<div class="text">
<div class="layer-title">
{{ steps[3].title }}
</div>
<div class="layer-desc">
{{ steps[3].desc }}
</div>
</div>
</div>
<div
v-if="currentStep >= 4"
class="layer-detail"
>
{{ steps[3].detail }}
</div>
</div>
<!-- Layer 3: Chat -->
<div
class="layer-block chat-layer"
:class="{ visible: currentStep >= 3 }"
>
<div class="layer-content">
<span class="icon">{{ steps[2].icon }}</span>
<div class="text">
<div class="layer-title">
{{ steps[2].title }}
</div>
<div class="layer-desc">
{{ steps[2].desc }}
</div>
</div>
</div>
<div
v-if="currentStep >= 3"
class="layer-detail"
>
{{ steps[2].detail }}
</div>
</div>
<!-- Layer 2: Task -->
<div
class="layer-block task-layer"
:class="{ visible: currentStep >= 2 }"
>
<div class="layer-content">
<span class="icon">{{ steps[1].icon }}</span>
<div class="text">
<div class="layer-title">
{{ steps[1].title }}
</div>
<div class="layer-desc">
{{ steps[1].desc }}
</div>
</div>
</div>
<div
v-if="currentStep >= 2"
class="layer-detail"
>
{{ steps[1].detail }}
</div>
</div>
<!-- Layer 1: Base -->
<div
class="layer-block base-layer"
:class="{ visible: currentStep >= 1 }"
>
<div class="layer-content">
<span class="icon">{{ steps[0].icon }}</span>
<div class="text">
<div class="layer-title">
{{ steps[0].title }}
</div>
<div class="layer-desc">
{{ steps[0].desc }}
</div>
</div>
</div>
<div
v-if="currentStep >= 1"
class="layer-detail"
>
{{ steps[0].detail }}
</div>
</div>
<!-- Empty State Placeholder -->
<div
v-if="currentStep === 0"
class="empty-placeholder"
>
🚧 空地点击下方按钮开始建造记忆宫殿
</div>
</div>
</div>
<!-- Control Area -->
<div class="control-area">
<div class="step-indicator">
当前进度: {{ currentStep }}/4
</div>
<button
class="build-btn"
:class="{ 'reset-mode': isComplete }"
@click="nextStep"
>
{{ isComplete ? '🔄 重置重建' : (currentStep === 0 ? '🏗️ 开始建造' : ' 添加下一层') }}
</button>
</div>
<!-- Explanation Box -->
<div
v-if="currentStep > 0"
class="explanation-box"
>
<div class="exp-title">
为什么这样设计
</div>
<div
v-if="currentStep === 1"
class="exp-content"
>
**地基最稳** System Prompt 放在最前面利用 KV Cache 机制 AI "背下来"后续请求**速度快且免费**
</div>
<div
v-if="currentStep === 2"
class="exp-content"
>
**目标明确**无论聊得多嗨任务目标写一个 Python 爬虫必须**钉死**防止 AI 聊偏了
</div>
<div
v-if="currentStep === 3"
class="exp-content"
>
**保持鲜活**最近的对话最重要用滑动窗口保留**旧的自动忘掉**给新信息腾地方
</div>
<div
v-if="currentStep === 4"
class="exp-content"
>
**无限外脑**遇到不懂的不要瞎编图书馆查资料**用完即走**不占宝贵的脑容量
</div>
</div>
</div>
</template>
<style scoped>
.memory-palace-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 12px;
background-color: var(--vp-c-bg-soft);
margin: 1.5rem 0;
overflow: hidden;
}
.palace-container {
padding: 2rem;
min-height: 320px;
display: flex;
align-items: flex-end; /* Stack from bottom */
justify-content: center;
background: linear-gradient(to top, var(--vp-c-bg-alt), var(--vp-c-bg));
}
.palace-stack {
width: 100%;
max-width: 400px;
display: flex;
flex-direction: column-reverse; /* Stack from bottom */
gap: 8px;
position: relative;
}
.layer-block {
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.75rem;
opacity: 0;
transform: translateY(20px) scale(0.95);
transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.layer-block.visible {
opacity: 1;
transform: translateY(0) scale(1);
}
/* Layer Specific Styles */
.base-layer {
border-color: var(--vp-c-brand);
border-bottom-width: 6px; /* Heavy foundation */
background: var(--vp-c-brand-dimm);
}
.task-layer {
border-color: #8e44ad;
background: rgba(142, 68, 173, 0.1);
margin: 0 10px; /* Slightly narrower */
}
.chat-layer {
border-color: #e67e22;
background: rgba(230, 126, 34, 0.1);
margin: 0 20px; /* Narrower */
}
.rag-layer {
border-color: #27ae60;
border-style: dashed;
background: rgba(39, 174, 96, 0.1);
margin: 0 30px; /* Narrowest */
}
.layer-content {
display: flex;
align-items: center;
gap: 1rem;
}
.icon {
font-size: 1.5rem;
}
.layer-title {
font-weight: bold;
font-size: 0.95rem;
color: var(--vp-c-text-1);
}
.layer-desc {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.layer-detail {
font-size: 0.75rem;
background: rgba(255,255,255,0.5);
padding: 4px 8px;
border-radius: 4px;
color: var(--vp-c-text-1);
display: inline-block;
align-self: flex-start;
}
.dark .layer-detail {
background: rgba(0,0,0,0.3);
}
.empty-placeholder {
text-align: center;
color: var(--vp-c-text-3);
padding: 2rem;
border: 2px dashed var(--vp-c-divider);
border-radius: 6px;
}
/* Controls */
.control-area {
padding: 0.75rem;
background: var(--vp-c-bg);
border-top: 1px solid var(--vp-c-divider);
display: flex;
justify-content: space-between;
align-items: center;
}
.step-indicator {
font-family: var(--vp-font-mono);
font-size: 0.9rem;
color: var(--vp-c-text-2);
}
.build-btn {
background: var(--vp-c-brand);
color: white;
padding: 0.6rem 1.2rem;
border-radius: 6px;
font-weight: 600;
transition: all 0.2s;
}
.build-btn:hover {
background: var(--vp-c-brand-dark);
transform: translateY(-1px);
}
.build-btn.reset-mode {
background: var(--vp-c-text-3);
}
/* Explanation */
.explanation-box {
padding: 0.75rem;
background: var(--vp-c-bg-alt);
border-top: 1px solid var(--vp-c-divider);
}
.exp-title {
font-size: 0.8rem;
font-weight: bold;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
text-transform: uppercase;
}
.exp-content {
font-size: 0.9rem;
line-height: 1.5;
color: var(--vp-c-text-1);
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
</style>