用Needle 2的complete()手写Agent循环:不依赖run()的完整可控教程
【免费下载链接】needle14MB foundation model for tiny devices; phones, wearables, smart home, and robots.项目地址: https://gitcode.com/GitHub_Trending/needle20/needle
Needle 2 是一个仅 14MB 的端侧工具调用基础模型(45M 参数,约 28MB 内存跑完整个会话),专为手机、可穿戴、智能家居和机器人等小设备设计。本文教你跳出run()的自动托管,用complete()一步步手写 Agent 循环,获得对每一轮的完全控制权。
从上图可以看到,Needle 2 在 Mobile-Actions 基准上的精度与 FunctionGemma 270M、LFM2.5 230M 等模型互有胜负,但体积小 5~70 倍、且采用 2-bit 量化。正因如此,它常被嵌入到对内存敏感、需要精细控制的应用里——而手写complete()循环正是这类场景的必修课。
先搞懂:run() 和 complete() 的分工
| 方法 | 行为 | 适合场景 |
|---|---|---|
agent.run(query) | 全自动循环:模型选工具 → 执行 → 回喂结果,直到结束,results里附带所有已执行结果 | 快速验证、标准调用 |
agent.complete(text) | 只跑一轮:返回原始调用 JSON,由你自己执行函数、自己决定下一步 | 需要拦截、审计、自定义逻辑 |
agent.reset() | 清空对话历史,但保留已加载的工具 | 开始新话题 |
run()本质上就是"自动版的手写循环"。想理解它内部在做什么,可以对照 needle/init.py 中run()的实现:它就是一个while循环,不断调用complete()、执行function_calls、把结果json.dumps回喂进去。
手写Agent循环的3步流程
手动驱动循环只需要记住一个节奏:发问 → 执行 → 回喂。
import json import needle @needle.tool def set_lights(room: str, on: bool, brightness: int): "Turn a room's lights on or off and set brightness." return {"ok": True, "room": room} agent = needle.Needle(tools=[set_lights]) # 第 1 步:发问,拿回模型的第一轮决策 response = agent.complete("把客厅灯调暗一点,亮度30") # 第 2 步:判断是调用,就自己执行 if response["type"] == "call": result = set_lights(**response["function_calls"][0]["arguments"]) # 第 3 步:把执行结果回喂给模型,进入下一轮 response = agent.complete(json.dumps(result))注意两点:
- 回喂的内容是结果对象的 JSON 字符串,不是自然语言。模型会基于这个结构继续推理。
- 一轮可能返回多个
function_calls(同一轮要调多个工具),要逐个执行后合并回喂。
每轮响应里藏着什么
complete()每轮都返回同一个结构的 JSON 信封:
{ "type": "call", "function_calls": [ { "name": "set_lights", "arguments": { "room": "客厅", "on": true, "brightness": 30 } } ], "reasoning": "'客厅' -> room; '调暗' -> brightness 30", "confidence": 0.94, "peak_ram_mb": 28.5 }几个关键字段值得每个循环都读一遍:
type:"call"表示模型发起调用;"respond"且function_calls为空表示循环结束——这就是你的while条件。reasoning:模型对每个参数来源的简短推导(如'ten minutes' -> minutes 10),调试时非常有用。confidence:校准过的置信度分数,见下一节。- 无关请求不会编造调用,而是返回空调用
[]拒绝——这是契约的一部分。
用 confidence 给循环加一道安全闸
手写循环的最大红利,是你可以在每一轮检查置信度,而不是等run()跑完:
response = agent.complete(query) if response["type"] == "call" and response["confidence"] is not None \ and response["confidence"] < 0.8: # 低于门槛:不执行,转人工或升级到大模型 response = agent.complete("insufficient confidence, please clarify")confidence取"校准头打分"和"解码概率"两者的最小值,官方建议:定一个产品门槛,高于它就执行,低于就重新提问或升级模型。一个细节:微调后的权重(.cact)不会更新置信头,此时该字段为None,需要跳过阈值判断。详见 doc/apis.md 的 Confidence 一节。
什么时候该手写循环
适合手动驱动的典型场景:
- 执行前审批:转账、删除这类高危操作,执行前弹确认框——
run()无法中途暂停。 - 结果后处理:把工具结果先落库、脱敏或改写,再决定回喂什么。
- 多轮业务逻辑:根据上一轮结果动态决定是继续、重试还是切换工具集。
- 循环护栏:
run()内置max_steps=8,手写时你可以自己实现更复杂的步数限制、超时和降级策略。
会话结束时记得调用agent.reset()清空对话(工具集保留),避免旧话题污染下一轮推理。
小结与延伸
- 循环骨架就三步:
complete()拿调用 → 自己执行 →json.dumps(result)回喂,type == "respond"时收尾。 - 每一轮都读取
type、reasoning、confidence,它们分别决定"停不停""为什么""信不信"。 - 完整 API(
Field约束、工具检索、system 事实、离线部署)都整理在 doc/apis.md;想让自己的工具更听话,可以参考 doc/finetuning.md 的 LoRA 微调流程,训完的.cact同样能用这套循环驱动。 - 想直接上手:
pip install cactus-needle即可,首次运行会自动从 Hugging Face 拉取引擎并缓存,推理过程完全离线、不联网。
【免费下载链接】needle14MB foundation model for tiny devices; phones, wearables, smart home, and robots.项目地址: https://gitcode.com/GitHub_Trending/needle20/needle
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考