diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..3d9bf00 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-18 - Missing Memoization for Regex Compilations +**Learning:** `_compiled_context_lexicon` function inside `openmed/openmed/clinical/context.py` compiles multiple heavy regular expressions dynamically without memoization. The function is called for every span context resolution (`resolve_temporality`, `resolve_uncertainty`, etc), leading to severe performance bottlenecks. +**Action:** Always memoize deterministic regex compilations and lexicon generation in NLP pipelines (e.g. `openmed.clinical`) using `@functools.lru_cache` to prevent bottlenecks during repeated string/span evaluations. Make sure to only cache hashable parameters. diff --git a/openmed/openmed/clinical/context.py b/openmed/openmed/clinical/context.py index 9fd11df..ceacbcc 100644 --- a/openmed/openmed/clinical/context.py +++ b/openmed/openmed/clinical/context.py @@ -35,7 +35,9 @@ from __future__ import annotations +import functools import re +import types from collections.abc import Iterable, Iterator, Mapping, Sequence from dataclasses import dataclass, replace from datetime import date @@ -154,6 +156,7 @@ class _CompiledContextLexicon: backward_context_cues: frozenset[str] +@functools.lru_cache(maxsize=None) def _compiled_context_lexicon(language: str | None = None) -> _CompiledContextLexicon: lexicon = get_clinical_cue_lexicon(language) token_boundaries = lexicon.token_boundaries @@ -195,7 +198,7 @@ def _compiled_context_lexicon(language: str | None = None) -> _CompiledContextLe ), token_boundaries=token_boundaries, ), - category_by_text=_cue_category_lookup(lexicon), + category_by_text=types.MappingProxyType(_cue_category_lookup(lexicon)), backward_context_cues=frozenset( _normalize_cue_text(cue) for cue in lexicon.backward ),