从 Prompt Engineering 到 Function Calling:AI 开发范式的演变

1|

引言:从"调 Prompt"到"调函数"

2|

如果你在过去两年里一直在关注 AI 开发,一定对"Prompt Engineering"这个词不陌生。从最初把 prompt 当作咒语一样精雕细琢,到如今用 function calling / tool use 让模型自主完成任务,AI 应用的开发范式已经经历了一次深刻的转变。

3|

这篇文章试图梳理这条脉络,帮助开发者理解这一演变的本质:我们不是在抛弃 prompt engineering,而是在把它工程化、系统化。

4| 5|

第一阶段:Prompt 即一切

6|

2022 年底 ChatGPT 刚问世时,开发者能做的事情其实非常有限------把精心设计的一段文本发送给模型,然后祈祷回复符合预期。这就是"Prompt Engineering"的起源。

7| 8|

1.1 纯文本 prompt 的局限

9|

早期的典型 prompt 是这样的:

10|

复制代码
你是一个优秀的 Python 工程师。请编写一个函数来... 
    11|要求:
    12|1. 使用类型注解
    13|2. 包含完整注释
    14|3. 处理边界情况

15|

这种方式的痛点显而易见:

16|

  • 17|
  • 缺乏结构:所有约束混在同一个文本流里,模型容易遗漏
  • 18|
  • 不确定性高:同样的 prompt 在不同温度下结果可能天差地别
  • 19|
  • 难以复用:每次都要重写或复制黏贴
  • 20|
  • 无法编程控制:prompt 是静态文本,无法做条件判断或循环
  • 21|

22| 23|

1.2 早期优化手段

24|

为了弥补这些短板,社区想出了各种技巧:

25|

  • 26|
  • Few-shot 示例:在 prompt 里塞入输入输出对,让模型模仿格式
  • 27|
  • Chain-of-Thought:引导模型"一步步思考",提升推理准确率
  • 28|
  • 角色扮演:System prompt 里定义"你是一个... ",利用预训练的角色映射
  • 29|
  • 模板化:用 Jinja2/string.Template 把变量插入固定的 prompt 模板
  • 30|

31|

但这些本质上都是文本层面的优化,没有触及交互范式的变革。

32| 33|

第二阶段:Chat Completions 的进化

34|

2023 年,OpenAI 引入了 Chat Completions API,把单一的 prompt 拆解为 system、user、assistant 三条消息。虽然看起来只是 API 格式的调整,但它带来了质的飞跃。

35| 36|

2.1 角色分离带来的结构化

37|

开发者可以把「系统指令」「用户输入」「模型回复」分开管理:

38|

复制代码
messages = [
    39|    {"role": "system", "content": "你是一个代码审查助手,请用中文回复"},
    40|    {"role": "user", "content": file_content},
    41|]

42|

这意味着:

43|

  • 44|
  • System prompt 可以独立维护:作为"永远不变的行为基线"
  • 45|
  • 多轮对话成为可能:模型可以记住上下文,在后续轮次中持续改善
  • 46|
  • 角色混合:可以在对话中切换角色,实现更复杂的交互
  • 47|

48| 49|

2.2 从"一次性"到"对话式"

50|

Chat Completion 催生了最早的"Agent"雏形:

51|

  • 52|
  • 用户提问 → 模型思考 → 用户追问 → 模型修正
  • 53|
  • 但模型仍然只能返回文本,无法自主行动
  • 54|

55|

这个阶段,prompt engineering 的复杂度从"写一个好 prompt"变成了"管理一整段对话上下文"。一个典型的 prompt 可能包含几千字的 system message、十几轮历史对话、以及各种 few-shot 示例。上下文窗口的消耗成了一个新问题。

56| 57|

第三阶段:Function Calling ------ 范式的分水岭

58|

2023 年 6 月,OpenAI 发布了 Function Calling(后来改名为 Tool Use)功能。这不仅是API 功能的补丁,更是一次交互范式的根本转变。

59| 60|

3.1 What is Function Calling?

61|

Function Calling 允许开发者在请求中注册一组"可调用函数"的 JSON Schema,模型在需要时自主选择调用哪个函数,并返回结构化的参数。开发者再执行函数,将结果回传给模型。

62|

这是一个里程碑:模型不再只能"说",它开始能够"做"

63| 64|

3.2 一个直观的对比

65|

没有 Function Calling:

66|

复制代码
用户:"北京的天气怎么样?"
    67|模型回复:"我无法实时获取天气数据,请查天气预报应用。"

68|

有了 Function Calling:

69|

复制代码
用户:"北京的天气怎么样?"
    70|模型返回:{"function": "get_weather", "args": {"city": "北京"}}
    71|→ 开发者执行函数 → 返回结果给模型
    72|模型回复:"北京目前 22°C,晴,空气质量良好。"

73| 74|

3.3 核心能力对比

75| 76| 77| 78| 79| 80| 81| 82| 83| 84| 85| 86| 87| 88| 89| 90| 91| 92| 93| 94| 95| 96| 97| 98| 99| 100| 101| 102| 103| 104| 105| 106| 107| 108|

|--------|------------------------|------------------------------|
| 维度 | Prompt Engineering | Function Calling |
| 输出形式 | 自然语言文本 | 结构化 JSON(可程序消费) |
| 与代码的边界 | 模糊,结果需二次解析 | 清晰,Schema 定义即契约 |
| 可靠度 | 高度依赖 prompt 文本质量 | 依赖 Schema 设计 + 模型能力 |
| 可测试性 | 低------"感觉对了"就是通过 | 高------JSON Schema 校验 + 单元测试 |
| 组合能力 | 文本拼接 | 多个 function 自由组合 |

109| 110|

第四阶段:从 Function Calling 到 Agent 框架

111|

Function Calling 打开了潘多拉魔盒------既然模型可以调用函数 ,那为什么不能让它自我循环呢?

112| 113|

4.1 ReAct 模式:思考→行动→观察

114|

2024 年,几乎所有主流 Agent 框架(LangChain、AutoGen、CrewAI、Hermes 等)都采用了 ReAct(Reasoning + Acting)模式。其核心循环是:

115|

  1. 116|
  2. 模型收到用户请求
  3. 117|
  4. 模型进行推理(Thought),决定下一步行动
  5. 118|
  6. 模型调用函数(Action),传入参数
  7. 119|
  8. 开发者执行函数,返回结果(Observation)
  9. 120|
  10. 模型根据结果调整思路,回到第 2 步
  11. 121|
  12. 直到模型认为任务完成,返回最终答案
  13. 122|

123|

这本质上就是一个 while 循环。Prompt Engineering 在这个框架里的角色发生了根本变化:

124| 125|

4.2 Prompt 的新角色

126|

在 Agent 框架中,prompt 不再是"告诉模型答案",而是定义模型的决策逻辑

127|

  • 128|
  • System prompt 描述 Agent 的边界(能做什么、不能做什么)
  • 129|
  • Function schema 描述工具接口(输入是什么、输出是什么)
  • 130|
  • Runtime context 提供当前状态(已经做了什么、还需要做什么)
  • 131|

132|

换句话说,函数调用处理了"怎么做",而 prompt 处理了"要不要做"和"下一步做什么"。两者各司其职。

133| 134|

4.3 现实中的例子

135|

以 Hermes Agent 自身为例------当一个用户说"帮我写一篇 CSDN 文章并发布"时,背后的流程是:

136|

复制代码
1. LLM 通过 ReAct 决定:需要调用 generate_article 函数
   137|2. generate_article 返回一篇 HTML 格式的文章
   138|3. LLM 评估文章质量,决定进一步调用 publish_csdn 函数
   139|4. publish_csdn 函数使用 Playwright 操作浏览器
   140|5. 浏览器返回发布结果
   141|6. LLM 将结果整理为用户可读的回复

142|

全程开发者不需要写任何 if-else 逻辑,LLM 的推理能力就是控制流本身。

143| 144|

第五阶段:MCP 与标准化工具生态

145|

进入 2025 年,业界最大的变化是工具生态的标准化。Anthropic 推出的 MCP(Model Context Protocol)让 function calling 从"每个项目自定协议"走向了"通用标准协议"。

146| 147|

5.1 从独占到开放

148|

早期每个 Agent 框架都自己定义 tool 接口:

149|

  • 150|
  • LangChain: @tool 装饰器 + Tool 类
  • 151|
  • OpenAI: function 参数的 JSON Schema
  • 152|
  • AutoGen: 自定义 register_function()
  • 153|

154|

MCP 的贡献在于统一了服务端和客户端的交互协议:

155|

复制代码
# 任何 MCP 服务器暴露的工具都可以被任何 MCP 客户端消费
   156|# 不需要适配层,不需要桥接代码

157| 158|

5.2 对开发者的影响

159|

这意味着:

160|

  • 161|
  • 你写一个 MCP 服务器 = 所有支持 MCP 的 Agent 都能用
  • 162|
  • 多工具链组合不再是噩梦------MCP 天然支持多个服务器
  • 163|
  • 非 AI 开发者也能提供"AI 可消费的 API"------只需写一个 MCP 服务端
  • 164|

165| 166|

总结:范式迁移的本质

167|

回顾这两年多的演变,我们可以看到一个清晰的趋势:

168| 169|

三个转变

170|

  1. 171|
  2. 从<用词>到<用结构>:不再追求 prompt 中的某个关键词,而是设计清晰的交互结构(角色、消息、函数)
  3. 172|
  4. 从<写提示>到<写系统>:AI 应用开发越来越像传统后端开发------定义 API(function schema)、写业务逻辑(tool implementation)、配置路由(Agent 循环)
  5. 173|
  6. 从<一次性>到<循环>:单次问答 → 多轮对话 → Agent 自主循环,模型的自主性每提升一层,开发者控制的方式就向更高抽象层退一层
  7. 174|

175| 176|

对你意味着什么?

177|

如果你仍在专注于"怎么写一个好 prompt",建议拓宽视野:

178|

  • 179|
  • 学一点 JSON Schema:Function calling 的参数定义比 prompt 文本更影响结果质量
  • 180|
  • 理解 MCP 协议:它会像 REST API 一样成为基础设施
  • 181|
  • 把 Agent 看作一个微服务:给它定义清晰的输入输出、状态管理和错误处理
  • 182|
  • 不要放弃 Prompt Engineering:它仍然是 system prompt 和 agent 行为的核心,只是从"前台"退到了"后台"
  • 183|

184|

Prompt Engineering 没有死,它被工程化了。

185|

这句话大概是对这两年 AI 应用范式演变最好的总结。

186| 187|

188|

(完)