Token 与上下文窗口:理解 AI 模型的「记忆」与限制
Token 与上下文窗口理解 AI 模型的「记忆」与限制一、为什么 Token 是你必须理解的概念如果你只用 AI 编程工具做简单的代码补全Tab 补全那你可能不需要太关心 Token 是什么。但如果你想要让 AI 理解和修改一整个文件让 AI 跨多个文件做重构编写精确的 Prompt 来控制 AI 输出理解为什么 AI 有时会忘记你之前说的话那你就必须理解 Token 和上下文窗口这两个核心概念。在我使用 AI 编程的早期遇到过一个让我困惑的问题我给 Claude 贴了一个 1500 行的代码文件然后在对话中讨论了前面几个函数的优化方案。但当我让它修改文件末尾的一个函数时它好像不记得这个函数的内容了——它的修改建议明显是错误的。后来我才明白这不是 AI 的 Bug而是上下文窗口的特性。当你理解了 Token 和上下文窗口的机制后这种问题就是完全可以预判和避免的。二、什么是 Token——AI 的原子单位2.1 Token 的定义Token词元是大语言模型理解和生成文本的最小单位。类比一下英语中的字母是最小书写单位但人类不会一个字母一个字母地读——我们会把字母组合成词Token 就是 AI 的词——AI 不一个一个字符地读也不一个一个单词地读而是把文本切分为一定大小的Token块2.2 Tokenization 的工作机制文本转为 Token 的过程叫做 Tokenization分词。目前主流模型GPT、Claude使用的是一种叫 BPEByte Pair Encoding的算法。BPE 的工作方式是从字符级别开始统计最常见的字符对将它们合并为一个新的 Token。反复执行这个过程直到达到预设的词汇表大小。让我们看一个具体的例子原始文本: const userName hello world; BPE Tokenization 过程简化示意 Step 1: 先按常见编程符号拆分 [const, , user, Name, , , , , hello, , world, , ;] Step 2: 高频组合合并 user Name 经常一起出现 → 作为一个 Token hello world → 由于hello world是高频短语hello和world可能各为一个Token 最终 Token 序列近似: [const, , userName, , , , , hello, , world, , ;] 约 12 个 Token2.3 英文 vs 中文的 Token 消耗差异这是一个很多中文开发者没意识到的隐性成本。不同语言的 Token 效率差异很大英文的 Token 效率文本: The quick brown fox jumps over the lazy dog Token 数: ~10 比例: 1个单词 ≈ 1.2 个 Token中文的 Token 效率文本: 快速的棕色狐狸跳过了懒惰的狗 Token 数: ~15-20 比例: 1个汉字 ≈ 1.5-2 个 Token代码的 Token 效率Python: def calculate_sum(a, b): return a b Token 数: ~12 中文注释: # 这个函数用来计算两个数的和 Token 数: ~15-20比代码本身还多各语言 Token 消耗对比表以表达相同语义为准语言相对 Token 消耗说明英文1x基准拉丁字母与BPE天然契合中文1.5-2x每个汉字通常占1-2个Token日文/韩文1.5-2.5x类似中文字符集大代码英文关键词0.8-1.2x常见关键字和模式Token化效率高代码含中文注释1.2-1.8x中文注释增加额外消耗实用建议如果使用按 Token 计费的 API如 GPT-4 API、Claude API用英文 Prompt 性价比更高。中文 Prompt 的效果可能同样好甚至在某些情境下更好但 Token 消耗明显更大。2.4 代码的 Tokenization 示例让我们看看一段实际的 JavaScript 代码是如何被 Token 化的// 源代码functioncalculateDiscount(price,userLevel){if(userLevelvip){returnprice*0.8;}returnprice;}// 大致的 Token 分解GPT-3.5/4 的 Tokenizer// function → 1 Token高频关键字// → 1 Token// calculate → 1 Token// Discount → 1 Token// ( → 1 Token// price → 1 Token// , → 1 Token// → 1 Token// user → 1 Token// Level → 1 Token// ) → 1 Token// → 1 Token// { → 1 Token// \n → 1 Token// if → 1 Token// 依此类推...// 总计约 30-35 个 Token 高频出现的关键字function、if、return、常见变量名、常用模式箭头函数在 Token 表中有自己的专属位置通常一个 Token 就够了。三、上下文窗口——AI 的工作记忆3.1 上下文窗口的概念上下文窗口Context Window是模型在一次推理中能看到的 Token 最大数量。它决定了 AI 的视野范围。用一个类比来理解上下文窗口就像你在一个白板上写字。白板的大小是固定的——当白板写满后你若要写新内容就必须擦掉一些旧内容。同样当 Token 数量超出上下文窗口后模型就会忘记最早的内容。上下文窗口示意图 [最早的内容] ... [中间的内容] ... [最新的内容] |-------------- 上下文窗口 ---------------| 超出窗口的内容会被截断——模型完全看不到了3.2 上下文窗口的历史演进上下文窗口的增长速度是 AI 进步最显眼的指标之一时间模型上下文窗口约等于2018GPT-1512一段话2019GPT-21,024一页文字2020GPT-32,048一篇短文2022GPT-3.54,096一篇长文2023GPT-48,192一个章节2023GPT-4 Turbo128,000一本小说2024Claude 3200,000300页的书2024Gemini 1.5 Pro1,000,000一部《战争与和平》从 512 到 1,000,000——增长近 2000 倍仅用了 6 年时间。这个速度甚至超过了摩尔定律。3.3 200K Token 意味着什么Claude 3 的 200K Token 上下文窗口对编程来说意味着≈ 150,000 个英文单词 ≈ 300 页的技术文档 ≈ 50,000-80,000 行代码取决于语言和注释密度 ≈ 可以一次性放入以下内容 - 一个中型 Next.js 项目的所有源文件 - React 官方文档 Express.js 文档 Prisma 文档 - 整个项目的 package.json tsconfig 所有组件的完整代码3.4 “近因效应”——不是所有 Token 都同等重要虽然模型有大的上下文窗口但研究表明模型注意得最多的是靠近末尾的内容。这被称为近因效应Recency Bias或Lost in the Middle现象。上下文中各部分的注意权重分布示意 高权重开头部分首因效应 中低权重中间部分Lost in the Middle 最高权重结尾部分近因效应 建议把最重要的信息放在开头或结尾不要让核心指令沉在中间实用建议将核心指令和约束放在 Prompt 的最后最新位置将背景信息和示例放在 Prompt 的前部在长对话中定期重申关键要求对于特别重要的约束在对话的各个环节反复强调四、上下文窗口对编程的影响4.1 单文件代码理解当你让 AI 理解一个代码文件时首先需要确保整个文件的内容能放进上下文窗口。一个 1000 行的 JavaScript 文件 ≈ 10,000-15,000 Token → 在 GPT-48K中放不下 → 在 GPT-4 Turbo128K和 Claude 3200K中完全没问题4.2 多文件代码修改这是上下文窗口最能体现差异的场景。假设你要做一个涉及 5 个文件的修改文件1页面组件: 200 行 ≈ 2,500 Token 文件2API路由: 150 行 ≈ 1,800 Token 文件3数据模型: 100 行 ≈ 1,200 Token 文件4类型定义: 80 行 ≈ 1,000 Token 文件5工具函数: 120 行 ≈ 1,500 Token 对话历史 Prompt AI响应: ≈ 4,000 Token 总计: ~12,000 Token这个总数在 8K 的窗口GPT-4中已经很拥挤了——可能放不下完整的 5 个文件加上充分的对话讨论。但在 128KGPT-4 Turbo和 200KClaude 3中还有大量空间可以添加相关文档、API 规范等额外上下文。4.3 长对话的记忆丧失当你与 AI 进行长时间的多轮对话时早期交换的信息会逐渐被推出上下文窗口。第 1 轮对话讨论项目架构占 5,000 Token 第 2 轮对话讨论数据库设计占 8,000 Token 第 3 轮对话开始写代码累计 13,000 Token ... 第 10 轮对话修改 bug累计 35,000 Token 此时第 1 轮讨论的架构细节可能在 GPT-48K中完全消失了 只在 GPT-4 Turbo 和 Claude 3 中还能被记住。⚠️这就是我在文章开头提到的那个问题的原因——当我把 1500 行代码放进会话经过多轮讨论后文件末尾的内容虽然一开始在上下文中但随着新内容的不断加入AI 对较早位置的注意力减弱了。五、高效管理 Token 的实用策略5.1 文件拆分策略不要把一个 3000 行的文件直接丢给 AI。相反采用分层递进策略步骤①给 AI 项目的骨架 这是我的项目结构[目录树] 我要修改 [具体功能] 模块请先帮我理解相关的文件。 步骤②给 AI 关键部分 这是 [具体文件] 的核心部分前 200 行请分析... 步骤③选择性提供上下文 这是和当前修改相关的 [类型定义/接口/配置]请参考... 步骤④总结代替完整代码 文件中剩余的 800 行是 [功能描述]如果你需要某部分的具体代码请告诉我。5.2 选择性上下文Selective Context给 AI 的上下文不是越多越好而是越相关越好❌ 不好的做法把整个项目的 50 个文件全部放进 Prompt → 浪费 TokenAI 反而可能被无关信息干扰✅ 好的做法只放与当前任务直接相关的文件 - 正在修改的文件 - 被修改文件的依赖它 import 了什么 - 类型定义和接口 - 相关的配置文件5.3 Prompt 压缩技巧一些减少 Token 消耗的实用技巧去掉不必要的空白和注释仅在你发送给 AI 的代码中// 原始包含格式化空白和开发注释functiongetUserById(id){// 查询用户信息constuserawaitdb.user.findUnique({// Prisma 查询where:{id:id},include:{profile:true}});returnuser;}// 压缩后去掉注释和多余空白AI 仍然能理解functiongetUserById(id){constuserawaitdb.user.findUnique({where:{id},include:{profile:true}});returnuser;}用简洁的描述替代完整的文件内容项目的 ESLint 配置是标准配置 React plugin TypeScript plugin 而不是粘贴整个 .eslintrc.json 文件在大文件场景中用 // … (略) 标记省略部分functionfirstFunction(){/* ... */}functionsecondFunction(){/* ... */}// ... (此处省略 500 行业务逻辑函数)// 以下是要修改的核心部分functionprocessOrder(order){// 这个函数有 150 行// ...}5.4 分而治之策略对于大型任务不要试图在一个对话中完成所有工作# 错误做法一个长对话处理一切 对话1Token 0 → 50K讨论需求 → 设计架构 → 生成所有代码 → 修改 → 测试 → 后期 AI 的记忆已经严重过载 # 正确做法分阶段、分对话 对话1Token 0 → 15K需求分析和架构设计 → 输出设计文档 对话2Token 0 → 20K基于设计文档实现模块 A → 完成并测试 对话3Token 0 → 20K基于设计文档实现模块 B → 完成并测试 对话4Token 0 → 10K集成测试和问题修复 → 每个对话都有充足的上下文空间5.5 利用工具自动管理上下文一些工具已经内置了智能的上下文管理Claude Code自动选择相关文件放入上下文而非全部文件Cursor通过 .cursorrules 和项目索引来优选上下文GitHub Copilot分析最近查看和编辑的文件自动构建上下文经验法则让工具帮你管理上下文你只需要关注当前这个对话中聊什么。六、常见 Token 管理错误与避免方法错误一把所有文件都放进 Prompt错误示范 我有以下文件[粘贴了10个文件总计5000行代码]。 帮我给所有文件的函数加错误处理。 问题AI 被过多的信息淹没可能漏掉某些文件或做出不准确的修改。✅ 改进方法分文件逐个处理并在需求中明确具体文件。错误二忽视 Token 消耗的隐形大户错误示范 在 Prompt 中粘贴了一个 200 行的 JSON 配置文件包含了 AI 不需要知道的 所有细节而这个文件的精华信息其实只有 5 行。✅ 改进方法提取关键信息而非全量粘贴。对于 JSON 配置只给出结构或关键字段。错误三在长对话中依赖 AI 记住所有内容错误示范 第 1 轮我告诉 AI 使用 async/await 风格 ...50 轮对话后 第 51 轮我让 AI 写一个新函数期望它还记得 async/await 的偏好 → AI 忘了因为它已经被推出上下文窗口✅ 改进方法在关键指令被遗忘前主动重申。或在工具层面设置如 CLAUDE.md 中的规范会在每次对话开始时重新加载。错误四中文 Prompt 中不必要的啰嗦错误示范 请帮我写一个能够处理用户登录请求的 Express.js 路由处理函数 这个函数需要接受用户名和密码两个参数然后... Token 数~100中文 代码 改进版 写 Express.js 登录路由接收 username passwordJWT 认证bcrypt 加密 Token 数~30中文英文混排 代码✅ 改进方法Prompt 中使用简洁的关键词 英文技术术语API、框架名等减少 Token 浪费。七、总结Token 和上下文窗口是大语言模型最基础的物理限制理解它们就像理解计算机的内存和硬盘——你不需要成为硬件专家但了解基本概念能在你编程时做出更好的决策。核心要点✅ Token 是 AI 处理文本的最小单位中英文的 Token 效率不同✅ 上下文窗口决定了 AI 一次能看到多少内容✅ 模型对靠近末尾的内容注意得更多近因效应✅ 大型上下文窗口128K让理解整个项目成为可能✅ 高效管理上下文的关键是选择性提供信息 分层递进 工具辅助✅ 避免常见错误信息过载、忽视隐形 Token 消耗、依赖 AI 的长时记忆掌握了 Token 和上下文窗口的知识你就理解了为什么有时候 AI 的记忆好像不稳定——这不是 Bug而是机制。下一章我们将探讨 AI 编程的三种核心模式。下一篇AI 编程的三种模式代码补全、对话生成与智能体自动编程