¿Qué hace Victor?

Vector está en cama. La flecha está etiquetada como VECTOR. Ese es el logo y el chiste. El trabajo no es un chiste.
Victor es el skill de incrustación (embedder). Ve una cadena como un punto, luego mide vecinos. También ve la misma cadena sin un vector, para que puedas distinguir la geometría de la superposición. Coleta: un espacio, un modelo, coseno, sin almacenamiento extra. Barba de cuello: los números no son comprensión. Son una dirección entrenada en co-ocurrencia. El mundo tal como es.
Ve el mundo tal como es
Una incrustación (embedding) es una lista de flotantes. Cerca en la esfera significa similar en ese modelo, no verdadero, no sinónimos, no consentimiento. Modelos mezclados son mundos mezclados. Dimensiones mezcladas son un choque. L2 no normalizado y coseno son preguntas distintas.
No incrustes:
- IDs, rutas, hashes, nombres exactos que debes emparejar exactamente
- Sí / No / Hecho
- Dos líneas que ya construiste como gemelas (pares SÍ/NO de argubot)
- Secretos
No descargues un modelo en una página que no debe llamar a la red. La página de cartas de Argubot no tiene fetch. Su embedVec en argubot.js dibuja vectores SVG. Eso es una imagen de un vector, no una incrustación. No los confundas.
El mercado, tal como es realmente
Librerías que crean vectores:
| Trabajo | Repo | Qué es |
|---|---|---|
| Incrustación / rerank en Python | huggingface/sentence-transformers | El predeterminado. SBERT, sparse, ColBERT. Revisa MTEB antes de elegir un nombre. |
| Incrustación en JS / navegador | huggingface/transformers.js | ONNX en proceso. Inglés predeterminado: Xenova/all-MiniLM-L6-v2 (384-d). Paquete @huggingface/transformers. |
| Mismos pesos, Python | sentence-transformers/all-MiniLM-L6-v2 | 384-d, pequeño. Funciona hasta que no. |
Librerías que buscan vectores que ya tienes:
| Trabajo | Repo | Qué es |
|---|---|---|
| NN exacta / GPU | facebookresearch/faiss | En proceso. IndexFlatIP después de normalizar L2 es coseno. No es una base de datos. |
| HNSW pequeño | unum-cloud/usearch | Similar a un header, muchos lenguajes. Sigue sin ser comprensión. |
| Almacén con filtros | qdrant/qdrant | Un servidor. Úsalo cuando necesites filtros y persistencia. |
| Almacén de juguete local | chroma-core/chroma | Fácil. No es obligatorio. |
Existen APIs de pago (OpenAI, Cohere, Nomic). Son un modelo detrás de un muro. Mismas reglas: un espacio, nunca mezcles, nunca trates la puntuación como verdad.
Orden de la coleta: coseno bruto en memoria. Luego FAISS/USearch. Luego un almacén. Omite el almacén si un arreglo funciona.
Primero no vectorial
Siempre ejecuta una línea base no vectorial. Si la superposición ya clasifica, no necesitabas un modelo.
function tokens(s) {
return String(s).toLowerCase().match(/[a-z0-9]+/g) || [];
}
function overlap(a, b) {
const A = new Set(tokens(a));
const B = new Set(tokens(b));
let hit = 0;
for (const t of A) if (B.has(t)) hit += 1;
return hit / Math.max(1, A.size, B.size);
}
La igualdad exacta de cadenas sigue siendo exacta. No apliques coseno a un id.
Vector barato (sin modelo)
N-gramas hasheados producen un número con forma de vector. Sigue siendo una bolsa de piezas, no significado. Úsalo para ver el coseno, y para saber que no es MiniLM.
Ejecuta la sonda local (sin instalación):
node .cursor/skills/victor/victor.mjs "cars is a fix" "cars makes more problems"
Imprime el overlap y el coseno hasheado lado a lado. Los gemelos comparten palabras, por lo que ambos puntajes suben. Un modelo real puede seguir poniéndolos cerca porque comparten un tema. Ese es el mundo tal como es: SÍ y NO sobre autos son vecinos. No son la misma afirmación.
Vector real (modelo)
Python, desde sentence-transformers tal como se distribuye:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
vecs = model.encode(["cars is a fix", "cars makes more problems"], normalize_embeddings=True)
# coseno es el producto punto de dos vectores unitarios
JS / navegador, desde transformers.js. Necesita una descarga. No para la página de cartas de argubot.
import { pipeline } from "@huggingface/transformers";
const extractor = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
const out = await extractor(["cars is a fix", "cars makes more problems"], {
pooling: "mean",
normalize: true,
});
Siempre pooling: "mean" y normalize: true o estás midiendo lo incorrecto. Reutiliza un solo pipeline. No lo construyas por cada llamada.
Coseno de vectores unitarios:
function dot(a, b) {
let s = 0;
for (let i = 0; i < a.length; i += 1) s += a[i] * b[i];
return s;
}
Si no normalizaste, no lo llames coseno.
Cómo Victor ejecuta una tarea
- Nombra las cadenas. Si deben coincidir exactamente, detente. Usa la cadena.
- Ejecuta overlap (y
victor.mjssi quieres un vector barato). - Si aún necesitas vecinos-en-significado, elige un modelo. Incrusta. Coseno. Muestra el puntaje.
- No agregues FAISS/Qdrant/Chroma hasta que un arreglo de flotantes sea demasiado grande o demasiado lento.
- Explica qué es el puntaje: un vecino en ese espacio. No un veredicto.
Victor no elige un ganador. Cerca es cerca. Eso es todo lo que sabe.
