BaskaranAIExpert commited on
Commit
b7a0cbb
ยท
verified ยท
1 Parent(s): e1c9b92

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. Dockerfile +18 -12
  2. app.py +215 -0
  3. requirements.txt +7 -3
Dockerfile CHANGED
@@ -1,20 +1,26 @@
1
- FROM python:3.13.5-slim
 
2
 
 
3
  WORKDIR /app
4
 
5
- RUN apt-get update && apt-get install -y \
6
- build-essential \
7
- curl \
8
- git \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- COPY requirements.txt ./
12
- COPY src/ ./src/
13
 
 
14
  RUN pip3 install -r requirements.txt
15
 
16
- EXPOSE 8501
 
 
 
 
 
 
 
 
 
17
 
18
- HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
 
19
 
20
- ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
1
+ # Use a minimal base image with Python 3.9 installed
2
+ FROM python:3.9
3
 
4
+ # Set the working directory inside the container to /app
5
  WORKDIR /app
6
 
7
+ # Copy all files from the current directory on the host to the container's /app directory
8
+ COPY . .
 
 
 
 
 
 
9
 
10
+ # Install Python dependencies listed in requirements.txt
11
  RUN pip3 install -r requirements.txt
12
 
13
+ # Create a non-root user for security
14
+ RUN useradd -m -u 1000 user
15
+ USER user
16
+ ENV HOME=/home/user \
17
+ PATH=/home/user/.local/bin:$PATH
18
+
19
+ WORKDIR $HOME/app
20
+
21
+ # Copy files with proper ownership
22
+ COPY --chown=user . $HOME/app
23
 
24
+ # Define the command to run the Streamlit app on port "8501" and make it accessible externally
25
+ CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0", "--server.enableXsrfProtection=false"]
26
 
 
app.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Streamlit App for Wellness Tourism Package Prediction
3
+ This application allows users to input customer data and predict
4
+ whether they will purchase the Wellness Tourism Package.
5
+ """
6
+
7
+ import streamlit as st
8
+ import pandas as pd
9
+ from huggingface_hub import hf_hub_download
10
+ import joblib
11
+
12
+ # TODO: Replace with your Hugging Face username
13
+ HF_USERNAME = "BaskaranAIExpert" # Change this!
14
+
15
+ # Page configuration
16
+ st.set_page_config(
17
+ page_title="Wellness Tourism Package Prediction",
18
+ page_icon="โœˆ๏ธ",
19
+ layout="wide"
20
+ )
21
+
22
+ # Download and load the model
23
+ @st.cache_resource
24
+ def load_model():
25
+ """Load the trained model from Hugging Face Hub"""
26
+ try:
27
+ model_path = hf_hub_download(
28
+ repo_id=f"{HF_USERNAME}/wellness-tourism-model",
29
+ filename="wellness_tourism_model_v1.joblib"
30
+ )
31
+ model = joblib.load(model_path)
32
+ return model
33
+ except Exception as e:
34
+ st.error(f"Error loading model: {str(e)}")
35
+ st.info("Please ensure the model is uploaded to Hugging Face Hub and the username is correct.")
36
+ return None
37
+
38
+ # Load model
39
+ model = load_model()
40
+
41
+ # Streamlit UI
42
+ st.title("โœˆ๏ธ Wellness Tourism Package Prediction App")
43
+ st.markdown("""
44
+ This application predicts whether a customer will purchase the **Wellness Tourism Package**
45
+ based on their profile and interaction data. Enter the customer information below to get a prediction.
46
+ """)
47
+
48
+ if model is None:
49
+ st.stop()
50
+
51
+ # Create two columns for better layout
52
+ col1, col2 = st.columns(2)
53
+
54
+ with col1:
55
+ st.subheader("๐Ÿ“‹ Customer Details")
56
+
57
+ age = st.number_input("Age", min_value=18, max_value=100, value=35, step=1)
58
+ gender = st.selectbox("Gender", ["Male", "Female"])
59
+ marital_status = st.selectbox("Marital Status", ["Single", "Married", "Divorced"])
60
+ occupation = st.selectbox("Occupation", [
61
+ "Salaried", "Freelancer", "Small Business", "Large Business", "Other"
62
+ ])
63
+ designation = st.selectbox("Designation", [
64
+ "Executive", "Manager", "Senior Manager", "AVP", "VP", "Other"
65
+ ])
66
+ monthly_income = st.number_input(
67
+ "Monthly Income (โ‚น)",
68
+ min_value=0,
69
+ max_value=1000000,
70
+ value=50000,
71
+ step=1000
72
+ )
73
+
74
+ city_tier = st.selectbox("City Tier", ["Tier 1", "Tier 2", "Tier 3"])
75
+ number_of_trips = st.number_input(
76
+ "Number of Trips (Annual Average)",
77
+ min_value=0,
78
+ max_value=20,
79
+ value=2,
80
+ step=1
81
+ )
82
+ passport = st.selectbox("Has Passport", [0, 1], format_func=lambda x: "Yes" if x == 1 else "No")
83
+ own_car = st.selectbox("Owns Car", [0, 1], format_func=lambda x: "Yes" if x == 1 else "No")
84
+
85
+ with col2:
86
+ st.subheader("๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Travel Details")
87
+
88
+ number_of_persons = st.number_input(
89
+ "Number of Persons Visiting",
90
+ min_value=1,
91
+ max_value=10,
92
+ value=2,
93
+ step=1
94
+ )
95
+ number_of_children = st.number_input(
96
+ "Number of Children Visiting (Below 5 years)",
97
+ min_value=0,
98
+ max_value=5,
99
+ value=0,
100
+ step=1
101
+ )
102
+ preferred_property_star = st.selectbox(
103
+ "Preferred Property Star Rating",
104
+ [3, 4, 5],
105
+ index=1
106
+ )
107
+
108
+ st.subheader("๐Ÿ“ž Interaction Details")
109
+
110
+ type_of_contact = st.selectbox(
111
+ "Type of Contact",
112
+ ["Company Invited", "Self Inquiry"]
113
+ )
114
+ product_pitched = st.selectbox(
115
+ "Product Pitched",
116
+ ["Basic", "Standard", "Deluxe", "Super Deluxe", "King"]
117
+ )
118
+ pitch_satisfaction_score = st.slider(
119
+ "Pitch Satisfaction Score",
120
+ min_value=1,
121
+ max_value=5,
122
+ value=3,
123
+ step=1
124
+ )
125
+ number_of_followups = st.number_input(
126
+ "Number of Follow-ups",
127
+ min_value=0,
128
+ max_value=10,
129
+ value=2,
130
+ step=1
131
+ )
132
+ duration_of_pitch = st.number_input(
133
+ "Duration of Pitch (minutes)",
134
+ min_value=0.0,
135
+ max_value=60.0,
136
+ value=10.0,
137
+ step=0.5
138
+ )
139
+
140
+ # Encode categorical variables (matching the preprocessing in prep.py)
141
+ def encode_categorical(value, category_type):
142
+ """Encode categorical values to match training data encoding"""
143
+ encodings = {
144
+ 'Gender': {'Male': 0, 'Female': 1},
145
+ 'MaritalStatus': {'Single': 0, 'Married': 1, 'Divorced': 2},
146
+ 'TypeofContact': {'Company Invited': 0, 'Self Inquiry': 1},
147
+ 'CityTier': {'Tier 1': 0, 'Tier 2': 1, 'Tier 3': 2},
148
+ 'Occupation': {
149
+ 'Salaried': 0, 'Freelancer': 1, 'Small Business': 2,
150
+ 'Large Business': 3, 'Other': 4
151
+ },
152
+ 'Designation': {
153
+ 'Executive': 0, 'Manager': 1, 'Senior Manager': 2,
154
+ 'AVP': 3, 'VP': 4, 'Other': 5
155
+ },
156
+ 'ProductPitched': {
157
+ 'Basic': 0, 'Standard': 1, 'Deluxe': 2,
158
+ 'Super Deluxe': 3, 'King': 4
159
+ }
160
+ }
161
+ return encodings.get(category_type, {}).get(value, 0)
162
+
163
+ # Assemble input into DataFrame
164
+ if st.button("๐Ÿ”ฎ Predict Purchase Likelihood", type="primary"):
165
+ input_data = pd.DataFrame([{
166
+ 'Age': age,
167
+ 'TypeofContact': encode_categorical(type_of_contact, 'TypeofContact'),
168
+ 'CityTier': encode_categorical(city_tier, 'CityTier'),
169
+ 'Occupation': encode_categorical(occupation, 'Occupation'),
170
+ 'Gender': encode_categorical(gender, 'Gender'),
171
+ 'NumberOfPersonVisiting': number_of_persons,
172
+ 'PreferredPropertyStar': preferred_property_star,
173
+ 'MaritalStatus': encode_categorical(marital_status, 'MaritalStatus'),
174
+ 'NumberOfTrips': number_of_trips,
175
+ 'Passport': passport,
176
+ 'OwnCar': own_car,
177
+ 'NumberOfChildrenVisiting': number_of_children,
178
+ 'Designation': encode_categorical(designation, 'Designation'),
179
+ 'MonthlyIncome': monthly_income,
180
+ 'PitchSatisfactionScore': pitch_satisfaction_score,
181
+ 'ProductPitched': encode_categorical(product_pitched, 'ProductPitched'),
182
+ 'NumberOfFollowups': number_of_followups,
183
+ 'DurationOfPitch': duration_of_pitch
184
+ }])
185
+
186
+ try:
187
+ prediction = model.predict(input_data)[0]
188
+ prediction_proba = model.predict_proba(input_data)[0]
189
+
190
+ st.markdown("---")
191
+ st.subheader("๐Ÿ“Š Prediction Result")
192
+
193
+ if prediction == 1:
194
+ st.success(f"โœ… **The customer is LIKELY to purchase the Wellness Tourism Package!**")
195
+ st.info(f"Confidence: {prediction_proba[1]*100:.2f}%")
196
+ else:
197
+ st.warning(f"โŒ **The customer is NOT LIKELY to purchase the Wellness Tourism Package.**")
198
+ st.info(f"Confidence: {prediction_proba[0]*100:.2f}%")
199
+
200
+ col_prob1, col_prob2 = st.columns(2)
201
+ with col_prob1:
202
+ st.metric("Probability of Purchase", f"{prediction_proba[1]*100:.2f}%")
203
+ with col_prob2:
204
+ st.metric("Probability of No Purchase", f"{prediction_proba[0]*100:.2f}%")
205
+
206
+ except Exception as e:
207
+ st.error(f"Error making prediction: {str(e)}")
208
+
209
+ st.markdown("---")
210
+ st.markdown("""
211
+ <div style='text-align: center; color: gray;'>
212
+ <p>Built with โค๏ธ for Visit with Us | MLOps Pipeline</p>
213
+ </div>
214
+ """, unsafe_allow_html=True)
215
+
requirements.txt CHANGED
@@ -1,3 +1,7 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
1
+ pandas==2.2.2
2
+ huggingface_hub==0.32.6
3
+ streamlit==1.43.2
4
+ joblib==1.5.1
5
+ scikit-learn==1.6.0
6
+ xgboost==2.1.4
7
+