装饰方法
正确使用FastMCP装饰器中的实例方法、类方法和静态方法。
FastMCP的装饰器系统设计用于处理函数,但如果您尝试装饰实例或类方法,可能会遇到意外行为。本指南解释了如何正确使用方法与所有FastMCP装饰器(@tool()、@resource()和@prompt())。
为什么方法如此困难?
当你应用像@tool()、@resource()或@prompt()这样的FastMCP装饰器到一个方法时,装饰器会在装饰时捕获该函数。对于实例方法和类方法来说,这带来了一个挑战,因为:
- 例如实例方法:装饰器在任何实例存在之前获取未绑定的方法
- 对于类方法:装饰器在函数绑定到类之前获取该函数
这意味着直接装饰这些方法不会按预期工作。实际上,LLM会看到像self或cls这样的参数,但它无法为这些参数提供值。
推荐模式
实例方法
不要这样做(它无法正常工作):
当以这种方式应用装饰器时,它会捕获未绑定的方法。当LLM稍后尝试使用此组件时,它会将self视为必需参数,但不知道该为其提供什么值,从而导致错误或意外行为。
请改为这样做:
这种方法之所以有效是因为:
- 首先创建该类的实例(
obj) - 当你通过实例访问该方法时(
obj.add),Python会创建一个绑定方法,其中self已经设置为该实例 - 当你注册这个绑定方法时,系统会看到一个仅需要适当参数的可调用对象,而不需要
self
类方法
与实例方法类似,直接装饰类方法无法正常工作:
请不要这样做:
这里的问题在于FastMCP装饰器是在@classmethod装饰器之前应用的(Python的装饰器是从下往上执行的)。因此它捕获的是尚未转换为类方法的函数,从而导致错误行为。
请改为这样做:
这是因为:
- 在类定义期间正确应用了
@classmethod装饰器 - 当你访问
MyClass.from_string时,Python会提供一个特殊的方法对象,自动将类绑定到cls参数 - 注册时,只有适当的参数会暴露给LLM,隐藏了
cls参数的实现细节
静态方法
与实例方法和类方法不同,静态方法可以很好地与FastMCP装饰器配合使用:
这种方法之所以有效是因为:
- 首先应用
@staticmethod装饰器(最后执行),将方法转换为常规函数 - 当应用FastMCP装饰器时,它捕获的实际上只是一个常规函数
- 静态方法没有任何绑定要求 - 它不会接收
self或cls参数
或者,您可以使用与其他方法相同的模式:
这之所以有效是基于同样的原因 - 静态方法本质上只是类命名空间中的一个函数。
其他模式
在类初始化时创建组件
在创建对象时,您可以自动注册实例方法:
这种模式在以下情况下很有用:
- 您希望将注册逻辑封装在类本身中
- 您有多个相关组件需要一起注册
- 您希望确保在创建实例时方法总是被正确注册
该类在初始化过程中自动注册其方法,确保在注册前它们已正确绑定到实例上。
概述
虽然FastMCP的装饰器模式可以无缝应用于常规函数和静态方法,但对于实例方法和类方法,您应在创建实例或类之后再添加它们。这能确保方法在注册之前已正确绑定。
这些模式适用于所有FastMCP装饰器和注册方法:
@tool()和add_tool()@resource()和add_resource_fn()@prompt()和add_prompt()
理解这些模式可以让您有效地将组件组织到类中,同时保持正确的方法绑定,从而在不牺牲FastMCP装饰器系统简洁性的前提下,获得面向对象设计的优势。