Skip to content

Commit

Permalink
TriagerX Tools (#892)
Browse files Browse the repository at this point in the history
* 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
7 people authored Aug 1, 2024
1 parent 3010a3c commit 7745870
Show file tree
Hide file tree
Showing 13 changed files with 856 additions and 0 deletions.
1 change: 1 addition & 0 deletions TriagerXChatbot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/venv/
117 changes: 117 additions & 0 deletions TriagerXChatbot/README.md
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).
184 changes: 184 additions & 0 deletions TriagerXChatbot/main.py
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)
46 changes: 46 additions & 0 deletions TriagerXChatbot/requirements.txt
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
3 changes: 3 additions & 0 deletions TriagerXChatbot/startup.sh
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
3 changes: 3 additions & 0 deletions TriagerXServer/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.git*
**/*.pyc
.venv/
3 changes: 3 additions & 0 deletions TriagerXServer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
venv/
__pycache__/
tokens.txt
Loading

0 comments on commit 7745870

Please sign in to comment.