对话机器人 Rasa(十九):rasa 不同客户端类型区分处理 custom channel

更新日期: 2023-11-08 阅读次数: 1048 字数: 873 分类: AI

使用场景

例如,用 Rasa 实现一个自动聊天机器人,要同时实现多端:

  • 网页端
  • 微信小程序端
  • Android / iOS 原生 App 端
  • Windows 端

每一端的回复内容会有些许差异,如:

utter_greet

  • 网页端:欢迎使用大象计算器,地球上最不强大的计算器
  • 微信小程序端:欢迎使用大象计算器微信小程序,您也可以关注大象工具公众号接收各种骚扰信息

突然想到 Rasa channel 是否可以实现这个功能,于是查了一下官方文档,看起来很挺合适。

不同 channel 返回不同 response

参考:

https://rasa.com/docs/rasa/connectors/custom-connectors

domain.yml 中这样配置:

responses:
  utter_greet:
    - text: Hi! Welcome to my site.
    - text: Hi! Welcome to my Wechat mini app.
      channel: wechat

第二条是针对 wechat 这个 channel 的特定返回信息。

Custom Connectors 实现

自定义 Channel 是通过 Custom Connectors 实现的,需实现 name 和 blueprint (蓝图) 方法:

from rasa.core.channels.channel import InputChannel

class Wechat(InputChannel):
    def name() -> Text:
        """Name of your custom channel."""
        return "wechat"

完整代码参考官方文档:

https://rasa.com/docs/rasa/connectors/custom-connectors

即可。

注意,如果需要使用 metadata, 官方的实现有问题,需要自己实现从 request 中解析 metadata 的逻辑。

sanic blueprint 的用途

https://sanic.dev/en/guide/best-practices/blueprints.html#overview

可以理解为方便添加子目录路由解析。

Blueprints are objects that can be used for sub-routing within an application. Instead of adding routes to the application instance, blueprints define similar methods for adding routes, which are then registered with the application in a flexible and pluggable manner.

例如:

# ./my_blueprint.py
from sanic.response import json
from sanic import Blueprint

bp = Blueprint("my_blueprint")

@bp.route("/")
async def bp_root(request):
    return json({"my": "blueprint"})

获取每个端独有的信息

metadata = self.get_metadata(request)   # method to get metadata

credentials.yml

假如自定义渠道的代码定义在代码文件 addons/wechat_channel.py。

则对应的配置为:

addons.wechat_channel.Wechat:

默认的配置为:

rest:
#  # you don't need to provide anything here - this channel doesn't
#  # require any credentials

#facebook:
#  verify: "<verify>"
#  secret: "<your secret>"
#  page-access-token: "<your page access token>"

#slack:
#  slack_token: "<your slack token>"
#  slack_channel: "<the slack channel>"
#  slack_signing_secret: "<your slack signing secret>"

#socketio:
#  user_message_evt: <event name for user message>
#  bot_message_evt: <event name for bot messages>
#  session_persistence: <true/false>
socketio:
  user_message_evt: user_uttered
  bot_message_evt: bot_uttered
  session_persistence: false

客户端发送的数据格式

curl --request POST \
     --url http://localhost:5005/webhooks/wechat/webhook \
     --header 'Content-Type: application/json' \
     --data '{
            "sender": "test_user",
            "message": "Hi there!",
            "metadata": {}
          }'

TypeError: name() takes 0 positional arguments but 1 was given

运行

rasa run --enable-api --cors '*'

报错:

TypeError: name() takes 0 positional arguments but 1 was given

def name() -> Text:  # 原代码

def name(self) -> Text:   # 正确的代码

GraphComponentException

rasa run --enable-api --cors '*'

rasa.engine.exceptions.GraphComponentException: Error running graph component for node run_RegexMessageHandler.

rasa run --enable-api --cors '*' --credentials credentials.yml

不加 credentials 参数也是一样的效果。

参数 message 换成 text,因为代码中用的是 text,需要前后端统一。

> curl --request POST \
	--url http://localhost:5005/webhooks/windows/webhook \
	--header 'Content-Type: application/json' \
	--data '{
	   "sender": "test_user",
	   "text": "Hi there!",
	   "metadata": {}
	 }'

测试

  • http://localhost:5005/webhooks/wechat/webhook
  • http://localhost:5005/webhooks/rest/webhook

cors 参数

  • 对于新的自定义 channel ,启动 rasa 时,不加 cors 参数,curl 也可以正常访问。
  • 但是对于 rest channel,不加 cors 参数,curl 也可以正常访问

坑爹的官方文档

测试了一下,新 channel 和 rest channel 返回的消息是一样的。。。。

原来,需要自定义一个 OutputChannel 替换掉官方文档中的 CollectingOutputChannel

class WechatOutput(CollectingOutputChannel):
    @classmethod
    def name(cls) -> Text:
        return "wechat"

然后就可以了。

眼睛睁不开了,睡觉。

查看合集

📖 对话机器人 Rasa 中文系列教程

tags: rasa

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式