1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Embedding-**model** registry — the interchangeable set of models behind the
// [`super::store::Embedder`] trait (plan item G3).
//
// Historically the embedder was hard-wired to `jina-embeddings-v2-base-code`
// (768-dim). This registry makes the *model* a selectable axis: a small table
// of known models, each carrying everything the rest of the system needs —
// the HuggingFace repo + file paths (for `build.rs` to fetch), the output
// dimensionality (so the index + warehouse are dimension-aware), the max
// context, and a stable `profile_id` that namespaces the model in the
// `model_profile` warehouse key.
//
// ## Why this file is `include!`-able with **no deps**
//
// `build.rs` needs the *same* registry the crate uses (so the model it fetches
// is exactly the model the embedder loads). build scripts can't depend on the
// crate's modules, so the registry is written as a self-contained, `std`-only
// table that `build.rs` pulls in via `include!`. Keep it that way: no `use` of
// sibling modules, no external crates — only `&'static str` / `usize` data and
// pure lookups.
//
// ## Selection
//
// [`selected`] resolves the active model from `$NORNIR_EMBED_MODEL` (a model
// `id`, e.g. `jina-v2-base-code`), falling back to [`DEFAULT_MODEL_ID`]. The
// **same** env var is read by `build.rs`, so the fetched weights and the
// loaded model never disagree.
//
// ## Re-embed awareness (IMPORTANT)
//
// Each model has a distinct `profile_id`, which flows into
// [`super::store::ModelProfile`] and thus into the warehouse `model_profile`
// key (a hash over `model_name` + weight/tokenizer SHAs + `dim` + …). **Vectors
// from two different models therefore land under different `model_profile`
// keys and never mix** — a search reconstructs only the snapshot whose
// `model_profile` matches the query embedder. The practical consequence:
// **switching `$NORNIR_EMBED_MODEL` requires a fresh `nornir vector index`** at
// the new model before semantic search returns results; old vectors aren't
// reused (different dim, different semantics) and aren't silently blended in.
/// One interchangeable embedding model. All fields are build-time-stable data;
/// the runtime weight/tokenizer SHAs (which also enter the `model_profile`) are
/// resolved separately by `build.rs` and passed via `rustc-env`.
/// Default model id. Unchanged behaviour: jina-embeddings-v2-base-code, 768-dim.
pub const DEFAULT_MODEL_ID: &str = "jina-v2-base-code";
/// The known embedding models. The first entry is the default and the only one
/// `build.rs` fetches unless `$NORNIR_EMBED_MODEL` selects another. Additional
/// entries make the registry + selection plumbing real and dimension-aware even
/// before their weights are fetched.
pub const MODELS: & = &;
/// Look a model up by its `id`. `None` if no such id is registered.
/// The default model (first registry entry). Infallible — the table is
/// non-empty by construction.
/// Resolve the env-selected model id (trimmed, lower-cased). Returns the raw
/// value so callers can produce a precise error for an unknown id. `None` ⇒ use
/// the default.
/// The active model: `$NORNIR_EMBED_MODEL` (by `id`) or the default. Errors with
/// the list of known ids if the env names an unknown model.