我给 AOI 设备装了一个 Agent,然后发现工具注册才是最难写的

背景:Apple 供应链 AME,负责 AOI 设备导入和微米级视觉检测。写代码是自学的,主业是让产线上的相机拍到 5μm 的缺陷并且不误报。


做这个项目的起因很简单:我们的 AOI 设备每天产生上万张检测图像,大部分是 OK 的,小部分需要人工复判。我一开始只是想写个脚本,让 LLM 帮我过滤掉明显的伪缺陷------省点眼睛。

但做到后面发现,LLM 不只是能看图。它还能读 XML 配置文件里的检测参数(canny 阈值、CLAHE 对比度、NMS 的 IoU 门限),判断当前参数是不是导致误报/漏报的原因,然后自己改写配置,让上位机重新加载。

这个闭环一旦转起来------检测 → 分析 → 调参 → 复检------就不再是"AI 辅助检测",而是一个能自主优化产线设备的 Agent。

但要做到这一步,首先得解决一个问题:你的 Agent 怎么安全地、可靠地调用 20+ 个不同类型的工具?


一、工具不只是"函数调用"

刚开始我的工具就是一个字典:

python 复制代码
tools = {
    "aoi_detect": detect_defects,
    "xml_config_read": read_xml,
    "xml_config_write": write_xml,
}

AOI 检测工具需要传入图片路径、检测模式(传统算法 / 深度学习 / 混合)、canny 高低阈值、CLAHE clip limit、最小缺陷面积......总共 9 个参数。LLM 有时候传 canny_low="50"(字符串),有时候漏传必填参数,有时候把不存在的 mode 传进来。

在通用 Agent 场景下,参数传错了大不了返回个错误信息让 LLM 重试。但在设备控制场景下,如果 LLM 传了错误的 XML 参数直接写入了上位机配置,下一次检测可能整批漏检。 这比 API 报错严重得多。

所以工具注册中心的第一个需求不是"方便注册",是在参数触及设备之前把它拦下来


二、参数校验不是 nice-to-have,是安全边界

每个工具的参数在注册时就声明了完整约束:

python 复制代码
@dataclass
class ToolParameter:
    name: str
    type: str          # string / number / boolean / array
    description: str
    required: bool = True
    default: Any = None
    enum: list[str] | None = None   # 枚举白名单

执行时的校验顺序是精心设计的:

lua 复制代码
execute("xml_config_write", **kwargs)
  │
  ├── 1. 工具是否已注册?
  ├── 2. 工具是否被禁用?
  ├── 3. 参数校验(必填 / 类型 / 枚举白名单 / 默认值补全)
  ├── 4. 速率限制检查(被限流不会浪费在校验失败的调用上)
  │
  └── 5. 通过,执行函数

第 4 步的顺序是关键。 如果先查速率限制再校验参数,那参数错误会消耗限流令牌------LLM 被限流后看到的错误是"参数非法",它会以为工具不可用,换一个工具再试,又被限流。这个恶性循环在生产中非常致命。

校验同时做了自动补全 :如果 LLM 没传可选参数,直接填入默认值。比如 AOI 检测的 clahe_clip 默认 2.0,LLM 不需要每次显式传------这对 LLM 的 token 消耗也有好处,prompt 不用列出全部 9 个参数。


三、统一的返回格式:让 LLM 不需要理解异常

不管工具内部发生什么------文件不存在、ONNX 模型加载失败、XML 格式校验不通过------调用方永远拿到:

python 复制代码
{
    "success": True | False,
    "result": Any,
    "error": str | None,
    "latency": 0.123
}

这件事看起来极其简单,但它解决了一个实际的工程问题:LLM 的判断逻辑不需要针对每种工具写不同的错误处理 。它看到 success == Falseerror 字段,就能决定下一步------换参数重试、换工具、还是告诉用户"当前设备状态不支持此操作"。

对 AOI 场景来说,这个统一格式还有一个好处:所有工具调用的结果都可以被记录和审计。如果某次 XML 改写导致了检测质量下降,你能回溯到具体哪个工具调用、传了什么参数、耗时多久。


四、从 ToolRegistry 到 LangGraph:适配比注册更复杂

LangGraph 的 React Agent 期望的是 StructuredTool 对象,需要 Pydantic schema。如果每个工具手写一个 Pydantic 类,22 个工具就是 22 个类------维护成本不可接受。

Adapter 做的事是运行时动态生成

python 复制代码
def _make_pydantic_schema(params):
    fields = {}
    for p in params:
        field_type = {"string": str, "number": float, "integer": int}.get(p.type, str)
        fields[p.name] = (field_type, Field(description=p.description, default=p.default))
    return create_model("DynamicArgs", **fields)

没有手写任何 Pydantic 类。工具注册时声明参数元数据 → Adapter 自动生成 schema → LangGraph 直接使用。新增一个工具不需要改 Adapter 的任何代码。


五、单例和测试:写测试比写功能花的时间更多

工具注册中心是单例------Agent 启动后全局只有一个。但单例在测试中是个灾难:测试 A 注册了 5 个工具,测试 B 又注册了 3 个,状态互相污染。

解决方案是双重检查锁 + 显式 reset:

python 复制代码
class ToolRegistry:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    @classmethod
    def reset(cls):
        """仅用于测试"""
        cls._instance = None

每个测试文件开头调用 ToolRegistry.reset(),保证干净的状态。这件小事花了跟写功能差不多的时间,但没有它,196 个测试根本跑不稳。


六、和通用 Agent 框架的真正区别

LangChain / CrewAI 的工具注册解决的是"怎么让 LLM 调用工具"。我的场景多了一层:这些工具的背后是真实的工业设备

所以多了几样东西:

  • 参数的白名单约束 ------不是建议,是硬限制。canny_low 的范围是 [0, 255],传 300 就是拒绝。
  • 工具的分级禁用------设备维护时可以单独禁 AOI 检测工具,不影响 Agent 的其他功能。
  • 每个调用的统计追踪------不是为了计费,是为了追溯质量问题。

这些不是架构上的创新,只是工程上必须做的事。但恰恰是这些"必须做的事",让一个个人项目看起来像生产系统。


这个项目目前还处于早期------AOI 闭环调参还在验证阶段,很多边界情况还没覆盖。但工具注册中心这一层的设计,是后面所有功能的底座。下一篇聊另一个底座:在产线上跑 Agent,LLM API 抖一下真的会停线。怎么让 LLM 调用做到工业级的可靠性?

代码在 github.com/JamesW-ang/...

相关推荐
James_WangA1 小时前
产线上跑 Agent:LLM 挂了不是 500 错误,是停线
架构·github
生成论实验室2 小时前
《事件关系阴阳博弈动力学:识势应势之道》第四篇:降U动力学——认知确定度的自驱演化
人工智能·科技·神经网络·算法·架构
SamDeepThinking2 小时前
并发量就算只有2,该上锁还得上呀
java·后端·架构
Sam_Deep_Thinking3 小时前
如何让订单系统和营销系统解耦
java·架构·系统架构
ting94520003 小时前
Micro1 超详细深度解析:架构原理、部署实战、性能评测与落地应用全指南
人工智能·架构
该昵称用户已存在4 小时前
从边缘计量到碳足迹追踪:MyEMS 开源一体化架构的全栈拆解
架构·开源
福大大架构师每日一题4 小时前
ollama v0.22.1 重大更新全解析:新增Poolside集成、模型推荐机制与多架构适配
架构·ollama
该昵称用户已存在4 小时前
以开源筑基,架构先行——深度拆解 MyEMS 微服务能源管理系统的技术内核
微服务·架构·开源
生成论实验室5 小时前
《事件关系阴阳博弈动力学:识势应势之道》第一篇:生成正在发生——从《即事经》到事件-关系网络
人工智能·科技·算法·架构·创业创新