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

时间:2021-03-31 09:08:04

标签: python chatbot

我正在尝试使用 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 构建聊天机器人?

2 个答案:

答案 0 :(得分:2)

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

直接使用

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)

答案 1 :(得分:0)

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

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