b23ddf2980
Cierra el ciclo del feedback: el modelo real (fastembed-allMiniLML6V2, ~1-50ms por archivo) era invocado ciegamente en cada re-cluster del watcher. Ahora se cachea por sha256(bytes-vistos) + model_id, con write-through al CAS de arje. Pipeline en handle_file: 1. Lee primeros 8 KiB del archivo (igual que antes). 2. file_sha = ente_cas::sha256_of(buf) — hash de los bytes que el modelo *realmente* verá. Garantiza que un archivo creciendo mas alla de la ventana sin tocar la cabeza siga sirviendo cache hits. 3. Cache lookup -> HIT: respuesta en us, sin invocar fastembed. 4. MISS: ente_cas::store(&buf) (write-through, no-fatal si falla) -> backend.embed_one(text) -> cache.put(...). Backend de cache: sled local en $XDG_CACHE_HOME/brahman/nouser-nous-real-embed-cache.sled. Tree versionado embed_cache_v1; el MODEL_ID viaja en la key, asi que cambiar de modelo invalida el cache implicitamente. Override por env NOUSER_NOUS_REAL_CACHE. Encoding compacto: cada Vec<f32> se serializa como bytes little-endian (4B por f32, sin overhead). Para 384-d son 1.5 KiB por entry. Decode tolera bytes corruptos (longitud no-multiplo de 4 -> None, no panic). Por que sled y no ente-cas directo: el CAS de arje es flat sha256-keyed; la cache necesita un mapeo (file_sha, model_id) -> embedding, no expresable como entry CAS. El write-through a CAS queda como registro consultable + futura GC. Mock NO se modifica — su embedding pseudo-32d es metadata-hashing puro, sin costo. Cachearlo seria overhead. Tests: 5 unitarios verdes (roundtrip, miss, model collision, content collision, corrupted value). Stub mode (sin feature) sigue compilando sin tocar cache.
41 lines
1.3 KiB
TOML
41 lines
1.3 KiB
TOML
[package]
|
|
name = "nouser-nous-real"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
publish.workspace = true
|
|
description = "Nouser — proveedor Nous con LLM real (text-embedding via ONNX). El soporte AI vive detrás del feature `embeddings`; sin él, este crate compila como stub mínimo."
|
|
|
|
[features]
|
|
# Sin features = stub que arranca y rechaza requests. Compila en
|
|
# segundos, sin descargar nada.
|
|
default = []
|
|
# Con feature embeddings: pulls fastembed + ONNX Runtime descargado.
|
|
# Modelo default: all-MiniLM-L6-v2 (384-d, ~80MB descargado al primer
|
|
# run y cacheado).
|
|
embeddings = ["dep:fastembed"]
|
|
|
|
[dependencies]
|
|
brahman-card = { path = "../../../core/brahman-card" }
|
|
brahman-sidecar = { path = "../../../shared/brahman-sidecar" }
|
|
ente-cas = { path = "../../../core/ente-cas" }
|
|
nouser-nous = { path = "../nous" }
|
|
serde_json = { workspace = true }
|
|
sled = { workspace = true }
|
|
tokio = { workspace = true }
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
ulid = { workspace = true }
|
|
|
|
# Opcional: gateado por feature `embeddings`.
|
|
fastembed = { version = "4", optional = true }
|
|
|
|
[dev-dependencies]
|
|
tempfile = { workspace = true }
|
|
|
|
[[bin]]
|
|
name = "nouser-nous-real"
|
|
path = "src/main.rs"
|