perf: precompute valid_by_code at load; tighten code guard; clarify gap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+16
-18
@@ -13,6 +13,7 @@ pub struct Pipeline {
|
|||||||
pub meta: HashMap<String, IcdMeta>,
|
pub meta: HashMap<String, IcdMeta>,
|
||||||
pub lexical: LexicalIndex,
|
pub lexical: LexicalIndex,
|
||||||
pub pool_size: usize,
|
pub pool_size: usize,
|
||||||
|
pub valid_by_code: HashMap<String, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
@@ -20,7 +21,17 @@ impl Pipeline {
|
|||||||
let entries = corpus::load(&cfg.alpha_id_path)?;
|
let entries = corpus::load(&cfg.alpha_id_path)?;
|
||||||
let meta = claml::load(&cfg.claml_path)?;
|
let meta = claml::load(&cfg.claml_path)?;
|
||||||
let lexical = LexicalIndex::build_in_ram(&entries)?;
|
let lexical = LexicalIndex::build_in_ram(&entries)?;
|
||||||
Ok(Self { entries, meta, lexical, pool_size: cfg.pool_size })
|
let valid_by_code = {
|
||||||
|
let mut m: HashMap<String, bool> = HashMap::new();
|
||||||
|
for e in &entries {
|
||||||
|
if let Some(code) = corpus::primary_code(e) {
|
||||||
|
let v = m.entry(code.to_string()).or_insert(false);
|
||||||
|
*v = *v || e.valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m
|
||||||
|
};
|
||||||
|
Ok(Self { entries, meta, lexical, pool_size: cfg.pool_size, valid_by_code })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up ICD metadata: exact code first, then — only for 6-char dotted codes
|
/// Look up ICD metadata: exact code first, then — only for 6-char dotted codes
|
||||||
@@ -48,8 +59,8 @@ impl Pipeline {
|
|||||||
&& bytes[1].is_ascii_digit()
|
&& bytes[1].is_ascii_digit()
|
||||||
&& bytes[2].is_ascii_digit()
|
&& bytes[2].is_ascii_digit()
|
||||||
&& bytes[3] == b'.'
|
&& bytes[3] == b'.'
|
||||||
&& bytes[4].is_ascii_alphanumeric()
|
&& bytes[4].is_ascii_digit()
|
||||||
&& bytes[5].is_ascii_alphanumeric()
|
&& bytes[5].is_ascii_digit()
|
||||||
{
|
{
|
||||||
if let Some(m) = self.meta.get(&code[..5]) {
|
if let Some(m) = self.meta.get(&code[..5]) {
|
||||||
return Some(m);
|
return Some(m);
|
||||||
@@ -61,7 +72,7 @@ impl Pipeline {
|
|||||||
|
|
||||||
fn to_suggestion(&self, code: &str, phrase: &str, score: f32,
|
fn to_suggestion(&self, code: &str, phrase: &str, score: f32,
|
||||||
segs: Vec<usize>, alpha_valid: bool) -> Option<Suggestion> {
|
segs: Vec<usize>, alpha_valid: bool) -> Option<Suggestion> {
|
||||||
let m = self.meta_lookup(code)?;
|
let m = self.meta_lookup(code)?; // None ≈ 31 codes absent from ClaML entirely; accepted gap (see meta_lookup doc)
|
||||||
Some(Suggestion {
|
Some(Suggestion {
|
||||||
icd_code: code.to_string(),
|
icd_code: code.to_string(),
|
||||||
description: m.description.clone(),
|
description: m.description.clone(),
|
||||||
@@ -95,23 +106,10 @@ impl Pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let valid_by_code: HashMap<String, bool> = {
|
|
||||||
let mut m = HashMap::new();
|
|
||||||
for c in &candidates {
|
|
||||||
m.entry(c.icd_code.clone()).or_insert(false);
|
|
||||||
}
|
|
||||||
for e in &self.entries {
|
|
||||||
if let Some(code) = corpus::primary_code(e) {
|
|
||||||
if let Some(v) = m.get_mut(code) { *v = *v || e.valid; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m
|
|
||||||
};
|
|
||||||
|
|
||||||
let merged = cross_segment_dedupe(candidates);
|
let merged = cross_segment_dedupe(candidates);
|
||||||
let mut suggestions = Vec::new();
|
let mut suggestions = Vec::new();
|
||||||
for (d, score) in merged {
|
for (d, score) in merged {
|
||||||
let alpha_valid = *valid_by_code.get(&d.icd_code).unwrap_or(&false);
|
let alpha_valid = self.valid_by_code.get(&d.icd_code).copied().unwrap_or(false);
|
||||||
if let Some(s) = self.to_suggestion(&d.icd_code, &d.best_phrase, score,
|
if let Some(s) = self.to_suggestion(&d.icd_code, &d.best_phrase, score,
|
||||||
d.source_segments.clone(), alpha_valid) {
|
d.source_segments.clone(), alpha_valid) {
|
||||||
if filter.accepts(&s.tags) {
|
if filter.accepts(&s.tags) {
|
||||||
|
|||||||
Reference in New Issue
Block a user