Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-07-25 - Context Lexicon Compilation Bottleneck
**Learning:** Deterministic regex generation for clinical span lexicons (`_compiled_context_lexicon` in `openmed/clinical/context.py`) is expensive and is repeatedly invoked by various helpers (e.g. `is_negated`, `is_hypothetical`). Since the language argument is hashable, caching this generation avoids massive repetitive computation.
**Action:** Always verify if computationally heavy dynamic regex generation based on statically loadable parameters (like a language code or fixed taxonomy) is being done per-span, and aggressively memoize these functions (`@functools.lru_cache`) to avoid re-compilation.
7 changes: 7 additions & 0 deletions openmed/openmed/clinical/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from collections.abc import Iterable, Iterator, Mapping, Sequence
from dataclasses import dataclass, replace
from datetime import date
from functools import lru_cache
from typing import Any, Literal

from openmed.clinical.lexicons import (
Expand Down Expand Up @@ -154,7 +155,13 @@ class _CompiledContextLexicon:
backward_context_cues: frozenset[str]


@lru_cache(maxsize=16)
def _compiled_context_lexicon(language: str | None = None) -> _CompiledContextLexicon:
"""Returns regex matchers derived from the context cues lexicon.

Memoized as cue sets can be large to iterate and regexes are expensive
to compile across many invocations.
"""
lexicon = get_clinical_cue_lexicon(language)
token_boundaries = lexicon.token_boundaries
return _CompiledContextLexicon(
Expand Down