|
1 | 1 | import { useState, useEffect, useCallback, useMemo } from 'react'; |
2 | 2 | import { JsonBlock } from '../components/JsonBlock'; |
3 | 3 |
|
| 4 | +// 介绍内容组件 |
| 5 | +function Introduction({ isExpanded, onToggle }: { isExpanded: boolean; onToggle: () => void }) { |
| 6 | + return ( |
| 7 | + <div className="mb-6 bg-[var(--bg-elevated)] rounded-lg overflow-hidden border border-[var(--border-subtle)]"> |
| 8 | + <button |
| 9 | + onClick={onToggle} |
| 10 | + className="w-full px-4 py-3 flex items-center justify-between text-left hover:bg-[var(--bg-panel)] transition-colors" |
| 11 | + > |
| 12 | + <span className="text-lg font-semibold text-[var(--text-primary)]">📖 什么是上下文压缩?</span> |
| 13 | + <span className={`transform transition-transform text-[var(--text-muted)] ${isExpanded ? 'rotate-180' : ''}`}>▼</span> |
| 14 | + </button> |
| 15 | + |
| 16 | + {isExpanded && ( |
| 17 | + <div className="px-4 pb-4 space-y-4 text-sm"> |
| 18 | + {/* 核心概念 */} |
| 19 | + <div> |
| 20 | + <h3 className="text-[var(--terminal-green)] font-semibold mb-2">🎯 核心概念</h3> |
| 21 | + <p className="text-[var(--text-secondary)]"> |
| 22 | + <strong>上下文压缩</strong>是 CLI 保持长对话能力的关键机制。当对话历史超过 Token 限制时, |
| 23 | + 系统会智能压缩旧消息,保留最重要的信息,让 AI 能够继续理解上下文。 |
| 24 | + </p> |
| 25 | + </div> |
| 26 | + |
| 27 | + {/* 为什么需要 */} |
| 28 | + <div> |
| 29 | + <h3 className="text-[var(--terminal-green)] font-semibold mb-2">❓ 为什么需要压缩?</h3> |
| 30 | + <ul className="text-[var(--text-secondary)] space-y-1 list-disc list-inside"> |
| 31 | + <li><strong>Token 限制</strong>:每个 AI 模型都有最大上下文长度限制</li> |
| 32 | + <li><strong>成本控制</strong>:Token 越多,API 调用成本越高</li> |
| 33 | + <li><strong>响应速度</strong>:更少的 Token 意味着更快的响应</li> |
| 34 | + <li><strong>信息密度</strong>:压缩保留关键信息,丢弃冗余内容</li> |
| 35 | + </ul> |
| 36 | + </div> |
| 37 | + |
| 38 | + {/* 压缩策略 */} |
| 39 | + <div> |
| 40 | + <h3 className="text-[var(--terminal-green)] font-semibold mb-2">📊 压缩策略</h3> |
| 41 | + <div className="grid grid-cols-2 gap-2 text-xs"> |
| 42 | + <div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]"> |
| 43 | + <div className="text-[var(--amber)]">阈值触发</div> |
| 44 | + <div className="text-[var(--text-muted)]">Token 超过限制时自动触发</div> |
| 45 | + </div> |
| 46 | + <div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]"> |
| 47 | + <div className="text-[var(--cyber-blue)]">分割点选择</div> |
| 48 | + <div className="text-[var(--text-muted)]">寻找最佳压缩位置</div> |
| 49 | + </div> |
| 50 | + <div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]"> |
| 51 | + <div className="text-[var(--purple)]">AI 摘要</div> |
| 52 | + <div className="text-[var(--text-muted)]">用 AI 生成历史摘要</div> |
| 53 | + </div> |
| 54 | + <div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]"> |
| 55 | + <div className="text-[var(--terminal-green)]">重建上下文</div> |
| 56 | + <div className="text-[var(--text-muted)]">摘要 + 最近消息组成新上下文</div> |
| 57 | + </div> |
| 58 | + </div> |
| 59 | + </div> |
| 60 | + |
| 61 | + {/* 源码位置 */} |
| 62 | + <div> |
| 63 | + <h3 className="text-[var(--terminal-green)] font-semibold mb-2">📁 源码位置</h3> |
| 64 | + <code className="text-xs bg-[var(--bg-void)] p-2 rounded block border border-[var(--border-subtle)]"> |
| 65 | + packages/core/src/core/chatHistory.ts |
| 66 | + </code> |
| 67 | + </div> |
| 68 | + |
| 69 | + {/* 相关机制 */} |
| 70 | + <div> |
| 71 | + <h3 className="text-[var(--terminal-green)] font-semibold mb-2">🔗 相关机制</h3> |
| 72 | + <div className="flex flex-wrap gap-2"> |
| 73 | + <span className="px-2 py-1 bg-[var(--amber)]/20 text-[var(--amber)] rounded text-xs">Token 计数</span> |
| 74 | + <span className="px-2 py-1 bg-[var(--purple)]/20 text-[var(--purple)] rounded text-xs">消息格式</span> |
| 75 | + <span className="px-2 py-1 bg-[var(--cyber-blue)]/20 text-[var(--cyber-blue)] rounded text-xs">会话管理</span> |
| 76 | + <span className="px-2 py-1 bg-[var(--terminal-green)]/20 text-[var(--terminal-green)] rounded text-xs">记忆系统</span> |
| 77 | + </div> |
| 78 | + </div> |
| 79 | + </div> |
| 80 | + )} |
| 81 | + </div> |
| 82 | + ); |
| 83 | +} |
| 84 | + |
4 | 85 | // 消息类型 |
5 | 86 | interface Message { |
6 | 87 | id: number; |
@@ -295,6 +376,7 @@ export function ContextCompressionAnimation() { |
295 | 376 | const [splitPoint, setSplitPoint] = useState<number | null>(null); |
296 | 377 | const [isPlaying, setIsPlaying] = useState(false); |
297 | 378 | const [currentStep, setCurrentStep] = useState(0); |
| 379 | + const [isIntroExpanded, setIsIntroExpanded] = useState(true); |
298 | 380 |
|
299 | 381 | const totalTokens = useMemo( |
300 | 382 | () => messages.reduce((sum, m) => sum + m.tokens, 0), |
@@ -414,10 +496,11 @@ export function ContextCompressionAnimation() { |
414 | 496 |
|
415 | 497 | <p className="text-sm text-[var(--text-muted)] font-mono mb-6"> |
416 | 498 | // 当 Token 使用量超过阈值时,自动压缩历史消息以释放空间 |
417 | | - <br /> |
418 | | - // 源码位置: packages/core/src/services/chatCompressionService.ts |
419 | 499 | </p> |
420 | 500 |
|
| 501 | + {/* 介绍部分 */} |
| 502 | + <Introduction isExpanded={isIntroExpanded} onToggle={() => setIsIntroExpanded(!isIntroExpanded)} /> |
| 503 | + |
421 | 504 | {/* Controls */} |
422 | 505 | <div className="flex gap-3 mb-6 flex-wrap"> |
423 | 506 | <button |
|
0 commit comments