Mirror moondream/moondream3-preview @5112966d1a72
Browse files- LICENSE +27 -0
- NOTICE +14 -0
- README.md +57 -0
- config.json +20 -0
- config.py +102 -0
- hf_moondream.py +190 -0
- image_crops.py +231 -0
- layers.py +259 -0
- lora.py +437 -0
- model-00001-of-00004.safetensors +3 -0
- model-00002-of-00004.safetensors +3 -0
- model-00003-of-00004.safetensors +3 -0
- model-00004-of-00004.safetensors +3 -0
- model.safetensors.index.json +670 -0
- moondream.py +1097 -0
- region.py +136 -0
- rope.py +47 -0
- text.py +223 -0
- utils.py +41 -0
- vision.py +147 -0
LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| License | Business Source License (BSL 1.1) |
|
| 2 |
+
| --- | --- |
|
| 3 |
+
| Licensor | M87 Labs, Inc. |
|
| 4 |
+
| Licensed Work | “Moondream 3 (Preview)” including Model Weights and any Derivatives (“Derivatives” include fine-tunes, merges, quantizations, weight deltas, and other weight-level modifications or conversions.) |
|
| 5 |
+
| Additional Use Grant | You may make production use of the Licensed Work, provided Your use does not include offering the Licensed Work to third parties on a hosted or embedded basis in order to compete with M87 Labs’s paid version(s) of the Licensed Work. For purposes of this license:<br><br>A “competitive offering” is a Product that is offered to third parties on a paid basis, including through paid support arrangements, that significantly overlaps with the capabilities of M87 Labs’s paid version(s) of the Licensed Work. If Your Product is not a competitive offering when You first make it generally available, it will not become a competitive offering later due to M87 Labs releasing a new version of the Licensed Work with additional capabilities. In addition, Products that are not provided on a paid basis are not competitive.<br><br>“Product” means software that is offered to end users to manage in their own environments or offered as a service on a hosted basis.<br><br>“Embedded” means including the source code or executable code from the Licensed Work in a competitive offering. “Embedded” also means packaging the competitive offering in such a way that the Licensed Work must be accessed or downloaded for the competitive offering to operate.<br><br>Hosting or using the Licensed Work(s) for internal purposes within an organization is not considered a competitive offering. M87 Labs considers your organization to include all of your affiliates under common control. |
|
| 6 |
+
| Change Date | Two years after the first public release of this version of the Licensed Work |
|
| 7 |
+
| Change License | Apache License, Version 2.0 |
|
| 8 |
+
|
| 9 |
+
For information about alternative licensing arrangements for the Licensed Work, please contact [contact@m87.ai](mailto:contact@m87.ai).
|
| 10 |
+
|
| 11 |
+
The text of the Business Source License 1.1 follows. License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved. “Business Source License” is a trademark of MariaDB Corporation Ab.
|
| 12 |
+
|
| 13 |
+
## Terms
|
| 14 |
+
|
| 15 |
+
The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use.
|
| 16 |
+
|
| 17 |
+
Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate.
|
| 18 |
+
|
| 19 |
+
If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work.
|
| 20 |
+
|
| 21 |
+
All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor.
|
| 22 |
+
|
| 23 |
+
You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work.
|
| 24 |
+
|
| 25 |
+
Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work.
|
| 26 |
+
|
| 27 |
+
This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
|
NOTICE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
LibreMoondream3 weights
|
| 2 |
+
-----------------------
|
| 3 |
+
|
| 4 |
+
This product contains weights derived from moondream/moondream3-preview
|
| 5 |
+
(https://huggingface.co/moondream/moondream3-preview) at commit
|
| 6 |
+
5112966d1a723413b1c9a1e8bea272b72e647b35.
|
| 7 |
+
Copyright (c) M87 Labs, Inc..
|
| 8 |
+
Licensed under the Business Source License 1.1 with an
|
| 9 |
+
Additional Use Grant (no third-party competing hosted/embedded
|
| 10 |
+
paid service). The upstream license is shipped verbatim as LICENSE.
|
| 11 |
+
BSL grants the right to copy, modify, create derivative works,
|
| 12 |
+
and redistribute. Change License: Apache-2.0.
|
| 13 |
+
|
| 14 |
+
No learned parameters were changed by LibreYOLO.
|
README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: business-source-license-1.1
|
| 4 |
+
license_link: https://huggingface.co/moondream/moondream3-preview/blob/main/LICENSE.md
|
| 5 |
+
library_name: libreyolo
|
| 6 |
+
base_model: moondream/moondream3-preview
|
| 7 |
+
tags:
|
| 8 |
+
- object-detection
|
| 9 |
+
- image-text-to-text
|
| 10 |
+
- libreyolo
|
| 11 |
+
- vlm
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# LibreMoondream3
|
| 15 |
+
|
| 16 |
+
Moondream 3 Preview weights mirrored for LibreYOLO's LibreVLM tier.
|
| 17 |
+
|
| 18 |
+
> ## Custom-license weights (BSL 1.1)
|
| 19 |
+
>
|
| 20 |
+
> These weights are **not** covered by LibreYOLO's MIT license. They are
|
| 21 |
+
> Moondream 3 (Preview) from M87 Labs, licensed under the
|
| 22 |
+
> [Business Source License 1.1](https://huggingface.co/moondream/moondream3-preview/blob/main/LICENSE.md)
|
| 23 |
+
> with an Additional Use Grant. Redistribution is allowed. Production use
|
| 24 |
+
> is allowed except offering the model to third parties as a paid hosted
|
| 25 |
+
> or embedded service that competes with M87 Labs's paid versions.
|
| 26 |
+
> That restriction binds you, the downloader. The LibreYOLO **code** stays
|
| 27 |
+
> MIT. See [`LICENSE`](./LICENSE).
|
| 28 |
+
|
| 29 |
+
## Source
|
| 30 |
+
|
| 31 |
+
Mirrored from [moondream/moondream3-preview](https://huggingface.co/moondream/moondream3-preview)
|
| 32 |
+
at commit `5112966d1a723413b1c9a1e8bea272b72e647b35`.
|
| 33 |
+
Copyright (c) M87 Labs, Inc.. Licensed under BSL 1.1.
|
| 34 |
+
|
| 35 |
+
## Modifications
|
| 36 |
+
|
| 37 |
+
No learned parameters were changed. This repository preserves the Hugging Face
|
| 38 |
+
snapshot files needed by LibreYOLO's VLM wrapper, ships the upstream license
|
| 39 |
+
verbatim, and replaces the model card with LibreYOLO-specific loading notes.
|
| 40 |
+
|
| 41 |
+
## Usage
|
| 42 |
+
|
| 43 |
+
```python
|
| 44 |
+
from libreyolo import LibreVLM
|
| 45 |
+
|
| 46 |
+
model = LibreVLM("moondream-3")
|
| 47 |
+
model.set_classes(["person", "helmet"])
|
| 48 |
+
results = model.predict("image.jpg")
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
Official runtime notes ask for about 24 GB of GPU memory.
|
| 52 |
+
|
| 53 |
+
## License
|
| 54 |
+
|
| 55 |
+
Business Source License 1.1 with Additional Use Grant. See [`LICENSE`](./LICENSE)
|
| 56 |
+
and [`NOTICE`](./NOTICE). Change License is Apache-2.0 two years after first
|
| 57 |
+
public release of this version.
|
config.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"HfMoondream"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "hf_moondream.HfConfig",
|
| 7 |
+
"AutoModelForCausalLM": "hf_moondream.HfMoondream"
|
| 8 |
+
},
|
| 9 |
+
"config": {
|
| 10 |
+
"skills": [
|
| 11 |
+
"query",
|
| 12 |
+
"caption",
|
| 13 |
+
"detect",
|
| 14 |
+
"point"
|
| 15 |
+
]
|
| 16 |
+
},
|
| 17 |
+
"model_type": "moondream3",
|
| 18 |
+
"torch_dtype": "bfloat16",
|
| 19 |
+
"transformers_version": "4.51.1"
|
| 20 |
+
}
|
config.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass, field
|
| 2 |
+
from typing import Dict, List, Optional
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
@dataclass(frozen=True)
|
| 6 |
+
class TextMoeConfig:
|
| 7 |
+
num_experts: int = 64
|
| 8 |
+
start_layer: int = 4
|
| 9 |
+
experts_per_token: int = 8
|
| 10 |
+
expert_inner_dim: int = 1024
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
@dataclass(frozen=True)
|
| 14 |
+
class TextConfig:
|
| 15 |
+
dim: int = 2048
|
| 16 |
+
ff_dim: int = 8192
|
| 17 |
+
n_layers: int = 24
|
| 18 |
+
vocab_size: int = 51200
|
| 19 |
+
max_context: int = 4096
|
| 20 |
+
n_heads: int = 32
|
| 21 |
+
n_kv_heads: int = 32
|
| 22 |
+
prefix_attn: int = 730
|
| 23 |
+
group_size: Optional[int] = None
|
| 24 |
+
moe: Optional[TextMoeConfig] = TextMoeConfig()
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@dataclass(frozen=True)
|
| 28 |
+
class VisionConfig:
|
| 29 |
+
enc_dim: int = 1152
|
| 30 |
+
enc_patch_size: int = 14
|
| 31 |
+
enc_n_layers: int = 27
|
| 32 |
+
enc_ff_dim: int = 4304
|
| 33 |
+
enc_n_heads: int = 16
|
| 34 |
+
proj_out_dim: int = 2048
|
| 35 |
+
crop_size: int = 378
|
| 36 |
+
in_channels: int = 3
|
| 37 |
+
max_crops: int = 12
|
| 38 |
+
overlap_margin: int = 4
|
| 39 |
+
proj_inner_dim: int = 8192
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
@dataclass(frozen=True)
|
| 43 |
+
class RegionConfig:
|
| 44 |
+
dim: int = 2048
|
| 45 |
+
coord_feat_dim: int = 256
|
| 46 |
+
coord_out_dim: int = 1024
|
| 47 |
+
size_feat_dim: int = 512
|
| 48 |
+
size_out_dim: int = 2048
|
| 49 |
+
group_size: Optional[int] = None
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
@dataclass(frozen=True)
|
| 53 |
+
class TokenizerConfig:
|
| 54 |
+
bos_id: int = 0
|
| 55 |
+
eos_id: int = 0
|
| 56 |
+
answer_id: int = 3
|
| 57 |
+
thinking_id: int = 4
|
| 58 |
+
coord_id: int = 5
|
| 59 |
+
size_id: int = 6
|
| 60 |
+
start_ground_points_id: int = 7
|
| 61 |
+
end_ground_id: int = 9
|
| 62 |
+
templates: Dict[str, Optional[Dict[str, List[int]]]] = field(
|
| 63 |
+
default_factory=lambda: {
|
| 64 |
+
"caption": {
|
| 65 |
+
"short": [1, 32708, 2, 12492, 3],
|
| 66 |
+
"normal": [1, 32708, 2, 6382, 3],
|
| 67 |
+
"long": [1, 32708, 2, 4059, 3],
|
| 68 |
+
},
|
| 69 |
+
"query": {"prefix": [1, 15381, 2], "suffix": [3]},
|
| 70 |
+
"detect": {"prefix": [1, 7235, 476, 2], "suffix": [3]},
|
| 71 |
+
"point": {"prefix": [1, 2581, 2], "suffix": [3]},
|
| 72 |
+
}
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
@dataclass(frozen=True)
|
| 77 |
+
class MoondreamConfig:
|
| 78 |
+
text: TextConfig = TextConfig()
|
| 79 |
+
vision: VisionConfig = VisionConfig()
|
| 80 |
+
region: RegionConfig = RegionConfig()
|
| 81 |
+
tokenizer: TokenizerConfig = TokenizerConfig()
|
| 82 |
+
|
| 83 |
+
@classmethod
|
| 84 |
+
def from_dict(cls, config_dict: dict):
|
| 85 |
+
text_config = TextConfig(**config_dict.get("text", {}))
|
| 86 |
+
vision_config = VisionConfig(**config_dict.get("vision", {}))
|
| 87 |
+
region_config = RegionConfig(**config_dict.get("region", {}))
|
| 88 |
+
tokenizer_config = TokenizerConfig(**config_dict.get("tokenizer", {}))
|
| 89 |
+
return cls(
|
| 90 |
+
text=text_config,
|
| 91 |
+
vision=vision_config,
|
| 92 |
+
region=region_config,
|
| 93 |
+
tokenizer=tokenizer_config,
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
def to_dict(self):
|
| 97 |
+
return {
|
| 98 |
+
"text": self.text.__dict__,
|
| 99 |
+
"vision": self.vision.__dict__,
|
| 100 |
+
"region": self.region.__dict__,
|
| 101 |
+
"tokenizer": self.tokenizer.__dict__,
|
| 102 |
+
}
|
hf_moondream.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
from transformers import PreTrainedModel, PretrainedConfig
|
| 4 |
+
from typing import Union
|
| 5 |
+
|
| 6 |
+
from .config import MoondreamConfig
|
| 7 |
+
from .moondream import MoondreamModel
|
| 8 |
+
|
| 9 |
+
# Files sometimes don't get loaded without these...
|
| 10 |
+
from .image_crops import *
|
| 11 |
+
from .vision import *
|
| 12 |
+
from .text import *
|
| 13 |
+
from .region import *
|
| 14 |
+
from .utils import *
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def extract_question(text):
|
| 18 |
+
prefix = "<image>\n\nQuestion: "
|
| 19 |
+
suffix = "\n\nAnswer:"
|
| 20 |
+
|
| 21 |
+
if text.startswith(prefix) and text.endswith(suffix):
|
| 22 |
+
return text[len(prefix) : -len(suffix)]
|
| 23 |
+
else:
|
| 24 |
+
return None
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class HfConfig(PretrainedConfig):
|
| 28 |
+
_auto_class = "AutoConfig"
|
| 29 |
+
model_type = "moondream3"
|
| 30 |
+
|
| 31 |
+
def __init__(self, **kwargs):
|
| 32 |
+
super().__init__(**kwargs)
|
| 33 |
+
self.config = {"skills": ["query", "caption", "detect", "point"]}
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class HfMoondream(PreTrainedModel):
|
| 37 |
+
_auto_class = "AutoModelForCausalLM"
|
| 38 |
+
config_class = HfConfig
|
| 39 |
+
|
| 40 |
+
def __init__(self, config):
|
| 41 |
+
super().__init__(config)
|
| 42 |
+
self.model = MoondreamModel(
|
| 43 |
+
MoondreamConfig.from_dict(config.config), setup_caches=False
|
| 44 |
+
)
|
| 45 |
+
self._is_kv_cache_setup = False
|
| 46 |
+
self.post_init()
|
| 47 |
+
|
| 48 |
+
@classmethod
|
| 49 |
+
def from_pretrained(cls, *args, **kwargs):
|
| 50 |
+
output = super().from_pretrained(*args, **kwargs)
|
| 51 |
+
model = output[0] if isinstance(output, tuple) else output
|
| 52 |
+
model.model._refresh_runtime_buffers()
|
| 53 |
+
return output
|
| 54 |
+
|
| 55 |
+
def _setup_caches(self):
|
| 56 |
+
if not self._is_kv_cache_setup:
|
| 57 |
+
self.model._setup_caches()
|
| 58 |
+
self._is_kv_cache_setup = True
|
| 59 |
+
|
| 60 |
+
@property
|
| 61 |
+
def encode_image(self):
|
| 62 |
+
self._setup_caches()
|
| 63 |
+
return self.model.encode_image
|
| 64 |
+
|
| 65 |
+
@property
|
| 66 |
+
def query(self):
|
| 67 |
+
self._setup_caches()
|
| 68 |
+
return self.model.query
|
| 69 |
+
|
| 70 |
+
@property
|
| 71 |
+
def caption(self):
|
| 72 |
+
self._setup_caches()
|
| 73 |
+
return self.model.caption
|
| 74 |
+
|
| 75 |
+
@property
|
| 76 |
+
def detect(self):
|
| 77 |
+
self._setup_caches()
|
| 78 |
+
return self.model.detect
|
| 79 |
+
|
| 80 |
+
@property
|
| 81 |
+
def point(self):
|
| 82 |
+
self._setup_caches()
|
| 83 |
+
return self.model.point
|
| 84 |
+
|
| 85 |
+
@property
|
| 86 |
+
def detect_gaze(self):
|
| 87 |
+
self._setup_caches()
|
| 88 |
+
return self.model.detect_gaze
|
| 89 |
+
|
| 90 |
+
def answer_question(
|
| 91 |
+
self,
|
| 92 |
+
image_embeds,
|
| 93 |
+
question,
|
| 94 |
+
tokenizer=None,
|
| 95 |
+
chat_history="",
|
| 96 |
+
result_queue=None,
|
| 97 |
+
max_new_tokens=256,
|
| 98 |
+
**kwargs
|
| 99 |
+
):
|
| 100 |
+
answer = self.query(image_embeds, question)["answer"].strip()
|
| 101 |
+
|
| 102 |
+
if result_queue is not None:
|
| 103 |
+
result_queue.put(answer)
|
| 104 |
+
return answer
|
| 105 |
+
|
| 106 |
+
def batch_answer(self, images, prompts, tokenizer=None, **kwargs):
|
| 107 |
+
answers = []
|
| 108 |
+
for image, prompt in zip(images, prompts):
|
| 109 |
+
answers.append(self.query(image, prompt)["answer"].strip())
|
| 110 |
+
return answers
|
| 111 |
+
|
| 112 |
+
def _unsupported_exception(self):
|
| 113 |
+
raise NotImplementedError(
|
| 114 |
+
"This method is not supported in the latest version of moondream. "
|
| 115 |
+
"Consider upgrading to the updated API spec, or alternately pin "
|
| 116 |
+
"to 'revision=2024-08-26'."
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
def generate(self, image_embeds, prompt, tokenizer, max_new_tokens=128, **kwargs):
|
| 120 |
+
"""
|
| 121 |
+
Function definition remains unchanged for backwards compatibility.
|
| 122 |
+
Be aware that tokenizer, max_new_takens, and kwargs are ignored.
|
| 123 |
+
"""
|
| 124 |
+
prompt_extracted = extract_question(prompt)
|
| 125 |
+
if prompt_extracted is not None:
|
| 126 |
+
answer = self.model.query(
|
| 127 |
+
image=image_embeds, question=prompt_extracted, stream=False
|
| 128 |
+
)["answer"]
|
| 129 |
+
else:
|
| 130 |
+
image_embeds = self.encode_image(image_embeds)
|
| 131 |
+
prompt_tokens = torch.tensor(
|
| 132 |
+
[self.model.tokenizer.encode(prompt).ids],
|
| 133 |
+
device=self.device,
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
def generator():
|
| 137 |
+
for token in self.model._generate_answer(
|
| 138 |
+
prompt_tokens,
|
| 139 |
+
image_embeds.kv_cache,
|
| 140 |
+
image_embeds.pos,
|
| 141 |
+
max_new_tokens,
|
| 142 |
+
):
|
| 143 |
+
yield token
|
| 144 |
+
|
| 145 |
+
answer = "".join(list(generator()))
|
| 146 |
+
|
| 147 |
+
return [answer]
|
| 148 |
+
|
| 149 |
+
def get_input_embeddings(self) -> nn.Embedding:
|
| 150 |
+
"""
|
| 151 |
+
Lazily wrap the raw parameter `self.model.text.wte` in a real
|
| 152 |
+
`nn.Embedding` layer so that HF mix-ins recognise it. The wrapper
|
| 153 |
+
**shares** the weight tensor—no copy is made.
|
| 154 |
+
"""
|
| 155 |
+
if not hasattr(self, "_input_embeddings"):
|
| 156 |
+
self._input_embeddings = nn.Embedding.from_pretrained(
|
| 157 |
+
self.model.text.wte, # tensor created in text.py
|
| 158 |
+
freeze=True, # set to False if you need it trainable
|
| 159 |
+
)
|
| 160 |
+
return self._input_embeddings
|
| 161 |
+
|
| 162 |
+
def set_input_embeddings(self, value: Union[nn.Embedding, nn.Module]) -> None:
|
| 163 |
+
"""
|
| 164 |
+
Lets HF functions (e.g. `resize_token_embeddings`) replace or resize the
|
| 165 |
+
embeddings and keeps everything tied to `self.model.text.wte`.
|
| 166 |
+
"""
|
| 167 |
+
# 1. point the low-level parameter to the new weight matrix
|
| 168 |
+
self.model.text.wte = value.weight
|
| 169 |
+
# 2. keep a reference for get_input_embeddings()
|
| 170 |
+
self._input_embeddings = value
|
| 171 |
+
|
| 172 |
+
def input_embeds(
|
| 173 |
+
self,
|
| 174 |
+
input_ids: Union[torch.LongTensor, list, tuple],
|
| 175 |
+
*,
|
| 176 |
+
device: torch.device | None = None
|
| 177 |
+
) -> torch.FloatTensor:
|
| 178 |
+
"""
|
| 179 |
+
Back-compat wrapper that turns token IDs into embeddings.
|
| 180 |
+
|
| 181 |
+
Example:
|
| 182 |
+
ids = torch.tensor([[1, 2, 3]])
|
| 183 |
+
embeds = model.input_embeds(ids) # (1, 3, hidden_dim)
|
| 184 |
+
"""
|
| 185 |
+
if not torch.is_tensor(input_ids):
|
| 186 |
+
input_ids = torch.as_tensor(input_ids)
|
| 187 |
+
if device is not None:
|
| 188 |
+
input_ids = input_ids.to(device)
|
| 189 |
+
|
| 190 |
+
return self.get_input_embeddings()(input_ids)
|
image_crops.py
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import numpy as np
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from typing import TypedDict
|
| 6 |
+
|
| 7 |
+
try:
|
| 8 |
+
import pyvips
|
| 9 |
+
|
| 10 |
+
HAS_VIPS = True
|
| 11 |
+
except:
|
| 12 |
+
from PIL import Image
|
| 13 |
+
|
| 14 |
+
HAS_VIPS = False
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def select_tiling(
|
| 18 |
+
height: int, width: int, crop_size: int, max_crops: int
|
| 19 |
+
) -> tuple[int, int]:
|
| 20 |
+
"""
|
| 21 |
+
Determine the optimal number of tiles to cover an image with overlapping crops.
|
| 22 |
+
"""
|
| 23 |
+
if height <= crop_size or width <= crop_size:
|
| 24 |
+
return (1, 1)
|
| 25 |
+
|
| 26 |
+
# Minimum required tiles in each dimension
|
| 27 |
+
min_h = math.ceil(height / crop_size)
|
| 28 |
+
min_w = math.ceil(width / crop_size)
|
| 29 |
+
|
| 30 |
+
# If minimum required tiles exceed max_crops, return proportional distribution
|
| 31 |
+
if min_h * min_w > max_crops:
|
| 32 |
+
ratio = math.sqrt(max_crops / (min_h * min_w))
|
| 33 |
+
return (max(1, math.floor(min_h * ratio)), max(1, math.floor(min_w * ratio)))
|
| 34 |
+
|
| 35 |
+
# Perfect aspect-ratio tiles that satisfy max_crops
|
| 36 |
+
h_tiles = math.floor(math.sqrt(max_crops * height / width))
|
| 37 |
+
w_tiles = math.floor(math.sqrt(max_crops * width / height))
|
| 38 |
+
|
| 39 |
+
# Ensure we meet minimum tile requirements
|
| 40 |
+
h_tiles = max(h_tiles, min_h)
|
| 41 |
+
w_tiles = max(w_tiles, min_w)
|
| 42 |
+
|
| 43 |
+
# If we exceeded max_crops, scale down the larger dimension
|
| 44 |
+
if h_tiles * w_tiles > max_crops:
|
| 45 |
+
if w_tiles > h_tiles:
|
| 46 |
+
w_tiles = math.floor(max_crops / h_tiles)
|
| 47 |
+
else:
|
| 48 |
+
h_tiles = math.floor(max_crops / w_tiles)
|
| 49 |
+
|
| 50 |
+
return (max(1, h_tiles), max(1, w_tiles))
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class OverlapCropOutput(TypedDict):
|
| 54 |
+
crops: np.ndarray
|
| 55 |
+
tiling: tuple[int, int]
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def overlap_crop_image(
|
| 59 |
+
image: np.ndarray,
|
| 60 |
+
overlap_margin: int,
|
| 61 |
+
max_crops: int,
|
| 62 |
+
base_size: tuple[int, int] = (378, 378),
|
| 63 |
+
patch_size: int = 14,
|
| 64 |
+
) -> OverlapCropOutput:
|
| 65 |
+
"""
|
| 66 |
+
Process an image using an overlap-and-resize cropping strategy with margin handling.
|
| 67 |
+
|
| 68 |
+
This function takes an input image and creates multiple overlapping crops with
|
| 69 |
+
consistent margins. It produces:
|
| 70 |
+
1. A single global crop resized to base_size
|
| 71 |
+
2. Multiple overlapping local crops that maintain high resolution details
|
| 72 |
+
3. A patch ordering matrix that tracks correspondence between crops
|
| 73 |
+
|
| 74 |
+
The overlap strategy ensures:
|
| 75 |
+
- Smooth transitions between adjacent crops
|
| 76 |
+
- No loss of information at crop boundaries
|
| 77 |
+
- Proper handling of features that cross crop boundaries
|
| 78 |
+
- Consistent patch indexing across the full image
|
| 79 |
+
|
| 80 |
+
Args:
|
| 81 |
+
image (np.ndarray): Input image as numpy array with shape (H,W,C)
|
| 82 |
+
base_size (tuple[int,int]): Target size for crops, default (378,378)
|
| 83 |
+
patch_size (int): Size of patches in pixels, default 14
|
| 84 |
+
overlap_margin (int): Margin size in patch units, default 4
|
| 85 |
+
max_crops (int): Maximum number of crops allowed, default 12
|
| 86 |
+
|
| 87 |
+
Returns:
|
| 88 |
+
OverlapCropOutput: Dictionary containing:
|
| 89 |
+
- crops: A numpy array containing the global crop of the full image (index 0)
|
| 90 |
+
followed by the overlapping cropped regions (indices 1+)
|
| 91 |
+
- tiling: Tuple of (height,width) tile counts
|
| 92 |
+
"""
|
| 93 |
+
original_h, original_w = image.shape[:2]
|
| 94 |
+
|
| 95 |
+
# Convert margin from patch units to pixels
|
| 96 |
+
margin_pixels = patch_size * overlap_margin
|
| 97 |
+
total_margin_pixels = margin_pixels * 2 # Both sides
|
| 98 |
+
|
| 99 |
+
# Calculate crop parameters
|
| 100 |
+
crop_patches = base_size[0] // patch_size # patches per crop dimension
|
| 101 |
+
crop_window_patches = crop_patches - (2 * overlap_margin) # usable patches
|
| 102 |
+
crop_window_size = crop_window_patches * patch_size # usable size in pixels
|
| 103 |
+
|
| 104 |
+
# Determine tiling
|
| 105 |
+
tiling = select_tiling(
|
| 106 |
+
original_h - total_margin_pixels,
|
| 107 |
+
original_w - total_margin_pixels,
|
| 108 |
+
crop_window_size,
|
| 109 |
+
max_crops,
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
# Pre-allocate crops.
|
| 113 |
+
n_crops = tiling[0] * tiling[1] + 1 # 1 = global crop
|
| 114 |
+
crops = np.zeros(
|
| 115 |
+
(n_crops, base_size[0], base_size[1], image.shape[2]), dtype=np.uint8
|
| 116 |
+
)
|
| 117 |
+
|
| 118 |
+
# Resize image to fit tiling
|
| 119 |
+
target_size = (
|
| 120 |
+
tiling[0] * crop_window_size + total_margin_pixels,
|
| 121 |
+
tiling[1] * crop_window_size + total_margin_pixels,
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
if HAS_VIPS:
|
| 125 |
+
# Convert to vips for resizing
|
| 126 |
+
vips_image = pyvips.Image.new_from_array(image)
|
| 127 |
+
scale_x = target_size[1] / image.shape[1]
|
| 128 |
+
scale_y = target_size[0] / image.shape[0]
|
| 129 |
+
resized = vips_image.resize(scale_x, vscale=scale_y)
|
| 130 |
+
image = resized.numpy()
|
| 131 |
+
|
| 132 |
+
# Create global crop
|
| 133 |
+
scale_x = base_size[1] / vips_image.width
|
| 134 |
+
scale_y = base_size[0] / vips_image.height
|
| 135 |
+
global_vips = vips_image.resize(scale_x, vscale=scale_y)
|
| 136 |
+
crops[0] = global_vips.numpy()
|
| 137 |
+
else:
|
| 138 |
+
# Fallback to PIL
|
| 139 |
+
pil_img = Image.fromarray(image)
|
| 140 |
+
resized = pil_img.resize(
|
| 141 |
+
(int(target_size[1]), int(target_size[0])),
|
| 142 |
+
resample=Image.Resampling.LANCZOS,
|
| 143 |
+
)
|
| 144 |
+
image = np.asarray(resized)
|
| 145 |
+
|
| 146 |
+
# Create global crop
|
| 147 |
+
global_pil = pil_img.resize(
|
| 148 |
+
(int(base_size[1]), int(base_size[0])), resample=Image.Resampling.LANCZOS
|
| 149 |
+
)
|
| 150 |
+
crops[0] = np.asarray(global_pil)
|
| 151 |
+
|
| 152 |
+
for i in range(tiling[0]):
|
| 153 |
+
for j in range(tiling[1]):
|
| 154 |
+
# Calculate crop coordinates
|
| 155 |
+
y0 = i * crop_window_size
|
| 156 |
+
x0 = j * crop_window_size
|
| 157 |
+
|
| 158 |
+
# Extract crop with padding if needed
|
| 159 |
+
y_end = min(y0 + base_size[0], image.shape[0])
|
| 160 |
+
x_end = min(x0 + base_size[1], image.shape[1])
|
| 161 |
+
|
| 162 |
+
crop_region = image[y0:y_end, x0:x_end]
|
| 163 |
+
crops[
|
| 164 |
+
1 + i * tiling[1] + j, : crop_region.shape[0], : crop_region.shape[1]
|
| 165 |
+
] = crop_region
|
| 166 |
+
|
| 167 |
+
return {"crops": crops, "tiling": tiling}
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def reconstruct_from_crops(
|
| 171 |
+
crops: torch.Tensor,
|
| 172 |
+
tiling: tuple[int, int],
|
| 173 |
+
overlap_margin: int,
|
| 174 |
+
patch_size: int = 14,
|
| 175 |
+
) -> torch.Tensor:
|
| 176 |
+
"""
|
| 177 |
+
Reconstruct the original image from overlapping crops into a single seamless image.
|
| 178 |
+
|
| 179 |
+
Takes a list of overlapping image crops along with their positional metadata and
|
| 180 |
+
reconstructs them into a single coherent image by carefully stitching together
|
| 181 |
+
non-overlapping regions. Handles both numpy arrays and PyTorch tensors.
|
| 182 |
+
|
| 183 |
+
Args:
|
| 184 |
+
crops: List of image crops as numpy arrays or PyTorch tensors with shape
|
| 185 |
+
(H,W,C)
|
| 186 |
+
tiling: Tuple of (height,width) indicating crop grid layout
|
| 187 |
+
patch_size: Size in pixels of each patch, default 14
|
| 188 |
+
overlap_margin: Number of overlapping patches on each edge, default 4
|
| 189 |
+
|
| 190 |
+
Returns:
|
| 191 |
+
Reconstructed image as numpy array or PyTorch tensor matching input type,
|
| 192 |
+
with shape (H,W,C) where H,W are the original image dimensions
|
| 193 |
+
"""
|
| 194 |
+
tiling_h, tiling_w = tiling
|
| 195 |
+
crop_height, crop_width = crops[0].shape[:2]
|
| 196 |
+
margin_pixels = overlap_margin * patch_size
|
| 197 |
+
|
| 198 |
+
# Calculate output size (only adding margins once)
|
| 199 |
+
output_h = (crop_height - 2 * margin_pixels) * tiling_h + 2 * margin_pixels
|
| 200 |
+
output_w = (crop_width - 2 * margin_pixels) * tiling_w + 2 * margin_pixels
|
| 201 |
+
|
| 202 |
+
reconstructed = torch.zeros(
|
| 203 |
+
(output_h, output_w, crops[0].shape[2]),
|
| 204 |
+
device=crops[0].device,
|
| 205 |
+
dtype=crops[0].dtype,
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
for i, crop in enumerate(crops):
|
| 209 |
+
tile_y = i // tiling_w
|
| 210 |
+
tile_x = i % tiling_w
|
| 211 |
+
|
| 212 |
+
# For each tile, determine which part to keep
|
| 213 |
+
# Keep left margin only for first column
|
| 214 |
+
x_start = 0 if tile_x == 0 else margin_pixels
|
| 215 |
+
# Keep right margin only for last column
|
| 216 |
+
x_end = crop_width if tile_x == tiling_w - 1 else crop_width - margin_pixels
|
| 217 |
+
# Keep top margin only for first row
|
| 218 |
+
y_start = 0 if tile_y == 0 else margin_pixels
|
| 219 |
+
# Keep bottom margin only for last row
|
| 220 |
+
y_end = crop_height if tile_y == tiling_h - 1 else crop_height - margin_pixels
|
| 221 |
+
|
| 222 |
+
# Calculate where this piece belongs in the output
|
| 223 |
+
out_x = tile_x * (crop_width - 2 * margin_pixels)
|
| 224 |
+
out_y = tile_y * (crop_height - 2 * margin_pixels)
|
| 225 |
+
|
| 226 |
+
# Place the piece
|
| 227 |
+
reconstructed[
|
| 228 |
+
out_y + y_start : out_y + y_end, out_x + x_start : out_x + x_end
|
| 229 |
+
] = crop[y_start:y_end, x_start:x_end]
|
| 230 |
+
|
| 231 |
+
return reconstructed
|
layers.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
|
| 5 |
+
from dataclasses import dataclass
|
| 6 |
+
from typing import Literal, Optional
|
| 7 |
+
|
| 8 |
+
from .lora import (
|
| 9 |
+
DenseLoRALayer,
|
| 10 |
+
MoELoRALayer,
|
| 11 |
+
apply_dense_lora,
|
| 12 |
+
apply_moe_lora_fc1_flat,
|
| 13 |
+
apply_moe_lora_fc2_flat,
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
try:
|
| 17 |
+
from torchao import quantize_
|
| 18 |
+
from torchao.quantization import int4_weight_only
|
| 19 |
+
except ImportError:
|
| 20 |
+
|
| 21 |
+
def quantize_(model, quant_mode):
|
| 22 |
+
raise ImportError(
|
| 23 |
+
"torchao is not installed. Please install it with `pip install torchao`."
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
def int4_weight_only(group_size):
|
| 27 |
+
raise ImportError(
|
| 28 |
+
"torchao is not installed. Please install it with `pip install torchao`."
|
| 29 |
+
)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def gelu_approx(x):
|
| 33 |
+
return F.gelu(x, approximate="tanh")
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
@dataclass
|
| 37 |
+
class LinearWeights:
|
| 38 |
+
weight: torch.Tensor
|
| 39 |
+
bias: torch.Tensor
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def linear(x: torch.Tensor, w: LinearWeights) -> torch.Tensor:
|
| 43 |
+
return F.linear(x, w.weight, w.bias)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def dequantize_tensor(W_q, scale, zero, orig_shape, dtype=torch.bfloat16):
|
| 47 |
+
_step = W_q.shape[0]
|
| 48 |
+
W_r = torch.empty([2 * _step, W_q.shape[1]], dtype=dtype, device=W_q.device)
|
| 49 |
+
W_r[:_step] = (W_q & 0b11110000) >> 4
|
| 50 |
+
W_r[_step:] = W_q & 0b00001111
|
| 51 |
+
W_r.sub_(zero).mul_(scale)
|
| 52 |
+
return W_r.reshape(orig_shape)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class QuantizedLinear(nn.Module):
|
| 56 |
+
def __init__(
|
| 57 |
+
self,
|
| 58 |
+
in_features: int,
|
| 59 |
+
out_features: int,
|
| 60 |
+
dtype: torch.dtype,
|
| 61 |
+
):
|
| 62 |
+
# TODO: Take group_size as an input instead of hardcoding it here.
|
| 63 |
+
super().__init__()
|
| 64 |
+
self.in_features = in_features
|
| 65 |
+
self.out_features = out_features
|
| 66 |
+
self.weight = nn.ParameterDict(
|
| 67 |
+
{
|
| 68 |
+
"packed": nn.Parameter(
|
| 69 |
+
torch.empty(
|
| 70 |
+
out_features * in_features // (128 * 2), 128, dtype=torch.uint8
|
| 71 |
+
),
|
| 72 |
+
requires_grad=False,
|
| 73 |
+
),
|
| 74 |
+
"scale": nn.Parameter(
|
| 75 |
+
torch.empty(out_features * in_features // 128, 1),
|
| 76 |
+
requires_grad=False,
|
| 77 |
+
),
|
| 78 |
+
"zero_point": nn.Parameter(
|
| 79 |
+
torch.empty(out_features * in_features // 128, 1),
|
| 80 |
+
requires_grad=False,
|
| 81 |
+
),
|
| 82 |
+
}
|
| 83 |
+
)
|
| 84 |
+
self.bias = nn.Parameter(torch.empty(out_features), requires_grad=False)
|
| 85 |
+
self.unpacked = False
|
| 86 |
+
|
| 87 |
+
def unpack(self):
|
| 88 |
+
if self.unpacked:
|
| 89 |
+
return
|
| 90 |
+
|
| 91 |
+
self.weight = nn.Parameter(
|
| 92 |
+
dequantize_tensor(
|
| 93 |
+
self.weight["packed"],
|
| 94 |
+
self.weight["scale"],
|
| 95 |
+
self.weight["zero_point"],
|
| 96 |
+
(self.out_features, self.in_features),
|
| 97 |
+
torch.bfloat16,
|
| 98 |
+
)
|
| 99 |
+
)
|
| 100 |
+
with torch.device("meta"):
|
| 101 |
+
self.linear = nn.Linear(
|
| 102 |
+
self.in_features, self.out_features, dtype=torch.bfloat16
|
| 103 |
+
)
|
| 104 |
+
self.linear.weight = self.weight
|
| 105 |
+
self.linear.bias = nn.Parameter(
|
| 106 |
+
self.bias.to(torch.bfloat16), requires_grad=False
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
del self.weight, self.bias
|
| 110 |
+
quantize_(self, int4_weight_only(group_size=128))
|
| 111 |
+
self.unpacked = True
|
| 112 |
+
torch.cuda.empty_cache()
|
| 113 |
+
|
| 114 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 115 |
+
if not self.unpacked:
|
| 116 |
+
self.unpack()
|
| 117 |
+
return self.linear(x)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
@dataclass
|
| 121 |
+
class LayerNormWeights:
|
| 122 |
+
weight: torch.Tensor
|
| 123 |
+
bias: torch.Tensor
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def layer_norm(x: torch.Tensor, w: LayerNormWeights) -> torch.Tensor:
|
| 127 |
+
return F.layer_norm(x, w.bias.shape, w.weight, w.bias)
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
@dataclass
|
| 131 |
+
class MLPWeights:
|
| 132 |
+
fc1: LinearWeights
|
| 133 |
+
fc2: LinearWeights
|
| 134 |
+
act: Literal["gelu_approx"] = "gelu_approx"
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def mlp(
|
| 138 |
+
x: torch.Tensor, w: MLPWeights, lora: Optional[DenseLoRALayer] = None
|
| 139 |
+
) -> torch.Tensor:
|
| 140 |
+
x0 = w.fc1(x)
|
| 141 |
+
if lora is not None:
|
| 142 |
+
x = x0 + apply_dense_lora(x, lora.up_a, lora.up_b)
|
| 143 |
+
else:
|
| 144 |
+
x = x0
|
| 145 |
+
|
| 146 |
+
x = gelu_approx(x)
|
| 147 |
+
|
| 148 |
+
x0 = w.fc2(x)
|
| 149 |
+
if lora is not None:
|
| 150 |
+
x = x0 + apply_dense_lora(x, lora.down_a, lora.down_b)
|
| 151 |
+
else:
|
| 152 |
+
x = x0
|
| 153 |
+
|
| 154 |
+
return x
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def moe_mlp(
|
| 158 |
+
x: torch.Tensor,
|
| 159 |
+
mlp_module: nn.Module,
|
| 160 |
+
experts_per_token: int,
|
| 161 |
+
lora: Optional[MoELoRALayer] = None,
|
| 162 |
+
) -> torch.Tensor:
|
| 163 |
+
B, T, C = x.shape
|
| 164 |
+
x = x.reshape(-1, C)
|
| 165 |
+
|
| 166 |
+
# Router computation
|
| 167 |
+
router_logits = mlp_module.router(x)
|
| 168 |
+
topk_logits, topk_idxs = torch.topk(router_logits, experts_per_token, dim=-1)
|
| 169 |
+
topk_weights = F.softmax(topk_logits, dim=-1, dtype=torch.float32).to(x.dtype)
|
| 170 |
+
num_tokens, top_k = topk_idxs.shape
|
| 171 |
+
|
| 172 |
+
if T == 1:
|
| 173 |
+
w1_weight = mlp_module.fc1.weight
|
| 174 |
+
w2_weight = mlp_module.fc2.weight
|
| 175 |
+
|
| 176 |
+
# Flatten to process all token-expert pairs at once
|
| 177 |
+
flat_idxs = topk_idxs.view(-1) # [T*A]
|
| 178 |
+
flat_weights = topk_weights.view(-1) # [T*A]
|
| 179 |
+
|
| 180 |
+
# Select expert weights
|
| 181 |
+
w1_selected = w1_weight[flat_idxs]
|
| 182 |
+
w2_selected = w2_weight[flat_idxs]
|
| 183 |
+
|
| 184 |
+
# Expand input for all token-expert pairs
|
| 185 |
+
x_expanded = x.unsqueeze(1).expand(-1, top_k, -1).reshape(-1, C) # [T*A, D]
|
| 186 |
+
|
| 187 |
+
# First linear layer with GeGLU: [T*A, H, D] @ [T*A, D, 1] -> [T*A, H]
|
| 188 |
+
x1_full = torch.bmm(w1_selected, x_expanded.unsqueeze(-1)).squeeze(-1) # [T*A, H]
|
| 189 |
+
if lora is not None:
|
| 190 |
+
x1_full = x1_full + apply_moe_lora_fc1_flat(x_expanded, lora, flat_idxs)
|
| 191 |
+
x1, g = x1_full.chunk(2, dim=-1)
|
| 192 |
+
x1 = F.gelu(x1) * (g + 1)
|
| 193 |
+
|
| 194 |
+
# Second linear layer: [T*A, D, H] @ [T*A, H, 1] -> [T*A, D]
|
| 195 |
+
expert_outs = torch.bmm(w2_selected, x1.unsqueeze(-1)).squeeze(-1) # [T*A, D]
|
| 196 |
+
if lora is not None:
|
| 197 |
+
expert_outs = expert_outs + apply_moe_lora_fc2_flat(x1, lora, flat_idxs)
|
| 198 |
+
|
| 199 |
+
# Apply weights and reshape
|
| 200 |
+
weighted_outs = expert_outs * flat_weights.unsqueeze(-1) # [T*A, D]
|
| 201 |
+
weighted_outs = weighted_outs.view(num_tokens, top_k, C) # [T, A, D]
|
| 202 |
+
|
| 203 |
+
# Sum over experts
|
| 204 |
+
mlp_out = weighted_outs.sum(dim=1) # [T, D]
|
| 205 |
+
mlp_out = mlp_out.view(B, T, C)
|
| 206 |
+
|
| 207 |
+
return mlp_out
|
| 208 |
+
else:
|
| 209 |
+
out = x.new_zeros(x.size())
|
| 210 |
+
|
| 211 |
+
for expert_id in range(mlp_module.fc1.weight.shape[0]):
|
| 212 |
+
token_pos, which_k = (topk_idxs == expert_id).nonzero(as_tuple=True)
|
| 213 |
+
if token_pos.numel() == 0:
|
| 214 |
+
continue
|
| 215 |
+
|
| 216 |
+
x_tok = x.index_select(0, token_pos)
|
| 217 |
+
gate_tok = topk_weights[token_pos, which_k]
|
| 218 |
+
|
| 219 |
+
w1 = mlp_module.fc1.weight[expert_id]
|
| 220 |
+
h_full = F.linear(x_tok, w1)
|
| 221 |
+
if lora is not None:
|
| 222 |
+
lora_up_a = lora.up_a[expert_id]
|
| 223 |
+
lora_up_b = lora.up_b[expert_id]
|
| 224 |
+
lora_mid = F.linear(x_tok, lora_up_a)
|
| 225 |
+
h_full = h_full + F.linear(lora_mid, lora_up_b)
|
| 226 |
+
h, g = h_full.chunk(2, dim=-1)
|
| 227 |
+
h = F.gelu(h) * (g + 1)
|
| 228 |
+
w2 = mlp_module.fc2.weight[expert_id]
|
| 229 |
+
y = F.linear(h, w2)
|
| 230 |
+
if lora is not None:
|
| 231 |
+
lora_down_a = lora.down_a[expert_id]
|
| 232 |
+
lora_down_b = lora.down_b[expert_id]
|
| 233 |
+
lora_mid = F.linear(h, lora_down_a)
|
| 234 |
+
y = y + F.linear(lora_mid, lora_down_b)
|
| 235 |
+
|
| 236 |
+
y.mul_(gate_tok.unsqueeze(-1))
|
| 237 |
+
out.index_add_(0, token_pos, y)
|
| 238 |
+
|
| 239 |
+
return out.view(B, T, C)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
@dataclass
|
| 243 |
+
class AttentionWeights:
|
| 244 |
+
qkv: LinearWeights
|
| 245 |
+
proj: LinearWeights
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def attn(x: torch.Tensor, w: AttentionWeights, n_heads: int) -> torch.Tensor:
|
| 249 |
+
bsz, q_len, d_model = x.shape
|
| 250 |
+
head_dim = d_model // n_heads
|
| 251 |
+
|
| 252 |
+
q, k, v = [
|
| 253 |
+
t.view(bsz, q_len, n_heads, head_dim).transpose(1, 2)
|
| 254 |
+
for t in linear(x, w.qkv).chunk(3, dim=-1)
|
| 255 |
+
]
|
| 256 |
+
out = F.scaled_dot_product_attention(q, k, v)
|
| 257 |
+
out = out.transpose(1, 2).reshape(bsz, q_len, d_model)
|
| 258 |
+
out = linear(out, w.proj)
|
| 259 |
+
return out
|
lora.py
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import os
|
| 3 |
+
import re
|
| 4 |
+
import shutil
|
| 5 |
+
from dataclasses import dataclass
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from typing import Any, Dict, Optional, Tuple
|
| 8 |
+
from urllib.request import Request, urlopen
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
|
| 12 |
+
from .config import TextConfig
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class AdapterLoadError(RuntimeError):
|
| 16 |
+
pass
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def _cache_root() -> Path:
|
| 20 |
+
hf_hub_cache = os.environ.get("HF_HUB_CACHE")
|
| 21 |
+
if hf_hub_cache:
|
| 22 |
+
return Path(hf_hub_cache)
|
| 23 |
+
|
| 24 |
+
hf_home = os.environ.get("HF_HOME")
|
| 25 |
+
if hf_home:
|
| 26 |
+
return Path(hf_home) / "hub"
|
| 27 |
+
|
| 28 |
+
return Path("~/.cache/huggingface/hub").expanduser()
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def adapter_cache_dir() -> Path:
|
| 32 |
+
return _cache_root() / "md_finetunes"
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def normalize_adapter_id(value: Optional[str]) -> Optional[str]:
|
| 36 |
+
if not value:
|
| 37 |
+
return None
|
| 38 |
+
tail = value.split("/")[-1].strip()
|
| 39 |
+
if "@" not in tail:
|
| 40 |
+
return None
|
| 41 |
+
return tail
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def parse_adapter_id(adapter_id: str) -> Tuple[str, str]:
|
| 45 |
+
if not adapter_id or "@" not in adapter_id:
|
| 46 |
+
raise AdapterLoadError(
|
| 47 |
+
f"Invalid adapter id '{adapter_id}'. Expected 'finetune_id@step'."
|
| 48 |
+
)
|
| 49 |
+
finetune_id, step = adapter_id.split("@", 1)
|
| 50 |
+
if not finetune_id or not step:
|
| 51 |
+
raise AdapterLoadError(
|
| 52 |
+
f"Invalid adapter id '{adapter_id}'. Expected 'finetune_id@step'."
|
| 53 |
+
)
|
| 54 |
+
return finetune_id, step
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _fetch_presigned_url(finetune_id: str, step: str) -> str:
|
| 58 |
+
endpoint = os.getenv("MOONDREAM_ENDPOINT", "https://api.moondream.ai").rstrip("/")
|
| 59 |
+
api_key = os.getenv("MOONDREAM_API_KEY")
|
| 60 |
+
if not api_key:
|
| 61 |
+
raise AdapterLoadError("MOONDREAM_API_KEY is required to load finetune adapters.")
|
| 62 |
+
|
| 63 |
+
headers = {"User-Agent": "moondream-torch", "X-Moondream-Auth": api_key}
|
| 64 |
+
url = f"{endpoint}/v1/tuning/finetunes/{finetune_id}/checkpoints/{step}/download"
|
| 65 |
+
req = Request(url, headers=headers)
|
| 66 |
+
try:
|
| 67 |
+
with urlopen(req) as r:
|
| 68 |
+
payload = json.loads(r.read().decode("utf-8"))
|
| 69 |
+
except Exception as e:
|
| 70 |
+
raise AdapterLoadError(f"Failed to fetch adapter URL: {e}") from e
|
| 71 |
+
|
| 72 |
+
presigned = payload.get("url")
|
| 73 |
+
if not presigned:
|
| 74 |
+
raise AdapterLoadError("Adapter URL response missing 'url' field.")
|
| 75 |
+
return presigned
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def cached_adapter_path(adapter_id: str) -> Path:
|
| 79 |
+
finetune_id, step = parse_adapter_id(adapter_id)
|
| 80 |
+
|
| 81 |
+
cache_dir = adapter_cache_dir() / finetune_id / step
|
| 82 |
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
| 83 |
+
|
| 84 |
+
for name in ("adapter.pt", "adapter.safetensors"):
|
| 85 |
+
path = cache_dir / name
|
| 86 |
+
if path.exists() and path.stat().st_size > 0:
|
| 87 |
+
return path
|
| 88 |
+
|
| 89 |
+
presigned_url = _fetch_presigned_url(finetune_id, step)
|
| 90 |
+
dest = cache_dir / "adapter.pt"
|
| 91 |
+
|
| 92 |
+
try:
|
| 93 |
+
with urlopen(presigned_url) as r, open(dest, "wb") as f:
|
| 94 |
+
shutil.copyfileobj(r, f)
|
| 95 |
+
except Exception as e:
|
| 96 |
+
raise AdapterLoadError(f"Failed to download adapter: {e}") from e
|
| 97 |
+
return dest
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def _load_state_dict(path: Path, device: torch.device) -> Dict[str, Any]:
|
| 101 |
+
if path.suffix == ".safetensors":
|
| 102 |
+
try:
|
| 103 |
+
from safetensors.torch import safe_open
|
| 104 |
+
except Exception as e:
|
| 105 |
+
raise AdapterLoadError(
|
| 106 |
+
"safetensors is required to load .safetensors adapters."
|
| 107 |
+
) from e
|
| 108 |
+
data = {}
|
| 109 |
+
with safe_open(str(path), framework="pt") as f:
|
| 110 |
+
for key in f.keys():
|
| 111 |
+
data[key] = f.get_tensor(key).to(device=device)
|
| 112 |
+
return data
|
| 113 |
+
|
| 114 |
+
try:
|
| 115 |
+
return torch.load(path, map_location=device, weights_only=True)
|
| 116 |
+
except TypeError:
|
| 117 |
+
return torch.load(path, map_location=device)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
@dataclass
|
| 121 |
+
class DenseLoRALayer:
|
| 122 |
+
up_a: torch.Tensor
|
| 123 |
+
up_b: torch.Tensor
|
| 124 |
+
down_a: torch.Tensor
|
| 125 |
+
down_b: torch.Tensor
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
@dataclass
|
| 129 |
+
class MoELoRALayer:
|
| 130 |
+
up_a: torch.Tensor
|
| 131 |
+
up_b: torch.Tensor
|
| 132 |
+
down_a: torch.Tensor
|
| 133 |
+
down_b: torch.Tensor
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
class TextLoRA:
|
| 137 |
+
def __init__(
|
| 138 |
+
self,
|
| 139 |
+
text_config: TextConfig,
|
| 140 |
+
*,
|
| 141 |
+
rank: int,
|
| 142 |
+
max_rank: int,
|
| 143 |
+
dtype: torch.dtype,
|
| 144 |
+
device: torch.device,
|
| 145 |
+
adapter_id: Optional[str] = None,
|
| 146 |
+
) -> None:
|
| 147 |
+
if rank <= 0:
|
| 148 |
+
raise AdapterLoadError("LoRA rank must be positive.")
|
| 149 |
+
if max_rank < rank:
|
| 150 |
+
raise AdapterLoadError("max_rank must be >= rank.")
|
| 151 |
+
|
| 152 |
+
self.text_config = text_config
|
| 153 |
+
self.rank = rank
|
| 154 |
+
self.max_rank = max_rank
|
| 155 |
+
self.adapter_id = adapter_id
|
| 156 |
+
|
| 157 |
+
moe_cfg = text_config.moe
|
| 158 |
+
self.start_layer = moe_cfg.start_layer if moe_cfg else text_config.n_layers
|
| 159 |
+
|
| 160 |
+
if moe_cfg is not None:
|
| 161 |
+
self.rank_per_expert = rank // moe_cfg.experts_per_token
|
| 162 |
+
if self.rank_per_expert < 1:
|
| 163 |
+
raise AdapterLoadError(
|
| 164 |
+
f"rank ({rank}) must be >= experts_per_token ({moe_cfg.experts_per_token})"
|
| 165 |
+
)
|
| 166 |
+
self.max_rank_per_expert = max_rank // moe_cfg.experts_per_token
|
| 167 |
+
if self.max_rank_per_expert < 1:
|
| 168 |
+
raise AdapterLoadError(
|
| 169 |
+
f"max_rank ({max_rank}) must be >= experts_per_token ({moe_cfg.experts_per_token})"
|
| 170 |
+
)
|
| 171 |
+
else:
|
| 172 |
+
self.rank_per_expert = 0
|
| 173 |
+
self.max_rank_per_expert = 0
|
| 174 |
+
|
| 175 |
+
d_model = text_config.dim
|
| 176 |
+
d_ffn = text_config.ff_dim
|
| 177 |
+
|
| 178 |
+
self.dense: list[DenseLoRALayer] = []
|
| 179 |
+
for _ in range(self.start_layer):
|
| 180 |
+
self.dense.append(
|
| 181 |
+
DenseLoRALayer(
|
| 182 |
+
up_a=torch.zeros((max_rank, d_model), device=device, dtype=dtype),
|
| 183 |
+
up_b=torch.zeros((d_ffn, max_rank), device=device, dtype=dtype),
|
| 184 |
+
down_a=torch.zeros((max_rank, d_ffn), device=device, dtype=dtype),
|
| 185 |
+
down_b=torch.zeros((d_model, max_rank), device=device, dtype=dtype),
|
| 186 |
+
)
|
| 187 |
+
)
|
| 188 |
+
|
| 189 |
+
self.moe: list[MoELoRALayer] = []
|
| 190 |
+
if moe_cfg is not None:
|
| 191 |
+
num_experts = moe_cfg.num_experts
|
| 192 |
+
d_expert = moe_cfg.expert_inner_dim
|
| 193 |
+
for _ in range(text_config.n_layers - self.start_layer):
|
| 194 |
+
self.moe.append(
|
| 195 |
+
MoELoRALayer(
|
| 196 |
+
up_a=torch.zeros(
|
| 197 |
+
(num_experts, self.max_rank_per_expert, d_model),
|
| 198 |
+
device=device,
|
| 199 |
+
dtype=dtype,
|
| 200 |
+
),
|
| 201 |
+
up_b=torch.zeros(
|
| 202 |
+
(num_experts, d_expert * 2, self.max_rank_per_expert),
|
| 203 |
+
device=device,
|
| 204 |
+
dtype=dtype,
|
| 205 |
+
),
|
| 206 |
+
down_a=torch.zeros(
|
| 207 |
+
(num_experts, self.max_rank_per_expert, d_expert),
|
| 208 |
+
device=device,
|
| 209 |
+
dtype=dtype,
|
| 210 |
+
),
|
| 211 |
+
down_b=torch.zeros(
|
| 212 |
+
(num_experts, d_model, self.max_rank_per_expert),
|
| 213 |
+
device=device,
|
| 214 |
+
dtype=dtype,
|
| 215 |
+
),
|
| 216 |
+
)
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
def dense_layer(self, layer_idx: int) -> Optional[DenseLoRALayer]:
|
| 220 |
+
if layer_idx < len(self.dense):
|
| 221 |
+
return self.dense[layer_idx]
|
| 222 |
+
return None
|
| 223 |
+
|
| 224 |
+
def moe_layer(self, layer_idx: int) -> Optional[MoELoRALayer]:
|
| 225 |
+
moe_idx = layer_idx - self.start_layer
|
| 226 |
+
if 0 <= moe_idx < len(self.moe):
|
| 227 |
+
return self.moe[moe_idx]
|
| 228 |
+
return None
|
| 229 |
+
|
| 230 |
+
@staticmethod
|
| 231 |
+
def _pad_axis(tensor: torch.Tensor, target: int, axis: int) -> torch.Tensor:
|
| 232 |
+
if tensor.shape[axis] == target:
|
| 233 |
+
return tensor
|
| 234 |
+
if tensor.shape[axis] > target:
|
| 235 |
+
raise AdapterLoadError(
|
| 236 |
+
f"LoRA tensor rank {tensor.shape[axis]} exceeds max {target}"
|
| 237 |
+
)
|
| 238 |
+
pad_shape = list(tensor.shape)
|
| 239 |
+
pad_shape[axis] = target - tensor.shape[axis]
|
| 240 |
+
pad = torch.zeros(pad_shape, device=tensor.device, dtype=tensor.dtype)
|
| 241 |
+
return torch.cat([tensor, pad], dim=axis)
|
| 242 |
+
|
| 243 |
+
@staticmethod
|
| 244 |
+
def detect_rank(state_dict: Dict[str, Any], text_config: TextConfig) -> int:
|
| 245 |
+
for key, tensor in state_dict.items():
|
| 246 |
+
if "dense" in key and "up_a" in key:
|
| 247 |
+
return int(tensor.shape[0])
|
| 248 |
+
for key, tensor in state_dict.items():
|
| 249 |
+
if "moe" in key and "up_a" in key:
|
| 250 |
+
rank_per_expert = int(tensor.shape[1])
|
| 251 |
+
moe_cfg = text_config.moe
|
| 252 |
+
if moe_cfg:
|
| 253 |
+
return rank_per_expert * moe_cfg.experts_per_token
|
| 254 |
+
return rank_per_expert
|
| 255 |
+
raise AdapterLoadError("Could not detect LoRA rank from state dict.")
|
| 256 |
+
|
| 257 |
+
@classmethod
|
| 258 |
+
def from_state_dict(
|
| 259 |
+
cls,
|
| 260 |
+
state_dict: Dict[str, Any],
|
| 261 |
+
*,
|
| 262 |
+
text_config: TextConfig,
|
| 263 |
+
max_rank: int,
|
| 264 |
+
dtype: torch.dtype,
|
| 265 |
+
device: torch.device,
|
| 266 |
+
adapter_id: Optional[str] = None,
|
| 267 |
+
) -> "TextLoRA":
|
| 268 |
+
rank = cls.detect_rank(state_dict, text_config)
|
| 269 |
+
if rank > max_rank:
|
| 270 |
+
raise AdapterLoadError(
|
| 271 |
+
f"Adapter rank ({rank}) exceeds max_rank ({max_rank})."
|
| 272 |
+
)
|
| 273 |
+
|
| 274 |
+
lora = cls(
|
| 275 |
+
text_config,
|
| 276 |
+
rank=rank,
|
| 277 |
+
max_rank=max_rank,
|
| 278 |
+
dtype=dtype,
|
| 279 |
+
device=device,
|
| 280 |
+
adapter_id=adapter_id,
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
dense_seen = set()
|
| 284 |
+
moe_seen = set()
|
| 285 |
+
|
| 286 |
+
pattern = re.compile(r"(dense|moe)\.(\d+)\.(up_a|up_b|down_a|down_b)$")
|
| 287 |
+
for key, tensor in state_dict.items():
|
| 288 |
+
match = pattern.search(key)
|
| 289 |
+
if not match:
|
| 290 |
+
continue
|
| 291 |
+
kind, idx_str, name = match.group(1), match.group(2), match.group(3)
|
| 292 |
+
idx = int(idx_str)
|
| 293 |
+
arr = tensor.to(device=device, dtype=dtype)
|
| 294 |
+
|
| 295 |
+
if kind == "dense":
|
| 296 |
+
if idx >= len(lora.dense):
|
| 297 |
+
raise AdapterLoadError(f"Dense LoRA layer index {idx} out of range.")
|
| 298 |
+
layer = lora.dense[idx]
|
| 299 |
+
if name in ("up_a", "down_a"):
|
| 300 |
+
arr = cls._pad_axis(arr, lora.max_rank, axis=0)
|
| 301 |
+
else:
|
| 302 |
+
arr = cls._pad_axis(arr, lora.max_rank, axis=1)
|
| 303 |
+
setattr(layer, name, arr)
|
| 304 |
+
dense_seen.add((idx, name))
|
| 305 |
+
else:
|
| 306 |
+
if idx >= len(lora.moe):
|
| 307 |
+
raise AdapterLoadError(f"MoE LoRA layer index {idx} out of range.")
|
| 308 |
+
layer = lora.moe[idx]
|
| 309 |
+
if name in ("up_a", "down_a"):
|
| 310 |
+
arr = cls._pad_axis(arr, lora.max_rank_per_expert, axis=1)
|
| 311 |
+
else:
|
| 312 |
+
arr = cls._pad_axis(arr, lora.max_rank_per_expert, axis=2)
|
| 313 |
+
setattr(layer, name, arr)
|
| 314 |
+
moe_seen.add((idx, name))
|
| 315 |
+
|
| 316 |
+
for layer_idx in range(len(lora.dense)):
|
| 317 |
+
for name in ("up_a", "up_b", "down_a", "down_b"):
|
| 318 |
+
if (layer_idx, name) not in dense_seen:
|
| 319 |
+
raise AdapterLoadError(
|
| 320 |
+
f"Adapter missing dense LoRA for layer {layer_idx} ({name})."
|
| 321 |
+
)
|
| 322 |
+
for layer_idx in range(len(lora.moe)):
|
| 323 |
+
for name in ("up_a", "up_b", "down_a", "down_b"):
|
| 324 |
+
if (layer_idx, name) not in moe_seen:
|
| 325 |
+
raise AdapterLoadError(
|
| 326 |
+
f"Adapter missing MoE LoRA for layer {layer_idx} ({name})."
|
| 327 |
+
)
|
| 328 |
+
|
| 329 |
+
return lora
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
def select_layer_lora(
|
| 333 |
+
lora: Optional[TextLoRA], layer_idx: int, *, is_moe: bool
|
| 334 |
+
) -> Optional[object]:
|
| 335 |
+
if lora is None:
|
| 336 |
+
return None
|
| 337 |
+
return lora.moe_layer(layer_idx) if is_moe else lora.dense_layer(layer_idx)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
def apply_dense_lora(
|
| 341 |
+
x: torch.Tensor, lora_a: torch.Tensor, lora_b: torch.Tensor
|
| 342 |
+
) -> torch.Tensor:
|
| 343 |
+
b, t, c = x.shape
|
| 344 |
+
x_flat = x.reshape(-1, c)
|
| 345 |
+
lora_mid = torch.matmul(x_flat, lora_a.t())
|
| 346 |
+
lora_out = torch.matmul(lora_mid, lora_b.t())
|
| 347 |
+
return lora_out.reshape(b, t, -1)
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
def apply_moe_lora_fc1_flat(
|
| 351 |
+
x_expanded: torch.Tensor, lora: MoELoRALayer, flat_idxs: torch.Tensor
|
| 352 |
+
) -> torch.Tensor:
|
| 353 |
+
lora_up_a = lora.up_a[flat_idxs]
|
| 354 |
+
lora_up_b = lora.up_b[flat_idxs]
|
| 355 |
+
lora_mid = torch.bmm(lora_up_a, x_expanded.unsqueeze(-1)).squeeze(-1)
|
| 356 |
+
lora_up = torch.bmm(lora_up_b, lora_mid.unsqueeze(-1)).squeeze(-1)
|
| 357 |
+
return lora_up
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
def apply_moe_lora_fc2_flat(
|
| 361 |
+
h: torch.Tensor, lora: MoELoRALayer, flat_idxs: torch.Tensor
|
| 362 |
+
) -> torch.Tensor:
|
| 363 |
+
lora_down_a = lora.down_a[flat_idxs]
|
| 364 |
+
lora_down_b = lora.down_b[flat_idxs]
|
| 365 |
+
lora_mid = torch.bmm(lora_down_a, h.unsqueeze(-1)).squeeze(-1)
|
| 366 |
+
lora_down = torch.bmm(lora_down_b, lora_mid.unsqueeze(-1)).squeeze(-1)
|
| 367 |
+
return lora_down
|
| 368 |
+
|
| 369 |
+
|
| 370 |
+
_ADAPTER_CACHE: Dict[Tuple[str, str, str, Tuple], TextLoRA] = {}
|
| 371 |
+
_CACHE_ORDER: list[Tuple[str, str, str, Tuple]] = []
|
| 372 |
+
_CACHE_SIZE = 8
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
def _config_key(text_config: TextConfig) -> Tuple:
|
| 376 |
+
moe = text_config.moe
|
| 377 |
+
moe_key = None
|
| 378 |
+
if moe is not None:
|
| 379 |
+
moe_key = (
|
| 380 |
+
moe.num_experts,
|
| 381 |
+
moe.start_layer,
|
| 382 |
+
moe.experts_per_token,
|
| 383 |
+
moe.expert_inner_dim,
|
| 384 |
+
)
|
| 385 |
+
return (
|
| 386 |
+
text_config.dim,
|
| 387 |
+
text_config.ff_dim,
|
| 388 |
+
text_config.n_layers,
|
| 389 |
+
moe_key,
|
| 390 |
+
)
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
def load_adapter(
|
| 394 |
+
adapter_id: Optional[str],
|
| 395 |
+
*,
|
| 396 |
+
text_config: TextConfig,
|
| 397 |
+
device: torch.device,
|
| 398 |
+
dtype: torch.dtype,
|
| 399 |
+
max_rank: int = 16,
|
| 400 |
+
) -> Optional[TextLoRA]:
|
| 401 |
+
if adapter_id is None:
|
| 402 |
+
return None
|
| 403 |
+
|
| 404 |
+
adapter_id = normalize_adapter_id(adapter_id)
|
| 405 |
+
if adapter_id is None:
|
| 406 |
+
return None
|
| 407 |
+
|
| 408 |
+
key = (adapter_id, str(device), str(dtype), _config_key(text_config))
|
| 409 |
+
cached = _ADAPTER_CACHE.get(key)
|
| 410 |
+
if cached is not None:
|
| 411 |
+
return cached
|
| 412 |
+
|
| 413 |
+
path = cached_adapter_path(adapter_id)
|
| 414 |
+
checkpoint = _load_state_dict(path, device)
|
| 415 |
+
if not isinstance(checkpoint, dict):
|
| 416 |
+
raise AdapterLoadError("Invalid adapter checkpoint format.")
|
| 417 |
+
|
| 418 |
+
state_dict = checkpoint.get("lora_state_dict", checkpoint)
|
| 419 |
+
if not isinstance(state_dict, dict):
|
| 420 |
+
raise AdapterLoadError("Adapter checkpoint missing lora_state_dict.")
|
| 421 |
+
|
| 422 |
+
lora = TextLoRA.from_state_dict(
|
| 423 |
+
state_dict,
|
| 424 |
+
text_config=text_config,
|
| 425 |
+
max_rank=max_rank,
|
| 426 |
+
dtype=dtype,
|
| 427 |
+
device=device,
|
| 428 |
+
adapter_id=adapter_id,
|
| 429 |
+
)
|
| 430 |
+
|
| 431 |
+
_ADAPTER_CACHE[key] = lora
|
| 432 |
+
_CACHE_ORDER.append(key)
|
| 433 |
+
if len(_CACHE_ORDER) > _CACHE_SIZE:
|
| 434 |
+
old = _CACHE_ORDER.pop(0)
|
| 435 |
+
_ADAPTER_CACHE.pop(old, None)
|
| 436 |
+
|
| 437 |
+
return lora
|
model-00001-of-00004.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fd4b3d0d6daae9c4212056cd64f02f408ff083bbb0244114eecd05fcba30037e
|
| 3 |
+
size 4907406296
|
model-00002-of-00004.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7cf6d17391db58801b61173510ba629875679dbcbe4bfd3cb38ac0958b3c70a0
|
| 3 |
+
size 4736548872
|
model-00003-of-00004.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f4391c6d6b46ed49aa00afddf1f7df9dd0845cbc681fdaf424e727b01ea2d3e4
|
| 3 |
+
size 4502742464
|
model-00004-of-00004.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6af14858bdd7cdea5d19d786726e48434b02a3c0c52a771a0f25b6a8ca640187
|
| 3 |
+
size 4390620392
|
model.safetensors.index.json
ADDED
|
@@ -0,0 +1,670 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"metadata": {
|
| 3 |
+
"total_parameters": 9268626928,
|
| 4 |
+
"total_size": 18537253856
|
| 5 |
+
},
|
| 6 |
+
"weight_map": {
|
| 7 |
+
"model.region.coord_decoder.bias": "modelv2-00004-of-00004.safetensors",
|
| 8 |
+
"model.region.coord_decoder.weight": "modelv2-00004-of-00004.safetensors",
|
| 9 |
+
"model.region.coord_encoder.bias": "modelv2-00004-of-00004.safetensors",
|
| 10 |
+
"model.region.coord_encoder.weight": "modelv2-00004-of-00004.safetensors",
|
| 11 |
+
"model.region.coord_features": "modelv2-00004-of-00004.safetensors",
|
| 12 |
+
"model.region.ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 13 |
+
"model.region.ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 14 |
+
"model.region.size_decoder.bias": "modelv2-00004-of-00004.safetensors",
|
| 15 |
+
"model.region.size_decoder.weight": "modelv2-00004-of-00004.safetensors",
|
| 16 |
+
"model.region.size_encoder.bias": "modelv2-00004-of-00004.safetensors",
|
| 17 |
+
"model.region.size_encoder.weight": "modelv2-00004-of-00004.safetensors",
|
| 18 |
+
"model.region.size_features": "modelv2-00004-of-00004.safetensors",
|
| 19 |
+
"model.text.blocks.0.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 20 |
+
"model.text.blocks.0.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 21 |
+
"model.text.blocks.0.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 22 |
+
"model.text.blocks.0.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 23 |
+
"model.text.blocks.0.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 24 |
+
"model.text.blocks.0.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 25 |
+
"model.text.blocks.0.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 26 |
+
"model.text.blocks.0.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 27 |
+
"model.text.blocks.0.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 28 |
+
"model.text.blocks.0.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 29 |
+
"model.text.blocks.0.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 30 |
+
"model.text.blocks.0.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 31 |
+
"model.text.blocks.0.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 32 |
+
"model.text.blocks.1.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 33 |
+
"model.text.blocks.1.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 34 |
+
"model.text.blocks.1.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 35 |
+
"model.text.blocks.1.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 36 |
+
"model.text.blocks.1.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 37 |
+
"model.text.blocks.1.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 38 |
+
"model.text.blocks.1.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 39 |
+
"model.text.blocks.1.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 40 |
+
"model.text.blocks.1.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 41 |
+
"model.text.blocks.1.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 42 |
+
"model.text.blocks.1.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 43 |
+
"model.text.blocks.1.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 44 |
+
"model.text.blocks.1.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 45 |
+
"model.text.blocks.10.attn.proj.bias": "modelv2-00002-of-00004.safetensors",
|
| 46 |
+
"model.text.blocks.10.attn.proj.weight": "modelv2-00002-of-00004.safetensors",
|
| 47 |
+
"model.text.blocks.10.attn.qkv.bias": "modelv2-00002-of-00004.safetensors",
|
| 48 |
+
"model.text.blocks.10.attn.qkv.weight": "modelv2-00002-of-00004.safetensors",
|
| 49 |
+
"model.text.blocks.10.attn.tau.alpha": "modelv2-00002-of-00004.safetensors",
|
| 50 |
+
"model.text.blocks.10.attn.tau.wq": "modelv2-00002-of-00004.safetensors",
|
| 51 |
+
"model.text.blocks.10.attn.tau.wv": "modelv2-00002-of-00004.safetensors",
|
| 52 |
+
"model.text.blocks.10.ln.bias": "modelv2-00002-of-00004.safetensors",
|
| 53 |
+
"model.text.blocks.10.ln.weight": "modelv2-00002-of-00004.safetensors",
|
| 54 |
+
"model.text.blocks.10.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 55 |
+
"model.text.blocks.10.mlp.fc2.weight": "modelv2-00002-of-00004.safetensors",
|
| 56 |
+
"model.text.blocks.10.mlp.router.bias": "modelv2-00002-of-00004.safetensors",
|
| 57 |
+
"model.text.blocks.10.mlp.router.weight": "modelv2-00002-of-00004.safetensors",
|
| 58 |
+
"model.text.blocks.11.attn.proj.bias": "modelv2-00002-of-00004.safetensors",
|
| 59 |
+
"model.text.blocks.11.attn.proj.weight": "modelv2-00002-of-00004.safetensors",
|
| 60 |
+
"model.text.blocks.11.attn.qkv.bias": "modelv2-00002-of-00004.safetensors",
|
| 61 |
+
"model.text.blocks.11.attn.qkv.weight": "modelv2-00002-of-00004.safetensors",
|
| 62 |
+
"model.text.blocks.11.attn.tau.alpha": "modelv2-00002-of-00004.safetensors",
|
| 63 |
+
"model.text.blocks.11.attn.tau.wq": "modelv2-00002-of-00004.safetensors",
|
| 64 |
+
"model.text.blocks.11.attn.tau.wv": "modelv2-00002-of-00004.safetensors",
|
| 65 |
+
"model.text.blocks.11.ln.bias": "modelv2-00002-of-00004.safetensors",
|
| 66 |
+
"model.text.blocks.11.ln.weight": "modelv2-00002-of-00004.safetensors",
|
| 67 |
+
"model.text.blocks.11.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 68 |
+
"model.text.blocks.11.mlp.fc2.weight": "modelv2-00002-of-00004.safetensors",
|
| 69 |
+
"model.text.blocks.11.mlp.router.bias": "modelv2-00002-of-00004.safetensors",
|
| 70 |
+
"model.text.blocks.11.mlp.router.weight": "modelv2-00002-of-00004.safetensors",
|
| 71 |
+
"model.text.blocks.12.attn.proj.bias": "modelv2-00002-of-00004.safetensors",
|
| 72 |
+
"model.text.blocks.12.attn.proj.weight": "modelv2-00002-of-00004.safetensors",
|
| 73 |
+
"model.text.blocks.12.attn.qkv.bias": "modelv2-00002-of-00004.safetensors",
|
| 74 |
+
"model.text.blocks.12.attn.qkv.weight": "modelv2-00002-of-00004.safetensors",
|
| 75 |
+
"model.text.blocks.12.attn.tau.alpha": "modelv2-00002-of-00004.safetensors",
|
| 76 |
+
"model.text.blocks.12.attn.tau.wq": "modelv2-00002-of-00004.safetensors",
|
| 77 |
+
"model.text.blocks.12.attn.tau.wv": "modelv2-00002-of-00004.safetensors",
|
| 78 |
+
"model.text.blocks.12.ln.bias": "modelv2-00002-of-00004.safetensors",
|
| 79 |
+
"model.text.blocks.12.ln.weight": "modelv2-00002-of-00004.safetensors",
|
| 80 |
+
"model.text.blocks.12.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 81 |
+
"model.text.blocks.12.mlp.fc2.weight": "modelv2-00002-of-00004.safetensors",
|
| 82 |
+
"model.text.blocks.12.mlp.router.bias": "modelv2-00002-of-00004.safetensors",
|
| 83 |
+
"model.text.blocks.12.mlp.router.weight": "modelv2-00002-of-00004.safetensors",
|
| 84 |
+
"model.text.blocks.13.attn.proj.bias": "modelv2-00002-of-00004.safetensors",
|
| 85 |
+
"model.text.blocks.13.attn.proj.weight": "modelv2-00002-of-00004.safetensors",
|
| 86 |
+
"model.text.blocks.13.attn.qkv.bias": "modelv2-00002-of-00004.safetensors",
|
| 87 |
+
"model.text.blocks.13.attn.qkv.weight": "modelv2-00002-of-00004.safetensors",
|
| 88 |
+
"model.text.blocks.13.attn.tau.alpha": "modelv2-00002-of-00004.safetensors",
|
| 89 |
+
"model.text.blocks.13.attn.tau.wq": "modelv2-00002-of-00004.safetensors",
|
| 90 |
+
"model.text.blocks.13.attn.tau.wv": "modelv2-00002-of-00004.safetensors",
|
| 91 |
+
"model.text.blocks.13.ln.bias": "modelv2-00002-of-00004.safetensors",
|
| 92 |
+
"model.text.blocks.13.ln.weight": "modelv2-00002-of-00004.safetensors",
|
| 93 |
+
"model.text.blocks.13.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 94 |
+
"model.text.blocks.13.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 95 |
+
"model.text.blocks.13.mlp.router.bias": "modelv2-00002-of-00004.safetensors",
|
| 96 |
+
"model.text.blocks.13.mlp.router.weight": "modelv2-00002-of-00004.safetensors",
|
| 97 |
+
"model.text.blocks.14.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 98 |
+
"model.text.blocks.14.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 99 |
+
"model.text.blocks.14.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 100 |
+
"model.text.blocks.14.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 101 |
+
"model.text.blocks.14.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 102 |
+
"model.text.blocks.14.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 103 |
+
"model.text.blocks.14.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 104 |
+
"model.text.blocks.14.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 105 |
+
"model.text.blocks.14.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 106 |
+
"model.text.blocks.14.mlp.fc1.weight": "modelv2-00003-of-00004.safetensors",
|
| 107 |
+
"model.text.blocks.14.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 108 |
+
"model.text.blocks.14.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 109 |
+
"model.text.blocks.14.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 110 |
+
"model.text.blocks.15.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 111 |
+
"model.text.blocks.15.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 112 |
+
"model.text.blocks.15.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 113 |
+
"model.text.blocks.15.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 114 |
+
"model.text.blocks.15.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 115 |
+
"model.text.blocks.15.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 116 |
+
"model.text.blocks.15.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 117 |
+
"model.text.blocks.15.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 118 |
+
"model.text.blocks.15.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 119 |
+
"model.text.blocks.15.mlp.fc1.weight": "modelv2-00003-of-00004.safetensors",
|
| 120 |
+
"model.text.blocks.15.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 121 |
+
"model.text.blocks.15.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 122 |
+
"model.text.blocks.15.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 123 |
+
"model.text.blocks.16.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 124 |
+
"model.text.blocks.16.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 125 |
+
"model.text.blocks.16.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 126 |
+
"model.text.blocks.16.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 127 |
+
"model.text.blocks.16.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 128 |
+
"model.text.blocks.16.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 129 |
+
"model.text.blocks.16.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 130 |
+
"model.text.blocks.16.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 131 |
+
"model.text.blocks.16.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 132 |
+
"model.text.blocks.16.mlp.fc1.weight": "modelv2-00003-of-00004.safetensors",
|
| 133 |
+
"model.text.blocks.16.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 134 |
+
"model.text.blocks.16.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 135 |
+
"model.text.blocks.16.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 136 |
+
"model.text.blocks.17.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 137 |
+
"model.text.blocks.17.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 138 |
+
"model.text.blocks.17.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 139 |
+
"model.text.blocks.17.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 140 |
+
"model.text.blocks.17.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 141 |
+
"model.text.blocks.17.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 142 |
+
"model.text.blocks.17.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 143 |
+
"model.text.blocks.17.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 144 |
+
"model.text.blocks.17.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 145 |
+
"model.text.blocks.17.mlp.fc1.weight": "modelv2-00003-of-00004.safetensors",
|
| 146 |
+
"model.text.blocks.17.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 147 |
+
"model.text.blocks.17.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 148 |
+
"model.text.blocks.17.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 149 |
+
"model.text.blocks.18.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 150 |
+
"model.text.blocks.18.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 151 |
+
"model.text.blocks.18.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 152 |
+
"model.text.blocks.18.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 153 |
+
"model.text.blocks.18.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 154 |
+
"model.text.blocks.18.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 155 |
+
"model.text.blocks.18.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 156 |
+
"model.text.blocks.18.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 157 |
+
"model.text.blocks.18.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 158 |
+
"model.text.blocks.18.mlp.fc1.weight": "modelv2-00003-of-00004.safetensors",
|
| 159 |
+
"model.text.blocks.18.mlp.fc2.weight": "modelv2-00003-of-00004.safetensors",
|
| 160 |
+
"model.text.blocks.18.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 161 |
+
"model.text.blocks.18.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 162 |
+
"model.text.blocks.19.attn.proj.bias": "modelv2-00003-of-00004.safetensors",
|
| 163 |
+
"model.text.blocks.19.attn.proj.weight": "modelv2-00003-of-00004.safetensors",
|
| 164 |
+
"model.text.blocks.19.attn.qkv.bias": "modelv2-00003-of-00004.safetensors",
|
| 165 |
+
"model.text.blocks.19.attn.qkv.weight": "modelv2-00003-of-00004.safetensors",
|
| 166 |
+
"model.text.blocks.19.attn.tau.alpha": "modelv2-00003-of-00004.safetensors",
|
| 167 |
+
"model.text.blocks.19.attn.tau.wq": "modelv2-00003-of-00004.safetensors",
|
| 168 |
+
"model.text.blocks.19.attn.tau.wv": "modelv2-00003-of-00004.safetensors",
|
| 169 |
+
"model.text.blocks.19.ln.bias": "modelv2-00003-of-00004.safetensors",
|
| 170 |
+
"model.text.blocks.19.ln.weight": "modelv2-00003-of-00004.safetensors",
|
| 171 |
+
"model.text.blocks.19.mlp.fc1.weight": "modelv2-00004-of-00004.safetensors",
|
| 172 |
+
"model.text.blocks.19.mlp.fc2.weight": "modelv2-00004-of-00004.safetensors",
|
| 173 |
+
"model.text.blocks.19.mlp.router.bias": "modelv2-00003-of-00004.safetensors",
|
| 174 |
+
"model.text.blocks.19.mlp.router.weight": "modelv2-00003-of-00004.safetensors",
|
| 175 |
+
"model.text.blocks.2.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 176 |
+
"model.text.blocks.2.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 177 |
+
"model.text.blocks.2.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 178 |
+
"model.text.blocks.2.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 179 |
+
"model.text.blocks.2.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 180 |
+
"model.text.blocks.2.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 181 |
+
"model.text.blocks.2.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 182 |
+
"model.text.blocks.2.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 183 |
+
"model.text.blocks.2.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 184 |
+
"model.text.blocks.2.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 185 |
+
"model.text.blocks.2.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 186 |
+
"model.text.blocks.2.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 187 |
+
"model.text.blocks.2.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 188 |
+
"model.text.blocks.20.attn.proj.bias": "modelv2-00004-of-00004.safetensors",
|
| 189 |
+
"model.text.blocks.20.attn.proj.weight": "modelv2-00004-of-00004.safetensors",
|
| 190 |
+
"model.text.blocks.20.attn.qkv.bias": "modelv2-00004-of-00004.safetensors",
|
| 191 |
+
"model.text.blocks.20.attn.qkv.weight": "modelv2-00004-of-00004.safetensors",
|
| 192 |
+
"model.text.blocks.20.attn.tau.alpha": "modelv2-00004-of-00004.safetensors",
|
| 193 |
+
"model.text.blocks.20.attn.tau.wq": "modelv2-00004-of-00004.safetensors",
|
| 194 |
+
"model.text.blocks.20.attn.tau.wv": "modelv2-00004-of-00004.safetensors",
|
| 195 |
+
"model.text.blocks.20.ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 196 |
+
"model.text.blocks.20.ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 197 |
+
"model.text.blocks.20.mlp.fc1.weight": "modelv2-00004-of-00004.safetensors",
|
| 198 |
+
"model.text.blocks.20.mlp.fc2.weight": "modelv2-00004-of-00004.safetensors",
|
| 199 |
+
"model.text.blocks.20.mlp.router.bias": "modelv2-00004-of-00004.safetensors",
|
| 200 |
+
"model.text.blocks.20.mlp.router.weight": "modelv2-00004-of-00004.safetensors",
|
| 201 |
+
"model.text.blocks.21.attn.proj.bias": "modelv2-00004-of-00004.safetensors",
|
| 202 |
+
"model.text.blocks.21.attn.proj.weight": "modelv2-00004-of-00004.safetensors",
|
| 203 |
+
"model.text.blocks.21.attn.qkv.bias": "modelv2-00004-of-00004.safetensors",
|
| 204 |
+
"model.text.blocks.21.attn.qkv.weight": "modelv2-00004-of-00004.safetensors",
|
| 205 |
+
"model.text.blocks.21.attn.tau.alpha": "modelv2-00004-of-00004.safetensors",
|
| 206 |
+
"model.text.blocks.21.attn.tau.wq": "modelv2-00004-of-00004.safetensors",
|
| 207 |
+
"model.text.blocks.21.attn.tau.wv": "modelv2-00004-of-00004.safetensors",
|
| 208 |
+
"model.text.blocks.21.ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 209 |
+
"model.text.blocks.21.ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 210 |
+
"model.text.blocks.21.mlp.fc1.weight": "modelv2-00004-of-00004.safetensors",
|
| 211 |
+
"model.text.blocks.21.mlp.fc2.weight": "modelv2-00004-of-00004.safetensors",
|
| 212 |
+
"model.text.blocks.21.mlp.router.bias": "modelv2-00004-of-00004.safetensors",
|
| 213 |
+
"model.text.blocks.21.mlp.router.weight": "modelv2-00004-of-00004.safetensors",
|
| 214 |
+
"model.text.blocks.22.attn.proj.bias": "modelv2-00004-of-00004.safetensors",
|
| 215 |
+
"model.text.blocks.22.attn.proj.weight": "modelv2-00004-of-00004.safetensors",
|
| 216 |
+
"model.text.blocks.22.attn.qkv.bias": "modelv2-00004-of-00004.safetensors",
|
| 217 |
+
"model.text.blocks.22.attn.qkv.weight": "modelv2-00004-of-00004.safetensors",
|
| 218 |
+
"model.text.blocks.22.attn.tau.alpha": "modelv2-00004-of-00004.safetensors",
|
| 219 |
+
"model.text.blocks.22.attn.tau.wq": "modelv2-00004-of-00004.safetensors",
|
| 220 |
+
"model.text.blocks.22.attn.tau.wv": "modelv2-00004-of-00004.safetensors",
|
| 221 |
+
"model.text.blocks.22.ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 222 |
+
"model.text.blocks.22.ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 223 |
+
"model.text.blocks.22.mlp.fc1.weight": "modelv2-00004-of-00004.safetensors",
|
| 224 |
+
"model.text.blocks.22.mlp.fc2.weight": "modelv2-00004-of-00004.safetensors",
|
| 225 |
+
"model.text.blocks.22.mlp.router.bias": "modelv2-00004-of-00004.safetensors",
|
| 226 |
+
"model.text.blocks.22.mlp.router.weight": "modelv2-00004-of-00004.safetensors",
|
| 227 |
+
"model.text.blocks.23.attn.proj.bias": "modelv2-00004-of-00004.safetensors",
|
| 228 |
+
"model.text.blocks.23.attn.proj.weight": "modelv2-00004-of-00004.safetensors",
|
| 229 |
+
"model.text.blocks.23.attn.qkv.bias": "modelv2-00004-of-00004.safetensors",
|
| 230 |
+
"model.text.blocks.23.attn.qkv.weight": "modelv2-00004-of-00004.safetensors",
|
| 231 |
+
"model.text.blocks.23.attn.tau.alpha": "modelv2-00004-of-00004.safetensors",
|
| 232 |
+
"model.text.blocks.23.attn.tau.wq": "modelv2-00004-of-00004.safetensors",
|
| 233 |
+
"model.text.blocks.23.attn.tau.wv": "modelv2-00004-of-00004.safetensors",
|
| 234 |
+
"model.text.blocks.23.ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 235 |
+
"model.text.blocks.23.ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 236 |
+
"model.text.blocks.23.mlp.fc1.weight": "modelv2-00004-of-00004.safetensors",
|
| 237 |
+
"model.text.blocks.23.mlp.fc2.weight": "modelv2-00004-of-00004.safetensors",
|
| 238 |
+
"model.text.blocks.23.mlp.router.bias": "modelv2-00004-of-00004.safetensors",
|
| 239 |
+
"model.text.blocks.23.mlp.router.weight": "modelv2-00004-of-00004.safetensors",
|
| 240 |
+
"model.text.blocks.3.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 241 |
+
"model.text.blocks.3.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 242 |
+
"model.text.blocks.3.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 243 |
+
"model.text.blocks.3.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 244 |
+
"model.text.blocks.3.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 245 |
+
"model.text.blocks.3.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 246 |
+
"model.text.blocks.3.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 247 |
+
"model.text.blocks.3.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 248 |
+
"model.text.blocks.3.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 249 |
+
"model.text.blocks.3.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 250 |
+
"model.text.blocks.3.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 251 |
+
"model.text.blocks.3.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 252 |
+
"model.text.blocks.3.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 253 |
+
"model.text.blocks.4.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 254 |
+
"model.text.blocks.4.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 255 |
+
"model.text.blocks.4.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 256 |
+
"model.text.blocks.4.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 257 |
+
"model.text.blocks.4.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 258 |
+
"model.text.blocks.4.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 259 |
+
"model.text.blocks.4.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 260 |
+
"model.text.blocks.4.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 261 |
+
"model.text.blocks.4.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 262 |
+
"model.text.blocks.4.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 263 |
+
"model.text.blocks.4.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 264 |
+
"model.text.blocks.4.mlp.router.bias": "modelv2-00001-of-00004.safetensors",
|
| 265 |
+
"model.text.blocks.4.mlp.router.weight": "modelv2-00001-of-00004.safetensors",
|
| 266 |
+
"model.text.blocks.5.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 267 |
+
"model.text.blocks.5.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 268 |
+
"model.text.blocks.5.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 269 |
+
"model.text.blocks.5.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 270 |
+
"model.text.blocks.5.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 271 |
+
"model.text.blocks.5.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 272 |
+
"model.text.blocks.5.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 273 |
+
"model.text.blocks.5.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 274 |
+
"model.text.blocks.5.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 275 |
+
"model.text.blocks.5.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 276 |
+
"model.text.blocks.5.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 277 |
+
"model.text.blocks.5.mlp.router.bias": "modelv2-00001-of-00004.safetensors",
|
| 278 |
+
"model.text.blocks.5.mlp.router.weight": "modelv2-00001-of-00004.safetensors",
|
| 279 |
+
"model.text.blocks.6.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 280 |
+
"model.text.blocks.6.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 281 |
+
"model.text.blocks.6.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 282 |
+
"model.text.blocks.6.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 283 |
+
"model.text.blocks.6.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 284 |
+
"model.text.blocks.6.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 285 |
+
"model.text.blocks.6.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 286 |
+
"model.text.blocks.6.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 287 |
+
"model.text.blocks.6.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 288 |
+
"model.text.blocks.6.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 289 |
+
"model.text.blocks.6.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 290 |
+
"model.text.blocks.6.mlp.router.bias": "modelv2-00001-of-00004.safetensors",
|
| 291 |
+
"model.text.blocks.6.mlp.router.weight": "modelv2-00001-of-00004.safetensors",
|
| 292 |
+
"model.text.blocks.7.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 293 |
+
"model.text.blocks.7.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 294 |
+
"model.text.blocks.7.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 295 |
+
"model.text.blocks.7.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 296 |
+
"model.text.blocks.7.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 297 |
+
"model.text.blocks.7.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 298 |
+
"model.text.blocks.7.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 299 |
+
"model.text.blocks.7.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 300 |
+
"model.text.blocks.7.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 301 |
+
"model.text.blocks.7.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 302 |
+
"model.text.blocks.7.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 303 |
+
"model.text.blocks.7.mlp.router.bias": "modelv2-00001-of-00004.safetensors",
|
| 304 |
+
"model.text.blocks.7.mlp.router.weight": "modelv2-00001-of-00004.safetensors",
|
| 305 |
+
"model.text.blocks.8.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 306 |
+
"model.text.blocks.8.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 307 |
+
"model.text.blocks.8.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 308 |
+
"model.text.blocks.8.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 309 |
+
"model.text.blocks.8.attn.tau.alpha": "modelv2-00001-of-00004.safetensors",
|
| 310 |
+
"model.text.blocks.8.attn.tau.wq": "modelv2-00001-of-00004.safetensors",
|
| 311 |
+
"model.text.blocks.8.attn.tau.wv": "modelv2-00001-of-00004.safetensors",
|
| 312 |
+
"model.text.blocks.8.ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 313 |
+
"model.text.blocks.8.ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 314 |
+
"model.text.blocks.8.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 315 |
+
"model.text.blocks.8.mlp.fc2.weight": "modelv2-00002-of-00004.safetensors",
|
| 316 |
+
"model.text.blocks.8.mlp.router.bias": "modelv2-00001-of-00004.safetensors",
|
| 317 |
+
"model.text.blocks.8.mlp.router.weight": "modelv2-00001-of-00004.safetensors",
|
| 318 |
+
"model.text.blocks.9.attn.proj.bias": "modelv2-00002-of-00004.safetensors",
|
| 319 |
+
"model.text.blocks.9.attn.proj.weight": "modelv2-00002-of-00004.safetensors",
|
| 320 |
+
"model.text.blocks.9.attn.qkv.bias": "modelv2-00002-of-00004.safetensors",
|
| 321 |
+
"model.text.blocks.9.attn.qkv.weight": "modelv2-00002-of-00004.safetensors",
|
| 322 |
+
"model.text.blocks.9.attn.tau.alpha": "modelv2-00002-of-00004.safetensors",
|
| 323 |
+
"model.text.blocks.9.attn.tau.wq": "modelv2-00002-of-00004.safetensors",
|
| 324 |
+
"model.text.blocks.9.attn.tau.wv": "modelv2-00002-of-00004.safetensors",
|
| 325 |
+
"model.text.blocks.9.ln.bias": "modelv2-00002-of-00004.safetensors",
|
| 326 |
+
"model.text.blocks.9.ln.weight": "modelv2-00002-of-00004.safetensors",
|
| 327 |
+
"model.text.blocks.9.mlp.fc1.weight": "modelv2-00002-of-00004.safetensors",
|
| 328 |
+
"model.text.blocks.9.mlp.fc2.weight": "modelv2-00002-of-00004.safetensors",
|
| 329 |
+
"model.text.blocks.9.mlp.router.bias": "modelv2-00002-of-00004.safetensors",
|
| 330 |
+
"model.text.blocks.9.mlp.router.weight": "modelv2-00002-of-00004.safetensors",
|
| 331 |
+
"model.text.lm_head.bias": "modelv2-00004-of-00004.safetensors",
|
| 332 |
+
"model.text.lm_head.weight": "modelv2-00004-of-00004.safetensors",
|
| 333 |
+
"model.text.post_ln.bias": "modelv2-00004-of-00004.safetensors",
|
| 334 |
+
"model.text.post_ln.weight": "modelv2-00004-of-00004.safetensors",
|
| 335 |
+
"model.text.wte": "modelv2-00001-of-00004.safetensors",
|
| 336 |
+
"model.vision.blocks.0.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 337 |
+
"model.vision.blocks.0.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 338 |
+
"model.vision.blocks.0.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 339 |
+
"model.vision.blocks.0.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 340 |
+
"model.vision.blocks.0.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 341 |
+
"model.vision.blocks.0.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 342 |
+
"model.vision.blocks.0.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 343 |
+
"model.vision.blocks.0.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 344 |
+
"model.vision.blocks.0.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 345 |
+
"model.vision.blocks.0.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 346 |
+
"model.vision.blocks.0.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 347 |
+
"model.vision.blocks.0.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 348 |
+
"model.vision.blocks.1.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 349 |
+
"model.vision.blocks.1.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 350 |
+
"model.vision.blocks.1.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 351 |
+
"model.vision.blocks.1.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 352 |
+
"model.vision.blocks.1.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 353 |
+
"model.vision.blocks.1.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 354 |
+
"model.vision.blocks.1.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 355 |
+
"model.vision.blocks.1.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 356 |
+
"model.vision.blocks.1.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 357 |
+
"model.vision.blocks.1.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 358 |
+
"model.vision.blocks.1.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 359 |
+
"model.vision.blocks.1.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 360 |
+
"model.vision.blocks.10.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 361 |
+
"model.vision.blocks.10.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 362 |
+
"model.vision.blocks.10.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 363 |
+
"model.vision.blocks.10.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 364 |
+
"model.vision.blocks.10.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 365 |
+
"model.vision.blocks.10.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 366 |
+
"model.vision.blocks.10.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 367 |
+
"model.vision.blocks.10.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 368 |
+
"model.vision.blocks.10.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 369 |
+
"model.vision.blocks.10.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 370 |
+
"model.vision.blocks.10.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 371 |
+
"model.vision.blocks.10.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 372 |
+
"model.vision.blocks.11.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 373 |
+
"model.vision.blocks.11.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 374 |
+
"model.vision.blocks.11.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 375 |
+
"model.vision.blocks.11.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 376 |
+
"model.vision.blocks.11.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 377 |
+
"model.vision.blocks.11.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 378 |
+
"model.vision.blocks.11.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 379 |
+
"model.vision.blocks.11.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 380 |
+
"model.vision.blocks.11.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 381 |
+
"model.vision.blocks.11.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 382 |
+
"model.vision.blocks.11.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 383 |
+
"model.vision.blocks.11.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 384 |
+
"model.vision.blocks.12.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 385 |
+
"model.vision.blocks.12.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 386 |
+
"model.vision.blocks.12.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 387 |
+
"model.vision.blocks.12.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 388 |
+
"model.vision.blocks.12.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 389 |
+
"model.vision.blocks.12.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 390 |
+
"model.vision.blocks.12.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 391 |
+
"model.vision.blocks.12.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 392 |
+
"model.vision.blocks.12.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 393 |
+
"model.vision.blocks.12.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 394 |
+
"model.vision.blocks.12.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 395 |
+
"model.vision.blocks.12.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 396 |
+
"model.vision.blocks.13.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 397 |
+
"model.vision.blocks.13.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 398 |
+
"model.vision.blocks.13.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 399 |
+
"model.vision.blocks.13.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 400 |
+
"model.vision.blocks.13.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 401 |
+
"model.vision.blocks.13.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 402 |
+
"model.vision.blocks.13.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 403 |
+
"model.vision.blocks.13.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 404 |
+
"model.vision.blocks.13.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 405 |
+
"model.vision.blocks.13.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 406 |
+
"model.vision.blocks.13.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 407 |
+
"model.vision.blocks.13.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 408 |
+
"model.vision.blocks.14.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 409 |
+
"model.vision.blocks.14.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 410 |
+
"model.vision.blocks.14.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 411 |
+
"model.vision.blocks.14.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 412 |
+
"model.vision.blocks.14.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 413 |
+
"model.vision.blocks.14.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 414 |
+
"model.vision.blocks.14.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 415 |
+
"model.vision.blocks.14.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 416 |
+
"model.vision.blocks.14.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 417 |
+
"model.vision.blocks.14.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 418 |
+
"model.vision.blocks.14.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 419 |
+
"model.vision.blocks.14.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 420 |
+
"model.vision.blocks.15.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 421 |
+
"model.vision.blocks.15.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 422 |
+
"model.vision.blocks.15.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 423 |
+
"model.vision.blocks.15.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 424 |
+
"model.vision.blocks.15.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 425 |
+
"model.vision.blocks.15.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 426 |
+
"model.vision.blocks.15.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 427 |
+
"model.vision.blocks.15.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 428 |
+
"model.vision.blocks.15.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 429 |
+
"model.vision.blocks.15.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 430 |
+
"model.vision.blocks.15.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 431 |
+
"model.vision.blocks.15.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 432 |
+
"model.vision.blocks.16.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 433 |
+
"model.vision.blocks.16.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 434 |
+
"model.vision.blocks.16.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 435 |
+
"model.vision.blocks.16.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 436 |
+
"model.vision.blocks.16.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 437 |
+
"model.vision.blocks.16.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 438 |
+
"model.vision.blocks.16.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 439 |
+
"model.vision.blocks.16.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 440 |
+
"model.vision.blocks.16.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 441 |
+
"model.vision.blocks.16.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 442 |
+
"model.vision.blocks.16.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 443 |
+
"model.vision.blocks.16.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 444 |
+
"model.vision.blocks.17.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 445 |
+
"model.vision.blocks.17.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 446 |
+
"model.vision.blocks.17.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 447 |
+
"model.vision.blocks.17.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 448 |
+
"model.vision.blocks.17.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 449 |
+
"model.vision.blocks.17.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 450 |
+
"model.vision.blocks.17.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 451 |
+
"model.vision.blocks.17.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 452 |
+
"model.vision.blocks.17.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 453 |
+
"model.vision.blocks.17.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 454 |
+
"model.vision.blocks.17.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 455 |
+
"model.vision.blocks.17.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 456 |
+
"model.vision.blocks.18.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 457 |
+
"model.vision.blocks.18.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 458 |
+
"model.vision.blocks.18.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 459 |
+
"model.vision.blocks.18.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 460 |
+
"model.vision.blocks.18.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 461 |
+
"model.vision.blocks.18.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 462 |
+
"model.vision.blocks.18.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 463 |
+
"model.vision.blocks.18.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 464 |
+
"model.vision.blocks.18.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 465 |
+
"model.vision.blocks.18.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 466 |
+
"model.vision.blocks.18.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 467 |
+
"model.vision.blocks.18.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 468 |
+
"model.vision.blocks.19.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 469 |
+
"model.vision.blocks.19.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 470 |
+
"model.vision.blocks.19.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 471 |
+
"model.vision.blocks.19.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 472 |
+
"model.vision.blocks.19.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 473 |
+
"model.vision.blocks.19.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 474 |
+
"model.vision.blocks.19.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 475 |
+
"model.vision.blocks.19.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 476 |
+
"model.vision.blocks.19.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 477 |
+
"model.vision.blocks.19.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 478 |
+
"model.vision.blocks.19.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 479 |
+
"model.vision.blocks.19.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 480 |
+
"model.vision.blocks.2.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 481 |
+
"model.vision.blocks.2.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 482 |
+
"model.vision.blocks.2.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 483 |
+
"model.vision.blocks.2.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 484 |
+
"model.vision.blocks.2.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 485 |
+
"model.vision.blocks.2.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 486 |
+
"model.vision.blocks.2.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 487 |
+
"model.vision.blocks.2.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 488 |
+
"model.vision.blocks.2.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 489 |
+
"model.vision.blocks.2.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 490 |
+
"model.vision.blocks.2.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 491 |
+
"model.vision.blocks.2.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 492 |
+
"model.vision.blocks.20.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 493 |
+
"model.vision.blocks.20.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 494 |
+
"model.vision.blocks.20.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 495 |
+
"model.vision.blocks.20.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 496 |
+
"model.vision.blocks.20.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 497 |
+
"model.vision.blocks.20.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 498 |
+
"model.vision.blocks.20.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 499 |
+
"model.vision.blocks.20.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 500 |
+
"model.vision.blocks.20.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 501 |
+
"model.vision.blocks.20.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 502 |
+
"model.vision.blocks.20.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 503 |
+
"model.vision.blocks.20.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 504 |
+
"model.vision.blocks.21.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 505 |
+
"model.vision.blocks.21.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 506 |
+
"model.vision.blocks.21.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 507 |
+
"model.vision.blocks.21.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 508 |
+
"model.vision.blocks.21.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 509 |
+
"model.vision.blocks.21.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 510 |
+
"model.vision.blocks.21.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 511 |
+
"model.vision.blocks.21.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 512 |
+
"model.vision.blocks.21.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 513 |
+
"model.vision.blocks.21.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 514 |
+
"model.vision.blocks.21.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 515 |
+
"model.vision.blocks.21.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 516 |
+
"model.vision.blocks.22.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 517 |
+
"model.vision.blocks.22.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 518 |
+
"model.vision.blocks.22.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 519 |
+
"model.vision.blocks.22.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 520 |
+
"model.vision.blocks.22.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 521 |
+
"model.vision.blocks.22.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 522 |
+
"model.vision.blocks.22.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 523 |
+
"model.vision.blocks.22.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 524 |
+
"model.vision.blocks.22.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 525 |
+
"model.vision.blocks.22.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 526 |
+
"model.vision.blocks.22.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 527 |
+
"model.vision.blocks.22.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 528 |
+
"model.vision.blocks.23.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 529 |
+
"model.vision.blocks.23.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 530 |
+
"model.vision.blocks.23.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 531 |
+
"model.vision.blocks.23.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 532 |
+
"model.vision.blocks.23.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 533 |
+
"model.vision.blocks.23.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 534 |
+
"model.vision.blocks.23.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 535 |
+
"model.vision.blocks.23.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 536 |
+
"model.vision.blocks.23.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 537 |
+
"model.vision.blocks.23.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 538 |
+
"model.vision.blocks.23.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 539 |
+
"model.vision.blocks.23.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 540 |
+
"model.vision.blocks.24.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 541 |
+
"model.vision.blocks.24.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 542 |
+
"model.vision.blocks.24.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 543 |
+
"model.vision.blocks.24.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 544 |
+
"model.vision.blocks.24.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 545 |
+
"model.vision.blocks.24.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 546 |
+
"model.vision.blocks.24.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 547 |
+
"model.vision.blocks.24.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 548 |
+
"model.vision.blocks.24.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 549 |
+
"model.vision.blocks.24.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 550 |
+
"model.vision.blocks.24.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 551 |
+
"model.vision.blocks.24.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 552 |
+
"model.vision.blocks.25.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 553 |
+
"model.vision.blocks.25.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 554 |
+
"model.vision.blocks.25.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 555 |
+
"model.vision.blocks.25.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 556 |
+
"model.vision.blocks.25.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 557 |
+
"model.vision.blocks.25.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 558 |
+
"model.vision.blocks.25.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 559 |
+
"model.vision.blocks.25.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 560 |
+
"model.vision.blocks.25.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 561 |
+
"model.vision.blocks.25.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 562 |
+
"model.vision.blocks.25.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 563 |
+
"model.vision.blocks.25.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 564 |
+
"model.vision.blocks.26.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 565 |
+
"model.vision.blocks.26.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 566 |
+
"model.vision.blocks.26.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 567 |
+
"model.vision.blocks.26.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 568 |
+
"model.vision.blocks.26.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 569 |
+
"model.vision.blocks.26.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 570 |
+
"model.vision.blocks.26.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 571 |
+
"model.vision.blocks.26.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 572 |
+
"model.vision.blocks.26.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 573 |
+
"model.vision.blocks.26.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 574 |
+
"model.vision.blocks.26.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 575 |
+
"model.vision.blocks.26.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 576 |
+
"model.vision.blocks.3.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 577 |
+
"model.vision.blocks.3.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 578 |
+
"model.vision.blocks.3.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 579 |
+
"model.vision.blocks.3.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 580 |
+
"model.vision.blocks.3.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 581 |
+
"model.vision.blocks.3.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 582 |
+
"model.vision.blocks.3.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 583 |
+
"model.vision.blocks.3.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 584 |
+
"model.vision.blocks.3.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 585 |
+
"model.vision.blocks.3.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 586 |
+
"model.vision.blocks.3.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 587 |
+
"model.vision.blocks.3.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 588 |
+
"model.vision.blocks.4.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 589 |
+
"model.vision.blocks.4.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 590 |
+
"model.vision.blocks.4.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 591 |
+
"model.vision.blocks.4.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 592 |
+
"model.vision.blocks.4.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 593 |
+
"model.vision.blocks.4.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 594 |
+
"model.vision.blocks.4.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 595 |
+
"model.vision.blocks.4.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 596 |
+
"model.vision.blocks.4.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 597 |
+
"model.vision.blocks.4.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 598 |
+
"model.vision.blocks.4.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 599 |
+
"model.vision.blocks.4.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 600 |
+
"model.vision.blocks.5.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 601 |
+
"model.vision.blocks.5.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 602 |
+
"model.vision.blocks.5.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 603 |
+
"model.vision.blocks.5.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 604 |
+
"model.vision.blocks.5.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 605 |
+
"model.vision.blocks.5.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 606 |
+
"model.vision.blocks.5.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 607 |
+
"model.vision.blocks.5.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 608 |
+
"model.vision.blocks.5.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 609 |
+
"model.vision.blocks.5.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 610 |
+
"model.vision.blocks.5.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 611 |
+
"model.vision.blocks.5.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 612 |
+
"model.vision.blocks.6.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 613 |
+
"model.vision.blocks.6.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 614 |
+
"model.vision.blocks.6.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 615 |
+
"model.vision.blocks.6.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 616 |
+
"model.vision.blocks.6.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 617 |
+
"model.vision.blocks.6.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 618 |
+
"model.vision.blocks.6.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 619 |
+
"model.vision.blocks.6.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 620 |
+
"model.vision.blocks.6.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 621 |
+
"model.vision.blocks.6.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 622 |
+
"model.vision.blocks.6.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 623 |
+
"model.vision.blocks.6.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 624 |
+
"model.vision.blocks.7.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 625 |
+
"model.vision.blocks.7.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 626 |
+
"model.vision.blocks.7.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 627 |
+
"model.vision.blocks.7.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 628 |
+
"model.vision.blocks.7.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 629 |
+
"model.vision.blocks.7.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 630 |
+
"model.vision.blocks.7.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 631 |
+
"model.vision.blocks.7.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 632 |
+
"model.vision.blocks.7.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 633 |
+
"model.vision.blocks.7.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 634 |
+
"model.vision.blocks.7.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 635 |
+
"model.vision.blocks.7.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 636 |
+
"model.vision.blocks.8.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 637 |
+
"model.vision.blocks.8.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 638 |
+
"model.vision.blocks.8.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 639 |
+
"model.vision.blocks.8.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 640 |
+
"model.vision.blocks.8.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 641 |
+
"model.vision.blocks.8.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 642 |
+
"model.vision.blocks.8.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 643 |
+
"model.vision.blocks.8.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 644 |
+
"model.vision.blocks.8.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 645 |
+
"model.vision.blocks.8.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 646 |
+
"model.vision.blocks.8.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 647 |
+
"model.vision.blocks.8.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 648 |
+
"model.vision.blocks.9.attn.proj.bias": "modelv2-00001-of-00004.safetensors",
|
| 649 |
+
"model.vision.blocks.9.attn.proj.weight": "modelv2-00001-of-00004.safetensors",
|
| 650 |
+
"model.vision.blocks.9.attn.qkv.bias": "modelv2-00001-of-00004.safetensors",
|
| 651 |
+
"model.vision.blocks.9.attn.qkv.weight": "modelv2-00001-of-00004.safetensors",
|
| 652 |
+
"model.vision.blocks.9.ln1.bias": "modelv2-00001-of-00004.safetensors",
|
| 653 |
+
"model.vision.blocks.9.ln1.weight": "modelv2-00001-of-00004.safetensors",
|
| 654 |
+
"model.vision.blocks.9.ln2.bias": "modelv2-00001-of-00004.safetensors",
|
| 655 |
+
"model.vision.blocks.9.ln2.weight": "modelv2-00001-of-00004.safetensors",
|
| 656 |
+
"model.vision.blocks.9.mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 657 |
+
"model.vision.blocks.9.mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 658 |
+
"model.vision.blocks.9.mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 659 |
+
"model.vision.blocks.9.mlp.fc2.weight": "modelv2-00001-of-00004.safetensors",
|
| 660 |
+
"model.vision.patch_emb.bias": "modelv2-00001-of-00004.safetensors",
|
| 661 |
+
"model.vision.patch_emb.weight": "modelv2-00001-of-00004.safetensors",
|
| 662 |
+
"model.vision.pos_emb": "modelv2-00001-of-00004.safetensors",
|
| 663 |
+
"model.vision.post_ln.bias": "modelv2-00001-of-00004.safetensors",
|
| 664 |
+
"model.vision.post_ln.weight": "modelv2-00001-of-00004.safetensors",
|
| 665 |
+
"model.vision.proj_mlp.fc1.bias": "modelv2-00001-of-00004.safetensors",
|
| 666 |
+
"model.vision.proj_mlp.fc1.weight": "modelv2-00001-of-00004.safetensors",
|
| 667 |
+
"model.vision.proj_mlp.fc2.bias": "modelv2-00001-of-00004.safetensors",
|
| 668 |
+
"model.vision.proj_mlp.fc2.weight": "modelv2-00001-of-00004.safetensors"
|
| 669 |
+
}
|
| 670 |
+
}
|
moondream.py
ADDED
|
@@ -0,0 +1,1097 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import random
|
| 4 |
+
|
| 5 |
+
from typing import Literal, Tuple, TypedDict, Union, Dict, Any, Optional, List
|
| 6 |
+
from PIL import Image
|
| 7 |
+
from dataclasses import dataclass
|
| 8 |
+
from tokenizers import Tokenizer
|
| 9 |
+
from torch.nn.attention.flex_attention import create_block_mask
|
| 10 |
+
|
| 11 |
+
from .config import MoondreamConfig
|
| 12 |
+
from .image_crops import reconstruct_from_crops
|
| 13 |
+
from .vision import vision_encoder, vision_projection, prepare_crops, build_vision_model
|
| 14 |
+
from .text import build_text_model, text_encoder, lm_head, text_decoder
|
| 15 |
+
from .region import (
|
| 16 |
+
decode_coordinate,
|
| 17 |
+
encode_coordinate,
|
| 18 |
+
decode_size,
|
| 19 |
+
encode_size,
|
| 20 |
+
encode_spatial_refs,
|
| 21 |
+
SpatialRefs,
|
| 22 |
+
)
|
| 23 |
+
from .layers import QuantizedLinear
|
| 24 |
+
from .lora import load_adapter, normalize_adapter_id
|
| 25 |
+
from .rope import precompute_freqs_cis
|
| 26 |
+
from .utils import remove_outlier_points
|
| 27 |
+
|
| 28 |
+
ImageEncodingSettings = TypedDict(
|
| 29 |
+
"ImageEncodingSettings",
|
| 30 |
+
{"adapter": str, "model": str},
|
| 31 |
+
total=False,
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
TextSamplingSettings = TypedDict(
|
| 35 |
+
"TextSamplingSettings",
|
| 36 |
+
{
|
| 37 |
+
"max_tokens": int,
|
| 38 |
+
"temperature": float,
|
| 39 |
+
"top_p": float,
|
| 40 |
+
"adapter": str,
|
| 41 |
+
"model": str,
|
| 42 |
+
},
|
| 43 |
+
total=False,
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
ObjectSamplingSettings = TypedDict(
|
| 47 |
+
"ObjectSamplingSettings",
|
| 48 |
+
{"max_objects": int, "adapter": str, "model": str},
|
| 49 |
+
total=False,
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
DEFAULT_MAX_TOKENS = 768
|
| 54 |
+
DEFAULT_TEMPERATURE = 0.5
|
| 55 |
+
DEFAULT_TOP_P = 0.9
|
| 56 |
+
DEFAULT_MAX_OBJECTS = 150
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
@dataclass(frozen=True)
|
| 60 |
+
class EncodedImage:
|
| 61 |
+
pos: int
|
| 62 |
+
caches: List[Tuple[torch.Tensor, torch.Tensor]]
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
class KVCache(nn.Module):
|
| 66 |
+
|
| 67 |
+
def __init__(self, n_heads, n_kv_heads, max_context, dim, device, dtype):
|
| 68 |
+
super().__init__()
|
| 69 |
+
cache_shape = (1, n_kv_heads, max_context, dim // n_heads)
|
| 70 |
+
self.register_buffer(
|
| 71 |
+
"k_cache", torch.zeros(*cache_shape, device=device, dtype=dtype)
|
| 72 |
+
)
|
| 73 |
+
self.register_buffer(
|
| 74 |
+
"v_cache", torch.zeros(*cache_shape, device=device, dtype=dtype)
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
def update(self, pos_ids, k, v):
|
| 78 |
+
kout, vout = self.k_cache, self.v_cache
|
| 79 |
+
kout[:, :, pos_ids, :] = k
|
| 80 |
+
vout[:, :, pos_ids, :] = v
|
| 81 |
+
return kout, vout
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def causal_mask(b, h, q_idx, kv_idx):
|
| 85 |
+
return q_idx >= kv_idx
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def get_mask_mod(mask_mod, offset):
|
| 89 |
+
def _mask_mod(b, h, q, kv):
|
| 90 |
+
return mask_mod(b, h, q + offset, kv)
|
| 91 |
+
|
| 92 |
+
return _mask_mod
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class MoondreamModel(nn.Module):
|
| 96 |
+
|
| 97 |
+
def __init__(
|
| 98 |
+
self, config: MoondreamConfig, dtype=torch.bfloat16, setup_caches=True
|
| 99 |
+
):
|
| 100 |
+
super().__init__()
|
| 101 |
+
self.config = config
|
| 102 |
+
|
| 103 |
+
self.tokenizer = Tokenizer.from_pretrained("moondream/starmie-v1")
|
| 104 |
+
self.vision = build_vision_model(config.vision, dtype)
|
| 105 |
+
self.text = build_text_model(config.text, dtype)
|
| 106 |
+
|
| 107 |
+
# Region Model
|
| 108 |
+
linear_cls = (
|
| 109 |
+
QuantizedLinear if config.region.group_size is not None else nn.Linear
|
| 110 |
+
)
|
| 111 |
+
self.region = nn.ModuleDict(
|
| 112 |
+
{
|
| 113 |
+
"coord_encoder": linear_cls(
|
| 114 |
+
config.region.coord_feat_dim, config.region.dim, dtype=dtype
|
| 115 |
+
),
|
| 116 |
+
"coord_decoder": linear_cls(
|
| 117 |
+
config.region.dim, config.region.coord_out_dim, dtype=dtype
|
| 118 |
+
),
|
| 119 |
+
"size_encoder": linear_cls(
|
| 120 |
+
config.region.size_feat_dim, config.region.dim, dtype=dtype
|
| 121 |
+
),
|
| 122 |
+
"size_decoder": linear_cls(
|
| 123 |
+
config.region.dim, config.region.size_out_dim, dtype=dtype
|
| 124 |
+
),
|
| 125 |
+
"ln": nn.LayerNorm(config.region.dim, dtype=dtype),
|
| 126 |
+
}
|
| 127 |
+
)
|
| 128 |
+
self.region.coord_features = nn.Parameter(
|
| 129 |
+
torch.empty(config.region.coord_feat_dim // 2, 1, dtype=dtype).T
|
| 130 |
+
)
|
| 131 |
+
self.region.size_features = nn.Parameter(
|
| 132 |
+
torch.empty(config.region.size_feat_dim // 2, 2, dtype=dtype).T
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
attn_mask = torch.tril(
|
| 136 |
+
torch.ones(
|
| 137 |
+
1, 1, config.text.max_context, config.text.max_context, dtype=torch.bool
|
| 138 |
+
)
|
| 139 |
+
)
|
| 140 |
+
patch_w = config.vision.crop_size // config.vision.enc_patch_size
|
| 141 |
+
prefix_attn_len = 1 + patch_w**2
|
| 142 |
+
attn_mask[..., :prefix_attn_len, :prefix_attn_len] = 1
|
| 143 |
+
self.register_buffer("attn_mask", attn_mask, persistent=False)
|
| 144 |
+
|
| 145 |
+
self.use_flex_decoding = True
|
| 146 |
+
self._causal_block_mask = None
|
| 147 |
+
self._point_gen_indices = None
|
| 148 |
+
|
| 149 |
+
# Initialize KV caches.
|
| 150 |
+
if setup_caches:
|
| 151 |
+
self._setup_caches()
|
| 152 |
+
|
| 153 |
+
@property
|
| 154 |
+
def causal_block_mask(self):
|
| 155 |
+
# The things we do to deal with ZeroGPU...
|
| 156 |
+
if self._causal_block_mask is None:
|
| 157 |
+
self._causal_block_mask = create_block_mask(
|
| 158 |
+
causal_mask,
|
| 159 |
+
B=None,
|
| 160 |
+
H=None,
|
| 161 |
+
Q_LEN=self.config.text.max_context,
|
| 162 |
+
KV_LEN=self.config.text.max_context,
|
| 163 |
+
)
|
| 164 |
+
return self._causal_block_mask
|
| 165 |
+
|
| 166 |
+
@property
|
| 167 |
+
def point_gen_indices(self):
|
| 168 |
+
if self._point_gen_indices is None:
|
| 169 |
+
self._point_gen_indices = torch.tensor(
|
| 170 |
+
[self.config.tokenizer.coord_id, self.config.tokenizer.eos_id],
|
| 171 |
+
device=self.device,
|
| 172 |
+
)
|
| 173 |
+
return self._point_gen_indices
|
| 174 |
+
|
| 175 |
+
def _refresh_runtime_buffers(self):
|
| 176 |
+
attn_mask = torch.tril(
|
| 177 |
+
torch.ones(
|
| 178 |
+
1,
|
| 179 |
+
1,
|
| 180 |
+
self.config.text.max_context,
|
| 181 |
+
self.config.text.max_context,
|
| 182 |
+
dtype=torch.bool,
|
| 183 |
+
device=self.device,
|
| 184 |
+
)
|
| 185 |
+
)
|
| 186 |
+
patch_w = self.config.vision.crop_size // self.config.vision.enc_patch_size
|
| 187 |
+
prefix_attn_len = 1 + patch_w**2
|
| 188 |
+
attn_mask[..., :prefix_attn_len, :prefix_attn_len] = 1
|
| 189 |
+
self.attn_mask = attn_mask
|
| 190 |
+
self.text.freqs_cis = precompute_freqs_cis(
|
| 191 |
+
self.config.text.dim // (2 * self.config.text.n_heads),
|
| 192 |
+
self.config.text.max_context,
|
| 193 |
+
).to(device=self.device)
|
| 194 |
+
|
| 195 |
+
def _setup_caches(self):
|
| 196 |
+
c = self.config.text
|
| 197 |
+
for b in self.text.blocks:
|
| 198 |
+
b.kv_cache = KVCache(
|
| 199 |
+
c.n_heads,
|
| 200 |
+
c.n_kv_heads,
|
| 201 |
+
c.max_context,
|
| 202 |
+
c.dim,
|
| 203 |
+
device=self.device,
|
| 204 |
+
dtype=self.vision.pos_emb.dtype,
|
| 205 |
+
)
|
| 206 |
+
|
| 207 |
+
def _adapter_id_from_settings(self, settings: Optional[dict]) -> Optional[str]:
|
| 208 |
+
if settings is None:
|
| 209 |
+
return None
|
| 210 |
+
adapter = settings.get("adapter")
|
| 211 |
+
if adapter is not None:
|
| 212 |
+
return normalize_adapter_id(adapter)
|
| 213 |
+
|
| 214 |
+
model_value = settings.get("model")
|
| 215 |
+
if isinstance(model_value, str):
|
| 216 |
+
return normalize_adapter_id(model_value)
|
| 217 |
+
return None
|
| 218 |
+
|
| 219 |
+
def _resolve_lora(self, settings: Optional[dict]) -> Optional[object]:
|
| 220 |
+
adapter_id = self._adapter_id_from_settings(settings)
|
| 221 |
+
if adapter_id is None:
|
| 222 |
+
return None
|
| 223 |
+
return load_adapter(
|
| 224 |
+
adapter_id,
|
| 225 |
+
text_config=self.config.text,
|
| 226 |
+
device=self.device,
|
| 227 |
+
dtype=self.vision.pos_emb.dtype,
|
| 228 |
+
)
|
| 229 |
+
|
| 230 |
+
@property
|
| 231 |
+
def device(self):
|
| 232 |
+
return self.vision.pos_emb.device
|
| 233 |
+
|
| 234 |
+
def _vis_enc(self, x: torch.Tensor):
|
| 235 |
+
return vision_encoder(x, self.vision, self.config.vision)
|
| 236 |
+
|
| 237 |
+
def _vis_proj(self, g: torch.Tensor, r: torch.Tensor):
|
| 238 |
+
return vision_projection(g, r, self.vision, self.config.vision)
|
| 239 |
+
|
| 240 |
+
def _prefill(
|
| 241 |
+
self,
|
| 242 |
+
x: torch.Tensor,
|
| 243 |
+
attn_mask: torch.Tensor,
|
| 244 |
+
pos_ids: torch.Tensor,
|
| 245 |
+
lora: Optional[torch.Tensor],
|
| 246 |
+
):
|
| 247 |
+
return text_decoder(x, self.text, attn_mask, pos_ids, self.config.text, lora)
|
| 248 |
+
|
| 249 |
+
def _decode_one_tok(
|
| 250 |
+
self,
|
| 251 |
+
x: torch.Tensor,
|
| 252 |
+
attn_mask: torch.Tensor,
|
| 253 |
+
pos_ids: torch.Tensor,
|
| 254 |
+
lora: Optional[torch.Tensor],
|
| 255 |
+
lm_head_indices: Optional[torch.Tensor] = None,
|
| 256 |
+
):
|
| 257 |
+
if self.use_flex_decoding:
|
| 258 |
+
torch._assert(pos_ids.shape[-1] == 1, "Invalid position ID shape")
|
| 259 |
+
block_index = pos_ids // self.causal_block_mask.BLOCK_SIZE[0]
|
| 260 |
+
mask = self.causal_block_mask[:, :, block_index]
|
| 261 |
+
mask.seq_lengths = (1, mask.seq_lengths[1])
|
| 262 |
+
mask.mask_mod = get_mask_mod(self.causal_block_mask.mask_mod, pos_ids[0])
|
| 263 |
+
else:
|
| 264 |
+
mask = None
|
| 265 |
+
|
| 266 |
+
hidden = text_decoder(
|
| 267 |
+
x,
|
| 268 |
+
self.text,
|
| 269 |
+
attn_mask,
|
| 270 |
+
pos_ids,
|
| 271 |
+
self.config.text,
|
| 272 |
+
lora=lora,
|
| 273 |
+
flex_block_mask_slice=mask,
|
| 274 |
+
)
|
| 275 |
+
logits = lm_head(hidden, self.text, indices=lm_head_indices)
|
| 276 |
+
return logits, hidden
|
| 277 |
+
|
| 278 |
+
def compile(self):
|
| 279 |
+
for module in self.modules():
|
| 280 |
+
if isinstance(module, QuantizedLinear):
|
| 281 |
+
module.unpack()
|
| 282 |
+
|
| 283 |
+
# Initialize lazy properties to avoid first-call overhead
|
| 284 |
+
self.causal_block_mask
|
| 285 |
+
self.point_gen_indices
|
| 286 |
+
|
| 287 |
+
# TODO: vision_projection and _prefill is not being compiled
|
| 288 |
+
self._vis_enc = torch.compile(self._vis_enc, fullgraph=True)
|
| 289 |
+
self._decode_one_tok = torch.compile(
|
| 290 |
+
self._decode_one_tok, fullgraph=True, mode="reduce-overhead"
|
| 291 |
+
)
|
| 292 |
+
|
| 293 |
+
# Warm up compiled methods with dummy forward passes
|
| 294 |
+
device = self.device
|
| 295 |
+
dtype = self.vision.pos_emb.dtype
|
| 296 |
+
with torch.no_grad():
|
| 297 |
+
# Warmup vision encoder
|
| 298 |
+
dummy_crops = torch.randn(1, 3, 378, 378, device=device, dtype=dtype)
|
| 299 |
+
self._vis_enc(dummy_crops)
|
| 300 |
+
|
| 301 |
+
# Warmup _decode_one_tok (both normal and point generation modes)
|
| 302 |
+
dummy_emb = torch.randn(
|
| 303 |
+
1, 1, self.config.text.dim, device=device, dtype=dtype
|
| 304 |
+
)
|
| 305 |
+
dummy_mask = torch.ones(
|
| 306 |
+
1, 1, self.config.text.max_context, device=device, dtype=torch.bool
|
| 307 |
+
)
|
| 308 |
+
dummy_pos_ids = torch.tensor([100], device=device, dtype=torch.long)
|
| 309 |
+
self._decode_one_tok(dummy_emb, dummy_mask, dummy_pos_ids, None)
|
| 310 |
+
self._decode_one_tok(
|
| 311 |
+
dummy_emb,
|
| 312 |
+
dummy_mask,
|
| 313 |
+
dummy_pos_ids,
|
| 314 |
+
None,
|
| 315 |
+
lm_head_indices=self.point_gen_indices,
|
| 316 |
+
)
|
| 317 |
+
|
| 318 |
+
def _run_vision_encoder(self, image: Image.Image) -> torch.Tensor:
|
| 319 |
+
all_crops, tiling = prepare_crops(image, self.config.vision, device=self.device)
|
| 320 |
+
|
| 321 |
+
torch._dynamo.mark_dynamic(all_crops, 0)
|
| 322 |
+
|
| 323 |
+
outputs = self._vis_enc(all_crops)
|
| 324 |
+
|
| 325 |
+
global_features = outputs[0]
|
| 326 |
+
local_features = outputs[1:].view(
|
| 327 |
+
-1,
|
| 328 |
+
self.config.vision.enc_n_layers,
|
| 329 |
+
self.config.vision.enc_n_layers,
|
| 330 |
+
self.config.vision.enc_dim,
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
reconstructed = reconstruct_from_crops(
|
| 334 |
+
local_features,
|
| 335 |
+
tiling,
|
| 336 |
+
patch_size=1,
|
| 337 |
+
overlap_margin=self.config.vision.overlap_margin,
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
return self._vis_proj(global_features, reconstructed)
|
| 341 |
+
|
| 342 |
+
def encode_image(
|
| 343 |
+
self,
|
| 344 |
+
image: Union[Image.Image, EncodedImage],
|
| 345 |
+
settings: Optional[ImageEncodingSettings] = None,
|
| 346 |
+
) -> EncodedImage:
|
| 347 |
+
if isinstance(image, EncodedImage):
|
| 348 |
+
return image
|
| 349 |
+
elif not isinstance(image, Image.Image):
|
| 350 |
+
raise ValueError("image must be a PIL Image or EncodedImage")
|
| 351 |
+
|
| 352 |
+
lora = self._resolve_lora(settings)
|
| 353 |
+
|
| 354 |
+
# Run through text model in addition to the vision encoder, to minimize
|
| 355 |
+
# re-computation if multiple queries are performed on this image.
|
| 356 |
+
with torch.inference_mode():
|
| 357 |
+
img_emb = self._run_vision_encoder(image)
|
| 358 |
+
bos_emb = text_encoder(
|
| 359 |
+
torch.tensor([[self.config.tokenizer.bos_id]], device=self.device),
|
| 360 |
+
self.text,
|
| 361 |
+
)
|
| 362 |
+
inputs_embeds = torch.cat([bos_emb, img_emb[None]], dim=1)
|
| 363 |
+
mask = self.attn_mask[:, :, 0 : inputs_embeds.size(1), :]
|
| 364 |
+
pos_ids = torch.arange(
|
| 365 |
+
inputs_embeds.size(1), dtype=torch.long, device=self.device
|
| 366 |
+
)
|
| 367 |
+
self._prefill(inputs_embeds, mask, pos_ids, lora)
|
| 368 |
+
|
| 369 |
+
return EncodedImage(
|
| 370 |
+
pos=inputs_embeds.size(1),
|
| 371 |
+
caches=[
|
| 372 |
+
(
|
| 373 |
+
b.kv_cache.k_cache[:, :, : inputs_embeds.size(1), :].clone(),
|
| 374 |
+
b.kv_cache.v_cache[:, :, : inputs_embeds.size(1), :].clone(),
|
| 375 |
+
)
|
| 376 |
+
for b in self.text.blocks
|
| 377 |
+
],
|
| 378 |
+
)
|
| 379 |
+
|
| 380 |
+
def _apply_top_p(self, probs: torch.Tensor, top_p: float):
|
| 381 |
+
probs_sort, probs_idx = torch.sort(probs, dim=-1, descending=True)
|
| 382 |
+
probs_sum = torch.cumsum(probs_sort, dim=-1)
|
| 383 |
+
mask = probs_sum - probs_sort > top_p
|
| 384 |
+
probs_sort[mask] = 0.0
|
| 385 |
+
probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))
|
| 386 |
+
next_probs = torch.zeros_like(probs)
|
| 387 |
+
next_probs.scatter_(dim=-1, index=probs_idx, src=probs_sort)
|
| 388 |
+
return next_probs
|
| 389 |
+
|
| 390 |
+
def _prefill_prompt(
|
| 391 |
+
self,
|
| 392 |
+
prompt_tokens: torch.Tensor,
|
| 393 |
+
pos: int,
|
| 394 |
+
temperature: float,
|
| 395 |
+
top_p: float,
|
| 396 |
+
spatial_refs: Optional[SpatialRefs] = None,
|
| 397 |
+
attn_mask: Optional[torch.Tensor] = None,
|
| 398 |
+
lora: Optional[dict] = None,
|
| 399 |
+
):
|
| 400 |
+
with torch.inference_mode():
|
| 401 |
+
prompt_emb = text_encoder(prompt_tokens, self.text)
|
| 402 |
+
|
| 403 |
+
if spatial_refs:
|
| 404 |
+
encoded_refs = encode_spatial_refs(spatial_refs, self.region)
|
| 405 |
+
prompt_emb[prompt_tokens == self.config.tokenizer.coord_id] = (
|
| 406 |
+
encoded_refs["coords"]
|
| 407 |
+
)
|
| 408 |
+
if encoded_refs["sizes"] is not None:
|
| 409 |
+
prompt_emb[prompt_tokens == self.config.tokenizer.size_id] = (
|
| 410 |
+
encoded_refs["sizes"]
|
| 411 |
+
)
|
| 412 |
+
|
| 413 |
+
torch._dynamo.mark_dynamic(prompt_emb, 1)
|
| 414 |
+
|
| 415 |
+
if attn_mask is None:
|
| 416 |
+
attn_mask = self.attn_mask
|
| 417 |
+
|
| 418 |
+
mask = attn_mask[:, :, pos : pos + prompt_emb.size(1), :]
|
| 419 |
+
pos_ids = torch.arange(
|
| 420 |
+
pos, pos + prompt_emb.size(1), dtype=torch.long, device=self.device
|
| 421 |
+
)
|
| 422 |
+
hidden_BC = self._prefill(prompt_emb, mask, pos_ids, lora)
|
| 423 |
+
logits_BV = lm_head(hidden_BC, self.text)
|
| 424 |
+
|
| 425 |
+
if temperature == 0:
|
| 426 |
+
next_token = torch.argmax(logits_BV, dim=-1).unsqueeze(1)
|
| 427 |
+
else:
|
| 428 |
+
probs = torch.softmax(logits_BV / temperature, dim=-1)
|
| 429 |
+
probs = self._apply_top_p(probs, top_p)
|
| 430 |
+
next_token = torch.multinomial(probs, num_samples=1)
|
| 431 |
+
|
| 432 |
+
pos = pos + prompt_emb.size(1)
|
| 433 |
+
return logits_BV, hidden_BC, next_token, pos
|
| 434 |
+
|
| 435 |
+
def _generate_reasoning(
|
| 436 |
+
self,
|
| 437 |
+
prompt_tokens,
|
| 438 |
+
pos,
|
| 439 |
+
settings: Optional[TextSamplingSettings] = None,
|
| 440 |
+
spatial_refs: Optional[SpatialRefs] = None,
|
| 441 |
+
attn_mask: Optional[torch.Tensor] = None,
|
| 442 |
+
) -> Tuple[int, str, List[dict]]:
|
| 443 |
+
max_tokens = (
|
| 444 |
+
settings.get("max_tokens", DEFAULT_MAX_TOKENS)
|
| 445 |
+
if settings
|
| 446 |
+
else DEFAULT_MAX_TOKENS
|
| 447 |
+
)
|
| 448 |
+
temperature = (
|
| 449 |
+
settings.get("temperature", DEFAULT_TEMPERATURE)
|
| 450 |
+
if settings
|
| 451 |
+
else DEFAULT_TEMPERATURE
|
| 452 |
+
)
|
| 453 |
+
lora = self._resolve_lora(settings)
|
| 454 |
+
|
| 455 |
+
top_p = settings.get("top_p", DEFAULT_TOP_P) if settings else DEFAULT_TOP_P
|
| 456 |
+
eos_id = self.config.tokenizer.answer_id
|
| 457 |
+
|
| 458 |
+
_, last_hidden_BC, next_token, pos = self._prefill_prompt(
|
| 459 |
+
prompt_tokens,
|
| 460 |
+
pos,
|
| 461 |
+
temperature,
|
| 462 |
+
top_p,
|
| 463 |
+
spatial_refs,
|
| 464 |
+
attn_mask=attn_mask,
|
| 465 |
+
lora=lora,
|
| 466 |
+
)
|
| 467 |
+
|
| 468 |
+
text_token_chunks = [[]]
|
| 469 |
+
grounding_chunks = [[]]
|
| 470 |
+
|
| 471 |
+
mask = torch.zeros(
|
| 472 |
+
1, 1, self.config.text.max_context, device=self.device, dtype=torch.bool
|
| 473 |
+
)
|
| 474 |
+
mask[:, :, :pos] = 1
|
| 475 |
+
pos_ids = torch.tensor([pos], device=self.device, dtype=torch.long)
|
| 476 |
+
generated_tokens = 0
|
| 477 |
+
|
| 478 |
+
while (
|
| 479 |
+
next_token_id := next_token.item()
|
| 480 |
+
) != eos_id and generated_tokens < max_tokens:
|
| 481 |
+
if (
|
| 482 |
+
next_token_id == self.config.tokenizer.start_ground_points_id
|
| 483 |
+
or next_token_id == self.config.tokenizer.end_ground_id
|
| 484 |
+
):
|
| 485 |
+
text_token_chunks.append([])
|
| 486 |
+
grounding_chunks.append([])
|
| 487 |
+
|
| 488 |
+
text_token_chunks[-1].append(next_token_id)
|
| 489 |
+
|
| 490 |
+
with torch.inference_mode():
|
| 491 |
+
if next_token_id == self.config.tokenizer.coord_id:
|
| 492 |
+
coord_logits = decode_coordinate(last_hidden_BC, self.region)
|
| 493 |
+
coord = torch.argmax(coord_logits, dim=-1) / coord_logits.size(-1)
|
| 494 |
+
grounding_chunks[-1].append(coord.item())
|
| 495 |
+
|
| 496 |
+
next_emb = encode_coordinate(
|
| 497 |
+
coord.to(dtype=coord_logits.dtype), self.region
|
| 498 |
+
).unsqueeze(0)
|
| 499 |
+
else:
|
| 500 |
+
next_emb = text_encoder(next_token, self.text)
|
| 501 |
+
|
| 502 |
+
mask[:, :, pos], pos_ids[0] = 1, pos
|
| 503 |
+
|
| 504 |
+
logits_BV, last_hidden_BC = self._decode_one_tok(
|
| 505 |
+
next_emb, mask, pos_ids, lora
|
| 506 |
+
)
|
| 507 |
+
logits_BV[:, self.config.tokenizer.eos_id] = float("-inf")
|
| 508 |
+
logits_BV[:, self.config.tokenizer.size_id] = float("-inf")
|
| 509 |
+
|
| 510 |
+
pos += 1
|
| 511 |
+
|
| 512 |
+
if temperature == 0:
|
| 513 |
+
next_token = torch.argmax(logits_BV, dim=-1).unsqueeze(1) # (1, 1)
|
| 514 |
+
else:
|
| 515 |
+
probs = torch.softmax(logits_BV / temperature, dim=-1) # (1, V)
|
| 516 |
+
probs = self._apply_top_p(probs, top_p)
|
| 517 |
+
next_token = torch.multinomial(probs, num_samples=1) # (1, 1)
|
| 518 |
+
|
| 519 |
+
generated_tokens += 1
|
| 520 |
+
|
| 521 |
+
text_chunks = [
|
| 522 |
+
self.tokenizer.decode(chunk_tokens) for chunk_tokens in text_token_chunks
|
| 523 |
+
]
|
| 524 |
+
text = "".join(text_chunks)
|
| 525 |
+
|
| 526 |
+
start_idx = 0
|
| 527 |
+
grounding = []
|
| 528 |
+
for text_chunk, grounding_chunk in zip(text_chunks, grounding_chunks):
|
| 529 |
+
if len(grounding_chunk) > 1:
|
| 530 |
+
points = []
|
| 531 |
+
for i in range(0, len(grounding_chunk) - (len(grounding_chunk) % 2), 2):
|
| 532 |
+
points.append((grounding_chunk[i], grounding_chunk[i + 1]))
|
| 533 |
+
grounding.append(
|
| 534 |
+
{
|
| 535 |
+
"start_idx": start_idx,
|
| 536 |
+
"end_idx": start_idx + len(text_chunk),
|
| 537 |
+
"points": points,
|
| 538 |
+
}
|
| 539 |
+
)
|
| 540 |
+
start_idx += len(text_chunk)
|
| 541 |
+
|
| 542 |
+
return pos, text, grounding
|
| 543 |
+
|
| 544 |
+
def _generate_answer(
|
| 545 |
+
self,
|
| 546 |
+
prompt_tokens: torch.Tensor,
|
| 547 |
+
pos: int,
|
| 548 |
+
settings: Optional[TextSamplingSettings] = None,
|
| 549 |
+
spatial_refs: Optional[SpatialRefs] = None,
|
| 550 |
+
eos_id: Optional[int] = None,
|
| 551 |
+
attn_mask: Optional[torch.Tensor] = None,
|
| 552 |
+
):
|
| 553 |
+
max_tokens = (
|
| 554 |
+
settings.get("max_tokens", DEFAULT_MAX_TOKENS)
|
| 555 |
+
if settings
|
| 556 |
+
else DEFAULT_MAX_TOKENS
|
| 557 |
+
)
|
| 558 |
+
temperature = (
|
| 559 |
+
settings.get("temperature", DEFAULT_TEMPERATURE)
|
| 560 |
+
if settings
|
| 561 |
+
else DEFAULT_TEMPERATURE
|
| 562 |
+
)
|
| 563 |
+
top_p = settings.get("top_p", DEFAULT_TOP_P) if settings else DEFAULT_TOP_P
|
| 564 |
+
eos_id = eos_id if eos_id is not None else self.config.tokenizer.eos_id
|
| 565 |
+
lora = self._resolve_lora(settings)
|
| 566 |
+
|
| 567 |
+
_, _, next_token, pos = self._prefill_prompt(
|
| 568 |
+
prompt_tokens,
|
| 569 |
+
pos,
|
| 570 |
+
temperature,
|
| 571 |
+
top_p,
|
| 572 |
+
spatial_refs,
|
| 573 |
+
attn_mask=attn_mask,
|
| 574 |
+
lora=lora,
|
| 575 |
+
)
|
| 576 |
+
|
| 577 |
+
def generator(next_token, pos):
|
| 578 |
+
mask = torch.zeros(
|
| 579 |
+
1, 1, self.config.text.max_context, device=self.device, dtype=torch.bool
|
| 580 |
+
)
|
| 581 |
+
mask[:, :, :pos] = 1
|
| 582 |
+
pos_ids = torch.tensor([pos], device=self.device, dtype=torch.long)
|
| 583 |
+
generated_tokens = 0
|
| 584 |
+
|
| 585 |
+
# For properly handling token streaming with Unicode
|
| 586 |
+
token_cache = []
|
| 587 |
+
print_len = 0
|
| 588 |
+
|
| 589 |
+
while (
|
| 590 |
+
next_token_id := next_token.item()
|
| 591 |
+
) != eos_id and generated_tokens < max_tokens:
|
| 592 |
+
# Add token to our cache
|
| 593 |
+
token_cache.append(next_token_id)
|
| 594 |
+
|
| 595 |
+
# Decode all tokens collected so far
|
| 596 |
+
text = self.tokenizer.decode(token_cache)
|
| 597 |
+
|
| 598 |
+
# After a newline, we flush the cache completely
|
| 599 |
+
if text.endswith("\n"):
|
| 600 |
+
printable_text = text[print_len:]
|
| 601 |
+
token_cache = []
|
| 602 |
+
print_len = 0
|
| 603 |
+
if printable_text:
|
| 604 |
+
yield printable_text
|
| 605 |
+
# If the last token is a CJK character, we can safely print it
|
| 606 |
+
elif len(text) > 0 and _is_cjk_char(ord(text[-1])):
|
| 607 |
+
printable_text = text[print_len:]
|
| 608 |
+
print_len += len(printable_text)
|
| 609 |
+
if printable_text:
|
| 610 |
+
yield printable_text
|
| 611 |
+
# Otherwise, only yield up to the last space to avoid cutting words
|
| 612 |
+
else:
|
| 613 |
+
last_space_idx = text.rfind(" ", print_len)
|
| 614 |
+
if last_space_idx >= print_len:
|
| 615 |
+
printable_text = text[print_len : last_space_idx + 1]
|
| 616 |
+
print_len += len(printable_text)
|
| 617 |
+
if printable_text:
|
| 618 |
+
yield printable_text
|
| 619 |
+
|
| 620 |
+
with torch.inference_mode():
|
| 621 |
+
next_emb = text_encoder(next_token, self.text)
|
| 622 |
+
mask[:, :, pos], pos_ids[0] = 1, pos
|
| 623 |
+
|
| 624 |
+
logits_BV, _ = self._decode_one_tok(next_emb, mask, pos_ids, lora)
|
| 625 |
+
logits_BV[:, self.config.tokenizer.answer_id] = float("-inf")
|
| 626 |
+
|
| 627 |
+
pos += 1
|
| 628 |
+
|
| 629 |
+
if temperature == 0:
|
| 630 |
+
next_token = torch.argmax(logits_BV, dim=-1).unsqueeze(
|
| 631 |
+
1
|
| 632 |
+
) # (1, 1)
|
| 633 |
+
else:
|
| 634 |
+
probs = torch.softmax(logits_BV / temperature, dim=-1) # (1, V)
|
| 635 |
+
probs = self._apply_top_p(probs, top_p)
|
| 636 |
+
next_token = torch.multinomial(probs, num_samples=1) # (1, 1)
|
| 637 |
+
|
| 638 |
+
generated_tokens += 1
|
| 639 |
+
|
| 640 |
+
# Flush any remaining text in the cache
|
| 641 |
+
if token_cache:
|
| 642 |
+
text = self.tokenizer.decode(token_cache)
|
| 643 |
+
printable_text = text[print_len:]
|
| 644 |
+
if printable_text:
|
| 645 |
+
yield printable_text
|
| 646 |
+
|
| 647 |
+
return generator(next_token, pos)
|
| 648 |
+
|
| 649 |
+
def query(
|
| 650 |
+
self,
|
| 651 |
+
image: Optional[Union[Image.Image, EncodedImage]] = None,
|
| 652 |
+
question: str = None,
|
| 653 |
+
reasoning: bool = True,
|
| 654 |
+
spatial_refs: Optional[SpatialRefs] = None,
|
| 655 |
+
stream: bool = False,
|
| 656 |
+
settings: Optional[TextSamplingSettings] = None,
|
| 657 |
+
):
|
| 658 |
+
if self.config.tokenizer.templates["query"] is None:
|
| 659 |
+
raise NotImplementedError("Model does not support querying.")
|
| 660 |
+
|
| 661 |
+
if question is None:
|
| 662 |
+
raise ValueError("question must be provided.")
|
| 663 |
+
|
| 664 |
+
if spatial_refs and image is None:
|
| 665 |
+
raise ValueError("spatial_refs can only be used with an image.")
|
| 666 |
+
|
| 667 |
+
attn_mask = self.attn_mask
|
| 668 |
+
if image is not None:
|
| 669 |
+
image = self.encode_image(image, settings)
|
| 670 |
+
self.load_encoded_image(image)
|
| 671 |
+
pos = image.pos
|
| 672 |
+
prompt_toks = self.config.tokenizer.templates["query"]["prefix"]
|
| 673 |
+
else:
|
| 674 |
+
self._setup_caches()
|
| 675 |
+
pos = 0
|
| 676 |
+
prompt_toks = [
|
| 677 |
+
self.config.tokenizer.bos_id
|
| 678 |
+
] + self.config.tokenizer.templates["query"]["prefix"]
|
| 679 |
+
max_context = self.config.text.max_context
|
| 680 |
+
attn_mask = torch.tril(
|
| 681 |
+
torch.ones(1, 1, max_context, max_context, dtype=torch.bool)
|
| 682 |
+
).to(self.device)
|
| 683 |
+
|
| 684 |
+
spatial_toks = []
|
| 685 |
+
if spatial_refs:
|
| 686 |
+
for ref in spatial_refs:
|
| 687 |
+
coord_id = self.config.tokenizer.coord_id
|
| 688 |
+
size_id = self.config.tokenizer.size_id
|
| 689 |
+
if len(ref) == 2:
|
| 690 |
+
spatial_toks.extend([coord_id, coord_id])
|
| 691 |
+
else:
|
| 692 |
+
spatial_toks.extend([coord_id, coord_id, size_id])
|
| 693 |
+
|
| 694 |
+
prompt_tokens = [
|
| 695 |
+
prompt_toks + spatial_toks + self.tokenizer.encode(question).ids
|
| 696 |
+
]
|
| 697 |
+
|
| 698 |
+
if reasoning:
|
| 699 |
+
prompt_tokens[0] += [self.config.tokenizer.thinking_id]
|
| 700 |
+
prompt_tokens = torch.tensor(prompt_tokens, device=self.device)
|
| 701 |
+
pos, reasoning_text, reasoning_grounding = self._generate_reasoning(
|
| 702 |
+
prompt_tokens, pos, settings, spatial_refs, attn_mask=attn_mask
|
| 703 |
+
)
|
| 704 |
+
prompt_tokens = [self.config.tokenizer.templates["query"]["suffix"]]
|
| 705 |
+
reasoning_dict = {
|
| 706 |
+
"reasoning": {"text": reasoning_text, "grounding": reasoning_grounding}
|
| 707 |
+
}
|
| 708 |
+
spatial_refs = None
|
| 709 |
+
else:
|
| 710 |
+
prompt_tokens[0] += self.config.tokenizer.templates["query"]["suffix"]
|
| 711 |
+
reasoning_dict = {}
|
| 712 |
+
|
| 713 |
+
prompt_tokens = torch.tensor(prompt_tokens, device=self.device)
|
| 714 |
+
|
| 715 |
+
def generator():
|
| 716 |
+
for token in self._generate_answer(
|
| 717 |
+
prompt_tokens, pos, settings, spatial_refs, attn_mask=attn_mask
|
| 718 |
+
):
|
| 719 |
+
yield token
|
| 720 |
+
|
| 721 |
+
if stream:
|
| 722 |
+
return {**reasoning_dict, "answer": generator()}
|
| 723 |
+
else:
|
| 724 |
+
return {**reasoning_dict, "answer": "".join(list(generator()))}
|
| 725 |
+
|
| 726 |
+
def load_encoded_image(self, encoded_image: EncodedImage):
|
| 727 |
+
for b, (k, v) in zip(self.text.blocks, encoded_image.caches):
|
| 728 |
+
b.kv_cache.k_cache[:, :, : k.size(2), :] = k
|
| 729 |
+
b.kv_cache.v_cache[:, :, : v.size(2), :] = v
|
| 730 |
+
|
| 731 |
+
def caption(
|
| 732 |
+
self,
|
| 733 |
+
image: Union[Image.Image, EncodedImage],
|
| 734 |
+
length: Literal["normal", "short", "long"] = "normal",
|
| 735 |
+
stream: bool = False,
|
| 736 |
+
settings: Optional[TextSamplingSettings] = None,
|
| 737 |
+
):
|
| 738 |
+
if self.config.tokenizer.templates["caption"] is None:
|
| 739 |
+
raise NotImplementedError("Model does not support captioning.")
|
| 740 |
+
if length not in self.config.tokenizer.templates["caption"]:
|
| 741 |
+
raise ValueError(f"Model does not support caption length '{length}'.")
|
| 742 |
+
|
| 743 |
+
image = self.encode_image(image, settings)
|
| 744 |
+
self.load_encoded_image(image)
|
| 745 |
+
|
| 746 |
+
prompt_tokens = torch.tensor(
|
| 747 |
+
[self.config.tokenizer.templates["caption"][length]], device=self.device
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
def generator():
|
| 751 |
+
for token in self._generate_answer(prompt_tokens, image.pos, settings):
|
| 752 |
+
yield token
|
| 753 |
+
|
| 754 |
+
if stream:
|
| 755 |
+
return {"caption": generator()}
|
| 756 |
+
else:
|
| 757 |
+
return {"caption": "".join(list(generator()))}
|
| 758 |
+
|
| 759 |
+
def _generate_points(
|
| 760 |
+
self,
|
| 761 |
+
hidden: torch.Tensor,
|
| 762 |
+
next_token: torch.Tensor,
|
| 763 |
+
pos: int,
|
| 764 |
+
include_size: bool = True,
|
| 765 |
+
max_objects: int = DEFAULT_MAX_OBJECTS,
|
| 766 |
+
lora: Optional[dict] = None,
|
| 767 |
+
):
|
| 768 |
+
out = []
|
| 769 |
+
mask = torch.zeros(
|
| 770 |
+
1, 1, self.config.text.max_context, device=self.device, dtype=torch.bool
|
| 771 |
+
)
|
| 772 |
+
mask[:, :, :pos] = 1
|
| 773 |
+
pos_ids = torch.tensor([pos], device=self.device, dtype=torch.long)
|
| 774 |
+
|
| 775 |
+
with torch.inference_mode():
|
| 776 |
+
while (
|
| 777 |
+
next_token.item() != self.config.tokenizer.eos_id
|
| 778 |
+
and len(out) < max_objects
|
| 779 |
+
):
|
| 780 |
+
x_logits = decode_coordinate(hidden, self.region)
|
| 781 |
+
x_center = torch.argmax(x_logits, dim=-1) / x_logits.size(-1)
|
| 782 |
+
next_emb = encode_coordinate(
|
| 783 |
+
x_center.to(dtype=x_logits.dtype), self.region
|
| 784 |
+
).unsqueeze(0)
|
| 785 |
+
|
| 786 |
+
# Decode y-coordinate
|
| 787 |
+
mask[:, :, pos], pos_ids[0] = 1, pos
|
| 788 |
+
_, hidden = self._decode_one_tok(next_emb, mask, pos_ids, lora)
|
| 789 |
+
pos += 1
|
| 790 |
+
y_logits = decode_coordinate(hidden, self.region)
|
| 791 |
+
y_center = torch.argmax(y_logits, dim=-1) / y_logits.size(-1)
|
| 792 |
+
next_emb = encode_coordinate(
|
| 793 |
+
y_center.to(dtype=y_logits.dtype), self.region
|
| 794 |
+
).unsqueeze(0)
|
| 795 |
+
|
| 796 |
+
# Decode size
|
| 797 |
+
if include_size:
|
| 798 |
+
mask[:, :, pos], pos_ids[0] = 1, pos
|
| 799 |
+
logits, hidden = self._decode_one_tok(next_emb, mask, pos_ids, lora)
|
| 800 |
+
pos += 1
|
| 801 |
+
size_logits = decode_size(hidden, self.region)
|
| 802 |
+
|
| 803 |
+
# Get bin indices from the logits
|
| 804 |
+
w_bin = torch.argmax(size_logits[0], dim=-1)
|
| 805 |
+
h_bin = torch.argmax(size_logits[1], dim=-1)
|
| 806 |
+
|
| 807 |
+
# Convert from bin indices to actual size values using the inverse of the log-scale mapping
|
| 808 |
+
# Formula: size = 2^((bin / 1023.0) * 10.0 - 10.0)
|
| 809 |
+
w = torch.pow(2.0, (w_bin.float() / 1023.0) * 10.0 - 10.0)
|
| 810 |
+
h = torch.pow(2.0, (h_bin.float() / 1023.0) * 10.0 - 10.0)
|
| 811 |
+
|
| 812 |
+
next_emb = (
|
| 813 |
+
encode_size(
|
| 814 |
+
torch.tensor(
|
| 815 |
+
[w, h], device=self.device, dtype=size_logits.dtype
|
| 816 |
+
),
|
| 817 |
+
self.region,
|
| 818 |
+
)
|
| 819 |
+
.unsqueeze(0)
|
| 820 |
+
.unsqueeze(0)
|
| 821 |
+
)
|
| 822 |
+
|
| 823 |
+
# Add object
|
| 824 |
+
out.append(
|
| 825 |
+
{
|
| 826 |
+
"x_min": x_center.item() - w.item() / 2,
|
| 827 |
+
"y_min": y_center.item() - h.item() / 2,
|
| 828 |
+
"x_max": x_center.item() + w.item() / 2,
|
| 829 |
+
"y_max": y_center.item() + h.item() / 2,
|
| 830 |
+
}
|
| 831 |
+
)
|
| 832 |
+
else:
|
| 833 |
+
out.append({"x": x_center.item(), "y": y_center.item()})
|
| 834 |
+
|
| 835 |
+
# Decode next token (x-coordinate, or eos)
|
| 836 |
+
mask[:, :, pos], pos_ids[0] = 1, pos
|
| 837 |
+
logits, hidden = self._decode_one_tok(
|
| 838 |
+
next_emb,
|
| 839 |
+
mask,
|
| 840 |
+
pos_ids,
|
| 841 |
+
lora,
|
| 842 |
+
lm_head_indices=self.point_gen_indices,
|
| 843 |
+
)
|
| 844 |
+
pos += 1
|
| 845 |
+
# Map back: index 0 -> coord_id, index 1 -> eos_id
|
| 846 |
+
next_token_idx = torch.argmax(logits, dim=-1)
|
| 847 |
+
next_token = self.point_gen_indices[next_token_idx]
|
| 848 |
+
|
| 849 |
+
return out
|
| 850 |
+
|
| 851 |
+
def detect(
|
| 852 |
+
self,
|
| 853 |
+
image: Union[Image.Image, EncodedImage],
|
| 854 |
+
object: str,
|
| 855 |
+
settings: Optional[ObjectSamplingSettings] = None,
|
| 856 |
+
):
|
| 857 |
+
if self.config.tokenizer.templates["detect"] is None:
|
| 858 |
+
raise NotImplementedError("Model does not support object detection.")
|
| 859 |
+
|
| 860 |
+
image = self.encode_image(image, settings)
|
| 861 |
+
self.load_encoded_image(image)
|
| 862 |
+
|
| 863 |
+
prompt_tokens = torch.tensor(
|
| 864 |
+
[
|
| 865 |
+
self.config.tokenizer.templates["detect"]["prefix"]
|
| 866 |
+
+ self.tokenizer.encode(" " + object).ids
|
| 867 |
+
+ self.config.tokenizer.templates["detect"]["suffix"]
|
| 868 |
+
],
|
| 869 |
+
device=self.device,
|
| 870 |
+
)
|
| 871 |
+
|
| 872 |
+
lora = self._resolve_lora(settings)
|
| 873 |
+
|
| 874 |
+
_, hidden, next_token, pos = self._prefill_prompt(
|
| 875 |
+
prompt_tokens, image.pos, temperature=0, top_p=0, lora=lora
|
| 876 |
+
)
|
| 877 |
+
hidden = hidden[:, -1:, :]
|
| 878 |
+
|
| 879 |
+
max_objects = (
|
| 880 |
+
settings.get("max_objects", DEFAULT_MAX_OBJECTS)
|
| 881 |
+
if settings
|
| 882 |
+
else DEFAULT_MAX_OBJECTS
|
| 883 |
+
)
|
| 884 |
+
objects = self._generate_points(
|
| 885 |
+
hidden,
|
| 886 |
+
next_token,
|
| 887 |
+
pos,
|
| 888 |
+
include_size=True,
|
| 889 |
+
max_objects=max_objects,
|
| 890 |
+
lora=lora,
|
| 891 |
+
)
|
| 892 |
+
|
| 893 |
+
return {"objects": objects}
|
| 894 |
+
|
| 895 |
+
def point(
|
| 896 |
+
self,
|
| 897 |
+
image: Union[Image.Image, EncodedImage],
|
| 898 |
+
object: str,
|
| 899 |
+
settings: Optional[ObjectSamplingSettings] = None,
|
| 900 |
+
):
|
| 901 |
+
if self.config.tokenizer.templates["point"] is None:
|
| 902 |
+
raise NotImplementedError("Model does not support pointing.")
|
| 903 |
+
|
| 904 |
+
image = self.encode_image(image, settings)
|
| 905 |
+
self.load_encoded_image(image)
|
| 906 |
+
|
| 907 |
+
prompt_tokens = torch.tensor(
|
| 908 |
+
[
|
| 909 |
+
self.config.tokenizer.templates["point"]["prefix"]
|
| 910 |
+
+ self.tokenizer.encode(" " + object).ids
|
| 911 |
+
+ self.config.tokenizer.templates["point"]["suffix"]
|
| 912 |
+
],
|
| 913 |
+
device=self.device,
|
| 914 |
+
)
|
| 915 |
+
|
| 916 |
+
lora = self._resolve_lora(settings)
|
| 917 |
+
|
| 918 |
+
_, hidden, next_token, pos = self._prefill_prompt(
|
| 919 |
+
prompt_tokens, image.pos, temperature=0, top_p=0, lora=lora
|
| 920 |
+
)
|
| 921 |
+
hidden = hidden[:, -1:, :]
|
| 922 |
+
|
| 923 |
+
max_objects = (
|
| 924 |
+
settings.get("max_objects", DEFAULT_MAX_OBJECTS)
|
| 925 |
+
if settings
|
| 926 |
+
else DEFAULT_MAX_OBJECTS
|
| 927 |
+
)
|
| 928 |
+
objects = self._generate_points(
|
| 929 |
+
hidden,
|
| 930 |
+
next_token,
|
| 931 |
+
pos,
|
| 932 |
+
include_size=False,
|
| 933 |
+
max_objects=max_objects,
|
| 934 |
+
lora=lora,
|
| 935 |
+
)
|
| 936 |
+
|
| 937 |
+
return {"points": objects}
|
| 938 |
+
|
| 939 |
+
def _detect_gaze(
|
| 940 |
+
self,
|
| 941 |
+
image: EncodedImage,
|
| 942 |
+
source: Tuple[float, float],
|
| 943 |
+
force_detect: bool = False,
|
| 944 |
+
):
|
| 945 |
+
with torch.inference_mode():
|
| 946 |
+
before_emb = text_encoder(
|
| 947 |
+
torch.tensor(
|
| 948 |
+
[self.tokenizer.encode("\n\nPoint:").ids], device=self.device
|
| 949 |
+
),
|
| 950 |
+
self.text,
|
| 951 |
+
)
|
| 952 |
+
after_emb = text_encoder(
|
| 953 |
+
torch.tensor(
|
| 954 |
+
[self.tokenizer.encode(" gaze\n\n").ids], device=self.device
|
| 955 |
+
),
|
| 956 |
+
self.text,
|
| 957 |
+
)
|
| 958 |
+
x_emb = encode_coordinate(
|
| 959 |
+
torch.tensor([[[source[0]]]], device=self.device, dtype=torch.bfloat16),
|
| 960 |
+
self.region,
|
| 961 |
+
)
|
| 962 |
+
y_emb = encode_coordinate(
|
| 963 |
+
torch.tensor([[[source[1]]]], device=self.device, dtype=torch.bfloat16),
|
| 964 |
+
self.region,
|
| 965 |
+
)
|
| 966 |
+
|
| 967 |
+
prompt_emb = torch.cat([before_emb, x_emb, y_emb, after_emb], dim=1)
|
| 968 |
+
|
| 969 |
+
self.load_encoded_image(image)
|
| 970 |
+
|
| 971 |
+
mask = self.attn_mask[:, :, image.pos : image.pos + prompt_emb.size(1), :]
|
| 972 |
+
pos_ids = torch.arange(
|
| 973 |
+
image.pos,
|
| 974 |
+
image.pos + prompt_emb.size(1),
|
| 975 |
+
dtype=torch.long,
|
| 976 |
+
device=self.device,
|
| 977 |
+
)
|
| 978 |
+
hidden = self._prefill(prompt_emb, mask, pos_ids, lora=None)
|
| 979 |
+
logits = lm_head(hidden, self.text)
|
| 980 |
+
next_token = torch.argmax(logits, dim=-1)
|
| 981 |
+
pos = image.pos + prompt_emb.size(1)
|
| 982 |
+
hidden = hidden[:, -1:, :]
|
| 983 |
+
|
| 984 |
+
if force_detect:
|
| 985 |
+
next_token = torch.tensor([[0]], device=self.device)
|
| 986 |
+
|
| 987 |
+
if next_token.item() == self.config.tokenizer.eos_id:
|
| 988 |
+
return None
|
| 989 |
+
|
| 990 |
+
gaze = self._generate_points(
|
| 991 |
+
hidden, next_token, pos, include_size=False, max_objects=1
|
| 992 |
+
)
|
| 993 |
+
return gaze[0]
|
| 994 |
+
|
| 995 |
+
def detect_gaze(
|
| 996 |
+
self,
|
| 997 |
+
image: Union[Image.Image, EncodedImage],
|
| 998 |
+
eye: Optional[Tuple[float, float]] = None,
|
| 999 |
+
face: Optional[Dict[str, float]] = None,
|
| 1000 |
+
unstable_settings: Dict[str, Any] = {},
|
| 1001 |
+
):
|
| 1002 |
+
if "force_detect" in unstable_settings:
|
| 1003 |
+
force_detect = unstable_settings["force_detect"]
|
| 1004 |
+
else:
|
| 1005 |
+
force_detect = False
|
| 1006 |
+
|
| 1007 |
+
if "prioritize_accuracy" in unstable_settings:
|
| 1008 |
+
prioritize_accuracy = unstable_settings["prioritize_accuracy"]
|
| 1009 |
+
else:
|
| 1010 |
+
prioritize_accuracy = False
|
| 1011 |
+
|
| 1012 |
+
if not prioritize_accuracy:
|
| 1013 |
+
if eye is None:
|
| 1014 |
+
raise ValueError("eye must be provided when prioritize_accuracy=False")
|
| 1015 |
+
image = self.encode_image(image)
|
| 1016 |
+
return {"gaze": self._detect_gaze(image, eye, force_detect=force_detect)}
|
| 1017 |
+
else:
|
| 1018 |
+
if (
|
| 1019 |
+
not isinstance(image, Image.Image)
|
| 1020 |
+
and "flip_enc_img" not in unstable_settings
|
| 1021 |
+
):
|
| 1022 |
+
raise ValueError(
|
| 1023 |
+
"image must be a PIL Image when prioritize_accuracy=True, "
|
| 1024 |
+
"or flip_enc_img must be provided"
|
| 1025 |
+
)
|
| 1026 |
+
if face is None:
|
| 1027 |
+
raise ValueError("face must be provided when prioritize_accuracy=True")
|
| 1028 |
+
|
| 1029 |
+
encoded_image = self.encode_image(image)
|
| 1030 |
+
if (
|
| 1031 |
+
isinstance(image, Image.Image)
|
| 1032 |
+
and "flip_enc_img" not in unstable_settings
|
| 1033 |
+
):
|
| 1034 |
+
flipped_pil = image.copy()
|
| 1035 |
+
flipped_pil = flipped_pil.transpose(method=Image.FLIP_LEFT_RIGHT)
|
| 1036 |
+
encoded_flipped_image = self.encode_image(flipped_pil)
|
| 1037 |
+
else:
|
| 1038 |
+
encoded_flipped_image = unstable_settings["flip_enc_img"]
|
| 1039 |
+
|
| 1040 |
+
N = 10
|
| 1041 |
+
|
| 1042 |
+
detections = [
|
| 1043 |
+
self._detect_gaze(
|
| 1044 |
+
encoded_image,
|
| 1045 |
+
(
|
| 1046 |
+
random.uniform(face["x_min"], face["x_max"]),
|
| 1047 |
+
random.uniform(face["y_min"], face["y_max"]),
|
| 1048 |
+
),
|
| 1049 |
+
force_detect=force_detect,
|
| 1050 |
+
)
|
| 1051 |
+
for _ in range(N)
|
| 1052 |
+
]
|
| 1053 |
+
detections = [
|
| 1054 |
+
(gaze["x"], gaze["y"]) for gaze in detections if gaze is not None
|
| 1055 |
+
]
|
| 1056 |
+
flipped_detections = [
|
| 1057 |
+
self._detect_gaze(
|
| 1058 |
+
encoded_flipped_image,
|
| 1059 |
+
(
|
| 1060 |
+
1 - random.uniform(face["x_min"], face["x_max"]),
|
| 1061 |
+
random.uniform(face["y_min"], face["y_max"]),
|
| 1062 |
+
),
|
| 1063 |
+
force_detect=force_detect,
|
| 1064 |
+
)
|
| 1065 |
+
for _ in range(N)
|
| 1066 |
+
]
|
| 1067 |
+
detections.extend(
|
| 1068 |
+
[
|
| 1069 |
+
(1 - gaze["x"], gaze["y"])
|
| 1070 |
+
for gaze in flipped_detections
|
| 1071 |
+
if gaze is not None
|
| 1072 |
+
]
|
| 1073 |
+
)
|
| 1074 |
+
|
| 1075 |
+
if len(detections) < N:
|
| 1076 |
+
return {"gaze": None}
|
| 1077 |
+
|
| 1078 |
+
detections = remove_outlier_points(detections)
|
| 1079 |
+
mean_gaze = (
|
| 1080 |
+
sum(gaze[0] for gaze in detections) / len(detections),
|
| 1081 |
+
sum(gaze[1] for gaze in detections) / len(detections),
|
| 1082 |
+
)
|
| 1083 |
+
|
| 1084 |
+
return {"gaze": {"x": mean_gaze[0], "y": mean_gaze[1]}}
|
| 1085 |
+
|
| 1086 |
+
|
| 1087 |
+
def _is_cjk_char(cp):
|
| 1088 |
+
"""Checks whether CP is the codepoint of a CJK character."""
|
| 1089 |
+
# This defines a "chinese character" as anything in the CJK Unicode block:
|
| 1090 |
+
# https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
|
| 1091 |
+
if (
|
| 1092 |
+
(cp >= 0x4E00 and cp <= 0x9FFF)
|
| 1093 |
+
or (cp >= 0x3400 and cp <= 0x4DBF)
|
| 1094 |
+
or (cp >= 0x2F800 and cp <= 0x2FA1F)
|
| 1095 |
+
):
|
| 1096 |
+
return True
|
| 1097 |
+
return False
|
region.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import math
|
| 4 |
+
|
| 5 |
+
from typing import List, Tuple, Union
|
| 6 |
+
|
| 7 |
+
SpatialRefs = List[Union[Tuple[float, float], Tuple[float, float, float, float]]]
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def fourier_features(x: torch.Tensor, w: torch.Tensor) -> torch.Tensor:
|
| 11 |
+
"""
|
| 12 |
+
Applies Fourier feature mapping to input tensor x using frequency matrix w. This
|
| 13 |
+
projects inputs through sinusoidal functions to create higher dimensional features
|
| 14 |
+
that help mitigate spectral bias - the tendency of neural networks to learn
|
| 15 |
+
low-frequency functions more easily than high-frequency ones. By explicitly
|
| 16 |
+
mapping inputs to higher frequencies through sin/cos transformations, we enable
|
| 17 |
+
better learning of fine details and higher frequency patterns.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
x: Input tensor to transform
|
| 21 |
+
w: Matrix of frequencies for the Fourier features transformation
|
| 22 |
+
|
| 23 |
+
Returns:
|
| 24 |
+
Concatenated cosine and sine transformed features as a tensor
|
| 25 |
+
"""
|
| 26 |
+
f = 2 * math.pi * x @ w
|
| 27 |
+
return torch.cat([f.cos(), f.sin()], dim=-1)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def encode_coordinate(coord: torch.Tensor, w: nn.Module) -> torch.Tensor:
|
| 31 |
+
"""
|
| 32 |
+
Takes as input a tensor containing a single float coordinate value (x or y)
|
| 33 |
+
and encodes it into hidden states for input to the text model.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
coord: Tensor with single float coordinate value
|
| 37 |
+
|
| 38 |
+
Returns:
|
| 39 |
+
Encoded hidden states tensor for input to text model
|
| 40 |
+
"""
|
| 41 |
+
return w.coord_encoder(fourier_features(coord, w.coord_features))
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def decode_coordinate(hidden_state: torch.Tensor, w: nn.Module) -> torch.Tensor:
|
| 45 |
+
"""
|
| 46 |
+
Takes as input the last hidden state from the text model and outputs a single logit
|
| 47 |
+
representing either an x or y coordinate prediction.
|
| 48 |
+
|
| 49 |
+
Args:
|
| 50 |
+
hidden_state: The final hidden state tensor from the text model.
|
| 51 |
+
|
| 52 |
+
Returns:
|
| 53 |
+
A single logit representing the predicted coordinate value (x or y)
|
| 54 |
+
"""
|
| 55 |
+
hidden_state = w.ln(hidden_state)
|
| 56 |
+
return w.coord_decoder(hidden_state)
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def encode_size(size: torch.Tensor, w: nn.Module) -> torch.Tensor:
|
| 60 |
+
"""
|
| 61 |
+
Takes a tensor containing width and height values and encodes them into
|
| 62 |
+
hidden states for input to the text model.
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
size: Tensor with two floats for width and height
|
| 66 |
+
|
| 67 |
+
Returns:
|
| 68 |
+
Encoded hidden states tensor for input to text model
|
| 69 |
+
"""
|
| 70 |
+
return w.size_encoder(fourier_features(size, w.size_features))
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def decode_size(hidden_state: torch.Tensor, w: nn.Module) -> torch.Tensor:
|
| 74 |
+
"""
|
| 75 |
+
Takes as input the last hidden state from the text model and outputs logits
|
| 76 |
+
for 1024 bins representing width and height in log-scale.
|
| 77 |
+
|
| 78 |
+
The bins are distributed according to the formula:
|
| 79 |
+
bin = (log2(size) + 10.0) / 10.0 * 1023.0
|
| 80 |
+
where size values are clamped to be at least 1/1024.
|
| 81 |
+
|
| 82 |
+
To convert from bin back to size:
|
| 83 |
+
size = 2^((bin / 1023.0) * 10.0 - 10.0)
|
| 84 |
+
|
| 85 |
+
Args:
|
| 86 |
+
hidden_state: The final hidden state tensor from the text model.
|
| 87 |
+
|
| 88 |
+
Returns:
|
| 89 |
+
A tensor containing logits for 1024 bins for width and height.
|
| 90 |
+
Shape is (2, 1024) where the first dimension corresponds to width and height.
|
| 91 |
+
"""
|
| 92 |
+
hidden_state = w.ln(hidden_state)
|
| 93 |
+
return w.size_decoder(hidden_state).view(2, -1)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def encode_spatial_refs(spatial_refs: SpatialRefs, w: nn.Module) -> torch.Tensor:
|
| 97 |
+
"""
|
| 98 |
+
Takes a list of spatial references (points or regions) and encodes them into
|
| 99 |
+
hidden states for input to the text model.
|
| 100 |
+
|
| 101 |
+
Args:
|
| 102 |
+
spatial_refs: List of spatial references (points or boxes)
|
| 103 |
+
- Points are represented as normalized (x, y) tuples
|
| 104 |
+
- Boxes are represented as normalized (x_min, y_min, x_max, y_max) tuples
|
| 105 |
+
|
| 106 |
+
Returns:
|
| 107 |
+
{"coords": torch.Tensor, "sizes": Optional[torch.Tensor]}
|
| 108 |
+
"""
|
| 109 |
+
coords, sizes = [], []
|
| 110 |
+
for ref in spatial_refs:
|
| 111 |
+
if len(ref) == 2:
|
| 112 |
+
coords.append(ref[0])
|
| 113 |
+
coords.append(ref[1])
|
| 114 |
+
else:
|
| 115 |
+
x_c = (ref[0] + ref[2]) / 2
|
| 116 |
+
y_c = (ref[1] + ref[3]) / 2
|
| 117 |
+
width = ref[2] - ref[0]
|
| 118 |
+
height = ref[3] - ref[1]
|
| 119 |
+
coords.append(x_c)
|
| 120 |
+
coords.append(y_c)
|
| 121 |
+
sizes.append([width, height])
|
| 122 |
+
|
| 123 |
+
coords = torch.tensor(
|
| 124 |
+
coords, device=w.coord_features.device, dtype=w.coord_features.dtype
|
| 125 |
+
).view(-1, 1)
|
| 126 |
+
coords = encode_coordinate(coords, w)
|
| 127 |
+
|
| 128 |
+
if sizes:
|
| 129 |
+
sizes = torch.tensor(
|
| 130 |
+
sizes, device=w.size_features.device, dtype=w.size_features.dtype
|
| 131 |
+
)
|
| 132 |
+
sizes = encode_size(sizes, w)
|
| 133 |
+
else:
|
| 134 |
+
sizes = None
|
| 135 |
+
|
| 136 |
+
return {"coords": coords, "sizes": sizes}
|
rope.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ethically sourced from https://github.com/xjdr-alt/entropix
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def precompute_freqs_cis(
|
| 7 |
+
dim: int,
|
| 8 |
+
end: int,
|
| 9 |
+
theta: float = 1500000.0,
|
| 10 |
+
dtype: torch.dtype = torch.float32,
|
| 11 |
+
) -> torch.Tensor:
|
| 12 |
+
freqs = 1.0 / (theta ** (torch.arange(0, dim, 2, dtype=dtype)[: (dim // 2)] / dim))
|
| 13 |
+
t = torch.arange(end, dtype=dtype).unsqueeze(1)
|
| 14 |
+
freqs = t * freqs.unsqueeze(0)
|
| 15 |
+
freqs = torch.exp(1j * freqs)
|
| 16 |
+
return torch.stack([freqs.real, freqs.imag], dim=-1)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def apply_rotary_emb(
|
| 20 |
+
x: torch.Tensor,
|
| 21 |
+
freqs_cis: torch.Tensor,
|
| 22 |
+
position_ids: torch.Tensor,
|
| 23 |
+
num_heads: int,
|
| 24 |
+
rot_dim: int = 32,
|
| 25 |
+
interleave: bool = False,
|
| 26 |
+
) -> torch.Tensor:
|
| 27 |
+
assert rot_dim == freqs_cis.shape[-2] * 2
|
| 28 |
+
assert num_heads == x.shape[1]
|
| 29 |
+
|
| 30 |
+
x_rot, x_pass = x[..., :rot_dim], x[..., rot_dim:]
|
| 31 |
+
|
| 32 |
+
if interleave:
|
| 33 |
+
xq_r = x_rot.float().reshape(*x_rot.shape[:-1], -1, 2)[..., 0]
|
| 34 |
+
xq_i = x_rot.float().reshape(*x_rot.shape[:-1], -1, 2)[..., 1]
|
| 35 |
+
else:
|
| 36 |
+
d_q = x_rot.shape[-1] // 2
|
| 37 |
+
xq_r, xq_i = x_rot[..., :d_q], x_rot[..., d_q:]
|
| 38 |
+
|
| 39 |
+
freqs_cos = freqs_cis[..., 0][position_ids, :].unsqueeze(0).unsqueeze(0)
|
| 40 |
+
freqs_sin = freqs_cis[..., 1][position_ids, :].unsqueeze(0).unsqueeze(0)
|
| 41 |
+
|
| 42 |
+
# Complex multiplication: (a + bi) * (c + di) = (ac - bd) + (ad + bc)i
|
| 43 |
+
xq_out_r = xq_r * freqs_cos - xq_i * freqs_sin
|
| 44 |
+
xq_out_i = xq_r * freqs_sin + xq_i * freqs_cos
|
| 45 |
+
xq_out = torch.stack((xq_out_r, xq_out_i), dim=-1).flatten(-2)
|
| 46 |
+
|
| 47 |
+
return torch.cat([xq_out.to(x.dtype), x_pass], dim=-1)
|
text.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
|
| 4 |
+
from torch.nn import functional as F
|
| 5 |
+
from torch.nn.attention.flex_attention import flex_attention
|
| 6 |
+
from typing import Optional
|
| 7 |
+
|
| 8 |
+
from .layers import layer_norm, mlp, QuantizedLinear, moe_mlp
|
| 9 |
+
from .rope import apply_rotary_emb, precompute_freqs_cis
|
| 10 |
+
from .config import TextConfig
|
| 11 |
+
from .lora import select_layer_lora
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def text_encoder(input_ids: torch.Tensor, w: nn.Module):
|
| 15 |
+
return F.embedding(input_ids, w.wte)
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def attn(
|
| 19 |
+
x: torch.Tensor,
|
| 20 |
+
w: nn.Module,
|
| 21 |
+
freqs_cis: torch.Tensor,
|
| 22 |
+
kv_cache: nn.Module,
|
| 23 |
+
attn_mask: torch.Tensor,
|
| 24 |
+
n_heads: int,
|
| 25 |
+
n_kv_heads: int,
|
| 26 |
+
position_ids: torch.Tensor,
|
| 27 |
+
flex_block_mask_slice=None,
|
| 28 |
+
):
|
| 29 |
+
bsz, q_len, d_model = x.shape
|
| 30 |
+
head_dim = d_model // n_heads
|
| 31 |
+
|
| 32 |
+
qkv_out = w.qkv(x) # shape: (bsz, q_len, (n_heads + 2*n_kv_heads)*head_dim)
|
| 33 |
+
q_dim = n_heads * head_dim
|
| 34 |
+
kv_dim = n_kv_heads * head_dim
|
| 35 |
+
q, k, v = qkv_out.split([q_dim, kv_dim, kv_dim], dim=-1)
|
| 36 |
+
|
| 37 |
+
q = q.view(bsz, q_len, n_heads, head_dim).transpose(1, 2)
|
| 38 |
+
k = k.view(bsz, q_len, n_kv_heads, head_dim).transpose(1, 2)
|
| 39 |
+
v = v.view(bsz, q_len, n_kv_heads, head_dim).transpose(1, 2)
|
| 40 |
+
|
| 41 |
+
if hasattr(w, "tau") and w.tau is not None:
|
| 42 |
+
tok_feat = F.gelu(qkv_out)
|
| 43 |
+
tok_q = torch.tanh(torch.matmul(tok_feat, w.tau["wq"].t())).permute(0, 2, 1)
|
| 44 |
+
tok_v = torch.tanh(torch.matmul(tok_feat, w.tau["wv"].t())).permute(0, 2, 1)
|
| 45 |
+
pos = position_ids.to(q.dtype) + 1
|
| 46 |
+
tau_pos = 1 + (
|
| 47 |
+
torch.sigmoid(w.tau["alpha"][:, None] * pos.log()) - 0.5
|
| 48 |
+
) # (H,S)
|
| 49 |
+
tau_q = (tok_q + tau_pos[None]).unsqueeze(-1) # (B,H,S,1)
|
| 50 |
+
tau_v = (tok_v + tau_pos[None]).unsqueeze(-1)
|
| 51 |
+
q = q * tau_q
|
| 52 |
+
v = v * tau_v
|
| 53 |
+
|
| 54 |
+
q = apply_rotary_emb(q, freqs_cis, position_ids, n_heads)
|
| 55 |
+
k = apply_rotary_emb(k, freqs_cis, position_ids, n_kv_heads)
|
| 56 |
+
|
| 57 |
+
if kv_cache is not None:
|
| 58 |
+
k, v = kv_cache.update(position_ids, k, v)
|
| 59 |
+
|
| 60 |
+
if flex_block_mask_slice is not None:
|
| 61 |
+
torch._assert(n_heads == n_kv_heads, "gqa not supported yet")
|
| 62 |
+
out = flex_attention(q, k, v, block_mask=flex_block_mask_slice)
|
| 63 |
+
else:
|
| 64 |
+
out = F.scaled_dot_product_attention(
|
| 65 |
+
q, k, v, attn_mask=attn_mask, enable_gqa=n_heads != n_kv_heads
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
out = out.transpose(1, 2).reshape(bsz, q_len, d_model)
|
| 69 |
+
|
| 70 |
+
return w.proj(out)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def text_decoder(
|
| 74 |
+
x: torch.Tensor,
|
| 75 |
+
w: nn.Module,
|
| 76 |
+
attn_mask: torch.Tensor,
|
| 77 |
+
position_ids: torch.Tensor,
|
| 78 |
+
config: TextConfig,
|
| 79 |
+
lora: Optional[object] = None,
|
| 80 |
+
flex_block_mask_slice=None,
|
| 81 |
+
):
|
| 82 |
+
for i, block in enumerate(w.blocks):
|
| 83 |
+
layer_lora = select_layer_lora(
|
| 84 |
+
lora, i, is_moe=config.moe is not None and i >= config.moe.start_layer
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
l_in = layer_norm(x, block.ln)
|
| 88 |
+
l_attn = attn(
|
| 89 |
+
l_in,
|
| 90 |
+
block.attn,
|
| 91 |
+
freqs_cis=w.freqs_cis,
|
| 92 |
+
kv_cache=block.kv_cache,
|
| 93 |
+
attn_mask=attn_mask,
|
| 94 |
+
n_heads=config.n_heads,
|
| 95 |
+
n_kv_heads=config.n_kv_heads,
|
| 96 |
+
position_ids=position_ids,
|
| 97 |
+
flex_block_mask_slice=flex_block_mask_slice,
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
if config.moe is not None and i >= config.moe.start_layer:
|
| 101 |
+
l_mlp = moe_mlp(
|
| 102 |
+
l_in, block.mlp, config.moe.experts_per_token, lora=layer_lora
|
| 103 |
+
)
|
| 104 |
+
else:
|
| 105 |
+
l_mlp = mlp(l_in, block.mlp, lora=layer_lora)
|
| 106 |
+
|
| 107 |
+
x = x + l_attn + l_mlp
|
| 108 |
+
|
| 109 |
+
return x
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def lm_head(
|
| 113 |
+
hidden_BTC: torch.Tensor, w: nn.Module, indices: Optional[torch.Tensor] = None
|
| 114 |
+
):
|
| 115 |
+
hidden_BC = hidden_BTC[:, -1, :]
|
| 116 |
+
hidden_BC = layer_norm(hidden_BC, w.post_ln)
|
| 117 |
+
if indices is not None:
|
| 118 |
+
# Only compute logits for specified token indices
|
| 119 |
+
logits = hidden_BC @ w.lm_head.weight[indices].T + w.lm_head.bias[indices]
|
| 120 |
+
else:
|
| 121 |
+
logits = w.lm_head(hidden_BC)
|
| 122 |
+
return logits
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def build_dense_mlp(d_model, d_ffn, dtype, linear_cls):
|
| 126 |
+
return nn.ModuleDict(
|
| 127 |
+
{
|
| 128 |
+
"fc1": linear_cls(d_model, d_ffn, dtype=dtype),
|
| 129 |
+
"fc2": linear_cls(d_ffn, d_model, dtype=dtype),
|
| 130 |
+
}
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def build_moe_mlp(d_model, d_ffn, n_experts, dtype):
|
| 135 |
+
# For GeGLU, fc1 needs to output 2 * d_ffn (for gating)
|
| 136 |
+
mlp = nn.ModuleDict(
|
| 137 |
+
{
|
| 138 |
+
"router": nn.Linear(d_model, n_experts, dtype=dtype),
|
| 139 |
+
"fc1": nn.ParameterDict(
|
| 140 |
+
{
|
| 141 |
+
"weight": nn.Parameter(
|
| 142 |
+
torch.empty(n_experts, 2 * d_ffn, d_model, dtype=dtype)
|
| 143 |
+
)
|
| 144 |
+
}
|
| 145 |
+
),
|
| 146 |
+
"fc2": nn.ParameterDict(
|
| 147 |
+
{
|
| 148 |
+
"weight": nn.Parameter(
|
| 149 |
+
torch.empty(n_experts, d_model, d_ffn, dtype=dtype)
|
| 150 |
+
)
|
| 151 |
+
}
|
| 152 |
+
),
|
| 153 |
+
}
|
| 154 |
+
)
|
| 155 |
+
return mlp
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def build_text_model(config: TextConfig, dtype: torch.dtype) -> nn.Module:
|
| 159 |
+
qkv_dim = int(config.dim * (1 + 2 * config.n_kv_heads / config.n_heads))
|
| 160 |
+
linear_cls = QuantizedLinear if config.group_size is not None else nn.Linear
|
| 161 |
+
|
| 162 |
+
text = nn.ModuleDict(
|
| 163 |
+
{
|
| 164 |
+
"blocks": nn.ModuleList(
|
| 165 |
+
[
|
| 166 |
+
nn.ModuleDict(
|
| 167 |
+
{
|
| 168 |
+
"ln": nn.LayerNorm(config.dim, dtype=dtype),
|
| 169 |
+
"attn": nn.ModuleDict(
|
| 170 |
+
{
|
| 171 |
+
"qkv": linear_cls(config.dim, qkv_dim, dtype=dtype),
|
| 172 |
+
"proj": linear_cls(
|
| 173 |
+
config.dim, config.dim, dtype=dtype
|
| 174 |
+
),
|
| 175 |
+
"tau": nn.ParameterDict(
|
| 176 |
+
{
|
| 177 |
+
"wq": nn.Parameter(
|
| 178 |
+
torch.empty(
|
| 179 |
+
config.n_heads, qkv_dim, dtype=dtype
|
| 180 |
+
)
|
| 181 |
+
),
|
| 182 |
+
"wv": nn.Parameter(
|
| 183 |
+
torch.empty(
|
| 184 |
+
config.n_heads, qkv_dim, dtype=dtype
|
| 185 |
+
)
|
| 186 |
+
),
|
| 187 |
+
"alpha": nn.Parameter(
|
| 188 |
+
torch.empty(config.n_heads, dtype=dtype)
|
| 189 |
+
),
|
| 190 |
+
}
|
| 191 |
+
),
|
| 192 |
+
}
|
| 193 |
+
),
|
| 194 |
+
"mlp": (
|
| 195 |
+
build_moe_mlp(
|
| 196 |
+
config.dim,
|
| 197 |
+
config.moe.expert_inner_dim,
|
| 198 |
+
config.moe.num_experts,
|
| 199 |
+
dtype,
|
| 200 |
+
)
|
| 201 |
+
if config.moe is not None
|
| 202 |
+
and layer_idx >= config.moe.start_layer
|
| 203 |
+
else build_dense_mlp(
|
| 204 |
+
config.dim, config.ff_dim, dtype, linear_cls
|
| 205 |
+
)
|
| 206 |
+
),
|
| 207 |
+
}
|
| 208 |
+
)
|
| 209 |
+
for layer_idx in range(config.n_layers)
|
| 210 |
+
]
|
| 211 |
+
),
|
| 212 |
+
"post_ln": nn.LayerNorm(config.dim, dtype=dtype),
|
| 213 |
+
"lm_head": nn.Linear(config.dim, config.vocab_size, dtype=dtype),
|
| 214 |
+
}
|
| 215 |
+
)
|
| 216 |
+
text.wte = nn.Parameter(torch.empty(config.vocab_size, config.dim, dtype=dtype))
|
| 217 |
+
text.register_buffer(
|
| 218 |
+
"freqs_cis",
|
| 219 |
+
precompute_freqs_cis(config.dim // (2 * config.n_heads), config.max_context),
|
| 220 |
+
persistent=False,
|
| 221 |
+
)
|
| 222 |
+
|
| 223 |
+
return text
|
utils.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def remove_outlier_points(points_tuples, k_nearest=2, threshold=2.0):
|
| 5 |
+
"""
|
| 6 |
+
Robust outlier detection for list of (x,y) tuples.
|
| 7 |
+
Only requires numpy.
|
| 8 |
+
|
| 9 |
+
Args:
|
| 10 |
+
points_tuples: list of (x,y) tuples
|
| 11 |
+
k_nearest: number of neighbors to consider
|
| 12 |
+
threshold: multiplier for median distance
|
| 13 |
+
|
| 14 |
+
Returns:
|
| 15 |
+
list: filtered list of (x,y) tuples with outliers removed
|
| 16 |
+
list: list of booleans indicating which points were kept (True = kept)
|
| 17 |
+
"""
|
| 18 |
+
points = np.array(points_tuples)
|
| 19 |
+
n_points = len(points)
|
| 20 |
+
|
| 21 |
+
# Calculate pairwise distances manually
|
| 22 |
+
dist_matrix = np.zeros((n_points, n_points))
|
| 23 |
+
for i in range(n_points):
|
| 24 |
+
for j in range(i + 1, n_points):
|
| 25 |
+
# Euclidean distance between points i and j
|
| 26 |
+
dist = np.sqrt(np.sum((points[i] - points[j]) ** 2))
|
| 27 |
+
dist_matrix[i, j] = dist
|
| 28 |
+
dist_matrix[j, i] = dist
|
| 29 |
+
|
| 30 |
+
# Get k nearest neighbors' distances
|
| 31 |
+
k = min(k_nearest, n_points - 1)
|
| 32 |
+
neighbor_distances = np.partition(dist_matrix, k, axis=1)[:, :k]
|
| 33 |
+
avg_neighbor_dist = np.mean(neighbor_distances, axis=1)
|
| 34 |
+
|
| 35 |
+
# Calculate mask using median distance
|
| 36 |
+
median_dist = np.median(avg_neighbor_dist)
|
| 37 |
+
mask = avg_neighbor_dist <= threshold * median_dist
|
| 38 |
+
|
| 39 |
+
# Return filtered tuples and mask
|
| 40 |
+
filtered_tuples = [t for t, m in zip(points_tuples, mask) if m]
|
| 41 |
+
return filtered_tuples
|
vision.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
import numpy as np
|
| 5 |
+
|
| 6 |
+
from typing import Union, Tuple
|
| 7 |
+
from PIL import Image
|
| 8 |
+
|
| 9 |
+
from .layers import attn, layer_norm, mlp
|
| 10 |
+
from .image_crops import overlap_crop_image
|
| 11 |
+
from .config import VisionConfig
|
| 12 |
+
|
| 13 |
+
if torch.backends.mps.is_available():
|
| 14 |
+
# Non-divisible input sizes are not implemented on MPS device yet.
|
| 15 |
+
# https://github.com/pytorch/pytorch/issues/96056
|
| 16 |
+
def adaptive_avg_pool2d(input, output_size):
|
| 17 |
+
return F.adaptive_avg_pool2d(input.to("cpu"), output_size).to("mps")
|
| 18 |
+
|
| 19 |
+
else:
|
| 20 |
+
adaptive_avg_pool2d = F.adaptive_avg_pool2d
|
| 21 |
+
|
| 22 |
+
DeviceLike = Union[str, torch.device, int]
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def prepare_crops(
|
| 26 |
+
image: Image.Image, config: VisionConfig, device: DeviceLike
|
| 27 |
+
) -> Tuple[torch.Tensor, Tuple[int, int]]:
|
| 28 |
+
np_image = np.array(image.convert("RGB"))
|
| 29 |
+
overlap_crops = overlap_crop_image(
|
| 30 |
+
np_image, max_crops=config.max_crops, overlap_margin=config.overlap_margin
|
| 31 |
+
)
|
| 32 |
+
all_crops = overlap_crops["crops"]
|
| 33 |
+
all_crops = np.transpose(all_crops, (0, 3, 1, 2))
|
| 34 |
+
all_crops = (
|
| 35 |
+
torch.from_numpy(all_crops)
|
| 36 |
+
.to(device=device, dtype=torch.bfloat16)
|
| 37 |
+
.div_(255.0)
|
| 38 |
+
.sub_(0.5)
|
| 39 |
+
.div_(0.5)
|
| 40 |
+
)
|
| 41 |
+
return all_crops, overlap_crops["tiling"]
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def create_patches(x, patch_size):
|
| 45 |
+
# Original shape: [B, C, H, W]
|
| 46 |
+
B, C, H, W = x.shape
|
| 47 |
+
P1 = P2 = patch_size
|
| 48 |
+
|
| 49 |
+
# Step 1: Split H and W dimensions into patches
|
| 50 |
+
# [B, C, H/P1, P1, W/P2, P2]
|
| 51 |
+
x = x.reshape(B, C, H // P1, P1, W // P2, P2)
|
| 52 |
+
|
| 53 |
+
# Step 2: Rearrange dimensions to match target shape
|
| 54 |
+
# [B, H/P1, W/P2, C, P1, P2]
|
| 55 |
+
x = x.permute(0, 2, 4, 1, 3, 5)
|
| 56 |
+
|
| 57 |
+
# Step 3: Combine dimensions to get final shape
|
| 58 |
+
# [B, (H/P1)*(W/P2), C*P1*P2]
|
| 59 |
+
x = x.reshape(B, (H // P1) * (W // P2), C * P1 * P2)
|
| 60 |
+
|
| 61 |
+
return x
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def vision_encoder(input_BCHW: torch.Tensor, w: nn.Module, config: VisionConfig):
|
| 65 |
+
x = create_patches(input_BCHW, config.enc_patch_size)
|
| 66 |
+
|
| 67 |
+
x = w.patch_emb(x)
|
| 68 |
+
x = x + w.pos_emb
|
| 69 |
+
for block in w.blocks:
|
| 70 |
+
x = x + attn(layer_norm(x, block.ln1), block.attn, n_heads=config.enc_n_heads)
|
| 71 |
+
x = x + mlp(layer_norm(x, block.ln2), block.mlp)
|
| 72 |
+
x = layer_norm(x, w.post_ln)
|
| 73 |
+
|
| 74 |
+
return x
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def vision_projection(
|
| 78 |
+
global_features: torch.Tensor,
|
| 79 |
+
reconstructed: torch.Tensor,
|
| 80 |
+
w: nn.Module,
|
| 81 |
+
config: VisionConfig,
|
| 82 |
+
):
|
| 83 |
+
reconstructed = reconstructed.permute(2, 0, 1)
|
| 84 |
+
reconstructed = adaptive_avg_pool2d(
|
| 85 |
+
reconstructed, output_size=(config.enc_n_layers, config.enc_n_layers)
|
| 86 |
+
)
|
| 87 |
+
reconstructed = reconstructed.permute(1, 2, 0).view(729, config.enc_dim)
|
| 88 |
+
final_features = torch.cat([global_features, reconstructed], dim=-1)
|
| 89 |
+
return mlp(final_features, w.proj_mlp)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def build_vision_model(config: VisionConfig, dtype: torch.dtype):
|
| 93 |
+
patch_dim = config.enc_patch_size * config.enc_patch_size * config.in_channels
|
| 94 |
+
grid_size = config.crop_size // config.enc_patch_size
|
| 95 |
+
num_patches = grid_size * grid_size
|
| 96 |
+
|
| 97 |
+
vision = nn.ModuleDict(
|
| 98 |
+
{
|
| 99 |
+
"patch_emb": nn.Linear(patch_dim, config.enc_dim, dtype=dtype),
|
| 100 |
+
"blocks": nn.ModuleList(
|
| 101 |
+
[
|
| 102 |
+
nn.ModuleDict(
|
| 103 |
+
{
|
| 104 |
+
"ln1": nn.LayerNorm(config.enc_dim, dtype=dtype),
|
| 105 |
+
"attn": nn.ModuleDict(
|
| 106 |
+
{
|
| 107 |
+
"qkv": nn.Linear(
|
| 108 |
+
config.enc_dim, 3 * config.enc_dim, dtype=dtype
|
| 109 |
+
),
|
| 110 |
+
"proj": nn.Linear(
|
| 111 |
+
config.enc_dim, config.enc_dim, dtype=dtype
|
| 112 |
+
),
|
| 113 |
+
}
|
| 114 |
+
),
|
| 115 |
+
"ln2": nn.LayerNorm(config.enc_dim, dtype=dtype),
|
| 116 |
+
"mlp": nn.ModuleDict(
|
| 117 |
+
{
|
| 118 |
+
"fc1": nn.Linear(
|
| 119 |
+
config.enc_dim, config.enc_ff_dim, dtype=dtype
|
| 120 |
+
),
|
| 121 |
+
"fc2": nn.Linear(
|
| 122 |
+
config.enc_ff_dim, config.enc_dim, dtype=dtype
|
| 123 |
+
),
|
| 124 |
+
}
|
| 125 |
+
),
|
| 126 |
+
}
|
| 127 |
+
)
|
| 128 |
+
for _ in range(config.enc_n_layers)
|
| 129 |
+
]
|
| 130 |
+
),
|
| 131 |
+
"post_ln": nn.LayerNorm(config.enc_dim, dtype=dtype),
|
| 132 |
+
"proj_mlp": nn.ModuleDict(
|
| 133 |
+
{
|
| 134 |
+
"fc1": nn.Linear(
|
| 135 |
+
config.enc_dim * 2, config.proj_inner_dim, dtype=dtype
|
| 136 |
+
),
|
| 137 |
+
"fc2": nn.Linear(
|
| 138 |
+
config.proj_inner_dim, config.proj_out_dim, dtype=dtype
|
| 139 |
+
),
|
| 140 |
+
}
|
| 141 |
+
),
|
| 142 |
+
}
|
| 143 |
+
)
|
| 144 |
+
vision.pos_emb = nn.Parameter(
|
| 145 |
+
torch.zeros(1, num_patches, config.enc_dim, dtype=dtype)
|
| 146 |
+
)
|
| 147 |
+
return vision
|