foreman

foreman

Enables agents to query warehouse safety review results, including verified alerts, semantic timeline search, and audit logs of rejected detections.

Category
访问服务器

README

Foreman

Agentic vision AI for warehouse safety review, built on NVIDIA NIM.

Point it at warehouse footage and it returns a short queue of verified safety alerts, each one carrying the evidence it was confirmed on and the standard it maps to, plus a searchable index of everything else it saw. It runs on NVIDIA-hosted NIM endpoints, so it reproduces on a laptop with an API key and no GPU.

Live demo · analysis of a real run, no setup required. Evidence clips are local-only there, for the licensing reason in DATA.md.

Foreman review console: alert queue, evidence chain, search, and audit

The review console: verified alerts with the evidence each was confirmed on, natural language search across every window, and an audit view of everything suppressed.


The problem this is actually solving

Ask a vision language model "is there a safety hazard in this footage" and it will almost always say yes. On the labelled set in this repo, a single-pass VLM flags a hazard in 77% of windows that contain none. That is not a system a safety supervisor will use twice, and no amount of prompt rewriting fixes it, because the prompt is not the problem. Showing a model a safety camera and asking about hazards hands it an overwhelming prior that hazards are present.

Foreman treats that as an architecture problem rather than a wording problem. The perception pass is allowed to over-report, and a second model that can only remove things re-opens the same frames and decides whether the evidence actually meets the bar for the class that was claimed.

Measured on 49 hand-labelled windows:

arm precision recall F1 windows falsely alerting
vlm_only — every candidate becomes an alert 0.15 0.80 0.25 30/39 (77%)
vlm_conf_80 — keep candidates above 0.80 confidence 0.18 0.80 0.30 28/39 (72%)
llm_verifier — reasoning LLM reviews the perception text 0.14 0.30 0.19 12/39 (31%)
vlm_verifier — reasoning VLM re-opens the frames 0.35 0.60 0.44 10/39 (26%)

Over three repeats the verifier arm runs P=0.34 [0.31–0.38], R=0.50 [0.40–0.60], F1=0.40 [0.36–0.46]. Precision roughly doubles; recall pays for it. Full numbers, including a per-class false-positive breakdown, are in evals/RESULTS.md. Reproduce with python evals/run_eval.py.

Three findings worth more than the headline number

1. Confidence thresholds barely work. Going from every candidate to only those the model rated 0.80+ moved precision 0.15 → 0.18. A VLM's self-reported confidence is close to useless as a filter here: it is confident about the things it is wrong about.

2. Text-only verification is worse than no verification. The llm_verifier arm reads the perception pass's written evidence and adjudicates on that. It collapses to F1 0.19 — below the naive baseline. The written evidence is too thin to clear the bar the verifier is applying, so it rejects nearly everything, real hazards included. The verifier has to look at the pixels. This one surprised me and it is the reason the architecture has a VLM in the second position rather than a cheaper LLM.

3. VLMs read on-screen text as though it were the world. The first window of the first video is a title card: black screen, white words, "PASSING IN FRONT OF A FORKLIFT". The perception model reported a pedestrian walking in front of a moving forklift at 0.95 confidence. The verifier confirmed it as high severity. Both models had turned printed words into an observed event.

Real deployments are full of this — burned-in timestamps, camera labels, training overlays. The fix is a scene gate: the perception pass declares whether it is looking at real camera footage at all, in the same call, at no extra cost. It removes an entire class of confident nonsense and is worth +0.07 precision on top of the verifier (vlm_verifier 0.35 vs vlm_verifier_nogate 0.28).

What was filtered

Every suppressed detection stays visible and auditable. A safety tool that cannot show what it threw away is one nobody should trust.


Architecture

flowchart LR
    A[video] --> B[chunker<br/>8s windows, 4 frames]
    B --> C[perception<br/>Nemotron Nano VL 12B]
    C -->|is_camera_footage=false| X[gated: slides,<br/>title cards, presenters]
    C -->|hazard candidates| D[verifier<br/>Nemotron Nano Omni 30B<br/>re-opens the frames]
    D -->|rejected + reason| X
    D -->|confirmed| E[alert queue<br/>+ evidence clip]
    C --> F[embeddings<br/>Llama Nemotron Embed VL]
    F --> G[semantic search<br/>over every window]
    E --> H[MCP server]
    G --> H
    H --> I[Claude Code /<br/>any agent]
stage model why this one
perception nvidia/nemotron-nano-12b-v2-vl smallest model that reliably holds the JSON contract across every chunk; ~2s per window
verification nvidia/nemotron-3-nano-omni-30b-a3b-reasoning reasoning VLM, different family and size from the proposer, so a confirmation is a genuine second look rather than a model agreeing with itself
search nvidia/llama-nemotron-embed-vl-1b-v2 vision-language retriever, so queries land in the space the perception pass described

On Cosmos. nvidia/cosmos-reason2-8b is the natural perception model here — Cosmos Reason is post-trained for physical-world spatial and temporal reasoning rather than generic captioning, which is exactly the axis a hazard call turns on. It is not provisioned on the free build.nvidia.com tier (account-scoped 404 as of Aug 2026), so this runs on Nemotron VL. VLM_PRIMARY in src/foreman/nim.py is one line; swap it on a self-hosted NIM and the eval harness will report the comparison honestly instead of my asserting it.

Design decisions I would defend in review

8-second windows, 4 sampled frames. Shorter and the model cannot see motion, so a pedestrian standing still and a pedestrian walking into a travel path look identical. Longer and an alert cannot be localised to a moment a reviewer can act on.

The taxonomy is upstream of the model. hazards.py defines five classes from OSHA 29 CFR 1910.178 and the struck-by categories that dominate warehouse injury data — chosen from what an inspector needs, not from what a VLM happens to describe well. The perception prompt, the verifier's reject criteria, the label schema and the UI filters all read from that one definition, so a class cannot drift between the model proposing it and the harness grading it.

The proposer and the adjudicator get different information. The verifier sees each class's known false positive; the perception pass does not. Telling the proposer what not to say suppresses real detections along with phantom ones. Telling the adjudicator what to watch for raises precision without touching recall.

Tools are shaped like questions, not like the call graph. mcp_server.py exposes search_timeline, list_alerts, explain_alert, list_rejected_detections, shift_summary, hazard_taxonomy — the questions a supervisor actually asks. Agent surfaces that mirror internal module boundaries are how they become unusable.


Quickstart

git clone https://github.com/YashNirwan/foreman && cd foreman
python3 -m venv .venv && ./.venv/bin/pip install -e .
cp .env.example .env      # add a free key from https://build.nvidia.com

python scripts/fetch_data.py                          # pull sample footage locally
./.venv/bin/python -m foreman.pipeline data/raw_yt/MqvOjo62BHQ.mp4
./.venv/bin/streamlit run app.py                      # review console

Requires ffmpeg and yt-dlp on PATH (brew install ffmpeg yt-dlp).

A 172-second video: 21 windows, 26 candidates, 11 confirmed alerts, 98 seconds wall clock on a laptop against the free tier, 47 NIM calls.

Drive it from an agent

claude mcp add foreman -- /abs/path/to/foreman/.venv/bin/python -m foreman.mcp_server

Then ask in plain language: "what were the high-severity alerts in that shift, and show me what the verifier threw out."

Reproduce the eval

python evals/run_eval.py --perceive   # perception + all 7 arms
python evals/variance.py --repeats 3  # run-to-run spread on the headline arms

What this is not

Honest limits, because a work sample that oversells is worse than one that is small:

  • The eval is small. 49 windows, 10 positive events, one annotator (me). Class balance is skewed — 7 of 10 positives are pedestrian_in_path, and blocked_egress has no positive examples at all, so its numbers mean nothing yet. Treat the precision figures as a directional result on one labelled set, not a benchmark.
  • Recall drops meaningfully. 0.80 → 0.50. On a real floor you would tune the verifier's bar per class, and you would almost certainly accept lower precision on pedestrian_in_path than on missing_ppe, because the cost of missing them differs.
  • Labels are judgement calls. The guideline is written at the top of ground_truth.json's generator and ambiguous windows are labelled negative. A second annotator would move these numbers.
  • Sampled frames are not video. Four frames across eight seconds miss fast events. The production answer is a CV pipeline (DeepStream, or the tracking stage in the Metropolis VSS blueprint) triggering VLM review on clips it has already localised, rather than a VLM scanning uniformly.
  • No post-training. Everything here is prompted and orchestrated, not fine-tuned. The obvious next step is distilling the verifier's confirmed/rejected decisions into a small VLM and checking whether it holds precision at a fraction of the cost.
  • Not a substitute for a trained safety professional, and the eval footage is training material rather than live operational CCTV.

Where this goes at scale

The shape here is deliberately the shape of NVIDIA's VSS blueprint: ingest, VLM perception, retrieval over descriptions, verified alerts. Foreman is the laptop-scale version, and each stage has a real replacement — flat numpy index → a vector DB, uniform sampling → DeepStream-triggered clips, hosted NIM → self-hosted NIM containers, single video → multi-stream. What survives the swap is the part I would argue matters most and that the blueprint leaves to you: the verification stage and the eval harness that proves it earns its place.

Data and licensing

Code is MIT. No video is redistributed in this repo. The eval ships as labels and derived model output keyed on chunk ids; scripts/fetch_data.py rebuilds the local footage from public sources for analysis. See DATA.md.


Built by Yash Nirwan · github.com/YashNirwan

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选