如何将变量或对象传递给 aiogram dp.message_handler 装饰函数?

how to pass variable or object to aiogram dp.message_handler decorated function?

我正在尝试使用 aiogram 构建聊天机器人,但发现该软件包提供的示例没有帮助。问题是我找不到将我自己的对象或变量从 main 传递到由 'dp.message_handler()' 修饰的聊天函数的方法。我需要将作为文本生成器的对象和变量传递给聊天功能,这样机器人就可以聊天而不仅仅是回应。我使用他们的 echo 示例作为起点,我可以在 'message.text' 获取用户消息没问题...我的代码如下:

    @dp.message_handler()
    async def chat(message: types.Message, myobj, myvar):
        "using myobj and myvar to generate text as reply"
        await message.answer(reply)
        return message.text
     
    async def main():
        while Ture:
            said = await partial(chat, myobj=qna_model, myvar=text)
            if said == "bye": break
        dp.stop_polling()
        await dp.wait_closed()
        await bot.session.close()

    if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)
    asyncio.run(main())

但是我得到了错误:TypeError: chat() missing 2 required positional arguments: 'myobj' and 'myvar'. 我什至尝试 'async def chat(message: types.Message, **kwargs)' 并在没有部分包装的情况下从 main() 调用它,也没有运气......我搜索并找不到有关如何使用 aiogram 构建聊天机器人的示例,可能是我在aiogram的错误使用方法...有人成功使用aiogram构建聊天机器人吗?

如果你想将一个函数传递给你的处理程序,只需导入它并直接使用它。 如果你想将它应用于某些处理程序,你应该使用中间件。

直接使用

def generate_text():
    return "generated text"

async def handler(message: Message):
    text = generate_text()
    await message.answer(text)

中间件使用

创建一个中间件
from aiogram.dispatcher.middlewares import BaseMiddleware
from aiogram.types import Message

class YourMiddleware(BaseMiddleware):
    async def on_pre_process_message(self, message: Message, data: dict):
        # `text` is a name of var passed to handler
        data["text"] = generate_text()
通过 Dispatcher 注册 (on_startup)
dp.middleware.setup(YourMiddleware())
在处理程序中获取 text 数据
from aiogram.types import Message

async def handler(message: Message, text: str):
    await message.answer(text)

aiogram实际上有一种方法可以将数据传递给消息处理函数装饰函数,相当于Oleg给出的直接调用外部函数的方式,比Middleware更简单。

    async def myfunc(message: types.Message):
        myrparm = dict()
        myrparm["model"] = mymodel
        myrparm["reply"] = generator(message.text)
        return myparm

    @dp.message_handler(myfunc)
    async def chat(message: types.Message, model, reply):
         "do some thing with model or reply to get final_reply "
        await message.answer(final_reply)

条件是 myfunc 必须 return 一个字典。 这样,我可以将生成器放在 myfunc 或 chat 中,没有区别。为了解决长时间加载生成器模型的问题,我设置了一个类似“/load model”的用户命令,并使生成器保持为全局变量(或者可能使用 Redis),因此用户在聊天时发出加载命令时只会遭受缓慢的响应响应是可以接受的。