forked from seratch/ChatGPT-in-Slack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp_prod.py
161 lines (143 loc) · 5.29 KB
/
app_prod.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Unzip the dependencies managed by serverless-python-requirements
try:
import unzip_requirements # noqa: F401
except ImportError:
pass
#
# Imports
#
import logging
import os
from slack_bolt import App, Ack, BoltContext
import openai
from slack_sdk.web import WebClient
from slack_sdk.http_retry.builtin_handlers import RateLimitErrorRetryHandler
from app import register_listeners
#
# Product deployment (AWS Lambda)
#
# export SLACK_CLIENT_ID=
# export SLACK_CLIENT_SECRET=
# export SLACK_SIGNING_SECRET=
# export SLACK_SCOPES=app_mentions:read,channels:history,groups:history,im:history,mpim:history,chat:write.public,chat:write
# export SLACK_INSTALLATION_S3_BUCKET_NAME=
# export SLACK_STATE_S3_BUCKET_NAME=
# export OPENAI_S3_BUCKET_NAME=
# npm install -g serverless
# serverless plugin install -n serverless-python-requirements
# serverless deploy
#
import boto3
from slack_bolt.adapter.aws_lambda import SlackRequestHandler
from slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow import LambdaS3OAuthFlow
SlackRequestHandler.clear_all_log_handlers()
logging.basicConfig(format="%(asctime)s %(message)s", level=logging.WARN)
s3_client = boto3.client("s3")
openai_bucket_name = os.environ["OPENAI_S3_BUCKET_NAME"]
client = WebClient()
client.retry_handlers.append(RateLimitErrorRetryHandler(max_retry_count=2))
def handler(event, context_):
app = App(
process_before_response=True,
oauth_flow=LambdaS3OAuthFlow(),
client=client,
)
app.oauth_flow.settings.install_page_rendering_enabled = False
register_listeners(app)
@app.middleware
def set_s3_openai_api_key(context: BoltContext, next_):
try:
s3_response = s3_client.get_object(
Bucket=openai_bucket_name, Key=context.team_id
)
api_key = s3_response["Body"].read().decode("utf-8")
context["OPENAI_API_KEY"] = api_key
except: # noqa: E722
context["OPENAI_API_KEY"] = None
next_()
@app.event("app_home_opened")
def render_home_tab(client: WebClient, context: BoltContext):
text = (
"To enable this app in this Slack workspace, you need to save your OpenAI API key. "
"Visit <https://platform.openai.com/account/api-keys|your developer page> to grap your key!"
)
try:
s3_client.get_object(Bucket=openai_bucket_name, Key=context.team_id)
text = "This app is ready to use in this workspace :raised_hands:"
except: # noqa: E722
pass
client.views_publish(
user_id=context.user_id,
view={
"type": "home",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": text,
},
"accessory": {
"action_id": "configure",
"type": "button",
"text": {"type": "plain_text", "text": "Configure"},
"style": "primary",
"value": "api_key",
},
}
],
},
)
@app.action("configure")
def handle_some_action(ack, body: dict, client: WebClient):
ack()
client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "configure",
"submit": {"type": "plain_text", "text": "Submit"},
"close": {"type": "plain_text", "text": "Cancel"},
"title": {"type": "plain_text", "text": "OpenAI API Key"},
"blocks": [
{
"type": "input",
"block_id": "api_key",
"label": {
"type": "plain_text",
"text": "Save your OpenAI API key:",
},
"element": {"type": "plain_text_input", "action_id": "input"},
}
],
},
)
def validate_api_key_registration(ack: Ack, view: dict, logger: logging.Logger):
api_key = view["state"]["values"]["api_key"]["input"]["value"]
try:
openai.Model.retrieve(api_key=api_key, id="gpt-3.5-turbo")
ack()
except Exception as e:
logger.exception(e)
ack(
response_action="errors",
errors={"api_key": "This API key seems to be invalid"},
)
def save_api_key_registration(
view: dict,
logger: logging.Logger,
context: BoltContext,
):
api_key = view["state"]["values"]["api_key"]["input"]["value"]
try:
openai.Model.retrieve(api_key=api_key, id="gpt-3.5-turbo")
s3_client.put_object(
Bucket=openai_bucket_name, Key=context.team_id, Body=api_key
)
except Exception as e:
logger.exception(e)
app.view("configure")(
ack=validate_api_key_registration, lazy=[save_api_key_registration]
)
slack_handler = SlackRequestHandler(app=app)
return slack_handler.handle(event, context_)