Instructions to use UCSC-VLAA/openvision2-vit-large-patch14-336-vision-only with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- OpenCLIP
How to use UCSC-VLAA/openvision2-vit-large-patch14-336-vision-only with OpenCLIP:
import open_clip model, preprocess_train, preprocess_val = open_clip.create_model_and_transforms('hf-hub:UCSC-VLAA/openvision2-vit-large-patch14-336-vision-only') tokenizer = open_clip.get_tokenizer('hf-hub:UCSC-VLAA/openvision2-vit-large-patch14-336-vision-only') - Notebooks
- Google Colab
- Kaggle
Add caption text decoder (encoder + decoder = full OpenVision2 generative model)
Browse files- README.md +47 -0
- bert_base_vocab_bos_eos.txt +0 -0
- caption_decoder.safetensors +3 -0
- caption_example.py +72 -0
- modeling_openvision2_decoder.py +155 -0
- text_decoder_config.json +17 -0
README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
pipeline_tag: image-to-text
|
| 3 |
+
tags:
|
| 4 |
+
- openvision2
|
| 5 |
+
- image-captioning
|
| 6 |
+
- vision-encoder
|
| 7 |
+
library_name: open_clip
|
| 8 |
+
---
|
| 9 |
+
|
| 10 |
+
# OpenVision2 · L/14 @336 — vision encoder + caption decoder
|
| 11 |
+
|
| 12 |
+
This repo now contains the **full OpenVision2 generative model**: the **vision encoder**
|
| 13 |
+
(originally released here) **plus the caption text decoder** it was jointly trained with.
|
| 14 |
+
Together they map an image -> a descriptive caption. The encoder files are unchanged;
|
| 15 |
+
only the decoder (and this card) were added.
|
| 16 |
+
|
| 17 |
+
## Files
|
| 18 |
+
| file | role |
|
| 19 |
+
|---|---|
|
| 20 |
+
| `open_clip_pytorch_model.bin`, `open_clip_config.json` | L/14 vision encoder (open_clip format) |
|
| 21 |
+
| `caption_decoder.safetensors` | caption text decoder weights |
|
| 22 |
+
| `text_decoder_config.json` | decoder architecture config |
|
| 23 |
+
| `modeling_openvision2_decoder.py` | standalone PyTorch decoder + `generate()` |
|
| 24 |
+
| `bert_base_vocab_bos_eos.txt` | tokenizer vocab (`[PAD]=0 [bos]=1 [eos]=2`) |
|
| 25 |
+
| `caption_example.py` | end-to-end image -> caption demo |
|
| 26 |
+
|
| 27 |
+
## Decoder architecture
|
| 28 |
+
A **concat / prefix-LM** autoregressive transformer (not a CoCa cross-attention decoder):
|
| 29 |
+
ViT patch tokens are linearly projected and **prepended as a bidirectional prefix**, and
|
| 30 |
+
text is generated **causally** while attending to all image tokens.
|
| 31 |
+
|
| 32 |
+
`12 layers · width 768 · 12 heads · mlp 3072 · vocab 32000 ·
|
| 33 |
+
pre-LN · gelu(tanh) · LayerNorm eps 1e-6 · no positional embedding on the text stream.`
|
| 34 |
+
It consumes the encoder's pre-final-norm patch tokens (open_clip `output_tokens=True`).
|
| 35 |
+
|
| 36 |
+
## Usage
|
| 37 |
+
Needs the patched `open_clip` providing `create_vision_encoder_and_transforms`
|
| 38 |
+
(https://github.com/UCSC-VLAA/OpenVision), plus `torch`, `safetensors`, `pillow`.
|
| 39 |
+
See `caption_example.py`:
|
| 40 |
+
|
| 41 |
+
```bash
|
| 42 |
+
python caption_example.py --image your.jpg
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
## Notes
|
| 46 |
+
- Encoder and decoder are a **matched pair** exported from the same training checkpoint.
|
| 47 |
+
- Captions are LLaVA-style **dense** descriptions (multi-sentence, detailed).
|
bert_base_vocab_bos_eos.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
caption_decoder.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0241150fd5f5327e9fa5048a005f8ed82912a29b894b8c2be6151a37226558aa
|
| 3 |
+
size 539991872
|
caption_example.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
r'''
|
| 2 |
+
OpenVision2 ViT-H/14 @224 — image -> caption demo.
|
| 3 |
+
|
| 4 |
+
Combines the released vision encoder (this repo, open_clip format) with the caption
|
| 5 |
+
text decoder (this repo). Requires the patched open_clip that ships
|
| 6 |
+
`create_vision_encoder_and_transforms` (from the OpenVision repo:
|
| 7 |
+
https://github.com/UCSC-VLAA/OpenVision), plus torch / safetensors / pillow.
|
| 8 |
+
|
| 9 |
+
python caption_example.py --image path/to/img.jpg
|
| 10 |
+
'''
|
| 11 |
+
import argparse, json
|
| 12 |
+
import numpy as np, torch
|
| 13 |
+
from PIL import Image
|
| 14 |
+
from huggingface_hub import hf_hub_download
|
| 15 |
+
from open_clip.factory import create_vision_encoder_and_transforms # patched open_clip
|
| 16 |
+
from modeling_openvision2_decoder import OpenVision2TextDecoder, OpenVision2TextDecoderConfig
|
| 17 |
+
from safetensors.torch import load_file
|
| 18 |
+
|
| 19 |
+
REPO = "UCSC-VLAA/openvision2-vit-large-patch14-336-vision-only"
|
| 20 |
+
IMAGENET_MEAN = np.array([0.485, 0.456, 0.406]) * 255
|
| 21 |
+
IMAGENET_STD = np.array([0.229, 0.224, 0.225]) * 255
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def preprocess(path, res=224):
|
| 25 |
+
im = Image.open(path).convert("RGB")
|
| 26 |
+
w, h = im.size; s = res / min(w, h)
|
| 27 |
+
im = im.resize((round(w * s), round(h * s)), Image.BILINEAR)
|
| 28 |
+
w, h = im.size; l, t = (w - res) // 2, (h - res) // 2
|
| 29 |
+
im = im.crop((l, t, l + res, t + res))
|
| 30 |
+
x = (np.asarray(im, np.float32) - IMAGENET_MEAN) / IMAGENET_STD
|
| 31 |
+
return torch.tensor(x.transpose(2, 0, 1)[None], dtype=torch.float32) # [1,C,H,W]
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def load_decoder(cache_dir=None):
|
| 35 |
+
cfg = json.load(open(hf_hub_download(REPO, "text_decoder_config.json", cache_dir=cache_dir)))
|
| 36 |
+
dec = OpenVision2TextDecoder(OpenVision2TextDecoderConfig(
|
| 37 |
+
width=cfg["width"], depth=cfg["depth"], num_heads=cfg["num_heads"], mlp_dim=cfg["mlp_dim"],
|
| 38 |
+
vocab_size=cfg["vocab_size"], vision_width=cfg["vision_width"]))
|
| 39 |
+
dec.load_state_dict(load_file(hf_hub_download(REPO, "caption_decoder.safetensors", cache_dir=cache_dir)))
|
| 40 |
+
dec.eval()
|
| 41 |
+
vocab = [l.rstrip("\n") for l in open(hf_hub_download(REPO, "bert_base_vocab_bos_eos.txt", cache_dir=cache_dir))]
|
| 42 |
+
return dec, vocab
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def detok(ids, vocab):
|
| 46 |
+
w = []
|
| 47 |
+
for i in ids:
|
| 48 |
+
if i == 2: break # eos
|
| 49 |
+
if i in (0, 1, 2): continue # pad / bos / eos
|
| 50 |
+
tk = vocab[i] if 0 <= i < len(vocab) else "[UNK]"
|
| 51 |
+
if tk.startswith("##"): w[-1] = (w[-1] + tk[2:]) if w else tk[2:]
|
| 52 |
+
else: w.append(tk)
|
| 53 |
+
return " ".join(w)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def main():
|
| 57 |
+
ap = argparse.ArgumentParser()
|
| 58 |
+
ap.add_argument("--image", required=True)
|
| 59 |
+
ap.add_argument("--max_len", type=int, default=64)
|
| 60 |
+
ap.add_argument("--cache_dir", default=None)
|
| 61 |
+
args = ap.parse_args()
|
| 62 |
+
|
| 63 |
+
enc = create_vision_encoder_and_transforms(model_name=f"hf-hub:{REPO}", cache_dir=args.cache_dir).eval()
|
| 64 |
+
dec, vocab = load_decoder(args.cache_dir)
|
| 65 |
+
with torch.no_grad():
|
| 66 |
+
_, tokens = enc(preprocess(args.image)) # [1, N, 1280]
|
| 67 |
+
ids = dec.generate(tokens, max_len=args.max_len, bos_id=1, eos_id=2)[0].tolist()
|
| 68 |
+
print(detok(ids, vocab))
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
if __name__ == "__main__":
|
| 72 |
+
main()
|
modeling_openvision2_decoder.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""PyTorch reference implementation of the OpenVision2 caption decoder.
|
| 2 |
+
|
| 3 |
+
The OpenVision2 generative model is: a ViT vision encoder (released separately as
|
| 4 |
+
the `*-vision-only` open_clip checkpoint) whose patch tokens condition a small
|
| 5 |
+
autoregressive text decoder trained with a captioning loss.
|
| 6 |
+
|
| 7 |
+
This decoder is a **prefix-LM / concat-fusion** transformer (NOT a CoCa-style
|
| 8 |
+
cross-attention decoder):
|
| 9 |
+
|
| 10 |
+
text_embeds = Embed(text_tokens) # no positional embedding
|
| 11 |
+
image_embeds = image_projection(vit_patch_tokens) # Linear, no bias
|
| 12 |
+
x = concat([image_embeds, text_embeds], 1) # [B, N_img + L, width]
|
| 13 |
+
x = prefix_lm_transformer(x) # image=bidirectional prefix,
|
| 14 |
+
# text=causal, text->image=full,
|
| 15 |
+
# image-/->text
|
| 16 |
+
logits = lm_head( ln_final( x[:, N_img:] ) ) # over text positions
|
| 17 |
+
|
| 18 |
+
Faithful details that matter for numerical parity with the JAX model:
|
| 19 |
+
* LayerNorm eps = 1e-6 (flax default), pre-LN blocks.
|
| 20 |
+
* MLP activation = gelu(tanh approximation).
|
| 21 |
+
* attention scale = head_dim ** -0.5.
|
| 22 |
+
* NO positional embedding on the text stream.
|
| 23 |
+
* vision patch tokens are the pre-final-norm tokens, cls excluded
|
| 24 |
+
(open_clip vision model with output_tokens=True returns exactly these).
|
| 25 |
+
"""
|
| 26 |
+
from dataclasses import dataclass
|
| 27 |
+
from typing import Optional
|
| 28 |
+
import torch
|
| 29 |
+
import torch.nn as nn
|
| 30 |
+
import torch.nn.functional as F
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
@dataclass
|
| 34 |
+
class OpenVision2TextDecoderConfig:
|
| 35 |
+
width: int = 1024 # decoder hidden width (H decoder -> 1024)
|
| 36 |
+
depth: int = 24 # number of transformer blocks
|
| 37 |
+
num_heads: int = 16
|
| 38 |
+
mlp_dim: int = 4096
|
| 39 |
+
vocab_size: int = 32000
|
| 40 |
+
vision_width: int = 1280 # ViT token dim feeding image_projection (H ViT -> 1280)
|
| 41 |
+
layer_norm_eps: float = 1e-6
|
| 42 |
+
pad_id: int = 0
|
| 43 |
+
bos_id: int = 1
|
| 44 |
+
eos_id: int = 2
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
class _Mlp(nn.Module):
|
| 48 |
+
def __init__(self, width: int, mlp_dim: int):
|
| 49 |
+
super().__init__()
|
| 50 |
+
self.c_fc = nn.Linear(width, mlp_dim)
|
| 51 |
+
self.c_proj = nn.Linear(mlp_dim, width)
|
| 52 |
+
|
| 53 |
+
def forward(self, x):
|
| 54 |
+
return self.c_proj(F.gelu(self.c_fc(x), approximate="tanh"))
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class _Attention(nn.Module):
|
| 58 |
+
"""MHA with a fused in_proj (q,k,v) and an explicit boolean attend-mask."""
|
| 59 |
+
|
| 60 |
+
def __init__(self, width: int, num_heads: int):
|
| 61 |
+
super().__init__()
|
| 62 |
+
assert width % num_heads == 0
|
| 63 |
+
self.num_heads = num_heads
|
| 64 |
+
self.head_dim = width // num_heads
|
| 65 |
+
self.scale = self.head_dim ** -0.5
|
| 66 |
+
self.in_proj_weight = nn.Parameter(torch.empty(3 * width, width))
|
| 67 |
+
self.in_proj_bias = nn.Parameter(torch.zeros(3 * width))
|
| 68 |
+
self.out_proj = nn.Linear(width, width)
|
| 69 |
+
|
| 70 |
+
def forward(self, x, attend_mask):
|
| 71 |
+
# attend_mask: [L, L] bool, True = keep, False = -inf
|
| 72 |
+
B, L, D = x.shape
|
| 73 |
+
qkv = F.linear(x, self.in_proj_weight, self.in_proj_bias)
|
| 74 |
+
q, k, v = qkv.chunk(3, dim=-1)
|
| 75 |
+
H, hd = self.num_heads, self.head_dim
|
| 76 |
+
q = q.view(B, L, H, hd).transpose(1, 2) # [B,H,L,hd]
|
| 77 |
+
k = k.view(B, L, H, hd).transpose(1, 2)
|
| 78 |
+
v = v.view(B, L, H, hd).transpose(1, 2)
|
| 79 |
+
attn = (q @ k.transpose(-2, -1)) * self.scale # [B,H,L,L]
|
| 80 |
+
attn = attn.masked_fill(~attend_mask[None, None], float("-inf"))
|
| 81 |
+
attn = attn.softmax(dim=-1)
|
| 82 |
+
out = attn @ v # [B,H,L,hd]
|
| 83 |
+
out = out.transpose(1, 2).reshape(B, L, D)
|
| 84 |
+
return self.out_proj(out)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class _Block(nn.Module):
|
| 88 |
+
def __init__(self, cfg: OpenVision2TextDecoderConfig):
|
| 89 |
+
super().__init__()
|
| 90 |
+
self.ln_1 = nn.LayerNorm(cfg.width, eps=cfg.layer_norm_eps)
|
| 91 |
+
self.attn = _Attention(cfg.width, cfg.num_heads)
|
| 92 |
+
self.ln_2 = nn.LayerNorm(cfg.width, eps=cfg.layer_norm_eps)
|
| 93 |
+
self.mlp = _Mlp(cfg.width, cfg.mlp_dim)
|
| 94 |
+
|
| 95 |
+
def forward(self, x, attend_mask):
|
| 96 |
+
x = x + self.attn(self.ln_1(x), attend_mask)
|
| 97 |
+
x = x + self.mlp(self.ln_2(x))
|
| 98 |
+
return x
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
class OpenVision2TextDecoder(nn.Module):
|
| 102 |
+
def __init__(self, cfg: OpenVision2TextDecoderConfig):
|
| 103 |
+
super().__init__()
|
| 104 |
+
self.cfg = cfg
|
| 105 |
+
self.token_embedding = nn.Embedding(cfg.vocab_size, cfg.width)
|
| 106 |
+
self.image_projection = nn.Linear(cfg.vision_width, cfg.width, bias=False)
|
| 107 |
+
self.blocks = nn.ModuleList([_Block(cfg) for _ in range(cfg.depth)])
|
| 108 |
+
self.ln_final = nn.LayerNorm(cfg.width, eps=cfg.layer_norm_eps)
|
| 109 |
+
self.lm_head = nn.Linear(cfg.width, cfg.vocab_size, bias=False)
|
| 110 |
+
|
| 111 |
+
@staticmethod
|
| 112 |
+
def _prefix_lm_mask(li: int, lt: int, device) -> torch.Tensor:
|
| 113 |
+
"""[l, l] bool attend-mask. image(:li) bidirectional prefix; text(li:)
|
| 114 |
+
causal + attends all image; image does NOT attend text."""
|
| 115 |
+
l = li + lt
|
| 116 |
+
mask = torch.zeros(l, l, dtype=torch.bool, device=device)
|
| 117 |
+
mask[:li, :li] = True # image <-> image
|
| 118 |
+
mask[li:, :li] = True # text -> image
|
| 119 |
+
text_causal = torch.tril(torch.ones(lt, lt, dtype=torch.bool, device=device))
|
| 120 |
+
mask[li:, li:] = text_causal # text causal self
|
| 121 |
+
return mask
|
| 122 |
+
|
| 123 |
+
def forward(self, image_tokens: torch.Tensor, text_tokens: torch.Tensor) -> torch.Tensor:
|
| 124 |
+
"""image_tokens: [B, N_img, vision_width]; text_tokens: [B, L] (input side).
|
| 125 |
+
Returns logits [B, L, vocab] (next-token logits at each text position)."""
|
| 126 |
+
text_embeds = self.token_embedding(text_tokens) # [B, L, width]
|
| 127 |
+
image_embeds = self.image_projection(image_tokens) # [B, N_img, width]
|
| 128 |
+
li, lt = image_embeds.shape[1], text_embeds.shape[1]
|
| 129 |
+
x = torch.cat([image_embeds, text_embeds], dim=1) # [B, li+lt, width]
|
| 130 |
+
mask = self._prefix_lm_mask(li, lt, x.device)
|
| 131 |
+
for blk in self.blocks:
|
| 132 |
+
x = blk(x, mask)
|
| 133 |
+
x = x[:, li:] # text positions
|
| 134 |
+
x = self.ln_final(x)
|
| 135 |
+
return self.lm_head(x)
|
| 136 |
+
|
| 137 |
+
@torch.no_grad()
|
| 138 |
+
def generate(self, image_tokens: torch.Tensor, max_len: int = 64,
|
| 139 |
+
bos_id: Optional[int] = None, eos_id: Optional[int] = None) -> torch.Tensor:
|
| 140 |
+
"""Greedy autoregressive caption generation. image_tokens: [B, N, vision_width]."""
|
| 141 |
+
bos_id = self.cfg.bos_id if bos_id is None else bos_id
|
| 142 |
+
eos_id = self.cfg.eos_id if eos_id is None else eos_id
|
| 143 |
+
B = image_tokens.shape[0]
|
| 144 |
+
device = image_tokens.device
|
| 145 |
+
seq = torch.full((B, 1), bos_id, dtype=torch.long, device=device)
|
| 146 |
+
done = torch.zeros(B, dtype=torch.bool, device=device)
|
| 147 |
+
for _ in range(max_len):
|
| 148 |
+
logits = self.forward(image_tokens, seq) # [B, cur_len, vocab]
|
| 149 |
+
nxt = logits[:, -1].argmax(dim=-1) # [B]
|
| 150 |
+
nxt = torch.where(done, torch.full_like(nxt, self.cfg.pad_id), nxt)
|
| 151 |
+
seq = torch.cat([seq, nxt[:, None]], dim=1)
|
| 152 |
+
done = done | (nxt == eos_id)
|
| 153 |
+
if bool(done.all()):
|
| 154 |
+
break
|
| 155 |
+
return seq
|
text_decoder_config.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architecture": "OpenVision2TextDecoder",
|
| 3 |
+
"fusion_style": "concat",
|
| 4 |
+
"width": 768,
|
| 5 |
+
"depth": 12,
|
| 6 |
+
"num_heads": 12,
|
| 7 |
+
"mlp_dim": 3072,
|
| 8 |
+
"vocab_size": 32000,
|
| 9 |
+
"vision_width": 1024,
|
| 10 |
+
"layer_norm_eps": 1e-06,
|
| 11 |
+
"pad_id": 0,
|
| 12 |
+
"bos_id": 1,
|
| 13 |
+
"eos_id": 2,
|
| 14 |
+
"weights_file": "caption_decoder.safetensors",
|
| 15 |
+
"modeling_file": "modeling_openvision2_decoder.py",
|
| 16 |
+
"tokenizer": "bert wordpiece (bert_base_vocab_bos_eos.txt), lowercase, [PAD]=0 [bos]=1 [eos]=2"
|
| 17 |
+
}
|