File size: 9,875 Bytes
79c84e2
 
 
 
 
 
 
 
 
 
 
 
1a45883
79c84e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4b9b02
79c84e2
 
 
 
e4b9b02
79c84e2
 
 
 
 
 
 
 
 
 
 
 
 
 
e4b9b02
 
 
 
 
 
 
 
 
79c84e2
e4b9b02
 
79c84e2
 
e4b9b02
 
 
 
 
 
79c84e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4b9b02
 
3bab898
e4b9b02
 
79c84e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4b9b02
 
 
 
 
79c84e2
 
 
e4b9b02
 
 
79c84e2
 
 
 
e4b9b02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
"""Gradio Frontend Application.

This module provides a web-based user interface for the code comment classification API.
Users can input code comments and get real-time predictions through an interactive interface.
"""

import os

import gradio as gr
import requests

# API configuration for deploy
API_URL = os.getenv("API_URL", "https://se4ai2526-uniba-nygaard-nygaardcodecomment-backend.hf.space/")


def get_categories_for_language(language: str) -> str:
    """Get supported categories for a specific programming language.

    Args:
        language: The programming language

    Returns:
        Formatted string with supported categories
    """
    categories = {
        "Java": [
            "summary: A brief description of the behavior of the code",
            "Ownership: Describes the authors and ownership",
            "Expand: Aims to describe the associated code",
            "usage: Describes how to use the code",
            "Pointer: Points to related code or resources",
            "deprecation: Indicates deprecated code",
            "rational: Explains the reasoning behind the implementation",
        ],
        "Python": [
            "Usage: Describes usage of the code",
            "Parameters: Documents function/method parameters",
            "DevelopmentNotes: Contains notes for developers",
            "Expand: Provides detailed explanations",
            "Summary: Summarizes the functionality",
        ],
        "Pharo": [
            "Keyimplementationpoints: Highlights key implementation details",
            "Example: Provides code examples",
            "Responsibilities: Describes object responsibilities",
            "Intent: Explains the intent or purpose",
            "Keymessages: Documents key messages or methods",
            "Collaborators: Lists collaborating objects/classes",
        ],
    }

    lang_categories = categories.get(language, [])
    if lang_categories:
        return f"**Supported Categories for {language}:**\n" + "\n".join(
            f"- {cat}" for cat in lang_categories
        )
    return "**Supported Categories:** Not available"


def predict_gradio(text: str, class_name: str, language: str) -> str:
    """Gradio interface function for single text prediction.

    Args:
        text: The code comment to classify
        class_name: The name of the class containing the comment
        language: The programming language

    Returns:
        Formatted HTML string with prediction results
    """
    if not text.strip():
        return """
        <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    border-radius: 10px; padding: 20px; margin: 10px 0;
                    color: white; text-align: center; font-weight: bold;">
            ⚠️ Please enter a code comment to classify.
        </div>
        """

    if not class_name.strip():
        return """
        <div style="background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%);
                border-radius: 10px; padding: 20px; margin: 10px 0;
                color: white; text-align: center; font-weight: bold;">
            ⚠️ Please enter the class name containing the comment.
        </div>
        """

    try:
        # Call the API with separate texts and class_names
        # Backend will combine them as "comment | class_name" before passing to the model
        response = requests.post(
            f"{API_URL}/predict",
            json={
                "texts": [text],
                "class_names": [class_name],
                "language": language.lower(),
                "model_type": "catboost",
            },
            timeout=30,
        )

        if response.status_code == 200:
            data = response.json()
            results = data.get("data", {}).get("results", [])

            if results and len(results) > 0:
                labels = results[0].get("labels", [])
                if labels:
                    labels_html = "".join(
                        [
                            f'<span style="background: #4CAF50; color: white; padding: 4px 8px; '
                            f'margin: 2px; border-radius: 12px; font-size: 14px; display: inline-block;">'
                            f"🏷️ {label}</span>"
                            for label in labels
                        ]
                    )
                    return f"""
                    <div style="background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
                                border-radius: 15px; padding: 20px; margin: 10px 0;
                                box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
                        <h3 style="color: white; margin: 0 0 15px 0; text-align: center;">
                            βœ… Prediction Successful
                        </h3>
                        <div style="text-align: center;">
                            {labels_html}
                        </div>
                    </div>
                    """
                return """
                <div style="background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
                            border-radius: 10px; padding: 20px; margin: 10px 0;
                            color: white; text-align: center; font-weight: bold;">
                    πŸ“Š No labels predicted (below threshold)
                </div>
                """
            return """
            <div style="background: linear-gradient(135deg, #9c27b0 0%, #7b1fa2 100%);
                        border-radius: 10px; padding: 20px; margin: 10px 0;
                        color: white; text-align: center; font-weight: bold;">
                πŸ” No prediction results available
            </div>
            """
        else:
            return f"""
            <div style="background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);
                        border-radius: 10px; padding: 20px; margin: 10px 0;
                        color: white; text-align: center; font-weight: bold;">
                ❌ API Error: {response.status_code}<br>
                <small style="font-weight: normal;">{response.text}</small>
            </div>
            """

    except requests.exceptions.ConnectionError:
        return f"""
        <div style="background: linear-gradient(135deg, #607d8b 0%, #455a64 100%);
                    border-radius: 10px; padding: 20px; margin: 10px 0;
                    color: white; text-align: center; font-weight: bold;">
            🌐 Connection Error<br>
            <small style="font-weight: normal;">Cannot connect to API at {API_URL}</small>
        </div>
        """
    except requests.exceptions.Timeout:
        return """
        <div style="background: linear-gradient(135deg, #ff5722 0%, #d84315 100%);
                    border-radius: 10px; padding: 20px; margin: 10px 0;
                    color: white; text-align: center; font-weight: bold;">
            ⏱️ Timeout Error<br>
            <small style="font-weight: normal;">The request took too long</small>
        </div>
        """
    except Exception as e:
        return f"""
        <div style="background: linear-gradient(135deg, #9e9e9e 0%, #757575 100%);
                    border-radius: 10px; padding: 20px; margin: 10px 0;
                    color: white; text-align: center; font-weight: bold;">
            ⚠️ Unexpected Error<br>
            <small style="font-weight: normal;">{str(e)}</small>
        </div>
        """


def update_categories(language: str) -> str:
    """Update the categories display when language changes.

    Args:
        language: The selected programming language

    Returns:
        Updated description text with categories
    """
    return get_categories_for_language(language)


# Create Gradio interface with dynamic categories
with gr.Blocks(title="πŸ” Nygaard Code Comment Classifier") as gradio_app:
    gr.Markdown("# πŸ” Nygaard Code Comment Classifier")
    gr.Markdown("Classify code comments into multiple categories using machine learning.")

    # Language selector
    language_dropdown = gr.Dropdown(
        choices=["Java", "Python", "Pharo"], label="Programming Language", value="Python"
    )

    # Dynamic categories display
    categories_display = gr.Markdown(value=get_categories_for_language("Python"))

    # Connect language change to categories update
    language_dropdown.change(
        fn=update_categories, inputs=language_dropdown, outputs=categories_display
    )

    # Input components
    with gr.Row():
        text_input = gr.Textbox(
            label="Code Comment", placeholder="Enter your code comment here...", lines=5
        )

    with gr.Row():
        class_name_input = gr.Textbox(
            label="Class Name", placeholder="Enter the class name...", lines=1
        )

    # Output
    output_display = gr.HTML(label="Prediction Result")

    # Buttons
    with gr.Row():
        clear_btn = gr.Button("Clear", variant="secondary")
        submit_btn = gr.Button("Submit", variant="primary")

    gr.Examples(
        examples=[
            ["@deprecated Use newMethod() instead", "Java"],
            ["This method calculates the factorial of a number", "Python"],
            ["Returns the sum of all elements in the collection", "Pharo"],
        ],
        inputs=[text_input, language_dropdown],
    )

    # Connect clear button to reset inputs
    clear_btn.click(
        fn=lambda: ("", "", "Python"),
        inputs=[],
        outputs=[text_input, class_name_input, language_dropdown],
    )

    # Connect submit button to prediction function
    submit_btn.click(
        fn=predict_gradio,
        inputs=[text_input, class_name_input, language_dropdown],
        outputs=output_display,
    )


if __name__ == "__main__":
    gradio_app.launch(server_name="0.0.0.0", server_port=9001)