Files
searchi/crates/searchi-service

Shared hybrid retrieval

HybridSearch combines genuine lexical and Google multimodal retrieval. The CLI and desktop use the same service; it has no desktop-shell dependency.

search, search_semantic and search_semantic_with_origin preserve grouped parent files. ANN candidates expand until enough unique eligible parents exist or the complete bounded eligible chunk set is requested. Filename/type/folder, size/date/duration and explicit source filters apply before ANN top-k. Media candidate filesystem metadata is checked once per parent per query. Ninety-six near-identical video vectors cannot hide a second eligible parent (regression tested). HNSW remains approximate retrieval, not an exact recall guarantee.

Explicit spoken/audio wording prefers actual audio-source vectors, preserving exact lexical filename priority. Conservative English/German token cues detect requests such as “someone mentions”, “spoken”, “audio”, “jemand erwähnt” and “Gespräch”. Visual/document cues veto automatic routing. This finite parser is not language understanding; paraphrases, negation and mixed intents can remain ambiguous. If the preferred lane has no eligible results, ordinary retrieval is used. SemanticOrigin::All bypasses the hint; Audio, Image, Video and Text select an explicit channel without fallback or reembedding.

Persisted custom sampling limits can be reopened without generating embeddings again only when the complete model and preprocessing fingerprint matches. The custom suffix must contain the eight valid numeric sampling limits. Model or preprocessing changes never silently reuse incompatible vectors.

search_measured(query,limit,options,debug) returns SearchResponse with results and monotonic total milliseconds/result count. Basic mode stores no trace. search_traced(...,&mut TraceCollector,parent) shares the native request clock so queue/lock time and actual engine stages remain comparable. Debug mode adds bounded nested spans for lexical SQL, query embedding, worker diagnostics, filtered eligibility and its cache, ANN read/checksum/deserialization/search passes, parent materialization and validation, and rank fusion. Static stage names and numerical counters exclude query/source text and paths. Worker-local microsecond counters have a separate clock and are not aligned request spans.

Measured/source APIs retain existing result behavior except the explicit spoken/audio preference. Debug instrumentation does not change vector policy. Audio timestamps represent segment starts, not exact word locations. Smaller windows alone have not demonstrated accurate spoken navigation. No-answer calibration, music discrimination, exact spoken positions, process isolation, unchanged-vector reuse and production platform checks remain release gates.

Exact artist/title constraints use the core's normalized structured probe keys before ANN limits and in the eligibility cache key. Metadata-only writes advance a separate durable metadata epoch so warmed readers cannot retain old eligibility. They do not change source-corpus revisions during the indexer's own probe publication. Empty metadata-only hybrid requests use core results without model inference. These explicit constraints do not establish abstention for free-form topic queries.

Optional speech evidence

Attach a verified searchi_speech::SpeechWorker through with_speech_provider. BudgetedSpeechProvider admits one background thread per contiguous window; its admission time remains separate from native VAD/ASR/load/transport metrics. Aborted acceleration and CPU retry cost is aggregated separately as fallback_us. Recognition consumes at most thirty seconds of mono 16-kHz PCM, with two-second window overlap and an explicit 1024-window source ceiling. Four-hour default media fits the contiguous policy. Recognition never receives reference captions.

Speech uses decode_audio_aligned: source-frame timestamps preserve positive track origins, internal gaps, seeks and tails. Its CPU FFmpeg regression compares actual samples against known fixture clocks. Raw Google audio preprocessing is unchanged. DTW first/last point spans may have equal start/end; no invented duration is added. These functional contracts do not prove general timestamp accuracy.

Raw media, speech and document passages have independent completed source tasks. Adding/upgrading speech or retrying its failures reuses compatible verified raw vectors. Speech task identity includes native recognition assets/policy, aligned decoder policy, input SHA-256, title, maximum duration and maximum file bytes; raw sampling changes do not force speech recognition. Failed speech tasks publish explicit partial coverage while retaining raw evidence, and remain retryable. A genuine Google inference failure still aborts semantic publication.

SpeechProvider returns bounded recognized passages and numeric metrics. Google EmbeddingGemma 2 alone embeds those passages. Spoken-intent requests prefer semantic_speech, falling back to raw audio; music and sound requests use audio. Source locations retain timestamp_ms; recognized snippets are identified as local_speech_recognition, not exact document bytes. speech_excerpt_matching binds an issued result's recognized text when timestamps repeat, verifies current media SHA-256/revision and serves only active indexed evidence.

speech_policy_key and EmbeddingStatus.corpus_revision provide the stable (policy, source revision) automatic-retry key. Generation IDs and metadata-only updates must not trigger an endless retry loop. Status includes active speech policy and bounded explicit failures. Native interaction, full speech quality, other-platform execution and GPU evidence remain separate release gates.

Actual ASR/Google integration is an explicit ignored test: cargo test -p searchi-service --test speech_google_cpu -- --ignored --nocapture --test-threads=1. Provide verified SEARCHI_SPEECH_WORKER, SEARCHI_SPEECH_BASE, SEARCHI_SPEECH_VAD, Google model/worker variables, CPU FFmpeg/FFprobe helpers and a real short WAV in SEARCHI_TEST_SPEECH_AUDIO; Windows VM execution requires SEARCHI_FORCE_CPU=1. This tests publication/reuse and evidence binding, not independent relevance.

Recorded Windows CPU functional proof, 2026-10-13: the actual speech_google_cpu test passed in 113.50 seconds with native v3 worker SHA-256 299c1b784eac46b31d228453a399e1378f327fc9ed5e34ab950c804da33e433a and genuine Google embeddings. Adding/retrying speech made zero additional raw audio inference calls and preserved exact raw vector bytes. Policy-upgrade fault injection reported partial speech coverage, then genuine recognition restored it; the retained Google query reader and source-bound excerpts worked across publication. Ignored raw log .searchi/qa/service-speech-google-cpu-v3.log is 1292 bytes, SHA-256 170700adf9315ae15ae3ab5a7df6a77ab01dc5b776be179c861d2461cfc48c03. This uses a short existing English fixture and queries derived from recognition, so it does not score independent relevance, precise utterance timing, GPU behavior or native UI performance.