我刚刚使用Rasa开源部署了一个(veeery)最小可行的虚拟助手(explorer-ai.chat)。它目前作为一个简单的Web应用程序从构建在E2机器上的Docker容器网络中运行(Ubuntu 18.04)由Google Cloud托管。
帮助您与聊天机器人交互的背景:它的目的是作为一个虚拟导游的Exploratorium在弗朗西斯科。特别是,它应该能够回答人类讲解员可能被顾客问到的基本问题。用户意图分为以下类别:
- 在探索博物馆的一些展览中获得对一个概念或现象的解释
- 获取探索博物馆特定展览的信息,通过(通用)名称标识
- 简要说明
- 当前位置(E)g.gallery)
- 创建者姓名
- 创建年份
- 获取展品推荐
NLU和对话框管理有很多问题我正在解决,但 this post的目的是理解这里说明的行为:
具体地,机器人通常无法在对话中的某个点对用户话语做出响应。以下是一些可能相关的项目:
- 当我使用
rasa shell
命令在本地(未Dockerized)与bot交互时,不存在此问题。(然而,我应该提到,部署版本和本地版本中的模型是不同的--当我将应用程序Dockerized以进行部署时,我COPY
到Rasa服务的Docker容器中的任何模型都被认为是“无效的”(为什么?),所以我决定在Dockerfile中包含一个RUN rasa train
语句。但是,由于模型是在相同的数据上训练的,并且使用相同的配置,我不认为差异有什么关系。)
下面是网络的docker-compose.yml
:
version: '3'
services:
rasa_server:
container_name: "rasa_server"
build:
context: backend
user: root
ports:
- "5005:5005"
expose:
- 5005
action_server:
container_name: "action_server"
build:
context: actions
ports:
- "5055:5055"
expose:
- 5055
web_server:
container_name: "web_server"
image: nginx
depends_on:
- "rasa_server"
- "action_server"
ports:
- "80:80"
- "443:443"
restart: always
volumes:
- ./web/conf/default.conf:/etc/nginx/conf.d/default.conf
- ./web/conf/explorer-ai.chat.conf:/etc/nginx/conf.d/explorer-ai.chat.conf
- ./web/conf/nginx.conf:/etc/nginx/nginx.conf
- ./web/html:/var/www/html
- ./certbot/www:/var/www/certbot
- ./certbot/conf:/etc/letsencrypt
certbot:
container_name: "certbot"
image: certbot/certbot
volumes:
- ./certbot/www:/var/www/cerbot:rw
- ./certbot/conf:/etc/letsencrypt:rw
Dockerfile
,用于backend
:
FROM rasa/rasa:3.3.1
WORKDIR /app
USER root
COPY ./models /app/models
COPY ./data /app/data
COPY . /app
RUN rasa train
ENTRYPOINT ["rasa", "run", "-m", "models", "--enable-api", "--cors", "*", "--debug"]
Dockerfile
用于actions
(如果它有用):
FROM rasa/rasa-sdk:3.3.0
WORKDIR /app
COPY ./requirements-actions.txt requirements.txt
COPY . /app
USER root
RUN pip install --no-cache-dir -r requirements.txt
USER 1001
EXPOSE 5055
ENTRYPOINT ["python", "-m", "rasa_sdk", "--actions", "actions"]
- 我用的是 www.example.com ?)Nginx反向代理。
我的Rasa(后端)credentials.yml
文件包括
socketio:
user_message_evt: user_uttered
bot_message_evt: bot_uttered
session_persistence: false
我的index.html
文件包含:
<script
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.2/socket.io.js"
integrity="sha512-YybopSVjZU0fe8TY4YDuQbP5bhwpGBE/T6eBUEZ0usM72IWBfWrgVI13qfX4V2A/W7Hdqnm7PIOYOwP9YHnICw=="
crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
<script>
const socket = io("https://explorer-ai.chat");
const messages = document.getElementById('messages');
const form = document.getElementById('form');
const messageInput = document.getElementById('message-input');
function scrollToBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
function appendMessage(msg, type) {
const item = document.createElement('div');
item.textContent = msg;
item.classList.add("message");
item.classList.add(`message_${type}`);
messages.appendChild(item);
scrollToBottom();
}
const welcome = "Hello! I'm Explorer AI, a virtual assistant for visitors to the " +
"Exploratorium in San Francisco. I've been trained to answer questions about the " +
"Exploratorium's exhibits and the concepts they illustrate.";
const how_help = "How may I assist you?";
appendMessage(welcome, "received");
appendMessage(how_help, "received");
form.addEventListener('submit', function (e) {
e.preventDefault();
const msg = messageInput.value;
if (msg) {
socket.emit('user_uttered', {
"message": msg,
});
messageInput.value = '';
appendMessage(msg, "sent");
}
});
socket.on('connect', function () {
console.log("Connected to Socket.io server");
});
socket.on('connect_error', (error) => {
console.log("Connection to Socket.io FAILED");
console.error(error);
});
socket.on('bot_uttered', function (response) {
console.log("Bot uttered:", response);
if (response.text) {
appendMessage(response.text, "received");
}
if (response.attachment) {
appendImage(response.attachment.payload.src, "received");
}
if (response.quick_replies) {
appendQuickReplies(response.quick_replies);
}
});
</script>
下面是我的web_server
配置:
server {
listen 80;
listen [::]:80;
server_name explorer-ai.chat www.explorer-ai.chat;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://explorer-ai.chat$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name explorer-ai.chat www.explorer-ai.chat;
ssl_certificate /etc/letsencrypt/live/explorer-ai.chat/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/explorer-ai.chat/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/html;
index index.html;
location /socket.io/ {
proxy_pass http://rasa_server:5005;
}
}
- 为了在本地(在
localhost
上)测试应用程序,我必须对Docker配置进行轻微更改,以适应我的M1芯片。特别是,我的backend
服务是buildFROM khalosa/rasa-aarch64:3.3.1
。在这种情况下,我注意到机器人倾向于(几乎?)总是忽略第一用户话语。下面的日志来自这样的本地测试。
下面是一段日志,对应于上面对话的开头:
似乎预测到了正确的操作,并触发了BotUttered
事件。但在此期间Web服务器没有任何操作。(另外,为什么所有记录的事件都具有相同的时间戳?事实上,来自Web服务器的下一个日志条目是这些,它们发生在用户的下一个消息之前。
我认为这与网络有关,对吗 www.example.com ),而不是Rasa组件?
非常感谢您的阅读,以及您所能提供的任何帮助!如果不明显的话,我是个菜鸟。:)
1条答案
按热度按时间pexxcrt21#
问题是我没有正确配置代理。
/socket.io/
位置需要一些额外的指令。这最终工作:为了避免
unknown "connection_upgrade" variable
错误,我还需要将以下指令添加到nginx.conf
文件的http
块中:我认为,以前,代理连接会退回到HTTP长轮询(www.example的默认设置 www.example.com )上下载。