前言

BigTall最近把RAGAgent的原理想通了,对于“一切都是提示词”的理解又更多了一些。本文把我的理解大致整理了一下,给出BigTall自己的一个实验。希望能够对大家有用。

关于大模型

现在大模型很热,尤其是春节时候DeepSeek的出圈,直接让大模型跳出了IT圈,跟普通人产生了联系。最近的豆包相关的“我要去世了”文章,让大模型加上了一层人性与情感的光环。北京的机器人马拉松则让人看到了大模型真正落地进入人们生活的一个可能,让更多的人明白了“未来已来,只是尚未流行”。

我们每一分每一秒,都在踏步进入科幻时代。

但是大模型依然神秘。

大模型的出现提供了什么以前缺乏的能力?我思考的答案是:真正处理“模糊”的能力!以往用代码编写出来的“模糊”都是用基于精确匹配的改良:要么用偏移量多匹配几次,要么转化为数学相似度做一个范围取值。但是真正能够基于“语义”上的模糊匹配能力,而且可以直接使用的,大模型是唯一。

对于传统软件开发者来说,大模型更多是一种DSLDomain Specific Language)领域驱动语言,是一种“功能的粘合剂”。本质上跟你嵌入一个JavaScript引擎没多大区别,只不过大模型可以支持自然语言和模糊处理而已,但对于程序来说,都是提供功能调用入口,让DSL进行调用而已。

作为一个语言模型,文字是大模型唯一的输入和输出形式。我们是怎么做到让大模型去控制外部的设备的?我们是怎么做到大模型可以自主在网络上搜寻信息并向我们展示的?它又是如何读懂我给他的文档,帮我进行内容解释的?

提示词就是一切!

有了提示词的魔法,我们可以简单一句“请帮我规划到丽江的旅游”,驱动大模型帮我们去分解任务,寻找景点、规划线路、寻找住宿、寻找合适的交通工具、询价甚至直接订票。

魔法一样的技术背后,是多轮的提示词往来。

RAG应用

RAG应用的基本原理是把文档放向量数据库里,用户询问的问题会也向量化,跟向量数据库的内容做相似度查找,找到的前10条结果会组合成提示词以文字形式送给背后的AI渲染。背后的提示词类似:【问题xxx找到abcd等几个相似文档,文档该要和匹配片段分别是xyz,请分析并给出答案】。

智能体

Agent就是智能体,所谓的智能体就是一段特定任务相关的提示词,智能体背后可以是同一个AI,也可以是不同的AI。你可以认为智能体就是对应一组提示词的化身,通过把某个能力相关(例如订票)的一组提示词放在一个“智能体”中,实现任务的专有性。也符合软件开发领域【高内聚低耦合】的原理。

多个智能体之间的合作,就等价于多个提示词之间的合作,有任务分解的、有对结果监督的、有驱动过程的不同的提示词对应的Agent

例如【我要去桂林旅行】,就可以分解为几个智能体:

  1. 将文字整理成任务片段的:理解文字内容,并将文字分解成步骤和动作,负责总控和协调其他专有Agent的执行。
  2. 查机票火车票的:通过RAG的方式,大模型生成参数,调用外部的查询接口查到各种交通工具的信息,提供其他Agent使用。
  3. 整理行程的:负责从知识库或者网络查询检索获得一组行程,并根据用户的需求挑选出最合适的行程。
  4. 查桂林景点的:负责从知识库或者网络查询获得桂林的景点,并根据用户需求挑选出最合适的景点。
  5. 整理旅游计划的:将以上的信息综合,组合成旅游计划。

这个只是简单的说明,实际上智能体之间的关系是一个网状关系,非常复杂。所以智能体组合的运行速度其实很慢。

大模型回调

所谓的大模型和本地程序的回调,等价于提示词:【我现在有什么任务,这些是可以调用的本地接口定义如下123,请回复问题位置中插入适当的本地接口调用】。然后,你问ai,今天早上我要穿什么衣服?然后AI就会返回一个带占位符的文字【今天温度是${weather(2025-5-17)},请告诉我要穿什么衣服】,你的程序会把${}中的函数计算并嵌入结果,结果AI收到【今天温度25度,请告诉我要穿什么衣服】,然后ai再返回结果【穿短袖】。

大致原理就是这样,只不过支持回调的大模型都经过专门训练,可以使用json结构来定义回调函数,并且他们的回调准确率也更高。

MCP和A2A协议

说到这里,大家应该明白了,大模型离不开和外部的协作。所以需要一个大模型控制外部设施的协议。另外,刚才讲智能体协作的时候,很明显智能体之间存在通讯关系,因此也需要一个通讯协议。

MCPModel Context Protocol)模型上下文协议由AnthropicClaude 模型的开发公司)提出,OpenAI后续跟随采用让它成为事实上的标准。该协议就是让大模型和外部协作的。有人可能会说,大模型那么智能,我们让大模型学会各个系统的交互,就可以不要什么MCP了。有道理,但是大模型要记住这些的话,需要记忆,花这么多代价去训练怎么跟外部交互是不是很浪费?!未来还会有更多的新系统出现,难道不间断去训练吗?所以合理的方式就是让每个想和大模型协作的外部程序都学会“普通话”,能够和大模型对话,接受大模型的指令。

A2AAgent to Agent)由Google主导开发,定位为跨平台、跨厂商的AI 智能体之间的通讯协议。等于让智能体都加入了一个群,智能体们可以在群里互相@进行交流。大家看刚才旅游订票的例子就可以看到,智能体之间的交互其实并不比智能体和大模型之间的交互要来的少多少。

QWen3 0.6B的回调实验

无论是MCP还是A2A,还是普通的大模型功能调用,本质都是一回事:提示词输入通过大模型变成答案输出,答案又变成下一次的输入。来来回回,就把事情办完了。

这次我们的实验,就是把不支持回调的本地小模型改造成可以支持回调。让小模型也可以和代码进行交互。

实验环境

实验环境首先需要安装Ollama,一个决心要像使用docker一样使用大模型的环境。大家去官网 https://ollama.com/ 下载安装,并且启动运行(确保任务栏里有白色羊驼的图标)。

ollama pull qwen3:0.6b

  

另外,需要安装python3。我机器是MacBook Pro,所以用brew安装,其他操作系统请自己安装环境。

brew install python
mkdir ~/qwen3-callback
cd ~/qwen3-callback
python3 -m venv .
source ./bin/activate
python3 -m pip install requests

  

代码

把以下的源代码放到文件callback.py中。

  1 import requests
2 import re
3 import json
4
5 # Ollama API 配置
6 OLLAMA_API_URL = "http://localhost:11434/api/generate"
7 MODEL_NAME = "qwen3:0.6b"
8
9 # 模拟的天气函数
10 def weather(date):
11 # 实际场景可调用天气 API,这里模拟返回 25 度
12 return 35
13
14 def find_goods(item):
15 # 模拟返回商品信息
16 return f"""
17 List {item} brand:
18 - Apple: MacBook Pro, MacBook Air
19 - Dell: XPS, Inspiron
20 - HP: Spectre, Envy
21 - Lenovo: ThinkPad, IdeaPad
22 - Microsoft: Surface
23 - Razer: Blade
24 - Samsung: Galaxy Book
25 - Sony: VAIO
26 """
27
28 def find_goods_prices(item):
29 # 模拟返回商品价格
30 return f"{item} 5999.00元"
31
32
33 # 调用 Ollama API 的函数
34 def call_ollama(prompt, model=MODEL_NAME):
35 payload = {
36 "model": model,
37 "prompt": prompt,
38 "stream": False,
39 "temperature": 1
40 }
41 response = requests.post(OLLAMA_API_URL, json=payload)
42 if response.status_code == 200:
43 return json.loads(response.text)["response"]
44 else:
45 raise Exception(f"Ollama API error: {response.text}")
46
47 # 提取 </think> 之后的文本
48 def extract_post_think_text(text):
49 markers = ["</think>", "提示词", "提示词**", "输出:", "输出:"]
50 last_pos = -1
51 last_marker = None
52
53 # Find the last occurrence of any marker
54 for marker in markers:
55 try:
56 pos = text.rindex(marker) # Get the last index of the marker
57 if pos > last_pos:
58 last_pos = pos
59 last_marker = marker
60 except ValueError:
61 continue # Marker not found, skip
62
63 # If a marker was found, return text after it
64 if last_pos != -1:
65 return text[last_pos + len(last_marker):].strip()
66
67 # If no markers found, return original text
68 return text.strip()
69
70
71 # 解析占位符并执行函数调用
72 def process_placeholder(text):
73 # 查找 ${function(args)} 模式的占位符
74 placeholder_pattern = r'\${([^}]+)\}'
75 matches = re.findall(placeholder_pattern, text)
76
77 if not matches:
78 return text # 没有占位符,直接返回原文
79
80 for match in matches:
81 # 处理函数调用格式:${function(arg)}
82 if '(' in match and ')' in match:
83 func_name = match.split('(')[0].strip()
84 func_arg = match.split('(')[1].rstrip(')').strip()
85
86 if func_name == "weather":
87 result = weather(func_arg)
88 text = text.replace(f"${{{match}}}", f"{result}")
89 elif func_name == "find_goods":
90 result = find_goods(func_arg)
91 text = text.replace(f"${{{match}}}", f"{result}")
92 elif func_name == "find_goods_prices":
93 result = find_goods_prices(func_arg)
94 text = text.replace(f"${{{match}}}", f"${result}")
95 else:
96 text = text.replace(f"${{{match}}}", "[Unknown function]")
97 else:
98 text = text.replace(f"${{{match}}}", "[Invalid placeholder]")
99
100 return text
101
102 # 主逻辑
103 def main():
104 # 用户输入
105 # user_input = "今天我要穿什么衣服?"
106 # user_input = "请给我推荐一台性价比高的电脑"
107 # user_input = "我想买一个苹果笔记本电脑,需要准备多少预算?"
108 user_input = "列出中国历朝历代的名称"
109 print(f"用户输入: {user_input}")
110 print("======================")
111
112 # 第一次调用模型,生成带占位符的提示词
113 initial_prompt = f"""
114 今天是2025年5月17日。
115 用户问题:{user_input}
116 可用函数:
117 - weather('2025-5-17'): 返回当天的摄氏温度。
118 - find_goods(item): 返回商品信息(item可以是商品类别、产品名、型号等,如“mobile”或“Samsung”货“Galaxy S”,基于用户问题的主关键词)。
119 - find_goods_prices(item): 返回指定商品的价格(item同上)
120 推理:回答需要什么信息?选择一个函数。若问题未指定具体item,从问题中提取主关键词(如“电脑”)作为item。
121 生成提示词,仅输出:${{function(arg)}}提供的信息,请回答:{{用户问题}}。禁止附加任何说明或逻辑。
122 例如:
123 - 输入:“今天热不热?”,输出:“${{weather('2025-5-17')}}提供的信息,请回答:今天热不热?”
124 - 输入:“推荐一台笔记本电脑?”,输出:“${{find_goods('laptop')}}提供的信息,请回答:推荐一台笔记本电脑?”
125 - 输入:“衬衫多少钱?”,输出:“${{find_goods_prices('shirt')}}提供的信息,请回答:衬衫多少钱?
126 - 输入:“爱因斯坦的生平”,输出:“请回答:爱因斯坦的生平
127 """
128 print(f"初始提示词: {initial_prompt}")
129
130 response = call_ollama(initial_prompt)
131 print("======================")
132 print(f"模型第一次响应: {response}")
133
134 # 提取 </think> 之后的文本
135 post_think_text = extract_post_think_text(response)
136 print("======================")
137 print(f"</think> 后的文本: {post_think_text}")
138
139 # 处理占位符,调用外部函数
140 processed_response = process_placeholder(post_think_text)
141 print("======================")
142 print(f"处理占位符后的文本: {processed_response}")
143
144 # 第二次调用模型,使用回填后的提示词
145 final_prompt = f"""
146 根据以下信息回答用户的问题:
147 {processed_response}
148 """
149 print("======================")
150 print(f"最终提示词: {final_prompt}")
151
152 final_response = call_ollama(final_prompt)
153 print("======================")
154 print(f"最终回答: {final_response}")
155
156 if __name__ == "__main__":
157 main()

运行结果

整个程序运行完成之后是这样的输出内容:

$ python3 ./callback.py
用户输入: 今天天气适合穿什么衣服?
======================
初始提示词:
今天是2025年5月17日。
用户问题:今天天气适合穿什么衣服?
可用函数:
- weather('2025-5-17'): 返回当天的摄氏温度。
- find_goods(item): 返回商品信息(item可以是商品类别、产品名、型号等,如“mobile”或“Samsung”货“Galaxy S”,基于用户问题的主关键词)。
- find_goods_prices(item): 返回指定商品的价格(item同上)
推理:回答需要什么信息?选择一个函数。若问题未指定具体item,从问题中提取主关键词(如“电脑”)作为item。
生成提示词,仅输出:${function(arg)}提供的信息,请回答:{用户问题}。禁止附加任何说明或逻辑。
例如:
- 输入:“今天热不热?”,输出:“${weather('2025-5-17')}提供的信息,请回答:今天热不热?”
- 输入:“推荐一台笔记本电脑?”,输出:“${find_goods('laptop')}提供的信息,请回答:推荐一台笔记本电脑?”
- 输入:“衬衫多少钱?”,输出:“${find_goods_prices('shirt')}提供的信息,请回答:衬衫多少钱?
- 输入:“爱因斯坦的生平”,输出:“请回答:爱因斯坦的生平 ======================
模型第一次响应: <think>
好的,用户的问题是今天天气适合穿什么衣服,需要回答。首先,我需要确定可用的函数。用户的问题中提到了天气,所以应该使用weather函数来获取温度信息。然后,根据问题中的主关键词“天气”,可能需要提取这个关键词作为item,但问题中并没有具体商品类别,所以可能直接使用天气数据。接下来,生成提示词,只输出函数调用的结果,不需要其他说明。例如,用户的问题中没有指定商品,所以主关键词是“天气”,所以调用weather函数,然后给出回答。确保不添加任何其他说明,只输出指定的格式。
</think> ${weather('2025-5-17')}提供的信息,请回答:今天天气适合穿什么衣服?
======================
</think> 后的文本: ${weather('2025-5-17')}提供的信息,请回答:今天天气适合穿什么衣服?
======================
处理占位符后的文本: '2025-5-17' 的天气是 35°C提供的信息,请回答:今天天气适合穿什么衣服?
======================
最终提示词:
根据以下信息回答用户的问题:
'2025-5-17' 的天气是 35°C提供的信息,请回答:今天天气适合穿什么衣服? ======================
最终回答: <think>
好的,用户的问题是根据“2025-5-17”当天的天气35°C,回答今天适合穿什么衣服。首先,我需要确认用户提供的天气信息是否正确,然后根据温度来判断合适的服装。 首先,用户给出的信息是35°C,这通常意味着白天的温度在35度左右,可能还有傍晚的温度稍低。不过,具体天气情况可能还需要参考其他数据,比如是否有风、湿度等。但用户只提供了温度,所以需要假设白天是35度,可能在下午或晚上有降温。 接下来,考虑适合穿什么衣服。通常,白天的温度较高,所以可能会穿短袖、T恤、短裤和长袖衬衫。同时,考虑到天气可能比较热,建议选择透气、吸汗的面料,比如棉质或透气面料。另外,可能还需要考虑防晒,所以帽子和太阳镜也很重要。 不过,用户的问题可能只需要根据给出的信息直接回答,不需要考虑其他因素。所以综合来看,最合适的回答应该是推荐短袖、T恤、短裤和长袖衬衫,同时考虑防晒措施。 需要检查是否有其他可能的因素,比如是否有雨天,但用户只提到了温度,所以可能不需要考虑其他天气情况。因此,最终回答应基于温度和常见天气模式,给出具体的穿衣建议。
</think> 根据今天的天气情况,35°C的高温天气适合穿短袖、T恤、短裤和长袖衬衫。建议搭配防晒用品(如帽子和太阳镜)以保持舒适和安全。

  

总结

不知道有多少人会看到这里。

操控AI模型其实没什么难度,最大的难度还是在“提示词的调试”,你需要不停的试错,不停地和模型的理解能力和幻觉做斗争。模型参数量越小,这个调试的难度就越大,因为小模型本来就很笨。

这次调试多亏了Grok,否则要拿捏住0.6B的小模型不被它蠢哭,还真不容易。至于Big Tall是怎么跟Grok对话最终降伏小模型的?

不告诉你!

提示词才是AI时代最大的秘密!

AI模型的回调能力的理解和实现的更多相关文章

  1. Microsoft宣布为Power BI提供AI模型构建器,关键驱动程序分析和Azure机器学习集成

    微软的Power BI现在是一种正在大量结合人工智能(AI)的商业分析服务,它使用户无需编码经验或深厚的技术专长就能够创建报告,仪表板等.近日西雅图公司宣布推出几款新的AI功能,包括图像识别和文本分析 ...

  2. Local Response Normalization作用——对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力

    AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中.AlexNet主要使用到的新技术点如下. (1)成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过 ...

  3. AI 音辨世界:艺术小白的我,靠这个AI模型,速识音乐流派选择音乐 ⛵

    作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...

  4. 最强云硬盘来了,让AI模型迭代从1周缩短到1天

    摘要:华为云擎天架构+ Flash-Native存储引擎+低时延CurreNET,数据存储和处理还有啥担心的? 虽然我们已经进入大数据时代,但多数企业数据利用率只有10%,数据的价值没有得到充分释放. ...

  5. 如何借助 JuiceFS 为 AI 模型训练提速 7 倍

    背景 海量且优质的数据集是一个好的 AI 模型的基石之一,如何存储.管理这些数据集,以及在模型训练时提升 I/O 效率一直都是 AI 平台工程师和算法科学家特别关注的事情.不论是单机训练还是分布式训练 ...

  6. CANN5.0黑科技解密 | 别眨眼!缩小隧道,让你的AI模型“身轻如燕”!

    摘要:CANN作为释放昇腾硬件算力的关键平台,通过深耕先进的模型压缩技术,聚力打造AMCT模型压缩工具,在保证模型精度前提下,不遗余力地降低模型的存储空间和计算量. 随着深度学习的发展,推理模型巨大的 ...

  7. 回调函数透彻理解Java

    http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...

  8. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  9. js回调函数(callback)理解

    Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...

  10. 炸金花游戏(3)--基于EV(期望收益)的简单AI模型

    前言: 炸金花这款游戏, 从技术的角度来说, 比德州差了很多. 所以他的AI模型也相对简单一些. 本文从EV(期望收益)的角度, 来尝试构建一个简单的炸金花AI. 相关文章: 德州扑克AI--Prog ...

随机推荐

  1. bin格式转safetensors

    技术背景 本文主要介绍在Hugging Face上把bin格式的模型文件转为safetensors格式的模型文件,并下载到本地的方法. bin转safetensors 首先安装safetensors: ...

  2. Powershell 调用cmd 运行exe、bat、jar文件

    1. 配置路径 $nginxPath = "C:\path\to\nginx" $redisPath = "C:\path\to\redis" $ruoyiAd ...

  3. QT5笔记:10. 容器类的迭代

    1. 这里指的是Java类型的迭代器,即使用方式和Java中一致 代器的使用例子(适用于可读可写迭代器) QList<QString>list;//声明容器类 list << ...

  4. 『Python底层原理』--Python字典的实现机制

    在Python中,字典(dict)是一种极为强大且常用的内置数据结构,它以键值对的形式存储数据,并提供了高效的查找.插入和删除操作. 接下来,我们将深入探究 Python 字典背后的实现机制,特别是其 ...

  5. php实现地址跳转的方式

    在PHP中,实现地址跳转主要有以下几种方式: 1. 使用 header() 函数 header() 函数用于发送原始的 HTTP 头信息,常用于实现页面跳转. <?php header(&quo ...

  6. JS中的0和php中的0

    请注意:包含 0 的字符串 "0" 是 true 一些编程语言(比如 PHP)视 "0" 为 false.但在 JavaScript 中,非空的字符串总是 tr ...

  7. 原生开发,使用C语言调用Windows API 开发软件思路分享

    Githu: https://github.com/vladelaina/Catime 作者是一个高度依赖计时器功能的人,但是市面上的软件都不能满足个性化的需求,所以打算自己动手开发,同时采用c语言来 ...

  8. ctfhub-rce-部分做题记录

    命令注入 检查网页显示内容,可以直接看到源代码.大致意思是:检查用户输入的 GET 请求,判断用户是否输入了 ip 信息.如果输入了 ip 信息,则使用用户输入的这个 ip 数据执行一个 shell ...

  9. HarmonyOS SDK让小红书鸿蒙用户尽享原生相机的拍摄之美

    小红书是深受年轻人喜爱的生活社交类社区平台,越来越多的人在小红书上分享旅行.日常.心情.近日,不少使用鸿蒙原生版小红书的细心用户已经发现,直接使用小红书拍摄照片与自己使用原相机拍摄有一样清晰美观的呈现 ...

  10. browser-use 对 playwright 做了哪些事情

    browser-use 是基于 Playwright 的增强工具,专注于将 AI 代理与浏览器自动化结合,通过简化操作和扩展功能提升了开发效率. 以下是它对 Playwright 的主要增强点: AI ...