kiarina-llm 1.1.1__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/CHANGELOG.md +17 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/PKG-INFO +2 -3
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/pyproject.toml +2 -3
- kiarina_llm-1.3.0/src/kiarina/llm/content/__init__.py +37 -0
- kiarina_llm-1.3.0/src/kiarina/llm/content/_models/content_limits.py +69 -0
- kiarina_llm-1.3.0/src/kiarina/llm/content/_models/content_metrics.py +115 -0
- kiarina_llm-1.3.0/src/kiarina/llm/content/_models/content_scale.py +113 -0
- kiarina_llm-1.3.0/src/kiarina/llm/content/_operations/calculate_overflow.py +62 -0
- kiarina_llm-1.3.0/src/kiarina/llm/run_context/__init__.py +30 -0
- kiarina_llm-1.3.0/tests/conftest.py +0 -0
- kiarina_llm-1.3.0/tests/content/__init__.py +0 -0
- kiarina_llm-1.3.0/tests/content/conftest.py +0 -0
- kiarina_llm-1.3.0/tests/content/test_calculate_overflow.py +297 -0
- kiarina_llm-1.3.0/tests/content/test_content_limits.py +31 -0
- kiarina_llm-1.3.0/tests/content/test_content_metrics.py +147 -0
- kiarina_llm-1.3.0/tests/content/test_content_scale.py +342 -0
- kiarina_llm-1.3.0/tests/content/test_init.py +11 -0
- kiarina_llm-1.3.0/tests/run_context/__init__.py +0 -0
- kiarina_llm-1.3.0/tests/run_context/test_init.py +11 -0
- kiarina_llm-1.1.1/src/kiarina/llm/run_context/__init__.py +0 -9
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/.gitignore +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/README.md +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/__init__.py +0 -0
- {kiarina_llm-1.1.1/src/kiarina/llm/run_context/_types → kiarina_llm-1.3.0/src/kiarina/llm/content/_models}/__init__.py +0 -0
- {kiarina_llm-1.1.1/tests/run_context → kiarina_llm-1.3.0/src/kiarina/llm/content/_operations}/__init__.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/py.typed +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/run_context/_model.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/run_context/_registry.py +0 -0
- /kiarina_llm-1.1.1/tests/conftest.py → /kiarina_llm-1.3.0/src/kiarina/llm/run_context/_types/__init__.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/run_context/_types/fs_name.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/run_context/_types/id_str.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/src/kiarina/llm/run_context/settings.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/tests/run_context/conftest.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/tests/run_context/test_create_run_context.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/tests/run_context/test_fs_name.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/tests/run_context/test_id_str.py +0 -0
- {kiarina_llm-1.1.1 → kiarina_llm-1.3.0}/tests/run_context/test_run_context.py +0 -0
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [1.3.0] - 2025-10-05
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
- No changes
|
14
|
+
|
15
|
+
## [1.2.0] - 2025-09-25
|
16
|
+
|
17
|
+
### Added
|
18
|
+
- **Content measurement utilities**: Comprehensive utilities for measuring and managing LLM-handled content
|
19
|
+
- `ContentMetrics`: Tracks token count, file sizes, file counts by type, and media durations
|
20
|
+
- `ContentLimits`: Defines limits for different content types with feature flags
|
21
|
+
- `ContentScale`: Enum for content scale categories (SMALL, MEDIUM, LARGE, EXTRA_LARGE)
|
22
|
+
- `calculate_overflow`: Calculates overflow amounts when content exceeds defined limits
|
23
|
+
- **Type safety**: Full type hints and Pydantic validation for all content models
|
24
|
+
- **Feature flags**: Enable/disable specific input types (image, audio, video)
|
25
|
+
- **Lazy loading**: Efficient module loading using `__getattr__`
|
26
|
+
|
10
27
|
## [1.1.1] - 2025-09-11
|
11
28
|
|
12
29
|
### Changed
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kiarina-llm
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.0
|
4
4
|
Summary: LLM utilities and context management for kiarina namespace
|
5
5
|
Project-URL: Homepage, https://github.com/kiarina/kiarina-python
|
6
6
|
Project-URL: Repository, https://github.com/kiarina/kiarina-python
|
@@ -9,11 +9,10 @@ Project-URL: Changelog, https://github.com/kiarina/kiarina-python/blob/main/pack
|
|
9
9
|
Project-URL: Documentation, https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-llm#readme
|
10
10
|
Author-email: kiarina <kiarinadawa@gmail.com>
|
11
11
|
Maintainer-email: kiarina <kiarinadawa@gmail.com>
|
12
|
-
License: MIT
|
12
|
+
License-Expression: MIT
|
13
13
|
Keywords: agent,ai,context,llm,pydantic,runner,settings
|
14
14
|
Classifier: Development Status :: 4 - Beta
|
15
15
|
Classifier: Intended Audience :: Developers
|
16
|
-
Classifier: License :: OSI Approved :: MIT License
|
17
16
|
Classifier: Operating System :: OS Independent
|
18
17
|
Classifier: Programming Language :: Python :: 3
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
@@ -1,9 +1,9 @@
|
|
1
1
|
[project]
|
2
2
|
name = "kiarina-llm"
|
3
|
-
version = "1.
|
3
|
+
version = "1.3.0"
|
4
4
|
description = "LLM utilities and context management for kiarina namespace"
|
5
5
|
readme = "README.md"
|
6
|
-
license =
|
6
|
+
license = "MIT"
|
7
7
|
authors = [
|
8
8
|
{ name = "kiarina", email = "kiarinadawa@gmail.com" }
|
9
9
|
]
|
@@ -14,7 +14,6 @@ keywords = ["llm", "ai", "context", "pydantic", "settings", "agent", "runner"]
|
|
14
14
|
classifiers = [
|
15
15
|
"Development Status :: 4 - Beta",
|
16
16
|
"Intended Audience :: Developers",
|
17
|
-
"License :: OSI Approved :: MIT License",
|
18
17
|
"Operating System :: OS Independent",
|
19
18
|
"Programming Language :: Python :: 3",
|
20
19
|
"Programming Language :: Python :: 3.12",
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import logging
|
2
|
+
from importlib import import_module
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from ._models.content_limits import ContentLimits
|
7
|
+
from ._models.content_metrics import ContentMetrics
|
8
|
+
from ._models.content_scale import ContentScale
|
9
|
+
from ._operations.calculate_overflow import calculate_overflow
|
10
|
+
|
11
|
+
__all__ = [
|
12
|
+
# .models
|
13
|
+
"ContentLimits",
|
14
|
+
"ContentMetrics",
|
15
|
+
"ContentScale",
|
16
|
+
# .operations
|
17
|
+
"calculate_overflow",
|
18
|
+
]
|
19
|
+
|
20
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
21
|
+
|
22
|
+
|
23
|
+
def __getattr__(name: str) -> object:
|
24
|
+
if name not in __all__:
|
25
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
26
|
+
|
27
|
+
module_map = {
|
28
|
+
# .models
|
29
|
+
"ContentLimits": "._models.content_limits",
|
30
|
+
"ContentMetrics": "._models.content_metrics",
|
31
|
+
"ContentScale": "._models.content_scale",
|
32
|
+
# .operations
|
33
|
+
"calculate_overflow": "._operations.calculate_overflow",
|
34
|
+
}
|
35
|
+
|
36
|
+
globals()[name] = getattr(import_module(module_map[name], __name__), name)
|
37
|
+
return globals()[name]
|
@@ -0,0 +1,69 @@
|
|
1
|
+
from pydantic import BaseModel
|
2
|
+
|
3
|
+
|
4
|
+
class ContentLimits(BaseModel):
|
5
|
+
"""
|
6
|
+
Content Limits
|
7
|
+
"""
|
8
|
+
|
9
|
+
token_input_limit: int = -1
|
10
|
+
"""Maximum token count input limit (-1 indicates unlimited)"""
|
11
|
+
|
12
|
+
file_size_limit: int = -1
|
13
|
+
"""Maximum total file size limit (in bytes; -1 indicates unlimited)"""
|
14
|
+
|
15
|
+
# --------------------------------------------------
|
16
|
+
# Text Files
|
17
|
+
# --------------------------------------------------
|
18
|
+
|
19
|
+
text_file_limit: int = -1
|
20
|
+
"""Maximum number of text files (-1 indicates unlimited)"""
|
21
|
+
|
22
|
+
# --------------------------------------------------
|
23
|
+
# Image Files
|
24
|
+
# --------------------------------------------------
|
25
|
+
|
26
|
+
image_input_enabled: bool = True
|
27
|
+
"""Whether image input is enabled"""
|
28
|
+
|
29
|
+
image_file_limit: int = -1
|
30
|
+
"""Maximum number of image files (-1 indicates unlimited)"""
|
31
|
+
|
32
|
+
# --------------------------------------------------
|
33
|
+
# Audio Files
|
34
|
+
# --------------------------------------------------
|
35
|
+
|
36
|
+
audio_input_enabled: bool = True
|
37
|
+
"""Whether audio input is enabled"""
|
38
|
+
|
39
|
+
audio_duration_limit: float = 60 * 60 * 9.5
|
40
|
+
"""Maximum audio duration limit (in seconds; Gemini's limit is 9.5h)"""
|
41
|
+
|
42
|
+
audio_file_limit: int = -1
|
43
|
+
"""Maximum number of audio files (-1 indicates unlimited)"""
|
44
|
+
|
45
|
+
# --------------------------------------------------
|
46
|
+
# Video Files
|
47
|
+
# --------------------------------------------------
|
48
|
+
|
49
|
+
video_input_enabled: bool = True
|
50
|
+
"""Whether video input is enabled"""
|
51
|
+
|
52
|
+
video_duration_limit: float = 60 * 60 * 1.0
|
53
|
+
"""Maximum video duration limit (in seconds; Gemini's limit is 1h)"""
|
54
|
+
|
55
|
+
video_file_limit: int = -1
|
56
|
+
"""Maximum number of video files (-1 indicates unlimited)"""
|
57
|
+
|
58
|
+
# --------------------------------------------------
|
59
|
+
# PDF Files
|
60
|
+
# --------------------------------------------------
|
61
|
+
|
62
|
+
pdf_input_enabled: bool = True
|
63
|
+
"""Whether PDF input is enabled"""
|
64
|
+
|
65
|
+
pdf_page_limit: int = 100
|
66
|
+
"""Maximum number of PDF pages (default is 100)"""
|
67
|
+
|
68
|
+
pdf_file_limit: int = -1
|
69
|
+
"""Maximum number of PDF files (-1 indicates unlimited)"""
|
@@ -0,0 +1,115 @@
|
|
1
|
+
from typing import Self
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
|
6
|
+
class ContentMetrics(BaseModel):
|
7
|
+
"""
|
8
|
+
Content Metrics
|
9
|
+
"""
|
10
|
+
|
11
|
+
# --------------------------------------------------
|
12
|
+
# Properties
|
13
|
+
# --------------------------------------------------
|
14
|
+
|
15
|
+
token_count: int = 0
|
16
|
+
"""Token count"""
|
17
|
+
|
18
|
+
file_size: int = 0
|
19
|
+
"""Total file size (bytes)"""
|
20
|
+
|
21
|
+
text_file_count: int = 0
|
22
|
+
"""Number of text files"""
|
23
|
+
|
24
|
+
image_file_count: int = 0
|
25
|
+
"""Number of image files"""
|
26
|
+
|
27
|
+
audio_duration: float = 0.0
|
28
|
+
"""Audio duration (seconds)"""
|
29
|
+
|
30
|
+
audio_file_count: int = 0
|
31
|
+
"""Number of audio files"""
|
32
|
+
|
33
|
+
video_duration: float = 0.0
|
34
|
+
"""Video duration (seconds)"""
|
35
|
+
|
36
|
+
video_file_count: int = 0
|
37
|
+
"""Number of video files"""
|
38
|
+
|
39
|
+
pdf_page_count: int = 0
|
40
|
+
"""Number of PDF pages"""
|
41
|
+
|
42
|
+
pdf_file_count: int = 0
|
43
|
+
"""Number of PDF files"""
|
44
|
+
|
45
|
+
# --------------------------------------------------
|
46
|
+
# Properties for Meta Information
|
47
|
+
# --------------------------------------------------
|
48
|
+
|
49
|
+
text_token_count: int = 0
|
50
|
+
"""Text token count"""
|
51
|
+
|
52
|
+
image_token_count: int = 0
|
53
|
+
"""Image token count"""
|
54
|
+
|
55
|
+
audio_token_count: int = 0
|
56
|
+
"""Audio token count"""
|
57
|
+
|
58
|
+
video_token_count: int = 0
|
59
|
+
"""Video token count"""
|
60
|
+
|
61
|
+
pdf_token_count: int = 0
|
62
|
+
"""PDF token count"""
|
63
|
+
|
64
|
+
# --------------------------------------------------
|
65
|
+
# Methods
|
66
|
+
# --------------------------------------------------
|
67
|
+
|
68
|
+
def add_text_token_count(self, count: int) -> None:
|
69
|
+
self.text_token_count += count
|
70
|
+
self.token_count += count
|
71
|
+
|
72
|
+
def add_image_token_count(self, count: int) -> None:
|
73
|
+
self.image_token_count += count
|
74
|
+
self.token_count += count
|
75
|
+
|
76
|
+
def add_audio_token_count(self, count: int) -> None:
|
77
|
+
self.audio_token_count += count
|
78
|
+
self.token_count += count
|
79
|
+
|
80
|
+
def add_video_token_count(self, count: int) -> None:
|
81
|
+
self.video_token_count += count
|
82
|
+
self.token_count += count
|
83
|
+
|
84
|
+
def add_pdf_token_count(self, count: int) -> None:
|
85
|
+
self.pdf_token_count += count
|
86
|
+
self.token_count += count
|
87
|
+
|
88
|
+
# --------------------------------------------------
|
89
|
+
# Operators
|
90
|
+
# --------------------------------------------------
|
91
|
+
|
92
|
+
def __add__(self, other: Self) -> Self:
|
93
|
+
"""
|
94
|
+
Add metrics
|
95
|
+
"""
|
96
|
+
result = self.model_copy()
|
97
|
+
|
98
|
+
result.token_count += other.token_count
|
99
|
+
result.file_size += other.file_size
|
100
|
+
result.text_file_count += other.text_file_count
|
101
|
+
result.image_file_count += other.image_file_count
|
102
|
+
result.audio_duration += other.audio_duration
|
103
|
+
result.audio_file_count += other.audio_file_count
|
104
|
+
result.video_duration += other.video_duration
|
105
|
+
result.video_file_count += other.video_file_count
|
106
|
+
result.pdf_page_count += other.pdf_page_count
|
107
|
+
result.pdf_file_count += other.pdf_file_count
|
108
|
+
|
109
|
+
result.text_token_count += other.text_token_count
|
110
|
+
result.image_token_count += other.image_token_count
|
111
|
+
result.audio_token_count += other.audio_token_count
|
112
|
+
result.video_token_count += other.video_token_count
|
113
|
+
result.pdf_token_count += other.pdf_token_count
|
114
|
+
|
115
|
+
return result
|
@@ -0,0 +1,113 @@
|
|
1
|
+
from typing import Self
|
2
|
+
|
3
|
+
from pydantic import BaseModel, computed_field
|
4
|
+
|
5
|
+
from .._operations.calculate_overflow import calculate_overflow
|
6
|
+
from .content_limits import ContentLimits
|
7
|
+
from .content_metrics import ContentMetrics
|
8
|
+
|
9
|
+
|
10
|
+
class ContentScale(BaseModel):
|
11
|
+
"""
|
12
|
+
Content Scale
|
13
|
+
"""
|
14
|
+
|
15
|
+
limits: ContentLimits
|
16
|
+
"""Limits"""
|
17
|
+
|
18
|
+
metrics: ContentMetrics
|
19
|
+
"""Metrics (usage)"""
|
20
|
+
|
21
|
+
overflow: ContentMetrics
|
22
|
+
"""Overflow amount (in metrics format)"""
|
23
|
+
|
24
|
+
# --------------------------------------------------
|
25
|
+
# Properties
|
26
|
+
# --------------------------------------------------
|
27
|
+
|
28
|
+
@computed_field # type: ignore
|
29
|
+
@property
|
30
|
+
def token_ratio(self) -> float:
|
31
|
+
"""
|
32
|
+
Token usage ratio
|
33
|
+
"""
|
34
|
+
if self.limits.token_input_limit == 0:
|
35
|
+
return 0.0
|
36
|
+
|
37
|
+
return self.metrics.token_count / self.limits.token_input_limit
|
38
|
+
|
39
|
+
@computed_field # type: ignore
|
40
|
+
@property
|
41
|
+
def has_overflow(self) -> bool:
|
42
|
+
"""
|
43
|
+
Whether overflow has occurred
|
44
|
+
"""
|
45
|
+
return self.is_overflow()
|
46
|
+
|
47
|
+
@computed_field # type: ignore
|
48
|
+
@property
|
49
|
+
def error_message(self) -> str:
|
50
|
+
"""
|
51
|
+
Error message
|
52
|
+
"""
|
53
|
+
return self.get_error_message()
|
54
|
+
|
55
|
+
# --------------------------------------------------
|
56
|
+
# Methods
|
57
|
+
# --------------------------------------------------
|
58
|
+
|
59
|
+
def is_overflow(self) -> bool:
|
60
|
+
"""
|
61
|
+
Whether the message has overflowed
|
62
|
+
"""
|
63
|
+
return (
|
64
|
+
self.overflow.token_count > 0
|
65
|
+
or self.overflow.file_size > 0
|
66
|
+
or self.overflow.text_file_count > 0
|
67
|
+
or self.overflow.image_file_count > 0
|
68
|
+
or self.overflow.audio_duration > 0
|
69
|
+
or self.overflow.audio_file_count > 0
|
70
|
+
or self.overflow.video_duration > 0
|
71
|
+
or self.overflow.video_file_count > 0
|
72
|
+
or self.overflow.pdf_page_count > 0
|
73
|
+
or self.overflow.pdf_file_count > 0
|
74
|
+
)
|
75
|
+
|
76
|
+
def get_error_message(self) -> str:
|
77
|
+
"""
|
78
|
+
Get error message
|
79
|
+
"""
|
80
|
+
if self.overflow.file_size > 0:
|
81
|
+
return f"Total file size exceeds limit: {self.metrics.file_size} / {self.limits.file_size_limit} bytes"
|
82
|
+
elif self.overflow.pdf_file_count > 0:
|
83
|
+
return f"Number of PDF files exceeds limit: {self.metrics.pdf_file_count} / {self.limits.pdf_file_limit}"
|
84
|
+
elif self.overflow.pdf_page_count > 0:
|
85
|
+
return f"PDF page count exceeds limit: {self.metrics.pdf_page_count} / {self.limits.pdf_page_limit}"
|
86
|
+
elif self.overflow.video_file_count > 0:
|
87
|
+
return f"Number of video files exceeds limit: {self.metrics.video_file_count} / {self.limits.video_file_limit}"
|
88
|
+
elif self.overflow.video_duration > 0:
|
89
|
+
return f"Video duration exceeds limit: {self.metrics.video_duration}s / {self.limits.video_duration_limit}s"
|
90
|
+
elif self.overflow.audio_file_count > 0:
|
91
|
+
return f"Number of audio files exceeds limit: {self.metrics.audio_file_count} / {self.limits.audio_file_limit}"
|
92
|
+
elif self.overflow.audio_duration > 0:
|
93
|
+
return f"Audio duration exceeds limit: {self.metrics.audio_duration}s / {self.limits.audio_duration_limit}s"
|
94
|
+
elif self.overflow.image_file_count > 0:
|
95
|
+
return f"Number of image files exceeds limit: {self.metrics.image_file_count} / {self.limits.image_file_limit}"
|
96
|
+
elif self.overflow.text_file_count > 0:
|
97
|
+
return f"Number of text files exceeds limit: {self.metrics.text_file_count} / {self.limits.text_file_limit}"
|
98
|
+
elif self.overflow.token_count > 0:
|
99
|
+
return f"Token count exceeds limit: {self.metrics.token_count} / {self.limits.token_input_limit}"
|
100
|
+
else:
|
101
|
+
return "Message is valid"
|
102
|
+
|
103
|
+
# --------------------------------------------------
|
104
|
+
# Class Methods
|
105
|
+
# --------------------------------------------------
|
106
|
+
|
107
|
+
@classmethod
|
108
|
+
def create(cls, *, limits: ContentLimits, metrics: ContentMetrics) -> Self:
|
109
|
+
"""
|
110
|
+
Create scale information from metrics and limits
|
111
|
+
"""
|
112
|
+
overflow = calculate_overflow(limits=limits, metrics=metrics)
|
113
|
+
return cls(limits=limits, metrics=metrics, overflow=overflow)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
from .._models.content_limits import ContentLimits
|
2
|
+
from .._models.content_metrics import ContentMetrics
|
3
|
+
|
4
|
+
|
5
|
+
def calculate_overflow(
|
6
|
+
*, limits: ContentLimits, metrics: ContentMetrics
|
7
|
+
) -> ContentMetrics:
|
8
|
+
"""
|
9
|
+
Calculate overflow amount from metrics and limits
|
10
|
+
"""
|
11
|
+
return ContentMetrics(
|
12
|
+
token_count=(
|
13
|
+
max(0, metrics.token_count - limits.token_input_limit)
|
14
|
+
if limits.token_input_limit != -1
|
15
|
+
else 0
|
16
|
+
),
|
17
|
+
file_size=(
|
18
|
+
max(0, metrics.file_size - limits.file_size_limit)
|
19
|
+
if limits.file_size_limit != -1
|
20
|
+
else 0
|
21
|
+
),
|
22
|
+
text_file_count=(
|
23
|
+
max(0, metrics.text_file_count - limits.text_file_limit)
|
24
|
+
if limits.text_file_limit != -1
|
25
|
+
else 0
|
26
|
+
),
|
27
|
+
image_file_count=(
|
28
|
+
max(0, metrics.image_file_count - limits.image_file_limit)
|
29
|
+
if (limits.image_input_enabled and limits.image_file_limit != -1)
|
30
|
+
else 0
|
31
|
+
),
|
32
|
+
audio_duration=(
|
33
|
+
max(0.0, metrics.audio_duration - limits.audio_duration_limit)
|
34
|
+
if limits.audio_input_enabled
|
35
|
+
else 0.0
|
36
|
+
),
|
37
|
+
audio_file_count=(
|
38
|
+
max(0, metrics.audio_file_count - limits.audio_file_limit)
|
39
|
+
if (limits.audio_input_enabled and limits.audio_file_limit != -1)
|
40
|
+
else 0
|
41
|
+
),
|
42
|
+
video_duration=(
|
43
|
+
max(0.0, metrics.video_duration - limits.video_duration_limit)
|
44
|
+
if limits.video_input_enabled
|
45
|
+
else 0.0
|
46
|
+
),
|
47
|
+
video_file_count=(
|
48
|
+
max(0, metrics.video_file_count - limits.video_file_limit)
|
49
|
+
if (limits.video_input_enabled and limits.video_file_limit != -1)
|
50
|
+
else 0
|
51
|
+
),
|
52
|
+
pdf_page_count=(
|
53
|
+
max(0, metrics.pdf_page_count - limits.pdf_page_limit)
|
54
|
+
if limits.pdf_input_enabled
|
55
|
+
else 0
|
56
|
+
),
|
57
|
+
pdf_file_count=(
|
58
|
+
max(0, metrics.pdf_file_count - limits.pdf_file_limit)
|
59
|
+
if (limits.pdf_input_enabled and limits.pdf_file_limit != -1)
|
60
|
+
else 0
|
61
|
+
),
|
62
|
+
)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import logging
|
2
|
+
from importlib import import_module
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from ._model import RunContext
|
7
|
+
from ._registry import create_run_context
|
8
|
+
from .settings import settings_manager
|
9
|
+
|
10
|
+
__all__ = [
|
11
|
+
"create_run_context",
|
12
|
+
"RunContext",
|
13
|
+
"settings_manager",
|
14
|
+
]
|
15
|
+
|
16
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
17
|
+
|
18
|
+
|
19
|
+
def __getattr__(name: str) -> object:
|
20
|
+
if name not in __all__:
|
21
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
22
|
+
|
23
|
+
module_map = {
|
24
|
+
"create_run_context": "._registry",
|
25
|
+
"RunContext": "._model",
|
26
|
+
"settings_manager": ".settings",
|
27
|
+
}
|
28
|
+
|
29
|
+
globals()[name] = getattr(import_module(module_map[name], __name__), name)
|
30
|
+
return globals()[name]
|
File without changes
|
File without changes
|
File without changes
|