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
@@ -0,0 +1,113 @@
|
||||
//! Explicit real local speech proof; excluded from ordinary structural checks.
|
||||
use anyhow::{ensure, Context, Result};
|
||||
use searchi_speech::{Device, SpeechWorker, MAX_SAMPLES};
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
fn required(name: &str) -> Result<PathBuf> {
|
||||
std::env::var_os(name)
|
||||
.map(PathBuf::from)
|
||||
.with_context(|| format!("Set {name} for actual CPU speech proof"))
|
||||
}
|
||||
struct OwnedFixture(PathBuf);
|
||||
impl Drop for OwnedFixture {
|
||||
fn drop(&mut self) {
|
||||
let _ = fs::remove_dir_all(&self.0);
|
||||
}
|
||||
}
|
||||
fn link_or_copy(source: &Path, target: &Path) -> Result<()> {
|
||||
if fs::hard_link(source, target).is_err() {
|
||||
fs::copy(source, target)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Requires actual pinned native worker/models and a verified speech PCM fixture; CPU only"]
|
||||
fn actual_speech_reuses_contexts_and_supports_unicode_runtime_and_model_paths() -> Result<()> {
|
||||
let worker = required("SEARCHI_TEST_SPEECH_WORKER")?;
|
||||
let base = required("SEARCHI_TEST_SPEECH_BASE")?;
|
||||
let vad = required("SEARCHI_TEST_SPEECH_VAD")?;
|
||||
let pcm_file = required("SEARCHI_TEST_SPEECH_PCM")?;
|
||||
ensure!(
|
||||
fs::metadata(&pcm_file)?.len() <= MAX_SAMPLES as u64 * 4,
|
||||
"Proof PCM exceeds limit"
|
||||
);
|
||||
let bytes = fs::read(pcm_file)?;
|
||||
ensure!(
|
||||
!bytes.is_empty() && bytes.len() % 4 == 0,
|
||||
"Invalid proof PCM bytes"
|
||||
);
|
||||
let pcm: Vec<f32> = bytes
|
||||
.as_chunks::<4>()
|
||||
.0
|
||||
.iter()
|
||||
.map(|b| f32::from_le_bytes(*b))
|
||||
.collect();
|
||||
let unique = SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos();
|
||||
let fixture = OwnedFixture(std::env::temp_dir().join(format!(
|
||||
"searchi-sprachtest-München-測試-🚀-{}-{unique}",
|
||||
std::process::id()
|
||||
)));
|
||||
fs::create_dir(&fixture.0)?;
|
||||
let runtime = fixture.0.join("Laufzeit-測試-🚀");
|
||||
fs::create_dir(&runtime)?;
|
||||
let inventory = worker
|
||||
.parent()
|
||||
.context("Worker directory missing")?
|
||||
.join("runtime-manifest.json");
|
||||
let manifest: serde_json::Value = serde_json::from_slice(&fs::read(&inventory)?)?;
|
||||
for record in manifest["files"]
|
||||
.as_array()
|
||||
.context("Missing runtime files")?
|
||||
{
|
||||
let name = record["path"].as_str().context("Invalid inventory name")?;
|
||||
ensure!(
|
||||
!name.contains(['/', '\\', ':']) && name != "..",
|
||||
"Unsafe fixture artifact name"
|
||||
);
|
||||
fs::copy(worker.parent().unwrap().join(name), runtime.join(name))?;
|
||||
}
|
||||
fs::copy(inventory, runtime.join("runtime-manifest.json"))?;
|
||||
let unicode_base = fixture.0.join("Modell-München-測試-🚀.bin");
|
||||
let unicode_vad = fixture.0.join("Sprache-測試-🚀.bin");
|
||||
link_or_copy(&base, &unicode_base)?;
|
||||
link_or_copy(&vad, &unicode_vad)?;
|
||||
ensure!(
|
||||
std::env::var("SEARCHI_FORCE_CPU").ok().as_deref() == Some("1"),
|
||||
"Actual VM inference proof requires forced CPU"
|
||||
);
|
||||
let mut client = SpeechWorker::load(
|
||||
&runtime.join(worker.file_name().unwrap()),
|
||||
&unicode_base,
|
||||
&unicode_vad,
|
||||
Device::Auto,
|
||||
)?;
|
||||
let first = client.transcribe(&pcm, 16000)?;
|
||||
ensure!(
|
||||
!first.passages.is_empty(),
|
||||
"Actual speech fixture produced no passages"
|
||||
);
|
||||
let second = client.transcribe(&pcm, 16000)?;
|
||||
ensure!(
|
||||
first.passages == second.passages,
|
||||
"Warm speech result differs"
|
||||
);
|
||||
ensure!(
|
||||
second.metrics.load_ms == 0.0,
|
||||
"Persistent contexts unexpectedly reloaded"
|
||||
);
|
||||
for passage in first.passages {
|
||||
ensure!(
|
||||
passage.start_ms <= passage.end_ms && passage.end_ms as usize <= pcm.len() / 16,
|
||||
"Native passage outside source window"
|
||||
);
|
||||
}
|
||||
println!(
|
||||
"actual CPU speech: first={:?}; warm={:?}",
|
||||
first.metrics, second.metrics
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user