Spaces:
Sleeping
Sleeping
Commit ·
ccbf2d4
1
Parent(s): 9f4344b
Fix quality mode 500: pass ClaudeService instance to PdfConverter
Browse filesmarker's PdfConverter.__init__ eagerly resolves `default_llm_service`
(GoogleGeminiService) when `use_llm=True` *before* it applies any
config-dict override. So naming "marker.services.claude.ClaudeService"
in config["llm_service"] never took effect — Gemini's
verify_config_keys check fired first and 500'd on missing
gemini_api_key.
Build the ClaudeService instance ourselves and pass it via the
PdfConverter `llm_service=` constructor arg; that takes precedence
over the default and skips the Gemini path entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- _project/CHANGELOG.md +1 -0
- app/parser.py +15 -5
_project/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,7 @@ Newest first. Format: `## YYYY-MM-DD — short title`, then bullets.
|
|
| 8 |
|
| 9 |
## Unreleased
|
| 10 |
|
|
|
|
| 11 |
- **Fix:** Pre-create `<site-packages>/static/fonts/` and chown to the `app` user. marker-pdf's `PdfConverter.__init__` calls `download_font()`, which writes there on first parse — without the chown the non-root container user got `PermissionError`, surfaced as 500 from `/parse`. Affected both `fast` and `quality` modes.
|
| 12 |
- **Fix:** Redirect `~/.cache` to the bucket via `XDG_CACHE_HOME=/data/cache` and add `DATALAB_CACHE_DIR=/data/datalab` for explicit coverage. marker uses Vik's `datalab` loader for text-detection and OCR-error-detection models, which writes to `~/.cache/datalab/` by default. Without the redirect those models re-downloaded into the container's ephemeral overlay on every cold start (despite the bucket being mounted), adding seconds of avoidable latency. Also pinned `HF_HUB_CACHE` and `TRANSFORMERS_CACHE` explicitly under `/data/hf/`.
|
| 13 |
|
|
|
|
| 8 |
|
| 9 |
## Unreleased
|
| 10 |
|
| 11 |
+
- **Fix:** Instantiate `ClaudeService` ourselves in `app/parser.py` and pass it to `PdfConverter(llm_service=…)` instead of naming the service via `config["llm_service"]`. Marker's `PdfConverter.__init__` eagerly resolves `default_llm_service` (Gemini) when `use_llm=True` *before* applying the config override, so the previous setup tripped Gemini's `gemini_api_key` check even though we never wanted Gemini. Surfaced as 500 from `/parse` in `quality` mode.
|
| 12 |
- **Fix:** Pre-create `<site-packages>/static/fonts/` and chown to the `app` user. marker-pdf's `PdfConverter.__init__` calls `download_font()`, which writes there on first parse — without the chown the non-root container user got `PermissionError`, surfaced as 500 from `/parse`. Affected both `fast` and `quality` modes.
|
| 13 |
- **Fix:** Redirect `~/.cache` to the bucket via `XDG_CACHE_HOME=/data/cache` and add `DATALAB_CACHE_DIR=/data/datalab` for explicit coverage. marker uses Vik's `datalab` loader for text-detection and OCR-error-detection models, which writes to `~/.cache/datalab/` by default. Without the redirect those models re-downloaded into the container's ephemeral overlay on every cold start (despite the bucket being mounted), adding seconds of avoidable latency. Also pinned `HF_HUB_CACHE` and `TRANSFORMERS_CACHE` explicitly under `/data/hf/`.
|
| 14 |
|
app/parser.py
CHANGED
|
@@ -16,6 +16,7 @@ import torch
|
|
| 16 |
from marker.converters.pdf import PdfConverter
|
| 17 |
from marker.models import create_model_dict
|
| 18 |
from marker.output import text_from_rendered
|
|
|
|
| 19 |
|
| 20 |
log = logging.getLogger(__name__)
|
| 21 |
|
|
@@ -35,22 +36,31 @@ def device() -> str:
|
|
| 35 |
def parse(pdf_path: str | Path, mode: Mode = "fast") -> tuple[str, int]:
|
| 36 |
"""Run marker on the PDF at `pdf_path`. Returns (markdown, page_count)."""
|
| 37 |
config: dict[str, object] = {"output_format": "markdown"}
|
|
|
|
| 38 |
if mode == "quality":
|
| 39 |
api_key = os.getenv("ANTHROPIC_API_KEY")
|
| 40 |
if not api_key:
|
| 41 |
raise RuntimeError(
|
| 42 |
"parse_mode=quality requires ANTHROPIC_API_KEY to be set."
|
| 43 |
)
|
| 44 |
-
config
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
"claude_api_key": api_key,
|
| 49 |
"claude_model_name": CLAUDE_MODEL,
|
| 50 |
}
|
| 51 |
)
|
| 52 |
|
| 53 |
-
converter = PdfConverter(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
rendered = converter(str(pdf_path))
|
| 55 |
text, _, _ = text_from_rendered(rendered)
|
| 56 |
return text, _page_count(rendered, pdf_path)
|
|
|
|
| 16 |
from marker.converters.pdf import PdfConverter
|
| 17 |
from marker.models import create_model_dict
|
| 18 |
from marker.output import text_from_rendered
|
| 19 |
+
from marker.services.claude import ClaudeService
|
| 20 |
|
| 21 |
log = logging.getLogger(__name__)
|
| 22 |
|
|
|
|
| 36 |
def parse(pdf_path: str | Path, mode: Mode = "fast") -> tuple[str, int]:
|
| 37 |
"""Run marker on the PDF at `pdf_path`. Returns (markdown, page_count)."""
|
| 38 |
config: dict[str, object] = {"output_format": "markdown"}
|
| 39 |
+
llm_service: ClaudeService | None = None
|
| 40 |
if mode == "quality":
|
| 41 |
api_key = os.getenv("ANTHROPIC_API_KEY")
|
| 42 |
if not api_key:
|
| 43 |
raise RuntimeError(
|
| 44 |
"parse_mode=quality requires ANTHROPIC_API_KEY to be set."
|
| 45 |
)
|
| 46 |
+
config["use_llm"] = True
|
| 47 |
+
# Pass the service instance directly. Marker's PdfConverter eagerly
|
| 48 |
+
# instantiates `default_llm_service` (Gemini) when `use_llm=True`,
|
| 49 |
+
# *before* applying any config-dict override — so naming the service
|
| 50 |
+
# in `config["llm_service"]` is too late and trips Gemini's config
|
| 51 |
+
# check. Supplying the instance via the constructor arg skips that.
|
| 52 |
+
llm_service = ClaudeService(
|
| 53 |
+
config={
|
| 54 |
"claude_api_key": api_key,
|
| 55 |
"claude_model_name": CLAUDE_MODEL,
|
| 56 |
}
|
| 57 |
)
|
| 58 |
|
| 59 |
+
converter = PdfConverter(
|
| 60 |
+
artifact_dict=_models,
|
| 61 |
+
config=config,
|
| 62 |
+
llm_service=llm_service,
|
| 63 |
+
)
|
| 64 |
rendered = converter(str(pdf_path))
|
| 65 |
text, _, _ = text_from_rendered(rendered)
|
| 66 |
return text, _page_count(rendered, pdf_path)
|