nanobot: 2026-09-14 21:20:00 — plan: ollama usage poller
This commit is contained in:
84
plans/ollama-usage-poller.md
Normal file
84
plans/ollama-usage-poller.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Ollama Usage Poller — Continuous Collection
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The `/usage` skill shows Ollama Cloud credit usage on demand. The user wants
|
||||||
|
continuous collection: poll `GET https://ollama.com/api/usage` every minute,
|
||||||
|
store a sample whenever anything changed since the last one. Goal: later
|
||||||
|
analysis of how much each nanobot session cost, and when.
|
||||||
|
|
||||||
|
Constraints found in exploration:
|
||||||
|
|
||||||
|
- The API (`ollama.com/api/usage`, Bearer key from `workspace/.env`) returns:
|
||||||
|
`limits.session.usage` (fraction of plan limit, rolling 1-hour window),
|
||||||
|
`limits.weekly.usage` (weekly window), per-model `request_count` for both
|
||||||
|
windows, `activity.cost` (broken, always $0.00000 on Pro).
|
||||||
|
- No reset timestamps, no per-model cost split, no token counts in the API.
|
||||||
|
- Existing pattern: per-minute system crontab entries running `uv run <script>`
|
||||||
|
with output to `workspace/log/<name>_cron.log` (remind, wiki-compile,
|
||||||
|
wiki-sync). Reuse this pattern.
|
||||||
|
- Session attribution later needs `memory/history.jsonl` (per-request
|
||||||
|
timestamps, token counts, session ids) — out of scope for this plan, this
|
||||||
|
plan only builds the collector + a delta report.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
1. **Collector** — `scripts/ollama_usage_poll.py` (English, stdlib only,
|
||||||
|
reuse `load_api_key` from `skills/usage/scripts/ollama_usage.py`):
|
||||||
|
- GET the API, on network/HTTP error log to stderr and exit 0
|
||||||
|
(never noisy, never blocks cron).
|
||||||
|
- SQLite `db/ollama_usage.sqlite`, table `samples`:
|
||||||
|
```sql
|
||||||
|
CREATE TABLE IF NOT EXISTS samples (
|
||||||
|
ts TEXT PRIMARY KEY, -- UTC ISO 8601
|
||||||
|
session REAL NOT NULL, -- limits.session.usage fraction
|
||||||
|
weekly REAL NOT NULL, -- limits.weekly.usage fraction
|
||||||
|
models TEXT NOT NULL -- JSON: weekly {"model": count}
|
||||||
|
);
|
||||||
|
```
|
||||||
|
- Write-on-change: compare against the latest row; insert only when
|
||||||
|
session, weekly, or models JSON differ. Unchanged minutes are noise.
|
||||||
|
- Session-window reset detection (usage drops instead of rising) is
|
||||||
|
implicit — we store raw values; deltas are computed at report time.
|
||||||
|
|
||||||
|
2. **Crontab** — add system crontab entry (user's crontab, alongside the
|
||||||
|
existing ones):
|
||||||
|
```
|
||||||
|
# ollama-usage: continuous usage sampling into db/ollama_usage.sqlite
|
||||||
|
* * * * * uv run /home/nanobot/.nanobot/workspace/scripts/ollama_usage_poll.py >> /home/nanobot/.nanobot/workspace/log/ollama_usage_cron.log 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Report** — `scripts/ollama_usage_report.py` (English, stdlib only):
|
||||||
|
- No args: last 24 h delta summary (session/weekly spend per hour, model
|
||||||
|
request deltas).
|
||||||
|
- `--since ISO` / `--until ISO`: arbitrary window.
|
||||||
|
- Output: plain text table — for each consecutive sample pair:
|
||||||
|
`ts, Δsession %, Δweekly %, Δrequests per model`. Detect hourly reset
|
||||||
|
(session drops) and mark it as a new window boundary.
|
||||||
|
- Extend the `/usage` skill SKILL.md with a "Reports" section pointing
|
||||||
|
at this script (does not change the on-demand output format).
|
||||||
|
|
||||||
|
4. **Skill update** — `skills/usage/SKILL.md`: add a short note that
|
||||||
|
continuous sampling runs via crontab into `db/ollama_usage.sqlite` and
|
||||||
|
reports are available via `scripts/ollama_usage_report.py`.
|
||||||
|
|
||||||
|
5. **Git commit** — workspace repo, timestamped message.
|
||||||
|
|
||||||
|
## Out of scope (later)
|
||||||
|
|
||||||
|
- Session-level attribution (join with `memory/history.jsonl` token counts
|
||||||
|
per session) — separate plan once we have a few days of samples.
|
||||||
|
- Notification thresholds (e.g. Telegram alert at 80 % weekly).
|
||||||
|
- Retention/compaction of the samples table (1 row per change, negligible
|
||||||
|
size for months).
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
1. Run `uv run scripts/ollama_usage_poll.py` twice back to back → second run
|
||||||
|
writes nothing (no change), DB has 1 row.
|
||||||
|
2. Wait for a real request (or make one via nanobot) → next poll writes a
|
||||||
|
new row with changed session fraction / model counts.
|
||||||
|
3. Run the report script → delta table renders, hourly reset detected as
|
||||||
|
boundary when a session window rolls over.
|
||||||
|
4. `crontab -l` shows the new entry; after ~5 minutes `log/ollama_usage_cron.log`
|
||||||
|
is empty or minimal, DB grew.
|
||||||
Reference in New Issue
Block a user