kuruvabhageeerathashankar14 commited on
Commit
40954ee
Β·
verified Β·
1 Parent(s): e1184a6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -71
app.py CHANGED
@@ -3,93 +3,136 @@ import pickle
3
  import re
4
  import numpy as np
5
 
6
- # βœ… Load model and vectorizer
7
- with open("models/vectorizer.pkl", "rb") as f:
8
- vectorizer = pickle.load(f)
9
 
10
- with open("models/tag_predictor.pkl", "rb") as f:
11
- model = pickle.load(f)
12
-
13
- # βœ… Streamlit page configuration
14
- st.set_page_config(page_title="Stack Overflow Tags Predictor", layout="centered")
15
-
16
- # βœ… Custom CSS for better UI
17
  st.markdown("""
18
  <style>
19
- .main {
20
- background-color: #f0f2f6;
 
 
 
 
 
21
  padding: 2rem;
22
- border-radius: 10px;
 
 
 
 
 
 
 
 
 
 
23
  }
24
- .title {
25
- color: #1f2937;
26
- font-size: 2rem;
27
  text-align: center;
 
 
 
 
 
 
 
 
 
28
  }
29
- .tag-title {
30
- color: #111827;
 
 
 
 
31
  font-weight: 600;
 
 
32
  }
33
- .predicted-tag {
34
- background-color: #d1fae5;
35
- color: #065f46;
36
- padding: 0.25rem 0.75rem;
37
- border-radius: 1rem;
38
- margin: 0.25rem;
39
  display: inline-block;
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
  </style>
42
  """, unsafe_allow_html=True)
43
 
44
- st.markdown('<div class="main">', unsafe_allow_html=True)
45
- st.markdown('<h1 class="title">Stack Overflow Tags Predictor</h1>', unsafe_allow_html=True)
46
-
47
- # βœ… Input text
48
- user_input = st.text_area("Enter your Stack Overflow question:", height=180)
49
-
50
- # βœ… Preprocess function
51
  def clean_text(text):
52
- text = text.lower()
53
- text = re.sub(r"<[^>]+>", "", text)
54
- text = re.sub(r"[^\w\s]", "", text)
55
  return text
56
 
57
- # βœ… Threshold buttons (flow style)
58
- st.subheader("Select Tag Threshold Value:")
59
- threshold = 0.50 # default
60
-
61
- cols = st.columns(9)
62
- thresholds = [0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90]
63
-
64
- for i, val in enumerate(thresholds):
65
- if cols[i].button(f"{val:.2f}"):
66
- threshold = val
67
- st.session_state["selected_threshold"] = val
68
-
69
- # Use selected threshold from session state (persistent)
70
- threshold = st.session_state.get("selected_threshold", 0.50)
71
- st.success(f"Selected Threshold: {threshold:.2f}")
72
-
73
- # βœ… Predict Tags
74
- def predict_tags(text, threshold):
75
- cleaned = clean_text(text)
76
- X = vectorizer.transform([cleaned])
77
- probs = model.predict_proba(X)[0]
78
- tags = np.array(model.classes_)
79
- selected_tags = tags[probs >= threshold]
80
- return selected_tags
81
-
82
- # βœ… Prediction output
83
- if st.button("Predict Tags"):
84
- if user_input.strip() == "":
85
- st.warning("Please enter a question to predict tags.")
86
- else:
87
- tags = predict_tags(user_input, threshold)
88
- if len(tags) > 0:
89
- st.markdown('<h3 class="tag-title">Predicted Tags:</h3>', unsafe_allow_html=True)
90
- for tag in tags:
91
- st.markdown(f'<span class="predicted-tag">{tag}</span>', unsafe_allow_html=True)
92
  else:
93
- st.info("No tags matched the selected threshold.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- st.markdown('</div>', unsafe_allow_html=True)
 
3
  import re
4
  import numpy as np
5
 
6
+ # βœ… Page Config
7
+ st.set_page_config(page_title="Stack Overflow Tags Predictor", layout="wide")
 
8
 
9
+ # βœ… Enhanced CSS for a modern UI
 
 
 
 
 
 
10
  st.markdown("""
11
  <style>
12
+ body {
13
+ background: linear-gradient(to right, #e3f2fd, #ffffff);
14
+ }
15
+
16
+ .main-container {
17
+ max-width: 850px;
18
+ margin: auto;
19
  padding: 2rem;
20
+ border-radius: 16px;
21
+ background: rgba(255, 255, 255, 0.9);
22
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
23
+ }
24
+
25
+ .title-text {
26
+ font-size: 2.4rem;
27
+ font-weight: bold;
28
+ text-align: center;
29
+ color: #1e3a8a;
30
+ margin-bottom: 0.5rem;
31
  }
32
+
33
+ .description-text {
34
+ font-size: 1.1rem;
35
  text-align: center;
36
+ color: #333;
37
+ margin-bottom: 2rem;
38
+ }
39
+
40
+ .stTextInput input, .stTextArea textarea {
41
+ border-radius: 8px;
42
+ padding: 12px;
43
+ border: 1px solid #ccc;
44
+ background-color: #fafafa;
45
  }
46
+
47
+ .stButton button {
48
+ background: linear-gradient(to right, #1e88e5, #1976d2);
49
+ color: white;
50
+ border-radius: 8px;
51
+ padding: 0.6rem 1.4rem;
52
  font-weight: 600;
53
+ transition: 0.3s ease;
54
+ border: none;
55
  }
56
+
57
+ .stButton button:hover {
58
+ background: linear-gradient(to right, #1565c0, #0d47a1);
59
+ }
60
+
61
+ .tag {
62
  display: inline-block;
63
+ margin: 5px 6px 0 0;
64
+ background-color: #0ea5e9;
65
+ padding: 6px 14px;
66
+ border-radius: 20px;
67
+ font-size: 0.85rem;
68
+ color: white;
69
+ font-weight: 500;
70
+ }
71
+
72
+ .result-container {
73
+ text-align: center;
74
+ margin-top: 2rem;
75
  }
76
  </style>
77
  """, unsafe_allow_html=True)
78
 
79
+ # βœ… Text Preprocessing
 
 
 
 
 
 
80
  def clean_text(text):
81
+ text = re.sub(r"<.*?>", " ", text)
82
+ text = re.sub(r"\W", " ", text)
83
+ text = re.sub(r"\s+", " ", text.lower()).strip()
84
  return text
85
 
86
+ # βœ… Load Pickled Artifacts
87
+ @st.cache_resource
88
+ def load_artifacts():
89
+ with open("model12.pkl", "rb") as f:
90
+ model = pickle.load(f)
91
+ with open("tfidf12.pkl", "rb") as f:
92
+ vectorizer = pickle.load(f)
93
+ with open("mlb12.pkl", "rb") as f:
94
+ mlb = pickle.load(f)
95
+ return model, vectorizer, mlb
96
+
97
+ model, vectorizer, mlb = load_artifacts()
98
+
99
+ # βœ… UI Container
100
+ with st.container():
101
+ st.markdown("<div class='main-container'>", unsafe_allow_html=True)
102
+
103
+ st.markdown("<div class='title-text'>πŸ”– Stack Overflow Tags Predictor</div>", unsafe_allow_html=True)
104
+ st.markdown("<div class='description-text'>Enter your question title and description to generate the most relevant tags using Machine Learning.</div>", unsafe_allow_html=True)
105
+
106
+ with st.form(key="tag_prediction_form"):
107
+ title = st.text_input("πŸ“ Enter Question Title")
108
+ body = st.text_area("πŸ“„ Enter Question Description", height=180)
109
+ threshold = st.slider("πŸ”§ Tag Confidence Threshold", min_value=0.1, max_value=0.9, value=0.3, step=0.05)
110
+ submitted = st.form_submit_button("πŸ” Predict Tags")
111
+
112
+ if submitted:
113
+ if not title.strip() or not body.strip():
114
+ st.warning("⚠️ Please fill in both the title and description.")
 
 
 
 
 
 
115
  else:
116
+ with st.spinner("πŸ” Predicting the most relevant tags..."):
117
+ input_text = clean_text(title + " " + body)
118
+ X_input = vectorizer.transform([input_text])
119
+
120
+ try:
121
+ y_prob = model.predict_proba(X_input)
122
+ y_pred = (y_prob >= threshold).astype(int)
123
+ except AttributeError:
124
+ y_pred = model.predict(X_input)
125
+
126
+ predicted_tags = mlb.inverse_transform(y_pred)
127
+
128
+ with st.container():
129
+ st.markdown("<div class='result-container'>", unsafe_allow_html=True)
130
+ if predicted_tags and predicted_tags[0]:
131
+ st.success("βœ… Tags Predicted Successfully!")
132
+ tag_html = "".join([f"<span class='tag'>{tag}</span>" for tag in predicted_tags[0]])
133
+ st.markdown(tag_html, unsafe_allow_html=True)
134
+ else:
135
+ st.info("πŸ€” No tags predicted. Try refining your input or lowering the threshold.")
136
+ st.markdown("</div>", unsafe_allow_html=True)
137
 
138
+ st.markdown("</div>", unsafe_allow_html=True)