-
-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* created top folders for tools created by semesters-of-code-triager-x team * Update README.md Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@qatar.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> * Update README.md Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> * Fixed the repo link Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> * Fixed trailing lines Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@qatar.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> Co-authored-by: Diyorbek Ibragimov <dierbekibragimov@gmail.com> * Fixed the co-author email Co-authored by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored by: Diyorbek Ibragimov <dibragim@andrew.cmu.edu> Co-authored by: Lajeen Hasna<lhasna@andrew.cmu.edu> Co-authored by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored by: George Chkhaidze < gchkhaid@andrew.cmu.edu> * Deleted TriagerXServer/LICENSE Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> Co-authored-by: Diyorbek Ibragimov <dierbekibragimov@gmail.com> * Deleted TriagerXChatbot/LICENSE Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> Co-authored-by: Diyorbek Ibragimov <dierbekibragimov@gmail.com> * Fixed the license section Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> Co-authored-by: Diyorbek Ibragimov <dierbekibragimov@gmail.com> --------- Co-authored-by: Bel Ami Gisage Warakoze <bgisagew@andrew.cmu.edu> Co-authored-by: Fatima Al-Kharaz <fyk@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@qatar.cmu.edu> Co-authored-by: George Chkhaidze <gchkhaid@andrew.cmu.edu> Co-authored-by: Lujain Hasna <lhasna@andrew.cmu.edu> Co-authored-by: Bel Ami Gisage Warakoze <125438939+Belami02@users.noreply.github.com>
- Loading branch information
1 parent
3010a3c
commit 7745870
Showing
13 changed files
with
856 additions
and
0 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 @@ | ||
/venv/ |
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,117 @@ | ||
# Slack Chatbot | ||
|
||
A Slack chatbot designed to interact with users, recommend developers for issues, and summarize issues. | ||
|
||
## Features | ||
|
||
- Responds to Slack events such as `app_mention` and `url_verification`. | ||
- Sends messages to specific channels based on component mappings. | ||
- Recommends developers for github issues using the TriagerX model. | ||
- Summarizes github issues using the llama3 model. | ||
- Interacts with users and has the ability to fetch the conversation history. | ||
|
||
|
||
## Installation | ||
|
||
1. Clone the repository: | ||
|
||
```bash | ||
git clone https://github.com/adoptium/aqa-test-tools.git | ||
cd TriagerXChatbot | ||
``` | ||
|
||
3. Create and activate a virtual environment: | ||
|
||
```bash | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
``` | ||
|
||
4. Install the dependencies: | ||
- `requests`: Used for making HTTP requests. | ||
- `os`: Provides a way of using operating system dependent functionality like reading environment variables. | ||
- `logging`: Used for logging messages to the console or a file. | ||
- `slack_bolt`: A framework for building Slack apps. It provides the `App` class to initialize the Slack app and handle events. | ||
- `slack_sdk.errors.SlackApiError`: Used for handling Slack API errors. | ||
- `slackstyler`: A library for styling Slack messages. | ||
- `slack_bolt.adapter.flask.SlackRequestHandler`: An adapter to handle Slack requests using Flask. | ||
- `flask`: A micro web framework for Python used to create the web server. | ||
- `flask.request`: Used to handle incoming HTTP requests in Flask. | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
## Configuration | ||
|
||
1. Create a `.env` file in the root directory and add your Slack bot token, signing secret, and other necessary environment variables: | ||
```env | ||
SLACK_BOT_TOKEN=xoxb-your-slack-bot-token | ||
SIGNING_SECRET=your-signing-secret | ||
CHANNEL_BUILD=your-channel-id | ||
CHANNEL_GC=your-channel-id | ||
CHANNEL_JCLEXTENSIONS=your-channel-id | ||
CHANNEL_JVMTI=your-channel-id | ||
CHANNEL_TEST=your-channel-id | ||
CHANNEL_VM=your-channel-id | ||
GENERAL_CHANNEL=your-general-channel-id | ||
PAT_TOKEN=your-personal-access-token | ||
SERVER_URL=your-server-url | ||
``` | ||
|
||
## Usage | ||
|
||
1. Run the Flask app: | ||
```bash | ||
python main.py | ||
``` | ||
|
||
2. The app will start on port 3000. You can interact with the bot by mentioning it in Slack or by sending POST requests to the `/send-message` endpoint. | ||
|
||
## How to Use in Slack | ||
|
||
To interact with the chatbot in your Slack channel, you will have three options for actions and four options for models. Note that the `recommend` action only works with the `triagerx` model. You can tag the bot and follow this format: | ||
|
||
@your-bot-name <action> <model> <additional-parameters> | ||
|
||
### Actions | ||
- `summarize` | ||
- `interact` | ||
- `recommend` (only works with `triagerx`) | ||
|
||
### Models | ||
- `triagerx` | ||
- `chatgpt` | ||
- `gemini` | ||
- `llama3` | ||
|
||
### Examples | ||
|
||
- To summarize using the `chatgpt` model: | ||
``` | ||
@your-bot-name /summarize -chatgpt "github issue link" | ||
``` | ||
|
||
- To interact using the `llama3` model: | ||
``` | ||
@your-bot-name /interact -llama3 "What you would like to say" | ||
``` | ||
|
||
- To recommend using the `triagerx` model: | ||
``` | ||
@your-bot-name /recommend -triagerx "github issue link" | ||
``` | ||
|
||
The bot will process the request and respond in the channel accordingly. | ||
## Project Structure | ||
|
||
- `main.py`: The main entry point of the Slack chatbot application. | ||
- `requirements.txt`: A file containing the list of dependencies required by the project. | ||
- `.env`: Environment variables file (not included in the repository, to be created by the user). | ||
|
||
## License | ||
Distributed under the Apache License Version 2.0. See [LICENSE](../LICENSE) for more information. | ||
|
||
## Credits | ||
- **Created by the Tigers-X team**: [Lujain Hasna](https://github.com/coolujain), [Bel Ami Gisage Warakoze](https://github.com/Belami02), [Fatima Al-Kharaz](https://github.com/ftm-2005), [George Chkhaidze](https://github.com/GioChkhaidze), and [Diyorbek Ibragimov](https://github.com/diyorbekibragimov). | ||
- **Course Instructors**: Stephen Walli (Microsoft) and Prof. Eduardo Feo Flushing (CMUQ). | ||
- **Course Mentors**: Lan Xia (IBM), Longyu Zhang (IBM), and Shelley Lambert (Red Hat). | ||
- **TriagerX Model Creators**: Dr. Gias Udin (IBM) and Afif (University of Calgary). |
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,184 @@ | ||
import requests | ||
import os, logging | ||
from slack_bolt import App, request | ||
from slack_sdk.errors import SlackApiError | ||
from slackstyler import SlackStyler | ||
from slack_bolt.adapter.flask import SlackRequestHandler | ||
from flask import Flask, jsonify | ||
from flask import request as flask_request | ||
|
||
CHANNEL_BUILD = os.getenv("CHANNEL_BUILD") | ||
CHANNEL_GC = os.getenv("CHANNEL_GC") | ||
CHANNEL_JCLEXTENSIONS = os.getenv("CHANNEL_JCLEXTENSIONS") | ||
CHANNEL_JVMTI = os.getenv("CHANNEL_JVMTI") | ||
CHANNEL_TEST = os.getenv("CHANNEL_TEST") | ||
CHANNEL_VM = os.getenv("CHANNEL_VM") | ||
GENERAL_CHANNEL = os.getenv("GENERAL_CHANNEL") | ||
|
||
PAT_TOKEN = os.getenv("PAT_TOKEN") | ||
SLACK_APP_TOKEN = os.getenv("SLACK_APP_TOKEN") | ||
SLACK_BOT_TOKEN = os.getenv("SLACK_BOT_TOKEN") | ||
SIGNiNG_SECRET = os.getenv("SIGNING_SECRET") | ||
|
||
SERVER_URL = os.getenv("SERVER_URL") | ||
|
||
logging.basicConfig(level=logging.DEBUG) | ||
|
||
# Initialize your app with your bot token and signing secret | ||
app = App( | ||
token=SLACK_BOT_TOKEN, | ||
signing_secret=SIGNING_SECRET | ||
) | ||
styler = SlackStyler() | ||
|
||
@app.event("url_verification") | ||
def handle_challenge(request: request): | ||
json_body = request.body | ||
challenge = json_body.get("challenge") | ||
return { | ||
"statusCode": 200, | ||
"body": { | ||
"challenge": challenge | ||
} | ||
} | ||
|
||
def fetch_conversation_history(client, channel_id: str = GENERAL_CHANNEL, messages: int = 20): | ||
try: | ||
conversation_history = [] | ||
result = client.conversations_history(channel=channel_id, limit=messages) | ||
conversation_history = result["messages"] | ||
|
||
while len(conversation_history) < messages and result.get("has_more"): | ||
result = client.conversations_history(channel=channel_id, | ||
limit=messages - len(conversation_history), | ||
cursor=result["response_metadata"]["next_cursor"]) | ||
conversation_history.extend(result["messages"]) | ||
|
||
return conversation_history | ||
except SlackApiError as e: | ||
logging.error("Error fetching conversation history: {}".format(e)) | ||
return [] | ||
|
||
@app.event("app_mention") | ||
def event_test(client, event, say): | ||
text = event['text'] | ||
|
||
logging.debug("App mention event received") | ||
|
||
actions = ['summarize', 'interact', 'recommend'] | ||
models = ['triagerx','chatgpt', 'gemini', 'llama3'] | ||
model = None | ||
action = None | ||
|
||
for keyword in actions: | ||
if not action and f'/{keyword}' in text: | ||
text = text.replace(f'/{keyword}', '').strip() | ||
action = keyword | ||
|
||
for keyword in models: | ||
if not model and f'-{keyword}' in text: | ||
text = text.replace(f'-{keyword}', '').strip() | ||
model = keyword | ||
|
||
if None in [action, model]: | ||
print("Action or model is missing.") | ||
return | ||
|
||
issueData = { | ||
"title": "", | ||
"state": "open", | ||
"body": "", | ||
"labels": [], | ||
"assignees": [] | ||
} | ||
|
||
if action in ['summarize', 'recommend']: | ||
issueURL = text | ||
issueData = getIssueData(issueURL) | ||
|
||
inputData = { | ||
"issueData": issueData, | ||
"commentsData": [], | ||
"model": model, | ||
"action": action, | ||
"userComment": text | ||
} | ||
|
||
if action == "interact": | ||
history = fetch_conversation_history(client) | ||
inputData["commentsData"] = history | ||
|
||
####SEND inputData to our server#### | ||
headers = { | ||
'Content-Type': 'application/json' | ||
} | ||
|
||
serverURL = SERVER_URL | ||
response = requests.post(serverURL, json=inputData, headers=headers) | ||
message = response.json()['response'] | ||
try: | ||
response = client.chat_postMessage(channel=GENERAL_CHANNEL, blocks=[ | ||
{ | ||
"type": "section", | ||
"text": { | ||
"type": "mrkdwn", | ||
"text": styler.convert(message) | ||
} | ||
} | ||
]) | ||
except SlackApiError as e: | ||
print(f"Error posting message: {e}") | ||
|
||
def getIssueData(issue_url): | ||
issue_number = issue_url.split('/').pop() | ||
owner = issue_url.split('/')[3] | ||
repo = issue_url.split('/')[4] | ||
# GitHub API URL for the issue | ||
url = f'https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}' | ||
|
||
headers = { | ||
'Authorization': f'token {PAT_TOKEN}', | ||
'Accept': 'application/vnd.github.v3+json' | ||
} | ||
# Send the request | ||
response = requests.get(url, headers=headers) | ||
|
||
# Check if the request was successful | ||
if response.status_code == 200: | ||
issue_data = response.json() | ||
return issue_data | ||
else: | ||
print(f'Failed to fetch issue data: {response.status_code}') | ||
|
||
flask_app = Flask(__name__) | ||
handler = SlackRequestHandler(app) | ||
|
||
@flask_app.route("/slack/events", methods=["POST"]) | ||
def slack_events(): | ||
return handler.handle(flask_request) | ||
|
||
components_channel_mapping = { | ||
"comp:build": CHANNEL_BUILD, | ||
"comp:gc": CHANNEL_GC, | ||
"comp:jclextensions": CHANNEL_JCLEXTENSIONS, | ||
"comp:jvmti": CHANNEL_JVMTI, | ||
"comp:test": CHANNEL_TEST, | ||
"comp:vm": CHANNEL_VM, | ||
} | ||
|
||
@app.route('/send-message', methods=['POST']) | ||
def send_message(): | ||
data = flask_request.json | ||
component = data.get('component') | ||
channel_id = components_channel_mapping.get(component) | ||
message = data.get('message') | ||
|
||
try: | ||
response = app.client.chat_postMessage(channel=channel_id, text=message) | ||
return jsonify({'success': True, 'detail': 'Message sent successfully'}), 200 | ||
except SlackApiError as e: | ||
# You can add more error handling here based on SlackApiError | ||
return jsonify({'success': False, 'detail': str(e.response['error'])}), 400 | ||
|
||
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 |
---|---|---|
@@ -0,0 +1,46 @@ | ||
aiohttp==3.9.5 | ||
aiosignal==1.3.1 | ||
attrs==23.2.0 | ||
azure-core==1.30.2 | ||
blinker==1.8.2 | ||
botbuilder==0.0.1 | ||
botbuilder-core==4.15.1 | ||
botbuilder-integration-aiohttp==4.15.1 | ||
botbuilder-schema==4.15.1 | ||
botframework-connector==4.15.1 | ||
botframework-streaming==4.15.1 | ||
certifi==2024.6.2 | ||
cffi==1.16.0 | ||
charset-normalizer==3.3.2 | ||
click==8.1.7 | ||
cryptography==42.0.8 | ||
Flask==3.0.3 | ||
frozenlist==1.4.1 | ||
gunicorn==22.0.0 | ||
h11==0.14.0 | ||
idna==3.7 | ||
isodate==0.6.1 | ||
itsdangerous==2.2.0 | ||
Jinja2==3.1.4 | ||
jsonpickle==1.4.2 | ||
MarkupSafe==2.1.5 | ||
mistune==0.8.4 | ||
msal==1.29.0 | ||
msrest==0.7.1 | ||
multidict==6.0.5 | ||
oauthlib==3.2.2 | ||
packaging==24.1 | ||
pycparser==2.22 | ||
PyJWT==2.8.0 | ||
requests==2.32.3 | ||
requests-oauthlib==2.0.0 | ||
six==1.16.0 | ||
slack_bolt==1.19.0 | ||
slack_sdk==3.29.0 | ||
slackstyler==0.0.2 | ||
typing_extensions==4.12.2 | ||
ujson==5.10.0 | ||
urllib3==1.26.19 | ||
uvicorn==0.30.1 | ||
Werkzeug==3.0.3 | ||
yarl==1.9.4 |
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,3 @@ | ||
#!/bin/sh | ||
|
||
apt update && apt install -y libjpeg-dev libopenjp2-7-dev libtiff-dev libfreetype6-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev && gunicorn --bind=0.0.0.0 --timeout 600 main:flask_app |
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,3 @@ | ||
.git* | ||
**/*.pyc | ||
.venv/ |
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,3 @@ | ||
venv/ | ||
__pycache__/ | ||
tokens.txt |
Oops, something went wrong.