Spaces:
Running
Running
Sync from GitHub 50cd1ca57c1ae023f7e08f8af52ee596195014df
Browse files- .dockerignore +8 -1
- .env.example +36 -16
- .gitignore +1 -5
- DEPLOYMENT_CHECKLIST.md +32 -31
- requirements.txt +4 -6
.dockerignore
CHANGED
|
@@ -1,17 +1,24 @@
|
|
| 1 |
.git
|
|
|
|
| 2 |
.gitignore
|
|
|
|
| 3 |
.env
|
|
|
|
|
|
|
| 4 |
__pycache__
|
| 5 |
*.pyc
|
| 6 |
*.pyo
|
|
|
|
| 7 |
venv/
|
| 8 |
logs/
|
|
|
|
|
|
|
| 9 |
data/database/backups/
|
| 10 |
tests/
|
| 11 |
docs/
|
|
|
|
| 12 |
README.md
|
| 13 |
README_UPDATES.md
|
| 14 |
*.md
|
| 15 |
-
.github/
|
| 16 |
.pytest_cache/
|
| 17 |
htmlcov/
|
|
|
|
| 1 |
.git
|
| 2 |
+
.github/
|
| 3 |
.gitignore
|
| 4 |
+
.dockerignore
|
| 5 |
.env
|
| 6 |
+
.claude/
|
| 7 |
+
.DS_Store
|
| 8 |
__pycache__
|
| 9 |
*.pyc
|
| 10 |
*.pyo
|
| 11 |
+
*.log
|
| 12 |
venv/
|
| 13 |
logs/
|
| 14 |
+
data/
|
| 15 |
+
!data/database/
|
| 16 |
data/database/backups/
|
| 17 |
tests/
|
| 18 |
docs/
|
| 19 |
+
deploy/
|
| 20 |
README.md
|
| 21 |
README_UPDATES.md
|
| 22 |
*.md
|
|
|
|
| 23 |
.pytest_cache/
|
| 24 |
htmlcov/
|
.env.example
CHANGED
|
@@ -1,22 +1,42 @@
|
|
| 1 |
-
#
|
| 2 |
-
OPENAI_API_KEY=your_openai_api_key_here
|
| 3 |
|
| 4 |
-
#
|
| 5 |
-
#
|
|
|
|
| 6 |
|
| 7 |
-
#
|
| 8 |
-
# OPEN_ROUTER_API_KEY=your_openrouter_api_key_here
|
| 9 |
-
|
| 10 |
-
# Required variables if using Weaviate Cloud
|
| 11 |
WEAVIATE_API_KEY=your_weaviate_api_key
|
| 12 |
WEAVIATE_CLUSTER_URL=your_weaviate_rest_endpoint_url
|
| 13 |
-
HUGGING_FACE_API_KEY=your_hf_api_key
|
| 14 |
|
| 15 |
-
#
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
#
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ============================== Required at runtime ==============================
|
|
|
|
| 2 |
|
| 3 |
+
# OpenRouter API key - ALL LLM roles (agent, fallback, language detection,
|
| 4 |
+
# summarization) AND the embeddings run through OpenRouter (see config.py).
|
| 5 |
+
OPEN_ROUTER_API_KEY=your_openrouter_api_key_here
|
| 6 |
|
| 7 |
+
# Weaviate Cloud (EU cluster)
|
|
|
|
|
|
|
|
|
|
| 8 |
WEAVIATE_API_KEY=your_weaviate_api_key
|
| 9 |
WEAVIATE_CLUSTER_URL=your_weaviate_rest_endpoint_url
|
|
|
|
| 10 |
|
| 11 |
+
# ============================== Optional ==============================
|
| 12 |
+
|
| 13 |
+
# Only needed for the opt-in LLM test suites (RUN_LLM_EVAL / RUN_UAT_LLM_JUDGE),
|
| 14 |
+
# not by the runtime agent.
|
| 15 |
+
# OPENAI_API_KEY=your_openai_api_key_here
|
| 16 |
+
|
| 17 |
+
# Docling remote PDF parsing in the facts pipeline (falls back to pypdf without it).
|
| 18 |
+
# HUGGING_FACE_API_KEY=your_hf_api_key
|
| 19 |
+
|
| 20 |
+
# Weaviate manual database backups (only if the manual backup backend is selected)
|
| 21 |
+
# WEAVIATE_BACKUP_PATH=path_to_directory
|
| 22 |
+
|
| 23 |
+
# LangSmith tracing (debugging and monitoring)
|
| 24 |
+
# LANGSMITH_TRACING=true
|
| 25 |
+
# LANGSMITH_API_KEY=your_langsmith_api_key
|
| 26 |
+
# LANGSMITH_PROJECT=your_project_name
|
| 27 |
+
# LANGSMITH_ENDPOINT=https://api.smith.langchain.com
|
| 28 |
+
|
| 29 |
+
# ============================== Fact-change alerts ==============================
|
| 30 |
+
# Used by src/notification/notification_center.py when the facts pipeline
|
| 31 |
+
# detects price/deadline changes. In production these run as GitHub Actions
|
| 32 |
+
# secrets (.github/workflows/update_programme_facts.yml) - only set them
|
| 33 |
+
# locally if you want a machine to send alerts itself.
|
| 34 |
|
| 35 |
+
# NOTIFY_SMTP_HOST=smtp.example.com
|
| 36 |
+
# NOTIFY_SMTP_PORT=587
|
| 37 |
+
# NOTIFY_SMTP_USER=alerts@example.com
|
| 38 |
+
# NOTIFY_SMTP_PASSWORD=your_smtp_password
|
| 39 |
+
# NOTIFY_SMTP_USE_TLS=true
|
| 40 |
+
# NOTIFY_FROM_EMAIL=alerts@example.com
|
| 41 |
+
# NOTIFY_TO_EMAIL=team@example.com
|
| 42 |
+
# NOTIFY_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
|
.gitignore
CHANGED
|
@@ -60,12 +60,8 @@ pyrightconfig.json
|
|
| 60 |
.idea/
|
| 61 |
|
| 62 |
# OS junk
|
| 63 |
-
.Trashes
|
| 64 |
-
.env
|
| 65 |
|
| 66 |
-
#idk
|
| 67 |
-
--source-branch
|
| 68 |
-
--source-repo
|
| 69 |
/.gradio/certificate.pem
|
| 70 |
|
| 71 |
#feedback I just uploaded into the same file to check for accuracy
|
|
|
|
| 60 |
.idea/
|
| 61 |
|
| 62 |
# OS junk
|
| 63 |
+
.Trashes
|
|
|
|
| 64 |
|
|
|
|
|
|
|
|
|
|
| 65 |
/.gradio/certificate.pem
|
| 66 |
|
| 67 |
#feedback I just uploaded into the same file to check for accuracy
|
DEPLOYMENT_CHECKLIST.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Deployment Checklist — EMBA HSG RAG Chatbot
|
| 2 |
|
| 3 |
-
**Stand:** 2026-
|
| 4 |
**Ablöst:** [docs/deploy_readiness_checklist.md](docs/deploy_readiness_checklist.md) (vom 10.04., in Teilen veraltet — siehe Abschnitt 7)
|
| 5 |
|
| 6 |
Ziel: Single-Host-Deployment des Bots, eingebettet per `<iframe>` in die EMBA-Website
|
|
@@ -15,13 +15,14 @@ Browser auf emba.unisg.ch / embax.ch
|
|
| 15 |
└─ <iframe src="https://bot.hsg.ch">
|
| 16 |
└─ Caddy (TLS, reverse proxy, CSP) deploy/Caddyfile
|
| 17 |
└─ Container: python main.py --app de → 0.0.0.0:7860 (Gradio/FastAPI, /health)
|
| 18 |
-
├─ Weaviate Cloud (EU-Region)
|
| 19 |
-
├─
|
| 20 |
-
└─ OpenRouter text-embedding-3-small
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
| 25 |
```
|
| 26 |
|
| 27 |
---
|
|
@@ -55,9 +56,7 @@ Cron auf demselben Host:
|
|
| 55 |
|
| 56 |
## 3. Repo-Stand & Code (vor Build)
|
| 57 |
|
| 58 |
-
- [
|
| 59 |
-
Aktuell **nicht in `main`** — `main` importiert noch `src/cache/`. Redis ist optional
|
| 60 |
-
(Fallback auf dict-Cache, Redis-Verbindungsfehler ist unkritisch).
|
| 61 |
- [ ] `requirements.txt` entspricht dem tatsächlichen Runtime-Bedarf
|
| 62 |
- [ ] Dockerfile-Base-Image aktuell ([Dockerfile](Dockerfile): `python:3.11.14-slim-bookworm` ✓)
|
| 63 |
- [ ] Offline-Tests grün: `pytest tests/test_verified_facts.py tests/test_stream_parser.py`
|
|
@@ -79,12 +78,15 @@ Cron auf demselben Host:
|
|
| 79 |
|
| 80 |
## 5. Umgebungsvariablen (Prod-`.env`)
|
| 81 |
|
| 82 |
-
- [ ] `
|
| 83 |
-
- [ ] `OPEN_ROUTER_API_KEY` (Embeddings)
|
| 84 |
- [ ] `WEAVIATE_CLUSTER_URL`, `WEAVIATE_API_KEY` (EU-Cluster)
|
| 85 |
-
- [ ] **SMTP/Slack-Variablen** für Fakten-Änderungs-Alerts (sonst läuft der Facts-Cron ohne Benachrichtigung)
|
| 86 |
- [ ] Optional `LANGSMITH_*` (Tracing)
|
| 87 |
-
- [ ] Werte gegen `src/config/configs.py` verifiziert
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
---
|
| 90 |
|
|
@@ -99,20 +101,18 @@ Cron auf demselben Host:
|
|
| 99 |
|
| 100 |
---
|
| 101 |
|
| 102 |
-
## 7.
|
| 103 |
-
|
| 104 |
-
- [
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
(
|
| 114 |
-
- [ ] **Alert-Chain einmal testen:** Preis in `data/database/programme_facts.json` ändern →
|
| 115 |
-
`python -m src.pipeline.update_programme_facts` → E-Mail/Slack muss ankommen → Änderung zurücknehmen
|
| 116 |
|
| 117 |
---
|
| 118 |
|
|
@@ -139,7 +139,8 @@ Cron auf demselben Host:
|
|
| 139 |
|
| 140 |
## 10. Betrieb / Monitoring
|
| 141 |
|
| 142 |
-
- [ ]
|
|
|
|
| 143 |
- [ ] `grep "\[timing\]" logs/logs.log` — Latenz im Blick (Ziel ~6 s end-to-end)
|
| 144 |
- [ ] Weaviate-Cluster-Status (läuft, nicht abgelaufen — Lehre aus dem 404-Ausfall)
|
| 145 |
- [ ] Health-Check `GET /health` in Host-Monitoring eingebunden
|
|
@@ -149,7 +150,7 @@ Cron auf demselben Host:
|
|
| 149 |
## Go / No-Go
|
| 150 |
|
| 151 |
**Go**, wenn: Host in EU/CH steht · Datenschutz-Sign-off · Weaviate gefüllt & checkhealth grün ·
|
| 152 |
-
iframe-CSP gefixt & auf Zielseite getestet · beide
|
| 153 |
|
| 154 |
**No-Go**, wenn: kein DSGVO-Sign-off · Weaviate leer/abgelaufen · CSP blockiert iframe auf `*.unisg.ch` ·
|
| 155 |
SMTP/Slack fehlt (Fakten-Alerts stumm) · LLM-Eval nicht 31/31.
|
|
|
|
| 1 |
# Deployment Checklist — EMBA HSG RAG Chatbot
|
| 2 |
|
| 3 |
+
**Stand:** 2026-07-04 (Abschnitte 0/3/5/7 an den Ist-Zustand angepasst; ursprünglich 2026-06-16 @ `b0f8038`)
|
| 4 |
**Ablöst:** [docs/deploy_readiness_checklist.md](docs/deploy_readiness_checklist.md) (vom 10.04., in Teilen veraltet — siehe Abschnitt 7)
|
| 5 |
|
| 6 |
Ziel: Single-Host-Deployment des Bots, eingebettet per `<iframe>` in die EMBA-Website
|
|
|
|
| 15 |
└─ <iframe src="https://bot.hsg.ch">
|
| 16 |
└─ Caddy (TLS, reverse proxy, CSP) deploy/Caddyfile
|
| 17 |
└─ Container: python main.py --app de → 0.0.0.0:7860 (Gradio/FastAPI, /health)
|
| 18 |
+
├─ Weaviate Cloud (EU-Region) Retrieval
|
| 19 |
+
├─ OpenRouter gpt-4.1 Agent (alle LLM-Rollen, config.py)
|
| 20 |
+
└─ OpenRouter text-embedding-3-small Embeddings (app-seitig)
|
| 21 |
+
|
| 22 |
+
GitHub Actions (kein Host-Cron nötig):
|
| 23 |
+
update_programme_facts.yml täglich 06:23 UTC (verifizierte Fakten + Diff-Alerts)
|
| 24 |
+
scrape.yml wöchentlich So 05:17 UTC
|
| 25 |
+
NOTIFY_*-Secrets sind im Repo hinterlegt (Alerts laufen aus der Action)
|
| 26 |
```
|
| 27 |
|
| 28 |
---
|
|
|
|
| 56 |
|
| 57 |
## 3. Repo-Stand & Code (vor Build)
|
| 58 |
|
| 59 |
+
- [x] **PR #41 (Caching-Entfernung) gemergt** — `src/cache/` existiert nicht mehr in `main`.
|
|
|
|
|
|
|
| 60 |
- [ ] `requirements.txt` entspricht dem tatsächlichen Runtime-Bedarf
|
| 61 |
- [ ] Dockerfile-Base-Image aktuell ([Dockerfile](Dockerfile): `python:3.11.14-slim-bookworm` ✓)
|
| 62 |
- [ ] Offline-Tests grün: `pytest tests/test_verified_facts.py tests/test_stream_parser.py`
|
|
|
|
| 78 |
|
| 79 |
## 5. Umgebungsvariablen (Prod-`.env`)
|
| 80 |
|
| 81 |
+
- [ ] `OPEN_ROUTER_API_KEY` (**alle** LLM-Rollen + Embeddings — seit PR #49 läuft nichts mehr direkt über OpenAI)
|
|
|
|
| 82 |
- [ ] `WEAVIATE_CLUSTER_URL`, `WEAVIATE_API_KEY` (EU-Cluster)
|
|
|
|
| 83 |
- [ ] Optional `LANGSMITH_*` (Tracing)
|
| 84 |
+
- [ ] Werte gegen `src/config/configs.py` verifiziert (Vorlage: `.env.example`)
|
| 85 |
+
|
| 86 |
+
> `OPENAI_API_KEY` wird zur Laufzeit **nicht** mehr gebraucht — nur die opt-in
|
| 87 |
+
> Test-Suiten (`RUN_LLM_EVAL`, `RUN_UAT_LLM_JUDGE`) nutzen ihn.
|
| 88 |
+
> `NOTIFY_*` (SMTP/Slack) liegt als GitHub-Secrets bei der Facts-Action — auf dem
|
| 89 |
+
> App-Host nur nötig, falls der Host selbst Alerts verschicken soll.
|
| 90 |
|
| 91 |
---
|
| 92 |
|
|
|
|
| 101 |
|
| 102 |
---
|
| 103 |
|
| 104 |
+
## 7. Zeitgesteuerte Tasks (laufen als GitHub Actions — kein Host-Cron nötig)
|
| 105 |
+
|
| 106 |
+
- [x] **Verifizierte Fakten**: `.github/workflows/update_programme_facts.yml`, täglich 06:23 UTC —
|
| 107 |
+
läuft und ist grün (geprüft 2026-07-04; NOTIFY_*-Secrets im Repo hinterlegt)
|
| 108 |
+
- [x] **Scraping-Refresh**: `.github/workflows/scrape.yml`, wöchentlich So 05:17 UTC — läuft
|
| 109 |
+
- [ ] **Alert-Chain einmal end-to-end testen:** Preis in `data/database/programme_facts.json` ändern →
|
| 110 |
+
Workflow manuell triggern (`gh workflow run update_programme_facts.yml`) →
|
| 111 |
+
E-Mail/Slack muss ankommen → Änderung zurücknehmen
|
| 112 |
+
- [ ] `HUGGING_FACE_API_KEY` erneuern — Docling-Remote-Parsing der Fee-Sheet-PDFs liefert
|
| 113 |
+
aktuell **401** und fällt auf pypdf zurück (Qualität der Ratenplan-PDFs prüfen)
|
| 114 |
+
- [ ] Veralteten Cron auf dem Dev-Mac entfernen (`crontab -e`) — crasht täglich an macOS-TCC
|
| 115 |
+
(`failed to make path absolute`) und ist durch die GitHub Action ersetzt
|
|
|
|
|
|
|
| 116 |
|
| 117 |
---
|
| 118 |
|
|
|
|
| 139 |
|
| 140 |
## 10. Betrieb / Monitoring
|
| 141 |
|
| 142 |
+
- [ ] Facts-Action wöchentlich prüfen (`gh run list --workflow=update_programme_facts.yml`) —
|
| 143 |
+
laufen die Runs durch, sind Diffs plausibel?
|
| 144 |
- [ ] `grep "\[timing\]" logs/logs.log` — Latenz im Blick (Ziel ~6 s end-to-end)
|
| 145 |
- [ ] Weaviate-Cluster-Status (läuft, nicht abgelaufen — Lehre aus dem 404-Ausfall)
|
| 146 |
- [ ] Health-Check `GET /health` in Host-Monitoring eingebunden
|
|
|
|
| 150 |
## Go / No-Go
|
| 151 |
|
| 152 |
**Go**, wenn: Host in EU/CH steht · Datenschutz-Sign-off · Weaviate gefüllt & checkhealth grün ·
|
| 153 |
+
iframe-CSP gefixt & auf Zielseite getestet · beide GitHub Actions grün & Alert getestet · Smoke-Tests grün.
|
| 154 |
|
| 155 |
**No-Go**, wenn: kein DSGVO-Sign-off · Weaviate leer/abgelaufen · CSP blockiert iframe auf `*.unisg.ch` ·
|
| 156 |
SMTP/Slack fehlt (Fakten-Alerts stumm) · LLM-Eval nicht 31/31.
|
requirements.txt
CHANGED
|
@@ -1,15 +1,13 @@
|
|
| 1 |
# Core dependencies
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
langchain>=1.0.2
|
| 3 |
langchain-core>=1.0.1
|
| 4 |
-
langchain-deepseek>=1.0.0
|
| 5 |
-
langchain-groq>=1.0.0
|
| 6 |
-
langchain-huggingface>=1.0.0
|
| 7 |
-
langchain-ollama>=0.3.10
|
| 8 |
langchain-openai>=1.0.1
|
| 9 |
langsmith>=0.4.0
|
| 10 |
|
| 11 |
-
pytest
|
| 12 |
-
|
| 13 |
requests>=2.31.0
|
| 14 |
openai>=1.3.0
|
| 15 |
python-dotenv>=1.0.0
|
|
|
|
| 1 |
# Core dependencies
|
| 2 |
+
# NOTE: only the OpenRouter/OpenAI provider is used at runtime (config.py).
|
| 3 |
+
# The lazy imports in src/rag/models.py for groq/deepseek/ollama/huggingface
|
| 4 |
+
# raise a clear error if one of those providers gets configured again -
|
| 5 |
+
# re-add the matching langchain-* package in that case.
|
| 6 |
langchain>=1.0.2
|
| 7 |
langchain-core>=1.0.1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
langchain-openai>=1.0.1
|
| 9 |
langsmith>=0.4.0
|
| 10 |
|
|
|
|
|
|
|
| 11 |
requests>=2.31.0
|
| 12 |
openai>=1.3.0
|
| 13 |
python-dotenv>=1.0.0
|