装饰器的类型提示

问题描述 投票:0回答:1

outlines库有一个像这样的提示类

@dataclass
class Prompt:
    """Represents a prompt function.

    We return a `Prompt` class instead of a simple function so the
    template defined in prompt functions can be accessed.

    """

    template: str
    signature: inspect.Signature

    def __post_init__(self):
        self.parameters: List[str] = list(self.signature.parameters.keys())

    def __call__(self, *args, **kwargs) -> str:
        """Render and return the template.

        Returns
        -------
        The rendered template as a Python ``str``.

        """
        bound_arguments = self.signature.bind(*args, **kwargs)
        bound_arguments.apply_defaults()
        return render(self.template, **bound_arguments.arguments)

    def __str__(self):
        return self.template

它有一个像这样的提示装饰器

def prompt(fn: Callable) -> Prompt:
    signature = inspect.signature(fn)

    # The docstring contains the template that will be rendered to be used
    # as a prompt to the language model.
    docstring = fn.__doc__
    if docstring is None:
        raise TypeError("Could not find a template in the function's docstring.")

    template = cast(str, docstring)

    return Prompt(template, signature)

这似乎与我见过的装饰器和包装器嵌套函数的装饰器非常不同。

如果我尝试使用此提示

@prompt
def my_system_prompt():
    """This is system prompt."""

system_prompt = query_gen_system_prompt()

Pyright 似乎将 system_prompt 的类型推断为 str 而不是 Prompt(可能是因为 call?),这导致了问题。

我该如何解决这个问题?

python python-decorators type-hinting
1个回答
0
投票

如果你减少你的问题,你会发现 Pyright 是正确的:

class Thing:
    def __call__(self):
        return 'hello, world'


def deco(fn):
    return Thing()

@deco
def f():
    return 'world, hello'


# returns the value for Thing.__call__ 
f()
hello, world

这是因为,在装饰器中,您正在返回可调用的类。然后,当您调用该函数时,会调用该类,返回

__call__
的值,即
str

在这种情况下,

Prompt
嵌套包装器,因为它在技术上是可调用的,就像
def wrapper(*args, **kwargs)
在更传统的装饰器中一样。

© www.soinside.com 2019 - 2024. All rights reserved.