averye-duke commited on
Commit
e002dc4
·
1 Parent(s): 10bc8b7

Push streamlit app to hugging face

Browse files
Files changed (9) hide show
  1. .gitattributes +1 -0
  2. .gitignore +16 -0
  3. README.md +90 -0
  4. cli_demo.py +121 -0
  5. image.png +3 -0
  6. logo_image.png +3 -0
  7. nhtsa_api_call.py +22 -0
  8. requirements.txt +42 -3
  9. streamlit_app.py +204 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # virtual environments
2
+ venv/
3
+ .venv/
4
+
5
+ # python cache
6
+ __pycache__/
7
+
8
+ # log info and local stuff
9
+ *.log
10
+ .DS_Store
11
+ .idea/
12
+ .vscode/
13
+
14
+ # Environment & secrets
15
+ .env
16
+ env/
README.md CHANGED
@@ -17,3 +17,93 @@ Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :hear
17
 
18
  If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
  forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
  forums](https://discuss.streamlit.io).
20
+
21
+
22
+ # Car Dealership VIN Lookup App
23
+
24
+ ![alt text](logo_image.png)
25
+
26
+ ## 📌 Overview
27
+ This is a simple app for a car dealership that allows users to look up vehicle information (year, make, and model) by entering a VIN number.
28
+
29
+ Additionally, the app keeps track of search frequency and lets users view the **Top 3 most looked-up vehicle makes**.
30
+
31
+ All vehicle data is retrieved from the [NHTSA (National Highway Traffic Safety Administration) VIN decoding API](https://vpic.nhtsa.dot.gov/api/), accessed via the helper module [`nhtsa_api_call.py`](./nhtsa_api_call.py).
32
+
33
+ ---
34
+
35
+ ## ⚙️ Features
36
+ - 🔍 Lookup vehicle details (year, make, model) by VIN number
37
+ - 📊 View the **Top 3 most searched vehicle makes**
38
+ - 🌐 Fetches real-time data from the **NHTSA VIN API**
39
+ - 🖥️ Simple and interactive command-line interface
40
+
41
+ ---
42
+ ## 📦 Python Version
43
+
44
+ Tested on: Python 3.10
45
+
46
+ ---
47
+ ## 🚀 Getting Started
48
+
49
+ **How to run locally**
50
+
51
+ 1. Clone the Repository
52
+ git clone https://github.com/averyestopinal/AIPI503PROJECT
53
+ cd AIPI503PROJECT
54
+
55
+ 2. Create a virtual environment (optional but recommended):
56
+ python -m venv .venv
57
+ source .venv/bin/activate # macOS/Linux
58
+ .venv\Scripts\activate # Windows
59
+
60
+ 3. Install Dependencies
61
+ This app uses only standard Python libraries (no external dependencies).However, make sure you are running Python 3.7+.
62
+ pip install -r requirements.txt
63
+
64
+ 4. Run the Streamlit app:
65
+ streamlit run streamlit_app.py
66
+
67
+ **How to Run cli_demo.py**
68
+ This is a simple command-line version of the VIN decoder. Make sure your terminal is in the same directory as cli_demo.py.
69
+
70
+ python cli_demo.py
71
+
72
+ **Link to the Hugging Faces Space**
73
+
74
+
75
+ ---
76
+
77
+ 🧩 Project Structure
78
+ .
79
+ ├── streamlit_app.py # Entry point for the Streamlit application
80
+ ├── cli_demo.py # Command-line interface version of the VIN decoder
81
+ ├── nhtsa_api_call.py # Helper module for API requests
82
+ ├── car_image.png # Image file used in the Streamlit application
83
+ ├── logo_image.py # Logo image file used in the Streamlit application
84
+ ├── README.md # Project documentation
85
+ ├── requirements.txt # Python Dependencies
86
+
87
+ ---
88
+ 📡 API Reference
89
+ The app uses the NHTSA VIN Decoder API which provides vehicle details when supplied with a VIN number.
90
+
91
+ Example request: https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValues/<VIN>?format=json
92
+
93
+ ---
94
+ 🙌 Credits
95
+ NHTSA Vehicle API
96
+ Streamlit
97
+ Hugging Face Spaces
98
+
99
+ ---
100
+ 👨‍💻 Author
101
+ Developed as part of a learning project by
102
+ 1. Avery Estopinal
103
+ 2. Sharmil K
104
+ 3. Eugenia Tate
105
+ 4. Jaideep Aher
106
+ ---
107
+
108
+ Contributions are welcome!
109
+ Feel free to fork and submit a pull request 🚀
cli_demo.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ cli_demo.py
3
+
4
+ Author: Eugenia Tate
5
+ Date: August 24, 2025
6
+
7
+ A simple command-line application for a car dealership that allows users
8
+ to look up vehicle information (year, make, and model) by VIN number.
9
+ The app also lets a user view top 3 looked up vehicle makes.
10
+ The data is retrieved from the NHTSA (National Highway Traffic Safety
11
+ Administration) VIN decoding API via the helper module `nhtsa_api_call.py`.
12
+
13
+ Usage:
14
+ python cli_demo.py
15
+ """
16
+ import nhtsa_api_call, re, csv, os
17
+ import pandas as pd
18
+
19
+ TOP3 = 3
20
+
21
+ def is_valid_vin (vin):
22
+ """
23
+ Check whether vin is valid.
24
+ A valid VIN is a VIN of 17 alphanumeric characters long and can not
25
+ include I, O, Q.
26
+ """
27
+ vin = vin.upper()
28
+ if len(vin) != 17:
29
+ return False
30
+ if not re.match(r'^[A-HJ-NPR-Z0-9]{17}$', vin):
31
+ return False
32
+ return True
33
+
34
+ def save_vehicle(year, make, model, filename = "vin_lookup_history.csv"):
35
+ """Append VIN lookup result to a CSV file."""
36
+ file_exists = os.path.isfile(filename)
37
+ with open(filename, "a", newline="") as f:
38
+ writer = csv.writer(f)
39
+ if not file_exists:
40
+ # add first row
41
+ writer.writerow(["year", "make", "model"])
42
+ writer.writerow([year, make, model])
43
+
44
+ def display_top3(filename = "vin_lookup_history.csv"):
45
+ """Show top 3 car makes by lookup frequency"""
46
+ # if file does not exist then there is no history yet
47
+ if not os.path.isfile(filename):
48
+ print("\nNo VIN lookup history found. Please look up some VINs first.\n")
49
+ return
50
+ # create a dataframe using file data
51
+ df = pd.read_csv(filename)
52
+ # save number each make appears in the log as a series
53
+ counts = df['make'].value_counts()
54
+ # file exists but no data has been added yet
55
+ if len(counts) == 0:
56
+ print("\n No data in the log yet.\n")
57
+ return
58
+ # if there are fewer than 3 data entries in the log then the program will
59
+ # at least display 1 or 2 most looked up makes
60
+ if len(counts) < TOP3:
61
+ print(f"\nNot enough data for displaying top 3. Showing top {len(counts)} instead:\n")
62
+ top_makes = counts.head(len(counts))
63
+ else:
64
+ print(f"\n Top {TOP3} Car Makes from Lookups:\n")
65
+ top_makes = counts.head(TOP3)
66
+
67
+ for make, count in top_makes.items():
68
+ print(f" {make}: {count} lookups")
69
+ # an empty line print to space out CLI prompts
70
+ print()
71
+
72
+ def main():
73
+ """
74
+ Run the command-line VIN lookup loop.
75
+
76
+ Prompts the user for a VIN number, calls the NHTSA API,
77
+ and prints out the vehicle information if found.
78
+ Enter '0' to exit.
79
+ """
80
+ print("🚗 Welcome to the Car Dealership VIN Lookup!\n")
81
+
82
+ while True:
83
+ print("Choose an option from the menu:")
84
+ print("1. Lookup a VIN")
85
+ print("2. Show Top 3 Most Looked-up Makes")
86
+ print("0. Exit")
87
+ choice = input("Enter your choice: ").strip()
88
+
89
+ # exit condition gets checked first
90
+ if choice == "0":
91
+ print("👋 You chose to exit VIN lookup. Goodbye!")
92
+ break
93
+ # user selected to add a VIN
94
+ elif choice == "1":
95
+ vin = input("Please enter a valid VIN or 0 (zero) to exit: \n").strip()
96
+ if vin == "0":
97
+ continue
98
+ # check if vin is valid, and if not print error message
99
+ if not is_valid_vin(vin):
100
+ print("Invalid VIN format. Must be 17 letters/numbers (no I, O, Q). Try again.\n")
101
+ continue
102
+ # vin is valid, perform VIN lookup
103
+ else:
104
+ year, make, model = nhtsa_api_call.get_vehicle_info(vin)
105
+ if year and make and model:
106
+ print(f"✅ VIN {vin}")
107
+ print(f" Year: {year}")
108
+ print(f" Make: {make}")
109
+ print(f" Model: {model}")
110
+ save_vehicle(year, make, model) #save the data in the lookup history file
111
+ else:
112
+ print(f"❌ VIN {vin} not found in database. Try again.")
113
+ # user selected to view top3 vehicle makes
114
+ elif choice == "2":
115
+ display_top3()
116
+ # user entered something other than 1,2 or 0
117
+ else:
118
+ print("Invalid option. Please choose 1, 2, or 0.\n")
119
+
120
+ if __name__ == "__main__":
121
+ main()
image.png ADDED

Git LFS Details

  • SHA256: a6376e4eb5a4b96b02a76e76e6c37eb552e10cc7ab645a53a7de77eb3149c432
  • Pointer size: 132 Bytes
  • Size of remote file: 2 MB
logo_image.png ADDED

Git LFS Details

  • SHA256: eb63cae33a58536c8edbfd5636b882cd3adf64d96d24e254847ef7b05934da42
  • Pointer size: 132 Bytes
  • Size of remote file: 2.21 MB
nhtsa_api_call.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ def get_vehicle_info(vin):
4
+ """
5
+ This function takes the parameter "vin" and uses the NHTSA Decode VIN API to retrive year, make, and model
6
+ The API returns a JSON file which is not a dictionary so the file must be searched with a for loop by "Variable"
7
+ For more API information visit https://vpic.nhtsa.dot.gov/api/
8
+ """
9
+ url = f'https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVin/{vin}?format=json'
10
+ response = requests.get(url);
11
+ data = response.json()
12
+
13
+ for item in data["Results"]:
14
+ if item["Variable"] in ["Model Year"]:
15
+ year = item["Value"]
16
+ if item["Variable"] in ["Make"]:
17
+ make = item["Value"]
18
+ if item["Variable"] in ["Model"]:
19
+ model = item["Value"]
20
+
21
+ return year, make, model
22
+
requirements.txt CHANGED
@@ -1,3 +1,42 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ altair==5.5.0
2
+ attrs==25.3.0
3
+ blinker==1.9.0
4
+ cachetools==6.2.0
5
+ certifi==2025.8.3
6
+ charset-normalizer==3.4.3
7
+ click==8.2.1
8
+ contourpy==1.3.2
9
+ cycler==0.12.1
10
+ fonttools==4.59.1
11
+ gitdb==4.0.12
12
+ GitPython==3.1.45
13
+ idna==3.10
14
+ Jinja2==3.1.6
15
+ jsonschema==4.25.1
16
+ jsonschema-specifications==2025.4.1
17
+ kiwisolver==1.4.9
18
+ MarkupSafe==3.0.2
19
+ matplotlib==3.10.5
20
+ narwhals==2.2.0
21
+ numpy==2.2.6
22
+ packaging==25.0
23
+ pandas==2.3.2
24
+ pillow==11.3.0
25
+ protobuf==6.32.0
26
+ pyarrow==21.0.0
27
+ pydeck==0.9.1
28
+ pyparsing==3.2.3
29
+ python-dateutil==2.9.0.post0
30
+ pytz==2025.2
31
+ referencing==0.36.2
32
+ requests==2.32.5
33
+ rpds-py==0.27.0
34
+ six==1.17.0
35
+ smmap==5.0.2
36
+ streamlit==1.49.0
37
+ tenacity==9.1.2
38
+ toml==0.10.2
39
+ tornado==6.5.2
40
+ typing_extensions==4.15.0
41
+ tzdata==2025.2
42
+ urllib3==2.5.0
streamlit_app.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ VIN Decoder Streamlit App
3
+
4
+ This app allows users to input a Vehicle Identification Number (VIN) and fetch vehicle
5
+ information (year, make, model). The data is retrieved from the NHTSA (National Highway Traffic Safety
6
+ Administration) VIN decoding API via the helper module `nhtsa_api_call.py`.
7
+ Useful for car dealerships who need quick VIN lookups.
8
+
9
+ Usage:
10
+ streamlit run streamlit_vin_decoder.py
11
+
12
+ Author: Sharmil Nanjappa
13
+ Date: August 25, 2025
14
+ """
15
+
16
+ import streamlit as st # Import the Streamlit library for creating the web app
17
+ import nhtsa_api_call # Import the API call function from external file
18
+ import os
19
+ import re
20
+ import pandas as pd
21
+ import matplotlib.pyplot as plt
22
+ from collections import Counter
23
+
24
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Gets the current directory
25
+ logo_img_file = os.path.join(BASE_DIR, "logo_image.png")
26
+ car_img_file = os.path.join(BASE_DIR, "car_image.png")
27
+ TOP3 = 3 # Define top N makes to display
28
+
29
+ # Check if the 'make_history' key is already in Streamlit's session state
30
+ if "make_history" not in st.session_state:
31
+ # If not, initialize it as an empty list to store searched vehicle makes
32
+ st.session_state.make_history = []
33
+
34
+ # Define a function to track the vehicle make each time a VIN is decoded
35
+ def track_make(make):
36
+ """
37
+ Store the searched make in session state for pie chart stats.
38
+ """
39
+ # Proceed only if a valid make value is provided
40
+ if make:
41
+ # Capitalize and append the make to the session history list
42
+ st.session_state.make_history.append(make.title())
43
+ # Optional: Display the current list of searched makes in the sidebar for debugging
44
+ #st.sidebar.write("Debug – History:", st.session_state.make_history)
45
+
46
+
47
+ def show_top_3_makes():
48
+ """
49
+ Display a pie chart of the top 3 most searched vehicle makes.
50
+
51
+ if not st.session_state.make_history:
52
+ st.warning("No vehicle makes have been searched yet.")
53
+ return
54
+ """
55
+
56
+
57
+
58
+ if not st.session_state.make_history:
59
+ st.warning("No vehicle makes have been searched yet.")
60
+ return
61
+
62
+ # Count how many times each make was searched
63
+ counts = Counter(st.session_state.make_history)
64
+
65
+ if len(counts) < TOP3:
66
+ st.warning(f"Not enough data to display Top 3. Showing Top {len(counts)} instead.")
67
+
68
+ # Get the top N (3 or fewer)
69
+ top_n = counts.most_common(min(len(counts), TOP3))
70
+
71
+ labels = [item[0].upper() for item in top_n] # Label for the vehicle make, displayed in upper case for each slice of the pie chart
72
+ sizes = [item[1] for item in top_n] # Count of each make in the Top3. Used to determine how large each slice of the pie chart is.
73
+ colors = ['#4682B4', '#1E3F66', '#0B1F3A'][:len(labels)] #[colors of pie chart slices][match slice count]
74
+ with st.container():
75
+
76
+ st.markdown("""
77
+ <div style="
78
+ max-width: 700px;
79
+ margin: 0 auto;
80
+ padding: 12px 24px;
81
+ border: 1px solid #ccc;
82
+ border-radius: 10px;
83
+ background-color: #f9f9f9;
84
+ text-align: center;
85
+ font-size: 16px;
86
+ font-weight: 500;
87
+ ">
88
+ Pie chart displaying the Top 3 Vehicles<br>
89
+ searched based on their Make
90
+ </div>
91
+ """, unsafe_allow_html=True)
92
+
93
+ fig, ax = plt.subplots(figsize=(3,3), dpi=150)
94
+
95
+ # Draw pie chart with borders and percentage labels
96
+ wedges, texts, autotexts = ax.pie(
97
+ sizes,
98
+ labels=labels,
99
+ colors=colors,
100
+ autopct='%1.1f%%',
101
+ startangle=90, # autopct shows % and startangle starts the first slice from the top
102
+ wedgeprops={'edgecolor': 'white', 'linewidth': 1}
103
+ )
104
+
105
+ ax.axis('equal') # Forces the chart to be a perfect circle
106
+
107
+ # Style text and labels
108
+ for text in texts: #The labels of each pie slice
109
+ text.set_fontsize(5)
110
+ text.set_color('#000') # text color: Black
111
+ text.set_fontweight('semibold')
112
+
113
+ for autotext in autotexts: #The percentages shown on each slice
114
+ autotext.set_fontsize(5)
115
+ autotext.set_color('#fff') # text color: White
116
+
117
+ st.pyplot(fig)
118
+ st.markdown("</div>", unsafe_allow_html=True)
119
+
120
+ def get_vin(vin):
121
+ """
122
+ Decodes the VIN and displays model,make, model year.
123
+ Validates VIN format and displays vehicle details or error message.
124
+ """
125
+ status_area = st.empty()
126
+ col1, col2 = st.columns([1, 1])
127
+
128
+ if len(vin) != 17:
129
+ status_area.error(f"VIN must be exactly 17 characters long.")
130
+ return
131
+ elif not re.match(r'^[A-HJ-NPR-Z0-9]{17}$', vin):
132
+ status_area.error(f"VIN must be alpha-numeric and cannot include letters I, O, Q.")
133
+ return
134
+ else:
135
+ status_area.info("Decoding VIN...")
136
+
137
+ try:
138
+ year, make, model = nhtsa_api_call.get_vehicle_info(vin)
139
+
140
+ if not all([year, make, model]) or any([v is None for v in [year, make, model]]):
141
+ status_area.warning(f"Incomplete vehicle data returned. Please verify the VIN and try again.")
142
+ else:
143
+ status_area.success("VIN decoded successfully!")
144
+
145
+ track_make(make)
146
+ with col1:
147
+ st.image(car_img_file, use_container_width=True)
148
+
149
+ with col2:
150
+ st.write(f"Below are the vehicle details :")
151
+ st.write("🔍 Vehicle Information")
152
+ st.write(f"**Make:** {make}")
153
+ st.write(f"**Model:** {model}")
154
+ st.write(f"**Model Year:** {year}")
155
+
156
+ except Exception as e:
157
+ status_area.error(f"An error occurred while decoding the VIN: {e}")
158
+
159
+ def main():
160
+ """
161
+ Sets Streamlitcomponents for the page layout, handles user input, and calls get_vin function.
162
+ """
163
+
164
+ col1, col2 = st.columns([1, 2])
165
+ with col1:
166
+ st.image(logo_img_file, width=180)
167
+ with col2:
168
+ st.markdown("""
169
+ <div style='text-align: left; margin-top: 30px;'>
170
+ <h1 style='font-size: 38px;'>Vehicle VIN Decoder</h1>
171
+ </div>
172
+ """, unsafe_allow_html=True)
173
+ st.write("*" * 50)
174
+
175
+ st.markdown("<h5 style='text-align: center;'>Welcome to the Car Dealership VIN Lookup!</h5>", unsafe_allow_html=True)
176
+
177
+
178
+ with st.expander("ℹ️ About this app"):
179
+ st.write("This app is designed to help car dealerships and automotive professionals effortlessly decode Vehicle Identification Numbers (VINs) to retrieve key vehicle details such as model,make and model year. By simply entering a 17-character VIN, users can access verified vehicle information. The data is fetched in real-time from the National Highway Traffic Safety Administration (NHTSA). Whether you're validating trade-ins, checking vehicle specs, or streamlining inventory intake, this tool delivers quick and reliable insights.")
180
+
181
+
182
+
183
+ st.markdown("Enter a **17-character VIN** below to decode the vehicle info.")
184
+
185
+ vin = st.text_input("Enter VIN:", max_chars=17).strip().upper()
186
+ if st.button("Decode VIN", use_container_width=True):
187
+ if vin:
188
+ get_vin(vin)
189
+ else:
190
+ st.error(f"❌ Please enter a VIN before fetching the vehicle information.")
191
+
192
+ # Show top 3 searched makes
193
+ st.markdown("---")
194
+ if st.button("Top 3 Makes Searched", use_container_width=True):
195
+ show_top_3_makes()
196
+
197
+ st.markdown("___")
198
+ st.markdown("<p style='text-align: center; font-size: 14px;'>© 2025 Car Dealership VIN Lookup", unsafe_allow_html=True) #Footer for the webpage
199
+
200
+
201
+
202
+
203
+ if __name__ == "__main__":
204
+ main()