当AI开口说话:聊聊「上下文」这件事
当AI开口说话:聊聊「上下文」这件事
想象这样一个场景:你在微信上和朋友聊天,你们从早上讨论晚上吃什么,一直聊到下午三点,中间穿插了工作吐槽、午休闲聊、突然想起的童年回忆。你们聊了四个小时,发了几十条消息,每条消息都不是孤立存在的——后一条消息总是建立在前一条的基础上。
现在,把这个朋友换成AI。
当你和AI对话时,你可能很快发现一些奇怪的现象:有时候AI好像完全理解你的意思,有时候又会突然"断片",忘记你们几分钟前讨论的内容;有时候你问了一个很长的复杂问题,AI的回答突然变得莫名其妙;有时候AI会在对话进行到一半时,突然忘记了你们最初在讨论什么……
这些现象背后,都指向同一个核心概念——上下文。
理解上下文,是理解AI对话能力与局限的第一把钥匙。
小明的故事:一次让人困惑的AI对话
让我们通过一个具体的故事,来看看上下文是如何影响AI对话体验的。
小明是一个大学二年级的学生,这学期他正在学一门叫做"计算机科学导论"的课程。期末考试前一周,他决定让AI助手帮他复习。
第一轮对话
> 小明:我不太理解什么是递归函数,能给我解释一下吗? > > AI:递归函数就像俄罗斯套娃,一个函数内部调用自己。比如计算阶乘,5! = 5 × 4 × 3 × 2 × 1,可以用递归写成 `factorial(5) = 5 × factorial(4)`,一直分解到 `factorial(1) = 1`。 > > 小明:哦,我懂了。那它和循环有什么区别? > > AI:循环是重复执行一段代码,递归是函数调用自己。递归的优点是代码更简洁,缺点是可能有性能问题和栈溢出风险。
对话进行到这里,小明觉得AI的回答非常清晰。他继续问:
> 小明:那斐波那契数列用递归怎么写? > > AI:斐波那契数列是 1, 1, 2, 3, 5, 8, 13...每一项等于前两项之和。用递归写的话: > ```python > def fib(n): > if n <= 1: > return n > return fib(n-1) + fib(n-2) > ```
第二轮对话(十分钟后)
小明继续追问:
> 小明:但是你这个写法效率很低吧? > > AI:是的,这个朴素递归的时间复杂度是指数级的,有大量重复计算。比如计算 fib(5) 的时候,fib(3) 会被计算多次。
第三轮对话(半小时后,继续复习其他内容)
小明在复习完递归之后,转向了数据结构的内容:
> 小明:讲讲二叉树吧。 > > AI:二叉树是一种每个节点最多有两个子节点的数据结构。常见的有二叉搜索树、平衡树、堆等。
第四轮对话(一个小时后)
小明突然想起来:
> 小明:对了,你刚才说的那个递归计算斐波那契数列的问题,怎么优化? > > AI:哦,你可以用记忆化递归(Memoization),或者直接用循环实现。
问题出现了
小明发现,当他说"你刚才说的那个递归计算斐波那契数列的问题"时,AI并没有表现出任何困惑,立刻理解了"那个问题"指的是什么——这是因为上下文中还保留着这些信息。
但是,如果小明过了很长时间、问了很多其他问题之后再说这句话,AI很可能就会困惑:"什么递归问题?我不记得了。"
这就是上下文在起作用。
AI之所以能理解"你刚才说的那个问题",是因为小明之前问的所有内容都还在"上下文"里,AI可以回溯查看。AI之所以会"忘记",是因为上下文有容量限制,当内容太多时,早期的对话就会被"挤掉"。
这个故事揭示了上下文的两个核心特性:它让对话连贯,同时它有容量限制。
上下文就是AI理解对话的「记忆」
如果要用一句话向一个完全不懂技术的朋友解释"上下文"是什么,我会这样说:
上下文就是AI的"工作记忆",它决定了AI此时此刻能看到多少对话历史。
让我们把AI想象成一个人。
当你和一个人面对面聊天时,对方能记住你们刚才说了什么,能关联前面的讨论,甚至能引用几分钟前你开的玩笑。这种"知道我们在聊什么"的能力,就是记忆在工作。
AI的"上下文"扮演的正是这个角色。当你告诉AI"我的名字叫小明",然后问它"我的名字是什么",它能回答出来,是因为"我的名字叫小明"这条信息在上下文里,AI能"看到"它。
更准确地说,上下文是一段持续的文本,它包含了当前对话的所有相关信息:
- 你之前问过的所有问题
- AI之前的回答
- 你提供的任何背景信息
- 任何你希望AI记住的内容
每次你发送一条新消息,AI并不是在"回忆"你们之前的对话——它实际上是把整个上下文(包括所有历史消息)重新读一遍,然后生成回复。
这就是为什么AI有时会在长对话中"忘记"早期内容的原因:不是因为AI真的"失忆"了,而是因为早期内容已经从上下文中被挤出去了。
上下文的三个层次
为了更好地理解上下文,我们可以把它分成三个层次:
第一层:当前轮次上下文
这是你当前发送的消息本身。比如你问"北京的天气怎么样?"——这句话就构成了一个最小的上下文。AI需要从这句话中理解你的意图。
第二层:对话上下文
这是你和AI之间的一整段对话历史。比如:
``` 你:帮我写一封请假邮件 AI:好的,请告诉我请假的原因和时间 你:家里有事,本周五 AI:明白了,我帮你写 ```
在这种情况下,AI需要记住"你之前要写请假邮件"、"请假原因是家里有事"、"时间是本周五"这些信息,才能生成一封完整的邮件。
第三层:系统上下文
这通常包括AI的系统提示词(System Prompt)和其他预设信息。比如在某些场景下,AI被设定为"你是一个专业的客服,代表某某公司"——这个身份设定就属于系统上下文。
当我们讨论"AI的记忆"时,主要关心的是第二层——对话上下文。
一个思维实验:理解上下文的工作方式
让我们做一个思维实验,把上下文想象成一张纸。
假设你有一张只能写500个字的纸(实际上AI的上下文窗口比这大得多,但原理是一样的)。当你和AI开始对话时,这张纸是空的。
每当你发一条消息,这条消息就会被抄到纸上。每当AI回复,AI的回复也会被抄到纸上。
随着对话进行,纸上的字越来越多。当写到第500个字时,纸就满了。
这时候,如果你再发一条消息,会发生什么?
你需要把纸上的旧内容擦掉一部分,腾出空间写新内容。被擦掉的内容,AI就"看不见"了——这就是为什么AI会"忘记"。
当然,实际的AI不会真的"擦掉"——它是从上下文的开头开始,逐渐丢弃更早的内容,直到有足够的空间容纳新消息。但效果是一样的:上下文容量有限制,早期对话会被后期对话挤出上下文窗口。
上下文窗口有大小限制,就像人的短时记忆
在上一节中,我把上下文比喻成一张纸。现在,让我们把这个比喻延伸一下。
人类的大脑记忆分为两种:短时记忆和长时记忆。短时记忆就像一张便签纸,容量很小,只能同时记住几件事,而且如果不刻意复述,很快就会忘记。长时记忆则像一个大仓库,可以存储海量的信息,保存很长时间。
AI的"上下文窗口"扮演的正是短时记忆的角色——它有容量限制,容量用完后,早期的内容就会被"遗忘"。
什么是上下文窗口
上下文窗口(Context Window)是指AI一次性能够处理的最大文本长度。超过这个长度,早期的内容就会被截断或"遗忘"。
不同的AI模型有不同的上下文窗口大小:
- 早期的大型语言模型(如GPT-2)上下文窗口约为1024个token,大约相当于几百个中文字符
- GPT-3.5的上下文窗口约为4096个token
- GPT-4的不同版本,上下文窗口从8192到128000个token不等
- 最新的模型甚至达到了100万以上的token
以GPT-4的128K上下文窗口为例,这意味着AI可以同时处理相当于一本中篇小说长度的文本——这是一个相当大的容量。
但即使是这样的"大容量",也仍然是有限的。
为什么上下文窗口不能无限大
你可能会问:既然上下文这么重要,为什么不把上下文窗口做得无限大?
这是一个很好的问题。答案涉及到技术、经济和性能三个方面的限制。
技术限制:处理更长的上下文需要更多的计算资源。当上下文长度翻倍时,计算量不是简单地翻倍,而是呈几何级数增长。这是因为Transformer架构(大多数现代大语言模型的基础)中的注意力机制,其计算复杂度与序列长度的平方成正比。
经济限制:更长的上下文意味着更高的推理成本。如果AI每次对话都需要处理几十万token,即使你能负担得起硬件成本,电费和服务器费用也会让这种服务变得极其昂贵。
性能限制:即使技术上能做、经济上可承受,更长的上下文也会带来性能问题。研究表明,当上下文变得非常长时,AI对"中间位置"内容的理解能力会下降——这被称为"中间迷失"(Lost in the Middle)问题。AI更容易记住上下文开头和结尾的内容,而对中间部分记得不那么清楚。
上下文窗口大小的实际影响
理解上下文窗口大小的意义在于:它直接决定了你能和AI进行多长、多复杂的对话。
场景一:短问答
如果你的问题很简单,一两句话就能说清楚,比如"什么是光合作用?"——这时候上下文窗口的大小对你几乎没有影响,因为你的问题本身就非常短。
场景二:中等长度的任务
如果你让AI帮你写一篇2000字的文章,需要多轮修改,那么上下文窗口需要能容纳:初始需求 + 前几版草稿 + 修改意见。这样才能让AI理解你的修改方向,保持文章风格的一致性。
场景三:长文档处理
如果你想让AI帮你分析一本10万字的书,并在分析过程中不断提问,那么你就需要选择支持超长上下文的AI,或者使用分段处理的技术手段(比如先让AI总结章节,再进行跨章节的讨论)。
类比:人类短时记忆的7±2法则
在心理学中,有一个著名的发现叫做"米勒法则"(Miller's Law):人类的短时记忆容量大约是7±2个信息块。
这意味着你可以同时记住7个左右的电话号码、7个左右的购物清单项目,或者7个左右的讨论要点。
AI的上下文窗口也可以类比为一种"机器短时记忆"。虽然它能容纳的内容比人类多得多,但原理是相似的:容量有限制,需要有选择地保留最重要的信息。
有趣的是,AI的"遗忘"方式和人类有些不同。人类倾向于记住最近的事情(近因效应),而对中间部分记忆较弱。AI也有类似的问题——当上下文非常长时,AI对中间部分的理解能力可能会下降。这就是为什么在设计prompt(提示词)时,把最重要的信息放在开头或结尾,往往比放在中间更有效。
Token是AI处理信息的基本单位
在讨论上下文时,我们不可避免地会遇到一个术语:Token。如果你阅读过关于AI的文章或文档,你可能见过这个词,比如"上下文窗口有4096个token"或"这个模型支持128K上下文"。
那么,Token到底是什么?
Token不是"字",也不是"词"
最直觉的理解是把Token理解为"字"或"词"。但实际上,Token的定义比这复杂一些。
Token是AI模型处理文本时的最小单元。
为了理解这个概念,我们需要稍微了解一下AI是如何处理文本的。现代AI模型(包括GPT系列)并不能直接理解文字,它们只能处理数字。因此,文本在被送入模型之前,需要先被转换成数字序列。这个转换过程叫做"分词"(Tokenization),而转换后的每个单元就叫做Token。
不同的语言、不同的模型,分词的方式也不同。对于英文,一个Token大约对应一个单词的70-80%,但也可能是单词的一部分(比如"eating"可能被分成"eat"和"ing"两个Token)。对于中文,Token的划分方式更加灵活,一个Token可能对应一个汉字、一个词,或者一个短语。
粗略地说,在中文语境下,1个Token大约等于1-2个汉字。在英文语境下,1个Token大约等于0.75个单词。
为什么用Token而不是"字"?
你可能会好奇:为什么上下文窗口用Token而不是"字数"来衡量?
原因有几个:
第一,不同语言的信息密度不同。 同样的内容,用中文表达通常比用英文更短。一个英文概念可能需要一整个句子,用中文可能几个字就说清楚了。如果用"字数"来衡量,对不同语言的用户就不公平。用Token可以更公平地衡量处理成本。
第二,Token是模型实际处理的单元。 AI模型并不直接处理"字"或"词",它处理的是Token。用Token来描述上下文窗口,是最直接、最准确的方式。
第三,便于计费和控制。 AI服务提供商可以根据Token数量来计费——你使用了多少Token,就收多少费用。这比按"字数"更公平,也更精确。
一个Token的直观感受
让我们通过一些例子,来建立对Token大小的直观感受:
| 内容 | 大约Token数 | |------|------------| | 一个汉字 | 1 Token | | 一个英文单词 | 1-2 Token | | "你好,世界!" | 4-5 Token | | 一个短句(如"我想吃苹果") | 3-5 Token | | 一段话(100字中文) | 50-100 Token | | 一页A4纸的文字 | 约300-500 Token | | 一封中文邮件 | 约200-500 Token | | 本章的一节内容 | 约1000-2000 Token |
当你使用AI服务时,通常会有"已用Token数"和"最大Token数"的提示。这可以帮助你了解上下文窗口的使用情况。
Token对实际使用的影响
理解Token的概念,对实际使用AI有什么帮助?
第一,帮助你估算对话长度。
如果你知道上下文窗口是4096个Token,而平均每个中文字符占1.5个Token,那么4096个Token大约相当于2700个汉字。在纯中文对话中,这大约是几千字的对话容量。考虑到AI的回复也会占用Token,实际可用的对话长度会更短一些。
第二,帮助你优化提示词。
有时候,你不需要把大量历史对话都放在上下文中。比如,如果你只是问一个简单的事实问题("珠穆朗玛峰有多高?"),不需要提供任何额外背景,直接问就好。这样可以节省Token,让对话更高效。
第三,帮助你理解为什么AI会"忘记"。
当你发现AI突然"不记得"之前的对话时,可能是因为对话已经超出了上下文窗口的限制。你可以检查一下对话的总长度,考虑是否需要通过摘要、总结或重新开启对话的方式来处理。
上下文决定了AI能否理解对话的连贯性
现在我们已经理解了上下文和Token的基本概念。让我们通过一个具体的例子,来看看上下文是如何影响AI对话体验的。
场景:跨文化沟通的比喻
想象你和一位外国朋友用英语聊天。如果你们的对话很短,比如:
> 你:Hi, where is the train station? > 朋友:It's two blocks away.
你能轻松理解朋友的回答。但如果对话变得很长,比如:
> 你:Hi, where is the train station? > 朋友:It's two blocks away. Go straight and turn left at the traffic light. > 你:Thanks! By the way, do you know if there's a good coffee shop nearby? > 朋友:Yes, there's a Starbucks on Main Street. It's quite popular. > 你:Is it within walking distance? > 朋友:Yes, it's about five minutes from here.
然后,过了很久、聊了很多其他话题之后,你突然问:
> 你:How far was the coffee shop again?
你的朋友会理解你问的是Starbucks咖啡店——因为在上下文中,你们刚才讨论过这个话题。你的朋友不需要"回忆",他只是"看"到了这个信息在你们的对话记录里。
AI的工作方式与此非常相似。
失败的例子:上下文丢失
让我们看一个因为上下文丢失而导致沟通失败的例子:
``` 第一轮: 小明:帮我写一首关于春天的诗
第二轮(对话已经很长了): 小明:再写一首关于秋天的诗
第三轮(对话更长了,超过上下文限制): 小明:写得像一点
此时,AI可能不知道"写得像一点"是什么意思—— 是像春天的诗?还是像秋天的诗?还是两个都要? 因为更早的上下文已经丢失了。 ```
在这种情况下,如果小明说"写得像秋天的诗一样",AI就能理解——因为"秋天的诗"这个信息还在上下文中。
成功的例子:上下文保持
同样的场景,如果上下文保持完整:
``` 第一轮: 小明:帮我写一首关于春天的诗
第二轮: AI:好的,我来写... (生成一首春天的诗)
第三轮: 小明:再写一首关于秋天的诗
第四轮: AI:好的,我来写... (生成一首秋天的诗)
第五轮: 小明:写得像一点,像秋天的诗那样
此时,AI能清楚地理解"像秋天的诗"是指第二轮生成的那首秋天的诗。 ```
区别在于:在第二个例子中,上下文还没有超出限制,所以所有信息都在,AI能正确理解"像秋天的诗"指的是什么。
上下文与"理解"的本质区别
这里有一个重要的点需要澄清:AI的"理解"和人类的"理解"是不同的。
当你对一个人说"像秋天的诗那样",人类会运用自己的知识——他见过秋天,知道秋天的特点(落叶、金黄、萧瑟等),所以他"理解"你在说什么。
但AI并不是这样工作的。AI的"理解"是基于上下文的——它看到你们之前确实讨论过"秋天的诗",所以它知道你在引用那段对话。它并不是真的"理解"秋天的含义,而是知道你在说"那首诗"。
这意味着:AI没有真正的"记忆",只有"上下文"。
当你重新开启一段对话,AI不会记得你们之前聊过什么。即使你们聊了几个小时,只要开启新对话,一切从零开始。这是因为上下文窗口在对话结束后就被清空了。
这也是为什么上下文工程(Context Engineering)变得如此重要的原因——你需要通过精心设计的提示词,让AI在有限的上下文空间内,保持对当前任务的理解和专注。
传话游戏:理解上下文重要性的生动实验
在了解了上下文的概念之后,让我们通过一个有趣的"传话游戏",来直观感受上下文的重要性。
什么是传话游戏
传话游戏大家应该都玩过:一群人排成一排,第一个人看一句话,然后小声传给下一个人,下一个人再传给下