11# Waste Assistant Chatbot for Jyväskylä ♻️
22
3- ** Waste Assistant** is a friendly Flask + OpenAI bot that helps newcomers—and anyone else—figure out where every item belongs in the city’s recycling system.
3+ ** Waste Assistant** is a friendly Flask + OpenAI bot that helps newcomers—and anyone else—figure out where every item belongs in the city’s recycling system.
44
5- > " Where should this go in Jyväskylä?"
5+ > “ Where should this go in Jyväskylä?” \
66> Ask in English or Finnish, or snap a photo—the bot knows the answer.
77
8- <p align =" center " >
9- <img src =" docs/demo.png " alt =" Demo screenshot " width =" 300 " >
10- </p >
11-
12-
138---
149
1510## ✨ Features
1611
17- * ** Local expertise** Tailored to Jyväskylä’s official sorting rules.
18- * ** Text * or* photo** Type a question * or* upload an image of the item.
19- * ** Bilingual UI** Instantly switch between ** English** and ** Finnish** .
20- * ** Smart image compression** 500 × 500 JPEG (quality 75) before sending to OpenAI → fewer tokens & lower cost.
21- * ** GPT-4o- mini vision + chat** One model for language * and* image reasoning.
22- * ** Serverless host** Runs on Google Cloud Run; scales to zero when idle.
12+ - ** Local expertise** — tailored to Jyväskylä’s official sorting rules.
13+ - ** Text ***** or***** photo** — type a question * or* upload an image of the item.
14+ - ** Bilingual UI** — instantly switch between ** English** and ** Finnish** .
15+ - ** Smart image compression** — 500 × 500 JPEG (quality 75) → fewer OpenAI tokens & lower cost.
16+ - ** GPT‑4o‑ mini vision + chat** — one model for language * and* image reasoning.
17+ - ** Serverless host** — runs on Google Cloud Run; scales to zero when idle.
2318
2419---
2520
2621## 🔧 Tech stack
2722
28- | Layer | Tool / Service |
29- | ------------- | ------------------------------ |
30- | Language | Python 3.10 |
31- | Web framework | Flask |
32- | AI / Vision | OpenAI API (gpt-4o- mini) |
33- | Container | Docker |
34- | CI / CD | GitHub Actions → Cloud Build |
35- | Runtime | Google Cloud Run |
23+ | Layer | Tool / Service |
24+ | ------------- | ---------------------------- |
25+ | Language | Python 3.10 |
26+ | Web framework | Flask |
27+ | AI / Vision | OpenAI API (gpt‑4o‑ mini) |
28+ | Container | Docker |
29+ | CI / CD | GitHub Actions → Cloud Build |
30+ | Runtime | Google Cloud Run |
3631
3732---
3833
39- ## 🚀 Quick start (local)
34+ ## 🚀 Quick start (local)
4035
4136``` bash
42- # 1 Clone & enter repo
43- git clone https://github.com/< your- user> /waste-assistant.git
37+ # 1 Clone & enter repo
38+ git clone https://github.com/< your‑ user> /waste-assistant.git
4439cd waste-assistant
4540
46- # 2 Virtual env
41+ # 2 Virtual env
4742python -m venv venv
4843source venv/bin/activate # Windows: venv\Scripts\activate
4944
50- # 3 Install deps
45+ # 3 Install deps
5146pip install -r requirements.txt
5247
53- # 4 Create .env
48+ # 4 Create .env (local only)
5449cat > .env << EOF
5550api_key=YOUR_OPENAI_API_KEY
5651secret_key=YOUR_FLASK_SECRET_KEY
5752EOF
5853
59- # 5 Run
54+ # 5 Run
6055python app.py # → http://localhost:8086
6156```
6257
6358Open the URL, ask “Where do I throw plastic bags?” or upload a picture, and get an instant answer.
6459
6560---
6661
67- ## 🖥️ Usage tips
62+ ## 🖥️ Usage tips
6863
69- * ** Ask anything** "Cardboard pizza box?", "Where do batteries go?" …
70- The bot replies with the right bin, plus nuances (e.g. rinse / remove labels).
71- * ** Photo mode** Drag- and- drop or tap the camera icon on mobile.
72- The compressed image is analysed by GPT-4o- mini vision.
73- * ** Session memory** Context survives for 30 minutes so follow- ups are fluid.
64+ - ** Ask anything** — "Cardboard pizza box?", "Where do batteries go?" …\
65+ The bot replies with the right bin, plus nuances (e.g. rinse / remove labels).
66+ - ** Photo mode** — drag‑ and‑ drop or tap the camera icon on mobile.\
67+ The compressed image is analysed by GPT‑4o‑ mini vision.
68+ - ** Session memory** — context survives for 30 minutes so follow‑ ups are fluid.
7469
7570---
7671
7772## 🗂️ Code overview
7873
79- * ** ` main.py ` ** Flask routes (` / ` , ` /ask ` , ` /reset ` ) + OpenAI calls.
80- * ** Prompts** System messages live in ` model_instructions/ ` (EN & FI).
81- * ** Image pipeline** ` compress_image() ` resizes & recompresses uploads to save tokens .
82- * ** Session** Flask- Session stores chat history on disk (` ./flask_session ` ).
74+ - `` — Flask routes (` / ` , ` /ask ` , ` /reset ` ) + OpenAI calls.
75+ - ** Prompts** — system messages live in ` model_instructions/ ` (EN & FI).
76+ - ** Image pipeline** — ` compress_image() ` resizes & recompresses uploads.
77+ - ** Session** — Flask‑ Session stores chat history on disk (` ./flask_session ` ).
8378
8479---
8580
86- ## ☁️ Continuous deployment (Cloud Run)
81+ ## ☁️ Continuous deployment (Cloud Run)
82+
83+ The workflow ` .github/workflows/deploy.yml ` builds from source with Cloud Build and deploys a new revision on every push to ` main ` .
84+
85+ 1 . ** Checkout** the repo.
86+ 2 . ** Authenticate** using the service‑account key in ` GCP_SA_KEY ` .
87+ 3 . ` gcloud run deploy --source . ` — Buildpacks build & push the image.
88+ 4 . Cloud Run rolls out the revision and keeps the public URL unchanged.
89+
90+ > Public URL format: ` https://wasteassistant‑xxxxx.a.run.app `
91+
92+ ### GitHub Secrets required by the workflow
8793
88- A single GitHub Actions workflow (` .github/workflows/deploy.yml ` ) handles CI/CD:
94+ | Name | Purpose |
95+ | -------------------- | -------------------------------------------------------- |
96+ | ** GCP\_ SA\_ KEY** | JSON key with roles: Artifact Registry, Cloud Build, Run |
97+ | ** GCP\_ PROJECT\_ ID** | e.g. ` gpt-models-436109 ` |
98+ | ** GCP\_ REGION** | e.g. ` europe-north1 ` |
8999
90- 1 . ** Checkout** code.
91- 2 . ** Authenticate** with a service-account key (` GCP_SA_KEY ` ).
92- 3 . ` gcloud run deploy --source . ` – Buildpacks build & push the image.
93- 4 . Cloud Run rolls out a new revision of the ` wasteassistant ` service.
100+ ### Runtime secrets (Secret Manager)
94101
95- > Public URL format: ` https://wasteassistant-xxxxx.a.run.app `
102+ ` OPENAI_API_KEY ` and ` FLASK_SECRET_KEY ` are ** not stored in GitHub ** . They live in ** Google Cloud Secret Manager ** and are injected by Cloud Run as environment variables.
96103
97- Required secrets:
104+ ``` bash
105+ # Create the secrets
106+ echo -n " sk-…" | gcloud secrets create OPENAI_API_KEY --data-file=-
107+ openssl rand -hex 32 | gcloud secrets create FLASK_SECRET_KEY --data-file=-
108+
109+ # Allow Cloud Run’s runtime SA to read them
110+ PROJECT_ID=" gpt-models-436109"
111+ PROJECT_NUM=$( gcloud projects describe $PROJECT_ID --format=' value(projectNumber)' )
112+ RUN_SA=" ${PROJECT_NUM} -compute@developer.gserviceaccount.com"
113+
114+ for SEC in OPENAI_API_KEY FLASK_SECRET_KEY; do
115+ gcloud secrets add-iam-policy-binding $SEC \
116+ --member=" serviceAccount:${RUN_SA} " \
117+ --role=" roles/secretmanager.secretAccessor"
118+ done
119+ ```
120+
121+ The workflow maps the latest secret versions to env‑vars:
98122
99- | Secret name | Purpose / example value |
100- | ---------------- | ------------------------------------------------------ |
101- | GCP \_ SA \_ KEY | JSON key (Artifact Registry + Cloud Build + Run roles) |
102- | GCP \_ PROJECT \_ ID | e.g. ` gpt-models-436109 ` |
103- | GCP \_ REGION | e.g. ` europe-north1 ` |
104- | OPENAI \_ API \_ KEY | ` sk-… ` |
105- | FLASK \_ SECRET | ` openssl rand -hex 32 ` (any long random string) |
123+ ``` yaml
124+ secrets : |
125+ OPENAI_API_KEY=projects/${{ secrets.GCP_PROJECT_ID }}/secrets/OPENAI_API_KEY:latest
126+ FLASK_SECRET=projects/${{ secrets.GCP_PROJECT_ID }}/secrets/FLASK_SECRET_KEY:latest
127+ ` ` `
128+
129+ The app then reads them with ` os.getenv("api_key")` and `os.getenv("secret_key")`.
106130
107131---
108132
@@ -111,13 +135,14 @@ Required secrets:
111135Pull requests are welcome!
112136
1131371. Fork → branch → commit with clear messages.
114- 2 . Push and open a PR against ` main ` .
115- 3 . CI will build & deploy the preview automatically.
138+ 2. Push and open a PR against ``.
139+ 3. CI will build & deploy the preview automatically.
116140
117- Found a bug or want to suggest a new feature ? Open an issue.
141+ Found a bug or have an idea ? Open an issue.
118142
119143---
120144
121145# # 📄 License
122146
123- Apache-2.0. See ` LICENSE ` for full text
147+ Apache‑2.0 — see `LICENSE` for full text.
148+
0 commit comments