Metadata-Version: 2.4
Name: eagle-embodied
Version: 0.1.0
Summary: A lightweight local API bridge for NVIDIA NVLabs Eagle Embodied VLM
Author: eagle-embodied contributors
License-Expression: MIT
Project-URL: Official Eagle repository, https://github.com/NVlabs/Eagle
Project-URL: Official Embodied documentation, https://github.com/NVlabs/Eagle/tree/main/Embodied
Keywords: computer-vision,eagle,embodied-ai,locateanything,nvidia,vision-language-model,vlm
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: THIRD_PARTY_NOTICES.md
Requires-Dist: Pillow>=10.0
Requires-Dist: tqdm>=4.65
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Requires-Dist: types-tqdm>=4.65; extra == "dev"
Dynamic: license-file

# eagle-embodied

`eagle-embodied` is an independent, lightweight Python API bridge for running
the official NVIDIA NVLabs Eagle Embodied VLM from local image paths. It turns
the official worker workflow into a small path-based API with batch execution,
progress reporting, per-image failure isolation, and JSON/text result export.

> **NVIDIA copyright and license notice — read before use:** Eagle,
> LocateAnything, the official Eagle source code, and the official weights are
> NVIDIA works. **Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.**
> This package contains none of those works. The current official Embodied
> model is licensed separately under the NVIDIA License for non-commercial
> research or evaluation use. Review the complete official terms before
> downloading or using it.

This project is not a fork or derivative distribution of Eagle. It does not
copy, vendor, modify, download, or redistribute Eagle source code, internal
modules, model architecture code, pretrained weights, NVIDIA assets, or
datasets. At runtime it imports the public worker class from the user's own
official Eagle checkout and invokes that worker's public inference method.
Users must independently obtain and install all NVIDIA materials.

This project is not affiliated with, sponsored by, endorsed by, or maintained
by NVIDIA. “Eagle,” “NVLabs,” “LocateAnything,” and “NVIDIA” remain the property
of their respective owners.

## Features

- Three-line local image inference API
- A single image path, a folder path, or an explicit list of image paths
- Configurable threaded parallelism with one official model worker per thread
- Automatic use of the latest official `predict_batch` runtime when enabled
- Progress bars for folder and list batches
- Corrupted/unreadable image skipping with warning logs and failure records
- Atomic `.json` and `.txt` output
- Typed result objects with success/failure counts
- Clear errors for paths, formats, official environment, weights, and GPU OOM
- No Torch, Transformers, Eagle source, or model weights in this distribution

## Requirements

- Python 3.10 or newer
- Pillow and tqdm (installed with this wrapper)
- A separately cloned, official
  [NVLabs/Eagle](https://github.com/NVlabs/Eagle) checkout
- A separately downloaded official Embodied checkpoint
- All dependencies required by the official Eagle Embodied environment
- Hardware supported by the selected official checkpoint; CUDA is normally
  expected for practical inference

The wrapper itself is small. The official Eagle environment controls its own
CUDA, PyTorch, Transformers, and model-specific dependency versions.

## Install the official environment first

The upstream `Embodied` directory currently documents the public
`LocateAnythingWorker` API. Follow the official instructions in the official
environment where you plan to use this wrapper:

```bash
git clone https://github.com/NVlabs/Eagle.git
cd Eagle/Embodied
python -m pip install -e .
```

Download the official weights yourself. The current upstream example uses:

```bash
hf download nvidia/LocateAnything-3B \
  --local-dir /absolute/path/to/LocateAnything-3B
```

Do not treat these commands as a grant of rights. Before downloading, read:

- [Official Eagle repository license and terms](https://github.com/NVlabs/Eagle#licenseterms-of-use)
- [Official repository Apache 2.0 license](https://github.com/NVlabs/Eagle/blob/main/LICENSE)
- [Official Embodied model license](https://github.com/NVlabs/Eagle/blob/main/Embodied/LICENSE_MODEL)
- Any file-level, dependency, and checkpoint-specific notices in your checkout

The upstream repository states that its repository code is under Apache 2.0,
with reused portions subject to their original licenses and notices. The
current `Embodied/LICENSE_MODEL` is a separate NVIDIA License that, among other
conditions, limits use of the official model and derivative works to
non-commercial research or evaluation, requires notices when redistributing
NVIDIA work, does not generally grant trademark rights, and disclaims warranty.
That is a convenience summary only; the official license text controls.

## Install this wrapper

From PyPI:

```bash
python -m pip install eagle-embodied
```

For local development:

```bash
git clone <this-wrapper-repository>
cd eagle-embodied
python -m pip install -e ".[dev]"
```

`requirements.txt` intentionally contains only the wrapper's lightweight
dependencies. Installing this package will never fetch Eagle or its weights.

## Single image inference

```python
from eagle_embodied import EagleEmbodied

model = EagleEmbodied(
    weights_path="/models/LocateAnything-3B",
    eagle_path="/repos/Eagle/Embodied",
)

result = model.infer("/data/kitchen.jpg", "Point to: the red cup.")
print(result.answer)
```

The model loads lazily on the first inference call. `eagle_path` may point to
either the official repository root or its `Embodied` directory. It may be
omitted when the official editable installation already makes
`locateanything_worker` importable.

Save one result as JSON or plain text:

```python
result = model.infer(
    "/data/kitchen.jpg",
    "Locate all the instances that match the following description: cup.",
    output_path="/results/kitchen.json",
    generation_mode="hybrid",
    max_new_tokens=512,
)
```

Extra keyword arguments are forwarded unchanged to the official worker's
public `predict` method. Consult the matching official checkout for supported
generation options.

## Batch a folder in parallel and save JSON

```python
batch = model.infer_batch(
    "/data/robot_frames",
    "Point to: the door handle.",
    workers=2,
    progress=True,
    recursive=False,
    output_path="/results/door_handles.json",
)

print(f"{batch.succeeded}/{batch.total} images succeeded")
for failure in batch.failures:
    print(f"Skipped {failure.image_path}: {failure.message}")
```

Batch input may also be an explicit list:

```python
batch = model.infer_batch(
    ["frame_001.jpg", "frame_002.png", "frame_003.webp"],
    "Detect all the text in box format.",
    workers=3,
    output_path="text_boxes.txt",
)
```

Supported extensions are `.bmp`, `.jpeg`, `.jpg`, `.png`, `.tif`, `.tiff`,
and `.webp`. Folder discovery ignores other file types. Explicit unsupported
files produce an `UnsupportedImageFormatError` (or a captured batch failure).

### Parallel memory behavior

Parallel mode creates one official model instance per worker thread so that
inference calls can run concurrently. This can multiply CPU/GPU memory use.
Start with `workers=1`, especially for large GPU checkpoints, and increase only
after measuring available memory. The wrapper warns when parallel workers may
exhaust a CUDA device. The official worker's optional runtime can be configured
without being bundled here:

```python
model = EagleEmbodied(
    weights_path="/models/LocateAnything-3B",
    eagle_path="/repos/Eagle/Embodied",
    worker_options={
        "use_batch_runtime": True,
        "attn": "la_flash",
        "scheduler": "pipeline",
    },
)

batch = model.infer_batch(
    "/data/robot_frames",
    "Point to: the door handle.",
    workers=1,
    batch_size=4,
    output_path="/results/native_batch.json",
)
```

The official batch runtime has additional files and hardware requirements; see
the upstream Embodied README. When `worker_options["use_batch_runtime"]` is
true, this wrapper automatically calls the current official `predict_batch`
API and lets NVIDIA's hybrid scheduler manage GPU parallelism. Use `workers=1`;
`batch_size` controls how many image/prompt requests are submitted per official
call. Set `native_batch=False` explicitly to use wrapper-managed per-image
execution instead.

The integration defaults were verified against the latest official NVLabs
Eagle `main` Embodied revision available on August 12, 2026
([`bb860a7`](https://github.com/NVlabs/Eagle/commit/bb860a7efa22bb40cd4bb77959512375b92db934)),
including
`LocateAnythingWorker.predict`, `LocateAnythingWorker.predict_batch`, and the
optional Hugging Face `la_flash` batch runtime. NVIDIA may update the upstream
interface independently, so keep the official checkout and its matching
checkpoint/runtime files on compatible revisions.

That latest upstream revision also adds visual-prompt fine-tuning support, but
the official README warns that the currently released
`nvidia/LocateAnything-3B` weights do not support visual-prompt inference out
of the box. This wrapper therefore does not imply that capability for the
public checkpoint; follow future official checkpoint notices.

## Logging and corrupted files

Batch mode continues after per-image errors by default and emits warning logs:

```python
import logging

logging.basicConfig(level=logging.INFO)
```

Each skipped file appears in `batch.failures`, and JSON output preserves those
failure records. Pass `strict=True` to stop on the first failing image.

## Error handling

All expected wrapper exceptions inherit from `EagleEmbodiedError`:

```python
from eagle_embodied import (
    EagleEmbodiedError,
    EagleEnvironmentError,
    GPUOutOfMemoryError,
    WeightsNotFoundError,
)

try:
    model = EagleEmbodied(
        weights_path="/models/LocateAnything-3B",
        eagle_path="/repos/Eagle/Embodied",
    )
    result = model.infer("frame.jpg", "Point to: the target.")
except WeightsNotFoundError as exc:
    print(f"Download the official weights first: {exc}")
except EagleEnvironmentError as exc:
    print(f"Install the official Eagle environment first: {exc}")
except GPUOutOfMemoryError as exc:
    print(f"Reduce workers or change device: {exc}")
except EagleEmbodiedError as exc:
    print(f"Inference failed: {exc}")
```

Handled cases include:

- missing/non-file image paths
- unsupported image extensions
- corrupted or unreadable images
- an empty list or folder with no supported images
- missing official Eagle checkout/module/dependencies
- missing local weights
- official worker initialization/inference failures
- CUDA/MPS out-of-memory errors with recovery guidance
- invalid or unwritable result paths

## Alternate official worker layouts

The defaults match the current official Embodied public API:

```text
module: locateanything_worker
class:  LocateAnythingWorker
method: predict(image, prompt, **options)
batch:  predict_batch([(image, prompt), ...], **options)
```

If an official Eagle revision exposes a different public worker, the import
names can be configured without adding any official implementation here:

```python
model = EagleEmbodied(
    weights_path="/local/official/weights",
    eagle_path="/local/official/Eagle/Embodied",
    worker_module="official_public_worker",
    worker_class="OfficialWorker",
    inference_method="predict",
)
```

Only configure documented public interfaces from your official checkout.

## Demo

[`examples/demo.py`](examples/demo.py) runs all three requested workflows:
single-image inference, parallel folder inference, and JSON export.

```bash
python examples/demo.py \
  --eagle-path /repos/Eagle/Embodied \
  --weights-path /models/LocateAnything-3B \
  --single-image /data/example.jpg \
  --image-folder /data/robot_frames \
  --output-json /results/eagle_results.json \
  --workers 2
```

## Package contents

```text
eagle-embodied/
├── eagle_embodied/
│   ├── __init__.py
│   ├── _images.py
│   ├── _official.py
│   ├── _output.py
│   ├── core.py
│   ├── errors.py
│   ├── models.py
│   └── py.typed
├── examples/
│   └── demo.py
├── tests/
├── LICENSE
├── MANIFEST.in
├── README.md
├── THIRD_PARTY_NOTICES.md
├── pyproject.toml
├── requirements.txt
└── setup.py
```

## Development and release checks

```bash
python -m pytest
ruff check .
mypy eagle_embodied
python -m build
python -m twine check dist/*
```

## Wrapper license and upstream rights

The original wrapper code in this package is released under the MIT License.
That license applies only to this separate abstraction layer. It grants no
rights in Eagle, LocateAnything, NVIDIA model weights, NVIDIA names or marks,
or any other upstream material.

See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for the preserved NVIDIA
notice and license summary. Always rely on the official NVIDIA files for the
complete, controlling terms.
