-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
382 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# read .env files | ||
import dotenv, os | ||
dotenv.load_dotenv() | ||
|
||
# start a flask app | ||
from flask import Flask, request, jsonify | ||
|
||
flask_app = Flask(__name__) | ||
|
||
# this is the challenge route required by Slack to add perms | ||
@flask_app.route("/", methods=["POST"]) | ||
def slack_challenge(): | ||
if request.json and "challenge" in request.json: | ||
print("Received challenge") | ||
return jsonify({"challenge": request.json["challenge"]}) | ||
else: | ||
print("Got unknown request incoming") | ||
print(request.json) | ||
return | ||
|
||
if __name__ == "__main__": | ||
flask_app.run(port=3000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# read .env files | ||
import dotenv, os | ||
dotenv.load_dotenv() | ||
|
||
# Bring in deps including Slack Bolt framework | ||
from slack_bolt import App | ||
from slack_sdk import WebClient | ||
from flask import Flask, request, jsonify | ||
from slack_bolt.adapter.flask import SlackRequestHandler | ||
|
||
# Initialize Bolt app with token and secret | ||
app = App( | ||
token=os.environ.get("SLACK_BOT_TOKEN"), | ||
signing_secret=os.environ.get("SLACK_SIGNING_SECRET") | ||
) | ||
handler = SlackRequestHandler(app) | ||
|
||
# start flask app | ||
flask_app = Flask(__name__) | ||
|
||
# join the #bot-testing channel so we can listen to messages | ||
channel_list = app.client.conversations_list().data | ||
channel = next((channel for channel in channel_list.get('channels') if channel.get("name") == "bot-testing"), None) | ||
channel_id = channel.get('id') | ||
app.client.conversations_join(channel=channel_id) | ||
print(f"Found the channel {channel_id} and joined it") | ||
|
||
# get the bot's own user ID so it can tell when somebody is mentioning it | ||
auth_response = app.client.auth_test() | ||
bot_user_id = auth_response["user_id"] | ||
|
||
|
||
# this is the challenge route required by Slack | ||
# if it's not the challenge it's something for Bolt to handle | ||
@flask_app.route("/", methods=["POST"]) | ||
def slack_challenge(): | ||
if request.json and "challenge" in request.json: | ||
print("Received challenge") | ||
return jsonify({"challenge": request.json["challenge"]}) | ||
else: | ||
print("Incoming event:") | ||
print(request.json) | ||
return handler.handle(request) | ||
|
||
# this handles any incoming message the bot can hear | ||
# we want it to only respond when somebody messages it directly | ||
# otherwise it listens and stores every message as future context | ||
@app.message() | ||
def reply(message, say): | ||
# the slack message object is a complicated nested object | ||
# if message contains a "blocks" key | ||
# then look for a "block" with the type "rich text" | ||
# if you find it | ||
# then look inside that block for an "elements" key | ||
# if you find it | ||
# then examine each one of those for an "elements" key | ||
# if you find it | ||
# then look inside each "element" for one with type "user" | ||
# if you find it | ||
# and if that user matches the bot_user_id | ||
# then it's a message for the bot | ||
if message.get('blocks'): | ||
for block in message.get('blocks'): | ||
if block.get('type') == 'rich_text': | ||
for rich_text_section in block.get('elements'): | ||
for element in rich_text_section.get('elements'): | ||
if element.get('type') == 'user' and element.get('user_id') == bot_user_id: | ||
for element in rich_text_section.get('elements'): | ||
if element.get('type') == 'text': | ||
query = element.get('text') | ||
print(f"Somebody asked the bot: {query}") | ||
say("Yes?") | ||
return | ||
# otherwise do something else with it | ||
print("Saw a fact: ", message.get('text')) | ||
|
||
if __name__ == "__main__": | ||
flask_app.run(port=3000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,32 @@ | ||
# bring in llamaindex deps, debugging, and .env | ||
import dotenv | ||
import logging | ||
import sys | ||
dotenv.load_dotenv() | ||
|
||
from llama_index import VectorStoreIndex, Document, set_global_handler | ||
|
||
# turns on debuging | ||
set_global_handler("simple") | ||
|
||
# even noisier debugging | ||
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) | ||
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout)) | ||
|
||
# initialize index | ||
index = VectorStoreIndex([]) | ||
|
||
# create documents | ||
doc1 = Document(text="Molly is a cat") | ||
doc2 = Document(text="Doug is a dog") | ||
doc3 = Document(text="Carl is a rat") | ||
|
||
# add all 3 to the index | ||
index.insert(doc1) | ||
index.insert(doc2) | ||
index.insert(doc3) | ||
|
||
# run a query | ||
query_engine = index.as_query_engine() | ||
response = query_engine.query("Who is Molly?") | ||
print(response) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# read .env files | ||
import dotenv, os | ||
dotenv.load_dotenv() | ||
|
||
# Bring in deps including Slack Bolt framework | ||
from slack_bolt import App | ||
from flask import Flask, request, jsonify | ||
from slack_bolt.adapter.flask import SlackRequestHandler | ||
|
||
# bring in llamaindex deps | ||
import qdrant_client | ||
from llama_index import VectorStoreIndex, Document, StorageContext, ServiceContext | ||
from llama_index.vector_stores.qdrant import QdrantVectorStore | ||
|
||
# initialize qdrant client and a vector store that uses it | ||
client = qdrant_client.QdrantClient( | ||
path="./qdrant_data" | ||
) | ||
vector_store = QdrantVectorStore(client=client, collection_name="tweets") | ||
storage_context = StorageContext.from_defaults(vector_store=vector_store) | ||
|
||
index = VectorStoreIndex([],storage_context=storage_context) | ||
|
||
# Initialize Bolt app with token and secret | ||
app = App( | ||
token=os.environ.get("SLACK_BOT_TOKEN"), | ||
signing_secret=os.environ.get("SLACK_SIGNING_SECRET") | ||
) | ||
handler = SlackRequestHandler(app) | ||
|
||
# start flask app | ||
flask_app = Flask(__name__) | ||
|
||
# join the #bot-testing channel so we can listen to messages | ||
channel_list = app.client.conversations_list().data | ||
channel = next((channel for channel in channel_list.get('channels') if channel.get("name") == "bot-testing"), None) | ||
channel_id = channel.get('id') | ||
app.client.conversations_join(channel=channel_id) | ||
print(f"Found the channel {channel_id} and joined it") | ||
|
||
# get the bot's own user ID so it can tell when somebody is mentioning it | ||
auth_response = app.client.auth_test() | ||
bot_user_id = auth_response["user_id"] | ||
|
||
# this is the challenge route required by Slack | ||
# if it's not the challenge it's something for Bolt to handle | ||
@flask_app.route("/", methods=["POST"]) | ||
def slack_challenge(): | ||
if request.json and "challenge" in request.json: | ||
print("Received challenge") | ||
return jsonify({"challenge": request.json["challenge"]}) | ||
else: | ||
print("Incoming event:") | ||
print(request.json) | ||
return handler.handle(request) | ||
|
||
# this handles any incoming message the bot can hear | ||
# we want it to only respond when somebody messages it directly | ||
# otherwise it listens and stores every message as future context | ||
@app.message() | ||
def reply(message, say): | ||
# the slack message object is a complicated nested object | ||
# if message contains a "blocks" key | ||
# then look for a "block" with the type "rich text" | ||
# if you find it | ||
# then look inside that block for an "elements" key | ||
# if you find it | ||
# then examine each one of those for an "elements" key | ||
# if you find it | ||
# then look inside each "element" for one with type "user" | ||
# if you find it | ||
# and if that user matches the bot_user_id | ||
# then it's a message for the bot | ||
if message.get('blocks'): | ||
for block in message.get('blocks'): | ||
if block.get('type') == 'rich_text': | ||
for rich_text_section in block.get('elements'): | ||
for element in rich_text_section.get('elements'): | ||
if element.get('type') == 'user' and element.get('user_id') == bot_user_id: | ||
for element in rich_text_section.get('elements'): | ||
if element.get('type') == 'text': | ||
query = element.get('text') | ||
print(f"Somebody asked the bot: {query}") | ||
query_engine = index.as_query_engine() | ||
response = query_engine.query(query) | ||
print("Context was:") | ||
print(response.source_nodes) | ||
print(f"Response was: {response}") | ||
say(str(response)) | ||
return | ||
# otherwise treat it as a document to store | ||
index.insert(Document(text=message.get('text'))) | ||
print("Stored message", message.get('text')) | ||
|
||
if __name__ == "__main__": | ||
flask_app.run(port=3000) |
Oops, something went wrong.