lucas-vitrus commited on
Commit
acd4c85
·
verified ·
1 Parent(s): a09e26f

Publish Liquid Crow model card and examples

Browse files
README.md CHANGED
@@ -1,19 +1,97 @@
1
  ---
 
 
 
2
  license: apache-2.0
3
  tags:
4
  - vitrus
5
- - vision
6
- - world-description
 
 
7
  - gguf
 
8
  ---
9
 
10
- # Vitrus World Descriptor
11
 
12
- A compact vision model package for describing the visible world from a camera frame.
13
 
14
- ## Files
15
 
16
- - `vitrus-world-descriptor-q4_k_m.gguf` language model
17
- - `vitrus-world-descriptor-vision-f16.gguf` — vision encoder and projector
18
 
19
- Both files are required for visual inference.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ base_model: LiquidAI/LFM2.5-VL-450M-Extract
3
+ library_name: transformers
4
+ pipeline_tag: image-text-to-text
5
  license: apache-2.0
6
  tags:
7
  - vitrus
8
+ - vision-language-model
9
+ - multimodal
10
+ - lora
11
+ - onnx
12
  - gguf
13
+ - world-model
14
  ---
15
 
16
+ # Liquid Crow
17
 
18
+ [![Liquid Crow by Vitrus](media/liquid-crow-cover.png)](https://www.vitrus.com/news/micro-world-models-1)
19
 
20
+ **A small brain. Intelligent. Always observing.**
21
 
22
+ Liquid Crow is a compact visual brain designed to stay close to the world it watches: small enough to live beside physical agents, intelligent enough to turn a camera frame into useful context, and always observing so the system can understand what changes next.
 
23
 
24
+ [Live camera demo](https://www.vitrus.com/demos/micro-world-model) · [Research note](https://www.vitrus.com/news/micro-world-models-1) · [Vitrus](https://www.vitrus.com)
25
+
26
+ ## System
27
+
28
+ ```text
29
+ camera frame → image processor → vision projector → compact VLM → world description
30
+
31
+ LoRA · ONNX · ONNX Q4 · GGUF
32
+ ```
33
+
34
+ This repository is the single public release point for Liquid Crow: the model adapter, deployment formats, processor configuration, integrity manifests, code examples, and media.
35
+
36
+ ## Example
37
+
38
+ <video src="media/liquid-crow-demo.mp4" controls width="100%"></video>
39
+
40
+ [Open the example video](https://huggingface.co/lucas-vitrus/liquid-crow/blob/main/media/liquid-crow-demo.mp4)
41
+
42
+ ## Repository layout
43
+
44
+ | Path | Contents |
45
+ |---|---|
46
+ | `lora/` | PEFT LoRA adapter and processor files |
47
+ | `onnx/model.onnx` | FP16 ONNX forward-logits graph |
48
+ | `onnx/model-q4.onnx` | ONNX Runtime weight-only 4-bit graph |
49
+ | `gguf/` | Q4_K_M language model and FP16 vision projector |
50
+ | `transformers/` | tokenizer, processor, chat template, and model configuration |
51
+ | `examples/` | LoRA, ONNX Runtime, and llama.cpp examples |
52
+ | `media/` | cover image and example video |
53
+ | `RELEASE_MANIFEST.json` | sizes and SHA-256 hashes for the primary artifacts |
54
+
55
+ ## Quick start: LoRA
56
+
57
+ ```bash
58
+ pip install torch transformers peft pillow huggingface_hub
59
+ python examples/load_lora.py path/to/image.jpg
60
+ ```
61
+
62
+ The example downloads the Liquid Crow adapter from this repository and applies it to `LiquidAI/LFM2.5-VL-450M-Extract`.
63
+
64
+ ## Quick start: GGUF
65
+
66
+ ```bash
67
+ hf download lucas-vitrus/liquid-crow \
68
+ gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-Q4_K_M.gguf \
69
+ gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-mmproj-f16.gguf \
70
+ --local-dir ./liquid-crow
71
+
72
+ llama-server \
73
+ -m ./liquid-crow/gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-Q4_K_M.gguf \
74
+ --mmproj ./liquid-crow/gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-mmproj-f16.gguf \
75
+ -c 1024 --image-min-tokens 64 --image-max-tokens 256
76
+ ```
77
+
78
+ ## Quick start: ONNX Runtime
79
+
80
+ ```bash
81
+ pip install onnxruntime transformers torch pillow huggingface_hub
82
+ python examples/onnx_forward.py path/to/image.jpg --quantized
83
+ ```
84
+
85
+ The ONNX files expose a multimodal forward-logits graph. Autoregressive generation remains the responsibility of the consuming runtime. The quantized graph requires ONNX Runtime support for `com.microsoft::MatMulNBits`.
86
+
87
+ ## Runtime notes
88
+
89
+ - Both GGUF files are required for visual inference.
90
+ - The LoRA adapter requires the base model.
91
+ - `lora/` contains the final adapter; the ONNX and GGUF deployment exports use the selected step-2,000 checkpoint.
92
+ - `onnx/model-q4.onnx` quantizes eligible matrix weights; other operations retain their exported precision.
93
+ - See `SHA256SUMS` and `export_manifest.json` for artifact integrity and interface details.
94
+
95
+ ## License
96
+
97
+ Apache-2.0. The base model remains subject to its upstream terms.
RELEASE_MANIFEST.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repository": "lucas-vitrus/liquid-crow",
3
+ "artifacts": [
4
+ {
5
+ "path": "lora/adapter_model.safetensors",
6
+ "bytes": 28748008,
7
+ "sha256": "b240113d9abb27ebaeb6e6705e5481cc3882b3befed085fb56a71258dfe6c7f6"
8
+ },
9
+ {
10
+ "path": "onnx/model.onnx",
11
+ "bytes": 898430690,
12
+ "sha256": "d3a817fbbb916cf76abcca23be0742f09210e098500c904a78956a50758d4c14"
13
+ },
14
+ {
15
+ "path": "onnx/model-q4.onnx",
16
+ "bytes": 367162143,
17
+ "sha256": "0b8483f1f94dc1c3c0ef53b4b53248d867e6c7e29fb6dab6bc08c75654e8701e"
18
+ },
19
+ {
20
+ "path": "gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-Q4_K_M.gguf",
21
+ "bytes": 229312864,
22
+ "sha256": "ac097f6bdefc0d04457ff4dafe980c45fc83ca84170d19791d94c844fd327e16"
23
+ },
24
+ {
25
+ "path": "gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-mmproj-f16.gguf",
26
+ "bytes": 189125248,
27
+ "sha256": "7397ddeaa3dd43c27878c4b5270d3eb1dfbc21a93dc637f49aa2d9b9b11201f9"
28
+ },
29
+ {
30
+ "path": "media/liquid-crow-cover.png",
31
+ "bytes": 681437,
32
+ "sha256": "354d6d6cbb60b186dfde1fb83e7e80df6e165efe885215cf450f72741ecac659"
33
+ },
34
+ {
35
+ "path": "media/liquid-crow-demo.mp4",
36
+ "bytes": 2753701,
37
+ "sha256": "86dc40bc8ec2180e728ddca7a5c1dd97ba298b688c867bb648a72b0b240abb4d"
38
+ }
39
+ ]
40
+ }
examples/__pycache__/load_lora.cpython-311.pyc ADDED
Binary file (3.48 kB). View file
 
examples/__pycache__/onnx_forward.cpython-311.pyc ADDED
Binary file (3.72 kB). View file
 
examples/load_lora.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Run one image-description turn with the published Vitrus LoRA adapter."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import sys
7
+
8
+ import torch
9
+ from huggingface_hub import snapshot_download
10
+ from peft import PeftModel
11
+ from PIL import Image
12
+ from transformers import AutoModelForImageTextToText, AutoProcessor
13
+
14
+
15
+ REPO_ID = "lucas-vitrus/liquid-crow"
16
+ BASE_MODEL = "LiquidAI/LFM2.5-VL-450M-Extract"
17
+ PROMPT = "Describe the world you see in details."
18
+
19
+
20
+ def main() -> None:
21
+ if len(sys.argv) != 2:
22
+ raise SystemExit("usage: python examples/load_lora.py path/to/image.jpg")
23
+
24
+ image = Image.open(sys.argv[1]).convert("RGB")
25
+ adapter_dir = snapshot_download(REPO_ID, allow_patterns=["lora/*"])
26
+ device = "cuda" if torch.cuda.is_available() else "cpu"
27
+ dtype = torch.float16 if device == "cuda" else torch.float32
28
+
29
+ processor = AutoProcessor.from_pretrained(
30
+ BASE_MODEL,
31
+ min_image_tokens=64,
32
+ max_image_tokens=256,
33
+ do_image_splitting=True,
34
+ )
35
+ base = AutoModelForImageTextToText.from_pretrained(
36
+ BASE_MODEL,
37
+ dtype=dtype,
38
+ low_cpu_mem_usage=True,
39
+ ).to(device)
40
+ model = PeftModel.from_pretrained(base, f"{adapter_dir}/lora").eval()
41
+
42
+ messages = [
43
+ {
44
+ "role": "user",
45
+ "content": [
46
+ {"type": "text", "text": PROMPT},
47
+ {"type": "image", "image": image},
48
+ ],
49
+ }
50
+ ]
51
+ inputs = processor.apply_chat_template(
52
+ messages,
53
+ add_generation_prompt=True,
54
+ tokenize=True,
55
+ return_tensors="pt",
56
+ return_dict=True,
57
+ ).to(device)
58
+
59
+ with torch.inference_mode():
60
+ output_ids = model.generate(**inputs, max_new_tokens=256, do_sample=False)
61
+
62
+ generated_ids = output_ids[:, inputs["input_ids"].shape[1] :]
63
+ print(processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip())
64
+
65
+
66
+ if __name__ == "__main__":
67
+ main()
examples/onnx_forward.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Run a single multimodal forward pass with the published ONNX graph."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ from pathlib import Path
8
+
9
+ import numpy as np
10
+ import onnxruntime as ort
11
+ from huggingface_hub import hf_hub_download
12
+ from PIL import Image
13
+ from transformers import AutoProcessor
14
+
15
+
16
+ REPO_ID = "lucas-vitrus/liquid-crow"
17
+ BASE_MODEL = "LiquidAI/LFM2.5-VL-450M-Extract"
18
+ INPUT_NAMES = (
19
+ "input_ids",
20
+ "pixel_values",
21
+ "spatial_shapes",
22
+ "pixel_attention_mask",
23
+ "attention_mask",
24
+ )
25
+
26
+
27
+ def parse_args() -> argparse.Namespace:
28
+ parser = argparse.ArgumentParser()
29
+ parser.add_argument("image", type=Path)
30
+ parser.add_argument("--quantized", action="store_true")
31
+ return parser.parse_args()
32
+
33
+
34
+ def main() -> None:
35
+ args = parse_args()
36
+ filename = "onnx/model-q4.onnx" if args.quantized else "onnx/model.onnx"
37
+ model_path = hf_hub_download(REPO_ID, filename=filename)
38
+ image = Image.open(args.image).convert("RGB")
39
+
40
+ processor = AutoProcessor.from_pretrained(
41
+ BASE_MODEL,
42
+ min_image_tokens=64,
43
+ max_image_tokens=256,
44
+ do_image_splitting=True,
45
+ )
46
+ messages = [
47
+ {
48
+ "role": "user",
49
+ "content": [
50
+ {"type": "text", "text": "Describe the world you see in details."},
51
+ {"type": "image", "image": image},
52
+ ],
53
+ }
54
+ ]
55
+ inputs = processor.apply_chat_template(
56
+ messages,
57
+ add_generation_prompt=True,
58
+ tokenize=True,
59
+ return_tensors="np",
60
+ return_dict=True,
61
+ )
62
+ ort_inputs = {name: np.asarray(inputs[name]) for name in INPUT_NAMES}
63
+ session = ort.InferenceSession(model_path, providers=["CPUExecutionProvider"])
64
+ logits = session.run(["logits"], ort_inputs)[0]
65
+ next_token = int(logits[0, -1].argmax())
66
+
67
+ print(f"logits shape: {logits.shape}")
68
+ print(f"greedy next token: {next_token} ({processor.tokenizer.decode([next_token])!r})")
69
+ print("Use these logits inside an autoregressive generation loop for full decoding.")
70
+
71
+
72
+ if __name__ == "__main__":
73
+ main()
examples/requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ huggingface_hub
2
+ numpy
3
+ onnxruntime
4
+ peft
5
+ pillow
6
+ torch
7
+ transformers
examples/run_gguf.sh ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ MODEL_DIR="${1:-./liquid-crow}"
5
+
6
+ hf download lucas-vitrus/liquid-crow \
7
+ gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-Q4_K_M.gguf \
8
+ gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-mmproj-f16.gguf \
9
+ --local-dir "$MODEL_DIR"
10
+
11
+ llama-server \
12
+ -m "$MODEL_DIR/gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-Q4_K_M.gguf" \
13
+ --mmproj "$MODEL_DIR/gguf/LFM2.5-VL-450M-reasoning-tracing-step2000-mmproj-f16.gguf" \
14
+ -c 1024 \
15
+ --image-min-tokens 64 \
16
+ --image-max-tokens 256