From b1bda54441d70cb8d8e21c01fbf698facada87be Mon Sep 17 00:00:00 2001 From: Chandrasekharan M Date: Tue, 11 Aug 2026 14:08:56 +0530 Subject: [PATCH 1/2] fix: send LLMWhisperer V2 params under the correct names The adapter read the line splitter strategy under `line_spitter_strategy` while its JSON schema stores it as `line_splitter_strategy`, so the user's choice never applied. The same misspelling was also passed to the client, which forwarded a query param the service does not read. The page separator keeps its misspelled config key since existing adapter configs are stored under it, but is now sent under the client's corrected kwarg. Both need llmwhisperer-client 2.8.0 or newer. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Dra3Xevzb5oYtMz9fhj8iG --- unstract/sdk1/pyproject.toml | 2 +- .../x2text/llm_whisperer_v2/src/constants.py | 4 ++- .../x2text/llm_whisperer_v2/src/helper.py | 2 +- .../tests/test_llm_whisperer_v2_params.py | 27 +++++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 unstract/sdk1/tests/test_llm_whisperer_v2_params.py diff --git a/unstract/sdk1/pyproject.toml b/unstract/sdk1/pyproject.toml index 70b492f191..c944ac967a 100644 --- a/unstract/sdk1/pyproject.toml +++ b/unstract/sdk1/pyproject.toml @@ -47,7 +47,7 @@ dependencies = [ "pdfplumber>=0.11.2", "redis>=5.2.1", # # LLMWhisperer client - "llmwhisperer-client>=2.6.2", + "llmwhisperer-client>=2.8.0", # # Core utilities (Redis Sentinel-aware client factory, etc.) "unstract-core", ] diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py index 090a3bf6f4..1a9c15bb37 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py @@ -60,12 +60,14 @@ class WhispererConfig: MEDIAN_FILTER_SIZE = "median_filter_size" GAUSSIAN_BLUR_RADIUS = "gaussian_blur_radius" LINE_SPLITTER_TOLERANCE = "line_splitter_tolerance" - LINE_SPLITTER_STRATEGY = "line_spitter_strategy" + LINE_SPLITTER_STRATEGY = "line_splitter_strategy" HORIZONTAL_STRETCH_FACTOR = "horizontal_stretch_factor" PAGES_TO_EXTRACT = "pages_to_extract" MARK_VERTICAL_LINES = "mark_vertical_lines" MARK_HORIZONTAL_LINES = "mark_horizontal_lines" + # Misspelling retained: correcting the JSON schema key means migrating saved configs PAGE_SEPARATOR = "page_seperator" + PAGE_SEPARATOR_PARAM = "page_separator" URL_IN_POST = "url_in_post" TAG = "tag" USE_WEBHOOK = "use_webhook" diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py index ade89f7cba..686f6dfdd8 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py @@ -200,7 +200,7 @@ def get_whisperer_params( WhispererConfig.MARK_HORIZONTAL_LINES, WhispererDefaults.MARK_HORIZONTAL_LINES, ), - WhispererConfig.PAGE_SEPARATOR: config.get( + WhispererConfig.PAGE_SEPARATOR_PARAM: config.get( WhispererConfig.PAGE_SEPARATOR, WhispererDefaults.PAGE_SEPARATOR, ), diff --git a/unstract/sdk1/tests/test_llm_whisperer_v2_params.py b/unstract/sdk1/tests/test_llm_whisperer_v2_params.py new file mode 100644 index 0000000000..d21bdc8665 --- /dev/null +++ b/unstract/sdk1/tests/test_llm_whisperer_v2_params.py @@ -0,0 +1,27 @@ +"""Tests for the query params the LLMWhisperer V2 adapter sends.""" + +from unstract.sdk1.adapters.x2text.llm_whisperer_v2.src.dto import ( + WhispererRequestParams, +) +from unstract.sdk1.adapters.x2text.llm_whisperer_v2.src.helper import LLMWhispererHelper + + +def _params(config: dict) -> dict: + return LLMWhispererHelper.get_whisperer_params( + config=config, extra_params=WhispererRequestParams() + ) + + +def test_line_splitter_strategy_from_config() -> None: + """The key stored by the adapter's JSON schema is the one that is read.""" + params = _params({"line_splitter_strategy": "right-priority"}) + + assert params["line_splitter_strategy"] == "right-priority" + + +def test_page_separator_read_under_legacy_config_key() -> None: + """Existing configs store the misspelled key but the client kwarg is correct.""" + params = _params({"page_seperator": "<<< {{page_no}} >>>"}) + + assert params["page_separator"] == "<<< {{page_no}} >>>" + assert "page_seperator" not in params From 8b74d6f4b0dda3986f690361fdc2c860bba41115 Mon Sep 17 00:00:00 2001 From: Chandrasekharan M Date: Tue, 11 Aug 2026 14:08:56 +0530 Subject: [PATCH 2/2] feat: send the file name being extracted to LLMWhisperer Without it, usage reports record the service default for every Unstract-originated extraction, leaving no way to cross reference a row back to a document. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Dra3Xevzb5oYtMz9fhj8iG --- .../sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py | 1 + .../sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py index 1a9c15bb37..6d41cc11f4 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/constants.py @@ -80,6 +80,7 @@ class WhispererConfig: INCLUDE_LINE_CONFIDENCE = "include_line_confidence" EXTRACT_ALL_LINES = "extract_all_lines" LINES = "lines" + FILE_NAME = "file_name" class WhisperStatus: diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py index 686f6dfdd8..7cd271a4b1 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/x2text/llm_whisperer_v2/src/helper.py @@ -260,6 +260,8 @@ def send_whisper_request( params = LLMWhispererHelper.get_whisperer_params( config=config, extra_params=extra_params ) + # Recorded against the extraction for cross referencing in usage reports + params[WhispererConfig.FILE_NAME] = Path(input_file_path).name response: requests.Response try: input_file_data = BytesIO(fs.read(path=input_file_path, mode="rb"))