Spaces:
Sleeping
Sleeping
new upload restrictions
Browse files- backend/app/ccr.py +35 -7
- backend/app/jobs.py +2 -0
- backend/app/registry.py +6 -0
- backend/app/reproducibility.py +19 -2
- backend/tests/test_registry_and_prefixes.py +40 -0
- packages/model_registry/models.yaml +124 -0
backend/app/ccr.py
CHANGED
|
@@ -42,16 +42,39 @@ class SentenceTransformerBackend:
|
|
| 42 |
|
| 43 |
_cache: dict[str, object] = {}
|
| 44 |
|
| 45 |
-
def __init__(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
self.name = model_name
|
| 47 |
self.revision = revision
|
|
|
|
|
|
|
| 48 |
|
| 49 |
def _model(self):
|
| 50 |
if self.name not in self._cache:
|
| 51 |
from sentence_transformers import SentenceTransformer # lazy: heavy import
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
return self._cache[self.name]
|
| 56 |
|
| 57 |
@property
|
|
@@ -68,7 +91,7 @@ class SentenceTransformerBackend:
|
|
| 68 |
emb = model.encode(
|
| 69 |
texts[i : i + batch],
|
| 70 |
convert_to_numpy=True,
|
| 71 |
-
normalize_embeddings=True,
|
| 72 |
show_progress_bar=False,
|
| 73 |
)
|
| 74 |
out.append(emb)
|
|
@@ -115,7 +138,12 @@ def get_backend(model_id: str) -> EmbeddingBackend:
|
|
| 115 |
from . import registry # local import: engine stays importable without yaml deps
|
| 116 |
|
| 117 |
cfg = registry.get_model(model_id)
|
| 118 |
-
return SentenceTransformerBackend(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
|
| 121 |
@dataclass
|
|
@@ -201,8 +229,8 @@ def run_ccr(
|
|
| 201 |
doc_emb = encode_unique(backend, texts_for_encoding, progress_cb=doc_progress)
|
| 202 |
|
| 203 |
# Both matrices are L2-normalized -> cosine similarity is a dot product.
|
| 204 |
-
sims = doc_emb @ item_emb.T
|
| 205 |
-
scores = sims.mean(axis=1)
|
| 206 |
|
| 207 |
finished = datetime.now(timezone.utc)
|
| 208 |
items_hash = hashlib.sha256("\n".join(items).encode()).hexdigest()[:16]
|
|
|
|
| 42 |
|
| 43 |
_cache: dict[str, object] = {}
|
| 44 |
|
| 45 |
+
def __init__(
|
| 46 |
+
self,
|
| 47 |
+
model_name: str,
|
| 48 |
+
revision: str | None = None,
|
| 49 |
+
pooling_fallback: str | None = None,
|
| 50 |
+
max_seq_length: int | None = None,
|
| 51 |
+
):
|
| 52 |
self.name = model_name
|
| 53 |
self.revision = revision
|
| 54 |
+
self.pooling_fallback = pooling_fallback
|
| 55 |
+
self._max_seq_length = max_seq_length
|
| 56 |
|
| 57 |
def _model(self):
|
| 58 |
if self.name not in self._cache:
|
| 59 |
from sentence_transformers import SentenceTransformer # lazy: heavy import
|
| 60 |
|
| 61 |
+
if self.pooling_fallback:
|
| 62 |
+
# Registry-flagged repos ship modules.json without the pooling
|
| 63 |
+
# config it references, so auto-loading fails; build the module
|
| 64 |
+
# stack explicitly with the pooling the model card documents.
|
| 65 |
+
from sentence_transformers import models as st_models
|
| 66 |
+
|
| 67 |
+
margs = {"model_args": {"revision": self.revision}} if self.revision else {}
|
| 68 |
+
word = st_models.Transformer(
|
| 69 |
+
self.name, max_seq_length=self._max_seq_length, **margs
|
| 70 |
+
)
|
| 71 |
+
# renamed in newer sentence-transformers; support both
|
| 72 |
+
get_dim = getattr(word, "get_embedding_dimension", None) or word.get_word_embedding_dimension
|
| 73 |
+
pool = st_models.Pooling(get_dim(), pooling_mode=self.pooling_fallback)
|
| 74 |
+
self._cache[self.name] = SentenceTransformer(modules=[word, pool])
|
| 75 |
+
else:
|
| 76 |
+
kwargs = {"revision": self.revision} if self.revision else {}
|
| 77 |
+
self._cache[self.name] = SentenceTransformer(self.name, **kwargs)
|
| 78 |
return self._cache[self.name]
|
| 79 |
|
| 80 |
@property
|
|
|
|
| 91 |
emb = model.encode(
|
| 92 |
texts[i : i + batch],
|
| 93 |
convert_to_numpy=True,
|
| 94 |
+
normalize_embeddings=True, # scales every vector to length 1
|
| 95 |
show_progress_bar=False,
|
| 96 |
)
|
| 97 |
out.append(emb)
|
|
|
|
| 138 |
from . import registry # local import: engine stays importable without yaml deps
|
| 139 |
|
| 140 |
cfg = registry.get_model(model_id)
|
| 141 |
+
return SentenceTransformerBackend(
|
| 142 |
+
cfg.provider_model_id,
|
| 143 |
+
revision=cfg.pinned_revision,
|
| 144 |
+
pooling_fallback=cfg.pooling_fallback,
|
| 145 |
+
max_seq_length=cfg.max_seq_length,
|
| 146 |
+
)
|
| 147 |
|
| 148 |
|
| 149 |
@dataclass
|
|
|
|
| 229 |
doc_emb = encode_unique(backend, texts_for_encoding, progress_cb=doc_progress)
|
| 230 |
|
| 231 |
# Both matrices are L2-normalized -> cosine similarity is a dot product.
|
| 232 |
+
sims = doc_emb @ item_emb.T # similarity of every text to every item
|
| 233 |
+
scores = sims.mean(axis=1) # average across items = the CCR score
|
| 234 |
|
| 235 |
finished = datetime.now(timezone.utc)
|
| 236 |
items_hash = hashlib.sha256("\n".join(items).encode()).hexdigest()[:16]
|
backend/app/jobs.py
CHANGED
|
@@ -304,6 +304,8 @@ def run_job(job_id: str) -> None:
|
|
| 304 |
"model_registry_id": model_cfg.id if model_cfg else job.model_name,
|
| 305 |
"provider_model_id": model_cfg.provider_model_id if model_cfg else job.model_name,
|
| 306 |
"model_revision": model_cfg.revision if model_cfg else None,
|
|
|
|
|
|
|
| 307 |
"scoring": {"adjustment_strategy": "none", "aggregate": "mean_all_items"},
|
| 308 |
"output_schema": (
|
| 309 |
list(work_df.columns)
|
|
|
|
| 304 |
"model_registry_id": model_cfg.id if model_cfg else job.model_name,
|
| 305 |
"provider_model_id": model_cfg.provider_model_id if model_cfg else job.model_name,
|
| 306 |
"model_revision": model_cfg.revision if model_cfg else None,
|
| 307 |
+
"model_pooling_fallback": model_cfg.pooling_fallback if model_cfg else None,
|
| 308 |
+
"model_max_seq_length": model_cfg.max_seq_length if model_cfg else None,
|
| 309 |
"scoring": {"adjustment_strategy": "none", "aggregate": "mean_all_items"},
|
| 310 |
"output_schema": (
|
| 311 |
list(work_df.columns)
|
backend/app/registry.py
CHANGED
|
@@ -49,6 +49,11 @@ class ModelConfig:
|
|
| 49 |
text_prefix: str
|
| 50 |
normalize_embeddings: bool
|
| 51 |
lazy_load: bool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
user_warnings: tuple[str, ...] = field(default_factory=tuple)
|
| 53 |
|
| 54 |
@property
|
|
@@ -89,6 +94,7 @@ def _parse_model(raw: dict, lang_sets) -> ModelConfig:
|
|
| 89 |
text_prefix=usage.get("text_prefix") or sym or "",
|
| 90 |
normalize_embeddings=bool(usage.get("normalize_embeddings", True)),
|
| 91 |
lazy_load=bool(ops.get("lazy_load", False)),
|
|
|
|
| 92 |
user_warnings=tuple(raw.get("warnings", []) or []),
|
| 93 |
)
|
| 94 |
|
|
|
|
| 49 |
text_prefix: str
|
| 50 |
normalize_embeddings: bool
|
| 51 |
lazy_load: bool
|
| 52 |
+
# Set ("mean"/"cls") for repos whose sentence-transformers packaging is
|
| 53 |
+
# incomplete (modules.json references a pooling config the repo lacks):
|
| 54 |
+
# the backend then builds Transformer+Pooling explicitly instead of
|
| 55 |
+
# relying on SentenceTransformer(id) auto-loading.
|
| 56 |
+
pooling_fallback: str | None = None
|
| 57 |
user_warnings: tuple[str, ...] = field(default_factory=tuple)
|
| 58 |
|
| 59 |
@property
|
|
|
|
| 94 |
text_prefix=usage.get("text_prefix") or sym or "",
|
| 95 |
normalize_embeddings=bool(usage.get("normalize_embeddings", True)),
|
| 96 |
lazy_load=bool(ops.get("lazy_load", False)),
|
| 97 |
+
pooling_fallback=usage.get("pooling_fallback") or None,
|
| 98 |
user_warnings=tuple(raw.get("warnings", []) or []),
|
| 99 |
)
|
| 100 |
|
backend/app/reproducibility.py
CHANGED
|
@@ -47,6 +47,23 @@ def script_text(metadata: dict) -> str:
|
|
| 47 |
provider = metadata.get("provider_model_id", metadata.get("model", ""))
|
| 48 |
revision = metadata.get("model_revision")
|
| 49 |
revision_arg = f", revision={revision!r}" if revision and revision != "PIN_ME" else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
item_prefix = metadata.get("item_prefix", "")
|
| 51 |
text_prefix = metadata.get("text_prefix", "")
|
| 52 |
text_column = metadata.get("text_column", "text")
|
|
@@ -78,7 +95,7 @@ import sys
|
|
| 78 |
|
| 79 |
import numpy as np
|
| 80 |
import pandas as pd
|
| 81 |
-
|
| 82 |
|
| 83 |
TEXT_COLUMN = {text_column!r}
|
| 84 |
ITEM_PREFIX = {item_prefix!r} # model-required prefix (E5 family); empty = none
|
|
@@ -94,7 +111,7 @@ def main(csv_path: str) -> None:
|
|
| 94 |
work = df.loc[mask].reset_index(drop=True) # platform drops empty rows the same way
|
| 95 |
texts = work[TEXT_COLUMN].astype(str).tolist()
|
| 96 |
|
| 97 |
-
|
| 98 |
item_texts = [ITEM_PREFIX + i["text"] for i in ITEMS]
|
| 99 |
doc_texts = [TEXT_PREFIX + t for t in texts]
|
| 100 |
|
|
|
|
| 47 |
provider = metadata.get("provider_model_id", metadata.get("model", ""))
|
| 48 |
revision = metadata.get("model_revision")
|
| 49 |
revision_arg = f", revision={revision!r}" if revision and revision != "PIN_ME" else ""
|
| 50 |
+
pooling_fallback = metadata.get("model_pooling_fallback")
|
| 51 |
+
max_seq = metadata.get("model_max_seq_length")
|
| 52 |
+
if pooling_fallback:
|
| 53 |
+
# Repos with incomplete sentence-transformers packaging (pooling config
|
| 54 |
+
# missing) must be assembled module-by-module, exactly as the platform
|
| 55 |
+
# backend does - otherwise the exported script cannot load the model.
|
| 56 |
+
rev_model_args = f", model_args={{'revision': {revision!r}}}" if revision and revision != "PIN_ME" else ""
|
| 57 |
+
model_loader = (
|
| 58 |
+
f"word = st_models.Transformer({provider!r}, max_seq_length={max_seq!r}{rev_model_args})\n"
|
| 59 |
+
f" get_dim = getattr(word, 'get_embedding_dimension', None) or word.get_word_embedding_dimension\n"
|
| 60 |
+
f" pool = st_models.Pooling(get_dim(), pooling_mode={pooling_fallback!r})\n"
|
| 61 |
+
f" model = SentenceTransformer(modules=[word, pool])"
|
| 62 |
+
)
|
| 63 |
+
st_import = "from sentence_transformers import SentenceTransformer\nfrom sentence_transformers import models as st_models"
|
| 64 |
+
else:
|
| 65 |
+
model_loader = f"model = SentenceTransformer({provider!r}{revision_arg})"
|
| 66 |
+
st_import = "from sentence_transformers import SentenceTransformer"
|
| 67 |
item_prefix = metadata.get("item_prefix", "")
|
| 68 |
text_prefix = metadata.get("text_prefix", "")
|
| 69 |
text_column = metadata.get("text_column", "text")
|
|
|
|
| 95 |
|
| 96 |
import numpy as np
|
| 97 |
import pandas as pd
|
| 98 |
+
{st_import}
|
| 99 |
|
| 100 |
TEXT_COLUMN = {text_column!r}
|
| 101 |
ITEM_PREFIX = {item_prefix!r} # model-required prefix (E5 family); empty = none
|
|
|
|
| 111 |
work = df.loc[mask].reset_index(drop=True) # platform drops empty rows the same way
|
| 112 |
texts = work[TEXT_COLUMN].astype(str).tolist()
|
| 113 |
|
| 114 |
+
{model_loader}
|
| 115 |
item_texts = [ITEM_PREFIX + i["text"] for i in ITEMS]
|
| 116 |
doc_texts = [TEXT_PREFIX + t for t in texts]
|
| 117 |
|
backend/tests/test_registry_and_prefixes.py
CHANGED
|
@@ -108,3 +108,43 @@ def test_model_language_unsupported_warning():
|
|
| 108 |
assert w["code"] == "MODEL_LANGUAGE_UNSUPPORTED"
|
| 109 |
assert model_language_warning("en", "m", frozenset({"en"}), None) is None
|
| 110 |
assert model_language_warning("zz", "m", frozenset(), None) is None # unknown coverage: no warning
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
assert w["code"] == "MODEL_LANGUAGE_UNSUPPORTED"
|
| 109 |
assert model_language_warning("en", "m", frozenset({"en"}), None) is None
|
| 110 |
assert model_language_warning("zz", "m", frozenset(), None) is None # unknown coverage: no warning
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
# ------------------------------------- psyembedding models (pooling fallback)
|
| 114 |
+
def test_psyembedding_models_registered_with_pooling_fallback():
|
| 115 |
+
"""The published PsyEmbedding repos lack the 1_Pooling config their
|
| 116 |
+
modules.json references, so plain SentenceTransformer(id) cannot load
|
| 117 |
+
them; the registry must flag them for explicit module assembly."""
|
| 118 |
+
from app import registry
|
| 119 |
+
|
| 120 |
+
psy = [m for m in registry.list_models() if m.id.startswith("psyembedding-")]
|
| 121 |
+
assert len(psy) == 4
|
| 122 |
+
for m in psy:
|
| 123 |
+
assert m.pooling_fallback == "mean", m.id
|
| 124 |
+
assert not m.requires_prefix, m.id
|
| 125 |
+
assert m.embedding_dimension == 1024 and m.max_seq_length == 512, m.id
|
| 126 |
+
assert m.lazy_load, m.id
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def test_repro_script_uses_explicit_modules_for_pooling_fallback():
|
| 130 |
+
from app.reproducibility import script_text
|
| 131 |
+
|
| 132 |
+
meta = {
|
| 133 |
+
"construct_snapshot": {"items": [{"text": "I am satisfied.", "reverse_scored": False}],
|
| 134 |
+
"name": "X", "version": 1, "item_hash": "ab" * 16},
|
| 135 |
+
"model_registry_id": "psyembedding-bert-large",
|
| 136 |
+
"provider_model_id": "Culture-and-Morality-Lab/psyembedding-bert-large-uncased",
|
| 137 |
+
"model_revision": "PIN_ME",
|
| 138 |
+
"model_pooling_fallback": "mean",
|
| 139 |
+
"model_max_seq_length": 512,
|
| 140 |
+
"text_column": "text",
|
| 141 |
+
}
|
| 142 |
+
src = script_text(meta)
|
| 143 |
+
compile(src, "reproduce_analysis.py", "exec")
|
| 144 |
+
assert "st_models.Pooling" in src and "pooling_mode='mean'" in src
|
| 145 |
+
# plain models keep the one-line loader
|
| 146 |
+
plain = script_text({**meta, "model_pooling_fallback": None,
|
| 147 |
+
"model_registry_id": "all-minilm-l6-v2",
|
| 148 |
+
"provider_model_id": "sentence-transformers/all-MiniLM-L6-v2"})
|
| 149 |
+
compile(plain, "reproduce_analysis.py", "exec")
|
| 150 |
+
assert "st_models" not in plain
|
packages/model_registry/models.yaml
CHANGED
|
@@ -77,3 +77,127 @@ models:
|
|
| 77 |
warnings:
|
| 78 |
- "Quality varies by language, especially lower-resource languages."
|
| 79 |
- "Scores are not comparable across model families."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
warnings:
|
| 78 |
- "Quality varies by language, especially lower-resource languages."
|
| 79 |
- "Scores are not comparable across model families."
|
| 80 |
+
|
| 81 |
+
# PsyEmbedding family (Culture & Morality Lab): sentence-transformers models
|
| 82 |
+
# fine-tuned for psychological text analysis on sentence-similarity pairs.
|
| 83 |
+
# Added on PI request 2026-07-18. All four: mean pooling, no prefix, English,
|
| 84 |
+
# 1024-dim, 512-token window, ~1.3 GB download on first use (lazy).
|
| 85 |
+
|
| 86 |
+
- id: psyembedding-bert-large
|
| 87 |
+
provider_model_id: Culture-and-Morality-Lab/psyembedding-bert-large-uncased
|
| 88 |
+
display_name: "PsyEmbedding BERT Large (psychology fine-tune)"
|
| 89 |
+
revision: PIN_ME
|
| 90 |
+
default: false
|
| 91 |
+
supported_languages: ["en"]
|
| 92 |
+
embedding_dimension: 1024
|
| 93 |
+
max_seq_length: 512
|
| 94 |
+
quality_tier: specialized
|
| 95 |
+
speed_tier: slow
|
| 96 |
+
usage_config:
|
| 97 |
+
requires_prefix: false
|
| 98 |
+
symmetric_similarity_prefix: null
|
| 99 |
+
pooling: mean # per model card; see pooling_fallback
|
| 100 |
+
# The published repos' modules.json references a 1_Pooling config the
|
| 101 |
+
# repos do not contain, so SentenceTransformer(id) cannot auto-load
|
| 102 |
+
# them; the backend builds Transformer+mean-Pooling explicitly.
|
| 103 |
+
pooling_fallback: mean
|
| 104 |
+
normalize_embeddings: true
|
| 105 |
+
operational_config:
|
| 106 |
+
expected_time_per_1k_texts_cpu: benchmark_required
|
| 107 |
+
worker_ram_min_gb: 4
|
| 108 |
+
lazy_load: true
|
| 109 |
+
max_resident_models: 1
|
| 110 |
+
warnings:
|
| 111 |
+
- "Fine-tuned for psychological text; general-domain performance untested."
|
| 112 |
+
- "Substantially slower and heavier than MiniLM."
|
| 113 |
+
- "Scores are not comparable across model families."
|
| 114 |
+
|
| 115 |
+
- id: psyembedding-roberta-large
|
| 116 |
+
provider_model_id: Culture-and-Morality-Lab/psyembedding-roberta-large
|
| 117 |
+
display_name: "PsyEmbedding RoBERTa Large (psychology fine-tune)"
|
| 118 |
+
revision: PIN_ME
|
| 119 |
+
default: false
|
| 120 |
+
supported_languages: ["en"]
|
| 121 |
+
embedding_dimension: 1024
|
| 122 |
+
max_seq_length: 512
|
| 123 |
+
quality_tier: specialized
|
| 124 |
+
speed_tier: slow
|
| 125 |
+
usage_config:
|
| 126 |
+
requires_prefix: false
|
| 127 |
+
symmetric_similarity_prefix: null
|
| 128 |
+
pooling: mean # per model card; see pooling_fallback
|
| 129 |
+
# The published repos' modules.json references a 1_Pooling config the
|
| 130 |
+
# repos do not contain, so SentenceTransformer(id) cannot auto-load
|
| 131 |
+
# them; the backend builds Transformer+mean-Pooling explicitly.
|
| 132 |
+
pooling_fallback: mean
|
| 133 |
+
normalize_embeddings: true
|
| 134 |
+
operational_config:
|
| 135 |
+
expected_time_per_1k_texts_cpu: benchmark_required
|
| 136 |
+
worker_ram_min_gb: 4
|
| 137 |
+
lazy_load: true
|
| 138 |
+
max_resident_models: 1
|
| 139 |
+
warnings:
|
| 140 |
+
- "Fine-tuned for psychological text; general-domain performance untested."
|
| 141 |
+
- "Substantially slower and heavier than MiniLM."
|
| 142 |
+
- "Scores are not comparable across model families."
|
| 143 |
+
|
| 144 |
+
- id: psyembedding-gte-large
|
| 145 |
+
provider_model_id: Culture-and-Morality-Lab/psyembedding-gte-large
|
| 146 |
+
display_name: "PsyEmbedding GTE Large (psychology fine-tune)"
|
| 147 |
+
revision: PIN_ME
|
| 148 |
+
default: false
|
| 149 |
+
supported_languages: ["en"]
|
| 150 |
+
embedding_dimension: 1024
|
| 151 |
+
max_seq_length: 512
|
| 152 |
+
quality_tier: specialized
|
| 153 |
+
speed_tier: slow
|
| 154 |
+
usage_config:
|
| 155 |
+
requires_prefix: false
|
| 156 |
+
symmetric_similarity_prefix: null
|
| 157 |
+
pooling: mean # per model card; see pooling_fallback
|
| 158 |
+
# The published repos' modules.json references a 1_Pooling config the
|
| 159 |
+
# repos do not contain, so SentenceTransformer(id) cannot auto-load
|
| 160 |
+
# them; the backend builds Transformer+mean-Pooling explicitly.
|
| 161 |
+
pooling_fallback: mean
|
| 162 |
+
normalize_embeddings: true
|
| 163 |
+
operational_config:
|
| 164 |
+
expected_time_per_1k_texts_cpu: benchmark_required
|
| 165 |
+
worker_ram_min_gb: 4
|
| 166 |
+
lazy_load: true
|
| 167 |
+
max_resident_models: 1
|
| 168 |
+
warnings:
|
| 169 |
+
- "Fine-tuned for psychological text; general-domain performance untested."
|
| 170 |
+
- "Substantially slower and heavier than MiniLM."
|
| 171 |
+
- "Scores are not comparable across model families."
|
| 172 |
+
|
| 173 |
+
- id: psyembedding-e5-large-v2
|
| 174 |
+
provider_model_id: Culture-and-Morality-Lab/psyembedding-e5-large-v2
|
| 175 |
+
display_name: "PsyEmbedding E5 Large v2 (psychology fine-tune)"
|
| 176 |
+
revision: PIN_ME
|
| 177 |
+
default: false
|
| 178 |
+
supported_languages: ["en"]
|
| 179 |
+
embedding_dimension: 1024
|
| 180 |
+
max_seq_length: 512
|
| 181 |
+
quality_tier: specialized
|
| 182 |
+
speed_tier: slow
|
| 183 |
+
usage_config:
|
| 184 |
+
# Unlike base intfloat/e5-large-v2, the fine-tune's card specifies direct
|
| 185 |
+
# encoding with NO "query: " prefix; the ST package carries its own
|
| 186 |
+
# pooling+normalize config, so we match the card exactly.
|
| 187 |
+
requires_prefix: false
|
| 188 |
+
symmetric_similarity_prefix: null
|
| 189 |
+
pooling: mean # per model card; see pooling_fallback
|
| 190 |
+
# The published repos' modules.json references a 1_Pooling config the
|
| 191 |
+
# repos do not contain, so SentenceTransformer(id) cannot auto-load
|
| 192 |
+
# them; the backend builds Transformer+mean-Pooling explicitly.
|
| 193 |
+
pooling_fallback: mean
|
| 194 |
+
normalize_embeddings: true
|
| 195 |
+
operational_config:
|
| 196 |
+
expected_time_per_1k_texts_cpu: benchmark_required
|
| 197 |
+
worker_ram_min_gb: 4
|
| 198 |
+
lazy_load: true
|
| 199 |
+
max_resident_models: 1
|
| 200 |
+
warnings:
|
| 201 |
+
- "Fine-tuned for psychological text; general-domain performance untested."
|
| 202 |
+
- "Substantially slower and heavier than MiniLM."
|
| 203 |
+
- "Scores are not comparable across model families."
|