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?),这导致了问题。
我该如何解决这个问题?
如果你减少你的问题,你会发现 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)
在更传统的装饰器中一样。