From 1b0e5472ce5802a08a244b3669bf59465a7074bd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 17:31:50 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Memoize=20expensive=20regex?= =?UTF-8?q?=20compilations=20in=20ConText=20lexicon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimizes the `_compiled_context_lexicon` function in `openmed.clinical.context` by wrapping it with `@functools.lru_cache(maxsize=None)` and ensuring immutability with `types.MappingProxyType`. This prevents compiling identical and complex regex patterns multiple times across different span resolutions, significantly improving performance for heavy clinical document evaluation pipelines. Co-authored-by: zrt219 <199104500+zrt219@users.noreply.github.com> --- .jules/bolt.md | 3 +++ openmed/openmed/clinical/context.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .jules/bolt.md 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 ),