在之前的 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 的逻辑加进来
查看合集
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式