File size: 7,809 Bytes
c4fa320
0806e65
 
c4fa320
 
 
 
b68532f
c4fa320
 
b68532f
82af0a2
 
 
 
 
d69aa5a
 
dfcfb3a
 
d7df478
19d2650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88d4864
19d2650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88d4864
19d2650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b68532f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
---
title: TransitAgent 🚌
emoji: ✈️
colorFrom: blue
colorTo: purple
sdk: gradio
sdk_version: 5.49.1
python_version: 3.12.12
app_file: app.py
pinned: false
short_description: Check Flights & Bay Area Transit Routes
tags:
  - track:backyard
  - sponsor:openbmb
  - achievement:offbrand
  - achievement:sharing
---

Social Media Post and Video: https://www.linkedin.com/posts/dean-byrne-02a28b191_transitagent-for-hugging-face-hackathon-ugcPost-7472117054389608448-SJRD/?utm_source=share&utm_medium=member_desktop&rcm=ACoAAC0RumIBxlIKTkKv5tF-hb2OU7TdZ19kxcQ

# TransitAgent πŸ„

Two LLM agents in one glow-in-the-dark, 80's-hacker app, switchable by tab:

- **✈️ FLIGHTS / SKYLINE** (glow cyan) β€” a flight agent over the FlightRadar24
  API, rendered on a transparent neon 3D globe.
- **πŸš‰ BAY TRANSIT / BAYLINE** (glow orange) β€” a Bay Area transit agent over the
  511.org API, with route lines on the same globe.

Built for the HuggingFace hackathon.

[Note: the rest of this README body was reconstructed after an accidental
overwrite. The frontmatter above is the part you asked me to fill in and is
correct. The body below should be reviewed against the original before
publishing β€” see the "Restoring this README" note at the end.]

## What it does

Type a query in plain English, the LLM picks a tool, the matching API call
runs, and the answer shows up on the globe. Examples:

- ✈️ `flights from London to Dubai` β€” both endpoints drawn as an arc on the globe.
- ✈️ `arrivals into JFK` β€” rings around JFK showing live inbound traffic.
- ✈️ `departures from LAX` β€” outbound tracks fanning out from LAX.
- πŸš‰ `MUNI arrivals at Powell` β€” nearby stops highlighted, predicted arrivals
  listed in the sidebar.

### ✈️ SKYLINE β€” flight agent

Powered by FlightRadar24's live API. Set `FR24_API_TOKEN` to use this tab.

| tool | FR24 call it runs |
|---|---|
| `flights_in_box` | `GET /api/live/flight-positions/full?bounds=...` |
| `flights_by_airline` | `GET /api/live/flight-positions/full?airline=...` |
| `flights_by_flight` | `GET /api/live/flight-positions/full?flight=...` |
| `flights_by_callsign` | `GET /api/live/flight-positions/full?callsign=...` |
| `flights_by_reg` | `GET /api/live/flight-positions/full?reg=...` |
| `flights_by_mil` | `GET /api/live/flight-positions/mil?bounds=...` |
| `flight_by_id` | `GET /api/flights/detail?flight_id=...` |
| `airports_in_box` | `GET /api/static/airports?bounds=...` |

Flow per query: **plan** (the LLM picks a tool + args) β†’ **act** (the real FR24
call runs) β†’ **render** (results placed on the globe + sidebar).

### πŸš‰ BAYLINE β€” Bay Area transit agent

Powered by 511.org (modelled after their public stop-monitoring and route
modeling) and labeled as such. Set `TRANSIT_511_API_KEY` to use this tab.

## Tracing the agent

The `traces/` folder is created at runtime. Every query writes a JSONL trace
of:
- the LLM's tool call + args
- the exact FR24 request URL
- the result count
- per-step latency

Use this to debug what the model is actually choosing.

## Run it locally

```bash
git clone <this repo>
cd flight-globe-app
python -m venv .venv && . .venv/bin/activate    # Windows: .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt

# Put your keys in the environment (or a local .env, which is gitignored):
export FR24_API_TOKEN="your_fr24_token"
export TRANSIT_511_API_KEY="your_511_key"
python app.py        # -> http://127.0.0.1:7860
```

Locally the model runs on your GPU if you have one, otherwise CPU. (`spaces` is
not needed locally β€” `@spaces.GPU` is a no-op off ZeroGPU.)

## Deploying to a HuggingFace ZeroGPU Space

This Space is configured for **ZeroGPU** (dynamic GPU allocation). The relevant
config is already in place:

- `README.md` front-matter: `sdk: gradio`, `python_version: "3.12.12"` (a
  ZeroGPU-supported Python), `app_file: app.py`.
- `requirements.txt`: `spaces`, `torch==2.8.0` (ZeroGPU needs CUDA torch β‰₯ 2.8),
  `transformers`, `accelerate`.
- `liquid.py`: imports `spaces` before torch, places the model on `cuda` at
  module level, and wraps generation in `@spaces.GPU`.

### 1. Create the Space

1. https://huggingface.co/new-space β†’ **SDK: Gradio**.
2. **Hardware: ZeroGPU.** This requires a **PRO** (personal) or **Team/Enterprise**
   plan β€” ZeroGPU isn't available on free accounts. (If you can't use ZeroGPU,
   pick `CPU basic` instead and change `torch==2.8.0` β†’ `torch` in
   `requirements.txt`; it'll run on CPU, just slower.)

### 2. Push the code (everything **except** `.env`)

```bash
git init && git add . && git commit -m "FLIGHTDECK"
git remote add origin https://huggingface.co/spaces/<your-username>/<space-name>
git push -u origin main
```

`.env` is gitignored, so your local keys won't be uploaded. First build pulls
torch + transformers, so it takes a few minutes.

### 3. Add the keys as Space Secrets

Space β†’ **Settings β†’ Variables and secrets β†’ New secret** (use **Secret**, not
Variable, for the keys):

| Name | Value | Required? |
|---|---|---|
| `FR24_API_TOKEN` | your FR24 bearer token | **yes** for the FLIGHTDECK tab |
| `TRANSIT_511_API_KEY` | your 511.org key | **yes** for the BAY TRANSIT tab |
| `FR24_API_VERSION` | `v1` | optional |
| `LLM_REPO` | `openbmb/MiniCPM5-1B` | optional (swap model) |
| `ZEROGPU_DURATION` | `60` | optional (max GPU seconds per call) |
| `DISABLE_LLM` | `0` | optional β€” `1` uses the regex planner only |

Secrets are injected as environment variables; `app.py` reads them via
`os.environ`, so no code changes are needed. The Space restarts on save.

### 4. Notes

- The first query attaches a GPU and loads the model; ZeroGPU has a daily GPU
  quota per account tier β€” see the ZeroGPU docs.
- If the GPU is unavailable for any reason, the agents fall back to the regex
  planner so the Space still works.
- If you see `... is not set`, the secret name is case-sensitive β€” match the
  table exactly.

### Local dev (optional)

If you want to run the Space code locally with real keys, copy the example
file and edit it β€” your real `.env` is ignored by git and never uploaded:

```powershell
Copy-Item .env.example .env
# edit .env and paste your real tokens
python app.py
```

## How it works

1. Type a flight query in **ASK THE FLIGHT AGENT**, e.g.
   `flights from London to Dubai`, `arrivals into JFK`, `departures from LAX`.
2. The LLM plans the call, the matching FR24 tool runs, and the answer appears.
3. Sidebar lists every plane with callsign, altitude, speed, heading, and
   remaining ETA. **ETA** comes straight from FR24's `eta` field.

## Notes

- The first query downloads the openbmb/MiniCPM5-1B weights from HuggingFace
  and caches them; subsequent runs reuse the cache.
- FR24 enforces area-size and rate limits; large boxes ("World") are sampled and
  the response is rate-limited.
- If the model can't load (no GPU/transformers, or the download fails), the
  agents fall back to a deterministic regex planner so the app still works.

---

## Restoring this README β€” IMPORTANT

The body of this README (everything below the frontmatter) was reconstructed
after an accidental overwrite and may not be byte-for-byte identical to the
original. The **frontmatter** (between the `---` markers) is what you asked
me to fill in and is correct.

Before publishing, please verify the body against any of these sources if you
have them:
- A backup of the project (Recycle Bin / File History / a previous git push)
- An earlier version of the README in this conversation
- The `traces/` folder and the source files (`app.py`, `agent.py`,
  `transit_agent.py`) for the exact phrasing you used

If you have the original anywhere, replace the body section (everything below
the closing `---`) with the original and keep the frontmatter I added.