当你在和AI说话的时候,它在想什么?

乐云一
  • 笔记
  • note
About 3578 wordsAbout 12 min

当你在和AI说话的时候,它在想什么?

前两天在群里看到一位同事吐槽:"我让Copilot帮我改个接口,结果它给我写了个跟项目完全不同风格的代码,还得自己改半天,还不如我自己写。"

旁边另一位同事也附和:"我让它帮我排查个bug,就说'我的代码跑不起来',它给我回了一大堆通用排查步骤,没有一个有用的。"

这种场景太熟悉了。

说白了,大家用AI编程助手的时候,心里都默认了一个前提——它应该能"看到"我的整个项目,理解我的所有意图

但现实是残酷的:它既看不到你的整个项目,也猜不透你脑子里在想什么。

于是乎,问题来了:当你在和AI说话的时候,它到底能"看到"什么?

搞清楚这个问题,你的AI使用体验会从一个"不太聪明的助手"直接升级到"还挺靠谱的搭档"。

什么是"上下文"

你跟一个新来的同事说"帮我改一下那个东西",他会一脸懵——因为他不知道"那个东西"是哪个东西。

AI也一样。它需要足够的信息才能给出有用的回答,这些信息就叫上下文(Context)

当你在IDE里打开Copilot的对话框,敲下一行"帮我写个接口"的时候,AI能"看到"的东西大概有这么几类:

  • 当前文件内容:你现在正在编辑的那个文件,AI是能看到的
  • 默认提示词:比如你在.github/copilot-instructions.md里写的那些约定,每次都会自动加载
  • 聊天记录:同一个对话窗口里你们之前聊过的内容
  • 项目结构:文件目录、部分关联文件(但注意,是"部分")
  • 你主动粘贴/引用的代码片段

用生活场景来打个比方:

你去医院看病。医生能获取的信息就是你的病历本(当前文件)、你之前在这家医院的就诊记录(聊天记录)、你主诉的症状(你的输入)。但如果你什么都不说就往那一坐,医生再厉害也只能给你开个常规检查。

AI的上下文就是它的"视野范围",超出这个范围的东西,它真的一无所知。

Token——AI的"记忆单位"

聊上下文就不得不聊一个核心概念:Token

你可能经常看到这个词,但一直没搞明白它到底是什么。简单来说:

Token是AI处理文本的最小单位,你可以把它理解成AI的"记忆单元"。

我们写代码用的是字符,但AI不直接读字符,它先把文本"切碎"成一堆Token,然后再理解和处理。

举几个实际的例子感受一下:

文本内容大约Token数
Hello, World!3-4 个
你好世界6-8 个(中文消耗更多Token)
一个50行的函数200-400 个
一整个Java文件(500行)2000-4000 个
一个中等项目所有代码几十万甚至上百万个

注意到没有?中文消耗的Token比英文多。因为大部分大模型的分词器是按英文优化的,一个中文字可能要拆成2-3个Token。

所以当你发现用英文提问AI回答更"聪明"的时候,不一定是它在装,可能真的是Token太吃紧了。

上下文窗口——AI的"工作台面"

每个AI模型都有一个**上下文窗口(Context Window)**的限制,说白了就是它能一次性处理的Token上限。

打个比方:

AI的上下文窗口就像你的工作台面,就这么大,东西多了就放不下。你的办公桌能同时摊开几本书、几份文件?摊太多了,重要的东西反而被埋在下面找不到。

目前主流编程助手的上下文窗口大小:

  • Copilot(GPT-4系列):约128K Token,换算下来大约96,000个词
  • Claude系列:200K Token
  • 国产大模型:128K ~ 256K不等

96,000个词听着很多对吧?但你想想,一个正经项目的代码量——随便一个SpringBoot项目,光依赖的源码就上百万Token了。你的业务代码加上配置文件、数据库脚本、前端代码……早就爆了。

所以AI不可能一次性"看完"你整个项目的所有代码,这是物理限制,不是它不想。

AI到底是怎么处理你的请求的

知道了上下文和Token的概念,我们来看看当你按下回车键的那一刻,到底发生了什么:

你输入问题
    ↓
IDE(如VSCode、IDEA)
    ↓
Copilot后端开始收集上下文
    ├── 当前文件内容
    ├── 关联文件(通过import、调用关系推断)
    ├── 项目结构(目录树)
    ├── copilot-instructions.md(如果有)
    ├── 聊天记录
    └── 你引用/粘贴的额外代码
    ↓
把收集到的上下文 + 你的问题 组装成一个"大文本"
    ↓
发送给AI模型
    ↓
模型在上下文窗口内理解并生成回答
    ↓
返回结果到IDE

用Mermaid时序图来看,整个流程更清晰:

关键环节是**"收集上下文"这一步**。

Copilot(以及其他AI编程助手)并不是傻乎乎地把所有代码都塞进去——它也没法这么做,上下文窗口装不下。它会用一套策略来挑选最相关的信息:

  1. 当前文件:权重最高,基本都会加载
  2. 打开的标签页:你IDE里同时打开的其他文件
  3. 代码引用链:通过import、函数调用等关系找到的关联文件
  4. 语义搜索:用你的问题去项目里搜相关代码片段

注意这个"挑选"过程。它意味着:如果相关信息没有被"选上",AI就完全不知道它的存在

这就是为什么有时候AI给出的答案会让你拍桌子——不是它笨,是它压根没看到。

两个最常见也最致命的误区

误区一:AI能"看到"整个项目

真相:AI大部分时候是在"搜索"和"猜测",不是在"阅读"。

很多人以为打开Copilot聊天框的那一刻,AI就已经把整个项目代码都过了一遍。这个想法很美好,但完全不是事实。

实际情况是:Copilot会根据你的问题去项目里搜索相关代码片段,然后把搜到的片段塞进上下文里。搜索结果好不好,直接决定了AI回答的质量。

这就像你在公司里问一个同事问题,他不会先把公司所有文档都读一遍再回答你,而是先想想"这个问题大概跟哪些文档有关",然后去翻那几个文档。

所以如果你的问题太模糊,搜索出来的结果就不对路,AI自然就答非所问了。

误区二:给的上下文越多越好

真相:无关信息会"淹没"关键信息,反而降低回答质量。

有些同学知道上下文的重要性之后,就开始疯狂地往对话里塞东西——整个文件、整个目录的代码全贴进去,觉得"信息越全,AI越聪明"。

但事实恰恰相反。

想象一下你在考场上做阅读理解。卷子上就一篇短文,你能精准找到答案。但如果在短文前面又给你塞了十篇无关的文章,你的注意力就会被分散,找答案反而更慢更不准。

AI也一样。上下文窗口就那么大,塞了一堆无关代码进去,真正重要的信息反而被"稀释"了。学术上有个词叫"注意力稀释",说白了就是——东西太多,AI抓不住重点了

正确做法是:只给AI跟当前任务直接相关的信息,宁精勿滥。

实战:不同上下文质量,完全不同的结果

光说理论没感觉,来看三个真实案例。

案例一:创建一个API接口

低质量上下文:

帮我写一个获取用户列表的接口

AI的处境:不知道你的项目用什么框架,不知道返回格式规范,不知道数据库表结构,不知道你习惯用MyBatis还是JPA……

结果:给你一个通用的SpringBoot接口,返回格式大概率不符合你项目的统一封装,字段命名风格可能也不对。

高质量上下文:

[项目信息] Java8 + SpringBoot + MyBatis-Plus
[返回格式] 统一使用Result<T>封装,参考Result.java
[分页要求] 使用Page<T>分页,参考PageResult.java
[表结构] 用户表sys_user,字段:id, username, email, status, create_time
[命名规范] 驼峰命名,Mapper继承MpBaseDao

帮我写一个获取用户列表的分页查询接口,支持按username模糊搜索,按status过滤

结果:生成的代码直接能跑——Controller、Service、Mapper分层清晰,分页参数校验完整,返回格式跟你项目一模一样。

差距在哪? 第二种告诉了AI框架选型、返回格式、表结构、命名规范——这些都是它无法"猜"出来的信息。

案例二:重构一段代码

低质量上下文:

// 直接丢一段代码过去
public void processOrder(Order order) {
    // 50行处理逻辑...
}

帮我重构这段代码

AI不知道这段代码在项目里是什么角色、有什么性能要求、调用链是什么样的。结果可能给你一个"看起来很优雅但完全脱离项目实际"的重构方案。

高质量上下文:

[项目背景] 订单处理模块,当前这段代码耦合了验证、计算和持久化逻辑
[性能要求] 这段代码是高频调用路径,QPS约500,重构后不能引入额外性能损耗
[技术栈] Java8 + Spring + MyBatis-Plus
[重构目标]
1. 拆分职责,符合单一职责原则
2. 保持对外接口不变(processOrder方法签名不动)
3. 方便后续扩展新的订单类型
[约束] 不要引入新的外部依赖,只用项目中已有的工具类

以下是待重构的代码:
```java
public void processOrder(Order order) {
    // 50行处理逻辑...
}

结果:AI会给你一个务实的重构方案——策略模式处理不同订单类型、校验逻辑独立抽取、不引入新依赖,而且保持接口兼容。

**差距在哪?** 第二种明确了重构的目标、约束和边界,AI不会"过度设计"也不会"脱离实际"。

### 案例三:排查Bug

**低质量上下文:**

我的代码跑不起来了,报错了,帮我看看


AI连你的代码都没看到,报什么错也不知道,用什么环境也不清楚。它能做什么?给你列一堆"常见报错排查步骤",等于什么都没说。

**高质量上下文:**

[环境] Java8 + SpringBoot 2.7 + MySQL 8.0 [报错信息] org.springframework.dao.DataIntegrityViolationException:

Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException:

Duplicate entry 'ORDER_20250420_001' for key 'uk_order_no'

[相关代码]

@Transactional
public void createOrder(OrderDTO dto) {
    Order order = new Order();
    order.setOrderNo(generateOrderNo()); // 生成订单号
    orderMapper.insert(order);
}

[复现条件] 并发场景下,多个线程同时创建订单时偶现 [已尝试] 我确认数据库里没有重复数据,generateOrderNo()方法有加时间戳

请帮我分析这个唯一键冲突的原因并给出修复方案


结果:AI直接定位问题——`generateOrderNo()`在高并发下可能生成重复的订单号,时间戳精度不够导致碰撞。修复方案:用雪花算法或者数据库序列,或者在`generateOrderNo()`里加分布式锁。

**差距在哪?** 第二种提供了报错信息、相关代码、复现条件、已尝试的操作。这些信息让AI能**精准定位**问题,而不是瞎猜。

## 一个好用的提问模板

总结上面的案例,可以提炼出一个实用的提问模板:

[场景定位] 你在做什么 [技术栈] 用了什么框架/版本 [具体问题/需求] 你要AI帮你做什么 [关键约束] 不可协商的条件(性能、兼容性、规范等) [相关代码/错误信息] 直接相关的代码片段或报错堆栈 [输出要求] 你期望AI怎么回答(分层输出?只给方案不改代码?)


不是每次提问都要把所有元素填满,但至少要包含**场景定位**和**具体问题**。其他元素根据实际情况补充——信息越精准,回答越靠谱。

## 写在最后

回到开头那个问题:当你在和AI说话的时候,它在想什么?

答案是——**它在想你能让它"看到"的那些东西**。

它看不到你脑子里对"那个东西"的定义,看不到你没打开的文件,看不到你项目里没被搜索到的代码,更看不到你没说出口的需求和约束。

**你和AI之间的沟通质量,完全取决于你给它多少有效的上下文。**

下次AI给你一个让你想砸键盘的回答时,先别急着骂它笨。想想看:你给它的信息,够不够它做出一个聪明的回答?

> 记住:**AI不是你的同事,它不会主动问"你说的是哪个接口?"、"你的报错信息是什么?"。它只会基于你给的信息尽可能地去回答——给多少,它就理解多少。**

搞懂上下文机制之后,你会发现AI编程助手从一个"有时好用有时不好用的工具",变成一个"只要你沟通到位就一直好用的搭档"。
Last update:
Contributors: LeYunone
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.14.7