你的每一次对话,都是第一次

先说个事:你跟 ChatGPT 聊天,它从来不记得你前面说过什么。服务器那边啥也没存。每次都是你的手机或电脑,把你们整个聊天记录重新发过去,模型看完给你回一句,然后服务器就把这事忘了------干干净净,跟第一次见你一样。

这就是大模型服务的"无状态"本质。

搞明白这个,你就能看懂现在所有的 AI 应用------不管是聊天机器人,还是那些看起来很厉害的智能体,底层全是同一套东西在跑。


你发的其实是全部聊天记录

直接看代码。这是我写的一个最简单的例子,用 DeepSeek 的接口来模拟一轮对话:

javascript

js 复制代码
import OpenAI from 'openai'

const client = new OpenAI({
    apiKey: process.env.DEEPSEEK_API_KEY,
    baseURL: 'https://api.deepseek.com'
})

// 我们自己记着聊天记录
const chatHistory = [
    { role: 'system', content: '你是一个严谨的助手' }
]

async function chat() {
    // 第一轮:告诉模型我叫什么
    chatHistory.push({ role: 'user', content: '请记住,我的名字是001' })

    const res1 = await client.chat.completions.create({
        model: 'deepseek-v4-flash',
        messages: chatHistory   // ← 把整个历史发过去
    })

    // 把模型的回复也记下来
    chatHistory.push({ role: 'assistant', content: res1.choices[0].message.content })

    // 第二轮:问它我叫什么
    chatHistory.push({ role: 'user', content: '请问我的名字是什么' })

    const res2 = await client.chat.completions.create({
        model: 'deepseek-v4-flash',
        messages: chatHistory   // ← 又把整个历史发过去
    })

    chatHistory.push({ role: 'assistant', content: res2.choices[0].message.content })

    console.log('第一轮回复:', res1.choices[0].message.content)
    console.log('第二轮回复:', res2.choices[0].message.content)
    console.log('聊天记录条数:', chatHistory.length)
    // 输出: 5 条 (系统提示 + 我的问题 + 模型回复 + 我的问题 + 模型回复)
}

chat()

第二轮发请求的时候,messages 数组里已经有 4 条消息了------系统提示、第一轮的问题、第一轮的回复、第二轮的问题。服务器拿到这一大堆,才能"推理"出我叫 001。

服务器那边看到的是这样:

text

js 复制代码
请求1 来了: ["你是严谨助手", "我叫001"]
         → 算完,回复,清空,忘了你

请求2 来了: ["你是严谨助手", "我叫001", "好的记住了", "我叫什么?"]
         → 算完,回复,清空,忘了你

两次请求中间,服务器什么都没留。模型好像"记得",只是因为我们的程序把历史消息又发了一遍。


这是故意这么设计的

为什么一定要这么设计?

想想看,要是每次聊天服务器都得替你记着------你是谁、聊到哪了、之前都说了啥------那一个人就得占一块地方。一万个人同时聊,就是一万份记录。这还是往少了算的,有的人可能聊了半小时,聊天记录攒了几十轮。

更要命的是多台机器一起工作的时候。

假如你有 10 台服务器轮流处理请求。要是服务器得记状态,那你的请求就必须每次发到同一台机器上,因为只有那台存着你之前聊的东西。这就叫"粘住",是搞服务器的人最头疼的事------万一那台机器坏了,上面所有人的聊天记录全没了。

不记状态就没这麻烦:

text

markdown 复制代码
请求来了 → 随便哪台机器 → 处理 → 忘掉
         → 下次换一台 → 一样处理 → 忘掉

每台机器处理每个请求的逻辑完全一样。加机器、减机器、换机器、更新系统------全变成普通操作。这就是网页请求原本的设计思路,大模型的接口也照着这么做了。


聊天记录的问题:钱在偷偷变多

这个设计有个很现实的麻烦:你聊得越久,每次发消息花的钱越多。

因为每次发请求,聊天记录里的每个字都会被算钱。聊到第 20 轮的时候,你说的每一句新话,都在替前面 19 轮的历史付钱。

简单算一下:

text

复制代码
第 1 轮: 花几十个字的钱
第 10 轮: 花两千个字的钱(历史堆起来了)
第 50 轮: 花一万五千个字的钱
第 200 轮: 花八万个字的钱

聊了两百轮,你最后一轮问的可能就二十个字,但你实际发出去的快八万个字。每一次发消息,都在替前面所有的历史买单。

而且各家模型价格差很多------便宜的一百万个字不到一块钱,贵的能到几十块。要是你的产品有一千个用户,一天几万次请求,这开销可不小。

还有一个不太容易注意的问题:模型注意力散掉了。

大模型一次能看的字数虽然越来越多,但它对长文字的处理不均匀。最前面和最后面的内容最受关注,中间的容易变模糊。你把几十轮之前的对话留在里面,它占着字数,但对模型帮你回答新问题,可能已经没用了。


于是有了三个阶段的改进

解决这些问题不是一步到位的。整个 AI 应用的开发,大概走了三步:

第一步:琢磨怎么说(提示词)

这步大家最熟。设计系统提示、给几个例子、调整措辞。本质上就是在"调参数"------通过改输入来影响输出。

但这儿有个很多人不说破的事:琢磨提示词很像抽奖。 你认真写的提示确实能提高好结果的概率,但不能保证。同样的提示跑十次,可能三次特别好、五次还行、两次完全不行。它让"中奖率"变高了,但离"能控制"还很远。

第二步:喂什么信息(上下文)

这步往前迈了一大块。思路变了:与其使劲打磨提示让模型"猜",不如直接把相关信息塞给它。

检索增强生成是最典型的做法------从知识库里搜出相关文件,拼进上下文,模型直接照着回答。各种工具和数据的接入,本质上也是同一件事:用标准的方式把东西塞进模型能看到的范围里。

核心道理:模型能做成什么样,由你给它的信息决定。 你给准的信息,它给准的答案。你让它瞎猜,它就瞎猜。

这步解决的是聊天记录"不够用"的问题------把真正有用的东西放进去,比把历史堆得老长有用得多。

第三步:让 AI 一直跑(循环)

这步是现在最前沿的。把模型从一个问一句答一句的工具,变成了能自己在循环里持续跑的"智能体"。

比如让模型自己读文件、写代码、跑测试、看报错、改代码、再跑,来回循环直到通过。

这步要解决的问题跟聊天记录直接挂钩:在长时间跑的循环里,管好上下文从"顺便弄弄"变成了"要命的事"。 一个智能体跑五十轮循环,如果不压缩和剪裁,花的钱会涨得很快,而且模型的注意力会彻底散掉。


回到开头

理解"不记事",是搞懂大模型应用的起点。

你写的每一个 AI 应用------不管多复杂、套了多少层框架------最底层都是同一件事:把一堆文字通过网络发给一个不记事的服务,拿回回复,把回复加到消息列表里,下次再一起发过去。

大模型没有记忆。"记忆"这件事,从头到尾是我们自己的程序在管。

搞明白这个,那些看起来花里胡哨的 AI 框架和架构,拆开看就都不神秘了。

相关推荐
不加辣椒1 小时前
第13章 检索增强提示工程
人工智能
小爷毛毛_卓寿杰1 小时前
我把 397B 的「Agentic 大脑」塞进了 Xinference,一键部署 Nex-N2
人工智能·架构·github
smallYoung1 小时前
Vibe Coding 笔记-中
人工智能
米小虾1 小时前
DSpark:让大模型"写得更快"的秘密武器
人工智能·deepseek
JavaGuide2 小时前
比 iTerm2 更适合 Claude Code/Codex 的终端,我换成 Ghostty 了
人工智能·后端
threerocks2 小时前
神级 Skill,作品个个儿爆,我开源了长期自用的手绘风格库
人工智能·aigc
小爷毛毛_卓寿杰3 小时前
我把一个 3B 模型塞进了 Xinference,然后它干掉了 DeepSeek V3.2
人工智能·开源·github
秦先生在广东3 小时前
Agent 闭环才是真正的护城河:Anthropic “300 个 Agent“ 背后被忽视的秘密
人工智能
Bigfish_coding3 小时前
前端转agent-【python】- 14 记忆系统优化:摘要与遗忘
人工智能