From 8a0390d4736df1918328643b4e5a52a3797b7080 Mon Sep 17 00:00:00 2001 From: Christopher Grant Date: Mon, 26 Feb 2024 11:50:59 -0500 Subject: [PATCH] Slackbot interface (#2) * Initial slackbot code * Slack bot server updates --- slack-bot/Dockerfile | 29 +++++++ slack-bot/README.md | 155 +++++++++++++++++++++++++++++++++++++ slack-bot/main.py | 54 +++++++++++++ slack-bot/mainfest.json | 42 ++++++++++ slack-bot/requirements.txt | 4 + 5 files changed, 284 insertions(+) create mode 100644 slack-bot/Dockerfile create mode 100644 slack-bot/README.md create mode 100644 slack-bot/main.py create mode 100644 slack-bot/mainfest.json create mode 100644 slack-bot/requirements.txt diff --git a/slack-bot/Dockerfile b/slack-bot/Dockerfile new file mode 100644 index 0000000..8b917a8 --- /dev/null +++ b/slack-bot/Dockerfile @@ -0,0 +1,29 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM python:3.8.5-slim-buster + +# Allow statements and log messages to immediately appear in the Knative logs +ENV PYTHONUNBUFFERED True + +# Copy local code to the container image. +ENV APP_HOME /app +WORKDIR $APP_HOME +COPY . ./ + +# Install production dependencies. +RUN pip install -U pip && pip install -r requirements.txt + +# Run the web service on container startup. +ENTRYPOINT gunicorn --bind :$PORT --workers 1 --threads 2 --timeout 120 main:flask_app diff --git a/slack-bot/README.md b/slack-bot/README.md new file mode 100644 index 0000000..0e3883d --- /dev/null +++ b/slack-bot/README.md @@ -0,0 +1,155 @@ +# Slack Client for GenAI with Vertex on Google + +## Installation + +### Create Slack App +- Create a new app on [https://api.slack.com/apps](https://api.slack.com/apps) +- Choose from App Manifest +- Select your workspace +- Paste the following manifest into the JSON tab + +```json + +{ + "display_information": { + "name": "DevAI Bot" + }, + "features": { + "app_home": { + "home_tab_enabled": false, + "messages_tab_enabled": true, + "messages_tab_read_only_enabled": false + }, + "bot_user": { + "display_name": "DevAI Bot", + "always_online": false + } + }, + "oauth_config": { + "scopes": { + "bot": [ + "calls:write", + "im:history", + "im:write", + "mpim:write", + "chat:write", + "channels:history", + "groups:history" + ] + } + }, + "settings": { + "event_subscriptions": { + "request_url": "https:///slack/events", + "bot_events": [ + "message.channels", + "message.groups", + "message.im" + ] + }, + "org_deploy_enabled": false, + "socket_mode_enabled": false, + "token_rotation_enabled": false + } +} +``` +- Click Create + +### Save Bot Tokens +You'll need to provide credentials to Slack from the cloud run backend. +Locate the tokens and set them as environment variables for later use. + +- Click the Basic Information link for your Slack App +- Scroll down and locate the Signing Secret +- Click show and copy the value +- In your terminal set the env variable with the command below, pasting in your value after the equal sign + +```sh +export SLACK_SIGNING_SECRET= +``` + +- Click on OAuth & Permissions in the navigation for your app in Slack +- Locate the OAuth Tokens for Your Workspace section +- Click Install to Workspace and complete the flow +- Copy the Bot User OAuth Token +- In your terminal set the env variable with the command below, pasting in your value after the equal sign + +```sh +export SLACK_BOT_TOKEN= +``` + +### Deploy Cloud Run Service + +From the slack-bot directory run the following command to deploy the backing service + +```sh +gcloud run deploy devai-slackbot \ + --source . \ + --allow-unauthenticated \ + --set-env-vars SLACK_SIGNING_SECRET=${SLACK_SIGNING_SECRET},SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN} +``` + +- Copy the endpoint URL from the following command + +```sh +echo "Slack Endpoint:" +echo "$(gcloud run services describe devai-slackbot \ + --format='value(status.url)' \ + --platform managed)/slack/events" +``` + +### Finalize Bot configuration + +You'll need to update the backend URL for your app within the slack dashboard. + +- Return to your app in [https://api.slack.com/apps](https://api.slack.com/apps) +- Click on Event SUbscriptions in the navigation. +- Paste the endpoint generated from the previous step, into the Request URL field. +- Once the url has been verified Click Save at the bottom of the screen to persist your changes. + +Now go into your slack workspace and start interacting with DevAI Bot + +## Development Resources + +Slack Guide: https://api.slack.com/start/building/bolt-python + +UI Based Configuration: + +OAuth & Permissions -> Scopes: +- calls:write +- chat:write +- im:history +- im:write +- mpim:write + + +Event Subscriptions -> Enable Events : URL: +- https:///slack/events +Event Subscriptions -> Subscribe to bot events: +- app_home_opened +- message.im + +Alternatively create and app using the manifest.json provided. Be sure to update the `request_url` first. + + +Teminal 2 +```sh +ngrok config add-authtoken +ngrok http 3000 +``` + +Terminal 1 +```sh +python3 -m venv .venv +source .venv/bin/activate +export SLACK_BOT_TOKEN= +export SLACK_SIGNING_SECRET= +pip install google-cloud-aiplatform +pip install slack_bolt +python3 app.py +``` + +Set the following in cloudrun from [API.slack.com](https://api.slack.com/apps/A06JUDJS63C) + +SLACK_BOT_TOKEN= +SLACK_SIGNING_SECRET= diff --git a/slack-bot/main.py b/slack-bot/main.py new file mode 100644 index 0000000..a55a19f --- /dev/null +++ b/slack-bot/main.py @@ -0,0 +1,54 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from slack_bolt.adapter.flask import SlackRequestHandler +from flask import Flask, request +import logging +import os + +from vertexai.language_models import CodeChatModel, ChatModel +from slack_bolt import App + +logging.basicConfig(level=logging.DEBUG) +app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + + +@app.event("message") +def echo_message(client, event, logger): + print(event) + code_chat_model = CodeChatModel.from_pretrained("codechat-bison") + context = "SYSTEM: You are a slackbot proficient in all coding languages. You specialize in development for Google Cloud. Respond ONLY to coding related questions. For non technical questions reply with 'I Don't know how to answer that, I can only answer coding related technical questions'. Ensure all responses are appropriate for a slackbot." + chat = code_chat_model.start_chat(context=context) + response = chat.send_message(event["text"]) + + client.chat_postMessage(channel=event["channel"], text=response.text) + + + +flask_app = Flask(__name__) +handler = SlackRequestHandler(app) + + +@flask_app.route("/slack/events", methods=["POST"]) +def slack_events(): + return handler.handle(request) + + +# Only for local debug +if __name__ == "__main__": + flask_app.run(debug=True, host="0.0.0.0", + port=int(os.environ.get("PORT", 3000))) diff --git a/slack-bot/mainfest.json b/slack-bot/mainfest.json new file mode 100644 index 0000000..b1410bd --- /dev/null +++ b/slack-bot/mainfest.json @@ -0,0 +1,42 @@ +{ + "display_information": { + "name": "DevAI Bot" + }, + "features": { + "app_home": { + "home_tab_enabled": false, + "messages_tab_enabled": true, + "messages_tab_read_only_enabled": false + }, + "bot_user": { + "display_name": "DevAI Bot", + "always_online": false + } + }, + "oauth_config": { + "scopes": { + "bot": [ + "calls:write", + "im:history", + "im:write", + "mpim:write", + "chat:write", + "channels:history", + "groups:history" + ] + } + }, + "settings": { + "event_subscriptions": { + "request_url": "/slack/events", + "bot_events": [ + "message.channels", + "message.groups", + "message.im" + ] + }, + "org_deploy_enabled": false, + "socket_mode_enabled": false, + "token_rotation_enabled": false + } +} \ No newline at end of file diff --git a/slack-bot/requirements.txt b/slack-bot/requirements.txt new file mode 100644 index 0000000..45de269 --- /dev/null +++ b/slack-bot/requirements.txt @@ -0,0 +1,4 @@ +slack_bolt +Flask>=1.1 +gunicorn>=20 +google-cloud-aiplatform==1.35.0 \ No newline at end of file