From 084ebed417748fcb58a1081449c3e30fbf4f4e51 Mon Sep 17 00:00:00 2001 From: sanbuphy Date: Tue, 3 Feb 2026 19:41:14 +0800 Subject: [PATCH] docs: update Chinese documentation and add Vue components - Update AI capability dictionary by removing redundant mention of Baidu's model - Add new Vue components for context engineering visualization (IntroProblemReasonSolution, MemoryPalaceDemo, MemoryPalaceActionDemo, KVCacheDemo, LostInMiddleDemo) - Register new components in theme index.js - Enhance audio introduction with new interactive demos (AudioQuickStartDemo, MelSpectrogramDemo, TTSPipelineDemo, VoiceCloningDemo, ASRvsTTSDemo, AudioTokenizationDemo, EmotionControlDemo) - Improve existing context engineering demos with Chinese localization and better tokenization - Fix Japanese documentation layout by properly closing NavGrid components --- .../appendix/audio-intro/ASRvsTTSDemo.vue | 789 ++++++++++++++ .../audio-intro/AudioQuickStartDemo.vue | 990 ++++++++++++------ .../audio-intro/AudioTokenizationDemo.vue | 887 +++++++++++----- .../audio-intro/EmotionControlDemo.vue | 533 ++++++++++ .../audio-intro/MelSpectrogramDemo.vue | 567 ++++++++++ .../appendix/audio-intro/TTSPipelineDemo.vue | 588 +++++++++++ .../appendix/audio-intro/VoiceCloningDemo.vue | 723 +++++++++++++ .../context-engineering/AgentContextFlow.vue | 596 +++-------- .../ContextCompressionDemo.vue | 355 ++++--- .../ContextWindowVisualizer.vue | 65 +- .../IntroProblemReasonSolution.vue | 70 ++ .../context-engineering/KVCacheDemo.vue | 402 +++++++ .../context-engineering/LostInMiddleDemo.vue | 283 +++++ .../MemoryPalaceActionDemo.vue | 521 +++++++++ .../context-engineering/MemoryPalaceDemo.vue | 337 ++++++ .../context-engineering/RAGSimulationDemo.vue | 721 ++++++------- .../SelectiveContextDemo.vue | 87 +- .../context-engineering/SlidingWindowDemo.vue | 111 +- .../url-to-browser/BrowserRenderingDemo.vue | 506 +++++++++ .../appendix/url-to-browser/DnsLookupDemo.vue | 724 +++++++++++++ .../url-to-browser/HttpExchangeDemo.vue | 533 ++++++++++ .../url-to-browser/TcpHandshakeDemo.vue | 551 ++++++++++ .../appendix/url-to-browser/UrlParserDemo.vue | 517 +++++++++ .../url-to-browser/UrlToBrowserQuickStart.vue | 914 ++++++++++++++++ docs/.vitepress/theme/index.js | 10 + docs/ja-jp/stage-2/intro.md | 278 +++-- .../appendix/ai-capability-dictionary.md | 2 +- docs/zh-cn/appendix/audio-intro.md | 143 ++- docs/zh-cn/appendix/context-engineering.md | 498 +++++++-- docs/zh-cn/appendix/url-to-browser.md | 388 +++++-- 30 files changed, 11563 insertions(+), 2126 deletions(-) create mode 100644 docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/audio-intro/EmotionControlDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/audio-intro/MelSpectrogramDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/audio-intro/TTSPipelineDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/audio-intro/VoiceCloningDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/context-engineering/IntroProblemReasonSolution.vue create mode 100644 docs/.vitepress/theme/components/appendix/context-engineering/KVCacheDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/context-engineering/LostInMiddleDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceActionDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/HttpExchangeDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/TcpHandshakeDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/UrlParserDemo.vue create mode 100644 docs/.vitepress/theme/components/appendix/url-to-browser/UrlToBrowserQuickStart.vue diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue new file mode 100644 index 0000000..3ef382a --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue @@ -0,0 +1,789 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue index 08c444d..d0c8d94 100644 --- a/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue +++ b/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue @@ -1,438 +1,796 @@ diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue index 9219132..caa5dea 100644 --- a/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue @@ -1,318 +1,687 @@ + diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/EmotionControlDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/EmotionControlDemo.vue new file mode 100644 index 0000000..fdd4a1e --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/audio-intro/EmotionControlDemo.vue @@ -0,0 +1,533 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/MelSpectrogramDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/MelSpectrogramDemo.vue new file mode 100644 index 0000000..5add0ba --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/audio-intro/MelSpectrogramDemo.vue @@ -0,0 +1,567 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/TTSPipelineDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/TTSPipelineDemo.vue new file mode 100644 index 0000000..6eb71d0 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/audio-intro/TTSPipelineDemo.vue @@ -0,0 +1,588 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/VoiceCloningDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/VoiceCloningDemo.vue new file mode 100644 index 0000000..fdb0d8a --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/audio-intro/VoiceCloningDemo.vue @@ -0,0 +1,723 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue b/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue index 456b9f0..2777381 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue @@ -1,531 +1,197 @@ - - diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/ContextCompressionDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/ContextCompressionDemo.vue index 92455a2..a9b8c14 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/ContextCompressionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/ContextCompressionDemo.vue @@ -1,10 +1,6 @@ + + diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/LostInMiddleDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/LostInMiddleDemo.vue new file mode 100644 index 0000000..3a56194 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/context-engineering/LostInMiddleDemo.vue @@ -0,0 +1,283 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceActionDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceActionDemo.vue new file mode 100644 index 0000000..3328d7b --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceActionDemo.vue @@ -0,0 +1,521 @@ + + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceDemo.vue new file mode 100644 index 0000000..65de6b7 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/context-engineering/MemoryPalaceDemo.vue @@ -0,0 +1,337 @@ + + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/RAGSimulationDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/RAGSimulationDemo.vue index cbe0b3b..38179c4 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/RAGSimulationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/RAGSimulationDemo.vue @@ -1,11 +1,6 @@ diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/SelectiveContextDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/SelectiveContextDemo.vue index 9053dbd..d9abf2e 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/SelectiveContextDemo.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/SelectiveContextDemo.vue @@ -17,12 +17,12 @@
{{ totalMessages }} - Total Messages + 现在一共记了几条
/
{{ maxSlots }} - Window Capacity + 黑板最多能记几条
@@ -39,8 +39,8 @@
📌 - Pinned Context (Protected) - {{ pinnedMessages.length }} items + 钉住区(永远保留的重要信息) + 当前 {{ pinnedMessages.length }} 条
@@ -56,10 +56,10 @@ class="pin-btn active" @click="togglePin(msg)" :disabled="msg.role === 'System'" - title="Unpin message" + title="取消钉住" > - 🔒 Fixed - 📌 Unpin + 🔒 系统信息固定在这 + 📌 取消钉住
{{ msg.content }}
@@ -72,8 +72,8 @@
📜 - Scrolling Context (FIFO) - {{ scrollingMessages.length }} items + 会被“挤走”的普通对话(先进先出) + 当前 {{ scrollingMessages.length }} 条
@@ -85,15 +85,15 @@ >
{{ msg.role }} -
{{ msg.content }}
- No scrolling messages... + 这里是“普通对话区”,暂时还空着
@@ -104,24 +104,24 @@
- - + +

💡 - Note: - "选择性保留" 解决了滑动窗口的遗忘问题。 - System Prompt 通常被永久钉住。用户也可以通过某些机制(如 RAG 或 记忆模块)将重要信息(如名字、密码)钉在窗口中,防止被挤出。 + 说明: + “选择性保留”就是:重要的就钉在黑板上,普通的让它自己滑走。 + 系统提示通常会永久钉住,用户的关键信息(比如名字、账号、重要偏好)也可以通过记忆模块或 RAG 钉在这里,避免被新对话挤掉。

@@ -194,7 +194,7 @@ const togglePin = (msg) => { border: 1px solid var(--vp-c-divider); border-radius: 8px; background-color: var(--vp-c-bg-soft); - padding: 1.5rem; + padding: 1rem; margin: 1rem 0; font-family: var(--vp-font-family-mono); } @@ -202,10 +202,10 @@ const togglePin = (msg) => { .control-panel { display: flex; align-items: center; - gap: 1.5rem; - margin-bottom: 1.5rem; + gap: 1rem; + margin-bottom: 1rem; background: var(--vp-c-bg); - padding: 1rem; + padding: 0.75rem; border-radius: 6px; border: 1px solid var(--vp-c-divider); } @@ -259,8 +259,8 @@ const togglePin = (msg) => { .visualization-area { display: flex; flex-direction: column; - gap: 1rem; - margin-bottom: 1.5rem; + gap: 0.75rem; + margin-bottom: 1rem; } .context-section { @@ -276,7 +276,7 @@ const togglePin = (msg) => { } .section-header { - padding: 0.5rem 1rem; + padding: 0.4rem 0.8rem; background: var(--vp-c-bg-alt); border-bottom: 1px solid var(--vp-c-divider); display: flex; @@ -298,15 +298,15 @@ const togglePin = (msg) => { } .message-list { - padding: 1rem; - min-height: 80px; + padding: 0.5rem; + min-height: 60px; } .message-card { border: 1px solid var(--vp-c-divider); border-radius: 6px; - padding: 0.75rem; - margin-bottom: 0.75rem; + padding: 0.5rem; + margin-bottom: 0.5rem; background: var(--vp-c-bg); transition: all 0.3s ease; } @@ -327,11 +327,11 @@ const togglePin = (msg) => { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 0.5rem; + margin-bottom: 0.25rem; } .role-badge { - font-size: 0.7rem; + font-size: 0.65rem; text-transform: uppercase; font-weight: bold; padding: 2px 6px; @@ -344,8 +344,8 @@ const togglePin = (msg) => { background: transparent; border: 1px solid var(--vp-c-divider); border-radius: 4px; - padding: 2px 8px; - font-size: 0.75rem; + padding: 2px 6px; + font-size: 0.7rem; cursor: pointer; color: var(--vp-c-text-2); transition: all 0.2s; @@ -369,19 +369,19 @@ const togglePin = (msg) => { } .card-content { - font-size: 0.9rem; - line-height: 1.4; + font-size: 0.85rem; + line-height: 1.3; } .empty-state { text-align: center; color: var(--vp-c-text-3); font-style: italic; - font-size: 0.85rem; + font-size: 0.8rem; } .input-section { - margin-bottom: 1rem; + margin-bottom: 0.75rem; } .input-group { @@ -392,7 +392,7 @@ const togglePin = (msg) => { input { flex: 1; - padding: 0.75rem; + padding: 0.5rem; border: 1px solid var(--vp-c-divider); border-radius: 6px; background: var(--vp-c-bg); @@ -405,13 +405,14 @@ input:focus { } .send-btn { - padding: 0 1.5rem; + padding: 0 1rem; background: var(--vp-c-brand); color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; + font-size: 0.9rem; } .send-btn:disabled { @@ -442,10 +443,10 @@ input:focus { .info-box { background-color: var(--vp-c-bg-alt); - padding: 1rem; + padding: 0.75rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.5; + font-size: 0.85rem; + line-height: 1.4; color: var(--vp-c-text-2); } diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/SlidingWindowDemo.vue b/docs/.vitepress/theme/components/appendix/context-engineering/SlidingWindowDemo.vue index 066d97c..000bfbc 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/SlidingWindowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/SlidingWindowDemo.vue @@ -15,15 +15,15 @@
- Window Size / 窗口大小 - {{ windowSize }} Messages + 窗口里最多能记住几条对话 + 最多 {{ windowSize }} 条
@@ -33,7 +33,7 @@
- 🗑️ Forgotten (History) + 🗑️ 已被遗忘的内容
- No history yet... + 这里暂时还没有被“挤出去”的对话
- ⬆ Out of Context + ⬆ 窗口外(模型已经看不到)
- ⬇ In Context + ⬇ 窗口内(模型还能看到)
- 🖼️ Active Context Window + 🖼️ 当前还在记忆里的对话
- Start the conversation... + 从这里开始聊天,看看旧对话是怎么被“挤出去”的
@@ -91,20 +91,20 @@

💡 - Note: - 滑动窗口是最简单的记忆管理策略。它保证了 Token 永远不会溢出,但代价是"健忘"。 - 一旦消息滑出窗口(进入上方灰色区域),模型就完全不知道它的存在了。 + 说明: + 滑动窗口是最简单的记忆管理方式:新的进来,旧的出去。 + 好处是永远不会“撑爆脑子”,代价就是——一旦滑出窗口(上面灰色区域),模型就完全忘了它存在过。

@@ -151,25 +151,25 @@ const addMessage = (role, content) => { const autoPlay = async () => { isAutoPlaying.value = true const script = [ - "Hello there!", - "Hi! I'm an AI assistant.", - "What is your name?", - "I am Model GPT-X.", - "Do you remember my first message?", - "Yes, you said 'Hello there!'.", - "Tell me a joke.", - "Why did the chicken cross the road?", - "To get to the other side!", - "Haha, classic.", - "Wait, what was my name again?", - "I... I don't remember. It fell out of my context window!" + '你好,我是张三。', + '你好呀,我是你的 AI 助手。', + '我今天有点累,帮我记录一下待办吧。', + '没问题,你可以把待办一条条发给我。', + '第一件事:给客户发邮件。', + '好的,已经记下来了。', + '第二件事:晚上去买菜做饭。', + '收到,也帮你记住了。', + '第三件事:记得给女朋友买花。', + '这条也帮你写在“小黑板”上了。', + '现在还记得我第一句话说了什么吗?', + '呃……我只看得到窗口里的几条,最早那句已经被挤出去了。' ] for (const line of script) { if (!isAutoPlaying.value) break const role = messages.value.length % 2 === 0 ? 'User' : 'AI' addMessage(role, line) - await new Promise(r => setTimeout(r, 1500)) + await new Promise((r) => setTimeout(r, 1500)) } isAutoPlaying.value = false } @@ -186,7 +186,7 @@ const reset = () => { border: 1px solid var(--vp-c-divider); border-radius: 8px; background-color: var(--vp-c-bg-soft); - padding: 1.5rem; + padding: 1rem; margin: 1rem 0; font-family: var(--vp-font-family-mono); } @@ -195,9 +195,9 @@ const reset = () => { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 1.5rem; + margin-bottom: 1rem; background: var(--vp-c-bg); - padding: 1rem; + padding: 0.75rem; border-radius: 6px; border: 1px solid var(--vp-c-divider); } @@ -245,10 +245,10 @@ const reset = () => { } .visualization-area { - margin-bottom: 1.5rem; + margin-bottom: 1rem; background: var(--vp-c-bg-alt); border-radius: 8px; - padding: 1rem; + padding: 0.75rem; border: 1px solid var(--vp-c-divider); } @@ -259,7 +259,7 @@ const reset = () => { } .zone { - padding: 1rem; + padding: 0.75rem; border-radius: 6px; transition: all 0.3s; } @@ -276,14 +276,14 @@ const reset = () => { border: 2px solid var(--vp-c-brand); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); margin-top: 0.5rem; - min-height: 150px; + min-height: 100px; } .zone-label { font-size: 0.8rem; font-weight: bold; color: var(--vp-c-text-2); - margin-bottom: 0.8rem; + margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.5rem; @@ -306,9 +306,9 @@ const reset = () => { .message-bubble { display: flex; - gap: 0.8rem; - margin-bottom: 0.8rem; - padding: 0.6rem; + gap: 0.5rem; + margin-bottom: 0.5rem; + padding: 0.5rem; border-radius: 6px; background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); @@ -334,9 +334,9 @@ const reset = () => { } .avatar { - font-size: 1.2rem; - width: 2rem; - height: 2rem; + font-size: 1rem; + width: 1.5rem; + height: 1.5rem; display: flex; align-items: center; justify-content: center; @@ -347,37 +347,37 @@ const reset = () => { .content { display: flex; flex-direction: column; - max-width: 80%; + max-width: 85%; } .role-name { - font-size: 0.7rem; + font-size: 0.65rem; color: var(--vp-c-text-3); - margin-bottom: 0.2rem; + margin-bottom: 0.1rem; } .text { - font-size: 0.9rem; - line-height: 1.4; + font-size: 0.85rem; + line-height: 1.3; } .empty-placeholder { text-align: center; color: var(--vp-c-text-3); font-style: italic; - padding: 1rem; - font-size: 0.9rem; + padding: 0.5rem; + font-size: 0.8rem; } .input-section { display: flex; gap: 0.5rem; - margin-bottom: 1rem; + margin-bottom: 0.75rem; } input { flex: 1; - padding: 0.75rem; + padding: 0.5rem; border: 1px solid var(--vp-c-divider); border-radius: 6px; background: var(--vp-c-bg); @@ -390,7 +390,7 @@ input:focus { } .send-btn { - padding: 0 1.5rem; + padding: 0 1rem; background: var(--vp-c-brand); color: white; border: none; @@ -398,6 +398,7 @@ input:focus { font-weight: bold; cursor: pointer; transition: background 0.2s; + font-size: 0.9rem; } .send-btn:hover { @@ -411,10 +412,10 @@ input:focus { .info-box { background-color: var(--vp-c-bg-alt); - padding: 1rem; + padding: 0.75rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.5; + font-size: 0.85rem; + line-height: 1.4; color: var(--vp-c-text-2); } diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue new file mode 100644 index 0000000..4a7a257 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue @@ -0,0 +1,506 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue new file mode 100644 index 0000000..01495e6 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue @@ -0,0 +1,724 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/HttpExchangeDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/HttpExchangeDemo.vue new file mode 100644 index 0000000..9be8441 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/HttpExchangeDemo.vue @@ -0,0 +1,533 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/TcpHandshakeDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/TcpHandshakeDemo.vue new file mode 100644 index 0000000..4cbdb9d --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/TcpHandshakeDemo.vue @@ -0,0 +1,551 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/UrlParserDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/UrlParserDemo.vue new file mode 100644 index 0000000..4463686 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/UrlParserDemo.vue @@ -0,0 +1,517 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/UrlToBrowserQuickStart.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/UrlToBrowserQuickStart.vue new file mode 100644 index 0000000..a069480 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/UrlToBrowserQuickStart.vue @@ -0,0 +1,914 @@ + + + + + + diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js index 24e3204..6a48e2e 100644 --- a/docs/.vitepress/theme/index.js +++ b/docs/.vitepress/theme/index.js @@ -215,11 +215,16 @@ import TrainingProcessDemo from './components/appendix/prompt-engineering/Traini // Context Engineering Components import AgentContextFlow from './components/appendix/context-engineering/AgentContextFlow.vue' +import IntroProblemReasonSolution from './components/appendix/context-engineering/IntroProblemReasonSolution.vue' import ContextWindowVisualizer from './components/appendix/context-engineering/ContextWindowVisualizer.vue' import SlidingWindowDemo from './components/appendix/context-engineering/SlidingWindowDemo.vue' import SelectiveContextDemo from './components/appendix/context-engineering/SelectiveContextDemo.vue' import RAGSimulationDemo from './components/appendix/context-engineering/RAGSimulationDemo.vue' import ContextCompressionDemo from './components/appendix/context-engineering/ContextCompressionDemo.vue' +import MemoryPalaceDemo from './components/appendix/context-engineering/MemoryPalaceDemo.vue' +import MemoryPalaceActionDemo from './components/appendix/context-engineering/MemoryPalaceActionDemo.vue' +import KVCacheDemo from './components/appendix/context-engineering/KVCacheDemo.vue' +import LostInMiddleDemo from './components/appendix/context-engineering/LostInMiddleDemo.vue' // Agent Intro Components import AgentWorkflowDemo from './components/appendix/agent-intro/AgentWorkflowDemo.vue' @@ -499,11 +504,16 @@ export default { // Context Engineering Components Registration app.component('AgentContextFlow', AgentContextFlow) + app.component('IntroProblemReasonSolution', IntroProblemReasonSolution) app.component('ContextWindowVisualizer', ContextWindowVisualizer) app.component('SlidingWindowDemo', SlidingWindowDemo) app.component('SelectiveContextDemo', SelectiveContextDemo) app.component('RAGSimulationDemo', RAGSimulationDemo) app.component('ContextCompressionDemo', ContextCompressionDemo) + app.component('MemoryPalaceDemo', MemoryPalaceDemo) + app.component('MemoryPalaceActionDemo', MemoryPalaceActionDemo) + app.component('KVCacheDemo', KVCacheDemo) + app.component('LostInMiddleDemo', LostInMiddleDemo) // Agent Intro Components Registration app.component('AgentWorkflowDemo', AgentWorkflowDemo) diff --git a/docs/ja-jp/stage-2/intro.md b/docs/ja-jp/stage-2/intro.md index 6934e93..c16017e 100644 --- a/docs/ja-jp/stage-2/intro.md +++ b/docs/ja-jp/stage-2/intro.md @@ -9,170 +9,142 @@ モダンなフロントエンド開発をマスターし、コンポーネントライブラリとデザインツールの使用方法を学ぶ: + +
+
+ 🖼️ + フロントエンド1 +
+
FigmaとMasterGo入門
+
+
+ +
+
+ + フロントエンド2 +
+
初めてのモダンアプリ - UIデザイン
+
+
+ + +
+
+ 📐 + フロントエンド3 +
+
UIデザインガイドラインとマルチプロダクト
+
+
+ + +
+
+ 🧙 + フロントエンド4 +
+
ホグワーツ肖像画を作ろう
+
+
-
Lovartで素材を作成
- - - - -
-
- 🖼️ - フロントエンド1 -
-
FigmaとMasterGo入門
-
-
- - -
-
- - フロントエンド2 -
-
初めてのモダンアプリ - UIデザイン
-
-
- - -
-
- 📐 - フロントエンド3 -
-
UIデザインガイドラインとマルチプロダクト
-
-
- - -
-
- 🧙 - フロントエンド4 -
-
ホグワーツ肖像画を作ろう
-
-
- - ### バックエンドとフルスタック API設計、データベース管理、アプリケーションデプロイメント戦略を学ぶ: + +
+
+ 🗄️ + バックエンド2 +
+
データベースからSupabaseへ
+
+
+ +
+
+ 🤖 + バックエンド3 +
+
AI支援インターフェースコードとドキュメント
+
+
+ + +
+
+ 🌿 + バックエンド4 +
+
Gitワークフロー
+
+
+ + +
+
+ 🚀 + バックエンド5 +
+
Zeaburデプロイメント
+
+
+ + +
+
+ 💻 + バックエンド6 +
+
モダンCLI開発ツール
+
+
+ + +
+
+ 💳 + バックエンド7 +
+
Stripe決済システムの統合
+
+
-
APIとは
- - - - -
-
- 🗄️ - バックエンド2 -
-
データベースからSupabaseへ
-
-
- - -
-
- 🤖 - バックエンド3 -
-
AI支援インターフェースコードとドキュメント
-
-
- - -
-
- 🌿 - バックエンド4 -
-
Gitワークフロー
-
-
- - -
-
- 🚀 - バックエンド5 -
-
Zeaburデプロイメント
-
-
- - -
-
- 💻 - バックエンド6 -
-
モダンCLI開発ツール
-
-
- - -
-
- 💳 - バックエンド7 -
-
Stripe決済システムの統合
-
-
- - ### 課題 実践プロジェクトを通じてフルスタック開発スキルを固める: - - -
初めてのモダンアプリ - フルスタック
- - - - -
- - - -
+ + ### AI機能拡張 - - -
Dify入門とナレッジベース統合
- - - - -
- - - -
+ + ## 対象者 @@ -200,42 +172,44 @@ API設計、データベース管理、アプリケーションデプロイメ .card-link { text-decoration: none; color: inherit; + display: block; } .content-card { + background: var(--vp-c-bg-soft); border: 1px solid var(--vp-c-divider); border-radius: 12px; - padding: 16px; + padding: 20px; transition: all 0.3s ease; - background: var(--vp-c-bg-soft); + height: 100%; } .content-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); border-color: var(--vp-c-brand); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .card-header { display: flex; align-items: center; - gap: 8px; - margin-bottom: 8px; + gap: 12px; + margin-bottom: 12px; } .card-icon { - font-size: 20px; + font-size: 24px; } .card-title { font-weight: 600; - color: var(--vp-c-brand); - font-size: 14px; + font-size: 16px; + color: var(--vp-c-text-1); } .card-desc { - color: var(--vp-c-text-2); font-size: 14px; + color: var(--vp-c-text-2); line-height: 1.5; } diff --git a/docs/zh-cn/appendix/ai-capability-dictionary.md b/docs/zh-cn/appendix/ai-capability-dictionary.md index 6d03121..831b074 100644 --- a/docs/zh-cn/appendix/ai-capability-dictionary.md +++ b/docs/zh-cn/appendix/ai-capability-dictionary.md @@ -50,7 +50,7 @@ > - OpenAI 系列:GPT-4、GPT-4.1、GPT-4o、GPT-5.1 等 > - Google 系列:Gemini 1.5 Pro、Gemini 1.5 Flash 等 > - Anthropic 系列:Claude 3.5 Sonnet、Claude 3.5 Haiku 等 -> - 国内模型:通义千问 Qwen 系列、文心一言 ERNIE Bot 系列、GLM/智谱清言、百度的文心大模型家族、腾讯混元、讯飞星火、月之暗面的 Kimi 背后的大模型等 +> - 国内模型:通义千问 Qwen 系列、文心一言 ERNIE Bot 系列、GLM/智谱清言、腾讯混元、讯飞星火、月之暗面的 Kimi 背后的大模型等 > > 更偏视觉和视频方向的大模型和服务,包括: > diff --git a/docs/zh-cn/appendix/audio-intro.md b/docs/zh-cn/appendix/audio-intro.md index af1d57a..929dc8c 100644 --- a/docs/zh-cn/appendix/audio-intro.md +++ b/docs/zh-cn/appendix/audio-intro.md @@ -2,6 +2,16 @@ > 💡 **学习指南**:声音是空气的振动,也是情感的载体。本章节将带你了解 AI 如何"听懂"声音,又是如何像人一样"开口说话"甚至"作曲"的。从语音识别到音乐生成,探索音频 AI 的完整技术栈。 + + ## 0. 快速上手:如何让 AI 说话? ### 0.1 常见的 AI 音频工具 @@ -38,6 +48,8 @@ - **场景**:开车、做饭、运动时,打字不方便,但说话很容易。 - **未来**:AI 助手将通过语音成为我们的自然伙伴。 + + ## 1. 概念界定:音频的数字化 (Definition) _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字化的音频信号**。_ @@ -49,8 +61,6 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 - **传统信号处理**:处理原始波形(WAV 文件)。 - **AI 音频模型**:处理更有意义的"中间表示"。 - - 本质上,音频 AI 是一个**从物理信号到语义表示**的转换过程: - **物理层**:声波振动(模拟信号) @@ -96,7 +106,7 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 2. **生成**:用图像生成模型(如 CNN、Diffusion)生成频谱图。 3. **还原**:通过**声码器 (Vocoder)** 将频谱图还原为音频波形。 - + **代表模型**:Tacotron 2, FastSpeech, F5-TTS @@ -133,11 +143,102 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 这让 AI 更关注人耳敏感的部分,忽略不重要的细节。 -## 4. 生成机制:从 GPT 到 Flow (Generation Methods) +## 4. TTS 流程全景 (TTS Pipeline) + +文本转语音(TTS)是音频 AI 最核心的应用之一。让我们深入了解其完整流程。 + + + +### 4.1 自回归 vs 非自回归 + +| 特性 | 自回归 (AR) | 非自回归 (NAR) | 流匹配 (Flow) | +|------|------------|---------------|--------------| +| 生成方式 | 逐个时间步 | 一次性生成 | 流匹配路径 | +| 速度 | 慢 | 快 | 很快 | +| 音质 | 高 | 中高 | 高 | +| 代表模型 | Tacotron 2 | FastSpeech 2 | F5-TTS | + +### 4.2 关键组件 + +1. **文本前端 (Text Frontend)**:将文本转换为音素序列,处理多音字、数字、缩写等。 +2. **声学模型 (Acoustic Model)**:将音素转换为声学特征(梅尔频谱)。 +3. **声码器 (Vocoder)**:将声学特征还原为音频波形。 + +## 5. ASR 与 TTS:语音的双向转换 (ASR vs TTS) + +语音识别(ASR)和语音合成(TTS)是音频 AI 的两个核心方向,它们互为逆过程。 + + + +### 5.1 ASR:音频 → 文本 + +- **输入**:音频波形 +- **输出**:文本/Token +- **核心任务**:模式识别、分类 +- **代表模型**:Whisper, Conformer + +### 5.2 TTS:文本 → 音频 + +- **输入**:文本序列 +- **输出**:音频波形 +- **核心任务**:序列生成、回归 +- **代表模型**:F5-TTS, CosyVoice + +### 5.3 联合应用 + +- **语音助手**:ASR → LLM → TTS +- **实时翻译**:ASR → 翻译 → TTS +- **字幕生成**:视频 → ASR → 字幕 + +## 6. 声音克隆:零样本能力的魔法 (Zero-Shot Voice Cloning) + +早期的 TTS 需要几十小时的数据来训练一个声音。现在,我们只需要几秒钟。 + + + +### 6.1 声音编码器 (Speaker Encoder) + +声音编码器是一个神经网络,它的任务是:**把一段音频压缩成一个固定长度的向量(Embedding)**。 + +这个向量捕捉了声音的"身份": + +- 音色(低沉 vs 清脆) +- 声道特征(男声 vs 女声) +- 说话风格(语速、停顿习惯) + +### 6.2 零样本合成流程 + +有了声音编码器,我们就能实现"一句话克隆": + +1. **提取声音特征**:参考音频 → 声音编码器 → 声音向量(如 256 维) +2. **条件生成**:文本 + 声音向量 → TTS 模型 → 音频 + +这就是 ElevenLabs、CosyVoice 等工具的核心技术。 + +## 7. 情感与风格控制 (Emotion & Style Control) + +现代 TTS 系统不仅能合成自然的语音,还能精确控制情感、语速、语调等风格特征。 + + + +### 7.1 全局风格 Token (GST) + +GST (Global Style Token) 是一种从参考音频中提取风格特征的方法。模型学习将情感、语速、语调等风格信息编码成一组 Token,在推理时可以通过选择或插值这些 Token 来控制合成风格。 + +### 7.2 细粒度控制 + +现代 TTS 模型支持细粒度的风格控制: + +- **速度控制**:调整音频播放速度而不改变音调 +- **音调控制**:改变基频 (F0) 曲线 +- **能量控制**:调整音量包络 +- **停顿控制**:调整句间和短语间的停顿长度 + +## 8. 生成机制演进 (Generation Evolution) 音频生成模型经历了从模仿人类到直接建模的演进。 -### 4.1 Audio Language Model (如 VALL-E, AudioLM) +### 8.1 Audio Language Model (如 VALL-E, AudioLM) 这一派的思想是:**把声音当语言学**。 @@ -145,8 +246,6 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 - **输入**:文本 Token + 音频 Token - **预测**:像成语接龙一样,根据前面的声音,预测下一个声音 Token。 - - **优点**: - 能学到非常自然的韵律、停顿和情感 @@ -157,7 +256,7 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 - 容易"胡言乱语"(重复、漏词) - 生成速度慢(必须逐个 Token 生成) -### 4.2 Flow Matching TTS (如 F5-TTS, CosyVoice, Matcha-TTS) +### 8.2 Flow Matching TTS (如 F5-TTS, CosyVoice, Matcha-TTS) 这是目前最前沿的流派,结合了生成模型的最新进展。 @@ -173,36 +272,14 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 - **鲁棒性强**:不容易丢字漏字 - **零样本克隆**:给一段几秒钟的参考音频,立马就能模仿它的音色和语调 -## 5. 声音克隆:零样本能力的魔法 (Zero-Shot Voice Cloning) - -早期的 TTS 需要几十小时的数据来训练一个声音。现在,我们只需要几秒钟。 - -### 5.1 声音编码器 (Speaker Encoder) - -声音编码器是一个神经网络,它的任务是:**把一段音频压缩成一个固定长度的向量(Embedding)**。 - -这个向量捕捉了声音的"身份": - -- 音色(低沉 vs 清脆) -- 声道特征(男声 vs 女声) -- 说话风格(语速、停顿习惯) - -### 5.2 零样本合成流程 - -有了声音编码器,我们就能实现"一句话克隆": - -1. **提取声音特征**:参考音频 → 声音编码器 → 声音向量(如 256 维) -2. **条件生成**:文本 + 声音向量 → TTS 模型 → 音频 - -这就是 ElevenLabs、CosyVoice 等工具的核心技术。 - -## 6. 总结 (Summary) +## 9. 总结 (Summary) 音频 AI 的进化,正在从"信号处理"走向"语义理解"。 - **Tokenization** 把声音变成了语言,让 GPT 能"开口说话"。 - **Flow Matching** 把生成速度提升了数十倍,让实时语音合成成为可能。 - **Speaker Encoder** 让声音克隆像换皮肤一样简单。 +- **Emotion Control** 让 AI 语音充满情感,适应各种场景。 未来的 AI(如 GPT-4o),将不再需要把声音转成文字再转回去,而是**直接在统一的多模态空间里理解声音的笑声、语气和情绪**。 @@ -218,3 +295,5 @@ _很多人以为 AI 直接处理"声音",但实际上 AI 处理的是**数字 | **零样本克隆** | Zero-Shot Cloning | 只需几秒参考音频就能模仿任何声音。 | | **流匹配** | Flow Matching | 一种高效的生成方法,用于最新的 TTS 模型。 | | **声音编码器** | Speaker Encoder | 提取声音身份特征的神经网络。 | +| **GST** | Global Style Token | 全局风格 Token,用于情感控制。 | +| **神经编解码器**| Neural Codec | 将音频压缩为离散 Token 的模型。 | diff --git a/docs/zh-cn/appendix/context-engineering.md b/docs/zh-cn/appendix/context-engineering.md index 824064b..3fc3b2e 100644 --- a/docs/zh-cn/appendix/context-engineering.md +++ b/docs/zh-cn/appendix/context-engineering.md @@ -1,165 +1,479 @@ # 上下文工程入门 (Context Engineering) -> 💡 **学习指南**:如果说 Prompt Engineering 是教 AI "怎么说话",那么 Context Engineering 就是教 AI "怎么记事"。本章节将通过一系列交互式实验,带你深入理解 AI 的记忆机制,从基础的滑动窗口到高级的 RAG 系统,掌握让 AI "过目不忘"的核心技术。 +> 💡 **学习指南**:提示词工程解决的是“怎么把话说清楚”,上下文工程解决的是“让模型在合适的时刻看到合适的信息”。本章节会围绕一个问题展开:**在有限的上下文窗口里,如何既让模型懂你,又不把钱烧光?** -在开始之前,建议你先了解两个概念: +在开始之前,建议你先补两块“基础砖”: - **Token 是什么**:可以先阅读 [大语言模型入门](./llm-intro.md) 的「分词 & Token」部分。 - **Prompt 是什么**:如果你还不熟悉 System / User / Assistant 的基本结构,可以先看 [提示词工程](./prompt-engineering/)。 - +--- -## 0. 引言:金鱼与大象 +## 0. 引言:为什么聊着聊着,它就忘事,还越来越贵? -想象一下,你正在和两个人聊天: +很多人在实际使用大模型时都会遇到类似的情况: -- **A (金鱼记忆)**:只能记住最后说的 3 句话。如果你问他"我刚才说了什么?",他可能会一脸茫然。 -- **B (大象记忆)**:能记住你们聊过的每一句话,甚至是你上个月提到的细节。 +- 聊到一半,模型突然“忘记”之前说过的关键条件; +- 长对话里,前后回答自相矛盾,很难保持同一套设定; +- 对话轮次一多,账单像打车计价一样不断往上走。 -**上下文工程 (Context Engineering)** 的目标,就是通过技术手段,让 AI 从 "金鱼" 进化成 "大象"。 +直觉上,我们会以为是:**“这个模型记性不好”**。 +但大多数时候,问题并不在于模型“不会记”,而在于我们**没有设计好它能看到的上下文**。 -更具体地说:你每次调用模型时,都会把一份「输入包」发给它,这份输入包通常由这些部分拼起来: + -- **系统设定**(System Prompt):角色、规则、边界。 -- **对话历史**(Messages):你们之前聊过什么。 -- **工具结果**(Tool / Observation):Agent 调用外部工具拿到的新信息。 -- **检索片段**(RAG Context):从知识库临时取回的相关内容。 - -但这里有一个核心挑战:**AI 的"脑容量"(上下文窗口)是有限的**。我们不能把全世界的信息都塞进去。 - -我们需要解决五个核心问题: - -1. **容量限制**:到底能装多少东西? -2. **遗忘机制**:装满了怎么办? -3. **智能保留**:如何只忘掉不重要的? -4. **长期记忆**:怎么记住很久以前的事? -5. **信息压缩**:怎么把书读薄? +面对这些挑战,单纯依靠“写好提示词”已经捉襟见肘。我们需要一套更系统的工程方法,来在有限的窗口和预算内,让模型始终获得最关键的信息。这正是**上下文工程**试图解决的问题。 --- -## 1. 第一步:理解瓶颈 (The Context Window) +## 1. 什么是“上下文工程”?(定义 + 场景) -### 1.1 什么是上下文窗口? +先给一个简短的工作定义,再看几个典型场景。 -大语言模型 (LLM) 的记忆不是无限的。它有一个固定的**上下文窗口 (Context Window)**,就像一个只能写 1000 个字的黑板。一旦写满,要么擦掉旧的,要么停止写入。 +> 上下文工程,是一门为 LLM 构建和管理“信息环境”的工程方法,决定模型“看到什么、忽略什么、什么时候看到”,从而在有限的上下文窗口内稳定完成任务。 -### 1.2 实验:Token 与容量 +你可以简单地把它理解成三件事:整理信息、控制窗口、管理成本。 +常见会用到它的场景包括: -在 AI 的世界里,计量的单位不是"字",而是 **Token**。(Token 的更完整解释可以回看 [大语言模型入门](./llm-intro.md)。) -粗略地说,一个 Token 大约相当于 0.75 个英文单词,或 0.5-1 个汉字(会因内容而变化)。 +- 对话型 Agent 和客服机器人 +- 代码 / 文档助手 +- 多轮工具调用和长流程编排 -试着在下面的模拟器中输入文字,看看它是如何填满上下文窗口的: +接下来,我们就从一个真实团队的“血泪教训”出发,看看他们是怎么一点点从“只会写 Prompt”进化到“会做上下文工程”的。 + +--- + +## 2. 从"血泪教训"说起:Manus 团队踩过的坑 + +本章案例来自 **Manus**(一款通用 AI Agent)。 +与普通对话不同,Manus 需要自主规划并调用工具完成长任务(涉及几十甚至上百轮交互)。 + +这带来了核心矛盾: +- **如果不记**:关键信息丢失,任务中断。 +- **全记**:成本和延迟爆炸,甚至超出窗口限制。 + +Manus 团队经历过多次架构重构,才明白一个道理:**上下文不能只靠“写”,而要靠“设计”。** + +### 2.1 四次重构教会我们什么? + +Manus 的联合创始人季逸超分享过他们的"踩坑史": + +| 阶段 | 遇到的问题 | 当时的想法 | 结果 | +| :--- | :--- | :--- | :--- | +| **第一次** | AI 聊着聊着就忘事 | "多写点提示词就好了" | 越写越长,越写越贵 | +| **第二次** | 重要信息总被挤掉 | "把重要的多复制几遍" | 文本更长,成本更高 | +| **第三次** | 账单高得吓人 | "能不能复用之前的计算?" | 找到降低重复计算成本的方式 | +| **第四次** | 长文档处理不了 | "能不能需要时再查?" | 建立“图书馆+按需检索”的方案 | + +**核心领悟**:**不是记得越多越好,而是记得越巧越好**。 + +### 2.2 AI 的"记性"到底像什么? + +**传统电脑内存** = **硬盘**: +- 容量大:可以长期保存大量数据; +- 价格低:存放一年成本较低; +- 读写速度相对较慢,查找信息需要一定时间。 + +**AI 的上下文** = **小黑板**: +- 读写快:模型可以在一次调用中直接看到全部上下文; +- 容量有限:写满后不得不擦除旧内容; +- 每写入一个 token 都会带来额外计算与费用。 + +**Manus 的经验**:**小黑板要用得省,用得巧,别用来存百科全书**。 + +--- + +## 3. 第一步:认识成本 - 你的每一分钱花在哪? + +### 3.1 为什么要先看成本? + +让我们看看一次典型的 AI 对话,你的钱是怎么花的: + +``` +💰 成本构成(一次对话): +├─ 70% 重复看旧内容("刚才聊了什么?") +├─ 20% 处理新内容("现在说什么?") +└─ 10% 生成回复("怎么回答?") +``` + +**惊人发现**:**70% 的钱花在让 AI 重新看你之前说过的话!** + +### 3.2 什么是 KV Cache?(前缀复用) + +在讨论价格之前,我们得先搞懂一个核心技术概念:**KV Cache(键值缓存)**。 +别被这个技术名词吓到,它其实就是 AI 的“短期记忆速查表”。 + +- **没有 KV Cache 时**:AI 每次都要像第一次看到这篇文章一样,从第一个字开始重新阅读、理解、计算。 +- **有了 KV Cache 时**:AI 会把看过的部分(Pre-fill)计算结果存下来。下次如果开头的内容没变,它就直接调取记忆,不用重新算了。 + +这就好比: +> 你去考场考试。 +> **情况 A**:每次都要把整本教材从头读一遍,再开始答题。(慢、累、贵) +> **情况 B**:教材内容你已经背滚瓜烂熟了(Cache),坐下直接答题。(快、轻松、便宜) + +在云厂商的计费表里,**“背过的书”(Cache Hit)**通常比**“新看的书”(Cache Miss)**便宜 90% 以上。 + +### 3.3 "背课文" vs "现查现用"的价格差 + +以 Claude 为例: +- **现查现用**(没缓存):$3.00 / 百万字 +- **背过再用**(有缓存):$0.30 / 百万字 +- **相差 10 倍**! + +**Manus 的实践**:通过让 AI "背课文",他们把成本从 **$0.15 降到 $0.02**,**省了 87%**! -**关键点**: +### 3.4 避坑指南:别让时间戳毁了你的“缓存” -- **溢出即丢失**:一旦超过红色警戒线,模型可能会报错,或者直接截断后面的内容。 -- **昂贵的记忆**:上下文越长,推理速度越慢,费用也越高。 +很多开发者习惯把“当前时间”写在 System Prompt 的第一句,觉得这样很严谨。 +**但这其实是上下文工程中最大的反模式之一。** -### 1.3 额外收益:前缀稳定与缓存命中 +想象一下:你背了一整本历史书(System Prompt),结果书的第一行写的是“现在的秒数”。 +如果这行字每秒都在变,那你上一秒背的所有内容,下一秒就全废了——你得从头再背一遍。 -在 Agent 场景里,上下文通常是「系统设定 + 工具定义 + 历史消息 + 本轮新信息」的拼接。 -如果你能让这份输入包的**前半段尽量稳定**(比如系统提示、工具列表不要频繁变动),很多模型/服务会更容易复用缓存,从而降低延迟与成本。 +这就是**前缀复用(KV Cache)**的死穴:**只要开头变了,后面全都要重算。** + +#### 错误示范:把动态信息放前面 +```text +System: 现在是 2024-01-01 12:00:01。你是助手... +(一分钟后) +System: 现在是 2024-01-01 12:01:01。你是助手... +``` +**后果**:虽然只变了几个字,但因为在开头,导致后续 99% 的固定内容无法复用缓存,每次请求都像第一次一样慢且贵。 + +#### 正确姿势:动静分离 +```text +System: 你是助手... (这里放几千字的固定规则、知识库) +User: (在这里通过工具调用或用户消息传入当前时间) +``` +**好处**:前面的几千字规则永远不变,AI 只需要“背”一次。后续请求直接调用记忆,速度极快。 + +👇 **动手点点看**: +点击下方的开关,开启**“背课文加速”**,然后多次点击“发送新请求”。 +观察一下:当第一块内容变成“已背过”时,**开口速度(TTFT)**会发生什么变化? + + --- -## 2. 第二步:即时记忆 (Sliding Window) +## 4. 第二步:滑动窗口 - 当"记性"变成"成本" -### 2.1 问题:聊久了就忘 +随着对话越来越长,最先遇到的问题就是:**窗口满了怎么办?** -当对话持续进行,Token 数量不断增加,最终会通过窗口限制。最简单的处理方式是**滑动窗口 (Sliding Window)**。 +### 4.1 为什么“先进先出”会出问题? -### 2.2 解决方案:先进先出 (FIFO) +最简单的记忆管理是**滑动窗口(Sliding Window)**:**新的进来,旧的出去**。 +这听起来很公平,但在实际任务中却是个灾难。 -就像一个滑动的相框,当新消息进来时,最旧的消息被"挤"出画面,被彻底遗忘。 +**场景重现**: +```text +对话记录: +[1] 用户:我是张三,负责支付系统 +[2] 用户:项目用 Go 语言开发 +[3] 用户:数据库是 PostgreSQL +... +[20] 用户:帮我写个接口 +``` +**结果**:当聊到第 20 句时,第 1 句“我是张三”已经被挤出了窗口。AI 彻底忘了你是谁,也不知道你在负责什么系统。 + +**问题本质**:这种策略把**重要信息**(身份、技术栈)和**废话**(“好的”、“收到”)同等对待,一起被踢了出去。 + +### 4.2 "中间失忆症" - 为什么 AI 总看不到关键信息? + +除了“忘得快”,AI 还有一个怪癖:**它也会“看漏”**。 +研究发现:**AI 对开头和结尾最敏感,中间最容易被忽略**。这就是著名的 **Lost in the Middle(中间迷失)**现象。 + +**U 型记忆曲线**: +```text +位置:开头 → 中间 → 结尾 +记忆: 高 → 低 → 高 +``` + +👇 **动手点点看**: +1. 先试试**“滑动窗口”**:在下面的聊天框里多发几条消息,看看旧的对话是怎么被无情“挤出去”的。 +2. 再看看**“中间迷失”**:观察一下,当关键信息藏在整段话的中间位置时,检索成功率是不是最低的? + -**观察**: - -- 当对话填满窗口后,最早的 `User` 消息变灰并消失。 -- **缺陷**:如果我在第一句话里告诉 AI "我的名字叫小明",几轮对话后,它就忘了我叫什么。 +**解决方案**:把关键信息放在**开头**(系统提示)或**结尾**(用户问题)。 --- -## 3. 第三步:智能管理 (Selective Retention) +## 5. 第三步:选择性保留 - 如何"钉"住关键信息? -### 3.1 问题:重要的事不能忘 +既然“先进先出”不靠谱,那我们该怎么办? +Manus 的答案是:**建立“信息等级制度”**。 -"滑动窗口"太笨了,它平等地对待每一句话。但有些信息(如你的名字、任务目标、系统设定)是**全局重要**的,无论对话多长都不能忘。 +### 5.1 为什么要给信息分等级? -### 3.2 解决方案:选择性保留 (Smart Context) +不再平等对待每条信息,而是根据重要程度决定它们的去留: -我们需要一种机制,将关键信息**钉 (Pin)** 在窗口里,不受滑动影响。这通常通过 `System Prompt` 或动态注入来实现。 +| 等级 | 信息类型 | 待遇 | 成本影响 | +| :--- | :--- | :--- | :--- | +| **VIP** | 系统设定、用户身份 | **永远保留** | +15% 成本 | +| **重要** | 当前任务目标 | **任务期内保留** | +10% 成本 | +| **一般** | 普通对话历史 | **最近 5 轮保留** | 基准成本 | +| **可弃** | 可检索的知识 | **用时再查** | -60% 成本 | + +**核心思想**:**用 25% 的成本增加,换取 90% 的关键信息保留**。 + +### 5.2 "钉钉子"策略 + +你可以把上下文窗口想象成一面黑板: +- **VIP 信息**:用钉子死死**钉在**黑板最上面(System Prompt)。 +- **重要信息**:用磁铁**吸在**黑板中间(Context Injection)。 +- **普通对话**:写在黑板下半部分,满了就擦掉旧的(Sliding Window)。 + +👇 **动手点点看**: +试着在下面的演示里,把某条重要的对话“钉”住。 +观察一下:当你继续聊天时,被钉住的信息是不是一直都在,而没钉住的就被挤走了? -**实验指南**: - -1. 观察顶部的 **📌 Pinned** 区域,这里的信息永远不会被挤走。 -2. 在下方添加新消息,注意观察 **📜 Scrolling** 区域的变化。 -3. 尝试点击某条消息旁边的 📌 按钮,把它变成"永久记忆"。 - -**原理**:我们牺牲了一部分流动窗口的空间,换取了关键信息的持久性。 - --- -## 4. 第四步:长期记忆 (RAG & Vector DB) +## 6. 第四步:RAG - 当"记性"需要"图书馆" -### 4.1 问题:如何记住一本书? +有时候,我们要处理的信息太多了(比如几百页的技术文档),黑板根本写不下。这时候就需要外挂大脑——**RAG(检索增强生成)**。 -如果我们需要 AI 记住几百页的技术文档,或者你过去一年的日记,即使是 "Pinned" 也装不下(窗口太贵且有限)。 +### 6.1 为什么“小黑板”不够用? -### 4.2 解决方案:外挂大脑 (RAG) +Manus 面对百万字级的技术文档时,对比了两种做法: -**检索增强生成 (RAG, Retrieval-Augmented Generation)** 是目前的终极解决方案。我们不把所有记忆都塞进大脑,而是把它们写在"笔记本"(向量数据库)里。 +1. **全量写入**:所有内容一次性塞进上下文。 + * **后果**:黑板瞬间被占满,处理极慢,而且根据“中间迷失”理论,AI 根本记不住中间的内容。 + * **成本**:约 $50/次,等待 15 秒。 +2. **按需检索(RAG)**:先去图书馆(数据库)查,只把相关的几段话抄到黑板上。 + * **后果**:黑板很清爽,AI 聚焦于关键信息。 + * **成本**:约 $0.5/次,等待 2 秒。 -当需要回答问题时,先去笔记本里**检索**相关的那一页,临时读入大脑。 +**省了 99% 的钱,87% 的时间!** + +### 6.2 "查资料"的最佳实践 + +Manus 的经验总结: +* **每本书撕成多大片?** 500-1000 字效果最好。 +* **一次查几本书?** 3-5 本,多了反而干扰。 +* **多相关的书才查?** 相似度 > 0.7,避免“硬凑”不相关的内容。 + +👇 **动手点点看**: +在搜索框里输入问题(比如“如何重置密码”),看看系统是如何从一大堆文档里只找出最相关的那几条的。 -**流程解析**: - -1. **Embedding**:将你的问题变成数学向量。 -2. **Search**:在数据库中寻找"长得像"(语义相似)的片段。 -3. **Retrieve**:只把那 2-3 个相关片段取出来。 -4. **Augment**:把这些片段和你的问题一起塞进 Prompt。 - -这样,AI 就能回答它从未"背过"的知识了。 - --- -## 5. 第五步:信息压缩 (Compression) +## 7. 第五步:压缩 - 如何让"小黑板"写得更密? -### 5.1 问题:检索出来的内容还是太长 +如果信息都很重要,实在删不掉,又不想查资料怎么办? +那就只能**把字写小点**——这就是**上下文压缩**。 -有时候,即使检索出的相关片段也太长了。我们需要一种方法,在保留核心含义的前提下,减少 Token 消耗。 +### 7.1 什么时候需要"缩写"? +* 检索回来的资料太厚(>2000 字)。 +* 对话历史太啰嗦(占了 >80% 黑板空间)。 +* 需要快速回答,不想让 AI 读长篇大论。 -### 5.2 解决方案:上下文压缩 +### 7.2 "缩写"的三种境界 -我们可以用更小的模型,或者专门的算法,对文本进行压缩。 +| 压缩方式 | 压缩率 | 保留什么 | 适用场景 | 省钱效果 | +| :--- | :--- | :--- | :--- | :--- | +| **总结式** | 70% | 主要意思 | 快速了解 | 省 30% | +| **要点式** | 50% | 关键要点 | 结构化输出 | 省 50% | +| **表格式** | 30% | 核心数据 | 程序处理 | 省 70% | + +👇 **动手点点看**: +选择不同的压缩策略,看看长篇大论是如何变短、变精炼的。 -**常见策略**: +--- -- **Summarize**:用自然语言总结大意。适合理解整体脉络。 -- **Extract Key Points**:提取要点列表。适合逻辑性强的内容。 -- **JSON Structure**:提取结构化数据。适合程序处理。 +## 8. 系统整合:打造 AI 的“记忆宫殿” + +前面我们像搭积木一样,学习了各种独立的策略: +* **KV Cache**:帮我们省钱(第 3 章) +* **滑动窗口**:帮我们腾位置(第 4 章) +* **分级保留**:帮我们留重点(第 5 章) +* **RAG**:帮我们开外挂(第 6 章) + +现在,是时候把这些积木搭成一座完整的城堡了——我们称之为 Manus 的**“记忆宫殿”**。 + +### 8.1 像盖房子一样组装上下文 + +不要把上下文看作一堆乱糟糟的文字,而要把它看作一座分层的建筑。每一层都有它独特的功能和“居住规则”。 + +👇 **动手点点看**: +点击“开始建造”,看看我们是如何一层层把这座宫殿盖起来的。 + + + +### 8.2 为什么这样设计最强? + +这座宫殿的设计哲学,其实就为了解决三个矛盾: + +1. **地基(System Prompt)—— 解决“贵”的问题** + * **矛盾**:系统设定(你是谁、规则是什么)最长,每次都要发。 + * **解法**:把它放在最底层,利用 **KV Cache** 技术,只要不改动,AI 就能“背诵全文”。后续几百轮对话,这部分的计算成本几乎为 **0**。 + +2. **支柱(Task Context)—— 解决“忘”的问题** + * **矛盾**:对话一长,AI 容易忘了最初的任务目标(比如“写一个贪吃蛇游戏”)。 + * **解法**:利用**分级保留**策略,把任务目标“钉”在第二层。不管聊了多少轮,这层永远不删,确保 AI 不忘初心。 + +3. **顶层(Chat & RAG)—— 解决“乱”的问题** + * **矛盾**:又有新对话,又有查到的资料,混在一起容易晕。 + * **解法**: + * **客厅(对话)**:用**滑动窗口**管理,只留最近 5-10 句热乎的。 + * **图书馆(RAG)**:资料用完即走,不占地方。 + +### 8.3 实战效果 + +Manus 团队把这套架构搬上线后,效果立竿见影: + +* **省钱了**:因为地基被“背”下来了,每轮对话的成本暴跌 **84%**。 +* **变快了**:AI 不用每次都从头读几千字,平均响应时间从 8 秒缩短到 **2 秒**。 +* **更准了**:关键信息被“钉”死,再也不会聊着聊着就忘了自己是干嘛的。 --- -## 6. 总结:构建 AI 的记忆宫殿 +## 9. 实战模板:直接抄作业 -上下文工程不仅仅是简单的"拼接字符串",它是一个精密的系统工程: +为了让你更直观地理解这套机制是如何运作的,我们为你准备了**全链路模拟**。 -| 阶段 | 核心技术 | 适用场景 | 类比 | -| :----------- | :----------- | :----------------- | :------------------ | -| **L1. 限制** | Token 计数 | 了解边界 | 黑板的大小 | -| **L2. 短期** | 滑动窗口 | 日常闲聊 | 只能记 3 句话的金鱼 | -| **L3. 关键** | 选择性保留 | 角色扮演、任务设定 | 手心写字的备忘录 | -| **L4. 长期** | RAG / 向量库 | 知识库问答 | 随时查阅的图书馆 | -| **L5. 优化** | 压缩 / 摘要 | 降低成本、提速 | 读书笔记 | +请选择一个场景,点击“下一步”,看看从用户发问到 AI 回答的几秒钟内,**记忆宫殿**是如何动态调取、组装和清理上下文的。 -掌握了这些,你就掌握了控制 AI "注意力"的钥匙。现在,去构建属于你的长记忆 AI 应用吧! + + +### 📝 拿来即用的实战设计 + +如果你要设计一个类似 Manus 的系统,不要只盯着 Prompt 怎么写,更要关注**系统架构如何调度上下文**。 + +以下是两个经典场景的**系统设计蓝图**,包含了**提示词设计**和**代码逻辑(伪代码)**。 + +#### 场景 1:全栈工程师 Agent(长程记忆型) +> **核心挑战**:任务周期长,容易忘了最初的需求和项目背景。 +> **解决策略**:System 层(身份)+ Task 层(钉死目标)+ Chat 层(滑动窗口)。 + +**1. 系统提示词 (Layer 1 & 2)** +```markdown +# Layer 1: 身份设定 (System Prompt) - 永远不变,利用 KV Cache +你是一名资深的全栈工程师,精通 Python 和 Vue3。 +代码风格: +- 变量命名严格遵守 PEP8 +- 关键逻辑必须包含注释 +- 优先使用项目已有的工具函数 + +# Layer 2: 任务锁定 (Task Context) - 任务期间不许删 +当前任务:重构支付模块 (payment_module) +核心约束: +1. 必须兼容旧版 API 接口 v1.0 +2. 数据库迁移脚本必须是幂等的 +3. 截止时间:本周五 +``` + +**2. 上下文组装逻辑 (Pseudo-Code)** +```python +def build_engineer_context(user_input, chat_history, task_info): + context = [] + + # 1. 地基层:身份设定 (利用 KV Cache 缓存) + # 这部分内容几百轮对话都不变,计算成本几乎为 0 + context.append(SYSTEM_PROMPT) + + # 2. 支柱层:任务锁定 (Pinned) + # 无论对话多长,这部分永远插入在 System 之后 + context.append(f"当前任务:{task_info}") + + # 3. 检索层:代码片段 (RAG) + # 根据用户的问题,去代码库里找相关的代码 + relevant_code = search_codebase(user_input) + if relevant_code: + context.append(f"参考代码:\n{relevant_code}") + + # 4. 交互层:对话历史 (Sliding Window) + # 只取最近 10 轮,避免撑爆上下文 + recent_chat = chat_history[-10:] + context.extend(recent_chat) + + # 5. 最新输入 + context.append(user_input) + + return context +``` + +#### 场景 2:智能客服 Agent(精准问答型) +> **核心挑战**:成本敏感,且绝对不能胡说八道。 +> **解决策略**:System 层(强约束)+ RAG 层(动态注入)。 + +**1. 系统提示词 (Layer 1)** +```markdown +# Layer 1: 身份设定 (System Prompt) +你是一名专业的电商客服专员。 +回复原则: +1. 语气温柔、专业、简洁 +2. **绝对禁止**编造事实,只根据[参考资料]回答 +3. 如果资料里没有答案,请直接回答“非常抱歉,这个问题我需要转接人工客服” +``` + +**2. 上下文组装逻辑 (Pseudo-Code)** +```python +def build_support_context(user_input): + context = [] + + # 1. 地基层:身份设定 + context.append(SYSTEM_PROMPT) + + # 2. 图书馆层:动态检索 (RAG) + # 只有客服场景,RAG 才是主角,放在中间位置 + docs = vector_db.search(user_input, top_k=3) + + context.append("【参考资料开始】") + for doc in docs: + context.append(doc.content) + context.append("【参考资料结束】") + + # 3. 交互层:极短的历史 + # 客服通常不需要太久远的记忆,保留最近 3 轮即可 + context.extend(get_recent_chat(limit=3)) + + context.append(user_input) + + return context +``` + +--- + +## 10. 名词对照表 + +| 英文术语 | 中文对照 | 解释 | +| :--- | :--- | :--- | +| **Context Window** | 上下文窗口 | 模型一次性能够处理的文本最大长度(包括输入和输出)。超出限制的内容会被截断或遗忘。 | +| **Token** | 词元 | LLM 处理文本的最小单位。通常 1 个 Token 约等于 0.75 个英文单词或 0.5 个汉字。计费和窗口限制都以此为单位。 | +| **KV Cache** | KV 缓存 | 一种推理加速技术,通过缓存已经计算过的注意力键值对,避免对重复前缀进行重复计算,显著降低延迟和成本。 | +| **RAG** | 检索增强生成 | 在回答问题前,先从外部知识库检索相关信息,作为上下文提供给模型,以减少幻觉并扩展知识边界。 | +| **Sliding Window** | 滑动窗口 | 最基础的上下文管理策略。保持窗口内 Token 数量恒定,当新内容进入时,自动移除最早的旧内容。 | +| **Lost in Middle** | 中间迷失 | 大模型的一种局限性。研究表明,模型对长上下文开头和结尾的信息记忆最深,而容易忽略中间部分的信息。 | +| **System Prompt** | 系统提示 | 位于对话最开始的指令,用于设定模型的身份、行为规范、回复风格和核心任务。 | +| **Few-shot** | 少样本学习 | 在提示词中提供几个“问题-答案”的示例,帮助模型快速理解任务模式和输出格式。 | +| **Chain of Thought** | 思维链 | 引导模型在给出最终答案前,先输出推理步骤。这种方法能显著提升模型解决复杂逻辑和数学问题的能力。 | +| **Hallucination** | 幻觉 | 模型自信地生成看似合理但实际上错误或不存在的信息的现象。 | +| **Embedding** | 向量化 | 将文本转换为高维数值向量的技术。语义相似的文本在向量空间中的距离更近,是语义搜索的基础。 | +| **Vector DB** | 向量数据库 | 专门用于存储和检索向量数据的数据库。支持通过相似度搜索快速找到与查询最匹配的文档片段。 | +| **Temperature** | 温度 | 控制模型输出随机性的超参数。数值越高(如 0.8)输出越多样、有创意;数值越低(如 0.2)输出越确定、严谨。 | +| **TTFT** | 首字延迟 | Time to First Token,即从用户发送请求到模型输出第一个 Token 所花费的时间,是衡量交互体验的关键指标。 | + +--- + +## 总结:上下文工程的本质 + +Manus 的四次重构告诉我们: + +**从实践来看**:不是记得越多越好,而是记得越有结构、越有选择性越好。 + +**从成本视角看**: +- 大部分浪费来自对固定前缀的重复计算,需要通过前缀稳定和缓存机制解决; +- 重要信息被误删,往往源于“一视同仁”的滑动窗口,需要通过信息分级与钉住策略解决; +- 面对超长文档和知识库时,仅依赖增大上下文窗口并不现实,必须结合检索与压缩机制。 + +目标是:在给定的模型与上下文上限下,让每一个 token 的投入都具备明确的用途。 diff --git a/docs/zh-cn/appendix/url-to-browser.md b/docs/zh-cn/appendix/url-to-browser.md index 6f257f3..3a5f76b 100644 --- a/docs/zh-cn/appendix/url-to-browser.md +++ b/docs/zh-cn/appendix/url-to-browser.md @@ -1,142 +1,358 @@ -# 从 URL 输入到浏览器显示 (From URL to Browser) +# 从 URL 到网页显示:一次网络"快递"之旅 -> 💡 **学习指南**:本章节通过交互式演示,带你深入了解浏览器如何将一行网址变成丰富多彩的页面。我们将从输入 URL 开始,一步步拆解背后的网络请求、连接建立和页面渲染过程。 + -## 0. 全景图:一次神奇的旅行 - -当你在浏览器地址栏输入一个网址并按下回车,短短几秒钟内,背后发生了一系列复杂而精妙的过程。这就像是一次跨越万水千山的旅行。 - -它的核心任务只有一个:**将你想要的资源(网页)准确无误地从世界的另一端搬运到你的屏幕上**。 - -我们可以把这个过程分为五个关键阶段,点击下方的步骤来预览整个流程: - - +> **学习指南**:本章节无需编程基础。我们将用**"寄快递"**的生活化比喻,配合**真实的技术过程**,带你一步步理解浏览器如何将一行网址变成丰富多彩的页面。 --- -## 1. 第一步:寻址 (URL Parsing) +## 0. 引言:当你按下回车键的那一刻 -### 1.1 计算机的"导航地址" +想象你要给远方的朋友寄一份礼物。你需要: +1. **填写快递单**(写明地址、收件人) +2. **快递公司查地址**(把"XX市XX区"转换成具体的门牌号) +3. **打电话确认**(确保对方在家能收件) +4. **快递员送达**(把包裹交给对方) +5. **朋友拆开包裹**(看到礼物) -计算机需要一个精确的地址格式才能找到资源。这就是 **URL (统一资源定位符)** 的作用。它不仅告诉浏览器**去哪里**(域名),还告诉它**怎么去**(协议),以及**找什么**(路径)。 +**访问网页的过程和寄快递惊人地相似!** -试着在下方的模拟地址栏中输入不同的 URL,看看它是如何被拆解的: +当你在浏览器输入 `google.com` 并按下回车,浏览器就是那个"快递员",它要完成一次从"你的电脑"到"远方服务器"再到"屏幕显示"的完整旅程。 + + + +--- + +## 1. 第一步:填写"快递单" —— URL 解析 + +### 生活比喻:填写快递单 + +假设你只在快递单上写"寄给张三",快递员肯定找不到人。你需要写清楚: +- **用什么快递**(顺丰/中通) +- **哪个城市**(北京市) +- **具体地址**(朝阳区XX街道XX号) +- **哪栋楼哪间房**(3号楼201) +- **备注信息**(放快递柜/打电话) + +### 真实过程:浏览器解析 URL + +**URL(Uniform Resource Locator,统一资源定位符)**就是浏览器世界的"快递单格式"。当你在地址栏输入 `https://www.example.com:8080/path/page.html?id=123#section`,浏览器会立即拆解它: + +| URL 部分 | 示例值 | 快递单类比 | 技术作用 | +|----------|--------|-----------|----------| +| **协议** `https://` | 安全超文本传输协议 | **快递公司**:顺丰(安全)vs 中通(普通) | 决定使用什么规则通信。`http` 是普通传输,`https` 是加密传输 | +| **域名** `www.example.com` | 服务器的人类可读名字 | **收件人姓名**:张三 | 告诉浏览器要找哪台服务器。域名是为了让人记住,最终要转换成 IP 地址 | +| **端口** `:8080` | 服务器的具体"门牌号" | **详细门牌号**:3号楼201(默认不写) | 服务器上可能有多个服务,端口指定访问哪一个。HTTP 默认 80,HTTPS 默认 443 | +| **路径** `/path/page.html` | 服务器上的文件位置 | **房间里的抽屉**:衣柜第二层 | 指定服务器上的具体资源位置 | +| **查询参数** `?id=123` | 附加信息 | **备注**:请轻拿轻放 | 传递给服务器的额外数据,如搜索关键词、页码等 | +| **锚点** `#section` | 页面内的位置 | **书里的页码**:翻到第5页 | 页面加载后自动滚动到指定位置,不发送给服务器 | -**关键部分解析**: - -- **Protocol (协议)**:通常是 `https` (安全) 或 `http`。就像告诉司机是"坐飞机"还是"坐火车"。 -- **Host (域名)**:`www.example.com`。目的地的名字,方便人类记忆。 -- **Port (端口)**:服务器的"门牌号"。Web 服务默认是 80 (HTTP) 或 443 (HTTPS),通常省略不写。 -- **Path (路径)**:`/path/to/page`。资源在服务器文件系统中的具体位置。 -- **Query (参数)**:`?q=vue`。给服务器的附加指令,就像点餐时的备注"不要香菜"。 +> **关键理解**:URL 的存在是为了让**人类**能记住和输入。计算机最终需要的是 **IP 地址**(就像快递员最终需要的是门牌号,而不是"张三的家")。 --- -## 2. 第二步:定位 (DNS Lookup) +## 2. 第二步:查"地址簿" —— DNS 查询 -### 2.1 互联网的"电话簿" +### 生活比喻:查地址簿 -虽然我们记住了 `google.com` 这样的域名,但计算机之间通信真正识别的是 **IP 地址**(如 `142.250.185.238`)。 +你告诉快递员"送到张三那里",但快递员怎么知道张三住哪?他需要查地址簿: +1. 先翻**通讯录**(最近联系过的人)→ 浏览器缓存 +2. 没有的话问**社区服务中心**(他们知道各个小区归谁管)→ 本地 DNS 服务器 +3. 社区问**总管理处**(他们知道XX街道归哪个片区管)→ 根域名服务器 +4. 片区查**住户登记**(最终找到张三的门牌号)→ 权威域名服务器 -**DNS (Domain Name System)** 就是互联网的"电话簿"或"导航系统"。当你输入域名时,浏览器需要先通过 DNS 找到它对应的 IP 地址。 +### 真实过程:DNS 分层查询 -点击下方的 **"Go"** 按钮,观察 DNS 的**递归查询**过程: +**DNS(Domain Name System,域名系统)**是互联网的"分布式地址簿查询系统"。由于全球有数十亿个域名,采用分层架构来分散查询压力: + +``` +你(浏览器) + ↓ 问:google.com 的 IP 是多少? +本地 DNS 服务器(你的网络运营商,如电信/联通) + ↓ 问:.com 归谁管? +根域名服务器(全球13组根服务器,管理所有顶级域) + ↓ 告诉:去问 .com 的管理者 +顶级域服务器(Verisign 管理 .com) + ↓ 告诉:去问 google.com 的管理者 +权威域名服务器(Google 自己的 DNS 服务器) + ↓ 告诉:google.com 的 IP 是 142.250.80.46 +返回 IP 地址给浏览器 +``` + +**查询类型说明:** +- **递归查询(Recursive Query)**:浏览器只发一次请求,本地 DNS 负责层层查询后返回结果 +- **迭代查询(Iterative Query)**:每一层只告诉下一层去哪查,浏览器需要多次查询 +- **缓存机制**:查询结果会被缓存,下次直接返回,大大加速访问 -**查询流程解析**: - -1. **浏览器缓存/Hosts**:先看看自己是否最近去过(缓存),或者本地小本本上有没有记(Hosts 文件)。 -2. **递归解析器 (Recursive Resolver)**:通常由你的 ISP (运营商) 提供。它像个尽职的跑腿员,负责帮你跑完剩下的路。 -3. **根域名服务器 (Root Server)**:它是 DNS 层级的顶端(`.`)。它不知道具体地址,但知道谁管 `.com`。 -4. **顶级域名服务器 (TLD Server)**:管理 `.com`、`.org` 等后缀的服务器。它会告诉你 `google.com` 归谁管。 -5. **权威域名服务器 (Authoritative Server)**:最终的管理者,它知道 `www.google.com` 的确切 IP 地址。 +> **为什么需要这么多层?** 想象一下如果全世界只有一个地址簿,几十亿人同时查,早就崩溃了。分层设计让每个层级只管理自己的"辖区",既高效又可靠。 --- -## 3. 第三步:连接 (TCP Handshake) +## 3. 第三步:打电话确认 —— TCP 三次握手 -### 3.1 建立可靠的通路 +### 生活比喻:打电话确认 -拿到 IP 地址后,浏览器找到了服务器。但在传输数据之前,它们必须建立一条可靠的连接,确保双方都能"听得到"且"说得出"。 +假设快递员直接冲到张三家门口,结果: +- 张三不在家 → 白跑一趟 +- 电话打不通 → 不知道送哪 +- 地址错了 → 送错地方 -这就是著名的 **TCP 三次握手 (Three-Way Handshake)**。 +**所以在真正送包裹之前,必须先确认"对方能收到"**。 -点击 **"Connect"** 亲自完成这次握手: +### 真实过程:TCP 三次握手 + +**TCP(Transmission Control Protocol,传输控制协议)**是确保数据可靠传输的规则。在发送任何数据前,客户端和服务器必须通过"三次握手"建立可靠连接: + +``` +客户端(你的浏览器) 服务器(网站) + | | + |--- SYN=1, seq=x ------------->| 第1次:我想连接你,我的初始序号是 x + | | + |<-- SYN=1, ACK=1, seq=y, ack=x+1 | 第2次:我也想连接你,我的初始序号是 y,期待收到 x+1 + | | + |--- ACK=1, ack=y+1 ----------->| 第3次:确认,期待收到 y+1 + | | + ===== 连接建立,开始传输数据 ===== +``` + +**为什么是三次,不是两次?** + +- **第一次(SYN)**:客户端证明自己能发送 +- **第二次(SYN-ACK)**:服务器证明自己能接收和发送 +- **第三次(ACK)**:客户端证明自己能接收 + +三次握手确保:**双方都能发、双方都能收** —— 四个条件都满足,才能可靠传输。 + +**TCP 还负责:** +- **数据分包**:大数据拆成小数据包传输 +- **顺序重组**:确保数据包按正确顺序组装 +- **错误重传**:丢包后自动重新发送 +- **流量控制**:根据网络状况调整发送速度 -**握手三部曲**: - -1. **SYN** (Synchronize):客户端发送一个包,说"你好,我想和你建立连接,我的序列号是 X"。 -2. **SYN-ACK** (Synchronize-Acknowledge):服务器收到后回复,"好的,收到了 X。我也想和你建立连接,我的序列号是 Y"。 -3. **ACK** (Acknowledge):客户端最后回复,"好的,收到了 Y。那我们开始传输数据吧"。 - -> 🔒 **关于 HTTPS (TLS)**: -> 如果使用 HTTPS,在 TCP 握手之后,还会进行 **TLS 握手**。双方会协商加密算法并交换证书,确保后续传输的数据像装在保险箱里一样安全。 +> **HTTPS 的额外步骤**:如果是 HTTPS(安全的网站),在 TCP 握手后还会进行 **TLS 握手**(1-RTT 或 2-RTT),双方交换加密密钥,确保之后的对话内容只有双方能看懂,就像用暗语通话。 --- -## 4. 第四步:交流 (HTTP Exchange) +## 4. 第四步:"快递员"和"收件人"的对话 —— HTTP 请求与响应 -### 4.1 索取与交付 +### 生活比喻:快递员送达 -连接建立好了,浏览器终于可以发出它的请求了:"请给我首页的 HTML 代码"。这就像在餐厅点餐。 +快递员敲门:"张三在吗?您的快递!" +张三开门:"好的,给我吧。" 或者 "我没买东西啊,退回去吧。" -**HTTP (HyperText Transfer Protocol)** 定义了这种对话的格式。 +### 真实过程:HTTP 协议通信 -在下方的模拟器中尝试发送不同的请求(GET/POST),观察网络日志: +**HTTP(HyperText Transfer Protocol,超文本传输协议)**是浏览器和服务器之间的"对话规则"。TCP 连接建立后,浏览器发送 HTTP 请求: + +**HTTP 请求示例:** +```http +GET /index.html HTTP/1.1 ← 请求方法 + 路径 + 协议版本 +Host: www.example.com ← 目标主机(支持虚拟主机,一台服务器可托管多个网站) +User-Agent: Chrome/120.0 ← 客户端标识(服务器可据此返回适配内容) +Accept: text/html,application/xhtml+xml ← 可接受的响应格式 +Accept-Language: zh-CN,zh;q=0.9 ← 偏好的语言 +Accept-Encoding: gzip, deflate ← 支持的压缩格式 +Connection: keep-alive ← 保持连接(复用 TCP 连接) +Cookie: session_id=abc123 ← 身份凭证 +``` + +**常见 HTTP 方法:** +- `GET`:获取资源(安全、幂等,可被缓存) +- `POST`:提交数据(创建资源,如注册、登录) +- `PUT`:更新资源(完整替换) +- `PATCH`:部分更新资源 +- `DELETE`:删除资源 +- `HEAD`:获取响应头(不返回主体,用于检查资源是否存在) + +**服务器返回 HTTP 响应:** +```http +HTTP/1.1 200 OK ← 协议版本 + 状态码 + 状态描述 +Date: Mon, 23 May 2025 12:00:00 GMT ← 服务器时间 +Content-Type: text/html; charset=UTF-8 ← 内容类型和编码 +Content-Length: 1234 ← 内容长度(字节) +Cache-Control: max-age=3600 ← 缓存策略 +Set-Cookie: user_id=xyz789 ← 设置 Cookie + +... ← 响应体(网页内容) +``` + +**HTTP 状态码分类:** + +| 状态码 | 类别 | 含义 | 生活类比 | +|--------|------|------|----------| +| **200** | 成功 | 请求成功处理 | "给,这是你要的" | +| **301/302** | 重定向 | 资源已移动 | "搬家了,去新地址取" | +| **304** | 未修改 | 缓存仍有效 | "和上次一样,不用重新拿" | +| **400** | 客户端错误 | 请求格式错误 | "你说的话我听不懂" | +| **401** | 未授权 | 需要身份验证 | "请出示证件" | +| **403** | 禁止访问 | 权限不足 | "你不准进" | +| **404** | 未找到 | 资源不存在 | "没这个人/没这个东西" | +| **500** | 服务器错误 | 服务器内部错误 | "我们这系统出故障了" | +| **502** | 网关错误 | 上游服务器无响应 | "我们上级部门没回应" | +| **503** | 服务不可用 | 服务器过载或维护 | "今天休息,不营业" | -**对话过程**: - -1. **请求 (Request)**: - - **Method**:`GET`(获取)、`POST`(提交数据)等。 - - **Path**:我要什么资源。 - - **Headers**:我是谁(User-Agent)、我想要什么格式(Accept)等元数据。 - -2. **响应 (Response)**: - - **Status Code**:`200 OK`(成功)、`404 Not Found`(没找到)、`500 Error`(服务器出错了)。 - - **Headers**:内容类型(Content-Type)、服务器信息等。 - - **Body**:具体的 HTML 代码、JSON 数据或图片二进制流。 - --- -## 5. 第五步:展示 (Browser Rendering) +## 5. 第五步:拆开"包裹" —— 浏览器渲染 -### 5.1 代码如何变成画面? +### 生活比喻:拆开包裹看到礼物 -浏览器收到的是一堆枯燥的 HTML 代码,它是如何变成我们在屏幕上看到的精美网页的呢?这个过程叫做**渲染 (Rendering)**。 +快递员把包裹交给张三,张三看到的是**包装盒**。他需要: +1. **拆开包装**(去掉快递袋)→ 解析 HTML +2. **查看说明书**(了解怎么用)→ 解析 CSS +3. **组装零件**(按说明书拼装)→ 构建渲染树 +4. **摆放位置**(确定放哪里)→ 布局计算 +5. **最终呈现**(展示成品)→ 绘制到屏幕 -浏览器就像一个精密的工厂,将原材料(HTML/CSS)加工成最终产品(屏幕上的像素)。 +### 真实过程:浏览器渲染引擎 -点击下方的步骤,查看渲染流水线的每个阶段: +浏览器收到的是 **HTML/CSS/JavaScript 代码**(枯燥的文本),但它要变成**像素画面**(精美的网页)。这个过程叫做**渲染(Rendering)**,由浏览器的**渲染引擎**(如 Chrome 的 Blink、Safari 的 WebKit)执行。 + +#### 步骤1:解析 HTML → 构建 DOM 树 + +浏览器读取 HTML 字节流,按编码(通常是 UTF-8)转换成字符,通过词法分析生成 Token,再解析成 DOM 节点,最终构建成**DOM(Document Object Model,文档对象模型)树**: + +```html + + + +
标题
+
内容
+ + +``` + +``` +变成树形结构: + Document + │ + html + │ + body + / \ + div div + .header .content + │ │ + "标题" "内容" +``` + +**关键特性:** +- **流式解析**:浏览器边下载边解析,不需要等整个 HTML 下载完 +- **遇到 script 标签**:会暂停解析,先下载并执行 JavaScript(除非加 `async` 或 `defer`) +- **遇到 css 链接**:不会阻塞解析,但会阻塞渲染(需要等 CSS 下载完) + +#### 步骤2:解析 CSS → 构建 CSSOM 树 + +浏览器同时解析 CSS(内联样式、`