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-29 - Memoization of NLP Lexicons
**Learning:** Deterministic regex compilations and lexicon generations in `openmed.clinical` (like `_compiled_context_lexicon` and `_alias_lookups`) are repeated continuously during string evaluations, causing significant performance overhead (e.g. 0.7s per 1000 calls).
**Action:** Always memoize deterministic lexicon building and regex compiling functions using `@functools.lru_cache` in text-processing pipelines to ensure they are only constructed once per language/configuration.
4 changes: 4 additions & 0 deletions openmed/openmed/clinical/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

from __future__ import annotations

import functools
import re
from collections.abc import Iterable, Iterator, Mapping, Sequence
from dataclasses import dataclass, replace
Expand Down Expand Up @@ -154,6 +155,9 @@ class _CompiledContextLexicon:
backward_context_cues: frozenset[str]


# ⚡ Bolt: Memoize lexicon compilation. Re-compiling 12+ regexes per span
# creates significant overhead during bulk document processing.
@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
Expand Down
11 changes: 9 additions & 2 deletions openmed/openmed/clinical/sections/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

import functools
import types
from collections.abc import Iterable, Mapping
from dataclasses import dataclass
from typing import Any
Expand Down Expand Up @@ -244,6 +246,8 @@ def _is_underline(text: str) -> bool:
return len(stripped) >= 3 and set(stripped) <= _UNDERLINE_CHARS


# ⚡ Bolt: Cache language alias lookups as they are repeated per document
@functools.lru_cache(maxsize=None)
def _alias_lookups(language: str | None) -> tuple[tuple[str, Mapping[str, str]], ...]:
languages = (
tuple(dict.fromkeys((get_section_lexicon(language).language, "en")))
Expand All @@ -253,14 +257,17 @@ def _alias_lookups(language: str | None) -> tuple[tuple[str, Mapping[str, str]],
return tuple((code, _aliases_for_language(code)) for code in languages)


def _aliases_for_language(language: str) -> dict[str, str]:
# ⚡ Bolt: Memoize alias construction to prevent redundant dictionary allocation.
# Returns MappingProxyType to safely prevent cached dictionary mutations.
@functools.lru_cache(maxsize=None)
def _aliases_for_language(language: str) -> types.MappingProxyType[str, str]:
lexicon = get_section_lexicon(language)
aliases: dict[str, str] = {}
for label, headers in lexicon.sections.items():
aliases[normalize_section_header(label)] = label
for header in headers:
aliases[normalize_section_header(header)] = label
return aliases
return types.MappingProxyType(aliases)


def _dedupe_hits(hits: Iterable[_HeaderHit]) -> tuple[_HeaderHit, ...]:
Expand Down
1 change: 1 addition & 0 deletions openmed/openmed/multimodal/epub.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from typing import Any
from urllib.parse import unquote
from xml.etree import ElementTree as ET

from defusedxml.ElementTree import fromstring as safe_fromstring

from .base import ExtractedDocument, SourceSpan, register_handler
Expand Down
4 changes: 3 additions & 1 deletion openmed/openmed/service/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,10 @@ async def get_job(job_id: str, request: Request) -> Dict[str, Any]:
log_config=service_log_config_from_env(),
)

from fastapi.staticfiles import StaticFiles
import os

from fastapi.staticfiles import StaticFiles

outputs_path = r"c:\Users\Zhane\Documents\New project\zrt-bionemo\outputs"
if os.path.exists(outputs_path):
app.mount("/outputs", StaticFiles(directory=outputs_path), name="outputs")
Expand Down
2 changes: 2 additions & 0 deletions openmed/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.