Add local spoken passages with Google retrieval and isolated runtime setup
This commit is contained in:
1 parent
bc9459785d
commit
dab703413e
55 files changed
+3633
-70
No files matched your search
@@ -2,9 +2,12 @@
|
||||
//! filtered HNSW retrieval. Production-scale validation remains a release gate.
|
||||
mod coordination;
|
||||
mod media;
|
||||
mod speech;
|
||||
pub use coordination::{
|
||||
BudgetedProvider, InferenceBudget, InferencePermit, InferenceRole, PendingForeground,
|
||||
};
|
||||
pub use searchi_speech::{SpeechMetrics, SpeechPassage, SpeechTranscription};
|
||||
pub use speech::{speech_policy_key, BudgetedSpeechProvider, SpeechExcerpt, SpeechProvider};
|
||||
mod prepared;
|
||||
pub use prepared::PreparedGraphs;
|
||||
mod pipeline;
|
||||
@@ -39,7 +42,23 @@ fn generation_fingerprint(model: &str) -> String {
|
||||
)
|
||||
}
|
||||
|
||||
fn raw_media_policy(policy: &str) -> &str {
|
||||
if let Some((base, hash)) = policy.rsplit_once(":speech-v1-") {
|
||||
if hash.len() == 64 && hash.bytes().all(|byte| byte.is_ascii_hexdigit()) {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
policy
|
||||
}
|
||||
|
||||
fn speech_component_policy(policy: &str) -> String {
|
||||
let raw = raw_media_policy(policy);
|
||||
format!("{}{}", policy_base(policy), &policy[raw.len()..])
|
||||
}
|
||||
|
||||
fn reusable_policy(expected: &str, active: &str) -> bool {
|
||||
let expected = raw_media_policy(expected);
|
||||
let active = raw_media_policy(active);
|
||||
if active == expected || active == format!("{expected}:text-only") {
|
||||
return true;
|
||||
}
|
||||
@@ -56,6 +75,7 @@ fn reusable_policy(expected: &str, active: &str) -> bool {
|
||||
/// Resolve compatible publication coverage without broadening model or window
|
||||
/// policy compatibility. A retained reader can start under either coverage.
|
||||
fn policy_base(policy: &str) -> &str {
|
||||
let policy = raw_media_policy(policy);
|
||||
if let Some(base) = policy.strip_suffix(":text-only") {
|
||||
return base;
|
||||
}
|
||||
@@ -213,12 +233,21 @@ pub struct EmbeddingReport {
|
||||
pub image_inference_calls: usize,
|
||||
pub audio_inference_calls: usize,
|
||||
pub resumed: bool,
|
||||
pub speech_requested: bool,
|
||||
pub speech_windows: usize,
|
||||
pub speech_chunks: usize,
|
||||
pub speech_reused_sources: usize,
|
||||
pub speech_failures: Vec<MediaFailure>,
|
||||
pub speech_metrics: std::collections::BTreeMap<String, u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct EmbeddingStatus {
|
||||
/// Coverage of a compatible, prepared active generation, if any.
|
||||
pub coverage: Option<SemanticCoverage>,
|
||||
pub speech_policy: Option<String>,
|
||||
pub speech_failures: Vec<MediaFailure>,
|
||||
pub corpus_revision: i64,
|
||||
pub requested_coverage: SemanticCoverage,
|
||||
/// Early setup must preserve an existing compatible full generation.
|
||||
pub text_indexing_allowed: bool,
|
||||
@@ -241,6 +270,7 @@ enum QueryTask {
|
||||
pub struct HybridSearch {
|
||||
lexical: SearchIndex,
|
||||
embedder: Box<dyn EmbeddingProvider>,
|
||||
speech: Option<Box<dyn SpeechProvider>>,
|
||||
store: Store,
|
||||
generation_fingerprint: String,
|
||||
// Real provider outputs only, scoped to this model session. Queries never
|
||||
@@ -300,6 +330,9 @@ impl HybridSearch {
|
||||
if !exists {
|
||||
return Ok(EmbeddingStatus {
|
||||
coverage: None,
|
||||
speech_policy: None,
|
||||
speech_failures: Vec::new(),
|
||||
corpus_revision: 0,
|
||||
requested_coverage,
|
||||
text_indexing_allowed: true,
|
||||
failures: Vec::new(),
|
||||
@@ -318,6 +351,9 @@ impl HybridSearch {
|
||||
if version < 6 {
|
||||
return Ok(EmbeddingStatus {
|
||||
coverage: None,
|
||||
speech_policy: None,
|
||||
speech_failures: Vec::new(),
|
||||
corpus_revision: 0,
|
||||
requested_coverage,
|
||||
text_indexing_allowed: true,
|
||||
failures: Vec::new(),
|
||||
@@ -329,7 +365,7 @@ impl HybridSearch {
|
||||
});
|
||||
}
|
||||
ensure!(
|
||||
(6..=8).contains(&version),
|
||||
(6..=9).contains(&version),
|
||||
"Unsupported semantic schema version {version}"
|
||||
);
|
||||
let (generation,fingerprint,revision,current,dimensions):(Option<i64>,Option<String>,Option<i64>,i64,Option<usize>)=snapshot.query_row(
|
||||
@@ -349,6 +385,25 @@ impl HybridSearch {
|
||||
})
|
||||
})?
|
||||
.collect::<rusqlite::Result<Vec<_>>>()?;
|
||||
let speech_policy = fingerprint
|
||||
.as_deref()
|
||||
.filter(|policy| raw_media_policy(policy) != *policy)
|
||||
.and_then(|policy| policy.rsplit_once(":speech-v1-"))
|
||||
.map(|(_, hash)| format!("speech-v1-{hash}"));
|
||||
let speech_failures = if version >= 8 {
|
||||
let mut speech_query=snapshot.prepare("SELECT path,message FROM semantic_tasks WHERE generation=?1 AND source_type='speech' AND state='failed' ORDER BY path LIMIT 1000")?;
|
||||
let failures = speech_query
|
||||
.query_map([generation], |row| {
|
||||
Ok(MediaFailure {
|
||||
path: row.get(0)?,
|
||||
message: row.get(1)?,
|
||||
})
|
||||
})?
|
||||
.collect::<rusqlite::Result<Vec<_>>>()?;
|
||||
failures
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let expected = generation_fingerprint(GEMMA_FINGERPRINT);
|
||||
let coverage = if dimensions == Some(GEMMA_DIMENSIONS) {
|
||||
fingerprint
|
||||
@@ -361,11 +416,16 @@ impl HybridSearch {
|
||||
let policy_matches = match requested_coverage {
|
||||
SemanticCoverage::TextOnly => prepared_coverage.is_some(),
|
||||
// Keep the default full-media status's exact configured policy rule.
|
||||
SemanticCoverage::FullMedia => fingerprint.as_deref() == Some(expected.as_str()),
|
||||
SemanticCoverage::FullMedia => {
|
||||
fingerprint.as_deref().map(raw_media_policy) == Some(expected.as_str())
|
||||
}
|
||||
};
|
||||
let stale = revision != Some(current) || !policy_matches;
|
||||
Ok(EmbeddingStatus {
|
||||
coverage: prepared_coverage,
|
||||
speech_policy,
|
||||
speech_failures,
|
||||
corpus_revision: current,
|
||||
requested_coverage,
|
||||
text_indexing_allowed: coverage != Some(SemanticCoverage::FullMedia),
|
||||
failures,
|
||||
@@ -416,6 +476,7 @@ impl HybridSearch {
|
||||
query_cache: VecDeque::new(),
|
||||
lexical,
|
||||
embedder,
|
||||
speech: None,
|
||||
store,
|
||||
generation_fingerprint,
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user