diff --git a/server/src/analyze/worker.rs b/server/src/analyze/worker.rs index 893124d..7da5ef0 100644 --- a/server/src/analyze/worker.rs +++ b/server/src/analyze/worker.rs @@ -7,18 +7,26 @@ use tracing::{error, info, warn}; use super::{llm, prompt, AnalysisInput, AnalyzeReceiver, ANALYSIS_INPUT_FILE, DOCUMENT_FILE}; use crate::config::Config; +use crate::gazetteer::Gazetteer; use crate::{BusyGuard, WorkerBusy}; /// Consume analyze jobs sequentially. The external LLM tolerates parallelism, /// but sequential processing keeps the architecture simple and shields the /// provider from bursts. Trivial to lift later via `tokio::spawn(process(..))`. +/// +/// `_vocab` is the gazetteer for proper-name correction. Currently unused; +/// wired into `process()` in a follow-up step. pub async fn run( mut rx: AnalyzeReceiver, config: Arc, client: reqwest::Client, worker_busy: WorkerBusy, + _vocab: Arc, ) { - info!("Analyze worker started"); + info!( + vocab_entries = _vocab.len(), + "Analyze worker started" + ); let timeout = Duration::from_secs(config.llm_timeout_seconds); while let Some(job) = rx.recv().await { diff --git a/server/src/main.rs b/server/src/main.rs index fd8363e..7f97017 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -10,6 +10,7 @@ use tracing_subscriber::EnvFilter; use doctate_server::analyze; use doctate_server::config::Config; +use doctate_server::gazetteer::Gazetteer; use doctate_server::transcribe; use doctate_server::AppState; @@ -64,6 +65,27 @@ async fn main() { .build() .expect("reqwest client build failed"); + // Gazetteer for pre-LLM proper-name correction. Missing / unreadable + // vocab directory is non-fatal — analysis falls back to plain prompts. + let vocab = Arc::new(match Gazetteer::load_dir(&config.vocab_dir).await { + Ok(g) => { + info!( + dir = %config.vocab_dir.display(), + entries = g.len(), + "Gazetteer loaded" + ); + g + } + Err(e) => { + warn!( + dir = %config.vocab_dir.display(), + error = %e, + "Gazetteer not available; running without proper-name correction" + ); + Gazetteer::empty() + } + }); + // Transcription pipeline: channel + worker + recovery scan. let (transcribe_tx, transcribe_rx) = transcribe::channel(); let transcribe_busy: doctate_server::WorkerBusy = @@ -96,6 +118,7 @@ async fn main() { config.clone(), http_client.clone(), analyze_busy.clone(), + vocab.clone(), )); { let tx = analyze_tx.clone(); diff --git a/server/tests/analyze_test.rs b/server/tests/analyze_test.rs index 433089f..4b03270 100644 --- a/server/tests/analyze_test.rs +++ b/server/tests/analyze_test.rs @@ -332,7 +332,8 @@ async fn analyze_worker_writes_document_via_wiremock() { let (tx, rx) = analyze::channel(); let client = reqwest::Client::new(); let busy = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = tokio::spawn(analyze::worker::run(rx, config, client, busy)); + let vocab = std::sync::Arc::new(doctate_server::gazetteer::Gazetteer::empty()); + let handle = tokio::spawn(analyze::worker::run(rx, config, client, busy, vocab)); tx.send(analyze::AnalyzeJob { case_dir: case_dir.clone(), @@ -863,7 +864,8 @@ async fn analyze_works_against_ollama_style_endpoint_without_api_key() { let (tx, rx) = analyze::channel(); let client = reqwest::Client::new(); let busy = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = tokio::spawn(analyze::worker::run(rx, config, client, busy)); + let vocab = std::sync::Arc::new(doctate_server::gazetteer::Gazetteer::empty()); + let handle = tokio::spawn(analyze::worker::run(rx, config, client, busy, vocab)); tx.send(analyze::AnalyzeJob { case_dir: case_dir.clone(),