对话机器人 Rasa(三十四): Socket.IO channel 设置 session id

更新日期: 2024-02-16 阅读次数: 357 字数: 513 分类: AI

在之前的 Rasa 笔记中记录过 Sender ID 的使用,即 session id 的管理:

对话机器人 Rasa(十二):用户会话 Session 管理

对于基于 HTTP 的自定义渠道,session id 比较好处理,直接获取请求中的 sender 等自定义的字段值即可。

但是,对于基于 socket.io channel 来说,代码修改相对复杂一些,还有额外的概念。这里记录一下。

session_persistence

参考官方文档:

https://rasa.com/docs/rasa/connectors/your-own-website/

socketio:
  user_message_evt: user_uttered
  bot_message_evt: bot_uttered
  session_persistence: true/false

这里有个 SESSION PERSISTENCE 的概念。

By default, the SocketIO channel uses the socket id as sender_id, which causes the session to restart at every page reload. session_persistence can be set to true to avoid that. In that case, the frontend is responsible for generating a session id and sending it to the Rasa Core server by emitting the event session_request with {session_id: [session_id]} immediately after the connect event.

因为默认情况下,session_persistence 为 false 时,使用的是 socket id 作为 session_id/sender_id, 这样做的弊端是,页面刷新,会导致 socket.io 连接重连,更换 socket id,于是无法判断为同一个用户的会话。

解决方案就是,将 session_persistence 设置为 true,然后在前端自己生成一个 session_id/sender_id, 当然也可以从 server 端获取一个 session_id/sender_id,默认的 socketio.py 也内置了这个逻辑。参考下面的 session_request 事件里的代码。

内置 socketio.py 的代码

默认的 session_id 的代码

@sio.on("session_request", namespace=self.namespace)
async def session_request(sid: Text, data: Optional[Dict]) -> None:
    if data is None:
        data = {}
    if "session_id" not in data or data["session_id"] is None:
        data["session_id"] = uuid.uuid4().hex
    if self.session_persistence:
        sio.enter_room(sid, data["session_id"])
    await sio.emit("session_confirm", data["session_id"], room=sid)
    logger.debug(f"User {sid} connected to socketIO endpoint.")

@sio.on(self.user_message_evt, namespace=self.namespace)
async def handle_message(sid: Text, data: Dict) -> None:
    output_channel = SocketIOOutput(sio, self.bot_message_evt)

    if self.session_persistence:
        if not data.get("session_id"):
            rasa.shared.utils.io.raise_warning(
                "A message without a valid session_id "
                "was received. This message will be "
                "ignored. Make sure to set a proper "
                "session id using the "
                "`session_request` socketIO event."
            )
            return
        sender_id = data["session_id"]
    else:
        sender_id = sid

    metadata = data.get(self.metadata_key, {})
    if isinstance(metadata, Text):
        metadata = json.loads(metadata)
    message = UserMessage(
        # data.get("message", ""),
        data.get("text", ""),
        output_channel,
        sender_id,
        input_channel=self.name(),
        metadata=metadata,
    )
    await on_new_message(message)

return socketio_webhook

修改逻辑

  • 将 session_persistence 设置为 true
  • session_request 事件中的逻辑先忽略, 即客户端不主动调用 session_request 中的逻辑
  • 将请求中的 session_id 改成自定义字段名,例如 sender,减少客户端的兼容性修改
  • 后续,将 enter_room 的逻辑加进来

查看合集

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

tags: rasa

关于作者 🌱

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