写在前面
我本身并不热衷于体验新工具,但是我的同桌是个喜欢尝鲜的人,去年就已经给我疯狂安利 AI 了,当时我嗤之以鼻,现在我逐帧学习😶🌫️。
记得早前 AI 开始出现的时候,它的使用方式就是一问一答,我有什么问题就去咨询 AI,然后复制粘贴。去年我对 AI 编程的概念仍停留在加强版的自动补全,下意识觉得它不能拿来做事。今年年前 AI 风气我感觉也还没那么盛行,虽然期间各种模型也是不断迭代,但我还是停留在一问一答的模式吧!
年后不知道怎么的,突然大家都开始疯狂用 AI 了,就真的,很突然😲,公司也开始推了。用了之后就一发不可收拾了,这东西是真的香,搞的我现在都不会写代码了,大部分情况都是在 pua AI 写需求改 bug,自己则在摸鱼、等待、review 和验证,它实实在在的改变了开发流程。
所以本篇文章主要记录下我眼中 AI 的演变过程,文末还会附上几个常见的经典问题🔥。
prompt 如何演进
其实大模型(LLM)出现也才三年时间,一路走来,就两个东西变了:
- 大模型自身变强了
- 人们约束变多了
大模型的本质是预测下一个词出现的概率,化简来看就是一个巨大的函数 y=f(x, θ),输入 x,输出越来越准确的 y。这里我们不去讨论模型本身如何迭代(我也不懂啦,这种东西看完即忘😂),因为大部分情况我们是在给模型加约束。提到大模型,经常会蹦出一堆词:
Prompt -> Tool -> MCP -> Agent -> Skill -> Harness
听起来一个比一个高级,很多时候也容易混在一起,实际上你可以理解为从左到右就是给模型的上下文约束越来越多。大模型的能力确实越来越强了,但是它不能保证每次执行的效果都很好,所以为了把不确定的事情转换为确定的事情,就有了各种各样的约束和规范。它给我的感觉就是大概是这个样子:本来是一匹马儿能在大草原上随意奔跑,现在有了栅栏,马儿只能在合适的范围内奔跑:
接下来让我们来以一个简单的问题来推演一下 prompt 的演变过程:
今天适合骑车上班吗?
1、纯 prompt
假设你直接问模型这个问题,早期的模型可能会回答:
如果天气晴朗、路程不远,今天是适合骑车上班的。
乍一看,好像没毛病。但问题是:它真的知道今天的天气吗?它知道你在哪吗?它知道你几点出门吗?它知道你的上班路线吗?都不知道。所以这个回答本质上不是判断,而是根据常识补了一段“看起来合理”的话,纯 Prompt 的流程大体如下:
用户:今天适合骑车上班吗 -> LLM 读取上下文 -> 根据 LLM 预测下一个 token -> 生成一个看似合理的建议
纯 prompt 能做什么?
- 解释骑车通勤要注意什么
- 总结骑车的优缺点
- 写一段通勤建议
- 给一些常识性提醒
但它没法真正判断你今天适不适合骑车,因为这个问题需要实时信息和个人上下文。
2、Prompt Engineering
后来大家发现,模型虽然容易猜,但如果我们把要求写清楚,它会稳很多。这时候我们通常会把输入改成:
你是一个通勤建议助手。
用户问今天适合出行吗之类的问题时,不要直接下结论。
请先判断是否缺少城市、通勤时间、通勤距离、天气信息。
如果缺少关键信息,请先追问。
如果没有实时工具,请明确说明无法判断实时情况。
那模型可能会回答:
我需要知道你的城市、出发时间和通勤距离,才能判断今天是否适合骑车。如果没有实时天气和路线工具,我只能给出一般性建议。
这就靠谱多了。Prompt Engineering 的本质不是让模型突然知道了真实世界,而是让模型别太自由发挥。就像你带新人做事,如果你只说“帮我看看能不能骑车”,新人可能随便回答一句。但如果你说“先确认城市,再查天气,再看通勤时间,最后按适合/不适合/谨慎骑行回答”,这个事情就稳定很多了。
一个好的 Prompt 大体会具备以下这些描述:
| 要素 | 在这个例子里怎么写 | 作用 |
|---|---|---|
| 角色 | 你是通勤建议助手 | 限定回答身份 |
| 任务 | 判断是否适合骑车上班 | 明确目标 |
| 缺失信息 | 城市、时间、距离 | 避免瞎判断 |
| 约束 | 没有实时数据就说明 | 减少胡编 |
| 输出格式 | 结论 + 原因 + 建议 | 让回答稳定 |
所以这个阶段也涌现了一些提示词工程师、提示词收藏家、提示词卖家等,不过这些都是一次性的文本片段,很难持续维护和演进。另外还有一个根本问题就是: Prompt 写得再好,模型也不会凭空知道今天下不下雨。所以接下来Tool 出现了。
3、Tool
有了 Tool,事情就开始变得像样了,因为模型终于可以“查一下”了。
用户还是问:今天适合骑车上班吗?模型则可以先判断:
这个问题需要实时信息,我得查天气。
于是它开始调用天气工具,拿到温度、降雨概率、风力、空气质量、未来几小时的天气情况。然后再回答:
今天上午小雨,风力 4 级,路面可能湿滑,不太建议骑车;如果一定要骑,建议穿防水外套并避开高峰路段。
这就不是纯靠猜了。这是工具查询 + 语言组织的结果。Tool 阶段的流程如下:
用户:今天适合骑车上班吗 -> LLM 判断需要实时信息 -> 调用天气工具 -> 返回天气数据 -> LLM 生成通勤建议
这一步很关键。因为从这里开始,LLM 不再只是一个“会说话的模型”,而开始变成一个“能连接外部世界的模型”。不过 Tool 也有问题。如果只查天气,一个工具绰绰有余;但“骑车上班”显然不只需要天气信息,它可能还要查:
- 地图路线
- 通勤距离
- 路况
- 用户偏好
- 公司打卡时间
- 是否有共享单车点位
工具一多,问题就来了。每个工具都有自己的接口、参数、鉴权、返回格式。如果都让模型一个个硬接,这不得炸了。好在编程领域对这种问题早有成熟的解决方案,就是加个中间层,统一各种接口规范,于是 MCP 登场了。
4、MCP
MCP 解决的问题不是“模型会不会思考”。它解决的是:模型怎么稳定、统一、安全地连接和调用一堆外部工具。没有 MCP 的时候,LLM 和工具之间的关系就像下面这样子:
这就像你桌上有一堆设备:一个圆孔、一个方孔、一个老式 USB、一个专用接口、一个还得单独装驱动。每接一个新设备,都要折腾半天。有了 MCP 之后就不一样了,它变成了一个插座:
回到原来的问题“今天适合骑车上班吗”,Tool 解决的是:能不能查天气、查路线、查日历?MCP 解决的是:这些工具能不能用统一方式接进来、被发现、被调用、被治理?它的好处在于:
| 无 MCP | 有 MCP | 变化 |
|---|---|---|
| 每个工具单独适配 | 工具按统一方式暴露 | 接入成本下降 |
| 模型不知道有哪些工具 | 可以发现可用工具 | 调度更清楚 |
| 参数格式各不相同 | 输入输出更结构化 | 更容易编排 |
| 权限散落各处 | 可以集中治理 | 更适合企业落地 |
当然有时候我们也把内部工具叫 Tool,外部工具称为 MCP。
5、Agent
有了 Tool 和 MCP 之后,模型就能接各种各样的工具了。但“今天适合骑车上班吗”这个问题,依然不是调用一个工具就能解决。如何更好的统筹调度这些工具,那就要提到 Agent 了。一个像样的 Agent 应该会自己拆任务:
- 先确认用户在哪个城市
- 查询今天通勤时段天气
- 查询骑车路线和距离
- 判断是否下雨、风大、空气差
- 看用户日历有没有早会
- 综合给出建议
- 如果不适合骑车,给替代方案
这个阶段模型已经不只是回答问题,而是在完成任务。Agent 的流程大概是下面这个样子:
Agent 的核心:不是更会聊天,而是更会安排步骤,能做具体的事情了。以前你要一步步告诉模型:先查天气,再查路线,再看我有没有会议,最后给建议。现在你只说“今天适合骑车上班吗”,它自己就会拆解。当然 Agent 也会带来新问题:它会不会乱调用工具?它会不会查不该查的数据?它失败了怎么办?它调用太多工具浪费成本怎么办?它给错建议谁兜底?可能中途出错了,你纠正一下可以了,但是下次它也许还会犯同样的错误。
所以光有 Agent 还不够,我们还需要把常见任务沉淀下来,把这些上下文封装成稳定能力,这时候 Skill 出现了。
6、Skill
Tool 是一个工具,MCP 是统一接口,Agent 是会自己拆步骤的执行者,Skill 则更像是一套封装好的专项能力,一个成熟的 SOP。判读“今天是否适合骑车上班”,它不只是调用工具,还包含了一套稳定流程:
这很像写代码。你当然可以每次都手写:先查天气,再查路线,再看会议,再判断是否适合骑车。但写多了你会发现:这不就是一个固定能力吗,为什么不封装起来?
Skill 的价值就在这里。它把反复出现的任务,封装成一个可复用的能力包,而这个能力包不是代码,就是一个普通的 md 文件,上手成本极低。Skill 里面通常会定义什么时候触发、需要哪些信息、缺信息时怎么追问、调哪些工具、判断规则是什么、输出格式是什么、哪些行为不能做。所以 Skill 比纯 Agent 更稳定。Agent 像“临场发挥的执行者”,Skill 像“训练好的标准动作”。不仅如此,它还把一次性 prompt 变成了可持续维护的文档。
“写 Skill 很简单,但写好 Skill 很难。” 能够稳定运行的 Skill,背后往往意味着大量的试错、边界条件处理以及持续维护,还是需要专业的人来沉淀会更好一些,他们最了解工具能力的边界,也最清楚真实场景中的最佳使用方式,然后再共享出去。
7、Harness
是的,Harness 就这样突然出现了😂,它是真正让 LLM 应用落地的底座。到这里,我们其实已经从“模型能力”聊到“工程系统”了。真正落地时,最麻烦的往往不是模型本身,而是下面这些问题:
- 用户位置能不能用?
- 日历权限谁来管?
- 工具调用失败怎么办?
- 多个工具结果冲突怎么办?
- 用户隐私怎么保护?
- 模型能不能调用打车工具?
- 能不能自动发消息?
- 日志和审计怎么做?
- Skill 怎么加载?
- MCP Server 怎么管理?
这些东西加在一起,就接近 Harness,所以 Harness 也不是才出现,它一直都有,只是现在拥有了合适的名字。这样一来,Harness 视角下的“骑车上班”就变成了:
最终用户看到的可能只是一句话:
今天不太适合骑车。上午小雨,风力偏大,而且你 9 点有会,建议坐地铁;如果骑车,建议提前 20 分钟出门并带雨衣。
但系统在背后其实做了很多事:理解意图、判断需要哪些信息、检查权限、调用工具、综合分析、生成建议、控制边界、返回结果。所以现在做 LLM 应用,拼的已经不只是“模型会不会回答”,更重要的是:有没有一套系统,能让模型稳定、安全、可复用地完成任务。
演进小结
这里简单再用“今天适合骑车上班吗”来总结 prompt 的进化,大概是这样:
1、纯 Prompt:“如果天气好,骑车上班挺不错。”
2、Prompt Engineering:“我需要先知道城市、时间和通勤距离,不能直接判断。”
3、Tool:“我查了一下,今天上午有小雨。”
4、MCP:“天气、地图、日历这些工具,可以按统一方式接进来。”
5、Agent:“我查了天气、路线和日历,发现你 9 点有会,骑车风险有点高。”
6、Skill:“我可以稳定完成‘通勤方式建议’这个任务。”
7、Harness:“我能在权限、安全、上下文和工具编排都可控的系统里完成这件事。”
模型的进化不是从“不会聊天”到“会聊天”,而是从一个会预测下一个 token 的模型,逐渐变成一个能连接真实世界、调用外部工具、拆解任务、复用技能,并被工程系统安全托管的智能执行单元。这和前端工程也有点像,一开始写几个页面,直接写就行;后来页面多了,需要组件;组件多了,需要状态管理;项目大了,需要工程化;团队协作了,需要权限、规范、发布、监控。LLM 也是一样,一开始一个 Prompt 就能玩;后来要接 Tool;工具多了要 MCP;任务复杂了要 Agent;流程稳定了要 Skill;真正落地还得有 Harness。毕竟,用户真正想要的,也不是一句漂亮话。
这里用表格加深下记忆(其实演进顺序不完全正确,但不用在意这些细节😬):
| 概念 | 类比 | 作用 | 骑车上班例子 |
|---|---|---|---|
| LLM | 大脑 | 理解和生成 | |
| Tool | 手 | 做具体动作 | 查天气、查路线 |
| MCP | 插座 | 标准化连接工具 | 让天气、地图、日历统一接入 |
| Agent | 执行者 | 拆解并推进任务 | 自己决定先查什么后查什么 |
| Skill | 专项技能 | 稳定复用能力 | 骑车通勤建议助手 |
| Harness | 身体和安全系统 | 托管、编排、治理 |
常见疑惑
感觉 skill 好像也还是 prompt?
仔细看看,skill 好像和最初的 prompt 区别好像不大,你 prompt 写完整点,也可以是 skill,毕竟都是自然语言描述的 md 文档,也都能复用。你可以直接把所有 prompt 片段全部塞进上下文;也可以先人工挑选出需要的 prompt 再喂给大模型,这两个操作都是 ok 的。那 skill 的优势在哪呢:
- token 成本低
- 上下文占用少不冗余
- 缓存命中率高
- 可持续迭代
- 更适合编排
prompt 能承载经验,但不适合承载很多经验。
为什么“预测下一个 token”能涌现推理能力?
大模型的本质是预测下一个词出现的概率,而“把下一个 token 预测对” 这件事,本身就逼着模型去学习很多比表面文字更深的结构,能够从更多维的角度去找到事物背后千丝万缕的关系。更准确的说,在真实语言数据里,要想持续预测正确,模型不得不学习隐藏在文本背后的状态跟踪、规则组合、因果链条和中间计算过程,推理能力可以看作这种高质量序列建模的副产品,当然这也是量变引起质变的效果。
如果是概率推测的话,那为什么同样的输入会有不同的输出结果呢?
因为模型输出的通常不是 “唯一正确的下一个 token”,而是 “一组候选 token 的概率分布”,我们提供的任意信息都会影响模型的生成结果。所以更准确的描述是“在给定上下文中,从一组候选词中挑选出下一个最合适的”,这个挑选过程就导致了结果的随机性,当然这个是有参数可调的,我们叫做温度(Temperature),温度是控制大模型输出“随机性/创造性”的一个参数:
- 温度越低,输出越确定、越保守、越趋于一致(
好像八股文) - 温度越高,输出越发散、越有创造性(
好像散文)
有时候我觉得 AI 用的好不好也是个概率问题,用的好说明你的描述符合 AI 胃口罢了。现在的优化也是提示词优化,对当前来说可能效果好,后续也可能变差,单纯的模型升级也不能保证效果比以前好,然后你就需要对提示词进行一些修修补补,好听点就是优化。
模型为什么会产生幻觉?
幻觉(Hallucination)不是模型 “撒谎”,而是它在 “猜下一个词” 的机制下,被迫生成了它其实并不知道的内容。大模型本质上是一个语言概率预测器,不是一个事实数据库。它总是要输出些什么,即使它其实没有可靠依据。这就是幻觉的根源,所以当它遇到不熟悉的问题时,它并不会停下来,而是继续生成最 “像正确答案” 的文本,听起来对,但可能不对。
每次请求到底给大模型发送了什么内容?
大模型本身是无状态的:它不会记住上一次的请求,所以每次都要把它“需要看到的所有信息”一次性重新发过去。假设你问一个 AI:“帮我总结上一封邮件”,实际发给模型的内容可能是这样(伪结构):
{
"model": "xxx-pro", // 模型标识
"messages": [ // 一组消息列表,包括系统提示词 && 历史对话 && 本轮用户输入
{
"role": "system",
"content": "你是企业助手,遵守以下规范……输出使用中文……"
}, {
"role": "user",
"content": "帮我看看这周日程"
}, {
"role": "assistant",
"content": "本周你有 3 个会议……"
}, {
"role": "user", // 你的本次输入在这里
"content": "帮我总结上一封邮件\n\n[邮件正文粘贴在这里]"
}
],
"tools": [ // 可选工具,tool 或者 skill 就在这里
{"name": "get_email", "description": "...", "parameters": {...}},
{"name": "search_docs", "description": "...", "parameters": {...}}
],
"temperature": 0.3, // 采样参数:温度
"max_tokens": 1024, // 采样参数:最多生成多少 token
"stream": true // 其它元信息:是否流式返回
}
直接训练一个代码模型有没有搞头?
现在的大模型通常是在一个已经预训练好的基础模型上,用特定领域的数据集后训练成一个“新”模型。那能不能直接跳过通用模型,只用特定领域数据训练一个小而专的模型?
当然是可以的,早期的 AI 代码补全也是这么做的。但只喂代码语料,模型在编码上也许会更确定,但另一个问题是它可能看不懂正常提示词。于是我们为了改善模型输入理解,又需要不断扩充基础语料,最终又会把它“训回”成一个通用模型。所以相比造一个纯粹的编码模型,让通用模型更好地理解和编写代码通常会更划算。
小结
那如何用好 AI 呢:
- 用好的模型
- 提供充分的上下文
模型本身效果咋样就是咋样,通常我们干预不了。我们主要完善的还是上下文工程,用工程思路去解决 LLM 的不确定性、效果和成本问题等。不过人与人之间差距还是很大的,如何更好的提问和描述问题,经验就在这里体现出来了。最好的状态就是:写好提示词,模型再差也能跑。
现在风向也变了,你也不用去读什么各种源码了(节奏太快了,你没时间读,也读不下去),面试也不问这些了,就问你用没用过 AI、怎么用、如何提效,你说你没怎么用,那就出门右转。不过我最大的感触还是 AI 虽然让你开发更轻松了,但它同时压缩了需求的时间,也变相压缩了人的时间,好像视频倍速播放一样,根本停不下来😂(省下来的时间是为了摸鱼不是为了赶下一个需求)。