はじめに
こちらの@taka_yayoi さんの記事にもありますが、LangchainのSQLDatabaseChainを使ってDatabricksの特定のデータに自然言語でアクセス出来るようになりました。
今回、こちらの仕組みをSlackから簡単にアクセスできるようにまとめましたので、皆様も是非トライしてみてください。
必要な環境
- Databricks SQLWarehouse
- OpenAI API (Secret Keyが必要です)
- Slack App
- EC2 or Lamdaなど pythonコードが動作する環境。デモの場合はPCでも可能です。
コードやSlackAppのデプロイファイルなど
今回必要なコード類やこちらのgitに公開しております。まずはお手元にクローンしてください。
https://github.com/maroon-spec/slack_sqldb
設定手順
1. SlackAppの作成
今回はレポジトリの中にSlackAppのデプロイファイルを用意してありますので、そちらを利用します。
display_information:
name: Databricks-sql-bot
features:
bot_user:
display_name: databricks-sql
always_online: true
oauth_config:
scopes:
bot:
- chat:write
- channels:history
- groups:history
- mpim:history
- im:history
- app_mentions:read
- reactions:write
- users:read
settings:
event_subscriptions:
bot_events:
- app_mention
- message.channels
- message.groups
org_deploy_enabled: false
socket_mode_enabled: true
token_rotation_enabled: false
[SlackApp]に移動して、Create New Appにて、From an app manifestを選択し、上記のyamlをコピーして貼り付けます。
Install Appに移動して、対象のワークスペースとAppを紐付けます。(以下はイメージ)
App Tokenを作成します。このTokenは後ほど利用します。
Basic information -> App-Levels Token. Scope: connections:write
最後にBot Tokenを取得します。
Install App -> Bot User OAuth Token取得
2. Slack上でAppが追加されているので、対象のChannelにBotを追加する.
3. Pythonコード実行
最後に Pythonコードを実行します。今回はシンプルにPC上で実行します。
(他にLambda とAPI Gatewayを組み合わせたり、Publicアクセス可能なEC2上などで動作させると本番でも利用できます)
まずはvenvを作成し、いくつかのライブラリーをインストールします。
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt
次にOS上に環境変数として以下をセットします。
export DATABRICKS_HOST="" # Databricks Workspace URL(https://は除く)
export DATABRICKS_TOKEN="" # Personal Access Token
export DATABRICKS_WAREHOUSE="" # SQL Warehouse ID (最後のID部分のみ)
export OPENAI_API_KEY="" # OpenAI APIのSecret Key
export SLACK_BOT_TOKEN="" # 先ほどのSlack BOT Token
export SLACK_APP_TOKEN="" # 先ほどのSlack App Token
実行するコードはこちらです。
コード内のカタログやスキーマ、テーブルを変更すると、対象となるテーブルを変更することができます。
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
#######################################################
## 今回検索対象とするカタログとスキーマを選択します。 #######
#######################################################
catalog = "samples"
schema = "nyctaxi"
tables = ["trips"]
host = os.environ.get("DATABRICKS_HOST")
warehouse_id = os.environ.get("DATABRICKS_WAREHOUSE")
api_token = os.environ.get("DATABRICKS_TOKEN")
# LLM
llm = OpenAI(temperature=0, verbose=True)
## Langchain SQLDatabaseChain
db = SQLDatabase.from_databricks(catalog=catalog,
schema=schema,
include_tables=tables,
host = host,
warehouse_id=warehouse_id,
api_token=api_token)
db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)
#######################################################
# ここから Slack 設定
# トークンとソケットモードハンドラーを使ってアプリを初期化します
#######################################################
app = App(token=os.environ.get("SLACK_BOT_TOKEN"))
# mentionされた場合メッセージを読み取ります
@app.event("app_mention")
def respond_to_mention(body, say):
channel_id = body["event"]["channel"]
user_id = body["event"]["user"]
question = body["event"]["text"]
response = db_chain.run(question)
# Craft your response message
message = f"Answer: {response}"
# Send the response message
say(message, channel=channel_id)
# アプリを起動します
if __name__ == "__main__":
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
実行します。
$ python app.py
設定は以上です。
試してみる
今回は、MentionでBotに問い合わせると、指定したテーブルに対して、自然言語で問い合わせできます。
例えば、どんなデータがあるか聞いてみます。(英語で帰ってきたので言語を指定しました)
次に、fare_amountというカラムがあったので、「運賃の平均金額は?」 と聞いてみると自動的に fare_amount と認識して平均値を出してくれます。
もう少し難しい、2つのカラムの時間差の平均時間を聞いてみました。
実行しているシェルを見てみると、裏ではSQLに変換して正しい問い合わせをしてくれてます。
Slack以外にも色々なインターフェースと組み合わせて利用できます。
対象となるテーブルはUnity CatalogのACLでRead権限のみを許可した方がいいです。MergeやDropもできてしまいます。DatabricksのService PrincipalなどでRead権限などを許可されたトークンを発行すると良いと思います。