为什么你的 Token 总是不够用?先想清楚这件事

很多刚接触 AI 编程的朋友,上来就把大段报错、整份文件、甚至整个项目目录丢给模型,然后抱怨“上下文窗口不够”“Token 烧得太快”。其实,Token 的本质是信息密度——你用越少的字符传递越完整的信息,模型就能用越多的“算力预算”去思考真正的逻辑问题,而不是浪费在解析冗余文本上。

我在代码客(daimake.cn)的建站教程里反复强调过:AI 编程不是“聊天”,而是“协作”。既然是协作,表达效率就是第一生产力。下面这套方法,是我在写小程序源码和部署课程时实际验证过的,能帮你把单次对话的 Token 消耗降低 30%—50%,同时让回答质量不降反升。


一、提问前先“压缩”你的问题

1. 去掉所有寒暄与背景铺垫

“你好,在吗?”“我有个问题想请教一下,可能有点复杂,希望您能帮我看看……”——这些全部是无效 Token。直接说需求,模型不会觉得你失礼。

反面示例(浪费约 80 Token):

你好,我最近在做一个 WordPress 网站的二次开发,遇到一个很奇怪的问题。我在 functions.php 里加了一段代码,想实现文章浏览量统计,但是不知道为什么,它只在首页生效,在单篇文章页面就不工作了。我查了很多资料,有人说要加 global $post,我也加了,还是不行。你能帮我看看吗?谢谢!

优化后(约 35 Token):

WordPress 单篇文章页,functions.php 里用 global $post 统计浏览量,只在首页生效。如何修复?

2. 用“动词+对象+约束条件”的句式

把你的需求拆成机器能理解的结构:你要做什么、在什么环境下、有什么限制

  • 示例:“写一个 Python 函数,接受 URL 列表,返回状态码非 200 的项,要求用 requests 库,不要额外依赖。”

这比“帮我写个爬虫检查一下哪些链接坏了”要节省大量来回追问的 Token。


二、给代码上下文时,学会“抽筋扒皮”

这是最容易被忽视的 Token 黑洞。很多朋友把整个文件 300 行贴进去,就为了问其中第 150 行的一个报错。正确做法是:

1. 只贴最小复现片段

保留与问题直接相关的函数、类、变量定义,其余逻辑用注释或伪代码代替。

低效做法(贴整个 controller,约 500 Token):

public function update(Request $request, $id)
{
    $post = Post::find($id);
    if (!$post) return response()->json(['error' => 'not found'], 404);
    // ... 中间 50 行与问题无关的权限校验、日志记录
    $post->title = $request->input('title');
    $post->save();
    return response()->json($post);
}

高效做法(只贴问题行 + 必要变量,约 80 Token):

// 在 update 方法中,$post->save() 后返回 500,但同代码在 create 方法正常
public function update(Request $request, $id)
{
    $post = Post::find($id);
    $post->title = $request->input('title');
    $post->save(); // 报错行
}

2. 用“diff 格式”描述改动

如果是修改已有代码,直接贴改动前后的差异,而不是整段代码。你可以手动整理,也可以让模型先帮你生成 diff。

示例:

- $post->status = $request->has('status') ? 1 : 0;
+ $post->status = $request->boolean('status') ? 1 : 0;

3. 明确告诉模型“只看这段,忽略其他”

在代码块前加一句“以下为独立函数,不依赖项目中其他类”,能防止模型为了“理解上下文”而臆想不存在的依赖关系,输出大量无关建议。


三、报错信息:只截取关键行,别整屏复制

报错日志动辄几十行,真正有用的往往只有 Exception 类型 + 文件路径 + 行号

反面示例(贴 200 行堆栈跟踪):

Traceback (most recent call last):
  File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "...", line 123, in run
    result = self.func(*args)
  ...

优化后(约 20 Token):

# 报错:TypeError: 'NoneType' object is not subscriptable
# 位置:/home/user/project/parser.py 第 45 行,data['items'][0]['title']
# 环境:Python 3.10, requests 2.31

如果你不确定哪一行是关键,用这条指令:

请从下面完整报错中提取最可能的 3 个原因,并告诉我需要提供哪几行代码才能进一步定位。完整报错如下:……

这比直接贴完整日志,能省下 60% 以上的 Token,而且模型会主动引导你给出有效信息。


四、善用“角色设定”与“输出约束”

在第一次提问时,用一行字设定模型的行为边界,能避免后续大量纠偏对话。

示例(加在问题开头):

你是一位有 10 年经验的 PHP 工程师,请用最简洁的代码解决下面的问题。只输出修改后的代码,不要解释原理,除非代码中有安全隐患。

输出约束的关键词:

  • “只输出代码” —— 省去模型写“好的,以下是……”这类废话。
  • “不要用 Markdown 表格” —— 当你要复制结果时。
  • “如果方案超过 20 行,请先列出思路让我确认” —— 防止模型一次性生成大段跑偏代码。

五、用“伪代码 + 自然语言”混合描述逻辑

当你需要实现一个复杂功能,但不确定具体 API 时,用结构化伪代码代替长篇大论:

低效描述(约 120 Token):

我想实现一个功能,就是用户注册的时候,如果邮箱已经存在,就提示他换一个,如果不存在就注册成功,同时给他发一封欢迎邮件,邮件里要带一个验证链接,链接有效期是 24 小时。

高效描述(约 60 Token):

# 用户注册流程
if email_exists(email):
    return "该邮箱已注册,请直接登录"
else:
    create_user(email, password)
    token = generate_token(email, expire=24h)
    send_email(email, template='welcome', data={link: f"/verify/{token}"})

模型一眼就能看懂逻辑结构,直接就能翻译成 Laravel、Django 或 Node.js 代码,不需要再追问“你是用什么框架?”“邮箱验证要不要异步?”等额外问题。


六、多轮对话的 Token 管理策略

1. 主动关闭已解决的分支

当一个问题解决后,明确说“这个问题已解决,接下来进入下一个问题”,并另起一段描述新需求。别让模型继续在旧上下文里打转。

2. 定期“总结 + 重置”

如果对话超过 5 轮,且主题有偏移,用这条指令:

请用 100 字以内总结我们刚才确认的解决方案。然后我将开始一个全新的、不相关的问题。

这等于手动给模型“清理缓存”,避免它把之前讨论的无关细节带入新任务。

3. 把重复的“项目背景”写进系统提示词

如果你在同一个项目上要问几十个问题,不要每次都重新描述项目结构。可以开一个新对话,第一句话固定为:

项目背景:ThinkPHP 6.0 + MySQL 8.0,现有 User 模型、Order 模型,均使用标准关联。请基于此背景回答下面每个问题,不要重复询问环境。


最后一条实操建议:把“省 Token”变成肌肉记忆

每次发消息前,停顿 3 秒,问自己三个问题:

  1. 这段内容删掉一半,模型还能理解吗?
  2. 我是在描述问题,还是在讲故事?
  3. 有没有更精简的代码片段可以代替这段文字?

你在代码客看到的每一篇源码解析、每一个部署教程,本质上都是“信息压缩”的产物——把几百页文档浓缩成可执行的步骤。AI 编程也一样,你压缩得越狠,模型的输出就越精准,你的 Token 预算就越耐用。这不仅是省钱,更是让你的每一次提问都直击要害。