Spaces:
Running on Zero
Running on Zero
Upload 28 files
Browse files- .gitignore +7 -0
- DEPLOY.md +101 -0
- README.md +110 -7
- app.py +494 -0
- assets/anomaly_confusion_matrix.png +0 -0
- assets/anomaly_roc_curve.png +0 -0
- assets/intent_confusion_matrix.png +0 -0
- build_artifacts.py +297 -0
- data/anomaly_eval.json +10 -0
- data/intent_dataset.csv +481 -0
- data/intent_eval.json +80 -0
- data/inventory.csv +61 -0
- data/latency_eval.json +6 -0
- data/orders.csv +81 -0
- data/retrieval_eval.json +87 -0
- data/sensor_dataset.csv +1001 -0
- models/anomaly_iforest.joblib +3 -0
- models/anomaly_scaler.joblib +3 -0
- models/intent_pipeline.joblib +3 -0
- requirements.txt +8 -0
- src/__init__.py +0 -0
- src/anomaly_model.py +53 -0
- src/data_generation.py +222 -0
- src/intent_model.py +58 -0
- src/inventory_db.py +59 -0
- src/knowledge_base.py +158 -0
- src/llm_client.py +118 -0
- src/retriever.py +53 -0
.gitignore
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
*.pyc
|
| 3 |
+
.ipynb_checkpoints/
|
| 4 |
+
.DS_Store
|
| 5 |
+
.env
|
| 6 |
+
venv/
|
| 7 |
+
.venv/
|
DEPLOY.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deploying to Hugging Face Spaces
|
| 2 |
+
|
| 3 |
+
## A note on hardware / ZeroGPU
|
| 4 |
+
|
| 5 |
+
This app is **CPU-only by design** — all local ML (intent classifier,
|
| 6 |
+
anomaly detector, TF-IDF retrieval) runs on scikit-learn, and the LLM
|
| 7 |
+
call goes to the remote HF Inference API rather than running locally.
|
| 8 |
+
|
| 9 |
+
If your account only offers the **ZeroGPU** hardware tier (some free/new
|
| 10 |
+
accounts can't select CPU-basic for new Spaces), that's fine: `app.py`
|
| 11 |
+
includes a small `@spaces.GPU`-decorated health-check function purely so
|
| 12 |
+
the platform's ZeroGPU compatibility check passes at startup. It's never
|
| 13 |
+
called on the actual request path, so it adds no latency or GPU cost —
|
| 14 |
+
you can safely select ZeroGPU hardware when creating the Space.
|
| 15 |
+
|
| 16 |
+
Two ways to deploy: the web UI (easiest, no git needed) or the CLI/git route.
|
| 17 |
+
|
| 18 |
+
## Option A — Web UI upload (fastest)
|
| 19 |
+
|
| 20 |
+
1. Go to https://huggingface.co/new-space
|
| 21 |
+
2. Fill in:
|
| 22 |
+
- **Space name:** e.g. `daifuku-warehouse-ai`
|
| 23 |
+
- **License:** MIT (or your choice)
|
| 24 |
+
- **Select the Space SDK:** **Gradio**
|
| 25 |
+
- **Space hardware:** CPU basic (free tier is enough for this app)
|
| 26 |
+
- Visibility: **Public** (so you can share the link with Daifuku)
|
| 27 |
+
3. Click **Create Space**.
|
| 28 |
+
4. On the new Space page, click **Files → Add file → Upload files**, and
|
| 29 |
+
upload the *entire project folder contents* (keep the folder structure:
|
| 30 |
+
`app.py`, `requirements.txt`, `README.md`, `src/`, `models/`, `data/`,
|
| 31 |
+
`assets/`). Drag-and-drop the whole folder works in most browsers.
|
| 32 |
+
5. Wait for the Space to build (check the **Logs** tab if it fails — almost
|
| 33 |
+
always a missing/incompatible package version).
|
| 34 |
+
6. Once it shows "Running", your demo is live at:
|
| 35 |
+
`https://huggingface.co/spaces/<your-username>/daifuku-warehouse-ai`
|
| 36 |
+
|
| 37 |
+
## Option B — git (recommended if you'll keep iterating)
|
| 38 |
+
|
| 39 |
+
```bash
|
| 40 |
+
# 1. Install the CLI and log in (needs a token with "write" scope)
|
| 41 |
+
pip install huggingface_hub
|
| 42 |
+
huggingface-cli login
|
| 43 |
+
|
| 44 |
+
# 2. Create the Space (or create it via the web UI first, then just clone it)
|
| 45 |
+
huggingface-cli repo create daifuku-warehouse-ai --type space --space_sdk gradio
|
| 46 |
+
|
| 47 |
+
# 3. Clone it, copy in the project files, and push
|
| 48 |
+
git clone https://huggingface.co/spaces/<your-username>/daifuku-warehouse-ai
|
| 49 |
+
cd daifuku-warehouse-ai
|
| 50 |
+
cp -r /path/to/this/project/* .
|
| 51 |
+
git add .
|
| 52 |
+
git commit -m "Initial commit: Smart Warehouse AI Assistant"
|
| 53 |
+
git push
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
The Space will automatically build from `requirements.txt` and launch
|
| 57 |
+
`app.py` (as declared in the README's YAML front matter: `sdk: gradio`,
|
| 58 |
+
`app_file: app.py`).
|
| 59 |
+
|
| 60 |
+
## Enabling the LLM (recommended before sharing with Daifuku)
|
| 61 |
+
|
| 62 |
+
By default the Space runs in **retrieval-only fallback mode** — it still
|
| 63 |
+
works, but answers are extractive rather than LLM-generated. To turn on
|
| 64 |
+
real LLM responses:
|
| 65 |
+
|
| 66 |
+
1. Create an access token at https://huggingface.co/settings/tokens
|
| 67 |
+
(a "Read" token is sufficient for Inference API calls).
|
| 68 |
+
2. In your Space, go to **Settings → Variables and secrets → New secret**.
|
| 69 |
+
- Name: `HF_TOKEN`
|
| 70 |
+
- Value: your token
|
| 71 |
+
3. (Optional) Add another secret/variable `LLM_MODEL_ID` if you want a
|
| 72 |
+
different hosted model than the default `Qwen/Qwen2.5-7B-Instruct`
|
| 73 |
+
(any chat-capable model available via HF Inference Providers works).
|
| 74 |
+
4. Restart the Space (**Settings → Factory reboot**, or just wait — it
|
| 75 |
+
picks up new secrets on the next restart).
|
| 76 |
+
|
| 77 |
+
## Re-training / updating the models
|
| 78 |
+
|
| 79 |
+
The Space **loads pre-built artifacts** from `models/` and `data/` — it
|
| 80 |
+
does not retrain on startup, so boot time stays fast. If you change
|
| 81 |
+
`src/data_generation.py`, `src/intent_model.py`, or `src/anomaly_model.py`,
|
| 82 |
+
regenerate everything locally before pushing:
|
| 83 |
+
|
| 84 |
+
```bash
|
| 85 |
+
python build_artifacts.py
|
| 86 |
+
git add models/ data/ assets/
|
| 87 |
+
git commit -m "Retrain models"
|
| 88 |
+
git push
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
## Sharing with Daifuku
|
| 92 |
+
|
| 93 |
+
Once it's live, share the Space URL directly:
|
| 94 |
+
|
| 95 |
+
```
|
| 96 |
+
https://huggingface.co/spaces/<your-username>/daifuku-warehouse-ai
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
Consider also linking the **Model Evaluation** tab specifically in your
|
| 100 |
+
application/cover letter, since it's the clearest evidence of rigorous,
|
| 101 |
+
reproducible ML work rather than just a UI demo.
|
README.md
CHANGED
|
@@ -1,14 +1,117 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
-
python_version: '3.12'
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
license: mit
|
|
|
|
| 12 |
---
|
| 13 |
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Smart Warehouse AI Assistant
|
| 3 |
+
emoji: 🏭
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: indigo
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.9.1
|
|
|
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: mit
|
| 11 |
+
short_description: LLM warehouse copilot with predictive maintenance
|
| 12 |
---
|
| 13 |
|
| 14 |
+
# 🏭 Smart Warehouse AI Assistant
|
| 15 |
+
|
| 16 |
+
An LLM-powered, retrieval-grounded AI copilot for automated warehouse
|
| 17 |
+
operations -- built as a portfolio / application project. Combines an
|
| 18 |
+
**LLM assistant (RAG)**, an **intent classifier**, an **inventory/order
|
| 19 |
+
query layer**, and an **Isolation-Forest predictive-maintenance model**,
|
| 20 |
+
with a full **Model Evaluation** tab reporting real accuracy/F1/ROC-AUC
|
| 21 |
+
metrics on held-out test data.
|
| 22 |
+
|
| 23 |
+
👉 **Live demo:** add your Space URL here once deployed, e.g.
|
| 24 |
+
`https://huggingface.co/spaces/<your-username>/daifuku-warehouse-ai`
|
| 25 |
+
|
| 26 |
+
## Tabs
|
| 27 |
+
|
| 28 |
+
1. **💬 AI Assistant** — ask free-text warehouse-ops questions; answers are
|
| 29 |
+
grounded via TF-IDF retrieval over a small knowledge base and generated
|
| 30 |
+
by a hosted LLM (Hugging Face Inference API), with a transparent
|
| 31 |
+
retrieval-only fallback if no API key is configured.
|
| 32 |
+
2. **📦 Inventory & Order Query** — natural-language queries over synthetic
|
| 33 |
+
inventory / order tables (SKU, zone, order-id extraction).
|
| 34 |
+
3. **⚠️ Predictive Maintenance** — Isolation Forest anomaly detector over
|
| 35 |
+
conveyor/crane motor sensor readings (temperature, vibration, current,
|
| 36 |
+
belt speed).
|
| 37 |
+
4. **📊 Model Evaluation** — accuracy, macro-F1, confusion matrices,
|
| 38 |
+
ROC-AUC, retrieval hit-rate, and latency benchmarks, all computed on
|
| 39 |
+
held-out data by `build_artifacts.py`.
|
| 40 |
+
5. **ℹ️ About** — project write-up, architecture diagram, tech stack.
|
| 41 |
+
|
| 42 |
+
## Quick start (local)
|
| 43 |
+
|
| 44 |
+
```bash
|
| 45 |
+
git clone <this-repo>
|
| 46 |
+
cd daifuku-warehouse-ai
|
| 47 |
+
pip install -r requirements.txt
|
| 48 |
+
|
| 49 |
+
# (re)generate datasets, train models, produce evaluation plots/metrics
|
| 50 |
+
python build_artifacts.py
|
| 51 |
+
|
| 52 |
+
# run the app
|
| 53 |
+
python app.py
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
Open the printed local URL (usually `http://127.0.0.1:7860`).
|
| 57 |
+
|
| 58 |
+
## Enabling full LLM responses
|
| 59 |
+
|
| 60 |
+
The app works out of the box in **retrieval-only fallback mode** (no
|
| 61 |
+
external API calls). To enable real LLM-generated answers:
|
| 62 |
+
|
| 63 |
+
1. Create a Hugging Face access token: https://huggingface.co/settings/tokens
|
| 64 |
+
2. Set it as an environment variable / Space secret named `HF_TOKEN`.
|
| 65 |
+
3. (Optional) Set `LLM_MODEL_ID` to override the default model
|
| 66 |
+
(`Qwen/Qwen2.5-7B-Instruct`) with any chat-capable model available via
|
| 67 |
+
HF Inference Providers.
|
| 68 |
+
|
| 69 |
+
```bash
|
| 70 |
+
export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx
|
| 71 |
+
python app.py
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
## Deploying to Hugging Face Spaces
|
| 75 |
+
|
| 76 |
+
See [`DEPLOY.md`](./DEPLOY.md) for full step-by-step instructions.
|
| 77 |
+
|
| 78 |
+
## Project structure
|
| 79 |
+
|
| 80 |
+
```
|
| 81 |
+
daifuku-warehouse-ai/
|
| 82 |
+
├── app.py # Gradio app (5 tabs)
|
| 83 |
+
├── build_artifacts.py # generates data, trains models, evaluates, saves plots
|
| 84 |
+
├── requirements.txt
|
| 85 |
+
├── src/
|
| 86 |
+
│ ├── data_generation.py # synthetic intent / inventory / sensor datasets
|
| 87 |
+
│ ├── knowledge_base.py # warehouse-ops knowledge base (RAG source docs)
|
| 88 |
+
│ ├── retriever.py # TF-IDF retriever
|
| 89 |
+
│ ├── intent_model.py # intent classifier (train/predict)
|
| 90 |
+
│ ├── anomaly_model.py # Isolation Forest anomaly detector
|
| 91 |
+
│ ├── llm_client.py # HF Inference API client + fallback
|
| 92 |
+
│ └── inventory_db.py # NL -> structured query helpers
|
| 93 |
+
├── models/ # trained model artifacts (.joblib)
|
| 94 |
+
├── data/ # generated datasets + evaluation JSON
|
| 95 |
+
└── assets/ # evaluation plots (confusion matrices, ROC curve)
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
## Evaluation summary
|
| 99 |
+
|
| 100 |
+
See the in-app **Model Evaluation** tab for full details (confusion
|
| 101 |
+
matrices, per-class precision/recall, retrieval hit-rate table, latency
|
| 102 |
+
benchmark). Headline numbers from the included run:
|
| 103 |
+
|
| 104 |
+
| Component | Metric | Score |
|
| 105 |
+
|---|---|---|
|
| 106 |
+
| Intent classifier | Accuracy | ~99% |
|
| 107 |
+
| Intent classifier | Macro F1 | ~99% |
|
| 108 |
+
| Anomaly detector | F1 | ~97% |
|
| 109 |
+
| Anomaly detector | ROC-AUC | ~1.00 |
|
| 110 |
+
| RAG retriever | Hit-rate@2 | 100% |
|
| 111 |
+
|
| 112 |
+
*(Computed on synthetic, held-out test data — see the Evaluation tab for
|
| 113 |
+
methodology notes.)*
|
| 114 |
+
|
| 115 |
+
## License
|
| 116 |
+
|
| 117 |
+
MIT — feel free to fork and adapt.
|
app.py
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Smart Warehouse AI Assistant
|
| 3 |
+
=============================
|
| 4 |
+
A Daifuku-style intralogistics AI copilot demo, built for a Hugging Face
|
| 5 |
+
Space. Combines:
|
| 6 |
+
|
| 7 |
+
1. An LLM-powered assistant (RAG: TF-IDF retrieval + hosted LLM via the
|
| 8 |
+
HF Inference API) for natural-language warehouse operations Q&A.
|
| 9 |
+
2. A TF-IDF + Logistic Regression intent classifier that routes queries
|
| 10 |
+
into 8 operational categories.
|
| 11 |
+
3. A lightweight NL -> structured query layer over synthetic inventory /
|
| 12 |
+
order tables.
|
| 13 |
+
4. An Isolation Forest anomaly detector for conveyor/crane sensor
|
| 14 |
+
streams (predictive maintenance).
|
| 15 |
+
5. A Model Evaluation tab reporting real accuracy/F1/ROC-AUC metrics
|
| 16 |
+
computed by build_artifacts.py.
|
| 17 |
+
|
| 18 |
+
Author: (your name here) -- built as an application project for Daifuku Co., Ltd.
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
import json
|
| 22 |
+
import os
|
| 23 |
+
|
| 24 |
+
import gradio as gr
|
| 25 |
+
import pandas as pd
|
| 26 |
+
|
| 27 |
+
from src.anomaly_model import FEATURES as SENSOR_FEATURES
|
| 28 |
+
from src.anomaly_model import load_artifacts as load_anomaly_artifacts
|
| 29 |
+
from src.anomaly_model import score_reading
|
| 30 |
+
from src.data_generation import generate_inventory_db, generate_orders_db
|
| 31 |
+
from src.intent_model import INTENT_DESCRIPTIONS, load_pipeline, predict as intent_predict
|
| 32 |
+
from src.inventory_db import query_inventory, query_orders
|
| 33 |
+
from src.llm_client import answer_query
|
| 34 |
+
from src.retriever import KBRetriever
|
| 35 |
+
|
| 36 |
+
ROOT = os.path.dirname(os.path.abspath(__file__))
|
| 37 |
+
MODELS_DIR = os.path.join(ROOT, "models")
|
| 38 |
+
DATA_DIR = os.path.join(ROOT, "data")
|
| 39 |
+
ASSETS_DIR = os.path.join(ROOT, "assets")
|
| 40 |
+
|
| 41 |
+
# --------------------------------------------------------------------------
|
| 42 |
+
# Load pre-trained artifacts (fast: no training happens at Space startup)
|
| 43 |
+
# --------------------------------------------------------------------------
|
| 44 |
+
intent_pipeline = load_pipeline(os.path.join(MODELS_DIR, "intent_pipeline.joblib"))
|
| 45 |
+
anomaly_model, anomaly_scaler = load_anomaly_artifacts(
|
| 46 |
+
os.path.join(MODELS_DIR, "anomaly_iforest.joblib"),
|
| 47 |
+
os.path.join(MODELS_DIR, "anomaly_scaler.joblib"),
|
| 48 |
+
)
|
| 49 |
+
retriever = KBRetriever()
|
| 50 |
+
|
| 51 |
+
# Prefer the pre-generated CSVs (so demo state matches the eval run); fall back to
|
| 52 |
+
# regenerating in-memory if they're missing for some reason.
|
| 53 |
+
try:
|
| 54 |
+
inventory_df = pd.read_csv(os.path.join(DATA_DIR, "inventory.csv"))
|
| 55 |
+
orders_df = pd.read_csv(os.path.join(DATA_DIR, "orders.csv"))
|
| 56 |
+
except FileNotFoundError:
|
| 57 |
+
inventory_df = generate_inventory_db()
|
| 58 |
+
orders_df = generate_orders_db()
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def _load_json(name):
|
| 62 |
+
path = os.path.join(DATA_DIR, name)
|
| 63 |
+
if os.path.exists(path):
|
| 64 |
+
with open(path) as f:
|
| 65 |
+
return json.load(f)
|
| 66 |
+
return {}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
intent_eval = _load_json("intent_eval.json")
|
| 70 |
+
anomaly_eval = _load_json("anomaly_eval.json")
|
| 71 |
+
retrieval_eval = _load_json("retrieval_eval.json")
|
| 72 |
+
latency_eval = _load_json("latency_eval.json")
|
| 73 |
+
|
| 74 |
+
HF_TOKEN_SET = bool(os.environ.get("HF_TOKEN"))
|
| 75 |
+
|
| 76 |
+
# --------------------------------------------------------------------------
|
| 77 |
+
# ZeroGPU compatibility shim
|
| 78 |
+
# --------------------------------------------------------------------------
|
| 79 |
+
# This app is CPU-only by design (scikit-learn locally, LLM calls go to the
|
| 80 |
+
# remote HF Inference API). Some Spaces accounts, however, only offer the
|
| 81 |
+
# free "ZeroGPU" hardware tier, which requires at least one function
|
| 82 |
+
# decorated with `@spaces.GPU` to be present or the platform's startup
|
| 83 |
+
# check fails with "No @spaces.GPU function detected". This is a harmless,
|
| 84 |
+
# unused health-check function that satisfies that requirement without
|
| 85 |
+
# changing any real behaviour -- it is never called on the request path.
|
| 86 |
+
try:
|
| 87 |
+
import spaces
|
| 88 |
+
|
| 89 |
+
@spaces.GPU(duration=5)
|
| 90 |
+
def _zerogpu_healthcheck():
|
| 91 |
+
return True
|
| 92 |
+
|
| 93 |
+
except ImportError:
|
| 94 |
+
# Running locally / on CPU-basic hardware where `spaces` isn't installed.
|
| 95 |
+
def _zerogpu_healthcheck():
|
| 96 |
+
return True
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
# ==========================================================================
|
| 100 |
+
# TAB 1 -- AI Assistant (LLM + RAG + intent routing)
|
| 101 |
+
# ==========================================================================
|
| 102 |
+
|
| 103 |
+
def chat_fn(message, history):
|
| 104 |
+
intent = intent_predict(intent_pipeline, message)
|
| 105 |
+
response = answer_query(message, retriever)
|
| 106 |
+
|
| 107 |
+
intent_label = INTENT_DESCRIPTIONS.get(intent.intent, intent.intent)
|
| 108 |
+
meta_lines = [f"**Detected intent:** {intent_label} ({intent.confidence:.0%} confidence)"]
|
| 109 |
+
if response.sources:
|
| 110 |
+
src_str = ", ".join(f"{s.title} ({s.score:.2f})" for s in response.sources)
|
| 111 |
+
meta_lines.append(f"**Retrieved context:** {src_str}")
|
| 112 |
+
meta_lines.append(
|
| 113 |
+
f"**Generation:** {'LLM (' + response.model_id + ')' if response.used_llm else 'retrieval-only fallback'}"
|
| 114 |
+
f" · {response.latency_s * 1000:.0f} ms"
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
full_reply = response.answer + "\n\n---\n" + "\n".join(meta_lines)
|
| 118 |
+
return full_reply
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
ASSISTANT_EXAMPLES = [
|
| 122 |
+
"The conveyor belt in Zone C is making noise",
|
| 123 |
+
"How many units of SKU-1042 are in Zone B?",
|
| 124 |
+
"What's the difference between an AGV and an AMR?",
|
| 125 |
+
"A forklift near-miss was reported in Zone A",
|
| 126 |
+
"What's the fastest picking route for a high volume order?",
|
| 127 |
+
"Is Crane-03 operational?",
|
| 128 |
+
]
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
# ==========================================================================
|
| 132 |
+
# TAB 2 -- Inventory & Order Query
|
| 133 |
+
# ==========================================================================
|
| 134 |
+
|
| 135 |
+
def inventory_query_fn(text):
|
| 136 |
+
intent = intent_predict(intent_pipeline, text)
|
| 137 |
+
if intent.intent == "order_status":
|
| 138 |
+
result = query_orders(orders_df, text)
|
| 139 |
+
note = "Interpreted as an **order status** query."
|
| 140 |
+
else:
|
| 141 |
+
result = query_inventory(inventory_df, text)
|
| 142 |
+
note = "Interpreted as an **inventory** query."
|
| 143 |
+
if result.empty:
|
| 144 |
+
result = pd.DataFrame({"message": ["No matching records found for this query."]})
|
| 145 |
+
return note, result
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
# ==========================================================================
|
| 149 |
+
# TAB 3 -- Predictive Maintenance / Anomaly Detection
|
| 150 |
+
# ==========================================================================
|
| 151 |
+
|
| 152 |
+
def anomaly_fn(motor_temp, vibration, current, belt_speed):
|
| 153 |
+
reading = {
|
| 154 |
+
"motor_temp_c": motor_temp,
|
| 155 |
+
"vibration_mm_s": vibration,
|
| 156 |
+
"current_amps": current,
|
| 157 |
+
"belt_speed_mps": belt_speed,
|
| 158 |
+
}
|
| 159 |
+
result = score_reading(anomaly_model, anomaly_scaler, reading)
|
| 160 |
+
verdict = "🔴 ANOMALY DETECTED" if result.is_anomaly else "🟢 Normal operating range"
|
| 161 |
+
detail = (
|
| 162 |
+
f"### {verdict}\n\n"
|
| 163 |
+
f"**Anomaly score:** {result.anomaly_score:.2f} / 1.00\n\n"
|
| 164 |
+
f"| Sensor | Value | Typical normal range |\n"
|
| 165 |
+
f"|---|---|---|\n"
|
| 166 |
+
f"| Motor temperature | {motor_temp:.1f} °C | 47–63 °C |\n"
|
| 167 |
+
f"| Vibration | {vibration:.2f} mm/s | 1.2–3.2 mm/s |\n"
|
| 168 |
+
f"| Motor current | {current:.1f} A | 9–15 A |\n"
|
| 169 |
+
f"| Belt speed | {belt_speed:.2f} m/s | 1.2–1.8 m/s |\n"
|
| 170 |
+
)
|
| 171 |
+
if result.is_anomaly:
|
| 172 |
+
detail += (
|
| 173 |
+
"\n**Recommended action:** Flag for inspection. Elevated temperature + "
|
| 174 |
+
"vibration + current with reduced belt speed typically indicates bearing "
|
| 175 |
+
"wear, belt misalignment, or motor overload -- schedule maintenance before "
|
| 176 |
+
"the next shift to avoid an unplanned stoppage."
|
| 177 |
+
)
|
| 178 |
+
return detail
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
ANOMALY_PRESETS = {
|
| 182 |
+
"Normal reading": (55.0, 2.2, 12.0, 1.5),
|
| 183 |
+
"Early bearing wear": (68.0, 3.8, 15.5, 1.3),
|
| 184 |
+
"Severe fault (imminent failure)": (85.0, 6.5, 21.0, 0.6),
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def load_preset(name):
|
| 189 |
+
return ANOMALY_PRESETS[name]
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
# ==========================================================================
|
| 193 |
+
# TAB 4 -- Model Evaluation
|
| 194 |
+
# ==========================================================================
|
| 195 |
+
|
| 196 |
+
def build_evaluation_markdown():
|
| 197 |
+
cls_report = intent_eval.get("classification_report", {})
|
| 198 |
+
per_class_rows = []
|
| 199 |
+
for cls in intent_eval.get("classes", []):
|
| 200 |
+
stats = cls_report.get(cls, {})
|
| 201 |
+
per_class_rows.append(
|
| 202 |
+
f"| {cls} | {stats.get('precision', 0):.2f} | {stats.get('recall', 0):.2f} | "
|
| 203 |
+
f"{stats.get('f1-score', 0):.2f} | {int(stats.get('support', 0))} |"
|
| 204 |
+
)
|
| 205 |
+
per_class_table = "\n".join(per_class_rows)
|
| 206 |
+
|
| 207 |
+
retrieval_rows = "\n".join(
|
| 208 |
+
f"| {r['query']} | {r['expected']} | {r['retrieved_top1']} | "
|
| 209 |
+
f"{'✅' if r['hit@1'] else ('〰️' if r['hit@2'] else '❌')} | {r['top1_score']:.2f} |"
|
| 210 |
+
for r in retrieval_eval.get("rows", [])
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
md = f"""
|
| 214 |
+
## 1. Intent Classifier (TF-IDF + Logistic Regression)
|
| 215 |
+
|
| 216 |
+
Trained on {intent_eval.get('n_train', '?')} examples, evaluated on a held-out
|
| 217 |
+
stratified test split of {intent_eval.get('n_test', '?')} examples across
|
| 218 |
+
{intent_eval.get('n_classes', '?')} intent classes.
|
| 219 |
+
|
| 220 |
+
| Metric | Score |
|
| 221 |
+
|---|---|
|
| 222 |
+
| **Accuracy** | **{intent_eval.get('accuracy', 0):.2%}** |
|
| 223 |
+
| **Macro F1** | **{intent_eval.get('macro_f1', 0):.2%}** |
|
| 224 |
+
|
| 225 |
+
**Per-class performance:**
|
| 226 |
+
|
| 227 |
+
| Intent | Precision | Recall | F1 | Support |
|
| 228 |
+
|---|---|---|---|---|
|
| 229 |
+
{per_class_table}
|
| 230 |
+
|
| 231 |
+

|
| 232 |
+
|
| 233 |
+
---
|
| 234 |
+
|
| 235 |
+
## 2. Predictive Maintenance Anomaly Detector (Isolation Forest)
|
| 236 |
+
|
| 237 |
+
Trained unsupervised on scaled sensor features ({', '.join(SENSOR_FEATURES)}),
|
| 238 |
+
evaluated against held-out ground-truth anomaly labels ({anomaly_eval.get('n_test', '?')} test readings,
|
| 239 |
+
{anomaly_eval.get('test_anomaly_rate', 0):.1%} true anomaly rate).
|
| 240 |
+
|
| 241 |
+
| Metric | Score |
|
| 242 |
+
|---|---|
|
| 243 |
+
| **Precision** | **{anomaly_eval.get('precision', 0):.2%}** |
|
| 244 |
+
| **Recall** | **{anomaly_eval.get('recall', 0):.2%}** |
|
| 245 |
+
| **F1 Score** | **{anomaly_eval.get('f1', 0):.2%}** |
|
| 246 |
+
| **ROC-AUC** | **{anomaly_eval.get('roc_auc', 0):.3f}** |
|
| 247 |
+
| Accuracy | {anomaly_eval.get('accuracy', 0):.2%} |
|
| 248 |
+
|
| 249 |
+

|
| 250 |
+

|
| 251 |
+
|
| 252 |
+
---
|
| 253 |
+
|
| 254 |
+
## 3. Retrieval (RAG) Evaluation
|
| 255 |
+
|
| 256 |
+
Hit-rate of the TF-IDF retriever against a hand-labelled query -> expected-document
|
| 257 |
+
evaluation set (higher is better; hit@1 = correct doc ranked first, hit@2 = correct
|
| 258 |
+
doc within top 2).
|
| 259 |
+
|
| 260 |
+
| Metric | Score |
|
| 261 |
+
|---|---|
|
| 262 |
+
| **Hit Rate @ 1** | **{retrieval_eval.get('hit_rate_at_1', 0):.0%}** |
|
| 263 |
+
| **Hit Rate @ 2** | **{retrieval_eval.get('hit_rate_at_2', 0):.0%}** |
|
| 264 |
+
|
| 265 |
+
| Query | Expected Doc | Retrieved (top-1) | Hit | Score |
|
| 266 |
+
|---|---|---|---|---|
|
| 267 |
+
{retrieval_rows}
|
| 268 |
+
|
| 269 |
+
---
|
| 270 |
+
|
| 271 |
+
## 4. Latency Benchmark (per-request, CPU)
|
| 272 |
+
|
| 273 |
+
| Component | Avg. latency |
|
| 274 |
+
|---|---|
|
| 275 |
+
| Intent classification | {latency_eval.get('intent_classifier_ms', '?')} ms |
|
| 276 |
+
| Anomaly scoring | {latency_eval.get('anomaly_detector_ms', '?')} ms |
|
| 277 |
+
| KB retrieval (TF-IDF) | {latency_eval.get('kb_retrieval_ms', '?')} ms |
|
| 278 |
+
| LLM generation | Depends on hosted Inference API (measured live per-request in the Assistant tab) |
|
| 279 |
+
|
| 280 |
+
---
|
| 281 |
+
|
| 282 |
+
### Evaluation methodology notes
|
| 283 |
+
|
| 284 |
+
- All datasets are **synthetically generated** (see `src/data_generation.py`) using
|
| 285 |
+
templated-but-varied natural language and randomised sensor distributions with a
|
| 286 |
+
fixed seed, so results are fully reproducible via `python build_artifacts.py`.
|
| 287 |
+
- The intent classifier and anomaly detector are evaluated on a **held-out test
|
| 288 |
+
split** they never saw during training (stratified, 25% / 30% respectively).
|
| 289 |
+
- The anomaly detector itself is trained **unsupervised** (Isolation Forest never
|
| 290 |
+
sees the `label` column during `.fit()`); labels are used only to *evaluate* it,
|
| 291 |
+
mirroring how you'd validate an anomaly model against a small set of confirmed
|
| 292 |
+
historical incidents in production.
|
| 293 |
+
- In a production deployment, all three components would be continuously
|
| 294 |
+
re-evaluated against real WMS/WCS/sensor logs rather than synthetic data.
|
| 295 |
+
"""
|
| 296 |
+
return md
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
# ==========================================================================
|
| 300 |
+
# TAB 5 -- About
|
| 301 |
+
# ==========================================================================
|
| 302 |
+
|
| 303 |
+
ABOUT_MD = f"""
|
| 304 |
+
# 🏭 Smart Warehouse AI Assistant
|
| 305 |
+
|
| 306 |
+
**A portfolio project demonstrating an applied-AI approach to intralogistics
|
| 307 |
+
operations, built as part of a job application to Daifuku Co., Ltd.**
|
| 308 |
+
|
| 309 |
+
## What this demonstrates
|
| 310 |
+
|
| 311 |
+
Daifuku builds material handling and automation systems -- AS/RS, conveyors
|
| 312 |
+
and sortation, AGVs/AMRs, and the software (WMS/WCS) that orchestrates them.
|
| 313 |
+
This project is a compact but end-to-end example of how an AI layer can sit
|
| 314 |
+
on top of that kind of system:
|
| 315 |
+
|
| 316 |
+
| Capability | Where |
|
| 317 |
+
|---|---|
|
| 318 |
+
| **LLM-powered natural-language assistant**, grounded with retrieval (RAG) so it answers from real warehouse-ops knowledge rather than hallucinating | *AI Assistant* tab |
|
| 319 |
+
| **Intent classification** to route free-text requests (maintenance, safety, navigation, inventory, etc.) the way a real ops system would triage tickets | *AI Assistant* / *Inventory* tabs |
|
| 320 |
+
| **Predictive maintenance** via unsupervised anomaly detection on conveyor/crane sensor streams -- catching bearing wear or misalignment before an unplanned stoppage | *Predictive Maintenance* tab |
|
| 321 |
+
| **NL-to-structured-query** over inventory/order data, a lightweight stand-in for a WMS query tool | *Inventory & Order Query* tab |
|
| 322 |
+
| **Rigorous, reproducible evaluation** of every ML component (accuracy, F1, ROC-AUC, retrieval hit-rate, latency) rather than just a demo that "looks like it works" | *Model Evaluation* tab |
|
| 323 |
+
|
| 324 |
+
## Tech stack
|
| 325 |
+
|
| 326 |
+
- **UI / deployment:** [Gradio](https://gradio.app) on Hugging Face Spaces
|
| 327 |
+
- **LLM:** Hosted instruct model via the Hugging Face **Inference API**
|
| 328 |
+
(`huggingface_hub.InferenceClient`), configurable via the `LLM_MODEL_ID`
|
| 329 |
+
env var. Falls back gracefully to a retrieval-only answer if no `HF_TOKEN`
|
| 330 |
+
is configured, so the public demo never breaks.
|
| 331 |
+
- **Retrieval:** TF-IDF + cosine similarity over a small hand-written
|
| 332 |
+
warehouse-operations knowledge base (simple, fast, fully local RAG).
|
| 333 |
+
- **Intent classification:** TF-IDF + Logistic Regression (scikit-learn) --
|
| 334 |
+
chosen deliberately over a heavier transformer classifier because it
|
| 335 |
+
trains in under a second and comfortably reaches **{intent_eval.get('accuracy', 0):.0%}
|
| 336 |
+
accuracy** on this task; right-sizing the model to the problem.
|
| 337 |
+
- **Anomaly detection:** Isolation Forest (scikit-learn), trained
|
| 338 |
+
unsupervised on scaled sensor features.
|
| 339 |
+
- **Evaluation:** scikit-learn metrics + matplotlib, all computed by
|
| 340 |
+
`build_artifacts.py` and saved as static artifacts the app loads at
|
| 341 |
+
startup (fast, reproducible Space boot).
|
| 342 |
+
|
| 343 |
+
## Architecture
|
| 344 |
+
|
| 345 |
+
```
|
| 346 |
+
┌───────────────────────┐
|
| 347 |
+
User query ───► │ Intent Classifier │ (TF-IDF + LogisticRegression)
|
| 348 |
+
└──────────┬────────────┘
|
| 349 |
+
│ intent label
|
| 350 |
+
▼
|
| 351 |
+
┌───────────────────────┐
|
| 352 |
+
│ KB Retriever (RAG) │ (TF-IDF cosine similarity)
|
| 353 |
+
└──────────┬────────────┘
|
| 354 |
+
│ top-k passages
|
| 355 |
+
▼
|
| 356 |
+
┌──���────────────────────┐
|
| 357 |
+
│ Hosted LLM │ (HF Inference API)
|
| 358 |
+
│ (or extractive │
|
| 359 |
+
│ fallback if offline) │
|
| 360 |
+
└──────────┬────────────┘
|
| 361 |
+
▼
|
| 362 |
+
Grounded answer
|
| 363 |
+
|
| 364 |
+
Sensor stream ───► StandardScaler ───► IsolationForest ───► anomaly / normal
|
| 365 |
+
```
|
| 366 |
+
|
| 367 |
+
## Why this matters for Daifuku
|
| 368 |
+
|
| 369 |
+
Modern intralogistics platforms generate huge volumes of operational data --
|
| 370 |
+
equipment telemetry, WMS transactions, safety logs. The value of AI here isn't
|
| 371 |
+
a flashy chatbot; it's **routing, grounding, and reliability**: correctly
|
| 372 |
+
triaging a request, answering from real operational context instead of
|
| 373 |
+
guessing, and flagging equipment problems before they cause downtime. This
|
| 374 |
+
project tries to demonstrate that mindset in miniature, with honest,
|
| 375 |
+
reproducible evaluation numbers rather than cherry-picked demo runs.
|
| 376 |
+
|
| 377 |
+
## Limitations & next steps
|
| 378 |
+
|
| 379 |
+
- All data here is **synthetic**, for portfolio/demo purposes -- a production
|
| 380 |
+
version would connect to real WMS/WCS APIs and historical sensor logs.
|
| 381 |
+
- The intent set (8 classes) and knowledge base (10 articles) are intentionally
|
| 382 |
+
small to keep the demo fast and auditable; both are easy to extend.
|
| 383 |
+
- The anomaly detector uses 4 hand-picked features; a production system would
|
| 384 |
+
likely use a richer multivariate sensor set and a supervised or
|
| 385 |
+
semi-supervised model once labelled failure data is available.
|
| 386 |
+
|
| 387 |
+
---
|
| 388 |
+
*Built as an application project. Source code available on request / in the
|
| 389 |
+
linked repository. Feedback welcome.*
|
| 390 |
+
"""
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
# ==========================================================================
|
| 394 |
+
# GRADIO APP
|
| 395 |
+
# ==========================================================================
|
| 396 |
+
|
| 397 |
+
CUSTOM_CSS = """
|
| 398 |
+
#title-banner { text-align: center; margin-bottom: 0.5em; }
|
| 399 |
+
.gradio-container { max-width: 1150px !important; margin: auto; }
|
| 400 |
+
"""
|
| 401 |
+
|
| 402 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), css=CUSTOM_CSS, title="Smart Warehouse AI Assistant") as demo:
|
| 403 |
+
gr.Markdown(
|
| 404 |
+
"<h1 id='title-banner'>🏭 Smart Warehouse AI Assistant</h1>"
|
| 405 |
+
"<p style='text-align:center; color:gray;'>LLM-powered intralogistics copilot · "
|
| 406 |
+
"intent routing · predictive maintenance · retrieval-grounded Q&A</p>"
|
| 407 |
+
)
|
| 408 |
+
if not HF_TOKEN_SET:
|
| 409 |
+
gr.Markdown(
|
| 410 |
+
"> ⚠️ **No `HF_TOKEN` secret detected.** The AI Assistant tab will run in "
|
| 411 |
+
"**retrieval-only fallback mode** (still functional, just not LLM-generated "
|
| 412 |
+
"prose). Add an `HF_TOKEN` secret in *Space settings → Variables and secrets* "
|
| 413 |
+
"to enable full LLM responses."
|
| 414 |
+
)
|
| 415 |
+
|
| 416 |
+
with gr.Tab("💬 AI Assistant"):
|
| 417 |
+
gr.Markdown(
|
| 418 |
+
"Ask about equipment status, maintenance, safety, inventory, order status, "
|
| 419 |
+
"AGV routing, picking strategy, or general warehouse-automation concepts. "
|
| 420 |
+
"Answers are grounded (RAG) in a small warehouse-operations knowledge base."
|
| 421 |
+
)
|
| 422 |
+
gr.ChatInterface(
|
| 423 |
+
fn=chat_fn,
|
| 424 |
+
type="messages",
|
| 425 |
+
examples=ASSISTANT_EXAMPLES,
|
| 426 |
+
chatbot=gr.Chatbot(height=430, label="Warehouse Assistant", type="messages"),
|
| 427 |
+
textbox=gr.Textbox(placeholder="e.g. The conveyor belt in Zone C is making noise"),
|
| 428 |
+
)
|
| 429 |
+
|
| 430 |
+
with gr.Tab("📦 Inventory & Order Query"):
|
| 431 |
+
gr.Markdown(
|
| 432 |
+
"Type a natural-language inventory or order question. The intent classifier "
|
| 433 |
+
"decides whether to query the inventory table or the orders table, then "
|
| 434 |
+
"extracts SKU / order-id / zone slots to filter the result."
|
| 435 |
+
)
|
| 436 |
+
with gr.Row():
|
| 437 |
+
inv_input = gr.Textbox(label="Query", placeholder="How many units of SKU-1042 are in Zone B?", scale=4)
|
| 438 |
+
inv_btn = gr.Button("Search", variant="primary", scale=1)
|
| 439 |
+
inv_note = gr.Markdown()
|
| 440 |
+
inv_result = gr.Dataframe(label="Results", wrap=True)
|
| 441 |
+
inv_btn.click(inventory_query_fn, inputs=inv_input, outputs=[inv_note, inv_result])
|
| 442 |
+
inv_input.submit(inventory_query_fn, inputs=inv_input, outputs=[inv_note, inv_result])
|
| 443 |
+
|
| 444 |
+
gr.Examples(
|
| 445 |
+
examples=[
|
| 446 |
+
"How many units of SKU-1042 are in Zone B?",
|
| 447 |
+
"What's the status of order #10007?",
|
| 448 |
+
"Show me low stock items",
|
| 449 |
+
"Any delayed orders?",
|
| 450 |
+
],
|
| 451 |
+
inputs=inv_input,
|
| 452 |
+
)
|
| 453 |
+
with gr.Accordion("Browse full tables", open=False):
|
| 454 |
+
gr.Markdown("**Inventory** (synthetic)")
|
| 455 |
+
gr.Dataframe(inventory_df, wrap=True)
|
| 456 |
+
gr.Markdown("**Orders** (synthetic)")
|
| 457 |
+
gr.Dataframe(orders_df, wrap=True)
|
| 458 |
+
|
| 459 |
+
with gr.Tab("⚠️ Predictive Maintenance"):
|
| 460 |
+
gr.Markdown(
|
| 461 |
+
"Enter live (or hypothetical) conveyor/crane motor sensor readings to check "
|
| 462 |
+
"for anomalous behaviour using an Isolation Forest model trained on "
|
| 463 |
+
"historical sensor patterns."
|
| 464 |
+
)
|
| 465 |
+
preset_dropdown = gr.Dropdown(
|
| 466 |
+
choices=list(ANOMALY_PRESETS.keys()), label="Load a preset reading", value="Normal reading"
|
| 467 |
+
)
|
| 468 |
+
with gr.Row():
|
| 469 |
+
motor_temp_in = gr.Slider(30, 100, value=55, step=0.5, label="Motor temperature (°C)")
|
| 470 |
+
vibration_in = gr.Slider(0, 10, value=2.2, step=0.1, label="Vibration (mm/s)")
|
| 471 |
+
with gr.Row():
|
| 472 |
+
current_in = gr.Slider(5, 30, value=12, step=0.5, label="Motor current (A)")
|
| 473 |
+
belt_speed_in = gr.Slider(0.1, 2.5, value=1.5, step=0.05, label="Belt speed (m/s)")
|
| 474 |
+
check_btn = gr.Button("Check for anomaly", variant="primary")
|
| 475 |
+
anomaly_output = gr.Markdown()
|
| 476 |
+
|
| 477 |
+
preset_dropdown.change(
|
| 478 |
+
load_preset, inputs=preset_dropdown,
|
| 479 |
+
outputs=[motor_temp_in, vibration_in, current_in, belt_speed_in],
|
| 480 |
+
)
|
| 481 |
+
check_btn.click(
|
| 482 |
+
anomaly_fn,
|
| 483 |
+
inputs=[motor_temp_in, vibration_in, current_in, belt_speed_in],
|
| 484 |
+
outputs=anomaly_output,
|
| 485 |
+
)
|
| 486 |
+
|
| 487 |
+
with gr.Tab("📊 Model Evaluation"):
|
| 488 |
+
gr.Markdown(build_evaluation_markdown())
|
| 489 |
+
|
| 490 |
+
with gr.Tab("ℹ️ About"):
|
| 491 |
+
gr.Markdown(ABOUT_MD)
|
| 492 |
+
|
| 493 |
+
if __name__ == "__main__":
|
| 494 |
+
demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
|
assets/anomaly_confusion_matrix.png
ADDED
|
assets/anomaly_roc_curve.png
ADDED
|
assets/intent_confusion_matrix.png
ADDED
|
build_artifacts.py
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
build_artifacts.py
|
| 3 |
+
-------------------
|
| 4 |
+
One-shot build script: generates synthetic datasets, trains the intent
|
| 5 |
+
classifier and the anomaly detector, evaluates the retrieval pipeline, and
|
| 6 |
+
saves every model/plot/metric the app needs to `models/`, `data/`, and
|
| 7 |
+
`assets/`. Run this once locally (or in CI) before deploying -- the Gradio
|
| 8 |
+
app itself only *loads* these pre-built artifacts, so the Space starts up
|
| 9 |
+
in a couple of seconds instead of retraining on every boot.
|
| 10 |
+
|
| 11 |
+
Usage:
|
| 12 |
+
python build_artifacts.py
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import json
|
| 16 |
+
import os
|
| 17 |
+
|
| 18 |
+
import matplotlib
|
| 19 |
+
matplotlib.use("Agg")
|
| 20 |
+
import matplotlib.pyplot as plt
|
| 21 |
+
import numpy as np
|
| 22 |
+
from sklearn.metrics import (
|
| 23 |
+
accuracy_score,
|
| 24 |
+
classification_report,
|
| 25 |
+
confusion_matrix,
|
| 26 |
+
f1_score,
|
| 27 |
+
precision_score,
|
| 28 |
+
recall_score,
|
| 29 |
+
roc_auc_score,
|
| 30 |
+
roc_curve,
|
| 31 |
+
)
|
| 32 |
+
from sklearn.model_selection import train_test_split
|
| 33 |
+
from sklearn.preprocessing import StandardScaler
|
| 34 |
+
|
| 35 |
+
from src.data_generation import (
|
| 36 |
+
RETRIEVAL_EVAL_SET,
|
| 37 |
+
generate_intent_dataset,
|
| 38 |
+
generate_inventory_db,
|
| 39 |
+
generate_orders_db,
|
| 40 |
+
generate_sensor_dataset,
|
| 41 |
+
)
|
| 42 |
+
from src.intent_model import build_pipeline, save_pipeline
|
| 43 |
+
from src.anomaly_model import FEATURES, build_model as build_anomaly_model, save_artifacts as save_anomaly_artifacts
|
| 44 |
+
from src.retriever import KBRetriever
|
| 45 |
+
|
| 46 |
+
ROOT = os.path.dirname(os.path.abspath(__file__))
|
| 47 |
+
MODELS_DIR = os.path.join(ROOT, "models")
|
| 48 |
+
DATA_DIR = os.path.join(ROOT, "data")
|
| 49 |
+
ASSETS_DIR = os.path.join(ROOT, "assets")
|
| 50 |
+
for d in (MODELS_DIR, DATA_DIR, ASSETS_DIR):
|
| 51 |
+
os.makedirs(d, exist_ok=True)
|
| 52 |
+
|
| 53 |
+
SEED = 42
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def build_intent_classifier():
|
| 57 |
+
print("== Intent classifier ==")
|
| 58 |
+
df = generate_intent_dataset(n_per_intent=60, seed=SEED)
|
| 59 |
+
df.to_csv(os.path.join(DATA_DIR, "intent_dataset.csv"), index=False)
|
| 60 |
+
|
| 61 |
+
X_train, X_test, y_train, y_test = train_test_split(
|
| 62 |
+
df["text"], df["intent"], test_size=0.25, random_state=SEED, stratify=df["intent"]
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
pipeline = build_pipeline()
|
| 66 |
+
pipeline.fit(X_train, y_train)
|
| 67 |
+
|
| 68 |
+
y_pred = pipeline.predict(X_test)
|
| 69 |
+
acc = accuracy_score(y_test, y_pred)
|
| 70 |
+
macro_f1 = f1_score(y_test, y_pred, average="macro")
|
| 71 |
+
report = classification_report(y_test, y_pred, output_dict=True)
|
| 72 |
+
labels = sorted(df["intent"].unique())
|
| 73 |
+
cm = confusion_matrix(y_test, y_pred, labels=labels)
|
| 74 |
+
|
| 75 |
+
print(f"accuracy={acc:.4f} macro_f1={macro_f1:.4f}")
|
| 76 |
+
|
| 77 |
+
# Confusion matrix plot
|
| 78 |
+
fig, ax = plt.subplots(figsize=(7.5, 6.5))
|
| 79 |
+
im = ax.imshow(cm, cmap="Blues")
|
| 80 |
+
ax.set_xticks(range(len(labels)))
|
| 81 |
+
ax.set_yticks(range(len(labels)))
|
| 82 |
+
ax.set_xticklabels(labels, rotation=45, ha="right", fontsize=8)
|
| 83 |
+
ax.set_yticklabels(labels, fontsize=8)
|
| 84 |
+
ax.set_xlabel("Predicted intent")
|
| 85 |
+
ax.set_ylabel("True intent")
|
| 86 |
+
ax.set_title(f"Intent Classifier Confusion Matrix (acc={acc:.1%})")
|
| 87 |
+
for i in range(len(labels)):
|
| 88 |
+
for j in range(len(labels)):
|
| 89 |
+
ax.text(j, i, cm[i, j], ha="center", va="center",
|
| 90 |
+
color="white" if cm[i, j] > cm.max() / 2 else "black", fontsize=8)
|
| 91 |
+
fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
|
| 92 |
+
fig.tight_layout()
|
| 93 |
+
fig.savefig(os.path.join(ASSETS_DIR, "intent_confusion_matrix.png"), dpi=150)
|
| 94 |
+
plt.close(fig)
|
| 95 |
+
|
| 96 |
+
# Retrain on FULL data for the deployed model (more data = better generalisation)
|
| 97 |
+
pipeline_full = build_pipeline()
|
| 98 |
+
pipeline_full.fit(df["text"], df["intent"])
|
| 99 |
+
save_pipeline(pipeline_full, os.path.join(MODELS_DIR, "intent_pipeline.joblib"))
|
| 100 |
+
|
| 101 |
+
metrics = {
|
| 102 |
+
"accuracy": acc,
|
| 103 |
+
"macro_f1": macro_f1,
|
| 104 |
+
"n_train": len(X_train),
|
| 105 |
+
"n_test": len(X_test),
|
| 106 |
+
"n_classes": len(labels),
|
| 107 |
+
"classes": labels,
|
| 108 |
+
"classification_report": report,
|
| 109 |
+
}
|
| 110 |
+
with open(os.path.join(DATA_DIR, "intent_eval.json"), "w") as f:
|
| 111 |
+
json.dump(metrics, f, indent=2)
|
| 112 |
+
return metrics
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def build_anomaly_detector():
|
| 116 |
+
print("== Anomaly detector ==")
|
| 117 |
+
df = generate_sensor_dataset(n_normal=900, n_anomaly=100, seed=SEED)
|
| 118 |
+
df.to_csv(os.path.join(DATA_DIR, "sensor_dataset.csv"), index=False)
|
| 119 |
+
|
| 120 |
+
X = df[FEATURES].values
|
| 121 |
+
y = df["label"].values # ground truth, used only for evaluation (model itself is unsupervised)
|
| 122 |
+
|
| 123 |
+
X_train, X_test, y_train, y_test = train_test_split(
|
| 124 |
+
X, y, test_size=0.3, random_state=SEED, stratify=y
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
scaler = StandardScaler()
|
| 128 |
+
X_train_scaled = scaler.fit_transform(X_train)
|
| 129 |
+
X_test_scaled = scaler.transform(X_test)
|
| 130 |
+
|
| 131 |
+
# Contamination set close to the true training-set anomaly rate
|
| 132 |
+
contamination = float(np.clip(y_train.mean(), 0.01, 0.4))
|
| 133 |
+
model = build_anomaly_model(contamination=contamination, seed=SEED)
|
| 134 |
+
model.fit(X_train_scaled)
|
| 135 |
+
|
| 136 |
+
raw_scores = model.decision_function(X_test_scaled) # higher = more normal
|
| 137 |
+
anomaly_scores = 0.5 - raw_scores # higher = more anomalous
|
| 138 |
+
preds = model.predict(X_test_scaled)
|
| 139 |
+
preds_binary = (preds == -1).astype(int)
|
| 140 |
+
|
| 141 |
+
precision = precision_score(y_test, preds_binary, zero_division=0)
|
| 142 |
+
recall = recall_score(y_test, preds_binary, zero_division=0)
|
| 143 |
+
f1 = f1_score(y_test, preds_binary, zero_division=0)
|
| 144 |
+
try:
|
| 145 |
+
roc_auc = roc_auc_score(y_test, anomaly_scores)
|
| 146 |
+
except ValueError:
|
| 147 |
+
roc_auc = float("nan")
|
| 148 |
+
acc = accuracy_score(y_test, preds_binary)
|
| 149 |
+
cm = confusion_matrix(y_test, preds_binary)
|
| 150 |
+
|
| 151 |
+
print(f"precision={precision:.4f} recall={recall:.4f} f1={f1:.4f} roc_auc={roc_auc:.4f}")
|
| 152 |
+
|
| 153 |
+
# Confusion matrix plot
|
| 154 |
+
fig, ax = plt.subplots(figsize=(4.5, 4))
|
| 155 |
+
im = ax.imshow(cm, cmap="Oranges")
|
| 156 |
+
ax.set_xticks([0, 1]); ax.set_yticks([0, 1])
|
| 157 |
+
ax.set_xticklabels(["Normal", "Anomaly"])
|
| 158 |
+
ax.set_yticklabels(["Normal", "Anomaly"])
|
| 159 |
+
ax.set_xlabel("Predicted"); ax.set_ylabel("Actual")
|
| 160 |
+
ax.set_title(f"Anomaly Detector Confusion Matrix\n(F1={f1:.2f})")
|
| 161 |
+
for i in range(2):
|
| 162 |
+
for j in range(2):
|
| 163 |
+
ax.text(j, i, cm[i, j], ha="center", va="center",
|
| 164 |
+
color="white" if cm[i, j] > cm.max() / 2 else "black")
|
| 165 |
+
fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
|
| 166 |
+
fig.tight_layout()
|
| 167 |
+
fig.savefig(os.path.join(ASSETS_DIR, "anomaly_confusion_matrix.png"), dpi=150)
|
| 168 |
+
plt.close(fig)
|
| 169 |
+
|
| 170 |
+
# ROC curve plot
|
| 171 |
+
fpr, tpr, _ = roc_curve(y_test, anomaly_scores)
|
| 172 |
+
fig, ax = plt.subplots(figsize=(5, 4.5))
|
| 173 |
+
ax.plot(fpr, tpr, label=f"ROC-AUC = {roc_auc:.3f}", color="#2563eb", linewidth=2)
|
| 174 |
+
ax.plot([0, 1], [0, 1], linestyle="--", color="gray", linewidth=1)
|
| 175 |
+
ax.set_xlabel("False Positive Rate")
|
| 176 |
+
ax.set_ylabel("True Positive Rate")
|
| 177 |
+
ax.set_title("Anomaly Detector ROC Curve")
|
| 178 |
+
ax.legend(loc="lower right")
|
| 179 |
+
fig.tight_layout()
|
| 180 |
+
fig.savefig(os.path.join(ASSETS_DIR, "anomaly_roc_curve.png"), dpi=150)
|
| 181 |
+
plt.close(fig)
|
| 182 |
+
|
| 183 |
+
# Retrain on full data for the deployed model
|
| 184 |
+
scaler_full = StandardScaler()
|
| 185 |
+
X_full_scaled = scaler_full.fit_transform(X)
|
| 186 |
+
contamination_full = float(np.clip(y.mean(), 0.01, 0.4))
|
| 187 |
+
model_full = build_anomaly_model(contamination=contamination_full, seed=SEED)
|
| 188 |
+
model_full.fit(X_full_scaled)
|
| 189 |
+
save_anomaly_artifacts(
|
| 190 |
+
model_full, scaler_full,
|
| 191 |
+
os.path.join(MODELS_DIR, "anomaly_iforest.joblib"),
|
| 192 |
+
os.path.join(MODELS_DIR, "anomaly_scaler.joblib"),
|
| 193 |
+
)
|
| 194 |
+
|
| 195 |
+
metrics = {
|
| 196 |
+
"precision": precision,
|
| 197 |
+
"recall": recall,
|
| 198 |
+
"f1": f1,
|
| 199 |
+
"roc_auc": roc_auc,
|
| 200 |
+
"accuracy": acc,
|
| 201 |
+
"n_test": len(y_test),
|
| 202 |
+
"test_anomaly_rate": float(y_test.mean()),
|
| 203 |
+
"contamination_used": contamination,
|
| 204 |
+
}
|
| 205 |
+
with open(os.path.join(DATA_DIR, "anomaly_eval.json"), "w") as f:
|
| 206 |
+
json.dump(metrics, f, indent=2)
|
| 207 |
+
return metrics
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def build_retrieval_eval():
|
| 211 |
+
print("== Retrieval (RAG) evaluation ==")
|
| 212 |
+
retriever = KBRetriever()
|
| 213 |
+
hits_at_1, hits_at_2 = 0, 0
|
| 214 |
+
rows = []
|
| 215 |
+
for query, expected_id in RETRIEVAL_EVAL_SET:
|
| 216 |
+
results = retriever.retrieve(query, k=2)
|
| 217 |
+
top_ids = [r.id for r in results]
|
| 218 |
+
hit1 = top_ids[0] == expected_id
|
| 219 |
+
hit2 = expected_id in top_ids
|
| 220 |
+
hits_at_1 += int(hit1)
|
| 221 |
+
hits_at_2 += int(hit2)
|
| 222 |
+
rows.append({
|
| 223 |
+
"query": query,
|
| 224 |
+
"expected": expected_id,
|
| 225 |
+
"retrieved_top1": top_ids[0],
|
| 226 |
+
"hit@1": hit1,
|
| 227 |
+
"hit@2": hit2,
|
| 228 |
+
"top1_score": round(results[0].score, 4),
|
| 229 |
+
})
|
| 230 |
+
|
| 231 |
+
n = len(RETRIEVAL_EVAL_SET)
|
| 232 |
+
metrics = {
|
| 233 |
+
"hit_rate_at_1": hits_at_1 / n,
|
| 234 |
+
"hit_rate_at_2": hits_at_2 / n,
|
| 235 |
+
"n_queries": n,
|
| 236 |
+
"rows": rows,
|
| 237 |
+
}
|
| 238 |
+
print(f"hit@1={metrics['hit_rate_at_1']:.2f} hit@2={metrics['hit_rate_at_2']:.2f}")
|
| 239 |
+
with open(os.path.join(DATA_DIR, "retrieval_eval.json"), "w") as f:
|
| 240 |
+
json.dump(metrics, f, indent=2)
|
| 241 |
+
return metrics
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def build_inventory_and_orders():
|
| 245 |
+
print("== Inventory & Orders synthetic DB ==")
|
| 246 |
+
inv = generate_inventory_db(seed=SEED)
|
| 247 |
+
orders = generate_orders_db(seed=SEED)
|
| 248 |
+
inv.to_csv(os.path.join(DATA_DIR, "inventory.csv"), index=False)
|
| 249 |
+
orders.to_csv(os.path.join(DATA_DIR, "orders.csv"), index=False)
|
| 250 |
+
print(f"inventory rows={len(inv)} orders rows={len(orders)}")
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def build_latency_benchmark(intent_metrics, anomaly_metrics):
|
| 254 |
+
print("== Latency benchmark ==")
|
| 255 |
+
import time
|
| 256 |
+
from src.intent_model import load_pipeline, predict as intent_predict
|
| 257 |
+
from src.anomaly_model import load_artifacts, score_reading
|
| 258 |
+
|
| 259 |
+
pipeline = load_pipeline(os.path.join(MODELS_DIR, "intent_pipeline.joblib"))
|
| 260 |
+
model, scaler = load_artifacts(
|
| 261 |
+
os.path.join(MODELS_DIR, "anomaly_iforest.joblib"),
|
| 262 |
+
os.path.join(MODELS_DIR, "anomaly_scaler.joblib"),
|
| 263 |
+
)
|
| 264 |
+
retriever = KBRetriever()
|
| 265 |
+
|
| 266 |
+
sample_query = "The conveyor belt in Zone C is making noise"
|
| 267 |
+
sample_reading = {"motor_temp_c": 82.0, "vibration_mm_s": 6.1, "current_amps": 20.5, "belt_speed_mps": 0.7}
|
| 268 |
+
|
| 269 |
+
def timeit(fn, n=50):
|
| 270 |
+
start = time.perf_counter()
|
| 271 |
+
for _ in range(n):
|
| 272 |
+
fn()
|
| 273 |
+
return (time.perf_counter() - start) / n * 1000 # ms
|
| 274 |
+
|
| 275 |
+
intent_ms = timeit(lambda: intent_predict(pipeline, sample_query))
|
| 276 |
+
anomaly_ms = timeit(lambda: score_reading(model, scaler, sample_reading))
|
| 277 |
+
retrieval_ms = timeit(lambda: retriever.retrieve(sample_query, k=2))
|
| 278 |
+
|
| 279 |
+
latency = {
|
| 280 |
+
"intent_classifier_ms": round(intent_ms, 3),
|
| 281 |
+
"anomaly_detector_ms": round(anomaly_ms, 3),
|
| 282 |
+
"kb_retrieval_ms": round(retrieval_ms, 3),
|
| 283 |
+
"note": "LLM generation latency depends on the external Inference API "
|
| 284 |
+
"call and is measured live in the app, not benchmarked here.",
|
| 285 |
+
}
|
| 286 |
+
with open(os.path.join(DATA_DIR, "latency_eval.json"), "w") as f:
|
| 287 |
+
json.dump(latency, f, indent=2)
|
| 288 |
+
print(latency)
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
if __name__ == "__main__":
|
| 292 |
+
intent_metrics = build_intent_classifier()
|
| 293 |
+
anomaly_metrics = build_anomaly_detector()
|
| 294 |
+
build_retrieval_eval()
|
| 295 |
+
build_inventory_and_orders()
|
| 296 |
+
build_latency_benchmark(intent_metrics, anomaly_metrics)
|
| 297 |
+
print("\nAll artifacts built successfully.")
|
data/anomaly_eval.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"precision": 0.9375,
|
| 3 |
+
"recall": 1.0,
|
| 4 |
+
"f1": 0.967741935483871,
|
| 5 |
+
"roc_auc": 1.0,
|
| 6 |
+
"accuracy": 0.9933333333333333,
|
| 7 |
+
"n_test": 300,
|
| 8 |
+
"test_anomaly_rate": 0.1,
|
| 9 |
+
"contamination_used": 0.1
|
| 10 |
+
}
|
data/intent_dataset.csv
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
text,intent
|
| 2 |
+
Is order #79471 delayed?,order_status
|
| 3 |
+
Is the sorter in Zone C running normally?,system_status
|
| 4 |
+
What is the uptime for Sorter-02 today?,system_status
|
| 5 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 6 |
+
Is the sorter in the receiving dock running normally?,system_status
|
| 7 |
+
The sorter in the mezzanine keeps jamming,equipment_maintenance
|
| 8 |
+
Optimize the pick path for Zone D,picking_optimization
|
| 9 |
+
Is Crane-03 operational?,system_status
|
| 10 |
+
Has order #25928 shipped yet?,order_status
|
| 11 |
+
What's the difference between AGV and AMR?,general_faq
|
| 12 |
+
What is the current stock level for SKU-1139?,inventory_check
|
| 13 |
+
Optimize the pick path for the receiving dock,picking_optimization
|
| 14 |
+
What's the difference between AGV and AMR?,general_faq
|
| 15 |
+
How can we reduce travel time for pickers in Zone C?,picking_optimization
|
| 16 |
+
What is the current stock level for SKU-9389?,inventory_check
|
| 17 |
+
What's the status of order #90477?,order_status
|
| 18 |
+
How much inventory is left for SKU-1882?,inventory_check
|
| 19 |
+
What is a WMS?,general_faq
|
| 20 |
+
Is SKU-8017 in stock at Zone A?,inventory_check
|
| 21 |
+
Send AGV AMR-21 to Zone B,agv_navigation
|
| 22 |
+
Redirect Sorter-02 around the blocked aisle in Zone B,agv_navigation
|
| 23 |
+
Explain how an AS/RS works,general_faq
|
| 24 |
+
When will order #90496 be delivered?,order_status
|
| 25 |
+
What's the fastest picking route for order #33531?,picking_optimization
|
| 26 |
+
Why hasn't order #61694 left the dock yet?,order_status
|
| 27 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 28 |
+
File an incident report for Zone D,safety_incident
|
| 29 |
+
"A worker slipped near AMR-21, please log it",safety_incident
|
| 30 |
+
"A worker slipped near Sorter-02, please log it",safety_incident
|
| 31 |
+
What is the current stock level for SKU-9444?,inventory_check
|
| 32 |
+
Is Crane-03 operational?,system_status
|
| 33 |
+
What is the current stock level for SKU-5638?,inventory_check
|
| 34 |
+
Are all cranes online in Zone D?,system_status
|
| 35 |
+
What is predictive maintenance?,general_faq
|
| 36 |
+
What is the uptime for AMR-21 today?,system_status
|
| 37 |
+
Track order #90980 for me,order_status
|
| 38 |
+
Log a safety incident involving Crane-05,safety_incident
|
| 39 |
+
"Belt AGV-12 stopped unexpectedly, please check",equipment_maintenance
|
| 40 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 41 |
+
Check inventory count for SKU-9594 in the mezzanine,inventory_check
|
| 42 |
+
A forklift near-miss was reported in the receiving dock,safety_incident
|
| 43 |
+
Why is AGV-12 stuck near Zone D?,agv_navigation
|
| 44 |
+
Has order #77844 shipped yet?,order_status
|
| 45 |
+
What is the current location of AGV-07?,agv_navigation
|
| 46 |
+
Do we have enough SKU-7730 to fulfill 200 units?,inventory_check
|
| 47 |
+
Report unsafe pallet stacking in Zone D,safety_incident
|
| 48 |
+
What's the difference between AGV and AMR?,general_faq
|
| 49 |
+
Track order #39863 for me,order_status
|
| 50 |
+
"Belt AGV-07 stopped unexpectedly, please check",equipment_maintenance
|
| 51 |
+
Is order #36387 delayed?,order_status
|
| 52 |
+
What is the uptime for Conveyor-14 today?,system_status
|
| 53 |
+
There was a near collision between AGV-12 and a pedestrian in Zone B,safety_incident
|
| 54 |
+
Is Sorter-02 operational?,system_status
|
| 55 |
+
How does goods-to-person picking work?,general_faq
|
| 56 |
+
Report unsafe pallet stacking in Zone A,safety_incident
|
| 57 |
+
Suggest a wave picking plan for Zone C,picking_optimization
|
| 58 |
+
Has order #81590 shipped yet?,order_status
|
| 59 |
+
Show the fulfillment status of #97907,order_status
|
| 60 |
+
What's the difference between AGV and AMR?,general_faq
|
| 61 |
+
Why hasn't order #64070 left the dock yet?,order_status
|
| 62 |
+
What's the difference between AGV and AMR?,general_faq
|
| 63 |
+
What's the fastest picking route for order #53089?,picking_optimization
|
| 64 |
+
Show the fulfillment status of #96188,order_status
|
| 65 |
+
Schedule maintenance for AMR-21,equipment_maintenance
|
| 66 |
+
Redirect Crane-03 around the blocked aisle in Zone D,agv_navigation
|
| 67 |
+
Report unsafe pallet stacking in the receiving dock,safety_incident
|
| 68 |
+
Report unsafe pallet stacking in Zone D,safety_incident
|
| 69 |
+
What's the status of order #77199?,order_status
|
| 70 |
+
What's the status of order #42868?,order_status
|
| 71 |
+
What is the current location of Sorter-02?,agv_navigation
|
| 72 |
+
"A worker slipped near Crane-03, please log it",safety_incident
|
| 73 |
+
Track order #80047 for me,order_status
|
| 74 |
+
Route Conveyor-14 to picking station 7,agv_navigation
|
| 75 |
+
"Belt AGV-12 stopped unexpectedly, please check",equipment_maintenance
|
| 76 |
+
AGV-12 motor temperature seems high,equipment_maintenance
|
| 77 |
+
Crane Crane-05 reported a fault code,equipment_maintenance
|
| 78 |
+
Suggest a wave picking plan for Zone A,picking_optimization
|
| 79 |
+
Explain how an AS/RS works,general_faq
|
| 80 |
+
A forklift near-miss was reported in Zone D,safety_incident
|
| 81 |
+
Is order #13773 delayed?,order_status
|
| 82 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 83 |
+
Give me stock levels across all zones for SKU-9745,inventory_check
|
| 84 |
+
The sorter in Zone D keeps jamming,equipment_maintenance
|
| 85 |
+
Explain how an AS/RS works,general_faq
|
| 86 |
+
Check inventory count for SKU-4142 in Zone D,inventory_check
|
| 87 |
+
There was a near collision between Crane-05 and a pedestrian in Zone D,safety_incident
|
| 88 |
+
A forklift near-miss was reported in the mezzanine,safety_incident
|
| 89 |
+
How many units of SKU-5262 are in Zone D?,inventory_check
|
| 90 |
+
Report unsafe pallet stacking in the receiving dock,safety_incident
|
| 91 |
+
Reassign Sorter-02 to charging station,agv_navigation
|
| 92 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 93 |
+
Redirect AGV-12 around the blocked aisle in Zone A,agv_navigation
|
| 94 |
+
Route AGV-12 to picking station 3,agv_navigation
|
| 95 |
+
Check system health for the receiving dock,system_status
|
| 96 |
+
Show me the on-hand quantity of SKU-3984,inventory_check
|
| 97 |
+
Check system health for Zone A,system_status
|
| 98 |
+
Crane AMR-21 reported a fault code,equipment_maintenance
|
| 99 |
+
Redirect AMR-21 around the blocked aisle in the mezzanine,agv_navigation
|
| 100 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 101 |
+
Check inventory count for SKU-5358 in Zone C,inventory_check
|
| 102 |
+
Is the sorter in Zone A running normally?,system_status
|
| 103 |
+
What is the uptime for Conveyor-14 today?,system_status
|
| 104 |
+
Crane AGV-12 reported a fault code,equipment_maintenance
|
| 105 |
+
What is predictive maintenance?,general_faq
|
| 106 |
+
Redirect AMR-21 around the blocked aisle in Zone B,agv_navigation
|
| 107 |
+
Reassign Crane-05 to charging station,agv_navigation
|
| 108 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 109 |
+
Give me stock levels across all zones for SKU-9349,inventory_check
|
| 110 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 111 |
+
Do we have enough SKU-1634 to fulfill 200 units?,inventory_check
|
| 112 |
+
Schedule maintenance for Conveyor-14,equipment_maintenance
|
| 113 |
+
Is AGV-07 operational?,system_status
|
| 114 |
+
Crane Conveyor-14 reported a fault code,equipment_maintenance
|
| 115 |
+
What is predictive maintenance?,general_faq
|
| 116 |
+
What's the difference between AGV and AMR?,general_faq
|
| 117 |
+
What is the current stock level for SKU-4153?,inventory_check
|
| 118 |
+
Report vibration issue on Sorter-02,equipment_maintenance
|
| 119 |
+
How can we reduce travel time for pickers in Zone B?,picking_optimization
|
| 120 |
+
Is Crane-05 operational?,system_status
|
| 121 |
+
Give me stock levels across all zones for SKU-2069,inventory_check
|
| 122 |
+
Show me the on-hand quantity of SKU-9500,inventory_check
|
| 123 |
+
Track order #76329 for me,order_status
|
| 124 |
+
Is Crane-05 operational?,system_status
|
| 125 |
+
Show the fulfillment status of #13780,order_status
|
| 126 |
+
Show me the on-hand quantity of SKU-3324,inventory_check
|
| 127 |
+
Why hasn't order #89759 left the dock yet?,order_status
|
| 128 |
+
Report vibration issue on AMR-21,equipment_maintenance
|
| 129 |
+
File an incident report for Zone B,safety_incident
|
| 130 |
+
How does goods-to-person picking work?,general_faq
|
| 131 |
+
What is predictive maintenance?,general_faq
|
| 132 |
+
Show the fulfillment status of #56924,order_status
|
| 133 |
+
Report unsafe pallet stacking in the receiving dock,safety_incident
|
| 134 |
+
Redirect AMR-21 around the blocked aisle in the mezzanine,agv_navigation
|
| 135 |
+
Is SKU-5796 in stock at Zone B?,inventory_check
|
| 136 |
+
Why is Conveyor-14 stuck near the receiving dock?,agv_navigation
|
| 137 |
+
How can we reduce travel time for pickers in Zone A?,picking_optimization
|
| 138 |
+
What is the uptime for Sorter-02 today?,system_status
|
| 139 |
+
Do we have enough SKU-6931 to fulfill 200 units?,inventory_check
|
| 140 |
+
What's the status of order #64054?,order_status
|
| 141 |
+
How much inventory is left for SKU-9186?,inventory_check
|
| 142 |
+
Check inventory count for SKU-6138 in Zone C,inventory_check
|
| 143 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 144 |
+
Is Crane-05 operational?,system_status
|
| 145 |
+
How many units of SKU-7673 are in Zone A?,inventory_check
|
| 146 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 147 |
+
Is order #42664 delayed?,order_status
|
| 148 |
+
Track order #32774 for me,order_status
|
| 149 |
+
Report unsafe pallet stacking in Zone B,safety_incident
|
| 150 |
+
How can we reduce travel time for pickers in Zone D?,picking_optimization
|
| 151 |
+
Check inventory count for SKU-5130 in the receiving dock,inventory_check
|
| 152 |
+
Report unsafe pallet stacking in Zone C,safety_incident
|
| 153 |
+
What is the current location of Crane-05?,agv_navigation
|
| 154 |
+
Give me stock levels across all zones for SKU-8391,inventory_check
|
| 155 |
+
Is SKU-1561 in stock at Zone C?,inventory_check
|
| 156 |
+
What is predictive maintenance?,general_faq
|
| 157 |
+
Is order #63615 delayed?,order_status
|
| 158 |
+
How many units of SKU-1334 are in the mezzanine?,inventory_check
|
| 159 |
+
Schedule maintenance for AGV-12,equipment_maintenance
|
| 160 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 161 |
+
Is order #48757 delayed?,order_status
|
| 162 |
+
Show the fulfillment status of #97109,order_status
|
| 163 |
+
Should we batch pick these orders together?,picking_optimization
|
| 164 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 165 |
+
The sorter in the mezzanine keeps jamming,equipment_maintenance
|
| 166 |
+
File an incident report for the mezzanine,safety_incident
|
| 167 |
+
Give me the current status of the WMS integration,system_status
|
| 168 |
+
What's the fastest picking route for order #64066?,picking_optimization
|
| 169 |
+
How can we reduce travel time for pickers in Zone D?,picking_optimization
|
| 170 |
+
Why is Sorter-02 stuck near the receiving dock?,agv_navigation
|
| 171 |
+
What is predictive maintenance?,general_faq
|
| 172 |
+
Report vibration issue on Conveyor-14,equipment_maintenance
|
| 173 |
+
File an incident report for the receiving dock,safety_incident
|
| 174 |
+
Has order #45389 shipped yet?,order_status
|
| 175 |
+
Redirect AMR-21 around the blocked aisle in Zone D,agv_navigation
|
| 176 |
+
Schedule maintenance for AMR-21,equipment_maintenance
|
| 177 |
+
What is the uptime for Sorter-02 today?,system_status
|
| 178 |
+
Send AGV AMR-21 to Zone D,agv_navigation
|
| 179 |
+
Route AGV-12 to picking station 7,agv_navigation
|
| 180 |
+
Has order #47696 shipped yet?,order_status
|
| 181 |
+
Reassign Conveyor-14 to charging station,agv_navigation
|
| 182 |
+
The sorter in Zone D keeps jamming,equipment_maintenance
|
| 183 |
+
Should we batch pick these orders together?,picking_optimization
|
| 184 |
+
"Belt AGV-07 stopped unexpectedly, please check",equipment_maintenance
|
| 185 |
+
Give me the current status of the WMS integration,system_status
|
| 186 |
+
Are all cranes online in Zone C?,system_status
|
| 187 |
+
Track order #70623 for me,order_status
|
| 188 |
+
Check system health for the mezzanine,system_status
|
| 189 |
+
Report vibration issue on AMR-21,equipment_maintenance
|
| 190 |
+
"A worker slipped near Crane-03, please log it",safety_incident
|
| 191 |
+
Route Conveyor-14 to picking station 7,agv_navigation
|
| 192 |
+
When will order #30254 be delivered?,order_status
|
| 193 |
+
Suggest a wave picking plan for Zone A,picking_optimization
|
| 194 |
+
What is the uptime for Conveyor-14 today?,system_status
|
| 195 |
+
Route AGV-12 to picking station 7,agv_navigation
|
| 196 |
+
Is order #82154 delayed?,order_status
|
| 197 |
+
Suggest a wave picking plan for Zone A,picking_optimization
|
| 198 |
+
Check system health for the receiving dock,system_status
|
| 199 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 200 |
+
Log a safety incident involving AMR-21,safety_incident
|
| 201 |
+
Should we batch pick these orders together?,picking_optimization
|
| 202 |
+
A forklift near-miss was reported in Zone A,safety_incident
|
| 203 |
+
What is the uptime for Sorter-02 today?,system_status
|
| 204 |
+
Is Conveyor-14 operational?,system_status
|
| 205 |
+
Are all cranes online in the mezzanine?,system_status
|
| 206 |
+
Do we have enough SKU-5966 to fulfill 200 units?,inventory_check
|
| 207 |
+
Why is Conveyor-14 stuck near the receiving dock?,agv_navigation
|
| 208 |
+
Log a breakdown for Conveyor-14 in Zone A,equipment_maintenance
|
| 209 |
+
File an incident report for Zone D,safety_incident
|
| 210 |
+
Why is AGV-12 stuck near Zone A?,agv_navigation
|
| 211 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 212 |
+
Should we batch pick these orders together?,picking_optimization
|
| 213 |
+
Show me the on-hand quantity of SKU-8952,inventory_check
|
| 214 |
+
Has order #57335 shipped yet?,order_status
|
| 215 |
+
Redirect Conveyor-14 around the blocked aisle in Zone C,agv_navigation
|
| 216 |
+
Is AMR-21 operational?,system_status
|
| 217 |
+
How many units of SKU-5103 are in Zone B?,inventory_check
|
| 218 |
+
"A worker slipped near AGV-07, please log it",safety_incident
|
| 219 |
+
A forklift near-miss was reported in Zone D,safety_incident
|
| 220 |
+
"Belt Conveyor-14 stopped unexpectedly, please check",equipment_maintenance
|
| 221 |
+
Log a breakdown for AGV-07 in Zone D,equipment_maintenance
|
| 222 |
+
Crane AMR-21 reported a fault code,equipment_maintenance
|
| 223 |
+
Is Conveyor-14 operational?,system_status
|
| 224 |
+
Why is Crane-05 stuck near Zone B?,agv_navigation
|
| 225 |
+
What's the fastest picking route for order #31767?,picking_optimization
|
| 226 |
+
Show me the on-hand quantity of SKU-4409,inventory_check
|
| 227 |
+
Is the sorter in Zone D running normally?,system_status
|
| 228 |
+
When will order #56214 be delivered?,order_status
|
| 229 |
+
When will order #45136 be delivered?,order_status
|
| 230 |
+
How many units of SKU-1334 are in Zone A?,inventory_check
|
| 231 |
+
What is the uptime for Crane-03 today?,system_status
|
| 232 |
+
The conveyor belt in the mezzanine is making noise,equipment_maintenance
|
| 233 |
+
What is predictive maintenance?,general_faq
|
| 234 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 235 |
+
Reassign Conveyor-14 to charging station,agv_navigation
|
| 236 |
+
Optimize the pick path for Zone B,picking_optimization
|
| 237 |
+
A forklift near-miss was reported in Zone C,safety_incident
|
| 238 |
+
How does goods-to-person picking work?,general_faq
|
| 239 |
+
Reassign AGV-07 to charging station,agv_navigation
|
| 240 |
+
Track order #71532 for me,order_status
|
| 241 |
+
Crane-03 motor temperature seems high,equipment_maintenance
|
| 242 |
+
The sorter in Zone D keeps jamming,equipment_maintenance
|
| 243 |
+
Should we batch pick these orders together?,picking_optimization
|
| 244 |
+
Crane AGV-12 reported a fault code,equipment_maintenance
|
| 245 |
+
What is the current stock level for SKU-5995?,inventory_check
|
| 246 |
+
What's the status of order #14451?,order_status
|
| 247 |
+
Check system health for the mezzanine,system_status
|
| 248 |
+
Show the fulfillment status of #98725,order_status
|
| 249 |
+
What's the difference between AGV and AMR?,general_faq
|
| 250 |
+
The sorter in the mezzanine keeps jamming,equipment_maintenance
|
| 251 |
+
File an incident report for the mezzanine,safety_incident
|
| 252 |
+
What's the status of order #57944?,order_status
|
| 253 |
+
Log a breakdown for Crane-05 in Zone C,equipment_maintenance
|
| 254 |
+
Send AGV Conveyor-14 to Zone D,agv_navigation
|
| 255 |
+
Is AMR-21 operational?,system_status
|
| 256 |
+
Are all cranes online in Zone A?,system_status
|
| 257 |
+
Should we batch pick these orders together?,picking_optimization
|
| 258 |
+
When will order #96195 be delivered?,order_status
|
| 259 |
+
What is the uptime for Crane-05 today?,system_status
|
| 260 |
+
Report vibration issue on Crane-03,equipment_maintenance
|
| 261 |
+
Reassign Crane-05 to charging station,agv_navigation
|
| 262 |
+
Redirect Crane-05 around the blocked aisle in the mezzanine,agv_navigation
|
| 263 |
+
Suggest a wave picking plan for Zone A,picking_optimization
|
| 264 |
+
What's the fastest picking route for order #40691?,picking_optimization
|
| 265 |
+
How can we reduce travel time for pickers in the receiving dock?,picking_optimization
|
| 266 |
+
"A worker slipped near Crane-05, please log it",safety_incident
|
| 267 |
+
How can we reduce travel time for pickers in the receiving dock?,picking_optimization
|
| 268 |
+
What is the uptime for Crane-03 today?,system_status
|
| 269 |
+
What is a WMS?,general_faq
|
| 270 |
+
Schedule maintenance for Sorter-02,equipment_maintenance
|
| 271 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 272 |
+
Send AGV AGV-07 to the mezzanine,agv_navigation
|
| 273 |
+
What is the uptime for Conveyor-14 today?,system_status
|
| 274 |
+
Why is Sorter-02 stuck near the mezzanine?,agv_navigation
|
| 275 |
+
Report vibration issue on Sorter-02,equipment_maintenance
|
| 276 |
+
Is the sorter in Zone C running normally?,system_status
|
| 277 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 278 |
+
File an incident report for Zone C,safety_incident
|
| 279 |
+
What's the difference between AGV and AMR?,general_faq
|
| 280 |
+
Optimize the pick path for the receiving dock,picking_optimization
|
| 281 |
+
Log a safety incident involving Crane-03,safety_incident
|
| 282 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 283 |
+
A forklift near-miss was reported in Zone C,safety_incident
|
| 284 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 285 |
+
Is order #50038 delayed?,order_status
|
| 286 |
+
Crane Crane-03 reported a fault code,equipment_maintenance
|
| 287 |
+
Suggest a wave picking plan for Zone C,picking_optimization
|
| 288 |
+
A forklift near-miss was reported in Zone B,safety_incident
|
| 289 |
+
"A worker slipped near Crane-05, please log it",safety_incident
|
| 290 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 291 |
+
File an incident report for Zone D,safety_incident
|
| 292 |
+
Reassign Sorter-02 to charging station,agv_navigation
|
| 293 |
+
Are all cranes online in the mezzanine?,system_status
|
| 294 |
+
Log a breakdown for AMR-21 in Zone A,equipment_maintenance
|
| 295 |
+
"Belt Sorter-02 stopped unexpectedly, please check",equipment_maintenance
|
| 296 |
+
Reassign Conveyor-14 to charging station,agv_navigation
|
| 297 |
+
Suggest a wave picking plan for Zone D,picking_optimization
|
| 298 |
+
What is the current location of Crane-05?,agv_navigation
|
| 299 |
+
What's the status of order #64365?,order_status
|
| 300 |
+
The conveyor belt in the receiving dock is making noise,equipment_maintenance
|
| 301 |
+
A forklift near-miss was reported in Zone C,safety_incident
|
| 302 |
+
Route Sorter-02 to picking station 12,agv_navigation
|
| 303 |
+
Is the sorter in the receiving dock running normally?,system_status
|
| 304 |
+
A forklift near-miss was reported in Zone A,safety_incident
|
| 305 |
+
"Belt Crane-05 stopped unexpectedly, please check",equipment_maintenance
|
| 306 |
+
Should we batch pick these orders together?,picking_optimization
|
| 307 |
+
Are all cranes online in Zone A?,system_status
|
| 308 |
+
Track order #93256 for me,order_status
|
| 309 |
+
A forklift near-miss was reported in the receiving dock,safety_incident
|
| 310 |
+
Report unsafe pallet stacking in the receiving dock,safety_incident
|
| 311 |
+
AGV-12 motor temperature seems high,equipment_maintenance
|
| 312 |
+
Is Sorter-02 operational?,system_status
|
| 313 |
+
Show me the on-hand quantity of SKU-4925,inventory_check
|
| 314 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 315 |
+
Is order #93706 delayed?,order_status
|
| 316 |
+
Suggest a wave picking plan for Zone B,picking_optimization
|
| 317 |
+
When will order #46154 be delivered?,order_status
|
| 318 |
+
Should we batch pick these orders together?,picking_optimization
|
| 319 |
+
What is the current location of AMR-21?,agv_navigation
|
| 320 |
+
Crane Sorter-02 reported a fault code,equipment_maintenance
|
| 321 |
+
Is SKU-5535 in stock at the mezzanine?,inventory_check
|
| 322 |
+
Check inventory count for SKU-7601 in the mezzanine,inventory_check
|
| 323 |
+
What is the current stock level for SKU-9473?,inventory_check
|
| 324 |
+
Report vibration issue on Conveyor-14,equipment_maintenance
|
| 325 |
+
Log a breakdown for AMR-21 in Zone B,equipment_maintenance
|
| 326 |
+
Is the sorter in Zone A running normally?,system_status
|
| 327 |
+
What is a WMS?,general_faq
|
| 328 |
+
Send AGV AGV-12 to the receiving dock,agv_navigation
|
| 329 |
+
When will order #51499 be delivered?,order_status
|
| 330 |
+
How much inventory is left for SKU-5685?,inventory_check
|
| 331 |
+
Should we batch pick these orders together?,picking_optimization
|
| 332 |
+
Give me the current status of the WMS integration,system_status
|
| 333 |
+
What is the uptime for AGV-07 today?,system_status
|
| 334 |
+
The conveyor belt in Zone D is making noise,equipment_maintenance
|
| 335 |
+
Check inventory count for SKU-6560 in Zone B,inventory_check
|
| 336 |
+
Give me the current status of the WMS integration,system_status
|
| 337 |
+
Why is Crane-03 stuck near Zone B?,agv_navigation
|
| 338 |
+
What's the fastest picking route for order #50161?,picking_optimization
|
| 339 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 340 |
+
Check system health for the mezzanine,system_status
|
| 341 |
+
How many units of SKU-7260 are in the mezzanine?,inventory_check
|
| 342 |
+
What's the fastest picking route for order #20834?,picking_optimization
|
| 343 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 344 |
+
Why hasn't order #23806 left the dock yet?,order_status
|
| 345 |
+
Redirect AMR-21 around the blocked aisle in Zone C,agv_navigation
|
| 346 |
+
Is the sorter in Zone A running normally?,system_status
|
| 347 |
+
Route Sorter-02 to picking station 12,agv_navigation
|
| 348 |
+
Schedule maintenance for AGV-07,equipment_maintenance
|
| 349 |
+
When will order #41787 be delivered?,order_status
|
| 350 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 351 |
+
Send AGV Crane-05 to Zone B,agv_navigation
|
| 352 |
+
Show the fulfillment status of #24126,order_status
|
| 353 |
+
How many units of SKU-4902 are in the mezzanine?,inventory_check
|
| 354 |
+
What is the current stock level for SKU-9081?,inventory_check
|
| 355 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 356 |
+
"A worker slipped near AMR-21, please log it",safety_incident
|
| 357 |
+
Why is AGV-12 stuck near Zone C?,agv_navigation
|
| 358 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 359 |
+
Do we have enough SKU-4509 to fulfill 200 units?,inventory_check
|
| 360 |
+
Check system health for Zone C,system_status
|
| 361 |
+
Redirect Crane-03 around the blocked aisle in Zone B,agv_navigation
|
| 362 |
+
Optimize the pick path for the mezzanine,picking_optimization
|
| 363 |
+
Optimize the pick path for Zone B,picking_optimization
|
| 364 |
+
Report vibration issue on Crane-05,equipment_maintenance
|
| 365 |
+
What is the uptime for AGV-12 today?,system_status
|
| 366 |
+
Crane AGV-12 reported a fault code,equipment_maintenance
|
| 367 |
+
What's the status of order #61814?,order_status
|
| 368 |
+
Log a breakdown for AMR-21 in Zone D,equipment_maintenance
|
| 369 |
+
The sorter in Zone C keeps jamming,equipment_maintenance
|
| 370 |
+
What is predictive maintenance?,general_faq
|
| 371 |
+
Is SKU-6807 in stock at Zone A?,inventory_check
|
| 372 |
+
File an incident report for Zone D,safety_incident
|
| 373 |
+
What is cycle counting?,general_faq
|
| 374 |
+
What's the status of order #96570?,order_status
|
| 375 |
+
There was a near collision between Conveyor-14 and a pedestrian in Zone A,safety_incident
|
| 376 |
+
What is the current stock level for SKU-4089?,inventory_check
|
| 377 |
+
Report vibration issue on AMR-21,equipment_maintenance
|
| 378 |
+
What is the current stock level for SKU-6220?,inventory_check
|
| 379 |
+
Explain how an AS/RS works,general_faq
|
| 380 |
+
Give me the current status of the WMS integration,system_status
|
| 381 |
+
Route AGV-07 to picking station 12,agv_navigation
|
| 382 |
+
How can we reduce travel time for pickers in Zone A?,picking_optimization
|
| 383 |
+
Give me the current status of the WMS integration,system_status
|
| 384 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 385 |
+
"A worker slipped near AGV-07, please log it",safety_incident
|
| 386 |
+
Reassign Crane-03 to charging station,agv_navigation
|
| 387 |
+
Redirect AGV-12 around the blocked aisle in the mezzanine,agv_navigation
|
| 388 |
+
Send AGV Crane-03 to Zone A,agv_navigation
|
| 389 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 390 |
+
What KPIs matter most in warehouse automation?,general_faq
|
| 391 |
+
What's the fastest picking route for order #13894?,picking_optimization
|
| 392 |
+
What's the difference between AGV and AMR?,general_faq
|
| 393 |
+
What's the difference between AGV and AMR?,general_faq
|
| 394 |
+
Log a safety incident involving AGV-12,safety_incident
|
| 395 |
+
File an incident report for the receiving dock,safety_incident
|
| 396 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 397 |
+
Redirect Crane-03 around the blocked aisle in Zone B,agv_navigation
|
| 398 |
+
"Belt AGV-12 stopped unexpectedly, please check",equipment_maintenance
|
| 399 |
+
Do we have enough SKU-9027 to fulfill 200 units?,inventory_check
|
| 400 |
+
What is the current location of Crane-05?,agv_navigation
|
| 401 |
+
What is the current location of Conveyor-14?,agv_navigation
|
| 402 |
+
Log a safety incident involving Crane-05,safety_incident
|
| 403 |
+
Suggest a wave picking plan for the mezzanine,picking_optimization
|
| 404 |
+
Is order #53968 delayed?,order_status
|
| 405 |
+
Give me stock levels across all zones for SKU-2884,inventory_check
|
| 406 |
+
Give me the current status of the WMS integration,system_status
|
| 407 |
+
Do we have enough SKU-2736 to fulfill 200 units?,inventory_check
|
| 408 |
+
Explain how an AS/RS works,general_faq
|
| 409 |
+
Explain how an AS/RS works,general_faq
|
| 410 |
+
Do we have enough SKU-1311 to fulfill 200 units?,inventory_check
|
| 411 |
+
When will order #64734 be delivered?,order_status
|
| 412 |
+
Route Crane-03 to picking station 5,agv_navigation
|
| 413 |
+
Check inventory count for SKU-3109 in Zone D,inventory_check
|
| 414 |
+
Should we batch pick these orders together?,picking_optimization
|
| 415 |
+
Is the sorter in Zone A running normally?,system_status
|
| 416 |
+
When will order #30168 be delivered?,order_status
|
| 417 |
+
There was a near collision between Crane-05 and a pedestrian in Zone B,safety_incident
|
| 418 |
+
How does goods-to-person picking work?,general_faq
|
| 419 |
+
How much inventory is left for SKU-6985?,inventory_check
|
| 420 |
+
"A worker slipped near AMR-21, please log it",safety_incident
|
| 421 |
+
Optimize the pick path for Zone D,picking_optimization
|
| 422 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 423 |
+
How many units of SKU-7468 are in the receiving dock?,inventory_check
|
| 424 |
+
"A worker slipped near AGV-07, please log it",safety_incident
|
| 425 |
+
Show the fulfillment status of #41997,order_status
|
| 426 |
+
Check system health for Zone D,system_status
|
| 427 |
+
What's the fastest picking route for order #44568?,picking_optimization
|
| 428 |
+
The conveyor belt in Zone A is making noise,equipment_maintenance
|
| 429 |
+
File an incident report for the receiving dock,safety_incident
|
| 430 |
+
What is predictive maintenance?,general_faq
|
| 431 |
+
The conveyor belt in Zone B is making noise,equipment_maintenance
|
| 432 |
+
There was a near collision between AGV-07 and a pedestrian in Zone D,safety_incident
|
| 433 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 434 |
+
A forklift near-miss was reported in the receiving dock,safety_incident
|
| 435 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 436 |
+
Give me stock levels across all zones for SKU-4496,inventory_check
|
| 437 |
+
Is AGV-07 operational?,system_status
|
| 438 |
+
What is the current stock level for SKU-7977?,inventory_check
|
| 439 |
+
AMR-21 motor temperature seems high,equipment_maintenance
|
| 440 |
+
Why is Crane-03 stuck near Zone C?,agv_navigation
|
| 441 |
+
What's the difference between AGV and AMR?,general_faq
|
| 442 |
+
Why is Sorter-02 stuck near Zone A?,agv_navigation
|
| 443 |
+
AMR-21 motor temperature seems high,equipment_maintenance
|
| 444 |
+
How much inventory is left for SKU-3540?,inventory_check
|
| 445 |
+
Do we have enough SKU-9249 to fulfill 200 units?,inventory_check
|
| 446 |
+
There was a near collision between AGV-12 and a pedestrian in Zone A,safety_incident
|
| 447 |
+
Reassign Conveyor-14 to charging station,agv_navigation
|
| 448 |
+
Should we batch pick these orders together?,picking_optimization
|
| 449 |
+
Do we have enough SKU-8501 to fulfill 200 units?,inventory_check
|
| 450 |
+
File an incident report for Zone A,safety_incident
|
| 451 |
+
Log a breakdown for AGV-07 in Zone B,equipment_maintenance
|
| 452 |
+
Recommend a picking strategy for high-velocity SKUs,picking_optimization
|
| 453 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 454 |
+
Route AMR-21 to picking station 12,agv_navigation
|
| 455 |
+
Is the sorter in Zone D running normally?,system_status
|
| 456 |
+
Should we batch pick these orders together?,picking_optimization
|
| 457 |
+
Is the sorter in the mezzanine running normally?,system_status
|
| 458 |
+
"A worker slipped near AGV-07, please log it",safety_incident
|
| 459 |
+
Suggest a wave picking plan for the receiving dock,picking_optimization
|
| 460 |
+
There was a near collision between Sorter-02 and a pedestrian in the receiving dock,safety_incident
|
| 461 |
+
Crane Sorter-02 reported a fault code,equipment_maintenance
|
| 462 |
+
Sorter-02 motor temperature seems high,equipment_maintenance
|
| 463 |
+
"Belt Crane-05 stopped unexpectedly, please check",equipment_maintenance
|
| 464 |
+
There was a near collision between Sorter-02 and a pedestrian in Zone D,safety_incident
|
| 465 |
+
Has order #94021 shipped yet?,order_status
|
| 466 |
+
Is Conveyor-14 operational?,system_status
|
| 467 |
+
Has order #91192 shipped yet?,order_status
|
| 468 |
+
What is a WMS?,general_faq
|
| 469 |
+
Report unsafe pallet stacking in Zone C,safety_incident
|
| 470 |
+
Route AMR-21 to picking station 3,agv_navigation
|
| 471 |
+
How do sortation systems decide where to route a parcel?,general_faq
|
| 472 |
+
Sorter-02 motor temperature seems high,equipment_maintenance
|
| 473 |
+
What is a WMS?,general_faq
|
| 474 |
+
Do we have enough SKU-1853 to fulfill 200 units?,inventory_check
|
| 475 |
+
Send AGV AGV-12 to Zone D,agv_navigation
|
| 476 |
+
What's the status of order #75717?,order_status
|
| 477 |
+
Why hasn't order #64929 left the dock yet?,order_status
|
| 478 |
+
Suggest a wave picking plan for the receiving dock,picking_optimization
|
| 479 |
+
"A worker slipped near Conveyor-14, please log it",safety_incident
|
| 480 |
+
What's the difference between AGV and AMR?,general_faq
|
| 481 |
+
Track order #86085 for me,order_status
|
data/intent_eval.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"accuracy": 0.9916666666666667,
|
| 3 |
+
"macro_f1": 0.9916573971078977,
|
| 4 |
+
"n_train": 360,
|
| 5 |
+
"n_test": 120,
|
| 6 |
+
"n_classes": 8,
|
| 7 |
+
"classes": [
|
| 8 |
+
"agv_navigation",
|
| 9 |
+
"equipment_maintenance",
|
| 10 |
+
"general_faq",
|
| 11 |
+
"inventory_check",
|
| 12 |
+
"order_status",
|
| 13 |
+
"picking_optimization",
|
| 14 |
+
"safety_incident",
|
| 15 |
+
"system_status"
|
| 16 |
+
],
|
| 17 |
+
"classification_report": {
|
| 18 |
+
"agv_navigation": {
|
| 19 |
+
"precision": 1.0,
|
| 20 |
+
"recall": 1.0,
|
| 21 |
+
"f1-score": 1.0,
|
| 22 |
+
"support": 15.0
|
| 23 |
+
},
|
| 24 |
+
"equipment_maintenance": {
|
| 25 |
+
"precision": 1.0,
|
| 26 |
+
"recall": 1.0,
|
| 27 |
+
"f1-score": 1.0,
|
| 28 |
+
"support": 15.0
|
| 29 |
+
},
|
| 30 |
+
"general_faq": {
|
| 31 |
+
"precision": 1.0,
|
| 32 |
+
"recall": 0.9333333333333333,
|
| 33 |
+
"f1-score": 0.9655172413793104,
|
| 34 |
+
"support": 15.0
|
| 35 |
+
},
|
| 36 |
+
"inventory_check": {
|
| 37 |
+
"precision": 1.0,
|
| 38 |
+
"recall": 1.0,
|
| 39 |
+
"f1-score": 1.0,
|
| 40 |
+
"support": 15.0
|
| 41 |
+
},
|
| 42 |
+
"order_status": {
|
| 43 |
+
"precision": 0.9375,
|
| 44 |
+
"recall": 1.0,
|
| 45 |
+
"f1-score": 0.967741935483871,
|
| 46 |
+
"support": 15.0
|
| 47 |
+
},
|
| 48 |
+
"picking_optimization": {
|
| 49 |
+
"precision": 1.0,
|
| 50 |
+
"recall": 1.0,
|
| 51 |
+
"f1-score": 1.0,
|
| 52 |
+
"support": 15.0
|
| 53 |
+
},
|
| 54 |
+
"safety_incident": {
|
| 55 |
+
"precision": 1.0,
|
| 56 |
+
"recall": 1.0,
|
| 57 |
+
"f1-score": 1.0,
|
| 58 |
+
"support": 15.0
|
| 59 |
+
},
|
| 60 |
+
"system_status": {
|
| 61 |
+
"precision": 1.0,
|
| 62 |
+
"recall": 1.0,
|
| 63 |
+
"f1-score": 1.0,
|
| 64 |
+
"support": 15.0
|
| 65 |
+
},
|
| 66 |
+
"accuracy": 0.9916666666666667,
|
| 67 |
+
"macro avg": {
|
| 68 |
+
"precision": 0.9921875,
|
| 69 |
+
"recall": 0.9916666666666667,
|
| 70 |
+
"f1-score": 0.9916573971078977,
|
| 71 |
+
"support": 120.0
|
| 72 |
+
},
|
| 73 |
+
"weighted avg": {
|
| 74 |
+
"precision": 0.9921875,
|
| 75 |
+
"recall": 0.9916666666666667,
|
| 76 |
+
"f1-score": 0.9916573971078978,
|
| 77 |
+
"support": 120.0
|
| 78 |
+
}
|
| 79 |
+
}
|
| 80 |
+
}
|
data/inventory.csv
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
sku,description,category,zone,on_hand_units,reorder_point,unit_cost_jpy
|
| 2 |
+
SKU-1000,Electronics item 1000,Food & Beverage,Zone C,877,158,12907
|
| 3 |
+
SKU-1001,Electronics item 1001,Food & Beverage,Zone A,188,181,14639
|
| 4 |
+
SKU-1002,Food & Beverage item 1002,Food & Beverage,Zone C,1572,178,2096
|
| 5 |
+
SKU-1003,Household item 1003,Automotive Parts,Zone C,741,95,13916
|
| 6 |
+
SKU-1004,Food & Beverage item 1004,Food & Beverage,Zone B,1645,186,6762
|
| 7 |
+
SKU-1005,Automotive Parts item 1005,Apparel,Zone A,1109,271,1144
|
| 8 |
+
SKU-1006,Household item 1006,Household,Zone B,1263,91,11419
|
| 9 |
+
SKU-1007,Food & Beverage item 1007,Apparel,Zone A,1941,161,13418
|
| 10 |
+
SKU-1008,Food & Beverage item 1008,Food & Beverage,Zone D,389,140,7107
|
| 11 |
+
SKU-1009,Automotive Parts item 1009,Electronics,Zone C,308,235,10309
|
| 12 |
+
SKU-1010,Household item 1010,Food & Beverage,Zone B,1935,152,5022
|
| 13 |
+
SKU-1011,Household item 1011,Apparel,Zone A,939,248,3004
|
| 14 |
+
SKU-1012,Automotive Parts item 1012,Electronics,Zone C,951,132,3558
|
| 15 |
+
SKU-1013,Automotive Parts item 1013,Food & Beverage,Zone D,874,90,12523
|
| 16 |
+
SKU-1014,Food & Beverage item 1014,Food & Beverage,Zone A,624,241,12517
|
| 17 |
+
SKU-1015,Automotive Parts item 1015,Household,Zone D,774,274,4467
|
| 18 |
+
SKU-1016,Apparel item 1016,Food & Beverage,Zone C,279,258,3158
|
| 19 |
+
SKU-1017,Household item 1017,Electronics,Zone D,1573,245,10039
|
| 20 |
+
SKU-1018,Automotive Parts item 1018,Food & Beverage,Zone B,1561,188,6991
|
| 21 |
+
SKU-1019,Automotive Parts item 1019,Automotive Parts,Zone A,279,111,1895
|
| 22 |
+
SKU-1020,Automotive Parts item 1020,Food & Beverage,Zone C,942,263,8565
|
| 23 |
+
SKU-1021,Electronics item 1021,Food & Beverage,Zone C,1269,191,8392
|
| 24 |
+
SKU-1022,Electronics item 1022,Automotive Parts,Zone D,607,200,656
|
| 25 |
+
SKU-1023,Apparel item 1023,Automotive Parts,Zone D,429,119,6246
|
| 26 |
+
SKU-1024,Household item 1024,Household,Zone A,467,255,1062
|
| 27 |
+
SKU-1025,Household item 1025,Apparel,Zone D,587,158,9996
|
| 28 |
+
SKU-1026,Electronics item 1026,Automotive Parts,Zone C,1567,299,10031
|
| 29 |
+
SKU-1027,Automotive Parts item 1027,Automotive Parts,Zone B,1628,130,2671
|
| 30 |
+
SKU-1028,Apparel item 1028,Electronics,Zone A,180,242,10890
|
| 31 |
+
SKU-1029,Food & Beverage item 1029,Automotive Parts,Zone C,322,275,7615
|
| 32 |
+
SKU-1030,Household item 1030,Electronics,Zone B,1392,173,6803
|
| 33 |
+
SKU-1031,Electronics item 1031,Apparel,Zone A,603,220,9528
|
| 34 |
+
SKU-1032,Food & Beverage item 1032,Apparel,Zone D,175,135,1946
|
| 35 |
+
SKU-1033,Apparel item 1033,Household,Zone B,1817,173,10555
|
| 36 |
+
SKU-1034,Automotive Parts item 1034,Apparel,Zone D,1938,115,11725
|
| 37 |
+
SKU-1035,Apparel item 1035,Food & Beverage,Zone D,898,234,4229
|
| 38 |
+
SKU-1036,Electronics item 1036,Electronics,Zone B,1805,81,6945
|
| 39 |
+
SKU-1037,Food & Beverage item 1037,Apparel,Zone C,611,252,8772
|
| 40 |
+
SKU-1038,Automotive Parts item 1038,Electronics,Zone B,1713,54,11426
|
| 41 |
+
SKU-1039,Automotive Parts item 1039,Food & Beverage,Zone C,864,127,9484
|
| 42 |
+
SKU-1040,Electronics item 1040,Automotive Parts,Zone A,1299,207,1449
|
| 43 |
+
SKU-1041,Food & Beverage item 1041,Automotive Parts,Zone D,83,94,7511
|
| 44 |
+
SKU-1042,Electronics item 1042,Apparel,Zone C,289,219,1730
|
| 45 |
+
SKU-1043,Electronics item 1043,Automotive Parts,Zone D,341,124,13891
|
| 46 |
+
SKU-1044,Household item 1044,Automotive Parts,Zone B,693,203,8945
|
| 47 |
+
SKU-1045,Apparel item 1045,Electronics,Zone A,1917,154,7338
|
| 48 |
+
SKU-1046,Automotive Parts item 1046,Food & Beverage,Zone A,165,118,7402
|
| 49 |
+
SKU-1047,Food & Beverage item 1047,Automotive Parts,Zone B,1875,90,8661
|
| 50 |
+
SKU-1048,Automotive Parts item 1048,Automotive Parts,Zone D,533,288,5107
|
| 51 |
+
SKU-1049,Automotive Parts item 1049,Automotive Parts,Zone D,877,121,519
|
| 52 |
+
SKU-1050,Apparel item 1050,Household,Zone A,1792,185,2275
|
| 53 |
+
SKU-1051,Apparel item 1051,Automotive Parts,Zone B,217,216,10149
|
| 54 |
+
SKU-1052,Electronics item 1052,Apparel,Zone A,1318,232,10959
|
| 55 |
+
SKU-1053,Household item 1053,Food & Beverage,Zone B,215,203,13756
|
| 56 |
+
SKU-1054,Household item 1054,Apparel,Zone A,74,85,8411
|
| 57 |
+
SKU-1055,Automotive Parts item 1055,Apparel,Zone B,1659,165,12162
|
| 58 |
+
SKU-1056,Household item 1056,Apparel,Zone A,1905,208,4505
|
| 59 |
+
SKU-1057,Food & Beverage item 1057,Automotive Parts,Zone D,511,297,14053
|
| 60 |
+
SKU-1058,Electronics item 1058,Electronics,Zone C,89,124,6639
|
| 61 |
+
SKU-1059,Household item 1059,Household,Zone A,1783,72,11279
|
data/latency_eval.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"intent_classifier_ms": 0.398,
|
| 3 |
+
"anomaly_detector_ms": 22.722,
|
| 4 |
+
"kb_retrieval_ms": 0.561,
|
| 5 |
+
"note": "LLM generation latency depends on the external Inference API call and is measured live in the app, not benchmarked here."
|
| 6 |
+
}
|
data/orders.csv
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
order_id,status,num_lines,priority,zone
|
| 2 |
+
#10000,Shipped,16,Express,Zone B
|
| 3 |
+
#10001,Shipped,5,Same-Day,Zone A
|
| 4 |
+
#10002,Shipped,18,Standard,Zone D
|
| 5 |
+
#10003,Packed,13,Same-Day,Zone B
|
| 6 |
+
#10004,Shipped,10,Standard,Zone D
|
| 7 |
+
#10005,Picking,3,Standard,Zone C
|
| 8 |
+
#10006,Shipped,7,Express,Zone C
|
| 9 |
+
#10007,Picking,2,Express,Zone D
|
| 10 |
+
#10008,Shipped,19,Standard,Zone A
|
| 11 |
+
#10009,Received,14,Express,Zone A
|
| 12 |
+
#10010,Shipped,9,Standard,Zone D
|
| 13 |
+
#10011,Picking,2,Standard,Zone B
|
| 14 |
+
#10012,Received,17,Standard,Zone B
|
| 15 |
+
#10013,Shipped,23,Express,Zone B
|
| 16 |
+
#10014,Shipped,3,Express,Zone B
|
| 17 |
+
#10015,Shipped,21,Standard,Zone B
|
| 18 |
+
#10016,Shipped,16,Standard,Zone A
|
| 19 |
+
#10017,Received,20,Express,Zone D
|
| 20 |
+
#10018,Shipped,7,Standard,Zone D
|
| 21 |
+
#10019,Packed,1,Standard,Zone A
|
| 22 |
+
#10020,Shipped,16,Standard,Zone B
|
| 23 |
+
#10021,Shipped,14,Standard,Zone C
|
| 24 |
+
#10022,Packed,20,Standard,Zone B
|
| 25 |
+
#10023,Packed,24,Standard,Zone A
|
| 26 |
+
#10024,Shipped,1,Standard,Zone A
|
| 27 |
+
#10025,Picking,23,Express,Zone B
|
| 28 |
+
#10026,Packed,13,Express,Zone D
|
| 29 |
+
#10027,Packed,11,Standard,Zone D
|
| 30 |
+
#10028,Received,3,Express,Zone A
|
| 31 |
+
#10029,Packed,18,Standard,Zone A
|
| 32 |
+
#10030,Picking,12,Standard,Zone C
|
| 33 |
+
#10031,Picking,6,Express,Zone B
|
| 34 |
+
#10032,Picking,24,Standard,Zone A
|
| 35 |
+
#10033,Delayed,9,Express,Zone D
|
| 36 |
+
#10034,Picking,19,Express,Zone D
|
| 37 |
+
#10035,Shipped,19,Standard,Zone B
|
| 38 |
+
#10036,Received,11,Standard,Zone D
|
| 39 |
+
#10037,Picking,18,Standard,Zone B
|
| 40 |
+
#10038,Picking,12,Express,Zone D
|
| 41 |
+
#10039,Shipped,16,Express,Zone B
|
| 42 |
+
#10040,Packed,3,Standard,Zone C
|
| 43 |
+
#10041,Packed,19,Standard,Zone A
|
| 44 |
+
#10042,Picking,16,Standard,Zone A
|
| 45 |
+
#10043,Packed,20,Same-Day,Zone A
|
| 46 |
+
#10044,Packed,11,Standard,Zone B
|
| 47 |
+
#10045,Received,4,Standard,Zone D
|
| 48 |
+
#10046,Shipped,2,Standard,Zone A
|
| 49 |
+
#10047,Packed,11,Standard,Zone D
|
| 50 |
+
#10048,Packed,20,Standard,Zone B
|
| 51 |
+
#10049,Packed,21,Standard,Zone B
|
| 52 |
+
#10050,Shipped,1,Standard,Zone D
|
| 53 |
+
#10051,Packed,8,Express,Zone A
|
| 54 |
+
#10052,Picking,6,Express,Zone C
|
| 55 |
+
#10053,Shipped,8,Same-Day,Zone A
|
| 56 |
+
#10054,Picking,6,Standard,Zone A
|
| 57 |
+
#10055,Picking,8,Express,Zone D
|
| 58 |
+
#10056,Picking,5,Standard,Zone D
|
| 59 |
+
#10057,Packed,22,Same-Day,Zone B
|
| 60 |
+
#10058,Picking,13,Standard,Zone A
|
| 61 |
+
#10059,Delayed,4,Express,Zone D
|
| 62 |
+
#10060,Shipped,6,Standard,Zone D
|
| 63 |
+
#10061,Picking,1,Express,Zone D
|
| 64 |
+
#10062,Picking,22,Express,Zone A
|
| 65 |
+
#10063,Picking,1,Standard,Zone D
|
| 66 |
+
#10064,Received,2,Standard,Zone D
|
| 67 |
+
#10065,Picking,9,Express,Zone C
|
| 68 |
+
#10066,Picking,7,Express,Zone B
|
| 69 |
+
#10067,Delayed,12,Standard,Zone C
|
| 70 |
+
#10068,Received,5,Standard,Zone A
|
| 71 |
+
#10069,Shipped,24,Standard,Zone A
|
| 72 |
+
#10070,Shipped,19,Standard,Zone C
|
| 73 |
+
#10071,Shipped,1,Express,Zone C
|
| 74 |
+
#10072,Received,11,Same-Day,Zone A
|
| 75 |
+
#10073,Picking,24,Standard,Zone B
|
| 76 |
+
#10074,Shipped,8,Standard,Zone D
|
| 77 |
+
#10075,Delayed,12,Standard,Zone A
|
| 78 |
+
#10076,Shipped,21,Standard,Zone A
|
| 79 |
+
#10077,Packed,1,Standard,Zone D
|
| 80 |
+
#10078,Delayed,18,Standard,Zone D
|
| 81 |
+
#10079,Shipped,21,Standard,Zone A
|
data/retrieval_eval.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"hit_rate_at_1": 0.8,
|
| 3 |
+
"hit_rate_at_2": 1.0,
|
| 4 |
+
"n_queries": 10,
|
| 5 |
+
"rows": [
|
| 6 |
+
{
|
| 7 |
+
"query": "How does an AS/RS crane retrieve a pallet?",
|
| 8 |
+
"expected": "asrs_overview",
|
| 9 |
+
"retrieved_top1": "asrs_overview",
|
| 10 |
+
"hit@1": true,
|
| 11 |
+
"hit@2": true,
|
| 12 |
+
"top1_score": 0.2435
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"query": "What's the difference between an AGV and an AMR?",
|
| 16 |
+
"expected": "agv_amr_overview",
|
| 17 |
+
"retrieved_top1": "safety_protocol",
|
| 18 |
+
"hit@1": false,
|
| 19 |
+
"hit@2": true,
|
| 20 |
+
"top1_score": 0.1499
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"query": "What does a WMS integrate with?",
|
| 24 |
+
"expected": "wms_overview",
|
| 25 |
+
"retrieved_top1": "wms_overview",
|
| 26 |
+
"hit@1": true,
|
| 27 |
+
"hit@2": true,
|
| 28 |
+
"top1_score": 0.2741
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"query": "Why would a sorter jam?",
|
| 32 |
+
"expected": "conveyor_sorting",
|
| 33 |
+
"retrieved_top1": "conveyor_sorting",
|
| 34 |
+
"hit@1": true,
|
| 35 |
+
"hit@2": true,
|
| 36 |
+
"top1_score": 0.0959
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"query": "What is batch picking?",
|
| 40 |
+
"expected": "picking_strategies",
|
| 41 |
+
"retrieved_top1": "picking_strategies",
|
| 42 |
+
"hit@1": true,
|
| 43 |
+
"hit@2": true,
|
| 44 |
+
"top1_score": 0.3279
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"query": "How can we predict a motor failure before it happens?",
|
| 48 |
+
"expected": "predictive_maintenance",
|
| 49 |
+
"retrieved_top1": "conveyor_sorting",
|
| 50 |
+
"hit@1": false,
|
| 51 |
+
"hit@2": true,
|
| 52 |
+
"top1_score": 0.1426
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"query": "What should I do after a near-miss with a forklift?",
|
| 56 |
+
"expected": "safety_protocol",
|
| 57 |
+
"retrieved_top1": "safety_protocol",
|
| 58 |
+
"hit@1": true,
|
| 59 |
+
"hit@2": true,
|
| 60 |
+
"top1_score": 0.3443
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"query": "How do we keep inventory counts accurate?",
|
| 64 |
+
"expected": "inventory_accuracy",
|
| 65 |
+
"retrieved_top1": "inventory_accuracy",
|
| 66 |
+
"hit@1": true,
|
| 67 |
+
"hit@2": true,
|
| 68 |
+
"top1_score": 0.2345
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"query": "What KPIs should a warehouse manager track?",
|
| 72 |
+
"expected": "kpi_overview",
|
| 73 |
+
"retrieved_top1": "kpi_overview",
|
| 74 |
+
"hit@1": true,
|
| 75 |
+
"hit@2": true,
|
| 76 |
+
"top1_score": 0.2838
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"query": "How can automated warehouses save energy?",
|
| 80 |
+
"expected": "energy_efficiency",
|
| 81 |
+
"retrieved_top1": "energy_efficiency",
|
| 82 |
+
"hit@1": true,
|
| 83 |
+
"hit@2": true,
|
| 84 |
+
"top1_score": 0.4366
|
| 85 |
+
}
|
| 86 |
+
]
|
| 87 |
+
}
|
data/sensor_dataset.csv
ADDED
|
@@ -0,0 +1,1001 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
motor_temp_c,vibration_mm_s,current_amps,belt_speed_mps,label
|
| 2 |
+
51.449217377141764,2.095295586480196,13.886668426304164,1.5128057072403882,0
|
| 3 |
+
58.228033127777884,2.6869095358586548,9.567112309754686,1.515025445699021,0
|
| 4 |
+
59.00698159060603,1.464442382807555,12.72036172876765,1.7973390450218385,0
|
| 5 |
+
48.232149403320946,2.0039801020646344,10.1108803999408,1.4916081851932097,0
|
| 6 |
+
45.66553552060678,2.6022851507924183,13.46937801173396,1.682322362474654,0
|
| 7 |
+
56.55081256504806,1.0929063144784987,13.14322386293803,1.3552480912830736,0
|
| 8 |
+
53.35344671113516,2.799259918258347,15.160327099917218,1.5877871297038284,0
|
| 9 |
+
54.655597392715805,2.8304686617814925,12.0839090251986,1.3462231208333737,0
|
| 10 |
+
57.66629067443814,2.2352095636636444,12.674722989834802,1.3760485234756639,0
|
| 11 |
+
56.25405538980078,2.693068158480384,11.950057890724594,1.5831495006948586,0
|
| 12 |
+
52.68842356768938,1.062131798139124,13.235581390565688,1.290924727194806,0
|
| 13 |
+
53.290989414653865,2.7523396077012654,13.094743183523294,1.5833868046949164,0
|
| 14 |
+
54.240304635910974,2.5746114636004274,10.525347108512587,1.4629764306732622,0
|
| 15 |
+
66.40446587435633,6.1553070769977145,15.970225700046807,1.410237827528495,1
|
| 16 |
+
79.42402862276309,4.692434778727042,18.20331727355799,0.9204302890313156,1
|
| 17 |
+
48.85743172029552,1.9784939233792664,10.707026467029937,1.7094137353867116,0
|
| 18 |
+
56.92057361356645,1.5397555079214815,12.610895840603202,1.4865403845132572,0
|
| 19 |
+
50.31211362839682,1.7082920106704849,10.964826688272082,1.4907502021190189,0
|
| 20 |
+
57.54148457144511,1.6499322231378473,12.069087207865673,1.2881038466098167,0
|
| 21 |
+
50.286785507540536,2.8624778396908157,13.158809711374142,1.1932907605492769,0
|
| 22 |
+
57.65066388154194,1.9033899075648206,13.124185523109846,1.5278751866278373,0
|
| 23 |
+
49.888249702721524,1.7435610066405864,9.989465687968194,1.5175470351035831,0
|
| 24 |
+
60.315842361747954,2.924672400618152,10.383625128594431,1.5311625896421186,0
|
| 25 |
+
55.525943267221805,2.6605753731973962,14.204905846411847,1.4905879974046987,0
|
| 26 |
+
58.663610169424054,2.9436991448429315,10.103187012078129,1.4272515413607414,0
|
| 27 |
+
52.383414239728815,2.8442221246591264,13.105254796380077,1.0890700316565782,0
|
| 28 |
+
60.19691319114426,1.8353565318131695,13.606956808394424,1.6454706731087618,0
|
| 29 |
+
70.72368720574445,5.104730155104767,16.547282104709303,0.5628084712711698,1
|
| 30 |
+
69.66285988669125,4.610777704265326,18.448359816896794,0.4433057308175821,1
|
| 31 |
+
75.64168237448382,6.5799995973156795,25.848760332770766,0.30899549040852725,1
|
| 32 |
+
52.63558629923558,1.9939253107715165,10.585980128202989,1.5727954924594711,0
|
| 33 |
+
66.65544986402932,2.5387006843461513,10.797571738847324,1.5113099314719094,0
|
| 34 |
+
55.128430695883736,0.8251619901847125,11.578899898723932,1.453026909163758,0
|
| 35 |
+
49.01975667909118,1.495090285526095,11.54082142731007,1.4372597414454287,0
|
| 36 |
+
55.045704222242634,2.9684828269588226,10.72377056642596,1.6288569087266604,0
|
| 37 |
+
54.97951253311972,2.686831755672045,11.203767257805529,1.3705799970640096,0
|
| 38 |
+
60.99349776118693,2.6713829006126377,13.27193811519555,1.424907278101702,0
|
| 39 |
+
57.85758593052263,2.588804765139268,13.026056869676072,1.388922626924832,0
|
| 40 |
+
92.50683321669868,4.430164654393557,17.128125940047706,1.0987578389343842,1
|
| 41 |
+
58.873113418365925,2.4040180884406337,9.904556913373302,1.630796324957851,0
|
| 42 |
+
50.31197122962074,2.4797701853080834,12.63343352868804,1.3738576291994313,0
|
| 43 |
+
49.70920155058239,2.583411435892122,9.673470881477918,1.5840493767348385,0
|
| 44 |
+
61.975738104671166,2.107021661406976,13.36685706685342,1.4368270526014266,0
|
| 45 |
+
69.83389843255519,6.808566389366279,15.803225080557821,0.6994984894935893,1
|
| 46 |
+
56.31198193485644,1.6708594745811816,14.31523928402183,1.4498818899929538,0
|
| 47 |
+
50.55035411206633,2.2743135476514156,12.080628844485753,1.4812433376210175,0
|
| 48 |
+
77.61677648925304,5.379066500864816,18.17736581987946,0.9037541278264591,1
|
| 49 |
+
52.6898444505774,1.8876982958924107,13.470286307507733,1.8092698729097412,0
|
| 50 |
+
56.71156176277967,2.0930977209547548,11.54254017193035,1.795829392791572,0
|
| 51 |
+
60.70994113473802,2.1052222442303608,11.679070284208782,1.4497601944089589,0
|
| 52 |
+
49.20749096233981,2.254742679723544,10.34900810364846,1.6622175704442799,0
|
| 53 |
+
54.88807017387913,2.9311776317366807,12.680993447170438,1.299368446006066,0
|
| 54 |
+
53.934450039964176,2.018369676215597,14.583539912993473,1.4958849968724415,0
|
| 55 |
+
53.98993066278814,2.0046611987004024,12.063946536656621,1.3850526975576443,0
|
| 56 |
+
54.38188207172479,1.9142753904016314,12.96683761797597,1.526947002117008,0
|
| 57 |
+
63.56659040348185,2.203008340218036,13.120908076715182,1.3245584996281758,0
|
| 58 |
+
55.966578086707,2.8560126311099574,11.051871265786634,1.3995007354682667,0
|
| 59 |
+
58.51759189945131,1.82412207609325,9.070776704927628,1.4924057830414514,0
|
| 60 |
+
55.96998716508489,2.2015542750928185,10.815020469198595,1.5336434099125387,0
|
| 61 |
+
53.07503550453835,2.7236576430368795,10.973165963730299,1.3908948389011302,0
|
| 62 |
+
56.1839759587484,1.5860000595887516,13.306234155549959,1.318492072546645,0
|
| 63 |
+
53.11850938282882,1.8439489790605308,12.712692101022013,1.661851445885417,0
|
| 64 |
+
55.990663604435774,1.504657285012372,8.91785803848706,1.5389312648357307,0
|
| 65 |
+
53.66350623719675,2.6201100813470988,12.93851335739423,1.581581550616827,0
|
| 66 |
+
52.45353886759106,2.094133098727803,10.701090174251572,1.9632768292290426,0
|
| 67 |
+
58.80821461255956,2.113081149952692,13.148933179089349,1.380648173749412,0
|
| 68 |
+
51.39030762082995,1.7917124462722127,11.768083862070137,1.5323261953952634,0
|
| 69 |
+
49.63129933451637,1.5916407908067967,11.400676587617358,1.6076022686413016,0
|
| 70 |
+
49.89725470664831,2.0586021254262152,13.307901549779176,1.645158808016921,0
|
| 71 |
+
54.283093498200984,2.919352741179616,11.717120800490985,1.538736928049584,0
|
| 72 |
+
53.64386769639775,2.012579268551195,12.220983495729707,1.2126652253296508,0
|
| 73 |
+
56.81586231723478,2.4311062445053127,11.36009252541135,1.3229108490369765,0
|
| 74 |
+
50.110502749840386,1.8918534559039462,9.058731602295701,1.4674284580385528,0
|
| 75 |
+
59.75090037304775,2.4515243341884325,12.611592554427059,1.506976975532211,0
|
| 76 |
+
60.885967891972626,2.0716729418001236,12.197810719681728,1.4911436674042418,0
|
| 77 |
+
54.586046927736156,2.129506051277791,12.701729674364486,1.70755805417895,0
|
| 78 |
+
61.67155044447808,1.9091393253988769,12.81169625732706,1.6238506429955488,0
|
| 79 |
+
57.602371151298804,2.632984319208577,10.648961724430984,1.7088106381461383,0
|
| 80 |
+
61.44446459399848,2.289370481643164,11.93250718853549,1.3457243638588094,0
|
| 81 |
+
60.20017837879583,1.760245185670529,10.429069280424285,1.659049080716954,0
|
| 82 |
+
54.33228827956574,2.37286328990079,11.579897059678688,1.4582855560518135,0
|
| 83 |
+
53.60509971100625,2.0720839643295883,11.68645161595887,1.2267974487113043,0
|
| 84 |
+
56.543386210226004,1.3998970754782616,10.070804944936814,1.547699804162107,0
|
| 85 |
+
53.15059282934173,1.8289039530012818,13.017785927100043,1.7628971331826409,0
|
| 86 |
+
58.95833573837941,1.6023205128509488,12.322647203728554,1.5567958985757053,0
|
| 87 |
+
57.827398563596205,2.046717189356471,14.253043877764696,1.6308523019942653,0
|
| 88 |
+
71.62772244692067,6.5070416261827155,17.408759875379364,0.7051188871215508,1
|
| 89 |
+
54.15723994254737,1.8609642357532505,12.185610021617086,1.3341247226771824,0
|
| 90 |
+
63.19502260345315,2.0071850092384196,8.872457554980183,1.608183805919969,0
|
| 91 |
+
54.7321873084072,1.9116763538831538,11.214340832188148,1.2962604907711817,0
|
| 92 |
+
48.5909618357643,1.1929487025673553,9.206272871062808,1.5344190546687644,0
|
| 93 |
+
56.39510357618518,2.481136435957247,11.87322017773279,1.3636503458229423,0
|
| 94 |
+
60.34313734528093,2.395265298159759,13.71037992141642,1.2507742620392235,0
|
| 95 |
+
54.381977283000396,2.3760172359014624,12.872775658960618,1.3470359721927805,0
|
| 96 |
+
54.18834406081781,2.3239737804259377,14.115242992952904,1.5398292973674708,0
|
| 97 |
+
52.86439904650578,2.4342763892531014,11.94135161817517,1.6898662387749832,0
|
| 98 |
+
56.363165632008425,2.7956948201457075,13.700353054313437,1.5737178884909386,0
|
| 99 |
+
56.92298663562364,2.048690120264777,9.658195616716679,1.4134952266608747,0
|
| 100 |
+
57.344889325437116,2.145136274152855,13.536148259761537,1.6333690976290511,0
|
| 101 |
+
55.1236691121308,1.7297348922493918,14.02961036631309,1.557708497187785,0
|
| 102 |
+
48.746088208525244,3.6571223242077098,12.016474338873602,1.5172697051261714,0
|
| 103 |
+
58.386335943373616,2.9583963285696244,13.097238611911402,1.359864140377806,0
|
| 104 |
+
76.41845909905054,4.914376118125679,20.445387292161303,1.259918934103251,1
|
| 105 |
+
56.73906429786648,2.2006699233772435,11.26071034665666,1.5796834842888872,0
|
| 106 |
+
53.855108200637325,1.7202861234290663,10.562982598948157,1.4577945012141449,0
|
| 107 |
+
53.650699351725976,2.881925162466345,13.22901464558962,1.2797604360196728,0
|
| 108 |
+
54.65162331578996,2.933590625354521,10.222223129201524,1.444444408550834,0
|
| 109 |
+
78.02584585405896,3.5,19.987028177865227,0.6513374511599186,1
|
| 110 |
+
54.37344840936764,2.922562978463267,11.354312499807063,1.5096884485414832,0
|
| 111 |
+
73.79193510141695,6.0339304750535465,19.458355534996052,0.7046111620919566,1
|
| 112 |
+
56.03291529329078,2.527329764223893,12.25421080678989,1.5923377931791933,0
|
| 113 |
+
46.53338220411788,3.161473097033289,12.317190228545876,1.2621594938099616,0
|
| 114 |
+
79.60664518495507,4.041212357833646,19.14035835061042,0.7133977428294936,1
|
| 115 |
+
53.39202967948318,1.9081598215969096,11.988649055053274,1.5669691531867782,0
|
| 116 |
+
53.122390639189106,1.4978654509546256,10.404660405847924,1.5016203127284022,0
|
| 117 |
+
54.4756533972491,2.63827180204076,10.069638839195438,1.507774814848927,0
|
| 118 |
+
56.715025753846454,2.2551978628061096,10.821035088102967,1.4997122399986418,0
|
| 119 |
+
73.87837427000493,5.414599613376296,15.745443119447255,1.1233000766249028,1
|
| 120 |
+
48.736963711277944,2.318474305772975,11.262688760764252,1.4272903857676509,0
|
| 121 |
+
54.052598941961264,3.1668967425940937,12.14188879943655,1.4271905695628815,0
|
| 122 |
+
53.36644549098109,2.3369211991542285,11.90502021043356,1.7701485901033105,0
|
| 123 |
+
53.567933247702285,2.6837331364625054,12.351447540565346,1.583492499851633,0
|
| 124 |
+
54.95166139684693,2.2392993530575187,13.207320848793568,1.4462905995643238,0
|
| 125 |
+
54.04730502410134,1.6064647868128152,9.829493135377476,1.3096365577710283,0
|
| 126 |
+
54.34933631782037,2.2186139182107887,13.494832326747606,1.7132440467123313,0
|
| 127 |
+
51.444810747076325,2.3786597113553136,14.357003724123551,1.4493855368840738,0
|
| 128 |
+
50.71146791429256,2.3649717693286325,11.22447866256846,1.6956770545673328,0
|
| 129 |
+
49.092568732617075,3.3549222110450394,11.069222069027008,1.5558488340090457,0
|
| 130 |
+
53.372225004909765,2.6210634795688166,11.592935260602413,1.3214484767747445,0
|
| 131 |
+
51.619818688123395,1.6360234882471656,11.184325793470915,1.4634707937412708,0
|
| 132 |
+
47.90015176143149,1.60926046603559,12.883054917322726,1.5227311193647899,0
|
| 133 |
+
58.87599148110343,2.6464279081614777,15.589015084527363,1.585266645839192,0
|
| 134 |
+
59.05086327127931,1.769579160738215,11.740693376334846,1.2600075998873483,0
|
| 135 |
+
73.26146351925132,5.294520707089209,15.003753669966793,0.6963635478473466,1
|
| 136 |
+
61.25887208667962,2.5727494532624915,13.499511029807984,1.282086367985678,0
|
| 137 |
+
52.444488607026635,2.885270494307066,10.962099455738086,1.3203617566448764,0
|
| 138 |
+
50.906010029512544,2.369937680596352,10.359394407424993,1.2688898255603878,0
|
| 139 |
+
59.011031301218416,2.239494358170005,12.238946675744462,1.7916896688390342,0
|
| 140 |
+
53.59146579804708,3.141087440102025,13.010691590501636,1.4443934423290343,0
|
| 141 |
+
51.322190855993554,2.3115610092030834,11.075710890013958,1.4633506717230707,0
|
| 142 |
+
55.46674323656291,2.344679578478556,10.03455487535184,1.6529266376496945,0
|
| 143 |
+
62.34765411328526,2.007877043559715,12.746884401404067,1.563370113635584,0
|
| 144 |
+
59.512075429397214,2.223278736663931,14.673440689057069,1.4826997507788995,0
|
| 145 |
+
48.02165605210323,2.627342865067781,12.580588094093615,1.7317848227544839,0
|
| 146 |
+
55.15432449192367,2.049617707576633,11.451424821530686,1.5672213216940059,0
|
| 147 |
+
66.88363282985833,4.5618517243200065,21.871855874556857,0.22892235038219366,1
|
| 148 |
+
54.19166701844238,1.9095199057342587,9.497948100166354,1.5766061923820271,0
|
| 149 |
+
63.516988448113196,2.2072639409687844,9.931276122977119,1.4801848180780313,0
|
| 150 |
+
50.35168194906285,1.8686492958223684,14.306036327846703,1.453159770809002,0
|
| 151 |
+
54.237395769979365,2.845281881160587,12.066325504350274,1.7251853795740815,0
|
| 152 |
+
55.68784132974824,2.147520921999914,13.109538762619385,1.617319235864211,0
|
| 153 |
+
53.00281760584339,2.2591739566941023,11.570450796202236,1.4490592461590146,0
|
| 154 |
+
81.66504618682013,6.0518803195693245,19.798885016808402,0.8238487316623401,1
|
| 155 |
+
56.571309873039674,2.5710144514897455,12.415934296816271,1.5554558888458696,0
|
| 156 |
+
87.98865635248963,4.590865930549303,18.780181476450256,0.8086978185246235,1
|
| 157 |
+
48.64173002676412,1.3333954483955086,12.20730769402992,1.583219478258797,0
|
| 158 |
+
61.929246421639775,2.348755535592778,12.3170797125724,1.6109446807479844,0
|
| 159 |
+
51.14544622252478,2.319300395464222,8.711184763788888,1.4609657054155318,0
|
| 160 |
+
48.26852091353678,3.008437199249304,12.983427091757074,1.395830213711197,0
|
| 161 |
+
50.62670456845047,2.5438805657999364,9.77169126071659,1.546350353412855,0
|
| 162 |
+
53.30557357415665,1.6480056823141696,10.260241071349553,1.5930558590897037,0
|
| 163 |
+
52.7752321646035,2.200999678207544,12.659274216437144,1.2156022201280905,0
|
| 164 |
+
53.43814420214876,2.397754553181254,13.228656253368207,1.362442658030886,0
|
| 165 |
+
62.39130005182418,1.4164708748822812,11.197369269934931,1.5097414631326114,0
|
| 166 |
+
58.3241274306719,2.1278578107398727,12.178194809854352,1.7514892197368543,0
|
| 167 |
+
52.90912521532128,2.5648578368918544,12.992921384145776,1.5454652827425495,0
|
| 168 |
+
47.97311287008567,2.9424593933669256,9.28778392969388,1.6229171358926846,0
|
| 169 |
+
53.30090508882763,1.972236077498285,11.996624633243764,1.4233748161420476,0
|
| 170 |
+
58.31195270718823,0.8741458325403992,12.734075908407613,1.6480871029475115,0
|
| 171 |
+
59.70964755591078,2.6433795272023692,12.585682398080824,1.8539657901494417,0
|
| 172 |
+
56.53357545741398,2.2487067064788913,10.584069712916996,1.5298857061873858,0
|
| 173 |
+
65.39069490638333,2.936805696126548,9.023785165306506,1.557003494857292,0
|
| 174 |
+
56.73769457418343,1.5825934565442608,10.829349818033323,1.4048503509711683,0
|
| 175 |
+
86.10102030757207,4.908557262610718,17.18535444828215,0.627581270301255,1
|
| 176 |
+
51.88207041309832,2.8243788862052535,13.0462324678815,1.3528350948797678,0
|
| 177 |
+
50.76585567208636,1.9764211713350268,12.950132311541024,1.5255762279029474,0
|
| 178 |
+
54.018888616231564,2.5489084195000027,12.549676719857326,1.1807745687021283,0
|
| 179 |
+
49.500416766520075,1.4911579149202154,10.360657138351876,1.7926415224030037,0
|
| 180 |
+
56.37841961900143,2.2707097366702724,11.86824648209445,1.59537650073989,0
|
| 181 |
+
56.68075439489975,2.714390459872755,12.317570676255896,1.4581168621182474,0
|
| 182 |
+
53.76530777781435,1.2643909419695065,13.747416667782192,1.4826294735042351,0
|
| 183 |
+
58.13937614643254,2.212564355608017,11.308460579128743,1.461725373746782,0
|
| 184 |
+
46.985910831733946,3.0100351545680257,12.76159267745738,1.2411968606988446,0
|
| 185 |
+
60.820182305082845,2.61221353119249,8.67078861206542,1.3628135582508973,0
|
| 186 |
+
56.461897890571336,1.8126740718689687,11.765367781285052,1.402641037043808,0
|
| 187 |
+
58.352506271577525,1.9211143270052884,10.257098390429869,1.5346008453570938,0
|
| 188 |
+
55.93151208054867,1.8857576349316054,12.901438927049846,1.3292509909558585,0
|
| 189 |
+
60.92582219063589,2.142250560350533,13.870817131713675,1.5006199323982299,0
|
| 190 |
+
77.45808593846922,3.5,19.740082692606542,0.6486530223667051,1
|
| 191 |
+
51.42747751366055,1.8529307194271674,12.749682156443699,1.4943367448327205,0
|
| 192 |
+
86.20440916643054,4.627690049283812,21.1659155874626,0.8833639875576256,1
|
| 193 |
+
44.30866226758825,2.2187616161697994,11.936349284881338,1.4831754149834124,0
|
| 194 |
+
51.52381100854087,1.8356947573702365,13.493908027233386,1.4067807048633338,0
|
| 195 |
+
54.34622840590195,2.820979998406906,15.321228923687867,1.6212821624403027,0
|
| 196 |
+
53.063322266665686,2.0797814014648286,11.98470582656243,1.1647446753152,0
|
| 197 |
+
47.027758515783376,0.811002859635714,12.91626737461628,1.3059742710992437,0
|
| 198 |
+
52.204278285685014,1.607935834050864,11.432941062402785,1.3155738903960603,0
|
| 199 |
+
51.487390532285,2.8517825339040437,13.783176171530812,1.3201324310782154,0
|
| 200 |
+
56.78528859017226,1.2012666535550705,9.83797380039892,1.5207335138211455,0
|
| 201 |
+
57.502361575869344,1.4915789537015631,14.137993415205457,1.569824516124942,0
|
| 202 |
+
56.72328401203153,2.237856643978417,11.660318123183792,1.310335445823418,0
|
| 203 |
+
57.54988361060449,2.1582756083867034,12.126991921099146,1.5818690639774928,0
|
| 204 |
+
51.870334664154214,2.426269209489796,15.31596131608986,1.590163775612144,0
|
| 205 |
+
50.870949317688655,2.2453712818760865,12.485985384408217,1.7466452565350536,0
|
| 206 |
+
53.69495197990784,1.5158328512244414,11.506185902461487,1.6406284382624636,0
|
| 207 |
+
52.91764634857836,2.361398732046624,11.337134974380465,1.5663333093054899,0
|
| 208 |
+
51.388291287651896,2.1698740767993567,12.727640802745668,1.3113926287527944,0
|
| 209 |
+
80.08921809566891,6.046358126099891,22.900877324686146,0.9664125761928686,1
|
| 210 |
+
58.742188501860596,3.13115878069744,13.391613599326808,1.6587829224212722,0
|
| 211 |
+
47.55261938702996,2.7636773808212114,11.171962906482635,1.361931636562605,0
|
| 212 |
+
58.173388940799704,1.5176291738992176,12.23584926515429,1.3958935014213538,0
|
| 213 |
+
51.04184751987254,2.6869470641087005,12.142240289595563,1.664409634958577,0
|
| 214 |
+
90.13265370512086,7.164391275890606,18.360442164393543,1.166507257450395,1
|
| 215 |
+
54.52955657829952,1.9353638466500536,14.199304229438523,1.3014617547897915,0
|
| 216 |
+
56.277601055164915,1.8858144459402608,12.134389151052652,1.094427347988999,0
|
| 217 |
+
57.55013524359079,1.6386157838645028,15.506767678758248,1.5857788773955064,0
|
| 218 |
+
54.67364892125951,1.7298893955371417,10.945867560268194,1.5728533438785772,0
|
| 219 |
+
50.31373348469863,2.7150977015763655,10.315564426339305,1.6753905163605256,0
|
| 220 |
+
86.80849093599178,6.21633507677066,19.397740605472514,0.5856479343390539,1
|
| 221 |
+
54.113855537076795,2.091157653282672,13.357889102240932,1.5740147982275543,0
|
| 222 |
+
50.7884059571842,1.8628937691377456,11.23190787102131,1.4306217924085762,0
|
| 223 |
+
56.112574905818505,2.341534294004995,11.737547944928734,1.30811190417371,0
|
| 224 |
+
89.84112862088202,4.376414469945647,20.004372298299366,0.9888301768869812,1
|
| 225 |
+
55.270316277955565,0.3757935873926084,12.992067284837562,1.6124648330487186,0
|
| 226 |
+
52.29593077727453,2.0363472848724884,12.742909419102897,1.435866827800572,0
|
| 227 |
+
58.00180478322583,2.1262787550409166,11.543359855715,1.6253065490853347,0
|
| 228 |
+
53.98648972420794,2.127986169972662,13.217603564994754,1.5727683838304372,0
|
| 229 |
+
56.473426450802634,2.6836496179213865,11.904736988342597,1.649378808655854,0
|
| 230 |
+
78.42081311019676,6.126832256601363,21.457290516154405,0.4145318191444824,1
|
| 231 |
+
52.84491472952903,1.9800061477351458,16.15115383804839,1.66459912608043,0
|
| 232 |
+
61.46483872660483,2.7224364062272137,10.92077768103218,1.5301275445913896,0
|
| 233 |
+
85.69675713661628,3.7274284418650874,20.568734741679613,1.0805686945819324,1
|
| 234 |
+
60.732858026424694,0.7664725231086285,12.02003338731551,1.275294033691343,0
|
| 235 |
+
49.18071005896884,2.1186005016836966,8.341125542141077,1.330202033988456,0
|
| 236 |
+
51.74490908700849,3.0236969988016646,12.621924427540055,1.430649044171807,0
|
| 237 |
+
53.37433993446154,2.42416203298658,12.086115107157237,1.3047098144754743,0
|
| 238 |
+
52.637171944146054,2.0684632877718236,11.259797686269186,1.6304513635041737,0
|
| 239 |
+
79.88847783353752,6.208384687583669,23.106835754844074,0.7634647997883999,1
|
| 240 |
+
53.467250715456046,2.597466126457814,12.347490666354776,1.4858977238872266,0
|
| 241 |
+
50.9451305342384,2.2432527709607313,12.486133833480071,1.5535693014406982,0
|
| 242 |
+
58.76225886556485,2.9941380535746314,11.385526607447996,1.6779213753178246,0
|
| 243 |
+
46.799311595875906,1.6513311627264784,9.892812678584509,1.4386651364686815,0
|
| 244 |
+
58.16322448676032,2.8839537253604854,12.744181062133178,1.6525465572356783,0
|
| 245 |
+
55.15565282760584,2.301816589354901,13.557434893475728,1.5892035317055275,0
|
| 246 |
+
53.662175310576494,1.8438314677936458,14.10132279046945,1.2039475985387098,0
|
| 247 |
+
48.0907183072306,2.389421301729197,12.653187503936127,1.2935935002640278,0
|
| 248 |
+
50.837824243369866,1.2610056170170463,12.727622650596194,1.6002626527929014,0
|
| 249 |
+
55.634158764306854,1.993831563897635,14.713371813124155,1.4304299337972848,0
|
| 250 |
+
50.21664141764384,2.3871932258531317,8.988160423792994,1.557715281630749,0
|
| 251 |
+
56.054868817426076,2.0419011477094062,11.857071319479099,1.531580200618387,0
|
| 252 |
+
53.547784613739715,2.3147408577318034,11.314785028892004,1.5751628148933698,0
|
| 253 |
+
77.48635621355311,7.358470670155434,15.466206690868368,0.589766658141087,1
|
| 254 |
+
54.39579248957228,2.636528300046372,12.936276408704298,1.4644110421353898,0
|
| 255 |
+
53.75301467671021,1.2739190722993994,14.098704572544131,1.443510791546477,0
|
| 256 |
+
57.120258822405866,1.6212676838832891,11.677276251343306,1.80198696821919,0
|
| 257 |
+
58.00347595492504,2.59127941285758,12.101506887094065,1.3856706103444127,0
|
| 258 |
+
61.515747790495965,2.2140110935129385,11.594404586856838,1.6502750954324112,0
|
| 259 |
+
85.14956168509539,6.422977002360169,18.84298319214011,0.8050903730515668,1
|
| 260 |
+
72.69944906347419,6.62213051322734,18.84061433752338,0.5695134511277214,1
|
| 261 |
+
49.79128197255073,3.230149085262039,9.118626111157228,1.4735680411557037,0
|
| 262 |
+
55.23309732374179,1.7846150591973324,12.813292928586383,1.7105205577151257,0
|
| 263 |
+
53.165298860242665,2.3884738928476863,13.184049833504558,1.5510660665252318,0
|
| 264 |
+
51.011012689594075,2.260588974649731,12.679528134468258,1.4613718201635313,0
|
| 265 |
+
55.621717310673866,3.428712046037946,13.446826023359,1.7114859325912541,0
|
| 266 |
+
56.0813729571269,2.180730869078294,10.785819406354008,1.428823059957144,0
|
| 267 |
+
52.660503460267996,1.741123231291243,11.970147493640122,1.5735910353683833,0
|
| 268 |
+
59.103347371540956,1.3311427024314342,9.129330397756611,1.4652829803466814,0
|
| 269 |
+
55.43152177737213,2.796809285928189,15.181715103950502,1.4300375240988847,0
|
| 270 |
+
65.197311810428,2.354695785078473,13.541371605830733,1.4947981124972116,0
|
| 271 |
+
60.23820273944211,1.1146922951022944,12.351646674723147,1.333679553759294,0
|
| 272 |
+
59.34114801778364,1.8640439881601618,12.669992272918355,1.2866922350789802,0
|
| 273 |
+
61.40711556528366,2.031584016179704,11.52406991212134,1.612930825072332,0
|
| 274 |
+
83.80947355422776,5.439431112662294,18.202235648617563,1.0926951439501484,1
|
| 275 |
+
53.527004172847874,2.292028915635783,13.150300939993592,1.324548599846337,0
|
| 276 |
+
54.23462405321976,2.9005931375169483,12.017574626579048,1.2233819323248714,0
|
| 277 |
+
51.58782428970568,1.6618773998406162,13.441101461391696,1.4829969003240289,0
|
| 278 |
+
57.57330717875618,2.9895927514908163,12.455756138456344,1.6468262011855799,0
|
| 279 |
+
52.48964985425232,2.365144972808296,10.953664190105538,1.6463984924723762,0
|
| 280 |
+
52.3522962357334,1.434642371371647,14.133159524885334,1.400839635628929,0
|
| 281 |
+
58.576853314053636,2.814210406140076,12.509712861735647,1.6965059539300424,0
|
| 282 |
+
51.65014638365923,1.5134984915572307,13.002833014885104,1.6609886747683735,0
|
| 283 |
+
59.236894955585285,3.387303275013216,12.430336677438907,1.661897348464818,0
|
| 284 |
+
52.88224229053571,2.2018981258107297,12.441889263837568,1.387391307260233,0
|
| 285 |
+
53.99209048717246,2.9658894453005265,12.292655959714333,1.596109366530438,0
|
| 286 |
+
49.694429129041744,2.064162808156354,14.665774260386586,1.78318859572942,0
|
| 287 |
+
57.742996141098644,1.3115066803369626,14.153991026651571,1.6416623802810408,0
|
| 288 |
+
54.40988527903859,1.9588837606485396,10.884208609356548,1.452631577076749,0
|
| 289 |
+
56.53350845272988,2.1454274242193327,13.748508134825729,1.535872392695019,0
|
| 290 |
+
62.50737844512668,2.1507769988460606,8.097167527422467,1.5415229593996231,0
|
| 291 |
+
86.57719184741063,5.161565142652067,20.477766286076392,0.681901688277796,1
|
| 292 |
+
86.53857089706972,3.5,18.765036418038445,1.2923746871339516,1
|
| 293 |
+
58.982805543599696,1.9671159175709612,13.856825531878096,1.6505214436316495,0
|
| 294 |
+
58.580739927886746,2.038007612251785,10.664968875354596,1.674524372145971,0
|
| 295 |
+
50.53046354804157,2.0101567374287197,12.716416094635155,1.4032709540044006,0
|
| 296 |
+
58.99929698764118,2.597889004872117,13.951737522978046,1.8707713614083203,0
|
| 297 |
+
59.42397347962919,2.822817480085937,9.23049448331928,1.3623436538249611,0
|
| 298 |
+
70.2555207785063,4.9645536827832855,19.70452137170888,0.9625948745620108,1
|
| 299 |
+
49.47127393849184,2.1380953528351703,15.278795649626439,1.391078339597046,0
|
| 300 |
+
53.73502963062567,1.561491777514886,11.999155354315562,1.070772244484899,0
|
| 301 |
+
62.07171965431953,2.936007283245067,10.463206630630491,1.736306497415331,0
|
| 302 |
+
51.69508213454419,2.3802958388284208,11.714892490648882,1.372096032804777,0
|
| 303 |
+
54.24302263625438,1.8010586181907526,13.844063576475156,1.4716131455147412,0
|
| 304 |
+
55.366080712692835,2.0412807225811593,13.657410733436588,1.3931918750725556,0
|
| 305 |
+
52.62239859120506,2.188876102575395,12.128990221121438,1.603147872676352,0
|
| 306 |
+
55.241543713697666,1.8369924511495117,13.899456835754048,1.6706935154100073,0
|
| 307 |
+
78.30991028668389,7.059216316664248,16.97277764047853,0.8879715263686692,1
|
| 308 |
+
55.13112837150504,2.3635049343946575,10.801791382660527,1.6637375429066208,0
|
| 309 |
+
60.34474440004868,3.2479993751127196,12.756666971493702,1.6441640229180323,0
|
| 310 |
+
76.97130101107324,5.5851936585099375,22.577747913973244,1.0189460452232755,1
|
| 311 |
+
52.388335421341154,1.5198708168553368,11.418318066676065,1.494160619927274,0
|
| 312 |
+
49.875723172616674,2.023192629193178,10.668804262886761,1.4125509174503899,0
|
| 313 |
+
53.552918090223315,2.0645359349210963,10.646833292728424,1.4326683569579424,0
|
| 314 |
+
50.37460935893867,2.4816565367582126,13.185510872677057,1.6152905648244553,0
|
| 315 |
+
57.23419583709689,2.2976315157398863,12.538194125859382,1.7506681842844871,0
|
| 316 |
+
59.45836977830951,2.6579651511397993,11.917943344726092,1.766507977067643,0
|
| 317 |
+
63.30792211621501,2.376313601958586,8.42809898981712,1.4798959168785952,0
|
| 318 |
+
51.58702659776472,2.0780519449113313,12.30811579044189,1.297436787291692,0
|
| 319 |
+
52.71622535391282,1.801544505351655,10.72988386067397,1.3644698330135592,0
|
| 320 |
+
50.439356323495076,2.3875310759461703,13.623527894687603,1.7815704712997462,0
|
| 321 |
+
55.12252597037767,1.6238755793616164,12.98819605254929,1.4998320417003164,0
|
| 322 |
+
53.76261384111905,2.4219063546915525,9.560873267060225,1.3483696623215524,0
|
| 323 |
+
59.26392092315057,1.7221874162993012,10.693175891961278,1.617929890297937,0
|
| 324 |
+
58.455312054792756,2.410113354737293,10.929270754171933,1.7949191207063384,0
|
| 325 |
+
50.83765578995027,1.1326531662615722,11.97474491439986,1.3989222467729159,0
|
| 326 |
+
56.58796521799536,2.3822625189964013,10.554337219148417,1.4665766736364183,0
|
| 327 |
+
64.68166004898961,2.3279534250521117,14.903071775293665,1.5719535795896296,0
|
| 328 |
+
55.28813429293031,3.0417931047690114,16.05597766091908,1.3665294015977385,0
|
| 329 |
+
54.318369675343185,2.2470915291161564,12.544513871571775,1.2948086583927205,0
|
| 330 |
+
57.80665459235827,2.0738129375077583,14.560151460628461,1.196632941593478,0
|
| 331 |
+
54.111109211604905,2.442580556272869,13.940264952689056,1.350646465973729,0
|
| 332 |
+
54.77218183514589,1.4891181753277136,12.726680158872632,1.6577782290791279,0
|
| 333 |
+
56.75634671571831,1.9554612659405384,12.744514551511097,1.4470134462258588,0
|
| 334 |
+
45.877048618512305,2.580927387021232,11.679304707225066,1.6596468279370773,0
|
| 335 |
+
45.34887867628204,2.5086407902461296,14.733082832014263,1.4608103413438118,0
|
| 336 |
+
56.21886831901772,2.3948458526600014,11.940440576479533,1.628581553033492,0
|
| 337 |
+
55.26618326343682,1.294690660009803,12.09404745485507,1.4053557604301805,0
|
| 338 |
+
51.357700464314206,2.4540395525995327,14.282550679105437,1.6064492798456815,0
|
| 339 |
+
50.96585583222757,2.958220050294702,10.96234538549653,1.2975198881556427,0
|
| 340 |
+
57.897130709824914,1.5523294077669827,11.303429411706826,1.5544894618871297,0
|
| 341 |
+
53.20574316788658,1.7659032846796103,12.39113157621175,1.3387067429667938,0
|
| 342 |
+
50.432247095430384,2.288630683474428,14.829283737834123,1.5265679745007545,0
|
| 343 |
+
57.08466902292845,2.0744487059815437,13.621284307426308,1.4893926612413306,0
|
| 344 |
+
53.18006607863688,2.085353673223846,12.157035044832188,1.3389576406293648,0
|
| 345 |
+
56.42748423659804,2.0177808738677694,10.21140700433635,1.4825600032034452,0
|
| 346 |
+
57.80781450488508,2.3288202104605804,12.259510709478338,1.77393140203602,0
|
| 347 |
+
55.36850663373644,1.8197455759643177,12.139019169043506,1.5500323517454306,0
|
| 348 |
+
56.185672003234636,2.1473879328745644,11.94412612117181,1.289225345898456,0
|
| 349 |
+
86.74902484487465,4.562570768623593,19.752782917751734,0.830682096030153,1
|
| 350 |
+
57.66154043589115,2.6352778047098635,13.536769013140034,1.7219385560476403,0
|
| 351 |
+
69.92363203293007,4.931103431960366,18.576034068756773,1.3441359101792056,1
|
| 352 |
+
55.87753000545543,2.124376176626812,11.159325796795386,1.6340698118903185,0
|
| 353 |
+
61.29341960990097,2.1575747341689953,12.08474503798985,1.5178685894049417,0
|
| 354 |
+
59.19735844217363,2.0371509449631358,13.431522493637546,1.8739108299957778,0
|
| 355 |
+
54.23478270047354,2.217305937092628,12.35335480595984,1.6154843971912147,0
|
| 356 |
+
55.610250048409874,2.7037553854932797,12.9441060091533,1.744110200919703,0
|
| 357 |
+
49.49325540977476,2.301387524126184,11.394611822220998,1.647100994149114,0
|
| 358 |
+
61.90940085665674,1.5387294333541606,12.384988096068392,1.6873534045310243,0
|
| 359 |
+
51.44746458506539,2.3143850144644693,10.350512481233487,1.5363966406985794,0
|
| 360 |
+
48.71183897738704,2.564357117037173,15.309787960710603,1.6103600040420245,0
|
| 361 |
+
51.7482356187587,1.8188382709861741,11.43048529372774,1.4003119991612105,0
|
| 362 |
+
49.07785394973993,1.4185578273300754,10.80893468745172,1.5819167746338672,0
|
| 363 |
+
45.3603121368005,2.4249891706732742,11.589444006273348,1.7615432800937347,0
|
| 364 |
+
50.937683675169836,2.1993036742783256,14.40634365702752,1.4838699383600904,0
|
| 365 |
+
54.47544987918662,2.0735592768410847,10.445127037695514,1.54057280791653,0
|
| 366 |
+
58.35395681494538,1.8778164398934887,10.898418363913049,1.3370889626081282,0
|
| 367 |
+
56.65093044638395,2.0838653350378826,10.685835113658063,1.7761883421640356,0
|
| 368 |
+
60.40250048381063,2.4250103367109164,12.274372095193058,1.5825650266402178,0
|
| 369 |
+
60.84577716896881,2.2901819715131992,13.447755739093,1.4005239374044853,0
|
| 370 |
+
56.10509671731422,3.2017547052006714,15.01638916860077,1.5231119988223303,0
|
| 371 |
+
58.63440543956845,1.8718145532259458,13.92988519693085,1.6550714162098465,0
|
| 372 |
+
54.83694989545826,2.161321910089573,13.194816045779996,1.5858363630280912,0
|
| 373 |
+
51.096164735540384,2.8790605479336304,13.379135514970478,1.3128558301284312,0
|
| 374 |
+
56.65763773310398,1.7226040914345895,10.088072396976742,1.4748188895860532,0
|
| 375 |
+
50.097576944931006,1.4036028701392365,14.544880024456276,1.215743122507818,0
|
| 376 |
+
55.51136161266914,2.0872842753859504,12.715552690839687,1.560046486246451,0
|
| 377 |
+
58.723352905402116,2.226728956308737,11.269329658777233,1.4506620194499935,0
|
| 378 |
+
55.025356249449075,2.34561570842369,11.180193310457433,1.5940664400223747,0
|
| 379 |
+
56.988642976215054,2.50840709984489,10.208451778913311,1.4754353843816697,0
|
| 380 |
+
81.87067612596672,6.064540426684205,19.668850715316385,1.3057781729269635,1
|
| 381 |
+
52.984169034357556,2.1434157951355517,11.411660980619576,1.6613584451241288,0
|
| 382 |
+
50.750342352561745,2.1556017761437496,10.509453184340275,1.4398117591020263,0
|
| 383 |
+
53.338570959281256,1.7703969907122152,9.295715705373176,1.343210582790229,0
|
| 384 |
+
57.04488725819014,1.5090254843181838,12.70473738480745,1.4576978277097186,0
|
| 385 |
+
52.083664649025565,2.117531112301891,12.170622230229215,1.386717087087447,0
|
| 386 |
+
54.104564732478,2.4251586390219066,12.022020209834567,1.3917008190394933,0
|
| 387 |
+
84.31244931614245,6.593473606228777,18.473202552308095,1.0997499293420148,1
|
| 388 |
+
60.45544891925564,2.791265370876329,11.264666774941837,1.4139495463712373,0
|
| 389 |
+
57.540603787257616,1.9498194613015503,10.705221506483584,1.6455746971295597,0
|
| 390 |
+
82.31008732136497,4.9277391723600665,15.961242852885762,0.9850324307233912,1
|
| 391 |
+
55.0482127224073,2.0862902936780583,11.890172514024268,1.3036357421418021,0
|
| 392 |
+
61.143023967983964,1.9958334185866655,11.565186576787696,1.5455200351225005,0
|
| 393 |
+
57.17261707322078,2.6431969797839763,12.01647827029129,1.597136115459253,0
|
| 394 |
+
45.71857595045542,2.3604248231623037,11.816874168042911,1.3644181065628689,0
|
| 395 |
+
58.36123254982958,2.578124081814903,11.29524523725191,1.5417499409355757,0
|
| 396 |
+
55.94179347323972,2.364183986415769,13.684641945662309,1.4390799531793521,0
|
| 397 |
+
53.89943099509326,1.9579849342136622,11.747022369899321,1.5958139072513966,0
|
| 398 |
+
53.93664483233849,0.9596457450077294,11.558478414709125,1.50669874214452,0
|
| 399 |
+
56.44768741571537,2.4194955146944475,9.909491273450742,1.465870587695517,0
|
| 400 |
+
58.42007729718912,1.3200921461522674,13.259352136161379,1.3585260113445916,0
|
| 401 |
+
77.00609714589586,4.233479462853155,23.47724642808229,0.8262837679013403,1
|
| 402 |
+
53.28668871134757,2.116921079025134,10.68053635894874,1.4121932247040434,0
|
| 403 |
+
62.74892464971807,2.864315533424718,11.678587586168302,1.4070535525478982,0
|
| 404 |
+
51.853736899583325,2.760420325701584,13.265905337330032,1.3272609699888065,0
|
| 405 |
+
51.235511616300165,1.7355054164347103,9.67123879004992,1.7264806024680472,0
|
| 406 |
+
52.54409279442841,2.0424128050573884,12.92435309482997,1.6702912097479783,0
|
| 407 |
+
51.693179812332424,2.3889854989973496,13.635989904132199,1.5875679817939423,0
|
| 408 |
+
78.27785978876484,5.774152818078785,21.13559965144208,1.1370226648416695,1
|
| 409 |
+
59.62124814442679,2.5090953573326504,12.478642251035362,1.3747723270842747,0
|
| 410 |
+
57.52515290335416,2.4258843004704924,12.346923034115047,1.4409543793054433,0
|
| 411 |
+
56.73953708585459,2.52587407070152,12.020063719073795,1.5480674270769057,0
|
| 412 |
+
57.67330407243199,3.3146368052779867,11.567571812809021,1.302461238955058,0
|
| 413 |
+
79.96964377248618,5.555443930977944,21.397016640027402,0.9969249773813702,1
|
| 414 |
+
54.681081744572765,1.6872949361110479,13.451998206830797,1.6334019380658524,0
|
| 415 |
+
56.886154090180554,1.707420983844587,11.536466452205627,1.5042490117624412,0
|
| 416 |
+
55.97641755591341,1.9357869344422374,13.395566786434339,1.4909861628367302,0
|
| 417 |
+
54.94541283281881,2.344109531545162,11.097808782661492,1.1707224380216688,0
|
| 418 |
+
60.00690003426078,2.4751012480132206,12.326160622954891,1.7817568697989694,0
|
| 419 |
+
50.488876940433144,2.0928124451474432,11.91647242102501,1.6960499330106025,0
|
| 420 |
+
58.59126163364219,2.6855695034114557,15.351579369296523,1.8351139621196597,0
|
| 421 |
+
53.674047311610984,1.8338573092989623,10.883064965342156,1.4829125410420374,0
|
| 422 |
+
58.51380120522909,2.8817143560428495,12.72597344092729,1.655905356737783,0
|
| 423 |
+
50.13643630358348,2.4660646869407192,11.120226523620053,1.5098298871245075,0
|
| 424 |
+
57.32310838131919,2.1176744862280246,12.415438012829048,1.5847375921909368,0
|
| 425 |
+
57.1937116833192,1.4864317989068796,10.675200553267313,1.4530436571110692,0
|
| 426 |
+
47.67637669660988,2.3350477170986434,14.37424417016,1.406459623555596,0
|
| 427 |
+
51.71099993083872,2.5310407672908766,9.436160844134767,1.5652880935756595,0
|
| 428 |
+
53.473048424006684,2.567791546214187,12.152171145975075,1.6598966444614702,0
|
| 429 |
+
53.6604598800569,2.26551355809671,10.373084066345642,1.257456089975258,0
|
| 430 |
+
57.31824456990591,1.7348676563649748,13.493308992244023,1.338156421942705,0
|
| 431 |
+
54.61085360634604,2.141559906795738,9.033376406449307,1.4953884251609206,0
|
| 432 |
+
53.1139007702002,1.5118062504610261,13.165609438486348,1.4329391112198202,0
|
| 433 |
+
54.389909870190564,2.699668166237245,11.217692032820425,1.6767676275477497,0
|
| 434 |
+
59.273886223956154,1.8373042389960124,12.33644596077239,1.4323236964140877,0
|
| 435 |
+
59.30496062986554,2.011893948108268,12.497993240185401,1.9007645069635029,0
|
| 436 |
+
59.76457181235546,2.383104798891969,8.765987990910931,1.408485170091433,0
|
| 437 |
+
55.26412279024486,2.4777910443250626,12.410705767985279,1.488784661765291,0
|
| 438 |
+
53.35629107666505,2.4162972258630764,12.046570800732832,1.6128575599069017,0
|
| 439 |
+
55.80922476732477,2.525124502789182,10.892435128684337,1.8115066988788535,0
|
| 440 |
+
58.7905984393932,2.2477195192438684,11.667605745002845,1.8081817641931166,0
|
| 441 |
+
49.86946139895791,2.3051456455430737,14.035144736195946,1.6294726108056208,0
|
| 442 |
+
50.662447711066534,2.082085318912574,11.895301821356794,1.4033316352675926,0
|
| 443 |
+
56.04814324829752,2.1932921065375957,11.827833076497116,1.4733783769359619,0
|
| 444 |
+
80.9273000521174,4.972643783983732,19.043842254182646,0.43088846443705536,1
|
| 445 |
+
50.585037208871974,2.0172652029428875,10.758623638898008,1.3791422750080813,0
|
| 446 |
+
54.363260514479755,2.3450201982417678,10.54529940732739,1.5505435014090285,0
|
| 447 |
+
53.82488431939148,2.2572922185119393,9.70070268247094,1.4164244209420351,0
|
| 448 |
+
47.25264783751926,1.6175859517694802,12.153708550654734,1.4403774997605854,0
|
| 449 |
+
61.31636502564174,2.8595065988706985,9.160243258142842,1.3016706050868827,0
|
| 450 |
+
48.17739113593793,1.8825934180142718,10.838871172526925,1.3077223128407003,0
|
| 451 |
+
49.73267915576703,2.193530615948206,12.876253610028435,1.412416959136167,0
|
| 452 |
+
62.989186122991974,1.7952568405536171,11.078872836983448,1.6513649705601008,0
|
| 453 |
+
55.2520094733388,3.05304587906382,12.72779734721656,1.4891381491754185,0
|
| 454 |
+
56.83754308686645,1.1354010553999914,12.055208248645432,1.3823786559794387,0
|
| 455 |
+
51.71445328310246,2.766117286089624,11.645804862333021,1.9589296843495236,0
|
| 456 |
+
66.62026867696163,2.7095218466208815,12.153384989471125,1.6089043549558713,0
|
| 457 |
+
53.75806409521623,3.2043776930925696,11.636071428899589,1.5084308479633728,0
|
| 458 |
+
56.155666668674826,2.806441845861578,12.21175352824896,1.8048505537065507,0
|
| 459 |
+
44.74102263271773,1.4064508496008794,12.024194122914006,1.518704591647702,0
|
| 460 |
+
64.31061240138433,2.211677658057278,12.077547482142922,1.3714235394333856,0
|
| 461 |
+
52.28694223937929,1.8624430239282694,13.93752969848801,1.742397363624307,0
|
| 462 |
+
55.56970294428226,1.7001438856653095,10.403290880810742,1.4358653453111814,0
|
| 463 |
+
49.21576858244618,1.3724523284074084,7.624260178954401,1.4199306090511188,0
|
| 464 |
+
55.96663887928335,2.555988511495526,11.033687624420327,1.4337926531451075,0
|
| 465 |
+
80.41464452006113,6.4112622505968915,20.785284371383252,1.3020763202855488,1
|
| 466 |
+
45.75958625346942,2.2848532725714064,13.089147542169501,1.6857240452234774,0
|
| 467 |
+
51.26552927996049,2.201496645599978,12.928657527697279,1.3716710320637135,0
|
| 468 |
+
55.28851803085548,1.677478145206849,13.785458555265176,1.5010810590564556,0
|
| 469 |
+
60.31074452907077,2.3880221848113057,11.852889647201238,1.477015355961268,0
|
| 470 |
+
53.229857152431265,1.744278188431355,12.7750542279727,1.411203178840503,0
|
| 471 |
+
51.61735586893061,1.9464473597858791,12.370024724416115,1.4604784124731447,0
|
| 472 |
+
49.81411068770095,2.0262382939032406,11.348699350111671,1.3780538963039728,0
|
| 473 |
+
53.30680675182339,3.0971850273001795,10.294616127884348,1.3821305595925841,0
|
| 474 |
+
82.36123718217854,4.6170976116996165,16.581274806561915,0.5831203775127997,1
|
| 475 |
+
56.78612470411978,1.9586049206376779,12.814287336716394,1.4325774855345443,0
|
| 476 |
+
52.315438890413674,2.2132926706630496,12.373400865594986,1.5208667609642388,0
|
| 477 |
+
93.7589094542214,7.637472313097882,18.344739443138426,1.258988360696103,1
|
| 478 |
+
74.23453655273383,6.335694268987323,22.079948508162555,0.8051625384094538,1
|
| 479 |
+
77.23648014608827,5.0502459102519,17.0630700110541,1.2297551981355932,1
|
| 480 |
+
57.16452644321812,2.449359720534862,9.528755551428842,1.5773937715151767,0
|
| 481 |
+
48.392963407282934,1.664149336569128,12.46319891527225,1.5830930258992986,0
|
| 482 |
+
55.94110444635305,2.474064189821098,14.363516388255992,1.5971420965829342,0
|
| 483 |
+
48.25066226416788,2.1451329091849085,11.600379698887235,1.6650556021045835,0
|
| 484 |
+
58.111167741715796,2.3985166500077457,9.039249195211553,1.605979876934674,0
|
| 485 |
+
58.040532341503415,1.4121903364146926,11.729539465725699,1.6992718216187597,0
|
| 486 |
+
56.809335802572555,1.3822683757710712,11.949594840065787,1.6304641780747435,0
|
| 487 |
+
55.92864529226688,2.800153129129661,9.753940244858196,1.233544854173067,0
|
| 488 |
+
52.337961170845226,2.4453833544969097,13.318431041551339,1.3752715841000436,0
|
| 489 |
+
52.9268806305349,2.4830938792874164,13.602693100866446,1.5409433632295084,0
|
| 490 |
+
56.539803864423455,2.42751186017376,11.867079082120249,1.7293970218450943,0
|
| 491 |
+
53.657570527525415,2.1087500786748694,10.874997395627233,1.469033136238419,0
|
| 492 |
+
54.95072282828276,1.5265987256102174,14.348669296804882,1.5509462650070027,0
|
| 493 |
+
58.250405151014576,1.6249572529238185,11.72505366535911,1.4908615417938098,0
|
| 494 |
+
51.31659840876349,2.3942371004257708,8.851190486158135,1.5354486423042302,0
|
| 495 |
+
53.48734978384244,2.170358676987034,11.16814139153933,1.461057895298134,0
|
| 496 |
+
58.21434007751441,2.346466911748646,12.226382290209743,1.4935975355658786,0
|
| 497 |
+
54.52544669556047,1.9067074574645497,14.362624241413096,1.3753071246073385,0
|
| 498 |
+
53.628855396542484,1.6838014902225764,12.738445367907055,1.4403333129089688,0
|
| 499 |
+
59.35686998684317,2.0985290281623152,12.01691654492799,1.3999873724689718,0
|
| 500 |
+
56.11545713858896,1.9743077745178026,13.036593848800315,1.6088561974978084,0
|
| 501 |
+
50.555580396329766,0.981812168376339,13.493452209176748,1.5117675196166867,0
|
| 502 |
+
58.267103468803164,2.7948110026438218,14.724790494210158,1.5338789754474829,0
|
| 503 |
+
55.639966454293756,3.6046054306147517,12.325909737342936,1.4194209308979873,0
|
| 504 |
+
55.552965728234724,2.6227415542409274,9.215532649328313,1.3299343461870408,0
|
| 505 |
+
73.4070281937465,6.301837412269157,18.23783034251648,1.6,1
|
| 506 |
+
56.56505863973294,1.9340612530286214,13.069496138017648,1.5362178239403643,0
|
| 507 |
+
78.08931525124557,4.967054254761382,15.963329181728596,1.2928576909543201,1
|
| 508 |
+
53.25837010822415,2.1403169003615616,11.849553498834888,1.48897820076144,0
|
| 509 |
+
49.99341114357544,2.5979193276098873,10.496436381350673,1.4216381352853464,0
|
| 510 |
+
76.60289570330649,5.2614020764253535,16.12710177365341,0.6720396223965255,1
|
| 511 |
+
53.80294118445897,2.836441384377332,11.83764999251554,1.605628551768475,0
|
| 512 |
+
53.495375715079604,2.9364767860947874,9.284680018369777,1.5170699348010446,0
|
| 513 |
+
45.42295878039811,1.5763412651529158,13.574247908794979,1.6363739403320814,0
|
| 514 |
+
50.13375940247549,1.803737084771043,11.47271289728506,1.5730227820723925,0
|
| 515 |
+
51.56283014846705,2.778753879010567,11.306809387241332,1.5101333226121236,0
|
| 516 |
+
62.28258463058721,1.7495515023477126,11.957973322656384,1.4744385514147527,0
|
| 517 |
+
57.55850563799161,2.5758982329177282,14.152509266983403,1.4658351681627986,0
|
| 518 |
+
55.70629343381484,1.8250933308577415,12.194894781249111,1.3090571356890401,0
|
| 519 |
+
56.14330455841017,2.91765007832272,12.733002786700961,1.5594612753310602,0
|
| 520 |
+
75.3102613581346,7.122017647432129,22.089457232485355,0.48967383036088225,1
|
| 521 |
+
59.89016535469612,2.259612930563696,13.832592999326389,1.2398082754594206,0
|
| 522 |
+
55.937603570794785,2.5872473519326857,12.498798469646461,1.433746230874051,0
|
| 523 |
+
48.53736664271729,1.6182631001038645,11.339238208728009,1.504500980779641,0
|
| 524 |
+
49.230803457762356,1.8111970361258667,10.949873955531167,1.5170055807037834,0
|
| 525 |
+
45.8348419656076,2.838490416099022,11.857552034110993,1.6889558779320608,0
|
| 526 |
+
56.89878835385281,1.6626169930911432,10.383658006699012,1.3995477857891696,0
|
| 527 |
+
57.22613377100505,2.454949124238268,12.932401969681457,1.4932900598718197,0
|
| 528 |
+
53.48077395284042,1.4790106321799938,12.00798429067755,1.5527896156227987,0
|
| 529 |
+
57.57575517310743,2.4598302866732515,12.377781622942507,1.419435451565083,0
|
| 530 |
+
61.443747980047576,2.477680114254288,9.716701087212858,1.5028486779960162,0
|
| 531 |
+
54.6811271563744,2.8574039357529526,8.765965436175028,1.4225553604707737,0
|
| 532 |
+
50.0221128495957,3.092659197112364,13.813896852638067,1.3685152763725204,0
|
| 533 |
+
58.431903525028616,2.6621788785937173,11.443832745806908,1.6238570462137965,0
|
| 534 |
+
56.075653790714405,2.0829372313585437,14.32483584919369,1.5248273193025144,0
|
| 535 |
+
50.55827726234209,2.194680661690904,13.533610838040708,1.3017953892532097,0
|
| 536 |
+
55.524231304184575,2.5356140058068495,14.170588044046653,1.4600404387211237,0
|
| 537 |
+
58.713187966273935,2.4059857910633773,10.614780330100045,1.4210239955225827,0
|
| 538 |
+
53.05476836370668,3.4225650725294585,11.019055299544616,1.536509837460081,0
|
| 539 |
+
57.76194141627107,1.6792061836893644,9.257407032837747,1.89521111316225,0
|
| 540 |
+
56.79125486689084,1.5900621275792393,13.722384636773983,1.2592416031494116,0
|
| 541 |
+
59.26888966628793,2.3634217351940117,9.626749475809623,1.6253422391829366,0
|
| 542 |
+
49.52736320301734,2.5266224416406136,10.790577268972974,1.440420853512439,0
|
| 543 |
+
56.26597704669323,1.2459347933873668,9.889628751597208,1.4920045696513269,0
|
| 544 |
+
46.41084388104538,2.2308523170251844,11.30616642551313,1.234955715280492,0
|
| 545 |
+
56.721205435830214,1.656716070204705,15.416145672834148,1.3915146471088742,0
|
| 546 |
+
55.08740858209377,2.0630747472268816,13.538022051386633,1.6169804418784164,0
|
| 547 |
+
74.11553876579029,6.258165639054314,23.626158084609386,1.1109076377136233,1
|
| 548 |
+
55.397909892062955,1.416034791784751,14.053176947855345,1.6056222212459677,0
|
| 549 |
+
55.11643978630668,2.24880199624772,11.76730030322911,1.7352309670595747,0
|
| 550 |
+
55.99614448922777,2.188657362337177,13.058954620048224,1.5416016269580322,0
|
| 551 |
+
60.85321156487825,1.1098949677552632,11.125327391545964,1.7763225987852396,0
|
| 552 |
+
55.930704845418816,2.2260866593287667,11.075926461665812,1.280631392271877,0
|
| 553 |
+
55.74130259766153,1.3973643764337162,13.362589945900957,1.5058969599036445,0
|
| 554 |
+
45.99289083752382,1.8352114029321769,10.857012714259515,1.342936241885032,0
|
| 555 |
+
60.97976524493758,3.3214601562014927,13.565615096580741,1.5497312542700539,0
|
| 556 |
+
55.33592401325782,1.671422562930863,9.856776848660584,1.4745188274630392,0
|
| 557 |
+
74.5233594865098,5.323511800589675,17.68286701003206,0.7572752642062148,1
|
| 558 |
+
58.37754076194128,2.4967773474527837,11.075737373738214,1.3732019302533647,0
|
| 559 |
+
55.21262139031147,1.9941252911576755,12.7960409070371,1.8047100247167753,0
|
| 560 |
+
58.48571511179276,2.367920628466512,12.049042837879906,1.6569078376571849,0
|
| 561 |
+
60.90379619221404,1.4203083823471956,12.191043713484728,1.7135339208397549,0
|
| 562 |
+
51.42109192417669,2.813146477824475,12.588016406048634,1.3184401908325818,0
|
| 563 |
+
70.63938759269018,5.440113530695945,19.80261502291209,0.5240084212964511,1
|
| 564 |
+
51.98843233108552,1.9417446289195839,13.710314218405104,1.570687568676884,0
|
| 565 |
+
58.1110695563397,1.3173898423485757,10.701985751847248,1.4022938564898673,0
|
| 566 |
+
52.778691124723935,1.4463371761134765,12.569531370920975,1.3895590325192497,0
|
| 567 |
+
60.282646622112665,1.936642304026896,13.413890431349689,1.5382790027634026,0
|
| 568 |
+
56.39740249024172,1.5688053505714175,12.054721133421348,1.4087628079201324,0
|
| 569 |
+
54.75470261668461,1.874718189797204,11.580484753300661,1.4601959837528617,0
|
| 570 |
+
56.21746691612104,1.6993542836217281,11.501747205241491,1.4821457240099811,0
|
| 571 |
+
78.05731371754108,6.609639036123751,20.043427007579574,0.6015680642914065,1
|
| 572 |
+
55.62819426978138,2.418756124309935,15.001444652385231,1.6463976075441078,0
|
| 573 |
+
58.340444983658315,1.1460233291112787,11.917346851436566,1.5013759872273194,0
|
| 574 |
+
55.176849512416794,1.9308418985692102,12.124077302794783,1.6099362836156301,0
|
| 575 |
+
56.156477594759934,1.3382682962972912,11.03768591882573,1.558724405602216,0
|
| 576 |
+
58.25505475986484,2.3509853712596356,10.386641570785477,1.4886342785310263,0
|
| 577 |
+
72.44353175789705,6.258851431078958,19.577524943138783,0.47347137928586536,1
|
| 578 |
+
46.47181487707476,2.5492831726857528,10.158126673962235,1.5870593947287905,0
|
| 579 |
+
56.39083380980383,1.4426226121032304,12.624552222208433,1.6596314233287013,0
|
| 580 |
+
52.18130694852047,1.7173244025956185,10.779914381479985,1.5886981093278727,0
|
| 581 |
+
52.8661906113411,2.7394395195148693,13.700683908846019,1.542585900176321,0
|
| 582 |
+
58.129401369670646,2.177781916147823,12.832718522917247,1.316191230079634,0
|
| 583 |
+
54.800296356054986,1.2596007860129714,11.608757312393125,1.337094817044878,0
|
| 584 |
+
55.8689247792421,2.1180232499865017,10.003684121079765,1.3445065651253099,0
|
| 585 |
+
52.01560697338995,1.9325943308907212,10.75010611269413,1.318144756041041,0
|
| 586 |
+
53.72357361195641,2.7124608465627,13.240759199431833,1.5818818256608718,0
|
| 587 |
+
58.31807616809629,2.8164509670513485,12.65648351030146,1.519769764051623,0
|
| 588 |
+
59.591250642934256,0.7221905878274653,13.251788321053587,1.6111922650477533,0
|
| 589 |
+
53.23739031372103,1.5659930415780017,9.208209473241666,1.2590614772556927,0
|
| 590 |
+
51.70207513723504,2.670144732441795,14.21741840357409,1.868736540860484,0
|
| 591 |
+
55.690351670888475,2.313393023054568,13.154785339583032,1.1635758567584351,0
|
| 592 |
+
49.850309674903876,2.5450522123820063,10.508497337257321,1.53407441975812,0
|
| 593 |
+
59.85675931571401,2.2366376572928486,10.774810231094616,1.2689468436227385,0
|
| 594 |
+
56.9282673421021,2.2810297795314374,13.983756497284684,1.457525500667024,0
|
| 595 |
+
62.14067360828852,2.0817767900177433,12.583556385650645,1.7192698751320958,0
|
| 596 |
+
47.25213226917834,1.6846414840338304,11.73008986817504,1.587179821799138,0
|
| 597 |
+
54.78486979672672,1.5113421722398166,12.322953944912268,1.376716234268544,0
|
| 598 |
+
55.20986719342498,2.382681871031884,11.29803553001356,1.73790057464398,0
|
| 599 |
+
60.097788867764955,2.8625733644374196,12.421759748465218,1.640913063269727,0
|
| 600 |
+
55.751894349944415,1.3161889435303098,13.18336182507486,1.3772253596384423,0
|
| 601 |
+
47.56065837381749,2.5241970056193566,13.181224056578287,1.4439835550475728,0
|
| 602 |
+
51.16446959668401,2.4647067035628614,13.39895826448668,1.5242879050927602,0
|
| 603 |
+
50.24494778270859,2.218029963398898,10.474163488347537,1.788674405551886,0
|
| 604 |
+
59.684988373869274,2.405491288450438,10.78631102258844,1.5602892424618218,0
|
| 605 |
+
58.10935030424697,2.255306561289339,12.874662203486615,1.3472823582721971,0
|
| 606 |
+
55.70958445854776,2.58576662988096,11.09310207573069,1.4213377660543436,0
|
| 607 |
+
76.9869444887822,5.421945192737429,14.710604289054208,0.828158680465103,1
|
| 608 |
+
61.894662883133186,1.901955550171917,12.586087539133343,1.3773662402505051,0
|
| 609 |
+
52.88202916374479,1.689477419660839,7.4285511519708685,1.4197116650054133,0
|
| 610 |
+
57.855280545929595,1.8425617190512453,10.882525591911538,1.475741849543813,0
|
| 611 |
+
58.05170592934775,1.1464038263351561,12.436099766800234,1.5726965266967554,0
|
| 612 |
+
60.2240069668273,2.321876240200824,12.255937617809689,1.545837028785372,0
|
| 613 |
+
48.86455438033545,1.9569029346504767,9.428271156755818,1.6031538277676673,0
|
| 614 |
+
56.77018249681621,2.264310796245633,14.235186513444859,1.6158317216028757,0
|
| 615 |
+
50.85968754383744,2.178710689477778,12.324307014484033,1.5194114305343804,0
|
| 616 |
+
49.013445240386694,2.78775328825439,9.29928196239873,1.3532338679937848,0
|
| 617 |
+
53.08358731635208,1.3895432408459243,11.828516747992879,1.563918592022914,0
|
| 618 |
+
78.47803643560539,3.5,19.74095755029189,1.1325687560552145,1
|
| 619 |
+
52.246510871076964,2.697745141472659,12.607473478387016,1.6812394238220751,0
|
| 620 |
+
71.69896728191574,7.689854821368538,17.110883208937018,0.6582246664146926,1
|
| 621 |
+
55.87475438691605,2.022150842214483,8.943407238397924,1.6740139269965326,0
|
| 622 |
+
77.7665397912827,5.166095477851393,20.008440606316814,0.45100185698313594,1
|
| 623 |
+
58.93095804409223,2.4055859590079818,10.195955121148454,1.518924779464646,0
|
| 624 |
+
53.04099926839516,1.8905267237043186,9.153278250150336,1.3222973034506513,0
|
| 625 |
+
56.78428880592832,1.642691518466037,11.539954068261094,1.398373268146235,0
|
| 626 |
+
56.475003136329995,2.9181508782816454,12.996530511359897,1.5172400867371518,0
|
| 627 |
+
53.810706549209456,3.3148659207047744,12.418862330900343,1.4907726480593044,0
|
| 628 |
+
57.71565425228758,2.391442868192525,11.423174834973125,1.474983639899702,0
|
| 629 |
+
81.16018825262746,3.8873213059703997,16.434003864712018,0.9658208009261717,1
|
| 630 |
+
68.6649635300104,3.5950086115224384,15.543154574253434,0.934554264945837,1
|
| 631 |
+
56.37858090494421,1.7739205970172032,12.549499400475066,1.5699493158255624,0
|
| 632 |
+
83.11939597721445,5.2864509331051766,15.615481201132855,0.8801422101933717,1
|
| 633 |
+
55.8923189705011,2.81301695495534,13.852871082465409,1.351941726819467,0
|
| 634 |
+
56.81768135285745,2.5164289573036536,12.237672075749602,1.5388931462302362,0
|
| 635 |
+
53.59619047112809,2.36200626209499,12.832860111419135,1.5204903424519052,0
|
| 636 |
+
54.116130728854586,2.30533343886231,12.762989314527148,1.5279079265478284,0
|
| 637 |
+
55.91291332055562,2.064922435331452,9.792281473013722,1.6347832920213925,0
|
| 638 |
+
57.12923674221339,2.115140101789811,13.290794561942167,1.3642788745178367,0
|
| 639 |
+
81.73974639751182,5.2270952430932125,19.228816098097152,0.9077886340300515,1
|
| 640 |
+
50.72099035484124,2.52894400521659,11.864711379933917,1.659852776208007,0
|
| 641 |
+
79.54016699425851,4.741821173100663,17.14496643777565,1.6,1
|
| 642 |
+
54.49996387872169,2.1752205812242087,12.90749006351831,1.4564901339094123,0
|
| 643 |
+
53.850466553803294,1.1512745211949293,11.282875413369263,1.453254084907542,0
|
| 644 |
+
51.639374092149886,2.15606162879219,11.611941147471406,1.4647274030078348,0
|
| 645 |
+
68.50828489537261,6.90369541718262,16.26861432404147,0.6587550115275124,1
|
| 646 |
+
57.216466005296375,1.8881996553708937,12.50256355130612,1.6901435341205857,0
|
| 647 |
+
51.15163553463349,2.6797952628750368,11.316778126717773,1.3217416718102597,0
|
| 648 |
+
71.39660800181909,6.03536920509721,23.160583128744094,0.5866750535074703,1
|
| 649 |
+
53.552669851662635,1.8127449692433024,10.41391988300508,1.388598171794827,0
|
| 650 |
+
59.1966944857654,2.043822279172065,13.826587781176706,1.2726462117729793,0
|
| 651 |
+
55.1423059079385,2.938696832487335,11.868140268946178,1.5528004430906448,0
|
| 652 |
+
50.57181727182605,1.8719725316795164,12.13180145562109,1.400663277101311,0
|
| 653 |
+
56.11430365804723,2.749595777773907,11.968940453840649,1.6390283870364812,0
|
| 654 |
+
52.22597534171088,1.6740563635507932,11.36615852580188,1.707191852333839,0
|
| 655 |
+
48.989986175836414,1.954172192517258,11.347950789415298,1.6656742537808351,0
|
| 656 |
+
78.82123992413631,6.400508265284292,20.407144800455978,0.5895837027945765,1
|
| 657 |
+
56.583735497723296,2.154564535187019,12.13523524150136,1.7341779799764723,0
|
| 658 |
+
56.45381735135629,3.052926340272282,11.869942948736815,1.4400419915565355,0
|
| 659 |
+
67.59368542530659,6.613054932776252,19.787607590290428,0.7145836779644378,1
|
| 660 |
+
63.513878929740656,1.971764427887639,11.593659559393593,1.382489841915507,0
|
| 661 |
+
82.71910050799099,5.329552470120472,18.752842210094286,0.5878197435475486,1
|
| 662 |
+
48.301268221182575,2.2548238772870044,9.335402555486558,1.7052704090647695,0
|
| 663 |
+
50.665204690567755,1.953299329808661,14.116975478815068,1.6983203841117716,0
|
| 664 |
+
70.0662816245989,6.366642050759749,16.359133841241356,0.6929011262466673,1
|
| 665 |
+
59.54419473422171,1.4164114547072768,11.429942906711705,1.3730846795734004,0
|
| 666 |
+
55.95094240932911,2.9211523955931225,12.764731061664177,1.4453357372903637,0
|
| 667 |
+
65.06989615013568,3.085670621133842,12.847730068214654,1.6201078682504484,0
|
| 668 |
+
53.164638027402795,1.7075025361377794,14.066604354412117,1.2676114235483635,0
|
| 669 |
+
57.95006227386835,2.5169551888668713,11.804960907752266,1.3527135231073795,0
|
| 670 |
+
51.65040710469015,1.9196229179561275,10.847466510678132,1.5278269959877115,0
|
| 671 |
+
60.41434355827759,2.795206781646872,9.771656995153393,1.3126886083938434,0
|
| 672 |
+
55.04580516668262,1.9466986520143987,9.481334358564425,1.2628033827733511,0
|
| 673 |
+
50.29354112228279,2.6390292894541,9.586789936095043,1.2961684131115476,0
|
| 674 |
+
54.79521155273361,1.4496652986090808,10.513340526618974,1.4251593675057082,0
|
| 675 |
+
52.144500703854064,2.3707543427684015,12.491619704927924,1.2784188054808452,0
|
| 676 |
+
54.0425774901079,2.5098509827412396,9.800721026295687,1.6264761465034003,0
|
| 677 |
+
53.721315134570794,1.6187856099300348,13.008171472644655,1.5170812791213018,0
|
| 678 |
+
50.85738498869675,2.097965707780576,12.368056513492999,1.7146378528236528,0
|
| 679 |
+
53.42503531110171,2.5769275349668415,12.907187373825852,1.6578966626423342,0
|
| 680 |
+
69.136153474096,5.059985447619374,14.0,0.884823779569971,1
|
| 681 |
+
50.12474775830549,1.8027002724374728,10.333603357176418,1.5030055936299467,0
|
| 682 |
+
59.8500753473264,2.604560655495122,9.236423306953991,1.3470623237748836,0
|
| 683 |
+
54.62680540138604,1.5440984171113945,10.56474493068053,1.5606817789629235,0
|
| 684 |
+
57.96005694521734,2.1486689544796835,13.992234931343695,1.302745634169337,0
|
| 685 |
+
54.93279536998284,2.234959790497413,12.059540289896344,1.5453387327728192,0
|
| 686 |
+
50.02317648455652,2.329903928402755,11.705252369402839,1.5671572545142602,0
|
| 687 |
+
54.5442101693805,1.6245677454072167,12.329377390769917,1.3583365682395363,0
|
| 688 |
+
62.8040502405052,1.5540588658841552,13.012716989842346,1.5627748611825576,0
|
| 689 |
+
54.303309064780166,1.8378287402958997,11.395255984604926,1.5630484244664193,0
|
| 690 |
+
51.05257168628705,1.9192584866085585,16.2861576347098,1.1225857206340852,0
|
| 691 |
+
53.685899107508426,2.148801646694452,13.157811438554743,1.2678250750890134,0
|
| 692 |
+
62.19037808973726,2.14041558133604,11.5321630316169,1.436799408803145,0
|
| 693 |
+
54.72807897606238,2.762521960854013,11.642345473529547,1.4510634477564257,0
|
| 694 |
+
52.521336263485544,2.1058079363678086,11.346404867749891,1.6168244575681547,0
|
| 695 |
+
57.19495527545651,2.2729691470723874,12.367022888231025,1.4488655130832475,0
|
| 696 |
+
52.76908445001914,2.196047742313382,10.451951632257634,1.7020984862420339,0
|
| 697 |
+
55.928679558505024,2.0726959151169853,12.409293777038659,1.5456653284220723,0
|
| 698 |
+
50.8627677933024,2.233956584584668,10.648448956117573,1.4240746099961499,0
|
| 699 |
+
53.51234167471484,1.7367334444214249,10.79321005466278,1.8496537007337106,0
|
| 700 |
+
53.860463734469704,2.4827302095845467,10.700375792010842,1.5430936141554545,0
|
| 701 |
+
54.36546065184525,1.5791222355608039,12.084617350754357,1.47673045657014,0
|
| 702 |
+
50.670291210446855,2.129302248928099,12.464119259639887,1.5134263499645721,0
|
| 703 |
+
49.02237752072277,2.0695500884995752,12.105169738099825,1.4477745313744987,0
|
| 704 |
+
48.1840285495585,2.707757608241465,9.135355641380578,1.4179492918732508,0
|
| 705 |
+
56.5401517506244,2.037227494240234,12.977310930965938,1.6724065261436727,0
|
| 706 |
+
59.97978951458578,2.754584905746066,9.36528491888053,1.3464528357450163,0
|
| 707 |
+
51.59385124325693,2.368200469344936,13.456509503938783,1.4464042409599775,0
|
| 708 |
+
54.43683645433446,2.47129723164598,10.636345667094966,1.4068767921479117,0
|
| 709 |
+
52.55161280376077,1.931168711548489,10.87175869789872,1.4148416785120947,0
|
| 710 |
+
54.61528425230667,2.488701288759625,11.677133315135768,1.501199104432322,0
|
| 711 |
+
85.14360407320751,6.341621006013791,24.35861706194245,1.1265755327928302,1
|
| 712 |
+
46.010925778636576,2.0981090694377262,12.946857492100722,1.7887519202603777,0
|
| 713 |
+
53.7048331828536,2.1270947709555923,9.125103798722684,1.5248418225348979,0
|
| 714 |
+
48.67362240218423,2.114217744891826,11.453434060660138,1.6333474770606973,0
|
| 715 |
+
46.70806625603483,2.6310000252060672,11.70753017082032,1.6014921827664788,0
|
| 716 |
+
57.92309876455458,2.4619754770963356,12.289772369719797,1.5019855009202505,0
|
| 717 |
+
55.73293774888762,1.5009451701005747,12.29757174093966,1.5767270552878787,0
|
| 718 |
+
60.43675030096175,2.5080673340011193,13.693486651443026,1.3453196897340622,0
|
| 719 |
+
55.124342351084614,1.9171806258224806,10.75978634191039,1.244385056152889,0
|
| 720 |
+
48.25761073046077,3.1987570889023815,8.441706707904729,1.348655103361762,0
|
| 721 |
+
56.070845849375345,2.250962943686329,8.729450686892717,1.6097720091481331,0
|
| 722 |
+
72.5583780894246,5.976437922752776,17.979567060027616,0.7113163935201676,1
|
| 723 |
+
53.42157950856164,2.4472783276614267,11.862689970872689,1.511792650429768,0
|
| 724 |
+
57.15213775971301,2.2661732532013366,11.1964276908459,1.4334147545371865,0
|
| 725 |
+
56.05099690058855,2.4087359793710075,10.627313010780748,1.8449496104422258,0
|
| 726 |
+
44.73336623627481,2.5750609060684724,13.228145925521163,1.8585334065977706,0
|
| 727 |
+
54.28155434467416,2.22674081341095,11.19069722711829,1.3475975205887667,0
|
| 728 |
+
55.87998673588706,2.4049142286643463,9.117743204177042,1.6013968283710385,0
|
| 729 |
+
59.42515484023956,2.23095824183998,11.621905776894966,1.6711219184042072,0
|
| 730 |
+
55.362339627606985,2.4991735235374417,12.65101473517516,1.65318334338287,0
|
| 731 |
+
52.382866893249776,3.555372763609163,10.646240240335063,1.5806150781341006,0
|
| 732 |
+
50.61285768618144,2.4365435990137376,12.990663849822656,1.7400070921979411,0
|
| 733 |
+
55.79116032776741,3.11811291986501,12.020847313998766,1.6123220828973714,0
|
| 734 |
+
74.08322223692524,8.914353273889166,18.555435686778274,1.0053929027963753,1
|
| 735 |
+
47.86555548114327,1.8518939742100504,10.5876935966553,1.8095841803485002,0
|
| 736 |
+
68.11333715337318,5.285713638527375,16.920597064342974,0.42153742079532003,1
|
| 737 |
+
51.42261581568989,2.6573120269934236,13.8111375424668,1.2996419236043146,0
|
| 738 |
+
53.27464224704196,1.4039934988792724,11.640343480659613,1.5304810400090858,0
|
| 739 |
+
51.2936962343779,2.7227661373948404,13.098641714644257,1.8740890508591983,0
|
| 740 |
+
50.54644783231261,1.3563261527933244,12.414621546380632,1.5731987056206882,0
|
| 741 |
+
58.282113901669675,2.507135219178532,12.136200035415072,1.6171771807835613,0
|
| 742 |
+
55.04578175636586,1.8802483045562624,12.690327959152595,1.6311513642669582,0
|
| 743 |
+
61.91598136354281,2.1553397986496328,15.409487738969084,1.2682050081706864,0
|
| 744 |
+
55.63247633962044,2.742257580464983,13.568460180313899,1.5789303027185844,0
|
| 745 |
+
75.21933231824762,5.596729330744626,18.386246275661247,0.5038730559466771,1
|
| 746 |
+
52.21622955331719,1.705686425282697,12.71490445098597,1.6368228593965168,0
|
| 747 |
+
57.79678692677955,2.619961302566399,12.856761099436572,1.6146171608252684,0
|
| 748 |
+
83.1705509652202,4.46718034820257,17.169980167735716,0.8267673844433696,1
|
| 749 |
+
50.939728377084734,2.468148484590447,11.349558772268718,1.7911300408772803,0
|
| 750 |
+
54.47108537387531,1.9732808508157038,10.51072978824909,1.4728153448179948,0
|
| 751 |
+
76.40675715222459,5.837025218470627,18.249229354409216,1.018551942844646,1
|
| 752 |
+
56.88454517359972,1.9877686451090513,12.151405187602732,1.6365152242409657,0
|
| 753 |
+
47.432214986752356,2.7597503404014585,11.640574266848029,1.4087448756143972,0
|
| 754 |
+
59.99866106817511,3.3934758997869614,12.538434660977206,1.5152730919654949,0
|
| 755 |
+
56.75854642406797,1.5368019483407258,11.81729216392,1.325739996159848,0
|
| 756 |
+
81.40302424211816,6.0044345510111485,17.77465412940155,0.9703786742680311,1
|
| 757 |
+
56.86032083800122,2.4565999055385905,12.392130619094953,1.4177481693202472,0
|
| 758 |
+
56.40702563359682,3.1008709738735734,11.951494321957178,1.397757817120435,0
|
| 759 |
+
50.4422839956337,1.530808794338078,14.486064180348745,1.5985227790080208,0
|
| 760 |
+
56.314648009129925,2.4138981991235666,10.791009586752303,1.9547643622665951,0
|
| 761 |
+
47.67437566313951,2.50132622315325,15.858776155454596,1.3047330393879735,0
|
| 762 |
+
52.62340017721282,1.9496276281215421,12.827788157296938,1.4369237484844664,0
|
| 763 |
+
54.01695399994839,1.4950151484580623,10.947349580599827,1.2410089978314334,0
|
| 764 |
+
56.26242001436136,1.8570736619116788,12.989226321377844,1.6767277279225776,0
|
| 765 |
+
54.813650918642644,3.6047844850481963,11.016384806351528,1.627629135578879,0
|
| 766 |
+
56.79239745574481,2.1784332051795463,11.468118679122963,1.6056022611482481,0
|
| 767 |
+
56.089479021096956,2.0900321023668322,11.350151015065467,1.2695591528933634,0
|
| 768 |
+
58.36728026756025,2.386526159217089,10.175094427065893,1.6156048173142146,0
|
| 769 |
+
81.36924692771787,3.5,22.51653883412661,0.8233080884856614,1
|
| 770 |
+
62.01476410680432,2.453291577095127,10.545902133392069,1.47689500251362,0
|
| 771 |
+
59.82341448355294,2.8908537966888987,11.404629238143313,1.6584578379046324,0
|
| 772 |
+
55.99514923920433,2.5201068296643796,13.491525702186477,1.662206219090572,0
|
| 773 |
+
64.53040913073629,2.2147117877924867,8.952570647005459,1.5937817895869197,0
|
| 774 |
+
52.210304706798894,1.0751081110241965,12.161301270080452,1.6585783905362048,0
|
| 775 |
+
55.65756281190921,2.475595864350847,13.153448807360618,1.5808956829414311,0
|
| 776 |
+
49.071258410228715,1.6099996107663705,13.185590215449258,1.5352679914727498,0
|
| 777 |
+
56.91550215408185,1.9182642872874653,12.58984466547724,1.233758543313191,0
|
| 778 |
+
57.589938762837896,2.0080995371461277,11.539309390371322,1.4939486420198982,0
|
| 779 |
+
51.546618941042475,3.069824020965506,13.016227263137091,1.3992228390358192,0
|
| 780 |
+
54.46470814193584,0.9745639357299569,11.095920955454666,1.5276550060763496,0
|
| 781 |
+
55.396139284028806,1.4539470822635043,11.931662809868188,1.665900943725418,0
|
| 782 |
+
60.45057055921336,2.1148057883219447,11.134727290277532,1.509620520356723,0
|
| 783 |
+
53.37892293820267,2.6907398746540583,10.472526701458113,1.2171640643334793,0
|
| 784 |
+
58.70975392623272,1.799894151699075,10.269487625400359,1.4706566503788467,0
|
| 785 |
+
54.179353244535825,1.9001252754405678,12.721542997145484,1.4986599198162045,0
|
| 786 |
+
48.59488825152459,2.2302342240586843,9.389245516458276,1.4293767513336695,0
|
| 787 |
+
55.36195912651149,2.1079121267423893,9.999788521898697,1.3985629953954577,0
|
| 788 |
+
82.31455827653002,6.409332113123424,18.12907659191482,0.7776807685186701,1
|
| 789 |
+
52.487735665098505,1.6936580743059193,9.214784397089751,1.5535134435462536,0
|
| 790 |
+
53.86254464783962,2.4024275438178546,12.946912095182364,1.6464998054967195,0
|
| 791 |
+
57.36362529117342,1.2961515701125337,13.404854033785181,1.5784265641123545,0
|
| 792 |
+
52.82601796826946,2.5473353058142045,11.260167231741134,1.4485733020635245,0
|
| 793 |
+
57.098029501144346,2.9581843233626683,11.805395695217245,1.2557936679073183,0
|
| 794 |
+
80.56488625272503,5.551147027694447,17.965986893138954,1.0319771900062993,1
|
| 795 |
+
85.36164525861564,5.838505469001856,19.588224272924673,0.4697333377627191,1
|
| 796 |
+
82.83660130080082,5.221449171405571,14.0,1.6,1
|
| 797 |
+
60.804715396084255,1.2327346321434414,8.509350304582036,1.61608367713648,0
|
| 798 |
+
55.05594088746117,2.514398146805152,11.121122684322623,1.4620916531140413,0
|
| 799 |
+
56.51712013746065,1.0373143125628568,12.307060029030795,1.3214274367967467,0
|
| 800 |
+
54.43198714236991,2.08167058767405,15.905439448125616,1.4651449140934842,0
|
| 801 |
+
67.71541471747014,1.9115018143112334,14.460531140847467,1.7408225074190946,0
|
| 802 |
+
51.98588967857049,3.34979454651866,12.225121695517537,1.402881085728072,0
|
| 803 |
+
89.49260814943716,3.9737737785989378,19.025838907955887,1.1949719908336212,1
|
| 804 |
+
59.991799940237726,1.471431043540222,10.95146722034411,1.1835074029680042,0
|
| 805 |
+
54.509261450019494,2.405106007839776,10.765946965381348,1.493730415818673,0
|
| 806 |
+
56.94788992314233,2.5159907418806977,12.400104251964962,1.5141704987729456,0
|
| 807 |
+
47.96908643457348,1.1992271277806608,14.874667315103116,1.503667308287968,0
|
| 808 |
+
51.339375536616295,2.9888841024659434,11.177890600132766,1.2212636006831197,0
|
| 809 |
+
50.2602249343319,2.4223634090976165,11.120922540036663,1.3665314510554203,0
|
| 810 |
+
60.61528556826623,2.29065710893071,8.424916945563957,1.5382623065801637,0
|
| 811 |
+
59.51588917088357,2.4947734430178015,12.131944344496503,1.439582558834064,0
|
| 812 |
+
48.25412739506359,1.8676869999684347,14.21919321577829,1.6670489560111947,0
|
| 813 |
+
52.380849218282435,2.1015571506480453,11.646248634278727,1.2234678873811935,0
|
| 814 |
+
57.349036667211166,1.5120432056992246,11.384199017977478,1.4482264699135654,0
|
| 815 |
+
51.667853108815954,1.3708322172088776,10.080754806129153,1.492561453817709,0
|
| 816 |
+
56.699863589744595,3.3338221019496275,10.574195689221387,1.5614626829434934,0
|
| 817 |
+
58.40514229937916,2.356909510053561,11.229545608927635,1.6573429299542164,0
|
| 818 |
+
76.35604941061798,8.859636666204771,19.21499766251304,1.2711151625527406,1
|
| 819 |
+
54.24931603628619,2.1914810553312685,12.218272208003393,1.5160732609258984,0
|
| 820 |
+
49.21155011030765,2.376360081513172,11.127609098577592,1.6013409949746717,0
|
| 821 |
+
51.93785889028115,2.429852977507494,12.72050144382207,1.7417865716201235,0
|
| 822 |
+
51.49255688732965,3.0593975015249297,13.38395958418178,1.746399044015435,0
|
| 823 |
+
50.91750792194665,0.9929460744844816,11.519189432493679,1.5095966567053283,0
|
| 824 |
+
55.75937357134977,2.104619769832726,11.467954045560484,1.2124776192352384,0
|
| 825 |
+
56.256308895479194,1.5067788733649037,13.22297410825745,1.3389446380923298,0
|
| 826 |
+
56.25563284583021,2.0110967336208643,8.434064262405029,1.4922648240785679,0
|
| 827 |
+
63.14029321092427,2.0023779274982645,12.296334423791254,1.6449194521506159,0
|
| 828 |
+
44.99320062336138,2.350776153406452,13.930263393968254,1.3800513866553534,0
|
| 829 |
+
51.627078918828516,1.5220930144367233,11.85870813697375,1.6713883834185173,0
|
| 830 |
+
53.11289586544666,2.0027135740653033,10.501282663003481,1.6406065450379472,0
|
| 831 |
+
47.85316995452769,1.575470014660974,9.587721283182688,1.7161218897006394,0
|
| 832 |
+
55.916845496460276,1.8692915538465922,12.021108124310258,1.4015270839771914,0
|
| 833 |
+
55.33448430964223,2.311983714186724,12.302017279822383,1.704368736600032,0
|
| 834 |
+
52.17094188019414,1.9541262901349328,12.43680780169724,1.3858702882427736,0
|
| 835 |
+
60.34959242977097,2.0193647874982776,11.009549825967017,1.7746431433134848,0
|
| 836 |
+
47.19585924538465,1.8888962773526412,12.138531057381687,1.5316296903132132,0
|
| 837 |
+
49.88063616943992,2.340977933697079,9.285574546624156,1.7131613907104675,0
|
| 838 |
+
63.210739927783564,2.3184776943596233,10.54257184048056,1.7531329559229958,0
|
| 839 |
+
81.78480098487611,5.796408048981009,16.186941224050415,0.6733377843778415,1
|
| 840 |
+
49.30506225840376,2.647802621657173,9.445832082160035,1.4738738156668203,0
|
| 841 |
+
48.52051202243292,2.2041409549789637,12.921660184338712,1.4573851491958825,0
|
| 842 |
+
55.813552962479775,3.3628898959408424,11.735451074266004,1.3734285032212916,0
|
| 843 |
+
60.84471546688132,2.766026144207089,13.02358876471919,1.5562886217250105,0
|
| 844 |
+
52.91470832545086,1.848465459551099,11.946262880001067,1.399663598999487,0
|
| 845 |
+
56.59909690689375,2.2653820939557723,11.325044427203027,1.5860043705259417,0
|
| 846 |
+
60.14932444642026,2.318413058394014,13.768431867887472,1.524228697823077,0
|
| 847 |
+
58.069268961844905,2.995226148958012,11.442873395876898,1.5787643960958897,0
|
| 848 |
+
51.40122085404899,1.069792621331074,14.389368133684211,1.4434210687816393,0
|
| 849 |
+
54.52983133068748,1.7017906869988053,11.315765705826964,1.6137529548966099,0
|
| 850 |
+
52.12207906686084,2.097965242475783,7.855986741489385,1.4540696881542678,0
|
| 851 |
+
55.89438219509873,0.7347028120736123,10.322541274190185,1.429520212617064,0
|
| 852 |
+
52.95102908371385,2.7826537677735885,10.324008596923088,1.759112742994215,0
|
| 853 |
+
49.789391532662144,2.059699776580968,14.058513514299777,1.502759132335698,0
|
| 854 |
+
53.65624309983941,2.255675214699056,11.122217326609483,1.3778745027020831,0
|
| 855 |
+
56.350298195195734,2.765049658202257,11.322073530219738,1.4159326785308441,0
|
| 856 |
+
49.11677482198937,1.9360411813378433,9.974851322810368,1.5739901690758649,0
|
| 857 |
+
56.461776257456314,2.406896158595107,14.33822437169863,1.4745673926449334,0
|
| 858 |
+
55.902239358040724,2.6045973659265864,13.849295614963514,1.596752503397259,0
|
| 859 |
+
49.14623199265199,1.7528963240102615,13.962369910319865,1.388082527558591,0
|
| 860 |
+
57.66234094525372,1.7420882613517814,9.629491023231697,1.2956923753721021,0
|
| 861 |
+
56.020853667423495,2.267561725934041,14.210119622162635,1.6643283617243714,0
|
| 862 |
+
61.41701744606856,2.3818490751714814,12.904510280140014,1.3111790310473495,0
|
| 863 |
+
53.83131525678578,2.5064826902373,11.055983273498244,1.5332974166514406,0
|
| 864 |
+
54.72344826109544,1.4574722604362822,11.026105620584795,1.3763803917990785,0
|
| 865 |
+
58.34323158525735,1.4732003600341848,10.6385737408491,1.498758017410562,0
|
| 866 |
+
55.21741434156153,1.9804730449475314,10.603389768086846,1.4002407419457565,0
|
| 867 |
+
62.28519540325244,1.8887299236672237,9.510168177870469,1.4257877354211432,0
|
| 868 |
+
47.03675201950401,2.4877732549999476,11.238899135399363,1.653713510062616,0
|
| 869 |
+
62.986923566767146,2.6028393196212507,10.984088723986083,1.679450922805537,0
|
| 870 |
+
55.651012260420025,1.6988280096545996,14.118769604941509,1.419972071147568,0
|
| 871 |
+
53.3716870545987,2.614560535533027,10.364329121174283,1.603291755146833,0
|
| 872 |
+
48.077313577971125,1.7983799540241476,11.312877297497808,1.5266386675385388,0
|
| 873 |
+
52.44099386900101,2.1976835138878275,13.299337801287793,1.25034654100047,0
|
| 874 |
+
71.71674743953778,4.412282728867404,16.192055044780098,0.9938137737824405,1
|
| 875 |
+
51.11940192139435,2.091386920890662,12.629197339279873,1.7140477150839704,0
|
| 876 |
+
62.34954670195008,1.7901230356145783,12.996438453083453,1.6294638680416362,0
|
| 877 |
+
75.42316412463299,5.8636579395192605,16.040602257349512,1.0550971416483426,1
|
| 878 |
+
57.84490631917142,2.1821946319049546,12.434828213877601,1.4186994144711043,0
|
| 879 |
+
56.0115392598796,2.520495359697487,11.095532531149495,1.4061563840397906,0
|
| 880 |
+
56.87003736900818,2.6937025725232004,12.255265414787898,1.4787895993761933,0
|
| 881 |
+
55.521098085891545,2.27492120699364,13.362094265276978,1.4908473973457388,0
|
| 882 |
+
57.97301668481377,2.3058048663975255,11.119018855854332,1.3720593273311592,0
|
| 883 |
+
53.855005065777235,1.9287210899440876,13.80405120980422,1.512938075433751,0
|
| 884 |
+
53.1692022761727,2.0909854359477893,11.439886594764177,1.657204436642588,0
|
| 885 |
+
50.102123873117996,1.4281873987389595,10.84917439720404,1.521248504608654,0
|
| 886 |
+
57.54762513348884,3.0991438504615316,14.523575378010147,1.2928254102763839,0
|
| 887 |
+
57.1524617480157,2.766840239378351,11.957875387343952,1.7363880432818084,0
|
| 888 |
+
49.99873784430741,1.4137358749987796,15.23798851605725,1.3567032736770286,0
|
| 889 |
+
49.171376720577335,2.438764668633398,11.550993138372418,1.2571392269822752,0
|
| 890 |
+
54.586319545701464,1.6392844769913726,9.339878191785479,1.5836363764237225,0
|
| 891 |
+
56.248037886204976,2.485268518069243,13.269456093461594,1.4856174596151044,0
|
| 892 |
+
53.51313321365722,2.110672415493055,9.397535876931851,1.4192551357025025,0
|
| 893 |
+
50.91087887341068,1.8199049556905473,9.43279026040431,1.6842591552501576,0
|
| 894 |
+
51.30845423241893,2.296210558884091,14.839573328133815,1.9221671179899242,0
|
| 895 |
+
55.70604968548979,3.1802423003915137,13.17703307419753,1.3850307248703497,0
|
| 896 |
+
54.01975739523719,2.766344910259795,12.373370398012545,1.6237406834421153,0
|
| 897 |
+
56.366222203762035,2.6813287862434207,10.16294283352419,1.6132292838711064,0
|
| 898 |
+
56.130347931677186,1.0278510531056615,11.8949807117808,1.5571243879256509,0
|
| 899 |
+
51.66652477620238,2.6581557205372834,10.822831129266014,1.5820000548924726,0
|
| 900 |
+
55.6407623732683,2.4330888310986554,10.226324141690345,1.3835288387777454,0
|
| 901 |
+
73.80448741101571,3.5084837940083147,15.579692884366738,1.203498124111994,1
|
| 902 |
+
56.24581133721376,2.263298355138847,10.981531028472027,1.4543283288380209,0
|
| 903 |
+
54.76635502456527,1.8849587448721654,11.478925749602203,1.3115917810697943,0
|
| 904 |
+
55.00033757236566,2.0182083548466005,11.705993553232476,1.4951288514123817,0
|
| 905 |
+
60.629927445254864,2.507049588556312,11.001183433319346,1.289024905948165,0
|
| 906 |
+
52.099095741856985,2.9270250907287294,11.039264892216861,1.5949302485335932,0
|
| 907 |
+
53.77166712666169,2.1428950541110816,8.720337031874148,1.5513005186131532,0
|
| 908 |
+
50.5218564989179,2.7389216778725913,11.187024899660711,1.618876111750891,0
|
| 909 |
+
55.78710438662783,1.157798922505763,11.734711209640807,1.421664228068624,0
|
| 910 |
+
50.87674511891539,2.8322699046690185,13.513002533932259,1.393042937746303,0
|
| 911 |
+
59.25540613093743,2.4780376369115755,10.082867455932295,1.6294631277068032,0
|
| 912 |
+
60.75110775966585,1.5011569184407985,10.975362297622238,1.5060504608332037,0
|
| 913 |
+
60.436882401182444,1.4009738123616433,12.959904248701188,1.4545197574934254,0
|
| 914 |
+
54.17824976852948,2.370104988434169,10.258632065419892,1.5163053229220114,0
|
| 915 |
+
57.95765068920379,2.2201282510002316,14.220148805570874,1.5592714228547588,0
|
| 916 |
+
49.34893646443054,2.6120998098979316,12.823474311115366,1.6454114686122308,0
|
| 917 |
+
50.840063575038016,2.2512765918631334,12.663681907454567,1.3331933618461198,0
|
| 918 |
+
86.01827674726094,7.353339373742408,18.654882311796165,1.0409182019205145,1
|
| 919 |
+
78.8206447039002,4.365692137751949,19.809297238947664,0.7927409674336395,1
|
| 920 |
+
56.33718051399086,1.8376944742411379,10.502964610059184,1.3361726509369563,0
|
| 921 |
+
56.82710095022965,2.4316849030163437,13.0872820073343,1.7256760077883841,0
|
| 922 |
+
54.805126392279526,2.550361578429793,13.684017381845608,1.5061770030523767,0
|
| 923 |
+
57.46391769030198,2.354810040954584,12.86799245072275,1.496154140947849,0
|
| 924 |
+
55.81118910759112,1.3924745547076063,12.571907085121463,1.5916113233694291,0
|
| 925 |
+
52.76171085580204,2.1956026552572143,13.936543582776203,1.653132423150371,0
|
| 926 |
+
61.88307932466394,1.4055512179106375,12.8689229569814,1.56193370928336,0
|
| 927 |
+
55.27752454053112,3.1564774038658765,13.550679251908349,1.408764040599407,0
|
| 928 |
+
52.02564708474974,1.7819714425771065,16.218973872358085,1.538473796766531,0
|
| 929 |
+
54.60605806196231,2.9396372553371153,10.825230207427248,1.4837195050972265,0
|
| 930 |
+
57.43504588889776,2.9759400600612445,13.888672274002104,1.4892002111340317,0
|
| 931 |
+
51.550728162097826,2.125963797726123,12.218445471515826,1.4143296128460394,0
|
| 932 |
+
58.60073825607985,2.6942766212326577,15.797857016613266,1.4264306758959435,0
|
| 933 |
+
46.74704689278103,2.2339933130255445,10.958604356627896,1.443972900422873,0
|
| 934 |
+
50.626114518152065,2.6942659314257313,10.776260028023351,1.1793749105879119,0
|
| 935 |
+
54.62294978298977,1.040194636624391,12.990056237685502,1.689773991823249,0
|
| 936 |
+
59.508964827872134,1.888916149872871,11.989324717307227,1.3289689715023263,0
|
| 937 |
+
53.81371618586117,1.5109953615760672,11.611186111027376,1.4149930462034774,0
|
| 938 |
+
57.06164161160324,1.916852542209497,11.33089593231175,1.5825380614550548,0
|
| 939 |
+
57.09675137125108,2.188383144574817,11.297361453150813,1.3641952180977253,0
|
| 940 |
+
63.37267323572238,1.7010740083779874,11.607657148400397,1.4123956000166988,0
|
| 941 |
+
58.726292051496976,1.6640187238548907,12.357582562256137,1.5765208073420163,0
|
| 942 |
+
62.62024085625788,2.005683409466591,12.882960227606103,1.526557402126487,0
|
| 943 |
+
66.36748423797884,5.050253016738091,14.0,0.8085233487182514,1
|
| 944 |
+
57.46102706787425,1.309630946218265,11.435843714160626,1.5384951571622294,0
|
| 945 |
+
56.092816091408494,2.503145578054354,10.843154750648042,1.501886775352775,0
|
| 946 |
+
54.772867222429234,1.3239507136365147,12.687838704318253,1.6035137122763092,0
|
| 947 |
+
74.20047478635844,5.950129796505029,17.778293577592592,0.998223328559262,1
|
| 948 |
+
43.14188464863339,1.9096742986272077,12.554037089549857,1.5643448086690799,0
|
| 949 |
+
61.245752807214295,2.184583742957908,10.520639834225104,1.471986279779347,0
|
| 950 |
+
49.13181901843604,1.9284145844719434,10.854841024034009,1.4559895363404038,0
|
| 951 |
+
54.36140677031193,1.5568033324581516,13.679095742997571,1.0875846920942167,0
|
| 952 |
+
47.165634238411876,2.3484579353680566,12.548231017557757,1.2153096722247756,0
|
| 953 |
+
55.204568234208644,1.7731203887062943,11.471602447575346,1.5495779292881393,0
|
| 954 |
+
58.163206884715954,1.0278283457905633,12.160657545014207,1.4964865561198777,0
|
| 955 |
+
61.603711728925,2.0616499549571436,9.959634843611738,1.4501336198490344,0
|
| 956 |
+
62.19024466657856,1.9310943268214305,11.869560036590968,1.6462127722629871,0
|
| 957 |
+
54.195581381924676,1.6662031154775572,13.847812701433956,1.4258490074725958,0
|
| 958 |
+
53.64296606446394,2.3822672445166315,7.4043302005314064,1.2358065893036183,0
|
| 959 |
+
57.50034080499262,2.1234870618968937,10.678142328845924,1.5487327078236877,0
|
| 960 |
+
48.756166588022225,1.990575628037481,13.239610964839887,1.506180910017243,0
|
| 961 |
+
51.536675537227026,2.199040073411827,12.590065305381145,1.61252223948485,0
|
| 962 |
+
57.47668446790157,2.1878513081145923,12.190300464443764,1.616521154829772,0
|
| 963 |
+
54.717278473391715,2.681480286624724,14.35499772749842,1.5161173054045975,0
|
| 964 |
+
56.34633250642174,3.0549719770060357,12.402244171432974,1.4682680095379208,0
|
| 965 |
+
57.0651902884058,2.784769073646942,15.030959548163748,1.6467889295497447,0
|
| 966 |
+
61.91479057762237,2.3363226317160644,13.73842437356535,1.4558146868007582,0
|
| 967 |
+
52.276281822384234,1.766497371838287,13.153854312055692,1.6934894547927362,0
|
| 968 |
+
56.755972634953196,1.8432230093148227,12.297867931022274,1.5177996254585995,0
|
| 969 |
+
54.896548608184574,2.0730186609761097,12.826386571340311,1.395266781040114,0
|
| 970 |
+
51.139532951070514,2.123157447818991,12.246480989072873,1.2797040854527062,0
|
| 971 |
+
51.94777116122093,1.8190127708448713,11.94828770244805,1.382361223662723,0
|
| 972 |
+
80.08760686309627,4.903930356647553,14.31961124391651,0.2991558784422512,1
|
| 973 |
+
54.281923146869595,2.204252813361577,12.81798489295059,1.5632425244864745,0
|
| 974 |
+
51.823454839898304,2.3252231501303804,12.02600194372696,1.6108989038512356,0
|
| 975 |
+
59.399918601368334,3.1514537311370843,10.653760543718006,1.747216824273582,0
|
| 976 |
+
57.997735598910964,2.4019770103678058,14.667481360079734,1.6169294131157175,0
|
| 977 |
+
56.46612562894892,2.9386968170850176,13.712221152154827,1.376724705538867,0
|
| 978 |
+
56.65556114149077,1.9345117477221427,12.591356474163046,1.426162936685192,0
|
| 979 |
+
61.727266477203294,1.8506597820075852,12.704040989431162,1.640460062552197,0
|
| 980 |
+
57.33062096795083,3.340816438638031,10.80276996336775,1.4594405166294961,0
|
| 981 |
+
54.929748694090215,2.269962156019557,10.030248422700094,1.1611179183633582,0
|
| 982 |
+
53.44076078737693,2.7938171963605605,9.42125829918593,1.3627161418270015,0
|
| 983 |
+
53.63063624534447,1.6265839589162798,10.216679769603592,1.3607513803816458,0
|
| 984 |
+
50.96842820150582,2.2360088209585265,14.153967187202664,1.6177431433031877,0
|
| 985 |
+
51.378083778559756,2.611876565938091,10.386396062032151,1.4034658312574029,0
|
| 986 |
+
58.42717593026611,2.0125276550754325,11.550520403916952,1.2643353386144074,0
|
| 987 |
+
55.04997647491075,2.365520077498098,12.299452526867272,1.4915338354669339,0
|
| 988 |
+
56.33228149047302,1.9948300133274455,13.626879587195766,1.28145218688281,0
|
| 989 |
+
61.04491373310689,1.9252236894349588,12.147002871149075,1.4850248129256824,0
|
| 990 |
+
53.68930762255216,2.2510156486202875,14.38532820843267,1.553604745823351,0
|
| 991 |
+
53.82723365340495,1.6365060448995683,12.912677604644518,1.3685910803834131,0
|
| 992 |
+
55.71710253982526,2.3580239353221435,13.54035861948093,1.5448377228876227,0
|
| 993 |
+
51.77360438277051,1.3588367591044868,13.66495446465855,1.6631181930222696,0
|
| 994 |
+
54.26055054581896,2.041046725685769,8.838465918578397,1.5263550684247276,0
|
| 995 |
+
59.45186356664105,2.1725325668985414,12.829615180537868,1.5598472851053518,0
|
| 996 |
+
50.46685114398608,2.146909034688712,11.157290184711616,1.5865062542315103,0
|
| 997 |
+
51.199911780357674,2.5350396211010953,12.048555151090547,1.7589198562004265,0
|
| 998 |
+
52.11376786582861,1.625398001405853,11.486770663901929,1.6542080348098775,0
|
| 999 |
+
51.071922320678794,1.6118998416782837,10.487536670588607,1.6076588413125095,0
|
| 1000 |
+
52.579997148765074,3.129747403811656,10.434083892797037,1.331260596734677,0
|
| 1001 |
+
53.5749441157543,1.9927634670820709,12.904405415632834,1.6311416518378596,0
|
models/anomaly_iforest.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9dc690ec59c1639e4bcdc6d85f3ae61e9e932ae935b250bab7dd5de7654d62fa
|
| 3 |
+
size 2149241
|
models/anomaly_scaler.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6eedcb449295a4276c34a0e08175010fd3b6958e8fc7158658461a9820011ff9
|
| 3 |
+
size 679
|
models/intent_pipeline.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2a036b8e8f424ee6a56643919058a5b8df1be3db1e3673cd0618f3aabd6b6b04
|
| 3 |
+
size 65196
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio==5.9.1
|
| 2 |
+
scikit-learn==1.7.2
|
| 3 |
+
pandas==2.2.3
|
| 4 |
+
numpy==1.26.4
|
| 5 |
+
matplotlib==3.9.2
|
| 6 |
+
joblib==1.4.2
|
| 7 |
+
huggingface_hub==0.26.5
|
| 8 |
+
spaces>=0.30.0
|
src/__init__.py
ADDED
|
File without changes
|
src/anomaly_model.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
anomaly_model.py
|
| 3 |
+
-----------------
|
| 4 |
+
Isolation Forest based anomaly detector for conveyor / crane motor sensor
|
| 5 |
+
streams (motor temperature, vibration, current draw, belt speed). This
|
| 6 |
+
powers the "Predictive Maintenance" tab -- flags abnormal equipment
|
| 7 |
+
behaviour before it causes an unplanned stoppage, which is exactly the kind
|
| 8 |
+
of workload Daifuku's intralogistics platforms (e.g. AS/RS, sorters, AGVs)
|
| 9 |
+
generate continuously in production.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from dataclasses import dataclass
|
| 13 |
+
|
| 14 |
+
import joblib
|
| 15 |
+
import numpy as np
|
| 16 |
+
from sklearn.ensemble import IsolationForest
|
| 17 |
+
from sklearn.preprocessing import StandardScaler
|
| 18 |
+
|
| 19 |
+
FEATURES = ["motor_temp_c", "vibration_mm_s", "current_amps", "belt_speed_mps"]
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@dataclass
|
| 23 |
+
class AnomalyResult:
|
| 24 |
+
is_anomaly: bool
|
| 25 |
+
anomaly_score: float # higher = more anomalous, roughly in [0, 1]
|
| 26 |
+
raw_score: float
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def build_model(contamination: float = 0.1, seed: int = 42) -> IsolationForest:
|
| 30 |
+
return IsolationForest(
|
| 31 |
+
n_estimators=200,
|
| 32 |
+
contamination=contamination,
|
| 33 |
+
random_state=seed,
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def score_reading(model: IsolationForest, scaler: StandardScaler, reading: dict) -> AnomalyResult:
|
| 38 |
+
x = np.array([[reading[f] for f in FEATURES]])
|
| 39 |
+
x_scaled = scaler.transform(x)
|
| 40 |
+
raw = model.decision_function(x_scaled)[0] # higher = more normal
|
| 41 |
+
pred = model.predict(x_scaled)[0] # 1 = normal, -1 = anomaly
|
| 42 |
+
# squash raw decision_function (~[-0.5, 0.5]) into a 0-1 "anomaly score"
|
| 43 |
+
anomaly_score = float(np.clip(0.5 - raw, 0, 1))
|
| 44 |
+
return AnomalyResult(is_anomaly=(pred == -1), anomaly_score=anomaly_score, raw_score=float(raw))
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def save_artifacts(model, scaler, model_path: str, scaler_path: str):
|
| 48 |
+
joblib.dump(model, model_path)
|
| 49 |
+
joblib.dump(scaler, scaler_path)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def load_artifacts(model_path: str, scaler_path: str):
|
| 53 |
+
return joblib.load(model_path), joblib.load(scaler_path)
|
src/data_generation.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
data_generation.py
|
| 3 |
+
-------------------
|
| 4 |
+
Generates the synthetic datasets used to train/evaluate the two ML models
|
| 5 |
+
that power the Smart Warehouse AI Assistant:
|
| 6 |
+
|
| 7 |
+
1. Intent classifier -> routes free-text queries into warehouse-ops intents
|
| 8 |
+
2. Anomaly detector -> flags abnormal conveyor/AGV sensor readings
|
| 9 |
+
|
| 10 |
+
All data is synthetically generated with templates + randomised slots so the
|
| 11 |
+
project is fully self-contained and reproducible (no external datasets or
|
| 12 |
+
scraping required). A fixed random seed keeps results reproducible.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import random
|
| 16 |
+
import numpy as np
|
| 17 |
+
import pandas as pd
|
| 18 |
+
|
| 19 |
+
RANDOM_SEED = 42
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# --------------------------------------------------------------------------
|
| 23 |
+
# 1. INTENT CLASSIFICATION DATA
|
| 24 |
+
# --------------------------------------------------------------------------
|
| 25 |
+
|
| 26 |
+
INTENT_TEMPLATES = {
|
| 27 |
+
"inventory_check": [
|
| 28 |
+
"How many units of {sku} are in {zone}?",
|
| 29 |
+
"What is the current stock level for {sku}?",
|
| 30 |
+
"Check inventory count for {sku} in {zone}",
|
| 31 |
+
"Do we have enough {sku} to fulfill 200 units?",
|
| 32 |
+
"Show me the on-hand quantity of {sku}",
|
| 33 |
+
"Is {sku} in stock at {zone}?",
|
| 34 |
+
"Give me stock levels across all zones for {sku}",
|
| 35 |
+
"How much inventory is left for {sku}?",
|
| 36 |
+
],
|
| 37 |
+
"order_status": [
|
| 38 |
+
"What's the status of order {order_id}?",
|
| 39 |
+
"Has order {order_id} shipped yet?",
|
| 40 |
+
"Track order {order_id} for me",
|
| 41 |
+
"Is order {order_id} delayed?",
|
| 42 |
+
"When will order {order_id} be delivered?",
|
| 43 |
+
"Show the fulfillment status of {order_id}",
|
| 44 |
+
"Why hasn't order {order_id} left the dock yet?",
|
| 45 |
+
],
|
| 46 |
+
"equipment_maintenance": [
|
| 47 |
+
"The conveyor belt in {zone} is making noise",
|
| 48 |
+
"Crane {equip_id} reported a fault code",
|
| 49 |
+
"Schedule maintenance for {equip_id}",
|
| 50 |
+
"{equip_id} motor temperature seems high",
|
| 51 |
+
"The sorter in {zone} keeps jamming",
|
| 52 |
+
"Report vibration issue on {equip_id}",
|
| 53 |
+
"Belt {equip_id} stopped unexpectedly, please check",
|
| 54 |
+
"Log a breakdown for {equip_id} in {zone}",
|
| 55 |
+
],
|
| 56 |
+
"agv_navigation": [
|
| 57 |
+
"Route {equip_id} to picking station {station}",
|
| 58 |
+
"Send AGV {equip_id} to {zone}",
|
| 59 |
+
"Why is {equip_id} stuck near {zone}?",
|
| 60 |
+
"Reassign {equip_id} to charging station",
|
| 61 |
+
"What is the current location of {equip_id}?",
|
| 62 |
+
"Redirect {equip_id} around the blocked aisle in {zone}",
|
| 63 |
+
],
|
| 64 |
+
"picking_optimization": [
|
| 65 |
+
"What's the fastest picking route for order {order_id}?",
|
| 66 |
+
"Optimize the pick path for {zone}",
|
| 67 |
+
"Should we batch pick these orders together?",
|
| 68 |
+
"Suggest a wave picking plan for {zone}",
|
| 69 |
+
"How can we reduce travel time for pickers in {zone}?",
|
| 70 |
+
"Recommend a picking strategy for high-velocity SKUs",
|
| 71 |
+
],
|
| 72 |
+
"safety_incident": [
|
| 73 |
+
"A forklift near-miss was reported in {zone}",
|
| 74 |
+
"Log a safety incident involving {equip_id}",
|
| 75 |
+
"There was a near collision between {equip_id} and a pedestrian in {zone}",
|
| 76 |
+
"File an incident report for {zone}",
|
| 77 |
+
"A worker slipped near {equip_id}, please log it",
|
| 78 |
+
"Report unsafe pallet stacking in {zone}",
|
| 79 |
+
],
|
| 80 |
+
"system_status": [
|
| 81 |
+
"Is {equip_id} operational?",
|
| 82 |
+
"What is the uptime for {equip_id} today?",
|
| 83 |
+
"Check system health for {zone}",
|
| 84 |
+
"Are all cranes online in {zone}?",
|
| 85 |
+
"Give me the current status of the WMS integration",
|
| 86 |
+
"Is the sorter in {zone} running normally?",
|
| 87 |
+
],
|
| 88 |
+
"general_faq": [
|
| 89 |
+
"What is a WMS?",
|
| 90 |
+
"Explain how an AS/RS works",
|
| 91 |
+
"What's the difference between AGV and AMR?",
|
| 92 |
+
"What is cycle counting?",
|
| 93 |
+
"How does goods-to-person picking work?",
|
| 94 |
+
"What KPIs matter most in warehouse automation?",
|
| 95 |
+
"What is predictive maintenance?",
|
| 96 |
+
"How do sortation systems decide where to route a parcel?",
|
| 97 |
+
],
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
ZONES = ["Zone A", "Zone B", "Zone C", "Zone D", "the mezzanine", "the receiving dock"]
|
| 101 |
+
EQUIP_IDS = ["AGV-07", "AGV-12", "Crane-03", "Sorter-02", "Conveyor-14", "AMR-21", "Crane-05"]
|
| 102 |
+
STATIONS = ["3", "5", "7", "12"]
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def _rand_sku():
|
| 106 |
+
return f"SKU-{random.randint(1000, 9999)}"
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def _rand_order():
|
| 110 |
+
return f"#{random.randint(10000, 99999)}"
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def generate_intent_dataset(n_per_intent: int = 45, seed: int = RANDOM_SEED) -> pd.DataFrame:
|
| 114 |
+
"""Generate a labelled (text, intent) dataset by sampling + slot-filling templates."""
|
| 115 |
+
rng = random.Random(seed)
|
| 116 |
+
rows = []
|
| 117 |
+
for intent, templates in INTENT_TEMPLATES.items():
|
| 118 |
+
for _ in range(n_per_intent):
|
| 119 |
+
template = rng.choice(templates)
|
| 120 |
+
text = template.format(
|
| 121 |
+
sku=_rand_sku(),
|
| 122 |
+
order_id=_rand_order(),
|
| 123 |
+
zone=rng.choice(ZONES),
|
| 124 |
+
equip_id=rng.choice(EQUIP_IDS),
|
| 125 |
+
station=rng.choice(STATIONS),
|
| 126 |
+
)
|
| 127 |
+
rows.append({"text": text, "intent": intent})
|
| 128 |
+
df = pd.DataFrame(rows)
|
| 129 |
+
df = df.sample(frac=1.0, random_state=seed).reset_index(drop=True)
|
| 130 |
+
return df
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
# --------------------------------------------------------------------------
|
| 134 |
+
# 2. INVENTORY / ORDERS DATA (used by the Inventory & Task Query tab)
|
| 135 |
+
# --------------------------------------------------------------------------
|
| 136 |
+
|
| 137 |
+
def generate_inventory_db(n_skus: int = 60, seed: int = RANDOM_SEED) -> pd.DataFrame:
|
| 138 |
+
rng = np.random.default_rng(seed)
|
| 139 |
+
categories = ["Electronics", "Apparel", "Automotive Parts", "Food & Beverage", "Household"]
|
| 140 |
+
zones = ["Zone A", "Zone B", "Zone C", "Zone D"]
|
| 141 |
+
rows = []
|
| 142 |
+
for i in range(n_skus):
|
| 143 |
+
sku = f"SKU-{1000 + i}"
|
| 144 |
+
rows.append({
|
| 145 |
+
"sku": sku,
|
| 146 |
+
"description": f"{rng.choice(categories)} item {1000 + i}",
|
| 147 |
+
"category": rng.choice(categories),
|
| 148 |
+
"zone": rng.choice(zones),
|
| 149 |
+
"on_hand_units": int(rng.integers(0, 2000)),
|
| 150 |
+
"reorder_point": int(rng.integers(50, 300)),
|
| 151 |
+
"unit_cost_jpy": int(rng.integers(200, 15000)),
|
| 152 |
+
})
|
| 153 |
+
return pd.DataFrame(rows)
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
def generate_orders_db(n_orders: int = 80, seed: int = RANDOM_SEED) -> pd.DataFrame:
|
| 157 |
+
rng = np.random.default_rng(seed)
|
| 158 |
+
statuses = ["Received", "Picking", "Packed", "Shipped", "Delayed"]
|
| 159 |
+
weights = [0.15, 0.25, 0.2, 0.3, 0.1]
|
| 160 |
+
rows = []
|
| 161 |
+
for i in range(n_orders):
|
| 162 |
+
order_id = f"#{10000 + i}"
|
| 163 |
+
rows.append({
|
| 164 |
+
"order_id": order_id,
|
| 165 |
+
"status": rng.choice(statuses, p=weights),
|
| 166 |
+
"num_lines": int(rng.integers(1, 25)),
|
| 167 |
+
"priority": rng.choice(["Standard", "Express", "Same-Day"], p=[0.6, 0.3, 0.1]),
|
| 168 |
+
"zone": rng.choice(["Zone A", "Zone B", "Zone C", "Zone D"]),
|
| 169 |
+
})
|
| 170 |
+
return pd.DataFrame(rows)
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
# --------------------------------------------------------------------------
|
| 174 |
+
# 3. SENSOR DATA FOR ANOMALY DETECTION (predictive maintenance)
|
| 175 |
+
# --------------------------------------------------------------------------
|
| 176 |
+
|
| 177 |
+
def generate_sensor_dataset(n_normal: int = 900, n_anomaly: int = 100, seed: int = RANDOM_SEED) -> pd.DataFrame:
|
| 178 |
+
"""
|
| 179 |
+
Synthetic conveyor/crane motor sensor readings.
|
| 180 |
+
Features: motor_temp_c, vibration_mm_s, current_amps, belt_speed_mps
|
| 181 |
+
Label: 1 = anomaly (bearing wear / misalignment / overload pattern), 0 = normal
|
| 182 |
+
"""
|
| 183 |
+
rng = np.random.default_rng(seed)
|
| 184 |
+
|
| 185 |
+
normal = pd.DataFrame({
|
| 186 |
+
"motor_temp_c": rng.normal(55, 4, n_normal).clip(35, 75),
|
| 187 |
+
"vibration_mm_s": rng.normal(2.2, 0.5, n_normal).clip(0.2, 5),
|
| 188 |
+
"current_amps": rng.normal(12, 1.5, n_normal).clip(5, 20),
|
| 189 |
+
"belt_speed_mps": rng.normal(1.5, 0.15, n_normal).clip(0.8, 2.2),
|
| 190 |
+
"label": 0,
|
| 191 |
+
})
|
| 192 |
+
|
| 193 |
+
# Anomalies: elevated temp + vibration + current, reduced/erratic belt speed
|
| 194 |
+
anomaly = pd.DataFrame({
|
| 195 |
+
"motor_temp_c": rng.normal(78, 6, n_anomaly).clip(65, 100),
|
| 196 |
+
"vibration_mm_s": rng.normal(5.5, 1.2, n_anomaly).clip(3.5, 10),
|
| 197 |
+
"current_amps": rng.normal(19, 2.5, n_anomaly).clip(14, 28),
|
| 198 |
+
"belt_speed_mps": rng.normal(0.9, 0.3, n_anomaly).clip(0.1, 1.6),
|
| 199 |
+
"label": 1,
|
| 200 |
+
})
|
| 201 |
+
|
| 202 |
+
df = pd.concat([normal, anomaly], ignore_index=True)
|
| 203 |
+
df = df.sample(frac=1.0, random_state=seed).reset_index(drop=True)
|
| 204 |
+
return df
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
# --------------------------------------------------------------------------
|
| 208 |
+
# 4. RETRIEVAL EVALUATION SET (query -> expected KB doc id)
|
| 209 |
+
# --------------------------------------------------------------------------
|
| 210 |
+
|
| 211 |
+
RETRIEVAL_EVAL_SET = [
|
| 212 |
+
("How does an AS/RS crane retrieve a pallet?", "asrs_overview"),
|
| 213 |
+
("What's the difference between an AGV and an AMR?", "agv_amr_overview"),
|
| 214 |
+
("What does a WMS integrate with?", "wms_overview"),
|
| 215 |
+
("Why would a sorter jam?", "conveyor_sorting"),
|
| 216 |
+
("What is batch picking?", "picking_strategies"),
|
| 217 |
+
("How can we predict a motor failure before it happens?", "predictive_maintenance"),
|
| 218 |
+
("What should I do after a near-miss with a forklift?", "safety_protocol"),
|
| 219 |
+
("How do we keep inventory counts accurate?", "inventory_accuracy"),
|
| 220 |
+
("What KPIs should a warehouse manager track?", "kpi_overview"),
|
| 221 |
+
("How can automated warehouses save energy?", "energy_efficiency"),
|
| 222 |
+
]
|
src/intent_model.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
intent_model.py
|
| 3 |
+
----------------
|
| 4 |
+
TF-IDF + Logistic Regression intent classifier that routes free-text
|
| 5 |
+
warehouse queries into one of 8 operational intents. Chosen deliberately
|
| 6 |
+
over a heavier transformer classifier: it trains in <1s, needs no GPU/
|
| 7 |
+
internet on Spaces startup, and reaches high accuracy on this
|
| 8 |
+
template-generated-but-linguistically-varied dataset -- a good example of
|
| 9 |
+
picking the right-sized model for the job rather than defaulting to the
|
| 10 |
+
biggest one.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
from dataclasses import dataclass
|
| 14 |
+
|
| 15 |
+
import joblib
|
| 16 |
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
| 17 |
+
from sklearn.linear_model import LogisticRegression
|
| 18 |
+
from sklearn.pipeline import Pipeline
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
@dataclass
|
| 22 |
+
class IntentPrediction:
|
| 23 |
+
intent: str
|
| 24 |
+
confidence: float
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
INTENT_DESCRIPTIONS = {
|
| 28 |
+
"inventory_check": "Inventory / stock level lookup",
|
| 29 |
+
"order_status": "Order status / tracking",
|
| 30 |
+
"equipment_maintenance": "Equipment fault / maintenance request",
|
| 31 |
+
"agv_navigation": "AGV / AMR routing & navigation",
|
| 32 |
+
"picking_optimization": "Picking route / strategy optimization",
|
| 33 |
+
"safety_incident": "Safety incident reporting",
|
| 34 |
+
"system_status": "Equipment / system status check",
|
| 35 |
+
"general_faq": "General warehouse automation question",
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def build_pipeline() -> Pipeline:
|
| 40 |
+
return Pipeline([
|
| 41 |
+
("tfidf", TfidfVectorizer(ngram_range=(1, 2), min_df=1, stop_words="english")),
|
| 42 |
+
("clf", LogisticRegression(max_iter=1000, C=8.0)),
|
| 43 |
+
])
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def predict(pipeline: Pipeline, text: str) -> IntentPrediction:
|
| 47 |
+
probs = pipeline.predict_proba([text])[0]
|
| 48 |
+
classes = pipeline.classes_
|
| 49 |
+
best_idx = probs.argmax()
|
| 50 |
+
return IntentPrediction(intent=classes[best_idx], confidence=float(probs[best_idx]))
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def load_pipeline(path: str) -> Pipeline:
|
| 54 |
+
return joblib.load(path)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def save_pipeline(pipeline: Pipeline, path: str):
|
| 58 |
+
joblib.dump(pipeline, path)
|
src/inventory_db.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
inventory_db.py
|
| 3 |
+
----------------
|
| 4 |
+
Very small "NL -> structured query" layer over the synthetic inventory and
|
| 5 |
+
orders tables. It uses the intent classifier's output plus simple regex
|
| 6 |
+
slot extraction (SKU codes, order IDs, zone names) to filter the
|
| 7 |
+
in-memory DataFrames -- a lightweight stand-in for the kind of
|
| 8 |
+
WMS/WCS query interface a production assistant would call as a tool.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import re
|
| 12 |
+
|
| 13 |
+
import pandas as pd
|
| 14 |
+
|
| 15 |
+
SKU_RE = re.compile(r"SKU-\d{3,4}", re.IGNORECASE)
|
| 16 |
+
ORDER_RE = re.compile(r"#\d{4,6}")
|
| 17 |
+
ZONE_RE = re.compile(r"zone [a-d]", re.IGNORECASE)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def extract_sku(text: str):
|
| 21 |
+
m = SKU_RE.search(text)
|
| 22 |
+
return m.group(0).upper() if m else None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def extract_order_id(text: str):
|
| 26 |
+
m = ORDER_RE.search(text)
|
| 27 |
+
return m.group(0) if m else None
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def extract_zone(text: str):
|
| 31 |
+
m = ZONE_RE.search(text)
|
| 32 |
+
return m.group(0).title() if m else None
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def query_inventory(inventory_df: pd.DataFrame, text: str) -> pd.DataFrame:
|
| 36 |
+
sku = extract_sku(text)
|
| 37 |
+
zone = extract_zone(text)
|
| 38 |
+
df = inventory_df.copy()
|
| 39 |
+
if sku:
|
| 40 |
+
df = df[df["sku"].str.upper() == sku]
|
| 41 |
+
if zone:
|
| 42 |
+
df = df[df["zone"].str.lower() == zone.lower()]
|
| 43 |
+
if df.empty and not sku and not zone:
|
| 44 |
+
# no specific filters recognised -> show low-stock items as a useful default
|
| 45 |
+
df = inventory_df[inventory_df["on_hand_units"] <= inventory_df["reorder_point"]]
|
| 46 |
+
return df.reset_index(drop=True)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def query_orders(orders_df: pd.DataFrame, text: str) -> pd.DataFrame:
|
| 50 |
+
order_id = extract_order_id(text)
|
| 51 |
+
zone = extract_zone(text)
|
| 52 |
+
df = orders_df.copy()
|
| 53 |
+
if order_id:
|
| 54 |
+
df = df[df["order_id"] == order_id]
|
| 55 |
+
elif zone:
|
| 56 |
+
df = df[df["zone"].str.lower() == zone.lower()]
|
| 57 |
+
elif "delay" in text.lower():
|
| 58 |
+
df = df[df["status"] == "Delayed"]
|
| 59 |
+
return df.reset_index(drop=True)
|
src/knowledge_base.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
knowledge_base.py
|
| 3 |
+
------------------
|
| 4 |
+
A small in-house knowledge base describing generic intralogistics / smart
|
| 5 |
+
warehouse concepts (ASRS, AGV/AMR, WMS, conveyor sorting, safety, picking
|
| 6 |
+
strategy). This is original written content (not scraped from any vendor
|
| 7 |
+
site) used purely as grounding context for the Retrieval-Augmented
|
| 8 |
+
Generation (RAG) pipeline that powers the AI Assistant tab.
|
| 9 |
+
|
| 10 |
+
Each entry has:
|
| 11 |
+
id - short unique key
|
| 12 |
+
title - human readable title
|
| 13 |
+
text - the passage used for retrieval + generation grounding
|
| 14 |
+
category - tag used for the retrieval evaluation set
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
KNOWLEDGE_BASE = [
|
| 18 |
+
{
|
| 19 |
+
"id": "asrs_overview",
|
| 20 |
+
"title": "Automated Storage & Retrieval Systems (AS/RS)",
|
| 21 |
+
"category": "equipment",
|
| 22 |
+
"text": (
|
| 23 |
+
"An Automated Storage and Retrieval System (AS/RS) uses stacker "
|
| 24 |
+
"cranes, shuttles, or mini-load systems to automatically place "
|
| 25 |
+
"and retrieve pallets, totes, or cartons from high-density "
|
| 26 |
+
"racking. AS/RS units are typically monitored for crane cycle "
|
| 27 |
+
"time, load/unload faults, and rail or lift motor temperature. "
|
| 28 |
+
"When a crane reports a fault code, the standard response is to "
|
| 29 |
+
"pause the aisle, dispatch a technician, and reroute retrieval "
|
| 30 |
+
"jobs to an adjacent aisle if one is available."
|
| 31 |
+
),
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"id": "agv_amr_overview",
|
| 35 |
+
"title": "AGVs and Autonomous Mobile Robots (AMR)",
|
| 36 |
+
"category": "equipment",
|
| 37 |
+
"text": (
|
| 38 |
+
"Automated Guided Vehicles (AGV) follow fixed paths such as "
|
| 39 |
+
"magnetic tape or wires, while Autonomous Mobile Robots (AMR) "
|
| 40 |
+
"navigate dynamically using LiDAR and SLAM mapping. Both are "
|
| 41 |
+
"used to move totes between picking stations, buffer zones, and "
|
| 42 |
+
"packing lines. Fleet management software assigns tasks based "
|
| 43 |
+
"on battery level, current queue length, and distance to the "
|
| 44 |
+
"target station. A vehicle blocked for more than a defined "
|
| 45 |
+
"timeout is automatically re-routed and flagged for review."
|
| 46 |
+
),
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"id": "wms_overview",
|
| 50 |
+
"title": "Warehouse Management System (WMS)",
|
| 51 |
+
"category": "software",
|
| 52 |
+
"text": (
|
| 53 |
+
"A Warehouse Management System (WMS) coordinates inbound "
|
| 54 |
+
"receiving, put-away, inventory tracking, order picking, "
|
| 55 |
+
"packing, and outbound shipping. It integrates with a "
|
| 56 |
+
"Warehouse Control System (WCS) that talks directly to "
|
| 57 |
+
"conveyors, sorters, and AS/RS controllers in real time. Key "
|
| 58 |
+
"WMS metrics include inventory accuracy, order cycle time, and "
|
| 59 |
+
"pick rate (lines picked per hour)."
|
| 60 |
+
),
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"id": "conveyor_sorting",
|
| 64 |
+
"title": "Conveyor and Sortation Systems",
|
| 65 |
+
"category": "equipment",
|
| 66 |
+
"text": (
|
| 67 |
+
"Sortation systems such as cross-belt, tilt-tray, or shoe "
|
| 68 |
+
"sorters route totes and parcels to the correct chute based on "
|
| 69 |
+
"barcode or RFID reads. Conveyor health is typically monitored "
|
| 70 |
+
"through motor current, belt speed, and vibration sensors. A "
|
| 71 |
+
"sudden rise in motor temperature combined with increased "
|
| 72 |
+
"vibration usually indicates bearing wear or belt misalignment "
|
| 73 |
+
"and should trigger a maintenance work order before a jam or "
|
| 74 |
+
"unplanned stoppage occurs."
|
| 75 |
+
),
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"id": "picking_strategies",
|
| 79 |
+
"title": "Order Picking Strategies",
|
| 80 |
+
"category": "process",
|
| 81 |
+
"text": (
|
| 82 |
+
"Common picking strategies include discrete picking (one order "
|
| 83 |
+
"at a time), batch picking (multiple orders in one pass), zone "
|
| 84 |
+
"picking (pickers assigned to fixed areas), and wave picking "
|
| 85 |
+
"(orders released in scheduled waves aligned with shipping "
|
| 86 |
+
"cutoffs). Goods-to-person systems, where an AS/RS or AMR "
|
| 87 |
+
"brings inventory to a stationary operator, generally reduce "
|
| 88 |
+
"walking time and increase pick rate compared to person-to-goods "
|
| 89 |
+
"picking."
|
| 90 |
+
),
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"id": "predictive_maintenance",
|
| 94 |
+
"title": "Predictive Maintenance in Warehouse Equipment",
|
| 95 |
+
"category": "maintenance",
|
| 96 |
+
"text": (
|
| 97 |
+
"Predictive maintenance uses sensor data such as motor "
|
| 98 |
+
"temperature, vibration amplitude, and current draw to detect "
|
| 99 |
+
"abnormal equipment behaviour before a breakdown occurs. "
|
| 100 |
+
"Machine-learning models such as Isolation Forest or "
|
| 101 |
+
"autoencoders are commonly trained on historical sensor "
|
| 102 |
+
"readings to flag anomalies. Catching a deviation early lets "
|
| 103 |
+
"a technician schedule maintenance during a planned downtime "
|
| 104 |
+
"window instead of reacting to an unplanned line stoppage."
|
| 105 |
+
),
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"id": "safety_protocol",
|
| 109 |
+
"title": "Warehouse Safety Protocols",
|
| 110 |
+
"category": "safety",
|
| 111 |
+
"text": (
|
| 112 |
+
"Safety protocols in automated warehouses cover pedestrian "
|
| 113 |
+
"separation from AGV/AMR traffic lanes, lockout-tagout (LOTO) "
|
| 114 |
+
"procedures before entering an AS/RS aisle, and near-miss "
|
| 115 |
+
"incident reporting. Any near-miss or safety incident should be "
|
| 116 |
+
"logged immediately with the location, equipment involved, and "
|
| 117 |
+
"a brief description, and forwarded to the site safety officer "
|
| 118 |
+
"the same shift."
|
| 119 |
+
),
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
"id": "inventory_accuracy",
|
| 123 |
+
"title": "Inventory Accuracy and Cycle Counting",
|
| 124 |
+
"category": "process",
|
| 125 |
+
"text": (
|
| 126 |
+
"Inventory accuracy is usually maintained through cycle "
|
| 127 |
+
"counting, where a subset of SKUs or storage locations is "
|
| 128 |
+
"counted on a rolling schedule rather than a single annual "
|
| 129 |
+
"count. Discrepancies between system quantity and physical "
|
| 130 |
+
"quantity above a defined tolerance trigger a recount and, if "
|
| 131 |
+
"confirmed, an inventory adjustment transaction in the WMS."
|
| 132 |
+
),
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"id": "kpi_overview",
|
| 136 |
+
"title": "Core Warehouse KPIs",
|
| 137 |
+
"category": "process",
|
| 138 |
+
"text": (
|
| 139 |
+
"Frequently tracked warehouse KPIs include order accuracy, "
|
| 140 |
+
"on-time shipment rate, dock-to-stock time, pick rate (lines "
|
| 141 |
+
"per hour), equipment uptime, and inventory turns. Automation "
|
| 142 |
+
"projects are typically justified using expected improvements "
|
| 143 |
+
"in throughput, labour cost per order, and space utilisation."
|
| 144 |
+
),
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"id": "energy_efficiency",
|
| 148 |
+
"title": "Energy Efficiency in Automated Warehouses",
|
| 149 |
+
"category": "sustainability",
|
| 150 |
+
"text": (
|
| 151 |
+
"Energy use in automated warehouses can be reduced through "
|
| 152 |
+
"regenerative braking on AS/RS cranes and conveyors, "
|
| 153 |
+
"variable-frequency drives on motors that scale power to load, "
|
| 154 |
+
"and scheduling high-throughput operations to avoid peak "
|
| 155 |
+
"electricity tariff windows."
|
| 156 |
+
),
|
| 157 |
+
},
|
| 158 |
+
]
|
src/llm_client.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
llm_client.py
|
| 3 |
+
-------------
|
| 4 |
+
Wraps a hosted LLM (via huggingface_hub's InferenceClient, using HF's
|
| 5 |
+
serverless Inference Providers) to answer warehouse-operations questions,
|
| 6 |
+
grounded with context retrieved from the local knowledge base (simple RAG).
|
| 7 |
+
|
| 8 |
+
Design notes
|
| 9 |
+
------------
|
| 10 |
+
* Reads the HF token from the `HF_TOKEN` environment variable, which should
|
| 11 |
+
be added as a Space "secret" when deployed (Settings -> Variables and
|
| 12 |
+
secrets). The public demo also works without a token: it falls back to a
|
| 13 |
+
deterministic, still-useful extractive answer built from the retrieved
|
| 14 |
+
knowledge-base passages, so the Space never shows a broken demo.
|
| 15 |
+
* The model name is configurable via `LLM_MODEL_ID` (defaults to a small,
|
| 16 |
+
fast, freely-hostable instruct model).
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import os
|
| 20 |
+
import time
|
| 21 |
+
from dataclasses import dataclass
|
| 22 |
+
from typing import List
|
| 23 |
+
|
| 24 |
+
from src.retriever import KBRetriever, RetrievedDoc
|
| 25 |
+
|
| 26 |
+
DEFAULT_MODEL_ID = os.environ.get("LLM_MODEL_ID", "Qwen/Qwen2.5-7B-Instruct")
|
| 27 |
+
|
| 28 |
+
SYSTEM_PROMPT = (
|
| 29 |
+
"You are the Smart Warehouse AI Assistant, a helpful operations copilot "
|
| 30 |
+
"for a large automated distribution center (conveyors, AS/RS, AGVs/AMRs, "
|
| 31 |
+
"sortation, and a WMS). Answer concisely and practically, in the tone of "
|
| 32 |
+
"an experienced warehouse operations engineer. Use the provided CONTEXT "
|
| 33 |
+
"when relevant, and say so plainly if the question is outside the "
|
| 34 |
+
"context. Prefer short paragraphs or bullet points over long prose."
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@dataclass
|
| 39 |
+
class AssistantResponse:
|
| 40 |
+
answer: str
|
| 41 |
+
used_llm: bool
|
| 42 |
+
sources: List[RetrievedDoc]
|
| 43 |
+
latency_s: float
|
| 44 |
+
model_id: str
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def _extractive_fallback(query: str, sources: List[RetrievedDoc]) -> str:
|
| 48 |
+
"""Deterministic answer used when no HF token / API call fails, so the
|
| 49 |
+
Space always returns something useful instead of an error."""
|
| 50 |
+
if not sources:
|
| 51 |
+
return (
|
| 52 |
+
"I don't have grounded context for that yet. Try asking about "
|
| 53 |
+
"inventory, order status, equipment maintenance, AGV routing, "
|
| 54 |
+
"picking strategy, safety incidents, or general warehouse "
|
| 55 |
+
"automation concepts."
|
| 56 |
+
)
|
| 57 |
+
lead = sources[0]
|
| 58 |
+
bullets = "\n".join(f"- **{s.title}**: {s.text}" for s in sources)
|
| 59 |
+
return (
|
| 60 |
+
f"(Offline / no LLM API key configured -- showing retrieved "
|
| 61 |
+
f"knowledge instead of a generated answer.)\n\n"
|
| 62 |
+
f"Based on **{lead.title}**, here's the relevant information:\n\n{bullets}"
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def answer_query(
|
| 67 |
+
query: str,
|
| 68 |
+
retriever: KBRetriever,
|
| 69 |
+
k: int = 2,
|
| 70 |
+
model_id: str = DEFAULT_MODEL_ID,
|
| 71 |
+
max_tokens: int = 350,
|
| 72 |
+
) -> AssistantResponse:
|
| 73 |
+
start = time.time()
|
| 74 |
+
sources = retriever.retrieve(query, k=k)
|
| 75 |
+
context_block = "\n\n".join(f"[{s.title}]\n{s.text}" for s in sources)
|
| 76 |
+
|
| 77 |
+
hf_token = os.environ.get("HF_TOKEN")
|
| 78 |
+
|
| 79 |
+
if not hf_token:
|
| 80 |
+
answer = _extractive_fallback(query, sources)
|
| 81 |
+
return AssistantResponse(
|
| 82 |
+
answer=answer,
|
| 83 |
+
used_llm=False,
|
| 84 |
+
sources=sources,
|
| 85 |
+
latency_s=time.time() - start,
|
| 86 |
+
model_id="extractive-fallback",
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
try:
|
| 90 |
+
from huggingface_hub import InferenceClient
|
| 91 |
+
|
| 92 |
+
client = InferenceClient(model=model_id, token=hf_token)
|
| 93 |
+
messages = [
|
| 94 |
+
{"role": "system", "content": SYSTEM_PROMPT},
|
| 95 |
+
{
|
| 96 |
+
"role": "user",
|
| 97 |
+
"content": f"CONTEXT:\n{context_block}\n\nQUESTION: {query}",
|
| 98 |
+
},
|
| 99 |
+
]
|
| 100 |
+
completion = client.chat_completion(messages=messages, max_tokens=max_tokens, temperature=0.3)
|
| 101 |
+
text = completion.choices[0].message.content
|
| 102 |
+
return AssistantResponse(
|
| 103 |
+
answer=text,
|
| 104 |
+
used_llm=True,
|
| 105 |
+
sources=sources,
|
| 106 |
+
latency_s=time.time() - start,
|
| 107 |
+
model_id=model_id,
|
| 108 |
+
)
|
| 109 |
+
except Exception as e: # noqa: BLE001 -- deliberately broad: any API/network issue -> fallback
|
| 110 |
+
answer = _extractive_fallback(query, sources)
|
| 111 |
+
answer += f"\n\n_(LLM call failed: {type(e).__name__}. Showing retrieval-only answer.)_"
|
| 112 |
+
return AssistantResponse(
|
| 113 |
+
answer=answer,
|
| 114 |
+
used_llm=False,
|
| 115 |
+
sources=sources,
|
| 116 |
+
latency_s=time.time() - start,
|
| 117 |
+
model_id="extractive-fallback",
|
| 118 |
+
)
|
src/retriever.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
retriever.py
|
| 3 |
+
------------
|
| 4 |
+
Lightweight TF-IDF + cosine-similarity retriever used to ground the LLM's
|
| 5 |
+
answers in the warehouse knowledge base (simple RAG pipeline). Kept
|
| 6 |
+
dependency-light (scikit-learn only) so it trains instantly and runs fast
|
| 7 |
+
on the free CPU tier of Hugging Face Spaces.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
from dataclasses import dataclass
|
| 11 |
+
from typing import List
|
| 12 |
+
|
| 13 |
+
import joblib
|
| 14 |
+
import numpy as np
|
| 15 |
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
| 16 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
| 17 |
+
|
| 18 |
+
from src.knowledge_base import KNOWLEDGE_BASE
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
@dataclass
|
| 22 |
+
class RetrievedDoc:
|
| 23 |
+
id: str
|
| 24 |
+
title: str
|
| 25 |
+
text: str
|
| 26 |
+
score: float
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class KBRetriever:
|
| 30 |
+
def __init__(self):
|
| 31 |
+
self.vectorizer = TfidfVectorizer(stop_words="english", ngram_range=(1, 2))
|
| 32 |
+
self.doc_ids = [d["id"] for d in KNOWLEDGE_BASE]
|
| 33 |
+
self.docs = {d["id"]: d for d in KNOWLEDGE_BASE}
|
| 34 |
+
corpus = [d["title"] + ". " + d["text"] for d in KNOWLEDGE_BASE]
|
| 35 |
+
self.doc_matrix = self.vectorizer.fit_transform(corpus)
|
| 36 |
+
|
| 37 |
+
def retrieve(self, query: str, k: int = 2) -> List[RetrievedDoc]:
|
| 38 |
+
q_vec = self.vectorizer.transform([query])
|
| 39 |
+
sims = cosine_similarity(q_vec, self.doc_matrix).flatten()
|
| 40 |
+
top_idx = np.argsort(sims)[::-1][:k]
|
| 41 |
+
results = []
|
| 42 |
+
for idx in top_idx:
|
| 43 |
+
doc_id = self.doc_ids[idx]
|
| 44 |
+
d = self.docs[doc_id]
|
| 45 |
+
results.append(RetrievedDoc(id=doc_id, title=d["title"], text=d["text"], score=float(sims[idx])))
|
| 46 |
+
return results
|
| 47 |
+
|
| 48 |
+
def save(self, path: str):
|
| 49 |
+
joblib.dump(self.vectorizer, path)
|
| 50 |
+
|
| 51 |
+
@staticmethod
|
| 52 |
+
def top1_id(query: str, retriever: "KBRetriever") -> str:
|
| 53 |
+
return retriever.retrieve(query, k=1)[0].id
|