Hackathon 0x0d - Slack My Ticket 🧾

Presentation 🤓

In recent years, there has been significant progress in the field of artificial intelligence, especially with the development of lightweight models that can run locally and provide good results. These local AIs are interesting because they ensure data confidentiality, which is a crucial factor in our work environment.

As a software company, we use many digital tools to facilitate our work and collaboration among colleagues. Among these tools, we use Slack for internal communication and Redmine for project management.

When there seems to be an issue with our software, the Product Owner often inquires on Slack to get more details and clarify the problem. This usually leads to interesting discussions which sometimes result in creating a bug ticket on Redmine that is as precise and clear as possible.

The idea of our hackathon subject was to write a bot that could be mentioned in a Slack discussion to retrieve all the information and automatically create the corresponding ticket.

To achieve this, we split the work into two steps:

  1. Choosing an AI model and writing a prompt suitable for our situation,
  2. Developing a bot that acts as an intermediary between the user on Slack, the AI model, and Redmine.

The artificial intelligence 🧠

Choosing an AI model 🦙

First, we had to decide which model we were going to use. We needed a lightweight but efficient model for execution on a local machine with just a CPU, without GPU. During the hackathon, we chose to use Meta Llama 2 but as I’m writing this article, Meta Llama 3 🦙 has recently been released. Therefore, this article has been updated to reflect results using Llama 3. We retrieved a quantized version of Meta Llama 3 8B Instruct available on Hugging Face 🤗, which is a hub dedicated to open source natural language processing and artificial intelligence tools.

As we decided to use Python for our bot, we needed a library compatible with Llama 3 in Python. For this purpose, we used llama-cpp-python which are simple Python bindings for llama.cpp library.

Writing an effective prompt 📋

The prompt plays a crucial role in the performance of an AI model. It serves as a starting point to help the AI better understand the context and the desired outcome.

Here is the prompt we used:

Answer with a valid JSON structure with double quotes and the following
- priority: the priority of a message. The possible priority values are
- subject: a short one-line summary of the message. The subject's maximum
length is 20 words. Subject must be written in English.
- content: the complete content of the message, new lines and blank lines are
kept. Content can be improved and must be translated if it's not in English.
- project: the possible project values are {possible_projects}. The project
can be part of the channel name or part of the message.
- type: the type of the ticket; Possible values: {possible_types}

The message from the channel {channel_id}:

The answer:

Coding the bot 🤖

Let’s now move on to creating the bot that will act as the interface between the user writing on Slack, the AI on the local machine, and Redmine server that handles ticket creation.

Reading messages from Slack 💬

Slack provides a framework named Bolt for Python that simplifies the process of creating Slack apps and a Getting started guide. We used the Socket Mode because it lets apps use the Events API and interactive components without exposing a public HTTP endpoint.

Here are the minimum permissions we used for our Slack application:

  • Bot token with chat:write, app_mentions:read and users:read scopes
  • App-level token with connections:write scope
  • Enable Events with subscription to bot app_mention events

Creating tickets on Redmine ✍️

To communicate with Redmine, we used the Python-Redmine library.

However, since the AI’s responses may not correspond exactly to a valid JSON, we first attempt to fix the JSON to ensure it is valid with jsonrepair.py . Afterward, we move on to the fuzzy matching step with TheFuzz . The fuzzy matching is a technique used to identify strings with partial matches. We use this technique to rectify values and associate them with predefined values. It is very important for specific fields when creating the ticket on Redmine such as project name, priority, and ticket type.

Our results 📊

To test our bot, we have chosen the following message that a Product Owner might send:

Hello; 💣 critique je pense qu'on a une régression sur le lab et prod :
géocodage d'un contact depuis son adresse (page de détails d'un contact déjà
existant) :
je tape une adresse pour le contact (auparavant : champ vide ; et pas de
coordonnées / pas de pin sur la carte), la requête HTTP part bien vers le
geocodeur, et ce dernier répond avec des résultats (200 OK, FeatureCollection,
etc.), mais le produit n'en fait rien :
- pas d'affichage des résultats dans le sélecteur,
- pas de géocodage à l'enregistrement de fait, pas d'affichage du pin sur la

The bot will first acknowledge receipt of the ticket creation request and then provide the final message containing the ticket details:

Ticket creation in progress. Please wait...
The ticket has been created on Redmine:

And here is the ticket created on Redmine by the bot:

Project: [REDACTED]
Type: Bug
Priority: Major
Subject: Regression on lab and prod: geocoding of a contact from its address
Hello; 💣 I think we have a regression on the lab and prod. Geocoding of a
contact from its address (contact details page already existing) is not
working as expected.

I enter an address for the contact (previously empty field, no coordinates/pin
on the map), the HTTP request goes well to the geocoder, and it responds with
results (200 OK, FeatureCollection, etc.), but the product does nothing:

- No display of results in the selector,
- No geocoding at registration, no display of the pin on the map.

This ticket was generated by SlackMyTicket based on the following message:

Conclusion ✨

During this hackathon, we successfully developed a bot that retrieves a message on Slack when it is mentioned, passes this message to a locally executed AI, and creates a Redmine ticket based on the analysis and response from the AI.

The AI was simply executed on the laptop we usually use for development, and although they have powerful CPUs, we only have a powerless integrated GPU, which caused the AI to take a long time to respond 🐌. This hinders the development possibilities of the bot.

Here is a list of features/improvements that would be interesting to implement:

  • Ask the user interactively to validate the fields before creating the ticket to avoid having a spam machine.
  • Retrieve the previous message if it is mentioned in an empty message or the parent message if mentioned in a thread.
  • Furthermore, consider the entire thread discussion to create the ticket content.
Author Avatar

Yannick Li

Author Avatar

Nicolas Pauss

Author Avatar

Alexis Brasy

Author Avatar

Lucas Nicolaos