Merge dev
Browse files- marker/builders/line.py +50 -44
- marker/converters/pdf.py +4 -1
- marker/processors/debug.py +7 -2
- marker/processors/line_merge.py +99 -0
- marker/processors/llm/llm_equation.py +1 -1
- marker/processors/llm/llm_inlinemath.py +178 -0
- marker/processors/llm/llm_text.py +2 -1
- marker/renderers/__init__.py +11 -0
- marker/renderers/html.py +1 -0
- marker/schema/blocks/base.py +1 -1
- marker/schema/text/line.py +8 -0
- marker/services/claude.py +144 -0
- poetry.lock +333 -197
- pyproject.toml +2 -1
- tests/builders/test_inline_math_lines.py +31 -0
marker/builders/line.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
|
|
| 1 |
from copy import deepcopy
|
|
|
|
| 2 |
from typing import Annotated, List, Optional, Tuple
|
| 3 |
|
| 4 |
import numpy as np
|
|
@@ -71,14 +73,14 @@ class LineBuilder(BaseBuilder):
|
|
| 71 |
float,
|
| 72 |
"The minimum overlap of a line with an inline math box to consider as a match"
|
| 73 |
] = 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
line_text_overlap_threshold: Annotated[
|
| 75 |
float,
|
| 76 |
"The minimum overlap of an equation with a text line to consider as a match"
|
| 77 |
] = .5
|
| 78 |
-
inline_math_minimum_area: Annotated[
|
| 79 |
-
float,
|
| 80 |
-
"The minimum area for an inline math block, in pixels."
|
| 81 |
-
] = 20
|
| 82 |
inline_math_line_vertical_merge_threshold: Annotated[
|
| 83 |
int,
|
| 84 |
"The maximum pixel distance between y1s for two lines to be merged"
|
|
@@ -109,9 +111,13 @@ class LineBuilder(BaseBuilder):
|
|
| 109 |
self.ocr_error_model = ocr_error_model
|
| 110 |
|
| 111 |
def __call__(self, document: Document, provider: PdfProvider):
|
| 112 |
-
# Disable
|
| 113 |
# Also disable if we won't use the inline detections (if we aren't using the LLM or texify)
|
| 114 |
-
do_inline_math_detection =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
provider_lines, ocr_lines = self.get_all_lines(document, provider, do_inline_math_detection)
|
| 116 |
self.merge_blocks(document, provider_lines, ocr_lines)
|
| 117 |
|
|
@@ -144,6 +150,7 @@ class LineBuilder(BaseBuilder):
|
|
| 144 |
batch_size=self.get_detection_batch_size()
|
| 145 |
)
|
| 146 |
|
|
|
|
| 147 |
detection_results = []
|
| 148 |
inline_results = []
|
| 149 |
idx = 0
|
|
@@ -183,7 +190,7 @@ class LineBuilder(BaseBuilder):
|
|
| 183 |
if sum(layout_good) > len(document.pages) * self.min_document_ocr_threshold:
|
| 184 |
layout_good = [True] * len(document.pages)
|
| 185 |
|
| 186 |
-
run_detection = [not good or do_inline_math_detection for good in layout_good]
|
| 187 |
page_images = [page.get_image(highres=False, remove_blocks=self.ocr_remove_blocks) for page, good in zip(document.pages, run_detection) if good]
|
| 188 |
|
| 189 |
# Note: run_detection is longer than page_images, since it has a value for each page, not just good ones
|
|
@@ -218,7 +225,7 @@ class LineBuilder(BaseBuilder):
|
|
| 218 |
page_lines[document_page.page_id].extend(
|
| 219 |
self.merge_provider_lines_inline_math(
|
| 220 |
provider_lines,
|
| 221 |
-
|
| 222 |
image_size,
|
| 223 |
page_size
|
| 224 |
)
|
|
@@ -365,7 +372,7 @@ class LineBuilder(BaseBuilder):
|
|
| 365 |
max_overlap = np.max(overlap_row) / inline_box.area
|
| 366 |
|
| 367 |
# Avoid small or nonoverlapping inline math regions
|
| 368 |
-
if max_overlap <= self.line_inline_math_overlap_threshold
|
| 369 |
continue
|
| 370 |
|
| 371 |
# Ignore vertical lines
|
|
@@ -386,67 +393,65 @@ class LineBuilder(BaseBuilder):
|
|
| 386 |
def merge_provider_lines_inline_math(
|
| 387 |
self,
|
| 388 |
provider_lines: List[ProviderOutput],
|
| 389 |
-
|
| 390 |
image_size,
|
| 391 |
page_size
|
| 392 |
):
|
| 393 |
# When provider lines is empty or no inline math detected, return provider lines
|
| 394 |
-
if not provider_lines or not
|
| 395 |
return provider_lines
|
| 396 |
|
| 397 |
horizontal_provider_lines = [
|
| 398 |
(j, provider_line) for j, provider_line in enumerate(provider_lines)
|
| 399 |
-
if provider_line.line.polygon.height < provider_line.line.polygon.width *
|
| 400 |
]
|
| 401 |
provider_line_boxes = [p.line.polygon.bbox for _, p in horizontal_provider_lines]
|
| 402 |
-
math_line_boxes = [PolygonBox(polygon=m.polygon).rescale(image_size, page_size).bbox for m in
|
| 403 |
|
| 404 |
-
overlaps = matrix_intersection_area(
|
| 405 |
|
| 406 |
# Find potential merges
|
| 407 |
-
merge_lines =
|
| 408 |
-
for i in range(len(
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
max_overlap = np.max(overlaps[i])
|
| 412 |
-
if max_overlap <= self.line_inline_math_overlap_threshold:
|
| 413 |
continue
|
| 414 |
|
| 415 |
best_overlap = np.argmax(overlaps[i])
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
merge_line.append(provider_idx)
|
| 434 |
-
|
| 435 |
-
if len(merge_line) > 0:
|
| 436 |
-
merge_lines.append(merge_line)
|
| 437 |
|
| 438 |
# Handle the merging
|
| 439 |
already_merged = set()
|
| 440 |
-
potential_merges = set(
|
| 441 |
out_provider_lines = [(i, p) for i, p in enumerate(provider_lines) if i not in potential_merges]
|
| 442 |
-
for
|
|
|
|
|
|
|
| 443 |
merge_section = [m for m in merge_section if m not in already_merged]
|
| 444 |
if len(merge_section) == 0:
|
| 445 |
continue
|
| 446 |
elif len(merge_section) == 1:
|
| 447 |
line_idx = merge_section[0]
|
| 448 |
merged_line = provider_lines[line_idx]
|
| 449 |
-
|
|
|
|
|
|
|
| 450 |
out_provider_lines.append((line_idx, merged_line))
|
| 451 |
already_merged.add(merge_section[0])
|
| 452 |
continue
|
|
@@ -461,6 +466,7 @@ class LineBuilder(BaseBuilder):
|
|
| 461 |
else:
|
| 462 |
# Combine the spans of the provider line with the merged line
|
| 463 |
merged_line = merged_line.merge(provider_line)
|
|
|
|
| 464 |
self.add_math_span_format(merged_line)
|
| 465 |
already_merged.add(idx) # Prevent double merging
|
| 466 |
out_provider_lines.append((min_idx, merged_line))
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
from copy import deepcopy
|
| 3 |
+
from itertools import chain
|
| 4 |
from typing import Annotated, List, Optional, Tuple
|
| 5 |
|
| 6 |
import numpy as np
|
|
|
|
| 73 |
float,
|
| 74 |
"The minimum overlap of a line with an inline math box to consider as a match"
|
| 75 |
] = 0.
|
| 76 |
+
line_inline_min_overlap_pct: Annotated[
|
| 77 |
+
float,
|
| 78 |
+
"The percentage of a provider line that has to be covered by a math line."
|
| 79 |
+
] = .3
|
| 80 |
line_text_overlap_threshold: Annotated[
|
| 81 |
float,
|
| 82 |
"The minimum overlap of an equation with a text line to consider as a match"
|
| 83 |
] = .5
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
inline_math_line_vertical_merge_threshold: Annotated[
|
| 85 |
int,
|
| 86 |
"The maximum pixel distance between y1s for two lines to be merged"
|
|
|
|
| 111 |
self.ocr_error_model = ocr_error_model
|
| 112 |
|
| 113 |
def __call__(self, document: Document, provider: PdfProvider):
|
| 114 |
+
# Disable inline detection for documents where layout model doesn't detect any equations
|
| 115 |
# Also disable if we won't use the inline detections (if we aren't using the LLM or texify)
|
| 116 |
+
do_inline_math_detection = all([
|
| 117 |
+
len(document.contained_blocks([BlockTypes.Equation, BlockTypes.TextInlineMath])) > 0,
|
| 118 |
+
(self.texify_inline_spans or self.use_llm)
|
| 119 |
+
])
|
| 120 |
+
|
| 121 |
provider_lines, ocr_lines = self.get_all_lines(document, provider, do_inline_math_detection)
|
| 122 |
self.merge_blocks(document, provider_lines, ocr_lines)
|
| 123 |
|
|
|
|
| 150 |
batch_size=self.get_detection_batch_size()
|
| 151 |
)
|
| 152 |
|
| 153 |
+
assert len(page_detection_results) == len(inline_detection_results) == sum(run_detection)
|
| 154 |
detection_results = []
|
| 155 |
inline_results = []
|
| 156 |
idx = 0
|
|
|
|
| 190 |
if sum(layout_good) > len(document.pages) * self.min_document_ocr_threshold:
|
| 191 |
layout_good = [True] * len(document.pages)
|
| 192 |
|
| 193 |
+
run_detection = [(not good or do_inline_math_detection) for good in layout_good]
|
| 194 |
page_images = [page.get_image(highres=False, remove_blocks=self.ocr_remove_blocks) for page, good in zip(document.pages, run_detection) if good]
|
| 195 |
|
| 196 |
# Note: run_detection is longer than page_images, since it has a value for each page, not just good ones
|
|
|
|
| 225 |
page_lines[document_page.page_id].extend(
|
| 226 |
self.merge_provider_lines_inline_math(
|
| 227 |
provider_lines,
|
| 228 |
+
merged_detection_boxes,
|
| 229 |
image_size,
|
| 230 |
page_size
|
| 231 |
)
|
|
|
|
| 372 |
max_overlap = np.max(overlap_row) / inline_box.area
|
| 373 |
|
| 374 |
# Avoid small or nonoverlapping inline math regions
|
| 375 |
+
if max_overlap <= self.line_inline_math_overlap_threshold:
|
| 376 |
continue
|
| 377 |
|
| 378 |
# Ignore vertical lines
|
|
|
|
| 393 |
def merge_provider_lines_inline_math(
|
| 394 |
self,
|
| 395 |
provider_lines: List[ProviderOutput],
|
| 396 |
+
text_lines: List[TextBox],
|
| 397 |
image_size,
|
| 398 |
page_size
|
| 399 |
):
|
| 400 |
# When provider lines is empty or no inline math detected, return provider lines
|
| 401 |
+
if not provider_lines or not text_lines:
|
| 402 |
return provider_lines
|
| 403 |
|
| 404 |
horizontal_provider_lines = [
|
| 405 |
(j, provider_line) for j, provider_line in enumerate(provider_lines)
|
| 406 |
+
if provider_line.line.polygon.height < provider_line.line.polygon.width * 5 # Multiply to account for small blocks inside equations, but filter out big vertical lines
|
| 407 |
]
|
| 408 |
provider_line_boxes = [p.line.polygon.bbox for _, p in horizontal_provider_lines]
|
| 409 |
+
math_line_boxes = [PolygonBox(polygon=m.polygon).rescale(image_size, page_size).bbox for m in text_lines]
|
| 410 |
|
| 411 |
+
overlaps = matrix_intersection_area(provider_line_boxes, math_line_boxes)
|
| 412 |
|
| 413 |
# Find potential merges
|
| 414 |
+
merge_lines = defaultdict(list)
|
| 415 |
+
for i in range(len(provider_line_boxes)):
|
| 416 |
+
max_overlap_pct = np.max(overlaps[i]) / max(1, horizontal_provider_lines[i][1].line.polygon.area)
|
| 417 |
+
if max_overlap_pct <= self.line_inline_min_overlap_pct:
|
|
|
|
|
|
|
| 418 |
continue
|
| 419 |
|
| 420 |
best_overlap = np.argmax(overlaps[i])
|
| 421 |
+
merge_lines[best_overlap].append(i)
|
| 422 |
+
|
| 423 |
+
# Filter to get rid of detected lines that include multiple provider lines
|
| 424 |
+
filtered_merge_lines = {}
|
| 425 |
+
for line_idx in merge_lines:
|
| 426 |
+
first_line = horizontal_provider_lines[merge_lines[line_idx][0]][1].line.polygon
|
| 427 |
+
all_close = all([
|
| 428 |
+
(
|
| 429 |
+
abs(horizontal_provider_lines[ml][1].line.polygon.y_start - first_line.y_start) < self.inline_math_line_vertical_merge_threshold
|
| 430 |
+
or
|
| 431 |
+
abs(horizontal_provider_lines[ml][1].line.polygon.y_end - first_line.y_end) < self.inline_math_line_vertical_merge_threshold
|
| 432 |
+
)
|
| 433 |
+
for ml in
|
| 434 |
+
merge_lines[line_idx]
|
| 435 |
+
])
|
| 436 |
+
if all_close:
|
| 437 |
+
filtered_merge_lines[line_idx] = merge_lines[line_idx]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
|
| 439 |
# Handle the merging
|
| 440 |
already_merged = set()
|
| 441 |
+
potential_merges = set(chain.from_iterable(filtered_merge_lines.values()))
|
| 442 |
out_provider_lines = [(i, p) for i, p in enumerate(provider_lines) if i not in potential_merges]
|
| 443 |
+
for line_idx in filtered_merge_lines:
|
| 444 |
+
text_line = text_lines[line_idx]
|
| 445 |
+
merge_section = filtered_merge_lines[line_idx]
|
| 446 |
merge_section = [m for m in merge_section if m not in already_merged]
|
| 447 |
if len(merge_section) == 0:
|
| 448 |
continue
|
| 449 |
elif len(merge_section) == 1:
|
| 450 |
line_idx = merge_section[0]
|
| 451 |
merged_line = provider_lines[line_idx]
|
| 452 |
+
# Only add math format to single lines if the detected line is math
|
| 453 |
+
if text_line.math:
|
| 454 |
+
self.add_math_span_format(merged_line)
|
| 455 |
out_provider_lines.append((line_idx, merged_line))
|
| 456 |
already_merged.add(merge_section[0])
|
| 457 |
continue
|
|
|
|
| 466 |
else:
|
| 467 |
# Combine the spans of the provider line with the merged line
|
| 468 |
merged_line = merged_line.merge(provider_line)
|
| 469 |
+
# Add math regardless, since we assume heavily broken lines are math lines
|
| 470 |
self.add_math_span_format(merged_line)
|
| 471 |
already_merged.add(idx) # Prevent double merging
|
| 472 |
out_provider_lines.append((min_idx, merged_line))
|
marker/converters/pdf.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
import os
|
| 2 |
-
|
| 3 |
os.environ["TOKENIZERS_PARALLELISM"] = "false" # disables a tokenizers warning
|
| 4 |
|
| 5 |
from collections import defaultdict
|
|
@@ -43,6 +42,8 @@ from marker.util import strings_to_classes
|
|
| 43 |
from marker.processors.llm.llm_handwriting import LLMHandwritingProcessor
|
| 44 |
from marker.processors.order import OrderProcessor
|
| 45 |
from marker.services.gemini import GoogleGeminiService
|
|
|
|
|
|
|
| 46 |
|
| 47 |
|
| 48 |
class PdfConverter(BaseConverter):
|
|
@@ -62,6 +63,7 @@ class PdfConverter(BaseConverter):
|
|
| 62 |
] = False
|
| 63 |
default_processors: Tuple[BaseProcessor, ...] = (
|
| 64 |
OrderProcessor,
|
|
|
|
| 65 |
BlockquoteProcessor,
|
| 66 |
CodeProcessor,
|
| 67 |
DocumentTOCProcessor,
|
|
@@ -82,6 +84,7 @@ class PdfConverter(BaseConverter):
|
|
| 82 |
LLMImageDescriptionProcessor,
|
| 83 |
LLMEquationProcessor,
|
| 84 |
LLMHandwritingProcessor,
|
|
|
|
| 85 |
ReferenceProcessor,
|
| 86 |
DebugProcessor,
|
| 87 |
)
|
|
|
|
| 1 |
import os
|
|
|
|
| 2 |
os.environ["TOKENIZERS_PARALLELISM"] = "false" # disables a tokenizers warning
|
| 3 |
|
| 4 |
from collections import defaultdict
|
|
|
|
| 42 |
from marker.processors.llm.llm_handwriting import LLMHandwritingProcessor
|
| 43 |
from marker.processors.order import OrderProcessor
|
| 44 |
from marker.services.gemini import GoogleGeminiService
|
| 45 |
+
from marker.processors.line_merge import LineMergeProcessor
|
| 46 |
+
from marker.processors.llm.llm_inlinemath import LLMInlineMathProcessor
|
| 47 |
|
| 48 |
|
| 49 |
class PdfConverter(BaseConverter):
|
|
|
|
| 63 |
] = False
|
| 64 |
default_processors: Tuple[BaseProcessor, ...] = (
|
| 65 |
OrderProcessor,
|
| 66 |
+
LineMergeProcessor,
|
| 67 |
BlockquoteProcessor,
|
| 68 |
CodeProcessor,
|
| 69 |
DocumentTOCProcessor,
|
|
|
|
| 84 |
LLMImageDescriptionProcessor,
|
| 85 |
LLMEquationProcessor,
|
| 86 |
LLMHandwritingProcessor,
|
| 87 |
+
LLMInlineMathProcessor,
|
| 88 |
ReferenceProcessor,
|
| 89 |
DebugProcessor,
|
| 90 |
)
|
marker/processors/debug.py
CHANGED
|
@@ -64,16 +64,21 @@ class DebugProcessor(BaseProcessor):
|
|
| 64 |
|
| 65 |
line_bboxes = []
|
| 66 |
span_bboxes = []
|
|
|
|
| 67 |
for child in page.children:
|
|
|
|
|
|
|
|
|
|
| 68 |
if child.block_type == BlockTypes.Line:
|
| 69 |
bbox = child.polygon.rescale(page.polygon.size, png_image.size).bbox
|
| 70 |
line_bboxes.append(bbox)
|
|
|
|
| 71 |
elif child.block_type == BlockTypes.Span:
|
| 72 |
bbox = child.polygon.rescale(page.polygon.size, png_image.size).bbox
|
| 73 |
span_bboxes.append(bbox)
|
| 74 |
|
| 75 |
-
self.render_on_image(line_bboxes, png_image, color="blue", draw_bbox=True, label_font_size=24)
|
| 76 |
-
self.render_on_image(span_bboxes, png_image, color="green", draw_bbox=True, label_font_size=24)
|
| 77 |
|
| 78 |
png_image = self.render_layout_boxes(page, png_image)
|
| 79 |
|
|
|
|
| 64 |
|
| 65 |
line_bboxes = []
|
| 66 |
span_bboxes = []
|
| 67 |
+
line_ids = []
|
| 68 |
for child in page.children:
|
| 69 |
+
# Skip any blocks that have been removed
|
| 70 |
+
if child.removed:
|
| 71 |
+
continue
|
| 72 |
if child.block_type == BlockTypes.Line:
|
| 73 |
bbox = child.polygon.rescale(page.polygon.size, png_image.size).bbox
|
| 74 |
line_bboxes.append(bbox)
|
| 75 |
+
line_ids.append(child.block_id)
|
| 76 |
elif child.block_type == BlockTypes.Span:
|
| 77 |
bbox = child.polygon.rescale(page.polygon.size, png_image.size).bbox
|
| 78 |
span_bboxes.append(bbox)
|
| 79 |
|
| 80 |
+
self.render_on_image(line_bboxes, png_image, color="blue", draw_bbox=True, label_font_size=24, labels=[str(i) for i in line_ids])
|
| 81 |
+
#self.render_on_image(span_bboxes, png_image, color="green", draw_bbox=True, label_font_size=24)
|
| 82 |
|
| 83 |
png_image = self.render_layout_boxes(page, png_image)
|
| 84 |
|
marker/processors/line_merge.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Annotated
|
| 2 |
+
|
| 3 |
+
from marker.processors import BaseProcessor
|
| 4 |
+
from marker.schema import BlockTypes
|
| 5 |
+
from marker.schema.document import Document
|
| 6 |
+
from marker.schema.text import Line
|
| 7 |
+
from marker.util import matrix_intersection_area
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class LineMergeProcessor(BaseProcessor):
|
| 11 |
+
"""
|
| 12 |
+
A processor for merging inline math lines.
|
| 13 |
+
"""
|
| 14 |
+
block_types = (BlockTypes.Text, BlockTypes.TextInlineMath)
|
| 15 |
+
min_merge_pct: Annotated[
|
| 16 |
+
float,
|
| 17 |
+
"The minimum percentage of intersection area to consider merging."
|
| 18 |
+
] = .02
|
| 19 |
+
min_merge_ydist: Annotated[
|
| 20 |
+
float,
|
| 21 |
+
"The minimum y distance between lines to consider merging."
|
| 22 |
+
] = 5
|
| 23 |
+
intersection_pct_threshold: Annotated[
|
| 24 |
+
float,
|
| 25 |
+
"The total amount of intersection area concentrated in the max intersection block."
|
| 26 |
+
] = .7
|
| 27 |
+
|
| 28 |
+
def __init__(self, config):
|
| 29 |
+
super().__init__(config)
|
| 30 |
+
|
| 31 |
+
def __call__(self, document: Document):
|
| 32 |
+
for page in document.pages:
|
| 33 |
+
for block in page.contained_blocks(document, self.block_types):
|
| 34 |
+
if block.structure is None:
|
| 35 |
+
continue
|
| 36 |
+
|
| 37 |
+
if not len(block.structure) >= 2: # Skip single lines
|
| 38 |
+
continue
|
| 39 |
+
|
| 40 |
+
lines = block.contained_blocks(document, (BlockTypes.Line,))
|
| 41 |
+
lines = [l for l in lines if l.polygon.width * 5 > l.polygon.height] # Skip vertical lines
|
| 42 |
+
line_bboxes = [l.polygon.expand(self.min_merge_pct, 0).bbox for l in lines] # Expand horizontally
|
| 43 |
+
intersections = matrix_intersection_area(line_bboxes, line_bboxes)
|
| 44 |
+
|
| 45 |
+
merges = []
|
| 46 |
+
merge = []
|
| 47 |
+
for i in range(len(line_bboxes) - 1):
|
| 48 |
+
next_idx = i + 1
|
| 49 |
+
intersection_val = intersections[i, next_idx]
|
| 50 |
+
intersection_pct = intersection_val / max(1, lines[i].polygon.area)
|
| 51 |
+
intersection_row = intersections[i]
|
| 52 |
+
intersection_row[i] = 0 # Zero out the current idx
|
| 53 |
+
|
| 54 |
+
# Zero out previous merge segments
|
| 55 |
+
for m in merge:
|
| 56 |
+
intersection_row[m] = 0
|
| 57 |
+
max_intersection_idx = intersection_row.argmax()
|
| 58 |
+
total_intersection = max(1, sum(intersection_row))
|
| 59 |
+
max_intersection = intersection_row[max_intersection_idx]
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
if all([
|
| 63 |
+
max_intersection_idx == next_idx, # The next line is the max intersection line
|
| 64 |
+
intersection_pct >= self.min_merge_pct,
|
| 65 |
+
abs(lines[i].polygon.y_start - lines[next_idx].polygon.y_start) <= self.min_merge_ydist,
|
| 66 |
+
abs(lines[i].polygon.y_end - lines[next_idx].polygon.y_end) <= self.min_merge_ydist,
|
| 67 |
+
max_intersection / total_intersection >= self.intersection_pct_threshold
|
| 68 |
+
]):
|
| 69 |
+
if not merge:
|
| 70 |
+
merge.append(i)
|
| 71 |
+
merge.append(next_idx)
|
| 72 |
+
else:
|
| 73 |
+
merges.append(merge)
|
| 74 |
+
merge = []
|
| 75 |
+
|
| 76 |
+
if merge:
|
| 77 |
+
merges.append(merge)
|
| 78 |
+
|
| 79 |
+
merges = [m for m in merges if len(m) > 1]
|
| 80 |
+
merged = set()
|
| 81 |
+
for merge in merges:
|
| 82 |
+
merge = [m for m in merge if m not in merged]
|
| 83 |
+
if len(merge) < 2:
|
| 84 |
+
continue
|
| 85 |
+
|
| 86 |
+
line: Line = lines[merge[0]]
|
| 87 |
+
merged.add(merge[0])
|
| 88 |
+
for idx in merge[1:]:
|
| 89 |
+
other_line: Line = lines[idx]
|
| 90 |
+
line.merge(other_line)
|
| 91 |
+
block.structure.remove(other_line.id)
|
| 92 |
+
other_line.removed = True # Mark line as removed
|
| 93 |
+
merged.add(idx)
|
| 94 |
+
|
| 95 |
+
# It is probably math if we are merging provider lines like this
|
| 96 |
+
if not line.formats:
|
| 97 |
+
line.formats = ["math"]
|
| 98 |
+
elif "math" not in line.formats:
|
| 99 |
+
line.formats.append("math")
|
marker/processors/llm/llm_equation.py
CHANGED
|
@@ -12,7 +12,7 @@ class LLMEquationProcessor(BaseLLMSimpleBlockProcessor):
|
|
| 12 |
min_equation_height: Annotated[
|
| 13 |
float,
|
| 14 |
"The minimum ratio between equation height and page height to consider for processing.",
|
| 15 |
-
] = 0.
|
| 16 |
image_expansion_ratio: Annotated[
|
| 17 |
float,
|
| 18 |
"The ratio to expand the image by when cropping.",
|
|
|
|
| 12 |
min_equation_height: Annotated[
|
| 13 |
float,
|
| 14 |
"The minimum ratio between equation height and page height to consider for processing.",
|
| 15 |
+
] = 0.06
|
| 16 |
image_expansion_ratio: Annotated[
|
| 17 |
float,
|
| 18 |
"The ratio to expand the image by when cropping.",
|
marker/processors/llm/llm_inlinemath.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 3 |
+
from typing import List, Tuple, Annotated
|
| 4 |
+
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from tqdm import tqdm
|
| 7 |
+
|
| 8 |
+
from marker.processors.llm import BaseLLMComplexBlockProcessor
|
| 9 |
+
|
| 10 |
+
from marker.processors.util import text_to_spans
|
| 11 |
+
from marker.schema import BlockTypes
|
| 12 |
+
from marker.schema.blocks import Block
|
| 13 |
+
from marker.schema.document import Document
|
| 14 |
+
from marker.schema.groups import PageGroup
|
| 15 |
+
from marker.schema.registry import get_block_class
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class LLMInlineMathProcessor(BaseLLMComplexBlockProcessor):
|
| 19 |
+
redo_inline_math: Annotated[
|
| 20 |
+
bool,
|
| 21 |
+
"If True, the inline math will be re-done, otherwise it will be left as is."
|
| 22 |
+
] = False
|
| 23 |
+
|
| 24 |
+
block_types = (BlockTypes.TextInlineMath,)
|
| 25 |
+
text_math_rewriting_prompt = """You are a text correction expert specializing in accurately reproducing text from images.
|
| 26 |
+
You will receive an image of a text block and a set of extracted lines corresponding to the text in the image.
|
| 27 |
+
Your task is to correct any errors in the extracted lines, including math, formatting, and other inaccuracies, and output the corrected lines in a JSON format.
|
| 28 |
+
The number of output lines MUST match the number of input lines. There are {input_line_count} input lines. Stay as faithful to the original text as possible.
|
| 29 |
+
|
| 30 |
+
**Instructions:**
|
| 31 |
+
|
| 32 |
+
1. Carefully examine the provided text block image .
|
| 33 |
+
2. Analyze the extracted lines.
|
| 34 |
+
3. For each extracted line, compare it to the corresponding line in the image.
|
| 35 |
+
4. If there are no errors in any of the extracted lines, output "No corrections needed".
|
| 36 |
+
5. For each extracted line, correct any errors, including:
|
| 37 |
+
* Inline math: Ensure all mathematical expressions are correctly formatted and rendered. Surround them with <math>...</math> tags.
|
| 38 |
+
* Formatting: Maintain consistent formatting with the text block image, including spacing, indentation, and special characters.
|
| 39 |
+
* Other inaccuracies: If the image is handwritten then you may correct any spelling errors, or other discrepancies.
|
| 40 |
+
6. Do not remove any formatting i.e bold, italics, math, superscripts, subscripts, etc from the extracted lines unless it is necessary to correct an error.
|
| 41 |
+
7. The number of corrected lines in the output MUST equal the number of extracted lines provided in the input. Do not add or remove lines.
|
| 42 |
+
8. Output the corrected lines in JSON format, as shown in the example below. Each line should be in HTML format. Only use the math, br, a, i, b, sup, sub, and span tags.
|
| 43 |
+
9. You absolutely cannot remove any <a href='#...'>...</a> tags, those are extremely important for references and are coming directly from the document, you MUST always preserve them.
|
| 44 |
+
|
| 45 |
+
**Example:**
|
| 46 |
+
|
| 47 |
+
Input:
|
| 48 |
+
```
|
| 49 |
+
{
|
| 50 |
+
"extracted_lines": [
|
| 51 |
+
"Adversarial training (AT) <a href='#page-9-1'>[23]</a>, which aims to minimize\n",
|
| 52 |
+
"the model's risk under the worst-case perturbations, is cur-\n",
|
| 53 |
+
"rently the most effective approach for improving the robust-\n",
|
| 54 |
+
"ness of deep neural networks. For a given neural network\n",
|
| 55 |
+
"f(x, w) with parameters w, the optimization objective of\n",
|
| 56 |
+
"AT can be formulated as follows:\n"
|
| 57 |
+
]
|
| 58 |
+
}
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
Output:
|
| 62 |
+
|
| 63 |
+
```json
|
| 64 |
+
{
|
| 65 |
+
"corrected_lines": [
|
| 66 |
+
"Adversarial training (AT) <a href='#page-9-1'>[23]</a>, which aims to minimize\n",
|
| 67 |
+
"the model's risk under the worst-case perturbations, is cur-\n",
|
| 68 |
+
"rently the most effective approach for improving the robust-\n",
|
| 69 |
+
"ness of deep neural networks. For a given neural network\n",
|
| 70 |
+
"<math>f(x, w)</math> with parameters <math>w</math>, the optimization objective of\n",
|
| 71 |
+
"AT can be formulated as follows:\n"
|
| 72 |
+
]
|
| 73 |
+
}
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
**Input:**
|
| 77 |
+
```json
|
| 78 |
+
{extracted_lines}
|
| 79 |
+
```
|
| 80 |
+
"""
|
| 81 |
+
|
| 82 |
+
def rewrite_blocks(self, document: Document):
|
| 83 |
+
if not self.redo_inline_math:
|
| 84 |
+
return
|
| 85 |
+
|
| 86 |
+
# Get inline math blocks
|
| 87 |
+
inline_blocks = [
|
| 88 |
+
(page, block)
|
| 89 |
+
for page in document.pages
|
| 90 |
+
for block in page.contained_blocks(document, self.block_types)
|
| 91 |
+
]
|
| 92 |
+
|
| 93 |
+
# Get other blocks with detected math in them
|
| 94 |
+
detected_blocks = [
|
| 95 |
+
(page, block)
|
| 96 |
+
for page in document.pages
|
| 97 |
+
for block in page.contained_blocks(document, (BlockTypes.Text, BlockTypes.Caption, BlockTypes.SectionHeader, BlockTypes.Footnote))
|
| 98 |
+
if any([b.formats and "math" in b.formats for b in block.contained_blocks(document, (BlockTypes.Line,))])
|
| 99 |
+
]
|
| 100 |
+
inference_blocks = inline_blocks + detected_blocks
|
| 101 |
+
|
| 102 |
+
# Don't show progress if there are no blocks to process
|
| 103 |
+
total_blocks = len(inference_blocks)
|
| 104 |
+
if total_blocks == 0:
|
| 105 |
+
return
|
| 106 |
+
|
| 107 |
+
pbar = tqdm(desc=f"{self.__class__.__name__} running", disable=self.disable_tqdm)
|
| 108 |
+
with ThreadPoolExecutor(max_workers=self.max_concurrency) as executor:
|
| 109 |
+
for future in as_completed([
|
| 110 |
+
executor.submit(self.process_rewriting, document, b[0], b[1])
|
| 111 |
+
for b in inference_blocks
|
| 112 |
+
]):
|
| 113 |
+
future.result() # Raise exceptions if any occurred
|
| 114 |
+
pbar.update(1)
|
| 115 |
+
|
| 116 |
+
pbar.close()
|
| 117 |
+
|
| 118 |
+
def get_block_lines(self, block: Block, document: Document) -> Tuple[list, list]:
|
| 119 |
+
text_lines = block.contained_blocks(document, (BlockTypes.Line,))
|
| 120 |
+
extracted_lines = [line.formatted_text(document) for line in text_lines]
|
| 121 |
+
return text_lines, extracted_lines
|
| 122 |
+
|
| 123 |
+
def process_rewriting(self, document: Document, page: PageGroup, block: Block):
|
| 124 |
+
SpanClass = get_block_class(BlockTypes.Span)
|
| 125 |
+
|
| 126 |
+
text_lines, extracted_lines = self.get_block_lines(block, document)
|
| 127 |
+
prompt = (self.text_math_rewriting_prompt.replace("{extracted_lines}",
|
| 128 |
+
json.dumps({"extracted_lines": extracted_lines}, indent=2))
|
| 129 |
+
.replace("{input_line_count}", str(len(extracted_lines)))
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
image = self.extract_image(document, block)
|
| 133 |
+
response = self.llm_service(prompt, image, block, LLMTextSchema)
|
| 134 |
+
|
| 135 |
+
if not response or "corrected_lines" not in response:
|
| 136 |
+
block.update_metadata(llm_error_count=1)
|
| 137 |
+
return
|
| 138 |
+
|
| 139 |
+
corrected_lines = response["corrected_lines"]
|
| 140 |
+
if not corrected_lines:
|
| 141 |
+
block.update_metadata(llm_error_count=1)
|
| 142 |
+
return
|
| 143 |
+
|
| 144 |
+
# Block is fine
|
| 145 |
+
if "no corrections needed" in str(corrected_lines).lower():
|
| 146 |
+
return
|
| 147 |
+
|
| 148 |
+
if len(corrected_lines) != len(extracted_lines):
|
| 149 |
+
block.update_metadata(llm_error_count=1)
|
| 150 |
+
return
|
| 151 |
+
|
| 152 |
+
for text_line, corrected_text in zip(text_lines, corrected_lines):
|
| 153 |
+
text_line.structure = []
|
| 154 |
+
corrected_spans = text_to_spans(corrected_text)
|
| 155 |
+
|
| 156 |
+
for span_idx, span in enumerate(corrected_spans):
|
| 157 |
+
if span_idx == len(corrected_spans) - 1:
|
| 158 |
+
span['content'] += "\n"
|
| 159 |
+
|
| 160 |
+
span_block = page.add_full_block(
|
| 161 |
+
SpanClass(
|
| 162 |
+
polygon=text_line.polygon,
|
| 163 |
+
text=span['content'],
|
| 164 |
+
font='Unknown',
|
| 165 |
+
font_weight=0,
|
| 166 |
+
font_size=0,
|
| 167 |
+
minimum_position=0,
|
| 168 |
+
maximum_position=0,
|
| 169 |
+
formats=[span['type']],
|
| 170 |
+
url=span.get('url'),
|
| 171 |
+
page_id=text_line.page_id,
|
| 172 |
+
text_extraction_method="gemini",
|
| 173 |
+
)
|
| 174 |
+
)
|
| 175 |
+
text_line.structure.append(span_block.id)
|
| 176 |
+
|
| 177 |
+
class LLMTextSchema(BaseModel):
|
| 178 |
+
corrected_lines: List[str]
|
marker/processors/llm/llm_text.py
CHANGED
|
@@ -38,7 +38,7 @@ The number of output lines MUST match the number of input lines. Stay as faithf
|
|
| 38 |
* Other inaccuracies: If the image is handwritten then you may correct any spelling errors, or other discrepancies.
|
| 39 |
5. Do not remove any formatting i.e bold, italics, math, superscripts, subscripts, etc from the extracted lines unless it is necessary to correct an error. The formatting
|
| 40 |
6. The number of corrected lines in the output MUST equal the number of extracted lines provided in the input. Do not add or remove lines. There are exactly {line_count} input lines.
|
| 41 |
-
7. Output the corrected lines in JSON format
|
| 42 |
8. You absolutely cannot remove any <a href='#...'>...</a> tags, those are extremely important for references and are coming directly from the document, you MUST always preserve them.
|
| 43 |
|
| 44 |
**Example:**
|
|
@@ -88,6 +88,7 @@ Output:
|
|
| 88 |
"block": block
|
| 89 |
})
|
| 90 |
|
|
|
|
| 91 |
out_blocks = []
|
| 92 |
for i in range(0, len(blocks), self.math_line_batch_size):
|
| 93 |
batch = blocks[i:i + self.math_line_batch_size]
|
|
|
|
| 38 |
* Other inaccuracies: If the image is handwritten then you may correct any spelling errors, or other discrepancies.
|
| 39 |
5. Do not remove any formatting i.e bold, italics, math, superscripts, subscripts, etc from the extracted lines unless it is necessary to correct an error. The formatting
|
| 40 |
6. The number of corrected lines in the output MUST equal the number of extracted lines provided in the input. Do not add or remove lines. There are exactly {line_count} input lines.
|
| 41 |
+
7. Output the corrected lines in JSON format, as shown in the example below. Each line should be in HTML format. Only use the math, br, a, i, b, sup, sub, and span tags.
|
| 42 |
8. You absolutely cannot remove any <a href='#...'>...</a> tags, those are extremely important for references and are coming directly from the document, you MUST always preserve them.
|
| 43 |
|
| 44 |
**Example:**
|
|
|
|
| 88 |
"block": block
|
| 89 |
})
|
| 90 |
|
| 91 |
+
|
| 92 |
out_blocks = []
|
| 93 |
for i in range(0, len(blocks), self.math_line_batch_size):
|
| 94 |
batch = blocks[i:i + self.math_line_batch_size]
|
marker/renderers/__init__.py
CHANGED
|
@@ -40,6 +40,17 @@ class BaseRenderer:
|
|
| 40 |
cropped = base64.b64encode(image_buffer.getvalue()).decode(settings.OUTPUT_ENCODING)
|
| 41 |
return cropped
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
@staticmethod
|
| 44 |
def merge_consecutive_tags(html, tag):
|
| 45 |
if not html:
|
|
|
|
| 40 |
cropped = base64.b64encode(image_buffer.getvalue()).decode(settings.OUTPUT_ENCODING)
|
| 41 |
return cropped
|
| 42 |
|
| 43 |
+
@staticmethod
|
| 44 |
+
def merge_consecutive_math(html, tag="math"):
|
| 45 |
+
if not html:
|
| 46 |
+
return html
|
| 47 |
+
pattern = fr'-</{tag}>(\s*)<{tag}>'
|
| 48 |
+
html = re.sub(pattern, " ", html)
|
| 49 |
+
|
| 50 |
+
pattern = fr'-</{tag}>(\s*)<{tag} display="inline">'
|
| 51 |
+
html = re.sub(pattern, " ", html)
|
| 52 |
+
return html
|
| 53 |
+
|
| 54 |
@staticmethod
|
| 55 |
def merge_consecutive_tags(html, tag):
|
| 56 |
if not html:
|
marker/renderers/html.py
CHANGED
|
@@ -82,6 +82,7 @@ class HTMLRenderer(BaseRenderer):
|
|
| 82 |
if level == 0:
|
| 83 |
output = self.merge_consecutive_tags(output, 'b')
|
| 84 |
output = self.merge_consecutive_tags(output, 'i')
|
|
|
|
| 85 |
output = textwrap.dedent(f"""
|
| 86 |
<!DOCTYPE html>
|
| 87 |
<html>
|
|
|
|
| 82 |
if level == 0:
|
| 83 |
output = self.merge_consecutive_tags(output, 'b')
|
| 84 |
output = self.merge_consecutive_tags(output, 'i')
|
| 85 |
+
output = self.merge_consecutive_math(output) # Merge consecutive inline math tags
|
| 86 |
output = textwrap.dedent(f"""
|
| 87 |
<!DOCTYPE html>
|
| 88 |
<html>
|
marker/schema/blocks/base.py
CHANGED
|
@@ -215,7 +215,7 @@ class Block(BaseModel):
|
|
| 215 |
blocks = []
|
| 216 |
for block_id in self.structure:
|
| 217 |
block = document.get_block(block_id)
|
| 218 |
-
if block_types is None or block.block_type in block_types:
|
| 219 |
blocks.append(block)
|
| 220 |
blocks += block.contained_blocks(document, block_types)
|
| 221 |
return blocks
|
|
|
|
| 215 |
blocks = []
|
| 216 |
for block_id in self.structure:
|
| 217 |
block = document.get_block(block_id)
|
| 218 |
+
if (block_types is None or block.block_type in block_types) and not block.removed:
|
| 219 |
blocks.append(block)
|
| 220 |
blocks += block.contained_blocks(document, block_types)
|
| 221 |
return blocks
|
marker/schema/text/line.py
CHANGED
|
@@ -91,3 +91,11 @@ class Line(Block):
|
|
| 91 |
children=[],
|
| 92 |
section_hierarchy=section_hierarchy
|
| 93 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
children=[],
|
| 92 |
section_hierarchy=section_hierarchy
|
| 93 |
)
|
| 94 |
+
|
| 95 |
+
def merge(self, other: "Line"):
|
| 96 |
+
self.polygon = self.polygon.merge([other.polygon])
|
| 97 |
+
self.structure = self.structure + other.structure
|
| 98 |
+
if self.formats is None:
|
| 99 |
+
self.formats = other.formats
|
| 100 |
+
elif other.formats is not None:
|
| 101 |
+
self.formats.extend(other.formats)
|
marker/services/claude.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import base64
|
| 2 |
+
import json
|
| 3 |
+
import time
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
from typing import List, Annotated, Union, T
|
| 6 |
+
|
| 7 |
+
import PIL
|
| 8 |
+
from PIL import Image
|
| 9 |
+
import anthropic
|
| 10 |
+
from anthropic import RateLimitError
|
| 11 |
+
from pydantic import BaseModel
|
| 12 |
+
|
| 13 |
+
from marker.schema.blocks import Block
|
| 14 |
+
from marker.services import BaseService
|
| 15 |
+
|
| 16 |
+
class ClaudeService(BaseService):
|
| 17 |
+
claude_model_name: Annotated[
|
| 18 |
+
str,
|
| 19 |
+
"The name of the Google model to use for the service."
|
| 20 |
+
] = "claude-3-5-sonnet-20241022"
|
| 21 |
+
claude_api_key: Annotated[
|
| 22 |
+
str,
|
| 23 |
+
"The Claude API key to use for the service."
|
| 24 |
+
] = None
|
| 25 |
+
max_claude_tokens: Annotated[
|
| 26 |
+
int,
|
| 27 |
+
"The maximum number of tokens to use for a single Claude request."
|
| 28 |
+
] = 4096
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def img_to_base64(self, img: PIL.Image.Image):
|
| 32 |
+
image_bytes = BytesIO()
|
| 33 |
+
img.save(image_bytes, format="WEBP")
|
| 34 |
+
return base64.b64encode(image_bytes.getvalue()).decode('utf-8')
|
| 35 |
+
|
| 36 |
+
def prepare_images(self, images: Union[Image.Image, List[Image.Image]]) -> List[dict]:
|
| 37 |
+
if isinstance(images, Image.Image):
|
| 38 |
+
images = [images]
|
| 39 |
+
|
| 40 |
+
return [
|
| 41 |
+
{
|
| 42 |
+
"type": "image",
|
| 43 |
+
"source": {
|
| 44 |
+
"type": "base64",
|
| 45 |
+
"media_type": "image/webp",
|
| 46 |
+
"data": self.img_to_base64(img)
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
for img in images
|
| 50 |
+
]
|
| 51 |
+
|
| 52 |
+
def validate_response(self, response_text: str, schema: type[T]) -> T:
|
| 53 |
+
response_text = response_text.strip()
|
| 54 |
+
if response_text.startswith("```json"):
|
| 55 |
+
response_text = response_text[7:]
|
| 56 |
+
if response_text.endswith("```"):
|
| 57 |
+
response_text = response_text[:-3]
|
| 58 |
+
|
| 59 |
+
try:
|
| 60 |
+
# Try to parse as JSON first
|
| 61 |
+
out_schema = schema.model_validate_json(response_text)
|
| 62 |
+
out_json = out_schema.model_dump()
|
| 63 |
+
return out_json
|
| 64 |
+
except Exception as e:
|
| 65 |
+
try:
|
| 66 |
+
# Re-parse with fixed escapes
|
| 67 |
+
escaped_str = response_text.replace('\\', '\\\\')
|
| 68 |
+
out_schema = schema.model_validate_json(escaped_str)
|
| 69 |
+
return out_schema.model_dump()
|
| 70 |
+
except Exception as e:
|
| 71 |
+
return
|
| 72 |
+
|
| 73 |
+
def get_client(self):
|
| 74 |
+
return anthropic.Anthropic(
|
| 75 |
+
api_key=self.claude_api_key,
|
| 76 |
+
)
|
| 77 |
+
|
| 78 |
+
def __call__(
|
| 79 |
+
self,
|
| 80 |
+
prompt: str,
|
| 81 |
+
image: PIL.Image.Image | List[PIL.Image.Image],
|
| 82 |
+
block: Block,
|
| 83 |
+
response_schema: type[BaseModel],
|
| 84 |
+
max_retries: int | None = None,
|
| 85 |
+
timeout: int | None = None
|
| 86 |
+
):
|
| 87 |
+
if max_retries is None:
|
| 88 |
+
max_retries = self.max_retries
|
| 89 |
+
|
| 90 |
+
if timeout is None:
|
| 91 |
+
timeout = self.timeout
|
| 92 |
+
|
| 93 |
+
if not isinstance(image, list):
|
| 94 |
+
image = [image]
|
| 95 |
+
|
| 96 |
+
schema_example = response_schema.model_json_schema()
|
| 97 |
+
system_prompt = f"""
|
| 98 |
+
Follow the instructions given by the user prompt. You must provide your response in JSON format matching this schema:
|
| 99 |
+
|
| 100 |
+
{json.dumps(schema_example, indent=2)}
|
| 101 |
+
|
| 102 |
+
Respond only with the JSON schema, nothing else. Do not include ```json, ```, or any other formatting.
|
| 103 |
+
""".strip()
|
| 104 |
+
|
| 105 |
+
client = self.get_client()
|
| 106 |
+
image_data = self.prepare_images(image)
|
| 107 |
+
|
| 108 |
+
messages = [
|
| 109 |
+
{
|
| 110 |
+
"role": "user",
|
| 111 |
+
"content": [
|
| 112 |
+
*image_data,
|
| 113 |
+
{
|
| 114 |
+
"type": "text",
|
| 115 |
+
"text": prompt
|
| 116 |
+
},
|
| 117 |
+
]
|
| 118 |
+
}
|
| 119 |
+
]
|
| 120 |
+
|
| 121 |
+
tries = 0
|
| 122 |
+
while tries < max_retries:
|
| 123 |
+
try:
|
| 124 |
+
response = client.messages.create(
|
| 125 |
+
system=system_prompt,
|
| 126 |
+
model=self.claude_model_name,
|
| 127 |
+
max_tokens=self.max_claude_tokens,
|
| 128 |
+
messages=messages,
|
| 129 |
+
timeout=timeout
|
| 130 |
+
)
|
| 131 |
+
# Extract and validate response
|
| 132 |
+
response_text = response.content[0].text
|
| 133 |
+
return self.validate_response(response_text, response_schema)
|
| 134 |
+
except RateLimitError as e:
|
| 135 |
+
# Rate limit exceeded
|
| 136 |
+
tries += 1
|
| 137 |
+
wait_time = tries * 3
|
| 138 |
+
print(f"Rate limit error: {e}. Retrying in {wait_time} seconds... (Attempt {tries}/{max_retries})")
|
| 139 |
+
time.sleep(wait_time)
|
| 140 |
+
except Exception as e:
|
| 141 |
+
print(e)
|
| 142 |
+
break
|
| 143 |
+
|
| 144 |
+
return {}
|
poetry.lock
CHANGED
|
@@ -163,6 +163,30 @@ files = [
|
|
| 163 |
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
| 164 |
]
|
| 165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
[[package]]
|
| 167 |
name = "anyio"
|
| 168 |
version = "4.8.0"
|
|
@@ -582,13 +606,13 @@ cffi = ">=1.0.0"
|
|
| 582 |
|
| 583 |
[[package]]
|
| 584 |
name = "cachetools"
|
| 585 |
-
version = "5.5.
|
| 586 |
description = "Extensible memoizing collections and decorators"
|
| 587 |
optional = false
|
| 588 |
python-versions = ">=3.7"
|
| 589 |
files = [
|
| 590 |
-
{file = "cachetools-5.5.
|
| 591 |
-
{file = "cachetools-5.5.
|
| 592 |
]
|
| 593 |
|
| 594 |
[[package]]
|
|
@@ -980,6 +1004,17 @@ files = [
|
|
| 980 |
{file = "Distance-0.1.3.tar.gz", hash = "sha256:60807584f5b6003f5c521aa73f39f51f631de3be5cccc5a1d67166fcbf0d4551"},
|
| 981 |
]
|
| 982 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 983 |
[[package]]
|
| 984 |
name = "ebooklib"
|
| 985 |
version = "0.18"
|
|
@@ -1756,6 +1791,91 @@ MarkupSafe = ">=2.0"
|
|
| 1756 |
[package.extras]
|
| 1757 |
i18n = ["Babel (>=2.7)"]
|
| 1758 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1759 |
[[package]]
|
| 1760 |
name = "joblib"
|
| 1761 |
version = "1.4.2"
|
|
@@ -3374,93 +3494,109 @@ wcwidth = "*"
|
|
| 3374 |
|
| 3375 |
[[package]]
|
| 3376 |
name = "propcache"
|
| 3377 |
-
version = "0.
|
| 3378 |
description = "Accelerated property cache"
|
| 3379 |
optional = false
|
| 3380 |
python-versions = ">=3.9"
|
| 3381 |
files = [
|
| 3382 |
-
{file = "propcache-0.
|
| 3383 |
-
{file = "propcache-0.
|
| 3384 |
-
{file = "propcache-0.
|
| 3385 |
-
{file = "propcache-0.
|
| 3386 |
-
{file = "propcache-0.
|
| 3387 |
-
{file = "propcache-0.
|
| 3388 |
-
{file = "propcache-0.
|
| 3389 |
-
{file = "propcache-0.
|
| 3390 |
-
{file = "propcache-0.
|
| 3391 |
-
{file = "propcache-0.
|
| 3392 |
-
{file = "propcache-0.
|
| 3393 |
-
{file = "propcache-0.
|
| 3394 |
-
{file = "propcache-0.
|
| 3395 |
-
{file = "propcache-0.
|
| 3396 |
-
{file = "propcache-0.
|
| 3397 |
-
{file = "propcache-0.
|
| 3398 |
-
{file = "propcache-0.
|
| 3399 |
-
{file = "propcache-0.
|
| 3400 |
-
{file = "propcache-0.
|
| 3401 |
-
{file = "propcache-0.
|
| 3402 |
-
{file = "propcache-0.
|
| 3403 |
-
{file = "propcache-0.
|
| 3404 |
-
{file = "propcache-0.
|
| 3405 |
-
{file = "propcache-0.
|
| 3406 |
-
{file = "propcache-0.
|
| 3407 |
-
{file = "propcache-0.
|
| 3408 |
-
{file = "propcache-0.
|
| 3409 |
-
{file = "propcache-0.
|
| 3410 |
-
{file = "propcache-0.
|
| 3411 |
-
{file = "propcache-0.
|
| 3412 |
-
{file = "propcache-0.
|
| 3413 |
-
{file = "propcache-0.
|
| 3414 |
-
{file = "propcache-0.
|
| 3415 |
-
{file = "propcache-0.
|
| 3416 |
-
{file = "propcache-0.
|
| 3417 |
-
{file = "propcache-0.
|
| 3418 |
-
{file = "propcache-0.
|
| 3419 |
-
{file = "propcache-0.
|
| 3420 |
-
{file = "propcache-0.
|
| 3421 |
-
{file = "propcache-0.
|
| 3422 |
-
{file = "propcache-0.
|
| 3423 |
-
{file = "propcache-0.
|
| 3424 |
-
{file = "propcache-0.
|
| 3425 |
-
{file = "propcache-0.
|
| 3426 |
-
{file = "propcache-0.
|
| 3427 |
-
{file = "propcache-0.
|
| 3428 |
-
{file = "propcache-0.
|
| 3429 |
-
{file = "propcache-0.
|
| 3430 |
-
{file = "propcache-0.
|
| 3431 |
-
{file = "propcache-0.
|
| 3432 |
-
{file = "propcache-0.
|
| 3433 |
-
{file = "propcache-0.
|
| 3434 |
-
{file = "propcache-0.
|
| 3435 |
-
{file = "propcache-0.
|
| 3436 |
-
{file = "propcache-0.
|
| 3437 |
-
{file = "propcache-0.
|
| 3438 |
-
{file = "propcache-0.
|
| 3439 |
-
{file = "propcache-0.
|
| 3440 |
-
{file = "propcache-0.
|
| 3441 |
-
{file = "propcache-0.
|
| 3442 |
-
{file = "propcache-0.
|
| 3443 |
-
{file = "propcache-0.
|
| 3444 |
-
{file = "propcache-0.
|
| 3445 |
-
{file = "propcache-0.
|
| 3446 |
-
{file = "propcache-0.
|
| 3447 |
-
{file = "propcache-0.
|
| 3448 |
-
{file = "propcache-0.
|
| 3449 |
-
{file = "propcache-0.
|
| 3450 |
-
{file = "propcache-0.
|
| 3451 |
-
{file = "propcache-0.
|
| 3452 |
-
{file = "propcache-0.
|
| 3453 |
-
{file = "propcache-0.
|
| 3454 |
-
{file = "propcache-0.
|
| 3455 |
-
{file = "propcache-0.
|
| 3456 |
-
{file = "propcache-0.
|
| 3457 |
-
{file = "propcache-0.
|
| 3458 |
-
{file = "propcache-0.
|
| 3459 |
-
{file = "propcache-0.
|
| 3460 |
-
{file = "propcache-0.
|
| 3461 |
-
{file = "propcache-0.
|
| 3462 |
-
{file = "propcache-0.
|
| 3463 |
-
{file = "propcache-0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3464 |
]
|
| 3465 |
|
| 3466 |
[[package]]
|
|
@@ -3755,13 +3891,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
|
| 3755 |
|
| 3756 |
[[package]]
|
| 3757 |
name = "pydantic-settings"
|
| 3758 |
-
version = "2.
|
| 3759 |
description = "Settings management using Pydantic"
|
| 3760 |
optional = false
|
| 3761 |
python-versions = ">=3.8"
|
| 3762 |
files = [
|
| 3763 |
-
{file = "pydantic_settings-2.
|
| 3764 |
-
{file = "pydantic_settings-2.
|
| 3765 |
]
|
| 3766 |
|
| 3767 |
[package.dependencies]
|
|
@@ -4507,114 +4643,114 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
|
|
| 4507 |
|
| 4508 |
[[package]]
|
| 4509 |
name = "rpds-py"
|
| 4510 |
-
version = "0.
|
| 4511 |
description = "Python bindings to Rust's persistent data structures (rpds)"
|
| 4512 |
optional = false
|
| 4513 |
python-versions = ">=3.9"
|
| 4514 |
files = [
|
| 4515 |
-
{file = "rpds_py-0.
|
| 4516 |
-
{file = "rpds_py-0.
|
| 4517 |
-
{file = "rpds_py-0.
|
| 4518 |
-
{file = "rpds_py-0.
|
| 4519 |
-
{file = "rpds_py-0.
|
| 4520 |
-
{file = "rpds_py-0.
|
| 4521 |
-
{file = "rpds_py-0.
|
| 4522 |
-
{file = "rpds_py-0.
|
| 4523 |
-
{file = "rpds_py-0.
|
| 4524 |
-
{file = "rpds_py-0.
|
| 4525 |
-
{file = "rpds_py-0.
|
| 4526 |
-
{file = "rpds_py-0.
|
| 4527 |
-
{file = "rpds_py-0.
|
| 4528 |
-
{file = "rpds_py-0.
|
| 4529 |
-
{file = "rpds_py-0.
|
| 4530 |
-
{file = "rpds_py-0.
|
| 4531 |
-
{file = "rpds_py-0.
|
| 4532 |
-
{file = "rpds_py-0.
|
| 4533 |
-
{file = "rpds_py-0.
|
| 4534 |
-
{file = "rpds_py-0.
|
| 4535 |
-
{file = "rpds_py-0.
|
| 4536 |
-
{file = "rpds_py-0.
|
| 4537 |
-
{file = "rpds_py-0.
|
| 4538 |
-
{file = "rpds_py-0.
|
| 4539 |
-
{file = "rpds_py-0.
|
| 4540 |
-
{file = "rpds_py-0.
|
| 4541 |
-
{file = "rpds_py-0.
|
| 4542 |
-
{file = "rpds_py-0.
|
| 4543 |
-
{file = "rpds_py-0.
|
| 4544 |
-
{file = "rpds_py-0.
|
| 4545 |
-
{file = "rpds_py-0.
|
| 4546 |
-
{file = "rpds_py-0.
|
| 4547 |
-
{file = "rpds_py-0.
|
| 4548 |
-
{file = "rpds_py-0.
|
| 4549 |
-
{file = "rpds_py-0.
|
| 4550 |
-
{file = "rpds_py-0.
|
| 4551 |
-
{file = "rpds_py-0.
|
| 4552 |
-
{file = "rpds_py-0.
|
| 4553 |
-
{file = "rpds_py-0.
|
| 4554 |
-
{file = "rpds_py-0.
|
| 4555 |
-
{file = "rpds_py-0.
|
| 4556 |
-
{file = "rpds_py-0.
|
| 4557 |
-
{file = "rpds_py-0.
|
| 4558 |
-
{file = "rpds_py-0.
|
| 4559 |
-
{file = "rpds_py-0.
|
| 4560 |
-
{file = "rpds_py-0.
|
| 4561 |
-
{file = "rpds_py-0.
|
| 4562 |
-
{file = "rpds_py-0.
|
| 4563 |
-
{file = "rpds_py-0.
|
| 4564 |
-
{file = "rpds_py-0.
|
| 4565 |
-
{file = "rpds_py-0.
|
| 4566 |
-
{file = "rpds_py-0.
|
| 4567 |
-
{file = "rpds_py-0.
|
| 4568 |
-
{file = "rpds_py-0.
|
| 4569 |
-
{file = "rpds_py-0.
|
| 4570 |
-
{file = "rpds_py-0.
|
| 4571 |
-
{file = "rpds_py-0.
|
| 4572 |
-
{file = "rpds_py-0.
|
| 4573 |
-
{file = "rpds_py-0.
|
| 4574 |
-
{file = "rpds_py-0.
|
| 4575 |
-
{file = "rpds_py-0.
|
| 4576 |
-
{file = "rpds_py-0.
|
| 4577 |
-
{file = "rpds_py-0.
|
| 4578 |
-
{file = "rpds_py-0.
|
| 4579 |
-
{file = "rpds_py-0.
|
| 4580 |
-
{file = "rpds_py-0.
|
| 4581 |
-
{file = "rpds_py-0.
|
| 4582 |
-
{file = "rpds_py-0.
|
| 4583 |
-
{file = "rpds_py-0.
|
| 4584 |
-
{file = "rpds_py-0.
|
| 4585 |
-
{file = "rpds_py-0.
|
| 4586 |
-
{file = "rpds_py-0.
|
| 4587 |
-
{file = "rpds_py-0.
|
| 4588 |
-
{file = "rpds_py-0.
|
| 4589 |
-
{file = "rpds_py-0.
|
| 4590 |
-
{file = "rpds_py-0.
|
| 4591 |
-
{file = "rpds_py-0.
|
| 4592 |
-
{file = "rpds_py-0.
|
| 4593 |
-
{file = "rpds_py-0.
|
| 4594 |
-
{file = "rpds_py-0.
|
| 4595 |
-
{file = "rpds_py-0.
|
| 4596 |
-
{file = "rpds_py-0.
|
| 4597 |
-
{file = "rpds_py-0.
|
| 4598 |
-
{file = "rpds_py-0.
|
| 4599 |
-
{file = "rpds_py-0.
|
| 4600 |
-
{file = "rpds_py-0.
|
| 4601 |
-
{file = "rpds_py-0.
|
| 4602 |
-
{file = "rpds_py-0.
|
| 4603 |
-
{file = "rpds_py-0.
|
| 4604 |
-
{file = "rpds_py-0.
|
| 4605 |
-
{file = "rpds_py-0.
|
| 4606 |
-
{file = "rpds_py-0.
|
| 4607 |
-
{file = "rpds_py-0.
|
| 4608 |
-
{file = "rpds_py-0.
|
| 4609 |
-
{file = "rpds_py-0.
|
| 4610 |
-
{file = "rpds_py-0.
|
| 4611 |
-
{file = "rpds_py-0.
|
| 4612 |
-
{file = "rpds_py-0.
|
| 4613 |
-
{file = "rpds_py-0.
|
| 4614 |
-
{file = "rpds_py-0.
|
| 4615 |
-
{file = "rpds_py-0.
|
| 4616 |
-
{file = "rpds_py-0.
|
| 4617 |
-
{file = "rpds_py-0.
|
| 4618 |
]
|
| 4619 |
|
| 4620 |
[[package]]
|
|
@@ -4903,13 +5039,13 @@ full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart
|
|
| 4903 |
|
| 4904 |
[[package]]
|
| 4905 |
name = "streamlit"
|
| 4906 |
-
version = "1.42.
|
| 4907 |
description = "A faster way to build and share data apps"
|
| 4908 |
optional = false
|
| 4909 |
python-versions = "!=3.9.7,>=3.9"
|
| 4910 |
files = [
|
| 4911 |
-
{file = "streamlit-1.42.
|
| 4912 |
-
{file = "streamlit-1.42.
|
| 4913 |
]
|
| 4914 |
|
| 4915 |
[package.dependencies]
|
|
@@ -5971,4 +6107,4 @@ test = ["pytest"]
|
|
| 5971 |
[metadata]
|
| 5972 |
lock-version = "2.0"
|
| 5973 |
python-versions = "^3.10"
|
| 5974 |
-
content-hash = "
|
|
|
|
| 163 |
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
| 164 |
]
|
| 165 |
|
| 166 |
+
[[package]]
|
| 167 |
+
name = "anthropic"
|
| 168 |
+
version = "0.46.0"
|
| 169 |
+
description = "The official Python library for the anthropic API"
|
| 170 |
+
optional = false
|
| 171 |
+
python-versions = ">=3.8"
|
| 172 |
+
files = [
|
| 173 |
+
{file = "anthropic-0.46.0-py3-none-any.whl", hash = "sha256:1445ec9be78d2de7ea51b4d5acd3574e414aea97ef903d0ecbb57bec806aaa49"},
|
| 174 |
+
{file = "anthropic-0.46.0.tar.gz", hash = "sha256:eac3d43271d02321a57c3ca68aca84c3d58873e8e72d1433288adee2d46b745b"},
|
| 175 |
+
]
|
| 176 |
+
|
| 177 |
+
[package.dependencies]
|
| 178 |
+
anyio = ">=3.5.0,<5"
|
| 179 |
+
distro = ">=1.7.0,<2"
|
| 180 |
+
httpx = ">=0.23.0,<1"
|
| 181 |
+
jiter = ">=0.4.0,<1"
|
| 182 |
+
pydantic = ">=1.9.0,<3"
|
| 183 |
+
sniffio = "*"
|
| 184 |
+
typing-extensions = ">=4.10,<5"
|
| 185 |
+
|
| 186 |
+
[package.extras]
|
| 187 |
+
bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"]
|
| 188 |
+
vertex = ["google-auth (>=2,<3)"]
|
| 189 |
+
|
| 190 |
[[package]]
|
| 191 |
name = "anyio"
|
| 192 |
version = "4.8.0"
|
|
|
|
| 606 |
|
| 607 |
[[package]]
|
| 608 |
name = "cachetools"
|
| 609 |
+
version = "5.5.2"
|
| 610 |
description = "Extensible memoizing collections and decorators"
|
| 611 |
optional = false
|
| 612 |
python-versions = ">=3.7"
|
| 613 |
files = [
|
| 614 |
+
{file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"},
|
| 615 |
+
{file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"},
|
| 616 |
]
|
| 617 |
|
| 618 |
[[package]]
|
|
|
|
| 1004 |
{file = "Distance-0.1.3.tar.gz", hash = "sha256:60807584f5b6003f5c521aa73f39f51f631de3be5cccc5a1d67166fcbf0d4551"},
|
| 1005 |
]
|
| 1006 |
|
| 1007 |
+
[[package]]
|
| 1008 |
+
name = "distro"
|
| 1009 |
+
version = "1.9.0"
|
| 1010 |
+
description = "Distro - an OS platform information API"
|
| 1011 |
+
optional = false
|
| 1012 |
+
python-versions = ">=3.6"
|
| 1013 |
+
files = [
|
| 1014 |
+
{file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"},
|
| 1015 |
+
{file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
|
| 1016 |
+
]
|
| 1017 |
+
|
| 1018 |
[[package]]
|
| 1019 |
name = "ebooklib"
|
| 1020 |
version = "0.18"
|
|
|
|
| 1791 |
[package.extras]
|
| 1792 |
i18n = ["Babel (>=2.7)"]
|
| 1793 |
|
| 1794 |
+
[[package]]
|
| 1795 |
+
name = "jiter"
|
| 1796 |
+
version = "0.8.2"
|
| 1797 |
+
description = "Fast iterable JSON parser."
|
| 1798 |
+
optional = false
|
| 1799 |
+
python-versions = ">=3.8"
|
| 1800 |
+
files = [
|
| 1801 |
+
{file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"},
|
| 1802 |
+
{file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"},
|
| 1803 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d"},
|
| 1804 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66"},
|
| 1805 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5"},
|
| 1806 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3"},
|
| 1807 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08"},
|
| 1808 |
+
{file = "jiter-0.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49"},
|
| 1809 |
+
{file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d"},
|
| 1810 |
+
{file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff"},
|
| 1811 |
+
{file = "jiter-0.8.2-cp310-cp310-win32.whl", hash = "sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43"},
|
| 1812 |
+
{file = "jiter-0.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105"},
|
| 1813 |
+
{file = "jiter-0.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b"},
|
| 1814 |
+
{file = "jiter-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15"},
|
| 1815 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0"},
|
| 1816 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f"},
|
| 1817 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099"},
|
| 1818 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74"},
|
| 1819 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586"},
|
| 1820 |
+
{file = "jiter-0.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc"},
|
| 1821 |
+
{file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88"},
|
| 1822 |
+
{file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6"},
|
| 1823 |
+
{file = "jiter-0.8.2-cp311-cp311-win32.whl", hash = "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44"},
|
| 1824 |
+
{file = "jiter-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855"},
|
| 1825 |
+
{file = "jiter-0.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f"},
|
| 1826 |
+
{file = "jiter-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44"},
|
| 1827 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f"},
|
| 1828 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60"},
|
| 1829 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57"},
|
| 1830 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e"},
|
| 1831 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887"},
|
| 1832 |
+
{file = "jiter-0.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d"},
|
| 1833 |
+
{file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152"},
|
| 1834 |
+
{file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29"},
|
| 1835 |
+
{file = "jiter-0.8.2-cp312-cp312-win32.whl", hash = "sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e"},
|
| 1836 |
+
{file = "jiter-0.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c"},
|
| 1837 |
+
{file = "jiter-0.8.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84"},
|
| 1838 |
+
{file = "jiter-0.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4"},
|
| 1839 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587"},
|
| 1840 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c"},
|
| 1841 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18"},
|
| 1842 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6"},
|
| 1843 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef"},
|
| 1844 |
+
{file = "jiter-0.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1"},
|
| 1845 |
+
{file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9"},
|
| 1846 |
+
{file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05"},
|
| 1847 |
+
{file = "jiter-0.8.2-cp313-cp313-win32.whl", hash = "sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a"},
|
| 1848 |
+
{file = "jiter-0.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865"},
|
| 1849 |
+
{file = "jiter-0.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca"},
|
| 1850 |
+
{file = "jiter-0.8.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0"},
|
| 1851 |
+
{file = "jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566"},
|
| 1852 |
+
{file = "jiter-0.8.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c"},
|
| 1853 |
+
{file = "jiter-0.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c"},
|
| 1854 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b"},
|
| 1855 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5"},
|
| 1856 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e"},
|
| 1857 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8"},
|
| 1858 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817"},
|
| 1859 |
+
{file = "jiter-0.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1"},
|
| 1860 |
+
{file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6"},
|
| 1861 |
+
{file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7"},
|
| 1862 |
+
{file = "jiter-0.8.2-cp38-cp38-win32.whl", hash = "sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63"},
|
| 1863 |
+
{file = "jiter-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6"},
|
| 1864 |
+
{file = "jiter-0.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee"},
|
| 1865 |
+
{file = "jiter-0.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc"},
|
| 1866 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d"},
|
| 1867 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c"},
|
| 1868 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d"},
|
| 1869 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9"},
|
| 1870 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4"},
|
| 1871 |
+
{file = "jiter-0.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27"},
|
| 1872 |
+
{file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841"},
|
| 1873 |
+
{file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637"},
|
| 1874 |
+
{file = "jiter-0.8.2-cp39-cp39-win32.whl", hash = "sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36"},
|
| 1875 |
+
{file = "jiter-0.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a"},
|
| 1876 |
+
{file = "jiter-0.8.2.tar.gz", hash = "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d"},
|
| 1877 |
+
]
|
| 1878 |
+
|
| 1879 |
[[package]]
|
| 1880 |
name = "joblib"
|
| 1881 |
version = "1.4.2"
|
|
|
|
| 3494 |
|
| 3495 |
[[package]]
|
| 3496 |
name = "propcache"
|
| 3497 |
+
version = "0.3.0"
|
| 3498 |
description = "Accelerated property cache"
|
| 3499 |
optional = false
|
| 3500 |
python-versions = ">=3.9"
|
| 3501 |
files = [
|
| 3502 |
+
{file = "propcache-0.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d"},
|
| 3503 |
+
{file = "propcache-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c"},
|
| 3504 |
+
{file = "propcache-0.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc"},
|
| 3505 |
+
{file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d"},
|
| 3506 |
+
{file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f"},
|
| 3507 |
+
{file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf"},
|
| 3508 |
+
{file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9"},
|
| 3509 |
+
{file = "propcache-0.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc"},
|
| 3510 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0"},
|
| 3511 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b"},
|
| 3512 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f"},
|
| 3513 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a"},
|
| 3514 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25"},
|
| 3515 |
+
{file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f"},
|
| 3516 |
+
{file = "propcache-0.3.0-cp310-cp310-win32.whl", hash = "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c"},
|
| 3517 |
+
{file = "propcache-0.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340"},
|
| 3518 |
+
{file = "propcache-0.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51"},
|
| 3519 |
+
{file = "propcache-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e"},
|
| 3520 |
+
{file = "propcache-0.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa"},
|
| 3521 |
+
{file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf"},
|
| 3522 |
+
{file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b"},
|
| 3523 |
+
{file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9"},
|
| 3524 |
+
{file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6"},
|
| 3525 |
+
{file = "propcache-0.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c"},
|
| 3526 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075"},
|
| 3527 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c"},
|
| 3528 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810"},
|
| 3529 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3"},
|
| 3530 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7"},
|
| 3531 |
+
{file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c"},
|
| 3532 |
+
{file = "propcache-0.3.0-cp311-cp311-win32.whl", hash = "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d"},
|
| 3533 |
+
{file = "propcache-0.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32"},
|
| 3534 |
+
{file = "propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e"},
|
| 3535 |
+
{file = "propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af"},
|
| 3536 |
+
{file = "propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5"},
|
| 3537 |
+
{file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b"},
|
| 3538 |
+
{file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667"},
|
| 3539 |
+
{file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7"},
|
| 3540 |
+
{file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7"},
|
| 3541 |
+
{file = "propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf"},
|
| 3542 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138"},
|
| 3543 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86"},
|
| 3544 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d"},
|
| 3545 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e"},
|
| 3546 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64"},
|
| 3547 |
+
{file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c"},
|
| 3548 |
+
{file = "propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d"},
|
| 3549 |
+
{file = "propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57"},
|
| 3550 |
+
{file = "propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568"},
|
| 3551 |
+
{file = "propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9"},
|
| 3552 |
+
{file = "propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767"},
|
| 3553 |
+
{file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8"},
|
| 3554 |
+
{file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0"},
|
| 3555 |
+
{file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d"},
|
| 3556 |
+
{file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05"},
|
| 3557 |
+
{file = "propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe"},
|
| 3558 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1"},
|
| 3559 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92"},
|
| 3560 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787"},
|
| 3561 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545"},
|
| 3562 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e"},
|
| 3563 |
+
{file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626"},
|
| 3564 |
+
{file = "propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374"},
|
| 3565 |
+
{file = "propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a"},
|
| 3566 |
+
{file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf"},
|
| 3567 |
+
{file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0"},
|
| 3568 |
+
{file = "propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829"},
|
| 3569 |
+
{file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa"},
|
| 3570 |
+
{file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6"},
|
| 3571 |
+
{file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db"},
|
| 3572 |
+
{file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54"},
|
| 3573 |
+
{file = "propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121"},
|
| 3574 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e"},
|
| 3575 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e"},
|
| 3576 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a"},
|
| 3577 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac"},
|
| 3578 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e"},
|
| 3579 |
+
{file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf"},
|
| 3580 |
+
{file = "propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863"},
|
| 3581 |
+
{file = "propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46"},
|
| 3582 |
+
{file = "propcache-0.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc"},
|
| 3583 |
+
{file = "propcache-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b"},
|
| 3584 |
+
{file = "propcache-0.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649"},
|
| 3585 |
+
{file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce"},
|
| 3586 |
+
{file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe"},
|
| 3587 |
+
{file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14"},
|
| 3588 |
+
{file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe"},
|
| 3589 |
+
{file = "propcache-0.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e"},
|
| 3590 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07"},
|
| 3591 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90"},
|
| 3592 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641"},
|
| 3593 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f"},
|
| 3594 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7"},
|
| 3595 |
+
{file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f"},
|
| 3596 |
+
{file = "propcache-0.3.0-cp39-cp39-win32.whl", hash = "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663"},
|
| 3597 |
+
{file = "propcache-0.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929"},
|
| 3598 |
+
{file = "propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043"},
|
| 3599 |
+
{file = "propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5"},
|
| 3600 |
]
|
| 3601 |
|
| 3602 |
[[package]]
|
|
|
|
| 3891 |
|
| 3892 |
[[package]]
|
| 3893 |
name = "pydantic-settings"
|
| 3894 |
+
version = "2.8.0"
|
| 3895 |
description = "Settings management using Pydantic"
|
| 3896 |
optional = false
|
| 3897 |
python-versions = ">=3.8"
|
| 3898 |
files = [
|
| 3899 |
+
{file = "pydantic_settings-2.8.0-py3-none-any.whl", hash = "sha256:c782c7dc3fb40e97b238e713c25d26f64314aece2e91abcff592fcac15f71820"},
|
| 3900 |
+
{file = "pydantic_settings-2.8.0.tar.gz", hash = "sha256:88e2ca28f6e68ea102c99c3c401d6c9078e68a5df600e97b43891c34e089500a"},
|
| 3901 |
]
|
| 3902 |
|
| 3903 |
[package.dependencies]
|
|
|
|
| 4643 |
|
| 4644 |
[[package]]
|
| 4645 |
name = "rpds-py"
|
| 4646 |
+
version = "0.23.1"
|
| 4647 |
description = "Python bindings to Rust's persistent data structures (rpds)"
|
| 4648 |
optional = false
|
| 4649 |
python-versions = ">=3.9"
|
| 4650 |
files = [
|
| 4651 |
+
{file = "rpds_py-0.23.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2a54027554ce9b129fc3d633c92fa33b30de9f08bc61b32c053dc9b537266fed"},
|
| 4652 |
+
{file = "rpds_py-0.23.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b5ef909a37e9738d146519657a1aab4584018746a18f71c692f2f22168ece40c"},
|
| 4653 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ee9d6f0b38efb22ad94c3b68ffebe4c47865cdf4b17f6806d6c674e1feb4246"},
|
| 4654 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7356a6da0562190558c4fcc14f0281db191cdf4cb96e7604c06acfcee96df15"},
|
| 4655 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9441af1d25aed96901f97ad83d5c3e35e6cd21a25ca5e4916c82d7dd0490a4fa"},
|
| 4656 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d8abf7896a91fb97e7977d1aadfcc2c80415d6dc2f1d0fca5b8d0df247248f3"},
|
| 4657 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b08027489ba8fedde72ddd233a5ea411b85a6ed78175f40285bd401bde7466d"},
|
| 4658 |
+
{file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fee513135b5a58f3bb6d89e48326cd5aa308e4bcdf2f7d59f67c861ada482bf8"},
|
| 4659 |
+
{file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:35d5631ce0af26318dba0ae0ac941c534453e42f569011585cb323b7774502a5"},
|
| 4660 |
+
{file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a20cb698c4a59c534c6701b1c24a968ff2768b18ea2991f886bd8985ce17a89f"},
|
| 4661 |
+
{file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e9c206a1abc27e0588cf8b7c8246e51f1a16a103734f7750830a1ccb63f557a"},
|
| 4662 |
+
{file = "rpds_py-0.23.1-cp310-cp310-win32.whl", hash = "sha256:d9f75a06ecc68f159d5d7603b734e1ff6daa9497a929150f794013aa9f6e3f12"},
|
| 4663 |
+
{file = "rpds_py-0.23.1-cp310-cp310-win_amd64.whl", hash = "sha256:f35eff113ad430b5272bbfc18ba111c66ff525828f24898b4e146eb479a2cdda"},
|
| 4664 |
+
{file = "rpds_py-0.23.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b79f5ced71efd70414a9a80bbbfaa7160da307723166f09b69773153bf17c590"},
|
| 4665 |
+
{file = "rpds_py-0.23.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9e799dac1ffbe7b10c1fd42fe4cd51371a549c6e108249bde9cd1200e8f59b4"},
|
| 4666 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721f9c4011b443b6e84505fc00cc7aadc9d1743f1c988e4c89353e19c4a968ee"},
|
| 4667 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f88626e3f5e57432e6191cd0c5d6d6b319b635e70b40be2ffba713053e5147dd"},
|
| 4668 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:285019078537949cecd0190f3690a0b0125ff743d6a53dfeb7a4e6787af154f5"},
|
| 4669 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92f5654157de1379c509b15acec9d12ecf6e3bc1996571b6cb82a4302060447"},
|
| 4670 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e768267cbe051dd8d1c5305ba690bb153204a09bf2e3de3ae530de955f5b5580"},
|
| 4671 |
+
{file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5334a71f7dc1160382d45997e29f2637c02f8a26af41073189d79b95d3321f1"},
|
| 4672 |
+
{file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6adb81564af0cd428910f83fa7da46ce9ad47c56c0b22b50872bc4515d91966"},
|
| 4673 |
+
{file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cafa48f2133d4daa028473ede7d81cd1b9f9e6925e9e4003ebdf77010ee02f35"},
|
| 4674 |
+
{file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fced9fd4a07a1ded1bac7e961ddd9753dd5d8b755ba8e05acba54a21f5f1522"},
|
| 4675 |
+
{file = "rpds_py-0.23.1-cp311-cp311-win32.whl", hash = "sha256:243241c95174b5fb7204c04595852fe3943cc41f47aa14c3828bc18cd9d3b2d6"},
|
| 4676 |
+
{file = "rpds_py-0.23.1-cp311-cp311-win_amd64.whl", hash = "sha256:11dd60b2ffddba85715d8a66bb39b95ddbe389ad2cfcf42c833f1bcde0878eaf"},
|
| 4677 |
+
{file = "rpds_py-0.23.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c"},
|
| 4678 |
+
{file = "rpds_py-0.23.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba"},
|
| 4679 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31"},
|
| 4680 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149"},
|
| 4681 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c"},
|
| 4682 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5"},
|
| 4683 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc"},
|
| 4684 |
+
{file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35"},
|
| 4685 |
+
{file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b"},
|
| 4686 |
+
{file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef"},
|
| 4687 |
+
{file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad"},
|
| 4688 |
+
{file = "rpds_py-0.23.1-cp312-cp312-win32.whl", hash = "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057"},
|
| 4689 |
+
{file = "rpds_py-0.23.1-cp312-cp312-win_amd64.whl", hash = "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165"},
|
| 4690 |
+
{file = "rpds_py-0.23.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935"},
|
| 4691 |
+
{file = "rpds_py-0.23.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4"},
|
| 4692 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6"},
|
| 4693 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10"},
|
| 4694 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122"},
|
| 4695 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4"},
|
| 4696 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013"},
|
| 4697 |
+
{file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64"},
|
| 4698 |
+
{file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8"},
|
| 4699 |
+
{file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957"},
|
| 4700 |
+
{file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93"},
|
| 4701 |
+
{file = "rpds_py-0.23.1-cp313-cp313-win32.whl", hash = "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd"},
|
| 4702 |
+
{file = "rpds_py-0.23.1-cp313-cp313-win_amd64.whl", hash = "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70"},
|
| 4703 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731"},
|
| 4704 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5"},
|
| 4705 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a"},
|
| 4706 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e"},
|
| 4707 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f"},
|
| 4708 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219"},
|
| 4709 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722"},
|
| 4710 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e"},
|
| 4711 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6"},
|
| 4712 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b"},
|
| 4713 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5"},
|
| 4714 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-win32.whl", hash = "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7"},
|
| 4715 |
+
{file = "rpds_py-0.23.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d"},
|
| 4716 |
+
{file = "rpds_py-0.23.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:09cd7dbcb673eb60518231e02874df66ec1296c01a4fcd733875755c02014b19"},
|
| 4717 |
+
{file = "rpds_py-0.23.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6760211eee3a76316cf328f5a8bd695b47b1626d21c8a27fb3b2473a884d597"},
|
| 4718 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72e680c1518733b73c994361e4b06441b92e973ef7d9449feec72e8ee4f713da"},
|
| 4719 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae28144c1daa61366205d32abd8c90372790ff79fc60c1a8ad7fd3c8553a600e"},
|
| 4720 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c698d123ce5d8f2d0cd17f73336615f6a2e3bdcedac07a1291bb4d8e7d82a05a"},
|
| 4721 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98b257ae1e83f81fb947a363a274c4eb66640212516becaff7bef09a5dceacaa"},
|
| 4722 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c9ff044eb07c8468594d12602291c635da292308c8c619244e30698e7fc455a"},
|
| 4723 |
+
{file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7938c7b0599a05246d704b3f5e01be91a93b411d0d6cc62275f025293b8a11ce"},
|
| 4724 |
+
{file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e9cb79ecedfc156c0692257ac7ed415243b6c35dd969baa461a6888fc79f2f07"},
|
| 4725 |
+
{file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7b77e07233925bd33fc0022b8537774423e4c6680b6436316c5075e79b6384f4"},
|
| 4726 |
+
{file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a970bfaf130c29a679b1d0a6e0f867483cea455ab1535fb427566a475078f27f"},
|
| 4727 |
+
{file = "rpds_py-0.23.1-cp39-cp39-win32.whl", hash = "sha256:4233df01a250b3984465faed12ad472f035b7cd5240ea3f7c76b7a7016084495"},
|
| 4728 |
+
{file = "rpds_py-0.23.1-cp39-cp39-win_amd64.whl", hash = "sha256:c617d7453a80e29d9973b926983b1e700a9377dbe021faa36041c78537d7b08c"},
|
| 4729 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c1f8afa346ccd59e4e5630d5abb67aba6a9812fddf764fd7eb11f382a345f8cc"},
|
| 4730 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fad784a31869747df4ac968a351e070c06ca377549e4ace94775aaa3ab33ee06"},
|
| 4731 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a96fcac2f18e5a0a23a75cd27ce2656c66c11c127b0318e508aab436b77428"},
|
| 4732 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e77febf227a1dc3220159355dba68faa13f8dca9335d97504abf428469fb18b"},
|
| 4733 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26bb3e8de93443d55e2e748e9fd87deb5f8075ca7bc0502cfc8be8687d69a2ec"},
|
| 4734 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db7707dde9143a67b8812c7e66aeb2d843fe33cc8e374170f4d2c50bd8f2472d"},
|
| 4735 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eedaaccc9bb66581d4ae7c50e15856e335e57ef2734dbc5fd8ba3e2a4ab3cb6"},
|
| 4736 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28358c54fffadf0ae893f6c1050e8f8853e45df22483b7fff2f6ab6152f5d8bf"},
|
| 4737 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:633462ef7e61d839171bf206551d5ab42b30b71cac8f10a64a662536e057fdef"},
|
| 4738 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a98f510d86f689fcb486dc59e6e363af04151e5260ad1bdddb5625c10f1e95f8"},
|
| 4739 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e0397dd0b3955c61ef9b22838144aa4bef6f0796ba5cc8edfc64d468b93798b4"},
|
| 4740 |
+
{file = "rpds_py-0.23.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:75307599f0d25bf6937248e5ac4e3bde5ea72ae6618623b86146ccc7845ed00b"},
|
| 4741 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3614d280bf7aab0d3721b5ce0e73434acb90a2c993121b6e81a1c15c665298ac"},
|
| 4742 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e5963ea87f88bddf7edd59644a35a0feecf75f8985430124c253612d4f7d27ae"},
|
| 4743 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad76f44f70aac3a54ceb1813ca630c53415da3a24fd93c570b2dfb4856591017"},
|
| 4744 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c6ae11e6e93728d86aafc51ced98b1658a0080a7dd9417d24bfb955bb09c3c2"},
|
| 4745 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc869af5cba24d45fb0399b0cfdbcefcf6910bf4dee5d74036a57cf5264b3ff4"},
|
| 4746 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c76b32eb2ab650a29e423525e84eb197c45504b1c1e6e17b6cc91fcfeb1a4b1d"},
|
| 4747 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4263320ed887ed843f85beba67f8b2d1483b5947f2dc73a8b068924558bfeace"},
|
| 4748 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f9682a8f71acdf59fd554b82b1c12f517118ee72c0f3944eda461606dfe7eb9"},
|
| 4749 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:754fba3084b70162a6b91efceee8a3f06b19e43dac3f71841662053c0584209a"},
|
| 4750 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:a1c66e71ecfd2a4acf0e4bd75e7a3605afa8f9b28a3b497e4ba962719df2be57"},
|
| 4751 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8d67beb6002441faef8251c45e24994de32c4c8686f7356a1f601ad7c466f7c3"},
|
| 4752 |
+
{file = "rpds_py-0.23.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a1e17d8dc8e57d8e0fd21f8f0f0a5211b3fa258b2e444c2053471ef93fe25a00"},
|
| 4753 |
+
{file = "rpds_py-0.23.1.tar.gz", hash = "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707"},
|
| 4754 |
]
|
| 4755 |
|
| 4756 |
[[package]]
|
|
|
|
| 5039 |
|
| 5040 |
[[package]]
|
| 5041 |
name = "streamlit"
|
| 5042 |
+
version = "1.42.2"
|
| 5043 |
description = "A faster way to build and share data apps"
|
| 5044 |
optional = false
|
| 5045 |
python-versions = "!=3.9.7,>=3.9"
|
| 5046 |
files = [
|
| 5047 |
+
{file = "streamlit-1.42.2-py2.py3-none-any.whl", hash = "sha256:e2516c7fcd17a11a85cc1999fae58ace0a6458e2b4c1a411ed3d75b1aee2eb93"},
|
| 5048 |
+
{file = "streamlit-1.42.2.tar.gz", hash = "sha256:62026dbdcb482790933f658b096d7dd58fa70da89c1f06fbc3658b91dcd4dab2"},
|
| 5049 |
]
|
| 5050 |
|
| 5051 |
[package.dependencies]
|
|
|
|
| 6107 |
[metadata]
|
| 6108 |
lock-version = "2.0"
|
| 6109 |
python-versions = "^3.10"
|
| 6110 |
+
content-hash = "307a7d77aa28ba7ae943396fbc36e03cd1b0c4dd354ed9e7cfbf7cd74c49e164"
|
pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
[tool.poetry]
|
| 2 |
name = "marker-pdf"
|
| 3 |
-
version = "1.5.
|
| 4 |
description = "Convert PDF to markdown with high speed and accuracy."
|
| 5 |
authors = ["Vik Paruchuri <github@vikas.sh>"]
|
| 6 |
readme = "README.md"
|
|
@@ -35,6 +35,7 @@ markdown2 = "^2.5.2"
|
|
| 35 |
filetype = "^1.2.0"
|
| 36 |
scikit-learn = "^1.6.1"
|
| 37 |
google-genai = "^1.0.0"
|
|
|
|
| 38 |
mammoth = "^1.9.0"
|
| 39 |
weasyprint = "^63.1"
|
| 40 |
openpyxl = "^3.1.5"
|
|
|
|
| 1 |
[tool.poetry]
|
| 2 |
name = "marker-pdf"
|
| 3 |
+
version = "1.5.6"
|
| 4 |
description = "Convert PDF to markdown with high speed and accuracy."
|
| 5 |
authors = ["Vik Paruchuri <github@vikas.sh>"]
|
| 6 |
readme = "README.md"
|
|
|
|
| 35 |
filetype = "^1.2.0"
|
| 36 |
scikit-learn = "^1.6.1"
|
| 37 |
google-genai = "^1.0.0"
|
| 38 |
+
anthropic = "^0.46.0"
|
| 39 |
mammoth = "^1.9.0"
|
| 40 |
weasyprint = "^63.1"
|
| 41 |
openpyxl = "^3.1.5"
|
tests/builders/test_inline_math_lines.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
from marker.processors.line_merge import LineMergeProcessor
|
| 4 |
+
from marker.schema import BlockTypes
|
| 5 |
+
|
| 6 |
+
@pytest.mark.config({"page_range": [1]})
|
| 7 |
+
def test_inline_box_nomerging(pdf_document, config):
|
| 8 |
+
first_page = pdf_document.pages[0]
|
| 9 |
+
block = pdf_document.get_block(first_page.structure[1]) # First inline math block
|
| 10 |
+
line_count = len(block.contained_blocks(pdf_document, (BlockTypes.Line,)))
|
| 11 |
+
assert line_count == 46
|
| 12 |
+
|
| 13 |
+
merger = LineMergeProcessor(config)
|
| 14 |
+
merger(pdf_document)
|
| 15 |
+
|
| 16 |
+
line_count = len(block.contained_blocks(pdf_document, (BlockTypes.Line,)))
|
| 17 |
+
assert line_count == 45
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@pytest.mark.config({"page_range": [1], "use_llm": True})
|
| 21 |
+
def test_inline_box_merging(pdf_document, config):
|
| 22 |
+
first_page = pdf_document.pages[0]
|
| 23 |
+
block = pdf_document.get_block(first_page.structure[1]) # First inline math block
|
| 24 |
+
line_count = len(block.contained_blocks(pdf_document, (BlockTypes.Line,)))
|
| 25 |
+
assert line_count == 21
|
| 26 |
+
|
| 27 |
+
merger = LineMergeProcessor(config)
|
| 28 |
+
merger(pdf_document)
|
| 29 |
+
|
| 30 |
+
line_count = len(block.contained_blocks(pdf_document, (BlockTypes.Line,)))
|
| 31 |
+
assert line_count == 21
|