feat: add desktop document search and verified native CPU embeddings
Core CI / core (ubuntu-latest) (push) Failing after 1m22s
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Successful in 3m46s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s

This commit is contained in:
karl committed 2026-10-12 16:07:53 +02:00
1 parent f77112db97
commit a9b6592330
46 files changed
+10794 -77

No files matched your search

+2 -1
View File
@@ -33,6 +33,7 @@ enabled. Model downloads and release checks must be explicit operations.
- Substring filename search scans the metadata table; the million-file target
requires an additional substring index and measured query planning.
- Initial indexing publishes after the root transaction finishes.
- File extraction currently covers bounded UTF-8 text, not PDF/DOCX/media.
- File extraction covers bounded UTF-8, PDF text and DOCX paragraphs. OCR and
media extraction remain upcoming work; parser workers are not isolated yet.
- No automatic watcher, persistent extraction queue or ANN index yet.
- Native CI and signed package validation require actual platform runners.
+46
View File
@@ -0,0 +1,46 @@
# Build and release targets
Install stable Rust, Node 22+, and native Tauri development prerequisites.
On Windows install Visual Studio C++ build tools and WebView2. Linux needs
WebKitGTK 4.1 development libraries. macOS needs Xcode command-line tools.
See https://v2.tauri.app/start/prerequisites/ for platform details.
```powershell
cargo test --workspace --locked
cd apps/desktop
npm ci
npm run build
# Windows VM: all rendering and inference tests must use CPU.
$env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS='--disable-gpu'
npm run tauri -- dev
```
The desktop is a standalone Cargo workspace; validate it separately:
```sh
cargo test --manifest-path apps/desktop/src-tauri/Cargo.toml --locked
```
## Cross-compilation
The Rust engine has no GUI dependency. Add the destination Rust target with
`rustup target add TARGET`, then use `cargo build -p searchi-cli --target TARGET`.
This requires the target linker, C toolchain and SDK because SQLite is compiled
from bundled C. Target installation alone is insufficient. Document each
verified host/target pair before treating it as supported.
Desktop builds also need the platform webview libraries and packaging tools.
Use native runners for dependable release builds. macOS signing/notarization
needs Apple credentials and tooling. Windows installer cross-builds have
additional Tauri caveats: https://v2.tauri.app/distribute/windows-installer/.
## CI and packaging gates
Both Gitea and GitHub workflow files are provided. Gitea needs registered runners
matching the configured OS labels; this repository does not provision runners.
No Linux/macOS checks are considered passed until actual job evidence exists.
Current bundles are disabled during development. Enable installers only after
packaging icons, native smoke tests, CPU model distribution and license review,
upgrade/migration tests, signatures and rollback checks are ready. Do not place
private signing keys, repository tokens or model credentials in source control.
+9 -2
View File
@@ -10,14 +10,14 @@ Status: implementation started; no production release yet. Windows VM tests use
- [x] Persistence and filesystem lifecycle integration tests (Windows CPU).
## 2. Document and semantic retrieval
- [ ] Text, Markdown, code, PDF and DOCX extraction with fixtures.
- [x] Text, Markdown, code, PDF and DOCX extraction with real fixtures (Windows CPU).
- [ ] Validate actual embedding model artifacts, license, CPU runtime and quantization.
- [ ] Versioned embeddings, ANN index, exact-match priority and hybrid fusion.
- [ ] English/German relevance corpus and measured top-10 recall.
- [ ] Atomic model/index replacement and resumable persistent work queues.
## 3. Desktop
- [ ] Tauri shell, accessible keyboard search, progressive results and previews.
- [ ] Tauri shell, accessible keyboard search, progressive results and previews (shell built; UI interaction verification pending).
- [ ] Folder selection, exclusion controls, resource budgets and indexing status.
- [ ] Global shortcut, opening/revealing source files, PDF page navigation.
- [ ] Watchers and reconciliation across Windows, macOS and Linux.
@@ -45,6 +45,13 @@ Completion requires recorded evidence; targets are not measured results.
- Actual CLI process integration tests and independent-reader concurrency test.
- TypeScript desktop frontend build and dependency audit passed; native validation underway.
- Initial README commit pushed to Gitea main via protected Infisical injection.
- Native desktop build and guarded opening tests passed on Windows.
- Genuine multilingual CPU model proof: 5/6 top-1, 6/6 recall@3; quality gate remains open.
- Native Rust CPU embedding adapter verifies pinned model/tokenizer assets;
integration with the search index and platform runtime packaging remain open.
- PDF page and DOCX paragraph matches persist; corrupt/encrypted/over-limit
documents remain filename-searchable and report extraction errors.
- CLI exposes folder/type/size/date filters and additional directory exclusions.
The partial features above do not close broader production milestones such as
crash-resumable jobs, fuzzy retrieval, watcher reliability or performance targets.
+155
View File
@@ -0,0 +1,155 @@
# CPU semantic inference proof
This milestone runs genuine neural embeddings locally. It does not yet connect
semantic vectors to the SQLite search index or desktop interface. Production
retrieval quality, large-corpus performance, and Linux/macOS runtime packaging
remain unverified.
## Model and runtime decision
The first working baseline is the quantized ONNX export of
`sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`, published by
`Xenova`. The upstream model card describes 384-dimensional text embeddings,
attention-mask mean pooling, a 128-token maximum, and Apache-2.0 licensing.
It covers multiple languages. This is a text-only baseline; it does not claim
EmbeddingGemma 2's multimodal features or compatibility.
Sources reviewed on 2026-10-12:
- [Original model card and pooling architecture](https://huggingface.co/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2)
- [ONNX export publisher](https://huggingface.co/Xenova/paraphrase-multilingual-MiniLM-L12-v2)
- [ONNX Runtime Python session API](https://onnxruntime.ai/docs/api/python/api_summary.html)
- [Rust ort dynamic-library initialization](https://docs.rs/ort/2.0.0-rc.13/ort/environment/fn.init_from.html)
- [Rust ort session configuration](https://docs.rs/ort/2.0.0-rc.13/ort/session/builder/struct.SessionBuilder.html)
Inference explicitly selects `CPUExecutionProvider`. Python uses the CPU
`onnxruntime` wheel, never `onnxruntime-gpu`. The native Rust crate disables ort
default features: there are no binary downloads, GPU provider features, or model
HTTP client features. It loads an explicitly supplied local runtime library and
disables runtime telemetry. Tokenization is sequential; ONNX sessions use
sequential graph execution with bounded intra-op threads and one inter-op thread.
## Reproduce on Windows
Run these commands from the repository root. Provisioning commands intentionally
use the network; the inference command does not provision anything.
```powershell
python -m venv tools/semantic-proof/.venv
& tools/semantic-proof/.venv/Scripts/python.exe -m pip install --only-binary=:all: -r tools/semantic-proof/requirements.txt
& tools/semantic-proof/.venv/Scripts/python.exe tools/semantic-proof/download.py
& tools/semantic-proof/.venv/Scripts/python.exe tools/semantic-proof/proof.py --threads 1 --output tools/semantic-proof/windows-cpu-result.json
```
On Linux/macOS, use `.venv/bin/python` instead of `.venv/Scripts/python.exe`.
These instructions have only been executed on Windows. Wheel availability and
native library distribution must be checked on other platforms.
`download.py` downloads exactly two revision-pinned artifacts, streams them to a
temporary file, rejects oversized downloads, checks byte length and SHA256, then
atomically replaces the local asset. Assets occupy approximately 136 MB in
decimal units and are ignored by Git. Inference validates both files again and
fails clearly when either is missing or damaged. It never contacts the model
hub. The Python proof sets offline environment flags and rejects Python socket
connect, name-resolution, and bind audit events throughout import and inference.
This guard checks Python socket activity; it is not an operating-system firewall
against arbitrary native libraries.
The proof intentionally exits nonzero if any fixture query misses top-1. Its
JSON report is written before the quality gate, preserving failures for review.
## Pinned artifacts and licensing
Revision: `2c4055b12046f11709e9df2c122e59ffbdc2f900`.
The manifest in `tools/semantic-proof/model-manifest.json` records the same
model contract and hashes used by the native adapter.
| Artifact | Bytes | SHA256 |
| --- | ---: | --- |
| `onnx/model_quantized.onnx` | 118,308,126 | `66fc00f5f29afcaff34092e1bdd20008ca3918265a82fb9695a551e510cc4ebc` |
| `tokenizer.json` | 17,082,913 | `b60b6b43406a48bf3638526314f3d232d97058bc93472ff2de930d43686fa441` |
The base model card specifies Apache-2.0. The export card identifies that base
model but does not display its own license declaration. Before redistributing
the ONNX export in installers, confirm export licensing and preserve the base
license, attribution, and applicable notices. Current code explicitly downloads
user-local assets and does not ship model weights or runtime DLLs in Git.
ONNX Runtime uses MIT licensing; ort uses MIT or Apache-2.0 and tokenizers uses
Apache-2.0. Release packaging must retain third-party notices and validate
platform-specific runtime hashes independently; a model hash does not attest
to the runtime library.
The tested Windows ONNX Runtime 1.31.0 DLL is 19,288,888 bytes with SHA256
`90497e3d406c09f4d59d364c696a2f93dc02f6ef13741b3b89eec95bdb4a3806`.
The adapter currently trusts the explicitly supplied runtime path; it validates
model hashes, not runtime-library hashes. A release distribution must add a
platform runtime manifest before shipping. `requirements-lock-windows.txt`
captures the exact Python environment used for this proof.
## Measured Windows VM result
`tools/semantic-proof/windows-cpu-result.json` contains the full measurement and
rankings. The run used Windows 11 AMD64, Python 3.14.8, ONNX Runtime 1.31.0,
four visible logical CPUs, and **one inference thread with only the CPU provider**.
| Metric | Measurement |
| --- | ---: |
| Fixture documents / queries | 8 / 6 |
| Timed warm query runs | 60 |
| Artifact verification plus runtime/model load | approximately 3.4 seconds |
| Corpus batch embedding | approximately 145 ms |
| Warm query p50 / p95 | approximately 3.1 / 11.9 ms |
| Top-1 accuracy | 5/6 (83.3%) |
| Recall at 3 | 6/6 (100%) |
The corpus includes English and German documents, same-language semantic
queries, and cross-language queries. A question about a postponed product
release ranks the supplier contract above the expected meeting notes. That
failure remains in the fixture and blocks the strict top-1 quality gate.
This small demonstration supports the feasibility of CPU inference; it does
not establish large-corpus latency, robust multilingual quality, or production
readiness. Quantization and batch shape can affect similarity scores.
## Native integration contract
`searchi-semantic` exposes:
```rust
CpuEmbedder::load(model_dir, runtime_library, threads) -> Result<CpuEmbedder>
CpuEmbedder::encode(&mut self, texts: &[&str]) -> Result<Vec<Vec<f32>>>
DIMENSIONS // 384
MODEL_FINGERPRINT // revision + quantization + pooling + normalization + token cap
```
Inputs are bounded to eight texts per batch, 64 KiB UTF-8 per text, and 128
tokens. Outputs are finite, normalized `f32` vectors. The runtime library is
process-global; adapter initialization rejects attempts to switch libraries or
silently accept an environment initialized outside the adapter. Supply a known,
trusted runtime before calling any other ort APIs in the process.
Default unit tests need no model or runtime. The real-artifact test is opt-in:
```powershell
$env:SEARCHI_MODEL_DIR = (Resolve-Path tools/semantic-proof/model).Path
$env:SEARCHI_ORT_LIBRARY = (Resolve-Path tools/semantic-proof/.venv/Lib/site-packages/onnxruntime/capi/onnxruntime.dll).Path
cargo test -p searchi-semantic --test cpu_model -- --ignored --nocapture
```
The smoke test checks actual local inference, vector normalization, English and
German retrieval, recall at three, and the measured five-of-six top-1 baseline.
It does not replace the strict production quality gate.
The native real-artifact smoke was executed successfully on the Windows VM,
using that CPU-only DLL. It reproduced five-of-six top-1 and six-of-six recall
at three. Three default unit tests passed; targeted Clippy passed with warnings
denied. Linux and macOS native checks have not been executed.
The next integration should read bounded `SearchIndex::passage_batch` rows,
split long passages into overlapping tokenizer windows, preserve source page or
paragraph locations, and persist each vector with a content fingerprint and
`MODEL_FINGERPRINT`. Passage IDs are not immutable content identities: changes
must invalidate stale vectors. Queries should combine lexical and semantic
retrieval while preserving exact filename priority. Model upgrades build a
separate vector generation before an atomic swap. Cancellation, persistent
embedding jobs, ANN retrieval, representative quality corpora, and signed
cross-platform runtime packaging are still required.
+17
View File
@@ -9,6 +9,23 @@ Initial foundation checks (2026-10-12):
- `cargo clippy --workspace --all-targets -- -D warnings`: passed.
- Rust formatting applied; final formatting verification follows integration.
- Desktop TypeScript/Vite build passed; npm audit reported zero vulnerabilities.
- Initial Windows desktop native check, embedded app build, strict Clippy and
two desktop tests passed (index gate recovery and guarded source opening).
- Desktop launched with WebView2 `--disable-gpu`. UI automation could not capture
the window: `GetCursorPos` access denied, then monitor capture error
`0x80070057`. Visual layout and end-to-end UI interactions remain unverified.
- Real Python CPU ONNX embedding proof completed on 8 documents / 6 queries:
5/6 top-1 accuracy, 6/6 recall@3. The strict top-1 quality gate is not met.
See `tools/semantic-proof/windows-cpu-result.json` for raw timings and rankings.
This tiny fixture is not evidence of large-corpus performance.
- Native Rust CPU embedding adapter compiled, passed its three unit tests and
the explicit local-model smoke test. The smoke reproduced the same 5/6 top-1
limitation. Default CI omits this asset-dependent test; it must be executed
separately with provisioned local artifacts.
- Integrated workspace validation: 19 default tests passed; 1 local-model test
is opt-in. Rust formatting and strict Clippy passed after lockfile refresh.
- PDF/DOCX fixture tests include matching source locations, corrupt replacement,
encrypted PDF behavior and compressed-input limits.
Not yet established: production latency targets, semantic inference, desktop
runtime behavior, Linux/macOS execution, installer signing or upgrades.