hetvi22/commit_message_quality
0
1{2 "nbformat": 4,3 "nbformat_minor": 0,4 "metadata": {5 "colab": {6 "provenance": []7 },8 "kernelspec": {9 "name": "python3",10 "display_name": "Python 3"11 },12 "language_info": {13 "name": "python"14 }15 },16 "cells": [17 {18 "cell_type": "markdown",19 "source": [20 "# **COMMIT MESSAGE QUALITY ANALYZER**\n",21 "## **Domain: Machine Learning and Software Engineering**\n",22 "\n",23 "**Year - 3rd** **|** **Div - A** **|** **Batch - A1**\n",24 "\n",25 "**Group Members:** \n",26 "**230090107043 - Hetvi Doshi** \n",27 "**230090107241 - Shreya Wani** \n",28 " **240093107004 - Bhavini Badgujar** \n",29 " **230090107081 - Himanshu Mali** \n",30 " **230090107175 - Prakhar Sinha** \n",31 " **230090107111 - Devansh Parekh**"32 ],33 "metadata": {34 "id": "a8t7OKyDuvUO"35 }36 },37 {38 "cell_type": "markdown",39 "source": [40 "## **IMPORTING LIBRARIES**"41 ],42 "metadata": {43 "id": "eH7yqekqK41q"44 }45 },46 {47 "cell_type": "code",48 "execution_count": 1,49 "metadata": {50 "colab": {51 "base_uri": "https://localhost:8080/"52 },53 "id": "FLQrDqkPuqws",54 "outputId": "6dc9a17f-e649-42ec-b80d-255067fba9d5"55 },56 "outputs": [57 {58 "output_type": "execute_result",59 "data": {60 "text/plain": [61 "0"62 ]63 },64 "metadata": {},65 "execution_count": 166 }67 ],68 "source": [69 "import re\n",70 "import pandas as pd\n",71 "from sklearn.model_selection import train_test_split\n",72 "from sklearn.feature_extraction.text import TfidfVectorizer\n",73 "from sklearn.naive_bayes import MultinomialNB\n",74 "from sklearn.pipeline import Pipeline\n",75 "from sklearn.metrics import classification_report, confusion_matrix, accuracy_score\n",76 "import matplotlib.pyplot as plt\n",77 "import seaborn as sns\n",78 "\n",79 "import random\n",80 "random.seed(42)\n",81 "\n",82 "import gc\n",83 "gc.collect()"84 ]85 },86 {87 "cell_type": "markdown",88 "source": [89 "## **DATA COLLECTION**"90 ],91 "metadata": {92 "id": "CnQ8vFEfK_qG"93 }94 },95 {96 "cell_type": "code",97 "source": [98 "data = [\n",99 " (\"Refactor user authentication module for better maintainability\", \"high\"),\n",100 " (\"Fix memory leak in image processing pipeline\", \"high\"),\n",101 " (\"Improve API response time by implementing caching\", \"high\"),\n",102 " (\"Add unit tests for payment gateway integration\", \"high\"),\n",103 " (\"Optimize database queries to reduce page load time\", \"high\"),\n",104 " (\"Implement role-based access control for admin panel\", \"high\"),\n",105 " (\"Fix critical security vulnerability in login endpoint\", \"high\"),\n",106 " (\"Improve error handling in file upload service\", \"high\"),\n",107 " (\"Add logging for debugging production issues\", \"high\"),\n",108 " (\"Refactor legacy code in dashboard module\", \"high\"),\n",109 " (\"Implement rate limiting to prevent abuse\", \"high\"),\n",110 " (\"Add input validation for user registration form\", \"high\"),\n",111 " (\"Fix race condition in async task queue\", \"high\"),\n",112 " (\"Improve documentation for API endpoints\", \"high\"),\n",113 " (\"Add support for multi-language UI\", \"high\"),\n",114 " (\"Fix broken link in footer navigation\", \"high\"),\n",115 " (\"Improve accessibility for screen readers\", \"high\"),\n",116 " (\"Add dark mode toggle in user settings\", \"high\"),\n",117 " (\"Fix timezone handling in event scheduler\", \"high\"),\n",118 " (\"Refactor email notification system\", \"high\"),\n",119 " (\"Add analytics tracking for user engagement\", \"high\"),\n",120 " (\"Fix CORS policy for frontend-backend communication\", \"high\"),\n",121 " (\"Improve password strength requirements\", \"high\"),\n",122 " (\"Add backup system for user data\", \"high\"),\n",123 " (\"Fix alignment issue in mobile view\", \"high\"),\n",124 " (\"Implement lazy loading for images\", \"high\"),\n",125 " (\"Add search functionality to user dashboard\", \"high\"),\n",126 " (\"Fix broken API endpoint for user profile\", \"high\"),\n",127 " (\"Improve SEO meta tags for marketing pages\", \"high\"),\n",128 " (\"Add social media sharing buttons\", \"high\"),\n",129 " (\"Fix broken form validation on checkout page\", \"high\"),\n",130 " (\"Improve performance of search algorithm\", \"high\"),\n",131 " (\"Add pagination to user list view\", \"high\"),\n",132 " (\"Fix broken redirect after login\", \"high\"),\n",133 " (\"Improve UX for password reset flow\", \"high\"),\n",134 " (\"Add tooltips for complex UI elements\", \"high\"),\n",135 " (\"Fix broken image paths in documentation\", \"high\"),\n",136 " (\"Improve loading spinner visibility\", \"high\"),\n",137 " (\"Add confirmation dialog before delete action\", \"high\"),\n",138 " (\"Fix broken sorting in data table\", \"high\"),\n",139 " (\"Improve contrast for better readability\", \"high\"),\n",140 " (\"Add keyboard shortcuts for power users\", \"high\"),\n",141 " (\"Fix broken export to CSV feature\", \"high\"),\n",142 " (\"Improve onboarding tutorial for new users\", \"high\"),\n",143 " (\"Add support for RTL languages\", \"high\"),\n",144 " (\"Fix broken drag-and-drop functionality\", \"high\"),\n",145 " (\"Improve error messages for form validation\", \"high\"),\n",146 " (\"Add auto-save feature for draft content\", \"high\"),\n",147 " (\"Fix broken print stylesheet\", \"high\"),\n",148 " (\"Update user profile page styles\", \"high\"),\n",149 " (\"Fix login bug for edge case\", \"high\"),\n",150 " (\"Refactor config loader for scalability\", \"high\"),\n",151 " (\"Add health check endpoint for monitoring\", \"high\"),\n",152 " (\"Improve test coverage for core module\", \"high\"),\n",153 " (\"Fix data race in concurrent requests\", \"high\"),\n",154 " (\"Add retry logic for flaky external API\", \"high\"),\n",155 " (\"Improve startup time of application\", \"high\"),\n",156 " (\"Fix edge case in date parsing logic\", \"high\"),\n",157 " (\"Add audit log for sensitive operations\", \"high\"),\n",158 " (\"Refactor state management for clarity\", \"high\"),\n",159 " (\"Fix memory leak in WebSocket handler\", \"high\"),\n",160 " (\"Improve handling of malformed input\", \"high\"),\n",161 " (\"Add rate limit headers to responses\", \"high\"),\n",162 " (\"Fix bug in CSV export formatting\", \"high\"),\n",163 " (\"Improve resilience to network failures\", \"high\"),\n",164 " (\"Add support for custom themes\", \"high\"),\n",165 " (\"Fix bug in notification delivery\", \"high\"),\n",166 " (\"Refactor API client for better error handling\", \"high\"),\n",167 " (\"Improve performance of dashboard rendering\", \"high\"),\n",168 " (\"Add validation for file uploads\", \"high\"),\n",169 " (\"Fix bug in user role assignment\", \"high\"),\n",170 " (\"Improve handling of large datasets\", \"high\"),\n",171 " (\"Add support for custom domains\", \"high\"),\n",172 " (\"Fix bug in session timeout logic\", \"high\"),\n",173 " (\"Refactor logging system for structured output\", \"high\"),\n",174 " (\"Improve reliability of background jobs\", \"high\"),\n",175 " (\"Add support for OAuth2 providers\", \"high\"),\n",176 " (\"Fix bug in password reset token generation\", \"high\"),\n",177 " (\"Improve scalability of message queue\", \"high\"),\n",178 " (\"fix bug\", \"low\"),\n",179 " (\"update code\", \"low\"),\n",180 " (\"change stuff\", \"low\"),\n",181 " (\"work on it\", \"low\"),\n",182 " (\"fix\", \"low\"),\n",183 " (\"update\", \"low\"),\n",184 " (\"changed things\", \"low\"),\n",185 " (\"did stuff\", \"low\"),\n",186 " (\"fix issue\", \"low\"),\n",187 " (\"tweak\", \"low\"),\n",188 " (\"adjust\", \"low\"),\n",189 " (\"minor change\", \"low\"),\n",190 " (\"small fix\", \"low\"),\n",191 " (\"update file\", \"low\"),\n",192 " (\"change code\", \"low\"),\n",193 " (\"fix typo\", \"low\"),\n",194 " (\"update config\", \"low\"),\n",195 " (\"change settings\", \"low\"),\n",196 " (\"work\", \"low\"),\n",197 " (\"stuff\", \"low\"),\n",198 " (\"whatever\", \"low\"),\n",199 " (\"idk\", \"low\"),\n",200 " (\"test\", \"low\"),\n",201 " (\"try\", \"low\"),\n",202 " (\"oops\", \"low\"),\n",203 " (\"again\", \"low\"),\n",204 " (\"help\", \"low\"),\n",205 " (\"broken\", \"low\"),\n",206 " (\"not working\", \"low\"),\n",207 " (\"why\", \"low\"),\n",208 " (\"debug\", \"low\"),\n",209 " (\"temp\", \"low\"),\n",210 " (\"quick fix\", \"low\"),\n",211 " (\"hack\", \"low\"),\n",212 " (\"patch\", \"low\"),\n",213 " (\"dirty fix\", \"low\"),\n",214 " (\"ugly code\", \"low\"),\n",215 " (\"sorry\", \"low\"),\n",216 " (\"later\", \"low\"),\n",217 " (\"todo\", \"low\"),\n",218 " (\"wip\", \"low\"),\n",219 " (\"experimental\", \"low\"),\n",220 " (\"prototype\", \"low\"),\n",221 " (\"draft\", \"low\"),\n",222 " (\"backup\", \"low\"),\n",223 " (\"old\", \"low\"),\n",224 " (\"new\", \"low\"),\n",225 " (\"version\", \"low\"),\n",226 " (\"fixed\", \"low\"),\n",227 " (\"updated\", \"low\"),\n",228 " (\"changes\", \"low\"),\n",229 " (\"did it\", \"low\"),\n",230 " (\"made it work\", \"low\"),\n",231 " (\"sort of works\", \"low\"),\n",232 " (\"kinda fixed\", \"low\"),\n",233 " (\"not sure\", \"low\"),\n",234 " (\"might be broken\", \"low\"),\n",235 " (\"works on my machine\", \"low\")\n",236 "]\n",237 "\n",238 "df = pd.DataFrame(data, columns=['commit_message', 'quality_label'])\n",239 "print(\"Dataset created with\", len(df), \"samples\")\n",240 "df.head(10)"241 ],242 "metadata": {243 "colab": {244 "base_uri": "https://localhost:8080/",245 "height": 380246 },247 "id": "WxcueMgVgRMB",248 "outputId": "e21916c2-dc29-4edb-a254-c6867a5a42e4"249 },250 "execution_count": 2,251 "outputs": [252 {253 "output_type": "stream",254 "name": "stdout",255 "text": [256 "Dataset created with 137 samples\n"257 ]258 },259 {260 "output_type": "execute_result",261 "data": {262 "text/plain": [263 " commit_message quality_label\n",264 "0 Refactor user authentication module for better... high\n",265 "1 Fix memory leak in image processing pipeline high\n",266 "2 Improve API response time by implementing caching high\n",267 "3 Add unit tests for payment gateway integration high\n",268 "4 Optimize database queries to reduce page load ... high\n",269 "5 Implement role-based access control for admin ... high\n",270 "6 Fix critical security vulnerability in login e... high\n",271 "7 Improve error handling in file upload service high\n",272 "8 Add logging for debugging production issues high\n",273 "9 Refactor legacy code in dashboard module high"274 ],275 "text/html": [276 "\n",277 " <div id=\"df-a2ccfbbf-42c6-47d8-b541-d6b7716eb81f\" class=\"colab-df-container\">\n",278 " <div>\n",279 "<style scoped>\n",280 " .dataframe tbody tr th:only-of-type {\n",281 " vertical-align: middle;\n",282 " }\n",283 "\n",284 " .dataframe tbody tr th {\n",285 " vertical-align: top;\n",286 " }\n",287 "\n",288 " .dataframe thead th {\n",289 " text-align: right;\n",290 " }\n",291 "</style>\n",292 "<table border=\"1\" class=\"dataframe\">\n",293 " <thead>\n",294 " <tr style=\"text-align: right;\">\n",295 " <th></th>\n",296 " <th>commit_message</th>\n",297 " <th>quality_label</th>\n",298 " </tr>\n",299 " </thead>\n",300 " <tbody>\n",301 " <tr>\n",302 " <th>0</th>\n",303 " <td>Refactor user authentication module for better...</td>\n",304 " <td>high</td>\n",305 " </tr>\n",306 " <tr>\n",307 " <th>1</th>\n",308 " <td>Fix memory leak in image processing pipeline</td>\n",309 " <td>high</td>\n",310 " </tr>\n",311 " <tr>\n",312 " <th>2</th>\n",313 " <td>Improve API response time by implementing caching</td>\n",314 " <td>high</td>\n",315 " </tr>\n",316 " <tr>\n",317 " <th>3</th>\n",318 " <td>Add unit tests for payment gateway integration</td>\n",319 " <td>high</td>\n",320 " </tr>\n",321 " <tr>\n",322 " <th>4</th>\n",323 " <td>Optimize database queries to reduce page load ...</td>\n",324 " <td>high</td>\n",325 " </tr>\n",326 " <tr>\n",327 " <th>5</th>\n",328 " <td>Implement role-based access control for admin ...</td>\n",329 " <td>high</td>\n",330 " </tr>\n",331 " <tr>\n",332 " <th>6</th>\n",333 " <td>Fix critical security vulnerability in login e...</td>\n",334 " <td>high</td>\n",335 " </tr>\n",336 " <tr>\n",337 " <th>7</th>\n",338 " <td>Improve error handling in file upload service</td>\n",339 " <td>high</td>\n",340 " </tr>\n",341 " <tr>\n",342 " <th>8</th>\n",343 " <td>Add logging for debugging production issues</td>\n",344 " <td>high</td>\n",345 " </tr>\n",346 " <tr>\n",347 " <th>9</th>\n",348 " <td>Refactor legacy code in dashboard module</td>\n",349 " <td>high</td>\n",350 " </tr>\n",351 " </tbody>\n",352 "</table>\n",353 "</div>\n",354 " <div class=\"colab-df-buttons\">\n",355 "\n",356 " <div class=\"colab-df-container\">\n",357 " <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-a2ccfbbf-42c6-47d8-b541-d6b7716eb81f')\"\n",358 " title=\"Convert this dataframe to an interactive table.\"\n",359 " style=\"display:none;\">\n",360 "\n",361 " <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",362 " <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",363 " </svg>\n",364 " </button>\n",365 "\n",366 " <style>\n",367 " .colab-df-container {\n",368 " display:flex;\n",369 " gap: 12px;\n",370 " }\n",371 "\n",372 " .colab-df-convert {\n",373 " background-color: #E8F0FE;\n",374 " border: none;\n",375 " border-radius: 50%;\n",376 " cursor: pointer;\n",377 " display: none;\n",378 " fill: #1967D2;\n",379 " height: 32px;\n",380 " padding: 0 0 0 0;\n",381 " width: 32px;\n",382 " }\n",383 "\n",384 " .colab-df-convert:hover {\n",385 " background-color: #E2EBFA;\n",386 " box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",387 " fill: #174EA6;\n",388 " }\n",389 "\n",390 " .colab-df-buttons div {\n",391 " margin-bottom: 4px;\n",392 " }\n",393 "\n",394 " [theme=dark] .colab-df-convert {\n",395 " background-color: #3B4455;\n",396 " fill: #D2E3FC;\n",397 " }\n",398 "\n",399 " [theme=dark] .colab-df-convert:hover {\n",400 " background-color: #434B5C;\n",401 " box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",402 " filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",403 " fill: #FFFFFF;\n",404 " }\n",405 " </style>\n",406 "\n",407 " <script>\n",408 " const buttonEl =\n",409 " document.querySelector('#df-a2ccfbbf-42c6-47d8-b541-d6b7716eb81f button.colab-df-convert');\n",410 " buttonEl.style.display =\n",411 " google.colab.kernel.accessAllowed ? 'block' : 'none';\n",412 "\n",413 " async function convertToInteractive(key) {\n",414 " const element = document.querySelector('#df-a2ccfbbf-42c6-47d8-b541-d6b7716eb81f');\n",415 " const dataTable =\n",416 " await google.colab.kernel.invokeFunction('convertToInteractive',\n",417 " [key], {});\n",418 " if (!dataTable) return;\n",419 "\n",420 " const docLinkHtml = 'Like what you see? Visit the ' +\n",421 " '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",422 " + ' to learn more about interactive tables.';\n",423 " element.innerHTML = '';\n",424 " dataTable['output_type'] = 'display_data';\n",425 " await google.colab.output.renderOutput(dataTable, element);\n",426 " const docLink = document.createElement('div');\n",427 " docLink.innerHTML = docLinkHtml;\n",428 " element.appendChild(docLink);\n",429 " }\n",430 " </script>\n",431 " </div>\n",432 "\n",433 "\n",434 " <div id=\"df-f311969b-713e-4580-bfd5-d6d05bebca53\">\n",435 " <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-f311969b-713e-4580-bfd5-d6d05bebca53')\"\n",436 " title=\"Suggest charts\"\n",437 " style=\"display:none;\">\n",438 "\n",439 "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",440 " width=\"24px\">\n",441 " <g>\n",442 " <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",443 " </g>\n",444 "</svg>\n",445 " </button>\n",446 "\n",447 "<style>\n",448 " .colab-df-quickchart {\n",449 " --bg-color: #E8F0FE;\n",450 " --fill-color: #1967D2;\n",451 " --hover-bg-color: #E2EBFA;\n",452 " --hover-fill-color: #174EA6;\n",453 " --disabled-fill-color: #AAA;\n",454 " --disabled-bg-color: #DDD;\n",455 " }\n",456 "\n",457 " [theme=dark] .colab-df-quickchart {\n",458 " --bg-color: #3B4455;\n",459 " --fill-color: #D2E3FC;\n",460 " --hover-bg-color: #434B5C;\n",461 " --hover-fill-color: #FFFFFF;\n",462 " --disabled-bg-color: #3B4455;\n",463 " --disabled-fill-color: #666;\n",464 " }\n",465 "\n",466 " .colab-df-quickchart {\n",467 " background-color: var(--bg-color);\n",468 " border: none;\n",469 " border-radius: 50%;\n",470 " cursor: pointer;\n",471 " display: none;\n",472 " fill: var(--fill-color);\n",473 " height: 32px;\n",474 " padding: 0;\n",475 " width: 32px;\n",476 " }\n",477 "\n",478 " .colab-df-quickchart:hover {\n",479 " background-color: var(--hover-bg-color);\n",480 " box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",481 " fill: var(--button-hover-fill-color);\n",482 " }\n",483 "\n",484 " .colab-df-quickchart-complete:disabled,\n",485 " .colab-df-quickchart-complete:disabled:hover {\n",486 " background-color: var(--disabled-bg-color);\n",487 " fill: var(--disabled-fill-color);\n",488 " box-shadow: none;\n",489 " }\n",490 "\n",491 " .colab-df-spinner {\n",492 " border: 2px solid var(--fill-color);\n",493 " border-color: transparent;\n",494 " border-bottom-color: var(--fill-color);\n",495 " animation:\n",496 " spin 1s steps(1) infinite;\n",497 " }\n",498 "\n",499 " @keyframes spin {\n",500 " 0% {\n",501 " border-color: transparent;\n",502 " border-bottom-color: var(--fill-color);\n",503 " border-left-color: var(--fill-color);\n",504 " }\n",505 " 20% {\n",506 " border-color: transparent;\n",507 " border-left-color: var(--fill-color);\n",508 " border-top-color: var(--fill-color);\n",509 " }\n",510 " 30% {\n",511 " border-color: transparent;\n",512 " border-left-color: var(--fill-color);\n",513 " border-top-color: var(--fill-color);\n",514 " border-right-color: var(--fill-color);\n",515 " }\n",516 " 40% {\n",517 " border-color: transparent;\n",518 " border-right-color: var(--fill-color);\n",519 " border-top-color: var(--fill-color);\n",520 " }\n",521 " 60% {\n",522 " border-color: transparent;\n",523 " border-right-color: var(--fill-color);\n",524 " }\n",525 " 80% {\n",526 " border-color: transparent;\n",527 " border-right-color: var(--fill-color);\n",528 " border-bottom-color: var(--fill-color);\n",529 " }\n",530 " 90% {\n",531 " border-color: transparent;\n",532 " border-bottom-color: var(--fill-color);\n",533 " }\n",534 " }\n",535 "</style>\n",536 "\n",537 " <script>\n",538 " async function quickchart(key) {\n",539 " const quickchartButtonEl =\n",540 " document.querySelector('#' + key + ' button');\n",541 " quickchartButtonEl.disabled = true; // To prevent multiple clicks.\n",542 " quickchartButtonEl.classList.add('colab-df-spinner');\n",543 " try {\n",544 " const charts = await google.colab.kernel.invokeFunction(\n",545 " 'suggestCharts', [key], {});\n",546 " } catch (error) {\n",547 " console.error('Error during call to suggestCharts:', error);\n",548 " }\n",549 " quickchartButtonEl.classList.remove('colab-df-spinner');\n",550 " quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",551 " }\n",552 " (() => {\n",553 " let quickchartButtonEl =\n",554 " document.querySelector('#df-f311969b-713e-4580-bfd5-d6d05bebca53 button');\n",555 " quickchartButtonEl.style.display =\n",556 " google.colab.kernel.accessAllowed ? 'block' : 'none';\n",557 " })();\n",558 " </script>\n",559 " </div>\n",560 "\n",561 " </div>\n",562 " </div>\n"563 ],564 "application/vnd.google.colaboratory.intrinsic+json": {565 "type": "dataframe",566 "variable_name": "df",567 "summary": "{\n \"name\": \"df\",\n \"rows\": 137,\n \"fields\": [\n {\n \"column\": \"commit_message\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 137,\n \"samples\": [\n \"help\",\n \"again\",\n \"Fix race condition in async task queue\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"quality_label\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"low\",\n \"high\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}"568 }569 },570 "metadata": {},571 "execution_count": 2572 }573 ]574 },575 {576 "cell_type": "markdown",577 "source": [578 "## **DATA PREPROCESSING AND VISUALIZATION**"579 ],580 "metadata": {581 "id": "KmLqSuHILOnC"582 }583 },584 {585 "cell_type": "code",586 "source": [587 "print(\"Label Distribution:\")\n",588 "df['quality_label'].value_counts()\n",589 "\n",590 "plt.figure(figsize=(6,4))\n",591 "sns.countplot(data=df, x='quality_label',hue='quality_label', palette='Set2')\n",592 "plt.title(\"Distribution of Commit Message Quality Labels\")\n",593 "plt.xlabel(\"Quality Label\")\n",594 "plt.ylabel(\"Count\")\n",595 "plt.show()"596 ],597 "metadata": {598 "colab": {599 "base_uri": "https://localhost:8080/",600 "height": 427601 },602 "id": "I1T9jb0dKVs-",603 "outputId": "afe0f2e9-401e-433c-8034-02445a9bc928"604 },605 "execution_count": 3,606 "outputs": [607 {608 "output_type": "stream",609 "name": "stdout",610 "text": [611 "Label Distribution:\n"612 ]613 },614 {615 "output_type": "display_data",616 "data": {617 "text/plain": [618 "<Figure size 600x400 with 1 Axes>"619 ],620 "image/png": "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RowYUeo2v//+O7p37w4PDw9ERERAqVTi8uXLOHr0KADAzc0NERERmD59OkaOHIl27doBAFq3bi31cefOHQQEBKBfv3547733YGNj88y65s6dC4VCgSlTpuDWrVtYsmQJ/Pz8kJycLI2glEd5anuaEALvvPMODh48iGHDhsHT0xN79uzBhx9+iOvXr5f4y/7IkSP47rvv8P7778PMzAzLli1DUFAQUlNTYWVlVWZdjx8/ho+PDy5fvoyxY8fCxcUFMTExCA4ORmZmJiZMmAA3Nzd89dVXCAsLg729PSZNmgQAsLa2LrXP3bt348mTJ8+dU1Hk999/R7t27WBubo7JkydDX18fa9asgY+PD+Lj4zX+CgWAcePGQa1WY9asWUhMTMTatWthYWGBY8eOwdHREZ9++il++uknfP7553jttdcwePBgjftv2bIFeXl5GDduHO7evYsFCxagT58+8PX1xaFDhzBlyhRcvnwZy5cvxwcffIAvv/yy1Lor+po+zdnZGd7e3vj6668REBAgPW9ZWVno168fli1bVuI+o0aNwoYNGxASEoLx48fjypUrWLFiBU6fPo2jR49CX18ft27dQpcuXWBtbY2PPvoIFhYWuHr1Kr777jupn3379qF///7o1KkTPvvsMwDA+fPncfToUUyYMAEA8Oeff2L79u3o3bs3XFxckJGRgTVr1qBDhw44d+4c7OzsAAAPHz6Er68vbt68iQkTJkCtViM6OhoHDx4sUf+BAwcQEBAALy8vzJgxAzo6OoiKioKvry9+/vln/Otf/yrz+dq1axcAlHgti6hUKvTo0QMbN27EH3/8gYYNGz73NXhaTEwMHj16hNGjR8PKygq//PILli9fjr/++gsxMTHl7qd9+/YYP348li1bho8//hhubm4A/nmvDBo0CJs2bcKePXs05sOkp6fjwIED5Tp8+DwnTpzAsWPH0K9fP9jb2+Pq1atYtWoVfHx8cO7cORgbG2tsP3bsWFhYWGDmzJlISUnBqlWrcO3aNWkCOgB89dVXGDJkCPz9/fHZZ5/h0aNHWLVqFdq2bYvTp0+XeSjned/XtZq208yr7HkjE0IIoVKpRPPmzaXbxZPu4sWLBQBx+/btMvs4ceJEmX8ddujQQQAQq1evLnVdaSMT9evXF9nZ2VL7t99+KwCIpUuXSm3lGZl4Xm3FRya2b98uAIg5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mZkIDg4GAKSnp8PAwAAWFhYa29nY2CA9Pb3MfubNmweVSiUtDg4O1Vg1ERER1ZgwsX79egQEBMDOzk5WP+Hh4cjKypKWtLS0KqqQiIiISqPVORNFrl27hv379+O7776T2tRqNfLy8pCZmakxOpGRkQG1Wl1mX0qlEkqlsjrLJSIioqfUiJGJqKgo1KtXD926dZPavLy8oK+vj7i4OKktJSUFqamp8Pb21kaZREREVAqtj0wUFhYiKioKQ4YMgZ7e/y9HpVJh2LBhmDhxIiwtLWFubo5x48bB29ubZ3IQERHVIFoPE/v370dqaiqGDh1aYt3ixYuho6ODoKAg5Obmwt/fHytXrtRClURERFQWrYeJLl26QAhR6jpDQ0NERkYiMjLyBVdFRERE5VUj5kwQERFR7cUwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLIwTBAREZEsDBNEREQkC8MEERERycIwQURERLJoPUxcv34d7733HqysrGBkZITXX38dJ0+elNYLITB9+nTY2trCyMgIfn5+uHTpkhYrJiIioqdpNUzcu3cPbdq0gb6+Pnbv3o1z585h4cKFqFOnjrTNggULsGzZMqxevRrHjx+HiYkJ/P39kZOTo8XKiYiIqIieNnf+2WefwcHBAVFRUVKbi4uL9G8hBJYsWYJPPvkEPXr0AABs2rQJNjY22L59O/r16/fCayYiIiJNWh2Z2LlzJ1q0aIHevXujXr16aN68OdatWyetv3LlCtLT0+Hn5ye1qVQqtGzZEgkJCaX2mZubi+zsbI2FiIiIqo9Ww8Sff/6JVatWwdXVFXv27MHo0aMxfvx4bNy4EQCQnp4OALCxsdG4n42NjbSuuHnz5kGlUkmLg4ND9T4IIiKiV5xWw0RhYSHefPNNfPrpp2jevDlGjhyJESNGYPXq1ZXuMzw8HFlZWdKSlpZWhRUTERFRcVoNE7a2tnB3d9doc3NzQ2pqKgBArVYDADIyMjS2ycjIkNYVp1QqYW5urrEQERFR9dFqmGjTpg1SUlI02i5evAgnJycA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\n"621 },622 "metadata": {}623 }624 ]625 },626 {627 "cell_type": "markdown",628 "source": [629 "## **RULE BASED APPROACH**"630 ],631 "metadata": {632 "id": "GkBGg9fPVx0w"633 }634 },635 {636 "cell_type": "code",637 "source": [638 "def rule_based_classifier(message):\n",639 " \"\"\"\n",640 " Simple, robust rule-based classifier from your original notebook.\n",641 " Handles ANY input โ even gibberish.\n",642 " \"\"\"\n",643 " # Handle None or non-string input\n",644 " if not message or not isinstance(message, str):\n",645 " return 'low'\n",646 "\n",647 " message_lower = message.lower().strip()\n",648 "\n",649 " # Rule 1: Too short (less than 3 words)\n",650 " if len(message_lower.split()) < 3:\n",651 " return 'low'\n",652 "\n",653 " # Rule 2: Contains vague keywords\n",654 " vague_keywords = ['fix', 'stuff', 'update', 'change', 'work', 'tweak', 'adjust', 'whatever', 'did', 'made']\n",655 " for kw in vague_keywords:\n",656 " if kw in message_lower:\n",657 " return 'low'\n",658 "\n",659 " # Rule 3: Too generic phrases\n",660 " if re.search(r'\\b(fix|update|change)\\s+(bug|code|stuff|things?)\\b', message_lower):\n",661 " return 'low'\n",662 "\n",663 " # Default: if none of the above, assume it's decent โ high\n",664 " return 'high'\n",665 " # Apply to dataset\n",666 "df['rule_based_pred'] = df['commit_message'].apply(rule_based_classifier)\n",667 "# Evaluate\n",668 "rule_accuracy = accuracy_score(df['quality_label'], df['rule_based_pred'])\n",669 "print(f\"FIXED Rule-Based Accuracy: {rule_accuracy:.2f}\")\n",670 "print(\"\\nClassification Report:\")\n",671 "print(classification_report(df['quality_label'], df['rule_based_pred'], zero_division=0))"672 ],673 "metadata": {674 "colab": {675 "base_uri": "https://localhost:8080/"676 },677 "id": "DAlAbVqTMB7X",678 "outputId": "7f755d54-6341-4677-ac3e-cb928ad62a8f"679 },680 "execution_count": 4,681 "outputs": [682 {683 "output_type": "stream",684 "name": "stdout",685 "text": [686 "FIXED Rule-Based Accuracy: 0.80\n",687 "\n",688 "Classification Report:\n",689 " precision recall f1-score support\n",690 "\n",691 " high 0.98 0.67 0.80 79\n",692 " low 0.69 0.98 0.81 58\n",693 "\n",694 " accuracy 0.80 137\n",695 " macro avg 0.83 0.83 0.80 137\n",696 "weighted avg 0.86 0.80 0.80 137\n",697 "\n"698 ]699 }700 ]701 },702 {703 "cell_type": "markdown",704 "source": [705 "## **MACHINE LEARNING APPROACH**"706 ],707 "metadata": {708 "id": "iq-eul--WI4F"709 }710 },711 {712 "cell_type": "code",713 "source": [714 "# Prepare data (same as before)\n",715 "df_ml = df[df['quality_label'] != 'neutral'].copy()\n",716 "X = df_ml['commit_message']\n",717 "y = df_ml['quality_label']\n",718 "\n",719 "X_train, X_test, y_train, y_test = train_test_split(\n",720 " X, y, test_size=0.3, random_state=42, stratify=y\n",721 ")\n",722 "\n",723 "# FIXED ML MODEL โ Better parameters\n",724 "ml_model = Pipeline([\n",725 " ('tfidf', TfidfVectorizer(\n",726 " stop_words='english',\n",727 " max_features=1000, # More features\n",728 " ngram_range=(1, 2), # Use word pairs\n",729 " lowercase=True\n",730 " )),\n",731 " ('classifier', MultinomialNB(alpha=0.1)) # Smoother probability\n",732 "])\n",733 "\n",734 "# Train\n",735 "ml_model.fit(X_train, y_train)\n",736 "\n",737 "# Predict on TEST SET (not full dataset!)\n",738 "y_pred_ml = ml_model.predict(X_test)\n",739 "\n",740 "# Evaluate on TEST SET\n",741 "ml_accuracy = accuracy_score(y_test, y_pred_ml)\n",742 "print(f\"FIXED ML Model Accuracy (Test Set): {ml_accuracy:.2f}\")\n",743 "print(\"\\nClassification Report (Test Set):\")\n",744 "print(classification_report(y_test, y_pred_ml))\n",745 "\n",746 "# Confusion Matrix\n",747 "cm = confusion_matrix(y_test, y_pred_ml)\n",748 "plt.figure(figsize=(5,4))\n",749 "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['high','low'], yticklabels=['high','low'])\n",750 "plt.title('Confusion Matrix (ML Model)')\n",751 "plt.ylabel('Actual')\n",752 "plt.xlabel('Predicted')\n",753 "plt.show()"754 ],755 "metadata": {756 "colab": {757 "base_uri": "https://localhost:8080/",758 "height": 618759 },760 "id": "YSgmKAy5Q1E2",761 "outputId": "b0aa7706-0b6e-4233-8732-0fd36855c5e7"762 },763 "execution_count": 5,764 "outputs": [765 {766 "output_type": "stream",767 "name": "stdout",768 "text": [769 "FIXED ML Model Accuracy (Test Set): 0.64\n",770 "\n",771 "Classification Report (Test Set):\n",772 " precision recall f1-score support\n",773 "\n",774 " high 0.65 0.83 0.73 24\n",775 " low 0.64 0.39 0.48 18\n",776 "\n",777 " accuracy 0.64 42\n",778 " macro avg 0.64 0.61 0.61 42\n",779 "weighted avg 0.64 0.64 0.62 42\n",780 "\n"781 ]782 },783 {784 "output_type": "display_data",785 "data": {786 "text/plain": [787 "<Figure size 500x400 with 2 Axes>"788 ],789 "image/png": "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\n"790 },791 "metadata": {}792 }793 ]794 },795 {796 "cell_type": "markdown",797 "source": [798 "## **COMPARATIVE EVALUATION OF APPROACHES**"799 ],800 "metadata": {801 "id": "kVDaCbA1XM-k"802 }803 },804 {805 "cell_type": "code",806 "source": [807 "# CORRECT COMPARISON โ Both models on TEST SET only\n",808 "X_test_list = X_test.tolist()\n",809 "\n",810 "# Rule-Based on Test Set\n",811 "rule_pred_test = [rule_based_classifier(msg) for msg in X_test_list]\n",812 "\n",813 "# ML on Test Set (already predicted)\n",814 "ml_pred_test = y_pred_ml\n",815 "\n",816 "# Calculate accuracy on same test set\n",817 "rule_acc_test = accuracy_score(y_test, rule_pred_test)\n",818 "ml_acc_test = accuracy_score(y_test, ml_pred_test)\n",819 "\n",820 "print(\"=== FIXED MODEL COMPARISON (Test Set Only) ===\")\n",821 "print(f\"Rule-Based Accuracy: {rule_acc_test:.2f}\")\n",822 "print(f\"ML Model Accuracy: {ml_acc_test:.2f}\")\n",823 "\n",824 "# Table\n",825 "pd.DataFrame({\n",826 " 'Model': ['Rule-Based', 'ML Model'],\n",827 " 'Accuracy': [rule_acc_test, ml_acc_test]\n",828 "})"829 ],830 "metadata": {831 "colab": {832 "base_uri": "https://localhost:8080/",833 "height": 164834 },835 "id": "tg8J1cYtQ67Q",836 "outputId": "e2a6a38e-efc6-4dd2-9f0f-3071e3701762"837 },838 "execution_count": 6,839 "outputs": [840 {841 "output_type": "stream",842 "name": "stdout",843 "text": [844 "=== FIXED MODEL COMPARISON (Test Set Only) ===\n",845 "Rule-Based Accuracy: 0.83\n",846 "ML Model Accuracy: 0.64\n"847 ]848 },849 {850 "output_type": "execute_result",851 "data": {852 "text/plain": [853 " Model Accuracy\n",854 "0 Rule-Based 0.833333\n",855 "1 ML Model 0.642857"856 ],857 "text/html": [858 "\n",859 " <div id=\"df-b6e79223-e76e-4a23-a0f2-8577e5e273f2\" class=\"colab-df-container\">\n",860 " <div>\n",861 "<style scoped>\n",862 " .dataframe tbody tr th:only-of-type {\n",863 " vertical-align: middle;\n",864 " }\n",865 "\n",866 " .dataframe tbody tr th {\n",867 " vertical-align: top;\n",868 " }\n",869 "\n",870 " .dataframe thead th {\n",871 " text-align: right;\n",872 " }\n",873 "</style>\n",874 "<table border=\"1\" class=\"dataframe\">\n",875 " <thead>\n",876 " <tr style=\"text-align: right;\">\n",877 " <th></th>\n",878 " <th>Model</th>\n",879 " <th>Accuracy</th>\n",880 " </tr>\n",881 " </thead>\n",882 " <tbody>\n",883 " <tr>\n",884 " <th>0</th>\n",885 " <td>Rule-Based</td>\n",886 " <td>0.833333</td>\n",887 " </tr>\n",888 " <tr>\n",889 " <th>1</th>\n",890 " <td>ML Model</td>\n",891 " <td>0.642857</td>\n",892 " </tr>\n",893 " </tbody>\n",894 "</table>\n",895 "</div>\n",896 " <div class=\"colab-df-buttons\">\n",897 "\n",898 " <div class=\"colab-df-container\">\n",899 " <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-b6e79223-e76e-4a23-a0f2-8577e5e273f2')\"\n",900 " title=\"Convert this dataframe to an interactive table.\"\n",901 " style=\"display:none;\">\n",902 "\n",903 " <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",904 " <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",905 " </svg>\n",906 " </button>\n",907 "\n",908 " <style>\n",909 " .colab-df-container {\n",910 " display:flex;\n",911 " gap: 12px;\n",912 " }\n",913 "\n",914 " .colab-df-convert {\n",915 " background-color: #E8F0FE;\n",916 " border: none;\n",917 " border-radius: 50%;\n",918 " cursor: pointer;\n",919 " display: none;\n",920 " fill: #1967D2;\n",921 " height: 32px;\n",922 " padding: 0 0 0 0;\n",923 " width: 32px;\n",924 " }\n",925 "\n",926 " .colab-df-convert:hover {\n",927 " background-color: #E2EBFA;\n",928 " box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",929 " fill: #174EA6;\n",930 " }\n",931 "\n",932 " .colab-df-buttons div {\n",933 " margin-bottom: 4px;\n",934 " }\n",935 "\n",936 " [theme=dark] .colab-df-convert {\n",937 " background-color: #3B4455;\n",938 " fill: #D2E3FC;\n",939 " }\n",940 "\n",941 " [theme=dark] .colab-df-convert:hover {\n",942 " background-color: #434B5C;\n",943 " box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",944 " filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",945 " fill: #FFFFFF;\n",946 " }\n",947 " </style>\n",948 "\n",949 " <script>\n",950 " const buttonEl =\n",951 " document.querySelector('#df-b6e79223-e76e-4a23-a0f2-8577e5e273f2 button.colab-df-convert');\n",952 " buttonEl.style.display =\n",953 " google.colab.kernel.accessAllowed ? 'block' : 'none';\n",954 "\n",955 " async function convertToInteractive(key) {\n",956 " const element = document.querySelector('#df-b6e79223-e76e-4a23-a0f2-8577e5e273f2');\n",957 " const dataTable =\n",958 " await google.colab.kernel.invokeFunction('convertToInteractive',\n",959 " [key], {});\n",960 " if (!dataTable) return;\n",961 "\n",962 " const docLinkHtml = 'Like what you see? Visit the ' +\n",963 " '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",964 " + ' to learn more about interactive tables.';\n",965 " element.innerHTML = '';\n",966 " dataTable['output_type'] = 'display_data';\n",967 " await google.colab.output.renderOutput(dataTable, element);\n",968 " const docLink = document.createElement('div');\n",969 " docLink.innerHTML = docLinkHtml;\n",970 " element.appendChild(docLink);\n",971 " }\n",972 " </script>\n",973 " </div>\n",974 "\n",975 "\n",976 " <div id=\"df-e39e47e5-b9e3-4636-b16a-43b46922c1e6\">\n",977 " <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-e39e47e5-b9e3-4636-b16a-43b46922c1e6')\"\n",978 " title=\"Suggest charts\"\n",979 " style=\"display:none;\">\n",980 "\n",981 "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",982 " width=\"24px\">\n",983 " <g>\n",984 " <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",985 " </g>\n",986 "</svg>\n",987 " </button>\n",988 "\n",989 "<style>\n",990 " .colab-df-quickchart {\n",991 " --bg-color: #E8F0FE;\n",992 " --fill-color: #1967D2;\n",993 " --hover-bg-color: #E2EBFA;\n",994 " --hover-fill-color: #174EA6;\n",995 " --disabled-fill-color: #AAA;\n",996 " --disabled-bg-color: #DDD;\n",997 " }\n",998 "\n",999 " [theme=dark] .colab-df-quickchart {\n",1000 " --bg-color: #3B4455;\n",1001 " --fill-color: #D2E3FC;\n",1002 " --hover-bg-color: #434B5C;\n",1003 " --hover-fill-color: #FFFFFF;\n",1004 " --disabled-bg-color: #3B4455;\n",1005 " --disabled-fill-color: #666;\n",1006 " }\n",1007 "\n",1008 " .colab-df-quickchart {\n",1009 " background-color: var(--bg-color);\n",1010 " border: none;\n",1011 " border-radius: 50%;\n",1012 " cursor: pointer;\n",1013 " display: none;\n",1014 " fill: var(--fill-color);\n",1015 " height: 32px;\n",1016 " padding: 0;\n",1017 " width: 32px;\n",1018 " }\n",1019 "\n",1020 " .colab-df-quickchart:hover {\n",1021 " background-color: var(--hover-bg-color);\n",1022 " box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",1023 " fill: var(--button-hover-fill-color);\n",1024 " }\n",1025 "\n",1026 " .colab-df-quickchart-complete:disabled,\n",1027 " .colab-df-quickchart-complete:disabled:hover {\n",1028 " background-color: var(--disabled-bg-color);\n",1029 " fill: var(--disabled-fill-color);\n",1030 " box-shadow: none;\n",1031 " }\n",1032 "\n",1033 " .colab-df-spinner {\n",1034 " border: 2px solid var(--fill-color);\n",1035 " border-color: transparent;\n",1036 " border-bottom-color: var(--fill-color);\n",1037 " animation:\n",1038 " spin 1s steps(1) infinite;\n",1039 " }\n",1040 "\n",1041 " @keyframes spin {\n",1042 " 0% {\n",1043 " border-color: transparent;\n",1044 " border-bottom-color: var(--fill-color);\n",1045 " border-left-color: var(--fill-color);\n",1046 " }\n",1047 " 20% {\n",1048 " border-color: transparent;\n",1049 " border-left-color: var(--fill-color);\n",1050 " border-top-color: var(--fill-color);\n",1051 " }\n",1052 " 30% {\n",1053 " border-color: transparent;\n",1054 " border-left-color: var(--fill-color);\n",1055 " border-top-color: var(--fill-color);\n",1056 " border-right-color: var(--fill-color);\n",1057 " }\n",1058 " 40% {\n",1059 " border-color: transparent;\n",1060 " border-right-color: var(--fill-color);\n",1061 " border-top-color: var(--fill-color);\n",1062 " }\n",1063 " 60% {\n",1064 " border-color: transparent;\n",1065 " border-right-color: var(--fill-color);\n",1066 " }\n",1067 " 80% {\n",1068 " border-color: transparent;\n",1069 " border-right-color: var(--fill-color);\n",1070 " border-bottom-color: var(--fill-color);\n",1071 " }\n",1072 " 90% {\n",1073 " border-color: transparent;\n",1074 " border-bottom-color: var(--fill-color);\n",1075 " }\n",1076 " }\n",1077 "</style>\n",1078 "\n",1079 " <script>\n",1080 " async function quickchart(key) {\n",1081 " const quickchartButtonEl =\n",1082 " document.querySelector('#' + key + ' button');\n",1083 " quickchartButtonEl.disabled = true; // To prevent multiple clicks.\n",1084 " quickchartButtonEl.classList.add('colab-df-spinner');\n",1085 " try {\n",1086 " const charts = await google.colab.kernel.invokeFunction(\n",1087 " 'suggestCharts', [key], {});\n",1088 " } catch (error) {\n",1089 " console.error('Error during call to suggestCharts:', error);\n",1090 " }\n",1091 " quickchartButtonEl.classList.remove('colab-df-spinner');\n",1092 " quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",1093 " }\n",1094 " (() => {\n",1095 " let quickchartButtonEl =\n",1096 " document.querySelector('#df-e39e47e5-b9e3-4636-b16a-43b46922c1e6 button');\n",1097 " quickchartButtonEl.style.display =\n",1098 " google.colab.kernel.accessAllowed ? 'block' : 'none';\n",1099 " })();\n",1100 " </script>\n",1101 " </div>\n",1102 "\n",1103 " </div>\n",1104 " </div>\n"1105 ],1106 "application/vnd.google.colaboratory.intrinsic+json": {1107 "type": "dataframe",1108 "summary": "{\n \"name\": \"})\",\n \"rows\": 2,\n \"fields\": [\n {\n \"column\": \"Model\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"ML Model\",\n \"Rule-Based\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Accuracy\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.13468700594029476,\n \"min\": 0.6428571428571429,\n \"max\": 0.8333333333333334,\n \"num_unique_values\": 2,\n \"samples\": [\n 0.6428571428571429,\n 0.8333333333333334\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}"1109 }1110 },1111 "metadata": {},1112 "execution_count": 61113 }1114 ]1115 },1116 {1117 "cell_type": "code",1118 "source": [1119 "import gradio as gr\n",1120 "# Define some common software-related keywords\n",1121 "tech_keywords = [\n",1122 " \"fix\", \"bug\", \"error\", \"issue\", \"feature\", \"update\", \"refactor\",\n",1123 " \"login\", \"signup\", \"user\", \"api\", \"database\", \"module\", \"function\",\n",1124 " \"class\", \"variable\", \"code\", \"ui\", \"backend\", \"frontend\", \"auth\",\n",1125 " \"encryption\", \"validation\", \"session\", \"deploy\"\n",1126 "]\n",1127 "\n",1128 "def is_meaningless(msg):\n",1129 " words = msg.lower().split()\n",1130 "\n",1131 " # Too short\n",1132 " if len(words) < 3:\n",1133 " return True\n",1134 "\n",1135 " # If no technical keywords present\n",1136 " if not any(kw in msg.lower() for kw in tech_keywords):\n",1137 " return True\n",1138 "\n",1139 " return False\n",1140 "\n",1141 "def predict_commit_quality(commit_message):\n",1142 " msg = commit_message.strip()\n",1143 "\n",1144 " # ๐จ If meaningless/unrelated โ directly LOW\n",1145 " if is_meaningless(msg):\n",1146 " return \"LOW\", \"LOW\", \"\"\"\n",1147 " <div style='\n",1148 " text-align: center;\n",1149 " padding: 15px;\n",1150 " background-color: #e74c3c;\n",1151 " color: white;\n",1152 " border-radius: 10px;\n",1153 " font-weight: bold;\n",1154 " font-size: 18px;\n",1155 " margin-top: 10px;\n",1156 " '>LOW QUALITY โ Not a Valid/Meaningful Commit Message</div>\n",1157 " \"\"\"\n",1158 "\n",1159 " # Rule-based prediction\n",1160 " rule_pred = rule_based_classifier(msg)\n",1161 "\n",1162 " # ML prediction (confidence not shown in UI)\n",1163 " ml_pred = ml_model.predict([msg])[0]\n",1164 "\n",1165 " # Final verdict: rule-based dominates (since in your project rules were more accurate)\n",1166 " if rule_pred == 'low' or ml_pred == 'low':\n",1167 " verdict_html = \"\"\"\n",1168 " <div style='\n",1169 " text-align: center;\n",1170 " padding: 15px;\n",1171 " background-color: #e74c3c;\n",1172 " color: white;\n",1173 " border-radius: 10px;\n",1174 " font-weight: bold;\n",1175 " font-size: 18px;\n",1176 " margin-top: 10px;\n",1177 " '>LOW QUALITY โ Needs Improvement</div>\n",1178 " \"\"\"\n",1179 " else:\n",1180 " verdict_html = \"\"\"\n",1181 " <div style='\n",1182 " text-align: center;\n",1183 " padding: 15px;\n",1184 " background-color: #27ae60;\n",1185 " color: white;\n",1186 " border-radius: 10px;\n",1187 " font-weight: bold;\n",1188 " font-size: 18px;\n",1189 " margin-top: 10px;\n",1190 " '>GOOD QUALITY COMMIT</div>\n",1191 " \"\"\"\n",1192 "\n",1193 " return rule_pred.upper(), ml_pred.upper(), verdict_html\n",1194 "\n",1195 "\n",1196 "\n",1197 "# --- Gradio UI ---\n",1198 "with gr.Blocks(theme=\"soft\", css=\"\"\"\n",1199 " footer { display: none !important; }\n",1200 " .app-footer {\n",