BryanW commited on
Commit
282a5a0
·
verified ·
1 Parent(s): b1f1791

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/parser_block.py +111 -0
  2. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/parser_core.py +45 -0
  3. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/renderer.py +336 -0
  4. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/tree.py +345 -0
  5. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/INSTALLER +1 -0
  6. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/License.txt +1568 -0
  7. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/METADATA +48 -0
  8. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/RECORD +22 -0
  9. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/WHEEL +5 -0
  10. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/top_level.txt +1 -0
  11. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/__init__.py +244 -0
  12. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/auto.py +184 -0
  13. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/config.py +408 -0
  14. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/functional.py +34 -0
  15. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/helpers.py +251 -0
  16. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/import_utils.py +172 -0
  17. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mapping.py +92 -0
  18. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mapping_func.py +128 -0
  19. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mixed_model.py +460 -0
  20. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/peft_model.py +0 -0
  21. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/py.typed +0 -0
  22. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_csv.pxd +55 -0
  23. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_cuda.pxd +67 -0
  24. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_dataset.pxd +183 -0
  25. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_dataset_parquet.pxd +43 -0
  26. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_feather.pyx +117 -0
  27. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_fs.pyx +1628 -0
  28. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_orc.pxd +134 -0
  29. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_s3fs.pyx +479 -0
  30. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/benchmark.py +21 -0
  31. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/conftest.py +386 -0
  32. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/json.py +19 -0
  33. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/libarrow_python_parquet_encryption.so.1900.1.0 +0 -0
  34. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/orc.py +384 -0
  35. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/pandas_compat.py +1277 -0
  36. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/configuration_utils.py +1380 -0
  37. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_graph_to_onnx.py +551 -0
  38. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_slow_tokenizer.py +1873 -0
  39. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_slow_tokenizers_checkpoints_to_fast.py +129 -0
  40. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dependency_versions_check.py +63 -0
  41. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/hf_argparser.py +430 -0
  42. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_utils_fast.py +833 -0
  43. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_transforms.py +977 -0
  44. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/masking_utils.py +1256 -0
  45. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_pytorch_utils.py +491 -0
  46. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_layers.py +289 -0
  47. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_utils.py +0 -0
  48. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/tokenization_mistral_common.py +1883 -0
  49. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/trainer_pt_utils.py +1406 -0
  50. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/trainer_seq2seq.py +386 -0
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/parser_block.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Block-level tokenizer."""
2
+ from __future__ import annotations
3
+
4
+ import logging
5
+ from typing import TYPE_CHECKING, Callable
6
+
7
+ from . import rules_block
8
+ from .ruler import Ruler
9
+ from .rules_block.state_block import StateBlock
10
+ from .token import Token
11
+ from .utils import EnvType
12
+
13
+ if TYPE_CHECKING:
14
+ from markdown_it import MarkdownIt
15
+
16
+ LOGGER = logging.getLogger(__name__)
17
+
18
+
19
+ RuleFuncBlockType = Callable[[StateBlock, int, int, bool], bool]
20
+ """(state: StateBlock, startLine: int, endLine: int, silent: bool) -> matched: bool)
21
+
22
+ `silent` disables token generation, useful for lookahead.
23
+ """
24
+
25
+ _rules: list[tuple[str, RuleFuncBlockType, list[str]]] = [
26
+ # First 2 params - rule name & source. Secondary array - list of rules,
27
+ # which can be terminated by this one.
28
+ ("table", rules_block.table, ["paragraph", "reference"]),
29
+ ("code", rules_block.code, []),
30
+ ("fence", rules_block.fence, ["paragraph", "reference", "blockquote", "list"]),
31
+ (
32
+ "blockquote",
33
+ rules_block.blockquote,
34
+ ["paragraph", "reference", "blockquote", "list"],
35
+ ),
36
+ ("hr", rules_block.hr, ["paragraph", "reference", "blockquote", "list"]),
37
+ ("list", rules_block.list_block, ["paragraph", "reference", "blockquote"]),
38
+ ("reference", rules_block.reference, []),
39
+ ("html_block", rules_block.html_block, ["paragraph", "reference", "blockquote"]),
40
+ ("heading", rules_block.heading, ["paragraph", "reference", "blockquote"]),
41
+ ("lheading", rules_block.lheading, []),
42
+ ("paragraph", rules_block.paragraph, []),
43
+ ]
44
+
45
+
46
+ class ParserBlock:
47
+ """
48
+ ParserBlock#ruler -> Ruler
49
+
50
+ [[Ruler]] instance. Keep configuration of block rules.
51
+ """
52
+
53
+ def __init__(self) -> None:
54
+ self.ruler = Ruler[RuleFuncBlockType]()
55
+ for name, rule, alt in _rules:
56
+ self.ruler.push(name, rule, {"alt": alt})
57
+
58
+ def tokenize(self, state: StateBlock, startLine: int, endLine: int) -> None:
59
+ """Generate tokens for input range."""
60
+ rules = self.ruler.getRules("")
61
+ line = startLine
62
+ maxNesting = state.md.options.maxNesting
63
+ hasEmptyLines = False
64
+
65
+ while line < endLine:
66
+ state.line = line = state.skipEmptyLines(line)
67
+ if line >= endLine:
68
+ break
69
+ if state.sCount[line] < state.blkIndent:
70
+ # Termination condition for nested calls.
71
+ # Nested calls currently used for blockquotes & lists
72
+ break
73
+ if state.level >= maxNesting:
74
+ # If nesting level exceeded - skip tail to the end.
75
+ # That's not ordinary situation and we should not care about content.
76
+ state.line = endLine
77
+ break
78
+
79
+ # Try all possible rules.
80
+ # On success, rule should:
81
+ # - update `state.line`
82
+ # - update `state.tokens`
83
+ # - return True
84
+ for rule in rules:
85
+ if rule(state, line, endLine, False):
86
+ break
87
+
88
+ # set state.tight if we had an empty line before current tag
89
+ # i.e. latest empty line should not count
90
+ state.tight = not hasEmptyLines
91
+
92
+ line = state.line
93
+
94
+ # paragraph might "eat" one newline after it in nested lists
95
+ if (line - 1) < endLine and state.isEmpty(line - 1):
96
+ hasEmptyLines = True
97
+
98
+ if line < endLine and state.isEmpty(line):
99
+ hasEmptyLines = True
100
+ line += 1
101
+ state.line = line
102
+
103
+ def parse(
104
+ self, src: str, md: MarkdownIt, env: EnvType, outTokens: list[Token]
105
+ ) -> list[Token] | None:
106
+ """Process input string and push block tokens into `outTokens`."""
107
+ if not src:
108
+ return None
109
+ state = StateBlock(src, md, env, outTokens)
110
+ self.tokenize(state, state.line, state.lineMax)
111
+ return state.tokens
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/parser_core.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ * class Core
3
+ *
4
+ * Top-level rules executor. Glues block/inline parsers and does intermediate
5
+ * transformations.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import Callable
10
+
11
+ from .ruler import Ruler
12
+ from .rules_core import (
13
+ block,
14
+ inline,
15
+ linkify,
16
+ normalize,
17
+ replace,
18
+ smartquotes,
19
+ text_join,
20
+ )
21
+ from .rules_core.state_core import StateCore
22
+
23
+ RuleFuncCoreType = Callable[[StateCore], None]
24
+
25
+ _rules: list[tuple[str, RuleFuncCoreType]] = [
26
+ ("normalize", normalize),
27
+ ("block", block),
28
+ ("inline", inline),
29
+ ("linkify", linkify),
30
+ ("replacements", replace),
31
+ ("smartquotes", smartquotes),
32
+ ("text_join", text_join),
33
+ ]
34
+
35
+
36
+ class ParserCore:
37
+ def __init__(self) -> None:
38
+ self.ruler = Ruler[RuleFuncCoreType]()
39
+ for name, rule in _rules:
40
+ self.ruler.push(name, rule)
41
+
42
+ def process(self, state: StateCore) -> None:
43
+ """Executes core chain rules."""
44
+ for rule in self.ruler.getRules(""):
45
+ rule(state)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/renderer.py ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ class Renderer
3
+
4
+ Generates HTML from parsed token stream. Each instance has independent
5
+ copy of rules. Those can be rewritten with ease. Also, you can add new
6
+ rules if you create plugin and adds new token types.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Sequence
11
+ import inspect
12
+ from typing import Any, ClassVar, Protocol
13
+
14
+ from .common.utils import escapeHtml, unescapeAll
15
+ from .token import Token
16
+ from .utils import EnvType, OptionsDict
17
+
18
+
19
+ class RendererProtocol(Protocol):
20
+ __output__: ClassVar[str]
21
+
22
+ def render(
23
+ self, tokens: Sequence[Token], options: OptionsDict, env: EnvType
24
+ ) -> Any:
25
+ ...
26
+
27
+
28
+ class RendererHTML(RendererProtocol):
29
+ """Contains render rules for tokens. Can be updated and extended.
30
+
31
+ Example:
32
+
33
+ Each rule is called as independent static function with fixed signature:
34
+
35
+ ::
36
+
37
+ class Renderer:
38
+ def token_type_name(self, tokens, idx, options, env) {
39
+ # ...
40
+ return renderedHTML
41
+
42
+ ::
43
+
44
+ class CustomRenderer(RendererHTML):
45
+ def strong_open(self, tokens, idx, options, env):
46
+ return '<b>'
47
+ def strong_close(self, tokens, idx, options, env):
48
+ return '</b>'
49
+
50
+ md = MarkdownIt(renderer_cls=CustomRenderer)
51
+
52
+ result = md.render(...)
53
+
54
+ See https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js
55
+ for more details and examples.
56
+ """
57
+
58
+ __output__ = "html"
59
+
60
+ def __init__(self, parser: Any = None):
61
+ self.rules = {
62
+ k: v
63
+ for k, v in inspect.getmembers(self, predicate=inspect.ismethod)
64
+ if not (k.startswith("render") or k.startswith("_"))
65
+ }
66
+
67
+ def render(
68
+ self, tokens: Sequence[Token], options: OptionsDict, env: EnvType
69
+ ) -> str:
70
+ """Takes token stream and generates HTML.
71
+
72
+ :param tokens: list on block tokens to render
73
+ :param options: params of parser instance
74
+ :param env: additional data from parsed input
75
+
76
+ """
77
+ result = ""
78
+
79
+ for i, token in enumerate(tokens):
80
+ if token.type == "inline":
81
+ if token.children:
82
+ result += self.renderInline(token.children, options, env)
83
+ elif token.type in self.rules:
84
+ result += self.rules[token.type](tokens, i, options, env)
85
+ else:
86
+ result += self.renderToken(tokens, i, options, env)
87
+
88
+ return result
89
+
90
+ def renderInline(
91
+ self, tokens: Sequence[Token], options: OptionsDict, env: EnvType
92
+ ) -> str:
93
+ """The same as ``render``, but for single token of `inline` type.
94
+
95
+ :param tokens: list on block tokens to render
96
+ :param options: params of parser instance
97
+ :param env: additional data from parsed input (references, for example)
98
+ """
99
+ result = ""
100
+
101
+ for i, token in enumerate(tokens):
102
+ if token.type in self.rules:
103
+ result += self.rules[token.type](tokens, i, options, env)
104
+ else:
105
+ result += self.renderToken(tokens, i, options, env)
106
+
107
+ return result
108
+
109
+ def renderToken(
110
+ self,
111
+ tokens: Sequence[Token],
112
+ idx: int,
113
+ options: OptionsDict,
114
+ env: EnvType,
115
+ ) -> str:
116
+ """Default token renderer.
117
+
118
+ Can be overridden by custom function
119
+
120
+ :param idx: token index to render
121
+ :param options: params of parser instance
122
+ """
123
+ result = ""
124
+ needLf = False
125
+ token = tokens[idx]
126
+
127
+ # Tight list paragraphs
128
+ if token.hidden:
129
+ return ""
130
+
131
+ # Insert a newline between hidden paragraph and subsequent opening
132
+ # block-level tag.
133
+ #
134
+ # For example, here we should insert a newline before blockquote:
135
+ # - a
136
+ # >
137
+ #
138
+ if token.block and token.nesting != -1 and idx and tokens[idx - 1].hidden:
139
+ result += "\n"
140
+
141
+ # Add token name, e.g. `<img`
142
+ result += ("</" if token.nesting == -1 else "<") + token.tag
143
+
144
+ # Encode attributes, e.g. `<img src="foo"`
145
+ result += self.renderAttrs(token)
146
+
147
+ # Add a slash for self-closing tags, e.g. `<img src="foo" /`
148
+ if token.nesting == 0 and options["xhtmlOut"]:
149
+ result += " /"
150
+
151
+ # Check if we need to add a newline after this tag
152
+ if token.block:
153
+ needLf = True
154
+
155
+ if token.nesting == 1 and (idx + 1 < len(tokens)):
156
+ nextToken = tokens[idx + 1]
157
+
158
+ if nextToken.type == "inline" or nextToken.hidden: # noqa: SIM114
159
+ # Block-level tag containing an inline tag.
160
+ #
161
+ needLf = False
162
+
163
+ elif nextToken.nesting == -1 and nextToken.tag == token.tag:
164
+ # Opening tag + closing tag of the same type. E.g. `<li></li>`.
165
+ #
166
+ needLf = False
167
+
168
+ result += ">\n" if needLf else ">"
169
+
170
+ return result
171
+
172
+ @staticmethod
173
+ def renderAttrs(token: Token) -> str:
174
+ """Render token attributes to string."""
175
+ result = ""
176
+
177
+ for key, value in token.attrItems():
178
+ result += " " + escapeHtml(key) + '="' + escapeHtml(str(value)) + '"'
179
+
180
+ return result
181
+
182
+ def renderInlineAsText(
183
+ self,
184
+ tokens: Sequence[Token] | None,
185
+ options: OptionsDict,
186
+ env: EnvType,
187
+ ) -> str:
188
+ """Special kludge for image `alt` attributes to conform CommonMark spec.
189
+
190
+ Don't try to use it! Spec requires to show `alt` content with stripped markup,
191
+ instead of simple escaping.
192
+
193
+ :param tokens: list on block tokens to render
194
+ :param options: params of parser instance
195
+ :param env: additional data from parsed input
196
+ """
197
+ result = ""
198
+
199
+ for token in tokens or []:
200
+ if token.type == "text":
201
+ result += token.content
202
+ elif token.type == "image":
203
+ if token.children:
204
+ result += self.renderInlineAsText(token.children, options, env)
205
+ elif token.type == "softbreak":
206
+ result += "\n"
207
+
208
+ return result
209
+
210
+ ###################################################
211
+
212
+ def code_inline(
213
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
214
+ ) -> str:
215
+ token = tokens[idx]
216
+ return (
217
+ "<code"
218
+ + self.renderAttrs(token)
219
+ + ">"
220
+ + escapeHtml(tokens[idx].content)
221
+ + "</code>"
222
+ )
223
+
224
+ def code_block(
225
+ self,
226
+ tokens: Sequence[Token],
227
+ idx: int,
228
+ options: OptionsDict,
229
+ env: EnvType,
230
+ ) -> str:
231
+ token = tokens[idx]
232
+
233
+ return (
234
+ "<pre"
235
+ + self.renderAttrs(token)
236
+ + "><code>"
237
+ + escapeHtml(tokens[idx].content)
238
+ + "</code></pre>\n"
239
+ )
240
+
241
+ def fence(
242
+ self,
243
+ tokens: Sequence[Token],
244
+ idx: int,
245
+ options: OptionsDict,
246
+ env: EnvType,
247
+ ) -> str:
248
+ token = tokens[idx]
249
+ info = unescapeAll(token.info).strip() if token.info else ""
250
+ langName = ""
251
+ langAttrs = ""
252
+
253
+ if info:
254
+ arr = info.split(maxsplit=1)
255
+ langName = arr[0]
256
+ if len(arr) == 2:
257
+ langAttrs = arr[1]
258
+
259
+ if options.highlight:
260
+ highlighted = options.highlight(
261
+ token.content, langName, langAttrs
262
+ ) or escapeHtml(token.content)
263
+ else:
264
+ highlighted = escapeHtml(token.content)
265
+
266
+ if highlighted.startswith("<pre"):
267
+ return highlighted + "\n"
268
+
269
+ # If language exists, inject class gently, without modifying original token.
270
+ # May be, one day we will add .deepClone() for token and simplify this part, but
271
+ # now we prefer to keep things local.
272
+ if info:
273
+ # Fake token just to render attributes
274
+ tmpToken = Token(type="", tag="", nesting=0, attrs=token.attrs.copy())
275
+ tmpToken.attrJoin("class", options.langPrefix + langName)
276
+
277
+ return (
278
+ "<pre><code"
279
+ + self.renderAttrs(tmpToken)
280
+ + ">"
281
+ + highlighted
282
+ + "</code></pre>\n"
283
+ )
284
+
285
+ return (
286
+ "<pre><code"
287
+ + self.renderAttrs(token)
288
+ + ">"
289
+ + highlighted
290
+ + "</code></pre>\n"
291
+ )
292
+
293
+ def image(
294
+ self,
295
+ tokens: Sequence[Token],
296
+ idx: int,
297
+ options: OptionsDict,
298
+ env: EnvType,
299
+ ) -> str:
300
+ token = tokens[idx]
301
+
302
+ # "alt" attr MUST be set, even if empty. Because it's mandatory and
303
+ # should be placed on proper position for tests.
304
+ if token.children:
305
+ token.attrSet("alt", self.renderInlineAsText(token.children, options, env))
306
+ else:
307
+ token.attrSet("alt", "")
308
+
309
+ return self.renderToken(tokens, idx, options, env)
310
+
311
+ def hardbreak(
312
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
313
+ ) -> str:
314
+ return "<br />\n" if options.xhtmlOut else "<br>\n"
315
+
316
+ def softbreak(
317
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
318
+ ) -> str:
319
+ return (
320
+ ("<br />\n" if options.xhtmlOut else "<br>\n") if options.breaks else "\n"
321
+ )
322
+
323
+ def text(
324
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
325
+ ) -> str:
326
+ return escapeHtml(tokens[idx].content)
327
+
328
+ def html_block(
329
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
330
+ ) -> str:
331
+ return tokens[idx].content
332
+
333
+ def html_inline(
334
+ self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType
335
+ ) -> str:
336
+ return tokens[idx].content
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/markdown_it/tree.py ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A tree representation of a linear markdown-it token stream.
2
+
3
+ This module is not part of upstream JavaScript markdown-it.
4
+ """
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Generator, Sequence
8
+ import textwrap
9
+ from typing import Any, NamedTuple, TypeVar, overload
10
+
11
+ from .token import Token
12
+
13
+
14
+ class _NesterTokens(NamedTuple):
15
+ opening: Token
16
+ closing: Token
17
+
18
+
19
+ _NodeType = TypeVar("_NodeType", bound="SyntaxTreeNode")
20
+
21
+
22
+ class SyntaxTreeNode:
23
+ """A Markdown syntax tree node.
24
+
25
+ A class that can be used to construct a tree representation of a linear
26
+ `markdown-it-py` token stream.
27
+
28
+ Each node in the tree represents either:
29
+ - root of the Markdown document
30
+ - a single unnested `Token`
31
+ - a `Token` "_open" and "_close" token pair, and the tokens nested in
32
+ between
33
+ """
34
+
35
+ def __init__(
36
+ self, tokens: Sequence[Token] = (), *, create_root: bool = True
37
+ ) -> None:
38
+ """Initialize a `SyntaxTreeNode` from a token stream.
39
+
40
+ If `create_root` is True, create a root node for the document.
41
+ """
42
+ # Only nodes representing an unnested token have self.token
43
+ self.token: Token | None = None
44
+
45
+ # Only containers have nester tokens
46
+ self.nester_tokens: _NesterTokens | None = None
47
+
48
+ # Root node does not have self.parent
49
+ self._parent: Any = None
50
+
51
+ # Empty list unless a non-empty container, or unnested token that has
52
+ # children (i.e. inline or img)
53
+ self._children: list[Any] = []
54
+
55
+ if create_root:
56
+ self._set_children_from_tokens(tokens)
57
+ return
58
+
59
+ if not tokens:
60
+ raise ValueError(
61
+ "Can only create root from empty token sequence."
62
+ " Set `create_root=True`."
63
+ )
64
+ elif len(tokens) == 1:
65
+ inline_token = tokens[0]
66
+ if inline_token.nesting:
67
+ raise ValueError(
68
+ "Unequal nesting level at the start and end of token stream."
69
+ )
70
+ self.token = inline_token
71
+ if inline_token.children:
72
+ self._set_children_from_tokens(inline_token.children)
73
+ else:
74
+ self.nester_tokens = _NesterTokens(tokens[0], tokens[-1])
75
+ self._set_children_from_tokens(tokens[1:-1])
76
+
77
+ def __repr__(self) -> str:
78
+ return f"{type(self).__name__}({self.type})"
79
+
80
+ @overload
81
+ def __getitem__(self: _NodeType, item: int) -> _NodeType:
82
+ ...
83
+
84
+ @overload
85
+ def __getitem__(self: _NodeType, item: slice) -> list[_NodeType]:
86
+ ...
87
+
88
+ def __getitem__(self: _NodeType, item: int | slice) -> _NodeType | list[_NodeType]:
89
+ return self.children[item]
90
+
91
+ def to_tokens(self: _NodeType) -> list[Token]:
92
+ """Recover the linear token stream."""
93
+
94
+ def recursive_collect_tokens(node: _NodeType, token_list: list[Token]) -> None:
95
+ if node.type == "root":
96
+ for child in node.children:
97
+ recursive_collect_tokens(child, token_list)
98
+ elif node.token:
99
+ token_list.append(node.token)
100
+ else:
101
+ assert node.nester_tokens
102
+ token_list.append(node.nester_tokens.opening)
103
+ for child in node.children:
104
+ recursive_collect_tokens(child, token_list)
105
+ token_list.append(node.nester_tokens.closing)
106
+
107
+ tokens: list[Token] = []
108
+ recursive_collect_tokens(self, tokens)
109
+ return tokens
110
+
111
+ @property
112
+ def children(self: _NodeType) -> list[_NodeType]:
113
+ return self._children
114
+
115
+ @children.setter
116
+ def children(self: _NodeType, value: list[_NodeType]) -> None:
117
+ self._children = value
118
+
119
+ @property
120
+ def parent(self: _NodeType) -> _NodeType | None:
121
+ return self._parent # type: ignore
122
+
123
+ @parent.setter
124
+ def parent(self: _NodeType, value: _NodeType | None) -> None:
125
+ self._parent = value
126
+
127
+ @property
128
+ def is_root(self) -> bool:
129
+ """Is the node a special root node?"""
130
+ return not (self.token or self.nester_tokens)
131
+
132
+ @property
133
+ def is_nested(self) -> bool:
134
+ """Is this node nested?.
135
+
136
+ Returns `True` if the node represents a `Token` pair and tokens in the
137
+ sequence between them, where `Token.nesting` of the first `Token` in
138
+ the pair is 1 and nesting of the other `Token` is -1.
139
+ """
140
+ return bool(self.nester_tokens)
141
+
142
+ @property
143
+ def siblings(self: _NodeType) -> Sequence[_NodeType]:
144
+ """Get siblings of the node.
145
+
146
+ Gets the whole group of siblings, including self.
147
+ """
148
+ if not self.parent:
149
+ return [self]
150
+ return self.parent.children
151
+
152
+ @property
153
+ def type(self) -> str:
154
+ """Get a string type of the represented syntax.
155
+
156
+ - "root" for root nodes
157
+ - `Token.type` if the node represents an unnested token
158
+ - `Token.type` of the opening token, with "_open" suffix stripped, if
159
+ the node represents a nester token pair
160
+ """
161
+ if self.is_root:
162
+ return "root"
163
+ if self.token:
164
+ return self.token.type
165
+ assert self.nester_tokens
166
+ return _removesuffix(self.nester_tokens.opening.type, "_open")
167
+
168
+ @property
169
+ def next_sibling(self: _NodeType) -> _NodeType | None:
170
+ """Get the next node in the sequence of siblings.
171
+
172
+ Returns `None` if this is the last sibling.
173
+ """
174
+ self_index = self.siblings.index(self)
175
+ if self_index + 1 < len(self.siblings):
176
+ return self.siblings[self_index + 1]
177
+ return None
178
+
179
+ @property
180
+ def previous_sibling(self: _NodeType) -> _NodeType | None:
181
+ """Get the previous node in the sequence of siblings.
182
+
183
+ Returns `None` if this is the first sibling.
184
+ """
185
+ self_index = self.siblings.index(self)
186
+ if self_index - 1 >= 0:
187
+ return self.siblings[self_index - 1]
188
+ return None
189
+
190
+ def _add_child(
191
+ self,
192
+ tokens: Sequence[Token],
193
+ ) -> None:
194
+ """Make a child node for `self`."""
195
+ child = type(self)(tokens, create_root=False)
196
+ child.parent = self
197
+ self.children.append(child)
198
+
199
+ def _set_children_from_tokens(self, tokens: Sequence[Token]) -> None:
200
+ """Convert the token stream to a tree structure and set the resulting
201
+ nodes as children of `self`."""
202
+ reversed_tokens = list(reversed(tokens))
203
+ while reversed_tokens:
204
+ token = reversed_tokens.pop()
205
+
206
+ if not token.nesting:
207
+ self._add_child([token])
208
+ continue
209
+ if token.nesting != 1:
210
+ raise ValueError("Invalid token nesting")
211
+
212
+ nested_tokens = [token]
213
+ nesting = 1
214
+ while reversed_tokens and nesting:
215
+ token = reversed_tokens.pop()
216
+ nested_tokens.append(token)
217
+ nesting += token.nesting
218
+ if nesting:
219
+ raise ValueError(f"unclosed tokens starting {nested_tokens[0]}")
220
+
221
+ self._add_child(nested_tokens)
222
+
223
+ def pretty(
224
+ self, *, indent: int = 2, show_text: bool = False, _current: int = 0
225
+ ) -> str:
226
+ """Create an XML style string of the tree."""
227
+ prefix = " " * _current
228
+ text = prefix + f"<{self.type}"
229
+ if not self.is_root and self.attrs:
230
+ text += " " + " ".join(f"{k}={v!r}" for k, v in self.attrs.items())
231
+ text += ">"
232
+ if (
233
+ show_text
234
+ and not self.is_root
235
+ and self.type in ("text", "text_special")
236
+ and self.content
237
+ ):
238
+ text += "\n" + textwrap.indent(self.content, prefix + " " * indent)
239
+ for child in self.children:
240
+ text += "\n" + child.pretty(
241
+ indent=indent, show_text=show_text, _current=_current + indent
242
+ )
243
+ return text
244
+
245
+ def walk(
246
+ self: _NodeType, *, include_self: bool = True
247
+ ) -> Generator[_NodeType, None, None]:
248
+ """Recursively yield all descendant nodes in the tree starting at self.
249
+
250
+ The order mimics the order of the underlying linear token
251
+ stream (i.e. depth first).
252
+ """
253
+ if include_self:
254
+ yield self
255
+ for child in self.children:
256
+ yield from child.walk(include_self=True)
257
+
258
+ # NOTE:
259
+ # The values of the properties defined below directly map to properties
260
+ # of the underlying `Token`s. A root node does not translate to a `Token`
261
+ # object, so calling these property getters on a root node will raise an
262
+ # `AttributeError`.
263
+ #
264
+ # There is no mapping for `Token.nesting` because the `is_nested` property
265
+ # provides that data, and can be called on any node type, including root.
266
+
267
+ def _attribute_token(self) -> Token:
268
+ """Return the `Token` that is used as the data source for the
269
+ properties defined below."""
270
+ if self.token:
271
+ return self.token
272
+ if self.nester_tokens:
273
+ return self.nester_tokens.opening
274
+ raise AttributeError("Root node does not have the accessed attribute")
275
+
276
+ @property
277
+ def tag(self) -> str:
278
+ """html tag name, e.g. \"p\" """
279
+ return self._attribute_token().tag
280
+
281
+ @property
282
+ def attrs(self) -> dict[str, str | int | float]:
283
+ """Html attributes."""
284
+ return self._attribute_token().attrs
285
+
286
+ def attrGet(self, name: str) -> None | str | int | float:
287
+ """Get the value of attribute `name`, or null if it does not exist."""
288
+ return self._attribute_token().attrGet(name)
289
+
290
+ @property
291
+ def map(self) -> tuple[int, int] | None:
292
+ """Source map info. Format: `tuple[ line_begin, line_end ]`"""
293
+ map_ = self._attribute_token().map
294
+ if map_:
295
+ # Type ignore because `Token`s attribute types are not perfect
296
+ return tuple(map_) # type: ignore
297
+ return None
298
+
299
+ @property
300
+ def level(self) -> int:
301
+ """nesting level, the same as `state.level`"""
302
+ return self._attribute_token().level
303
+
304
+ @property
305
+ def content(self) -> str:
306
+ """In a case of self-closing tag (code, html, fence, etc.), it
307
+ has contents of this tag."""
308
+ return self._attribute_token().content
309
+
310
+ @property
311
+ def markup(self) -> str:
312
+ """'*' or '_' for emphasis, fence string for fence, etc."""
313
+ return self._attribute_token().markup
314
+
315
+ @property
316
+ def info(self) -> str:
317
+ """fence infostring"""
318
+ return self._attribute_token().info
319
+
320
+ @property
321
+ def meta(self) -> dict[Any, Any]:
322
+ """A place for plugins to store an arbitrary data."""
323
+ return self._attribute_token().meta
324
+
325
+ @property
326
+ def block(self) -> bool:
327
+ """True for block-level tokens, false for inline tokens."""
328
+ return self._attribute_token().block
329
+
330
+ @property
331
+ def hidden(self) -> bool:
332
+ """If it's true, ignore this element when rendering.
333
+ Used for tight lists to hide paragraphs."""
334
+ return self._attribute_token().hidden
335
+
336
+
337
+ def _removesuffix(string: str, suffix: str) -> str:
338
+ """Remove a suffix from a string.
339
+
340
+ Replace this with str.removesuffix() from stdlib when minimum Python
341
+ version is 3.9.
342
+ """
343
+ if suffix and string.endswith(suffix):
344
+ return string[: -len(suffix)]
345
+ return string
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/License.txt ADDED
@@ -0,0 +1,1568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ End User License Agreement
2
+ --------------------------
3
+
4
+
5
+ Preface
6
+ -------
7
+
8
+ The Software License Agreement in Chapter 1 and the Supplement
9
+ in Chapter 2 contain license terms and conditions that govern
10
+ the use of NVIDIA software. By accepting this agreement, you
11
+ agree to comply with all the terms and conditions applicable
12
+ to the product(s) included herein.
13
+
14
+
15
+ NVIDIA Driver
16
+
17
+
18
+ Description
19
+
20
+ This package contains the operating system driver and
21
+ fundamental system software components for NVIDIA GPUs.
22
+
23
+
24
+ NVIDIA CUDA Toolkit
25
+
26
+
27
+ Description
28
+
29
+ The NVIDIA CUDA Toolkit provides command-line and graphical
30
+ tools for building, debugging and optimizing the performance
31
+ of applications accelerated by NVIDIA GPUs, runtime and math
32
+ libraries, and documentation including programming guides,
33
+ user manuals, and API references.
34
+
35
+
36
+ Default Install Location of CUDA Toolkit
37
+
38
+ Windows platform:
39
+
40
+ %ProgramFiles%\NVIDIA GPU Computing Toolkit\CUDA\v#.#
41
+
42
+ Linux platform:
43
+
44
+ /usr/local/cuda-#.#
45
+
46
+ Mac platform:
47
+
48
+ /Developer/NVIDIA/CUDA-#.#
49
+
50
+
51
+ NVIDIA CUDA Samples
52
+
53
+
54
+ Description
55
+
56
+ This package includes over 100+ CUDA examples that demonstrate
57
+ various CUDA programming principles, and efficient CUDA
58
+ implementation of algorithms in specific application domains.
59
+
60
+
61
+ Default Install Location of CUDA Samples
62
+
63
+ Windows platform:
64
+
65
+ %ProgramData%\NVIDIA Corporation\CUDA Samples\v#.#
66
+
67
+ Linux platform:
68
+
69
+ /usr/local/cuda-#.#/samples
70
+
71
+ and
72
+
73
+ $HOME/NVIDIA_CUDA-#.#_Samples
74
+
75
+ Mac platform:
76
+
77
+ /Developer/NVIDIA/CUDA-#.#/samples
78
+
79
+
80
+ NVIDIA Nsight Visual Studio Edition (Windows only)
81
+
82
+
83
+ Description
84
+
85
+ NVIDIA Nsight Development Platform, Visual Studio Edition is a
86
+ development environment integrated into Microsoft Visual
87
+ Studio that provides tools for debugging, profiling, analyzing
88
+ and optimizing your GPU computing and graphics applications.
89
+
90
+
91
+ Default Install Location of Nsight Visual Studio Edition
92
+
93
+ Windows platform:
94
+
95
+ %ProgramFiles(x86)%\NVIDIA Corporation\Nsight Visual Studio Edition #.#
96
+
97
+
98
+ 1. License Agreement for NVIDIA Software Development Kits
99
+ ---------------------------------------------------------
100
+
101
+
102
+ Release Date: July 26, 2018
103
+ ---------------------------
104
+
105
+
106
+ Important NoticeRead before downloading, installing,
107
+ copying or using the licensed software:
108
+ -------------------------------------------------------
109
+
110
+ This license agreement, including exhibits attached
111
+ ("Agreement”) is a legal agreement between you and NVIDIA
112
+ Corporation ("NVIDIA") and governs your use of a NVIDIA
113
+ software development kit (“SDK”).
114
+
115
+ Each SDK has its own set of software and materials, but here
116
+ is a description of the types of items that may be included in
117
+ a SDK: source code, header files, APIs, data sets and assets
118
+ (examples include images, textures, models, scenes, videos,
119
+ native API input/output files), binary software, sample code,
120
+ libraries, utility programs, programming code and
121
+ documentation.
122
+
123
+ This Agreement can be accepted only by an adult of legal age
124
+ of majority in the country in which the SDK is used.
125
+
126
+ If you are entering into this Agreement on behalf of a company
127
+ or other legal entity, you represent that you have the legal
128
+ authority to bind the entity to this Agreement, in which case
129
+ “you” will mean the entity you represent.
130
+
131
+ If you don’t have the required age or authority to accept
132
+ this Agreement, or if you don’t accept all the terms and
133
+ conditions of this Agreement, do not download, install or use
134
+ the SDK.
135
+
136
+ You agree to use the SDK only for purposes that are permitted
137
+ by (a) this Agreement, and (b) any applicable law, regulation
138
+ or generally accepted practices or guidelines in the relevant
139
+ jurisdictions.
140
+
141
+
142
+ 1.1. License
143
+
144
+
145
+ 1.1.1. License Grant
146
+
147
+ Subject to the terms of this Agreement, NVIDIA hereby grants
148
+ you a non-exclusive, non-transferable license, without the
149
+ right to sublicense (except as expressly provided in this
150
+ Agreement) to:
151
+
152
+ 1. Install and use the SDK,
153
+
154
+ 2. Modify and create derivative works of sample source code
155
+ delivered in the SDK, and
156
+
157
+ 3. Distribute those portions of the SDK that are identified
158
+ in this Agreement as distributable, as incorporated in
159
+ object code format into a software application that meets
160
+ the distribution requirements indicated in this Agreement.
161
+
162
+
163
+ 1.1.2. Distribution Requirements
164
+
165
+ These are the distribution requirements for you to exercise
166
+ the distribution grant:
167
+
168
+ 1. Your application must have material additional
169
+ functionality, beyond the included portions of the SDK.
170
+
171
+ 2. The distributable portions of the SDK shall only be
172
+ accessed by your application.
173
+
174
+ 3. The following notice shall be included in modifications
175
+ and derivative works of sample source code distributed:
176
+ “This software contains source code provided by NVIDIA
177
+ Corporation.”
178
+
179
+ 4. Unless a developer tool is identified in this Agreement
180
+ as distributable, it is delivered for your internal use
181
+ only.
182
+
183
+ 5. The terms under which you distribute your application
184
+ must be consistent with the terms of this Agreement,
185
+ including (without limitation) terms relating to the
186
+ license grant and license restrictions and protection of
187
+ NVIDIA’s intellectual property rights. Additionally, you
188
+ agree that you will protect the privacy, security and
189
+ legal rights of your application users.
190
+
191
+ 6. You agree to notify NVIDIA in writing of any known or
192
+ suspected distribution or use of the SDK not in compliance
193
+ with the requirements of this Agreement, and to enforce
194
+ the terms of your agreements with respect to distributed
195
+ SDK.
196
+
197
+
198
+ 1.1.3. Authorized Users
199
+
200
+ You may allow employees and contractors of your entity or of
201
+ your subsidiary(ies) to access and use the SDK from your
202
+ secure network to perform work on your behalf.
203
+
204
+ If you are an academic institution you may allow users
205
+ enrolled or employed by the academic institution to access and
206
+ use the SDK from your secure network.
207
+
208
+ You are responsible for the compliance with the terms of this
209
+ Agreement by your authorized users. If you become aware that
210
+ your authorized users didn’t follow the terms of this
211
+ Agreement, you agree to take reasonable steps to resolve the
212
+ non-compliance and prevent new occurrences.
213
+
214
+
215
+ 1.1.4. Pre-Release SDK
216
+
217
+ The SDK versions identified as alpha, beta, preview or
218
+ otherwise as pre-release, may not be fully functional, may
219
+ contain errors or design flaws, and may have reduced or
220
+ different security, privacy, accessibility, availability, and
221
+ reliability standards relative to commercial versions of
222
+ NVIDIA software and materials. Use of a pre-release SDK may
223
+ result in unexpected results, loss of data, project delays or
224
+ other unpredictable damage or loss.
225
+
226
+ You may use a pre-release SDK at your own risk, understanding
227
+ that pre-release SDKs are not intended for use in production
228
+ or business-critical systems.
229
+
230
+ NVIDIA may choose not to make available a commercial version
231
+ of any pre-release SDK. NVIDIA may also choose to abandon
232
+ development and terminate the availability of a pre-release
233
+ SDK at any time without liability.
234
+
235
+
236
+ 1.1.5. Updates
237
+
238
+ NVIDIA may, at its option, make available patches, workarounds
239
+ or other updates to this SDK. Unless the updates are provided
240
+ with their separate governing terms, they are deemed part of
241
+ the SDK licensed to you as provided in this Agreement. You
242
+ agree that the form and content of the SDK that NVIDIA
243
+ provides may change without prior notice to you. While NVIDIA
244
+ generally maintains compatibility between versions, NVIDIA may
245
+ in some cases make changes that introduce incompatibilities in
246
+ future versions of the SDK.
247
+
248
+
249
+ 1.1.6. Third Party Licenses
250
+
251
+ The SDK may come bundled with, or otherwise include or be
252
+ distributed with, third party software licensed by a NVIDIA
253
+ supplier and/or open source software provided under an open
254
+ source license. Use of third party software is subject to the
255
+ third-party license terms, or in the absence of third party
256
+ terms, the terms of this Agreement. Copyright to third party
257
+ software is held by the copyright holders indicated in the
258
+ third-party software or license.
259
+
260
+
261
+ 1.1.7. Reservation of Rights
262
+
263
+ NVIDIA reserves all rights, title, and interest in and to the
264
+ SDK, not expressly granted to you under this Agreement.
265
+
266
+
267
+ 1.2. Limitations
268
+
269
+ The following license limitations apply to your use of the
270
+ SDK:
271
+
272
+ 1. You may not reverse engineer, decompile or disassemble,
273
+ or remove copyright or other proprietary notices from any
274
+ portion of the SDK or copies of the SDK.
275
+
276
+ 2. Except as expressly provided in this Agreement, you may
277
+ not copy, sell, rent, sublicense, transfer, distribute,
278
+ modify, or create derivative works of any portion of the
279
+ SDK. For clarity, you may not distribute or sublicense the
280
+ SDK as a stand-alone product.
281
+
282
+ 3. Unless you have an agreement with NVIDIA for this
283
+ purpose, you may not indicate that an application created
284
+ with the SDK is sponsored or endorsed by NVIDIA.
285
+
286
+ 4. You may not bypass, disable, or circumvent any
287
+ encryption, security, digital rights management or
288
+ authentication mechanism in the SDK.
289
+
290
+ 5. You may not use the SDK in any manner that would cause it
291
+ to become subject to an open source software license. As
292
+ examples, licenses that require as a condition of use,
293
+ modification, and/or distribution that the SDK be:
294
+
295
+ a. Disclosed or distributed in source code form;
296
+
297
+ b. Licensed for the purpose of making derivative works;
298
+ or
299
+
300
+ c. Redistributable at no charge.
301
+
302
+ 6. Unless you have an agreement with NVIDIA for this
303
+ purpose, you may not use the SDK with any system or
304
+ application where the use or failure of the system or
305
+ application can reasonably be expected to threaten or
306
+ result in personal injury, death, or catastrophic loss.
307
+ Examples include use in avionics, navigation, military,
308
+ medical, life support or other life critical applications.
309
+ NVIDIA does not design, test or manufacture the SDK for
310
+ these critical uses and NVIDIA shall not be liable to you
311
+ or any third party, in whole or in part, for any claims or
312
+ damages arising from such uses.
313
+
314
+ 7. You agree to defend, indemnify and hold harmless NVIDIA
315
+ and its affiliates, and their respective employees,
316
+ contractors, agents, officers and directors, from and
317
+ against any and all claims, damages, obligations, losses,
318
+ liabilities, costs or debt, fines, restitutions and
319
+ expenses (including but not limited to attorney’s fees
320
+ and costs incident to establishing the right of
321
+ indemnification) arising out of or related to your use of
322
+ the SDK outside of the scope of this Agreement, or not in
323
+ compliance with its terms.
324
+
325
+
326
+ 1.3. Ownership
327
+
328
+ 1. NVIDIA or its licensors hold all rights, title and
329
+ interest in and to the SDK and its modifications and
330
+ derivative works, including their respective intellectual
331
+ property rights, subject to your rights described in this
332
+ section. This SDK may include software and materials from
333
+ NVIDIA’s licensors, and these licensors are intended
334
+ third party beneficiaries that may enforce this Agreement
335
+ with respect to their intellectual property rights.
336
+
337
+ 2. You hold all rights, title and interest in and to your
338
+ applications and your derivative works of the sample
339
+ source code delivered in the SDK, including their
340
+ respective intellectual property rights, subject to
341
+ NVIDIA’s rights described in this section.
342
+
343
+ 3. You may, but don’t have to, provide to NVIDIA
344
+ suggestions, feature requests or other feedback regarding
345
+ the SDK, including possible enhancements or modifications
346
+ to the SDK. For any feedback that you voluntarily provide,
347
+ you hereby grant NVIDIA and its affiliates a perpetual,
348
+ non-exclusive, worldwide, irrevocable license to use,
349
+ reproduce, modify, license, sublicense (through multiple
350
+ tiers of sublicensees), and distribute (through multiple
351
+ tiers of distributors) it without the payment of any
352
+ royalties or fees to you. NVIDIA will use feedback at its
353
+ choice. NVIDIA is constantly looking for ways to improve
354
+ its products, so you may send feedback to NVIDIA through
355
+ the developer portal at https://developer.nvidia.com.
356
+
357
+
358
+ 1.4. No Warranties
359
+
360
+ THE SDK IS PROVIDED BY NVIDIA “AS IS” AND “WITH ALL
361
+ FAULTS.” TO THE MAXIMUM EXTENT PERMITTED BY LAW, NVIDIA AND
362
+ ITS AFFILIATES EXPRESSLY DISCLAIM ALL WARRANTIES OF ANY KIND
363
+ OR NATURE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING,
364
+ BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
365
+ FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, OR THE
366
+ ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR PATENT. NO
367
+ WARRANTY IS MADE ON THE BASIS OF TRADE USAGE, COURSE OF
368
+ DEALING OR COURSE OF TRADE.
369
+
370
+
371
+ 1.5. Limitation of Liability
372
+
373
+ TO THE MAXIMUM EXTENT PERMITTED BY LAW, NVIDIA AND ITS
374
+ AFFILIATES SHALL NOT BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
375
+ PUNITIVE OR CONSEQUENTIAL DAMAGES, OR ANY LOST PROFITS, LOSS
376
+ OF USE, LOSS OF DATA OR LOSS OF GOODWILL, OR THE COSTS OF
377
+ PROCURING SUBSTITUTE PRODUCTS, ARISING OUT OF OR IN CONNECTION
378
+ WITH THIS AGREEMENT OR THE USE OR PERFORMANCE OF THE SDK,
379
+ WHETHER SUCH LIABILITY ARISES FROM ANY CLAIM BASED UPON BREACH
380
+ OF CONTRACT, BREACH OF WARRANTY, TORT (INCLUDING NEGLIGENCE),
381
+ PRODUCT LIABILITY OR ANY OTHER CAUSE OF ACTION OR THEORY OF
382
+ LIABILITY. IN NO EVENT WILL NVIDIA’S AND ITS AFFILIATES
383
+ TOTAL CUMULATIVE LIABILITY UNDER OR ARISING OUT OF THIS
384
+ AGREEMENT EXCEED US$10.00. THE NATURE OF THE LIABILITY OR THE
385
+ NUMBER OF CLAIMS OR SUITS SHALL NOT ENLARGE OR EXTEND THIS
386
+ LIMIT.
387
+
388
+ These exclusions and limitations of liability shall apply
389
+ regardless if NVIDIA or its affiliates have been advised of
390
+ the possibility of such damages, and regardless of whether a
391
+ remedy fails its essential purpose. These exclusions and
392
+ limitations of liability form an essential basis of the
393
+ bargain between the parties, and, absent any of these
394
+ exclusions or limitations of liability, the provisions of this
395
+ Agreement, including, without limitation, the economic terms,
396
+ would be substantially different.
397
+
398
+
399
+ 1.6. Termination
400
+
401
+ 1. This Agreement will continue to apply until terminated by
402
+ either you or NVIDIA as described below.
403
+
404
+ 2. If you want to terminate this Agreement, you may do so by
405
+ stopping to use the SDK.
406
+
407
+ 3. NVIDIA may, at any time, terminate this Agreement if:
408
+
409
+ a. (i) you fail to comply with any term of this
410
+ Agreement and the non-compliance is not fixed within
411
+ thirty (30) days following notice from NVIDIA (or
412
+ immediately if you violate NVIDIA’s intellectual
413
+ property rights);
414
+
415
+ b. (ii) you commence or participate in any legal
416
+ proceeding against NVIDIA with respect to the SDK; or
417
+
418
+ c. (iii) NVIDIA decides to no longer provide the SDK in
419
+ a country or, in NVIDIA’s sole discretion, the
420
+ continued use of it is no longer commercially viable.
421
+
422
+ 4. Upon any termination of this Agreement, you agree to
423
+ promptly discontinue use of the SDK and destroy all copies
424
+ in your possession or control. Your prior distributions in
425
+ accordance with this Agreement are not affected by the
426
+ termination of this Agreement. Upon written request, you
427
+ will certify in writing that you have complied with your
428
+ commitments under this section. Upon any termination of
429
+ this Agreement all provisions survive except for the
430
+ license grant provisions.
431
+
432
+
433
+ 1.7. General
434
+
435
+ If you wish to assign this Agreement or your rights and
436
+ obligations, including by merger, consolidation, dissolution
437
+ or operation of law, contact NVIDIA to ask for permission. Any
438
+ attempted assignment not approved by NVIDIA in writing shall
439
+ be void and of no effect. NVIDIA may assign, delegate or
440
+ transfer this Agreement and its rights and obligations, and if
441
+ to a non-affiliate you will be notified.
442
+
443
+ You agree to cooperate with NVIDIA and provide reasonably
444
+ requested information to verify your compliance with this
445
+ Agreement.
446
+
447
+ This Agreement will be governed in all respects by the laws of
448
+ the United States and of the State of Delaware as those laws
449
+ are applied to contracts entered into and performed entirely
450
+ within Delaware by Delaware residents, without regard to the
451
+ conflicts of laws principles. The United Nations Convention on
452
+ Contracts for the International Sale of Goods is specifically
453
+ disclaimed. You agree to all terms of this Agreement in the
454
+ English language.
455
+
456
+ The state or federal courts residing in Santa Clara County,
457
+ California shall have exclusive jurisdiction over any dispute
458
+ or claim arising out of this Agreement. Notwithstanding this,
459
+ you agree that NVIDIA shall still be allowed to apply for
460
+ injunctive remedies or an equivalent type of urgent legal
461
+ relief in any jurisdiction.
462
+
463
+ If any court of competent jurisdiction determines that any
464
+ provision of this Agreement is illegal, invalid or
465
+ unenforceable, such provision will be construed as limited to
466
+ the extent necessary to be consistent with and fully
467
+ enforceable under the law and the remaining provisions will
468
+ remain in full force and effect. Unless otherwise specified,
469
+ remedies are cumulative.
470
+
471
+ Each party acknowledges and agrees that the other is an
472
+ independent contractor in the performance of this Agreement.
473
+
474
+ The SDK has been developed entirely at private expense and is
475
+ “commercial items” consisting of “commercial computer
476
+ software” and “commercial computer software
477
+ documentation” provided with RESTRICTED RIGHTS. Use,
478
+ duplication or disclosure by the U.S. Government or a U.S.
479
+ Government subcontractor is subject to the restrictions in
480
+ this Agreement pursuant to DFARS 227.7202-3(a) or as set forth
481
+ in subparagraphs (c)(1) and (2) of the Commercial Computer
482
+ Software - Restricted Rights clause at FAR 52.227-19, as
483
+ applicable. Contractor/manufacturer is NVIDIA, 2788 San Tomas
484
+ Expressway, Santa Clara, CA 95051.
485
+
486
+ The SDK is subject to United States export laws and
487
+ regulations. You agree that you will not ship, transfer or
488
+ export the SDK into any country, or use the SDK in any manner,
489
+ prohibited by the United States Bureau of Industry and
490
+ Security or economic sanctions regulations administered by the
491
+ U.S. Department of Treasury’s Office of Foreign Assets
492
+ Control (OFAC), or any applicable export laws, restrictions or
493
+ regulations. These laws include restrictions on destinations,
494
+ end users and end use. By accepting this Agreement, you
495
+ confirm that you are not a resident or citizen of any country
496
+ currently embargoed by the U.S. and that you are not otherwise
497
+ prohibited from receiving the SDK.
498
+
499
+ Any notice delivered by NVIDIA to you under this Agreement
500
+ will be delivered via mail, email or fax. You agree that any
501
+ notices that NVIDIA sends you electronically will satisfy any
502
+ legal communication requirements. Please direct your legal
503
+ notices or other correspondence to NVIDIA Corporation, 2788
504
+ San Tomas Expressway, Santa Clara, California 95051, United
505
+ States of America, Attention: Legal Department.
506
+
507
+ This Agreement and any exhibits incorporated into this
508
+ Agreement constitute the entire agreement of the parties with
509
+ respect to the subject matter of this Agreement and supersede
510
+ all prior negotiations or documentation exchanged between the
511
+ parties relating to this SDK license. Any additional and/or
512
+ conflicting terms on documents issued by you are null, void,
513
+ and invalid. Any amendment or waiver under this Agreement
514
+ shall be in writing and signed by representatives of both
515
+ parties.
516
+
517
+
518
+ 2. CUDA Toolkit Supplement to Software License Agreement for
519
+ NVIDIA Software Development Kits
520
+ ------------------------------------------------------------
521
+
522
+
523
+ Release date: August 16, 2018
524
+ -----------------------------
525
+
526
+ The terms in this supplement govern your use of the NVIDIA
527
+ CUDA Toolkit SDK under the terms of your license agreement
528
+ (“Agreement”) as modified by this supplement. Capitalized
529
+ terms used but not defined below have the meaning assigned to
530
+ them in the Agreement.
531
+
532
+ This supplement is an exhibit to the Agreement and is
533
+ incorporated as an integral part of the Agreement. In the
534
+ event of conflict between the terms in this supplement and the
535
+ terms in the Agreement, the terms in this supplement govern.
536
+
537
+
538
+ 2.1. License Scope
539
+
540
+ The SDK is licensed for you to develop applications only for
541
+ use in systems with NVIDIA GPUs.
542
+
543
+
544
+ 2.2. Distribution
545
+
546
+ The portions of the SDK that are distributable under the
547
+ Agreement are listed in Attachment A.
548
+
549
+
550
+ 2.3. Operating Systems
551
+
552
+ Those portions of the SDK designed exclusively for use on the
553
+ Linux or FreeBSD operating systems, or other operating systems
554
+ derived from the source code to these operating systems, may
555
+ be copied and redistributed for use in accordance with this
556
+ Agreement, provided that the object code files are not
557
+ modified in any way (except for unzipping of compressed
558
+ files).
559
+
560
+
561
+ 2.4. Audio and Video Encoders and Decoders
562
+
563
+ You acknowledge and agree that it is your sole responsibility
564
+ to obtain any additional third-party licenses required to
565
+ make, have made, use, have used, sell, import, and offer for
566
+ sale your products or services that include or incorporate any
567
+ third-party software and content relating to audio and/or
568
+ video encoders and decoders from, including but not limited
569
+ to, Microsoft, Thomson, Fraunhofer IIS, Sisvel S.p.A.,
570
+ MPEG-LA, and Coding Technologies. NVIDIA does not grant to you
571
+ under this Agreement any necessary patent or other rights with
572
+ respect to any audio and/or video encoders and decoders.
573
+
574
+
575
+ 2.5. Licensing
576
+
577
+ If the distribution terms in this Agreement are not suitable
578
+ for your organization, or for any questions regarding this
579
+ Agreement, please contact NVIDIA at
580
+ nvidia-compute-license-questions@nvidia.com.
581
+
582
+
583
+ 2.6. Attachment A
584
+
585
+ The following portions of the SDK are distributable under the
586
+ Agreement:
587
+
588
+ Component
589
+
590
+ CUDA Runtime
591
+
592
+ Windows
593
+
594
+ cudart.dll, cudart_static.lib, cudadevrt.lib
595
+
596
+ Mac OSX
597
+
598
+ libcudart.dylib, libcudart_static.a, libcudadevrt.a
599
+
600
+ Linux
601
+
602
+ libcudart.so, libcudart_static.a, libcudadevrt.a
603
+
604
+ Android
605
+
606
+ libcudart.so, libcudart_static.a, libcudadevrt.a
607
+
608
+ Component
609
+
610
+ CUDA FFT Library
611
+
612
+ Windows
613
+
614
+ cufft.dll, cufftw.dll, cufft.lib, cufftw.lib
615
+
616
+ Mac OSX
617
+
618
+ libcufft.dylib, libcufft_static.a, libcufftw.dylib,
619
+ libcufftw_static.a
620
+
621
+ Linux
622
+
623
+ libcufft.so, libcufft_static.a, libcufftw.so,
624
+ libcufftw_static.a
625
+
626
+ Android
627
+
628
+ libcufft.so, libcufft_static.a, libcufftw.so,
629
+ libcufftw_static.a
630
+
631
+ Component
632
+
633
+ CUDA BLAS Library
634
+
635
+ Windows
636
+
637
+ cublas.dll, cublasLt.dll
638
+
639
+ Mac OSX
640
+
641
+ libcublas.dylib, libcublasLt.dylib, libcublas_static.a,
642
+ libcublasLt_static.a
643
+
644
+ Linux
645
+
646
+ libcublas.so, libcublasLt.so, libcublas_static.a,
647
+ libcublasLt_static.a
648
+
649
+ Android
650
+
651
+ libcublas.so, libcublasLt.so, libcublas_static.a,
652
+ libcublasLt_static.a
653
+
654
+ Component
655
+
656
+ NVIDIA "Drop-in" BLAS Library
657
+
658
+ Windows
659
+
660
+ nvblas.dll
661
+
662
+ Mac OSX
663
+
664
+ libnvblas.dylib
665
+
666
+ Linux
667
+
668
+ libnvblas.so
669
+
670
+ Component
671
+
672
+ CUDA Sparse Matrix Library
673
+
674
+ Windows
675
+
676
+ cusparse.dll, cusparse.lib
677
+
678
+ Mac OSX
679
+
680
+ libcusparse.dylib, libcusparse_static.a
681
+
682
+ Linux
683
+
684
+ libcusparse.so, libcusparse_static.a
685
+
686
+ Android
687
+
688
+ libcusparse.so, libcusparse_static.a
689
+
690
+ Component
691
+
692
+ CUDA Linear Solver Library
693
+
694
+ Windows
695
+
696
+ cusolver.dll, cusolver.lib
697
+
698
+ Mac OSX
699
+
700
+ libcusolver.dylib, libcusolver_static.a
701
+
702
+ Linux
703
+
704
+ libcusolver.so, libcusolver_static.a
705
+
706
+ Android
707
+
708
+ libcusolver.so, libcusolver_static.a
709
+
710
+ Component
711
+
712
+ CUDA Random Number Generation Library
713
+
714
+ Windows
715
+
716
+ curand.dll, curand.lib
717
+
718
+ Mac OSX
719
+
720
+ libcurand.dylib, libcurand_static.a
721
+
722
+ Linux
723
+
724
+ libcurand.so, libcurand_static.a
725
+
726
+ Android
727
+
728
+ libcurand.so, libcurand_static.a
729
+
730
+ Component
731
+
732
+ CUDA Accelerated Graph Library
733
+
734
+ Component
735
+
736
+ NVIDIA Performance Primitives Library
737
+
738
+ Windows
739
+
740
+ nppc.dll, nppc.lib, nppial.dll, nppial.lib, nppicc.dll,
741
+ nppicc.lib, nppicom.dll, nppicom.lib, nppidei.dll,
742
+ nppidei.lib, nppif.dll, nppif.lib, nppig.dll, nppig.lib,
743
+ nppim.dll, nppim.lib, nppist.dll, nppist.lib, nppisu.dll,
744
+ nppisu.lib, nppitc.dll, nppitc.lib, npps.dll, npps.lib
745
+
746
+ Mac OSX
747
+
748
+ libnppc.dylib, libnppc_static.a, libnppial.dylib,
749
+ libnppial_static.a, libnppicc.dylib, libnppicc_static.a,
750
+ libnppicom.dylib, libnppicom_static.a, libnppidei.dylib,
751
+ libnppidei_static.a, libnppif.dylib, libnppif_static.a,
752
+ libnppig.dylib, libnppig_static.a, libnppim.dylib,
753
+ libnppisu_static.a, libnppitc.dylib, libnppitc_static.a,
754
+ libnpps.dylib, libnpps_static.a
755
+
756
+ Linux
757
+
758
+ libnppc.so, libnppc_static.a, libnppial.so,
759
+ libnppial_static.a, libnppicc.so, libnppicc_static.a,
760
+ libnppicom.so, libnppicom_static.a, libnppidei.so,
761
+ libnppidei_static.a, libnppif.so, libnppif_static.a
762
+ libnppig.so, libnppig_static.a, libnppim.so,
763
+ libnppim_static.a, libnppist.so, libnppist_static.a,
764
+ libnppisu.so, libnppisu_static.a, libnppitc.so
765
+ libnppitc_static.a, libnpps.so, libnpps_static.a
766
+
767
+ Android
768
+
769
+ libnppc.so, libnppc_static.a, libnppial.so,
770
+ libnppial_static.a, libnppicc.so, libnppicc_static.a,
771
+ libnppicom.so, libnppicom_static.a, libnppidei.so,
772
+ libnppidei_static.a, libnppif.so, libnppif_static.a
773
+ libnppig.so, libnppig_static.a, libnppim.so,
774
+ libnppim_static.a, libnppist.so, libnppist_static.a,
775
+ libnppisu.so, libnppisu_static.a, libnppitc.so
776
+ libnppitc_static.a, libnpps.so, libnpps_static.a
777
+
778
+ Component
779
+
780
+ NVIDIA JPEG Library
781
+
782
+ Linux
783
+
784
+ libnvjpeg.so, libnvjpeg_static.a
785
+
786
+ Component
787
+
788
+ Internal common library required for statically linking to
789
+ cuBLAS, cuSPARSE, cuFFT, cuRAND, nvJPEG and NPP
790
+
791
+ Mac OSX
792
+
793
+ libculibos.a
794
+
795
+ Linux
796
+
797
+ libculibos.a
798
+
799
+ Component
800
+
801
+ NVIDIA Runtime Compilation Library and Header
802
+
803
+ All
804
+
805
+ nvrtc.h
806
+
807
+ Windows
808
+
809
+ nvrtc.dll, nvrtc-builtins.dll
810
+
811
+ Mac OSX
812
+
813
+ libnvrtc.dylib, libnvrtc-builtins.dylib
814
+
815
+ Linux
816
+
817
+ libnvrtc.so, libnvrtc-builtins.so
818
+
819
+ Component
820
+
821
+ NVIDIA Optimizing Compiler Library
822
+
823
+ Windows
824
+
825
+ nvvm.dll
826
+
827
+ Mac OSX
828
+
829
+ libnvvm.dylib
830
+
831
+ Linux
832
+
833
+ libnvvm.so
834
+
835
+ Component
836
+
837
+ NVIDIA Common Device Math Functions Library
838
+
839
+ Windows
840
+
841
+ libdevice.10.bc
842
+
843
+ Mac OSX
844
+
845
+ libdevice.10.bc
846
+
847
+ Linux
848
+
849
+ libdevice.10.bc
850
+
851
+ Component
852
+
853
+ CUDA Occupancy Calculation Header Library
854
+
855
+ All
856
+
857
+ cuda_occupancy.h
858
+
859
+ Component
860
+
861
+ CUDA Half Precision Headers
862
+
863
+ All
864
+
865
+ cuda_fp16.h, cuda_fp16.hpp
866
+
867
+ Component
868
+
869
+ CUDA Profiling Tools Interface (CUPTI) Library
870
+
871
+ Windows
872
+
873
+ cupti.dll
874
+
875
+ Mac OSX
876
+
877
+ libcupti.dylib
878
+
879
+ Linux
880
+
881
+ libcupti.so
882
+
883
+ Component
884
+
885
+ NVIDIA Tools Extension Library
886
+
887
+ Windows
888
+
889
+ nvToolsExt.dll, nvToolsExt.lib
890
+
891
+ Mac OSX
892
+
893
+ libnvToolsExt.dylib
894
+
895
+ Linux
896
+
897
+ libnvToolsExt.so
898
+
899
+ Component
900
+
901
+ NVIDIA CUDA Driver Libraries
902
+
903
+ Linux
904
+
905
+ libcuda.so, libnvidia-fatbinaryloader.so,
906
+ libnvidia-ptxjitcompiler.so
907
+
908
+ The NVIDIA CUDA Driver Libraries are only distributable in
909
+ applications that meet this criteria:
910
+
911
+ 1. The application was developed starting from a NVIDIA CUDA
912
+ container obtained from Docker Hub or the NVIDIA GPU
913
+ Cloud, and
914
+
915
+ 2. The resulting application is packaged as a Docker
916
+ container and distributed to users on Docker Hub or the
917
+ NVIDIA GPU Cloud only.
918
+
919
+
920
+ 2.7. Attachment B
921
+
922
+
923
+ Additional Licensing Obligations
924
+
925
+ The following third party components included in the SOFTWARE
926
+ are licensed to Licensee pursuant to the following terms and
927
+ conditions:
928
+
929
+ 1. Licensee's use of the GDB third party component is
930
+ subject to the terms and conditions of GNU GPL v3:
931
+
932
+ This product includes copyrighted third-party software licensed
933
+ under the terms of the GNU General Public License v3 ("GPL v3").
934
+ All third-party software packages are copyright by their respective
935
+ authors. GPL v3 terms and conditions are hereby incorporated into
936
+ the Agreement by this reference: http://www.gnu.org/licenses/gpl.txt
937
+
938
+ Consistent with these licensing requirements, the software
939
+ listed below is provided under the terms of the specified
940
+ open source software licenses. To obtain source code for
941
+ software provided under licenses that require
942
+ redistribution of source code, including the GNU General
943
+ Public License (GPL) and GNU Lesser General Public License
944
+ (LGPL), contact oss-requests@nvidia.com. This offer is
945
+ valid for a period of three (3) years from the date of the
946
+ distribution of this product by NVIDIA CORPORATION.
947
+
948
+ Component License
949
+ CUDA-GDB GPL v3
950
+
951
+ 2. Licensee represents and warrants that any and all third
952
+ party licensing and/or royalty payment obligations in
953
+ connection with Licensee's use of the H.264 video codecs
954
+ are solely the responsibility of Licensee.
955
+
956
+ 3. Licensee's use of the Thrust library is subject to the
957
+ terms and conditions of the Apache License Version 2.0.
958
+ All third-party software packages are copyright by their
959
+ respective authors. Apache License Version 2.0 terms and
960
+ conditions are hereby incorporated into the Agreement by
961
+ this reference.
962
+ http://www.apache.org/licenses/LICENSE-2.0.html
963
+
964
+ In addition, Licensee acknowledges the following notice:
965
+ Thrust includes source code from the Boost Iterator,
966
+ Tuple, System, and Random Number libraries.
967
+
968
+ Boost Software License - Version 1.0 - August 17th, 2003
969
+ . . . .
970
+
971
+ Permission is hereby granted, free of charge, to any person or
972
+ organization obtaining a copy of the software and accompanying
973
+ documentation covered by this license (the "Software") to use,
974
+ reproduce, display, distribute, execute, and transmit the Software,
975
+ and to prepare derivative works of the Software, and to permit
976
+ third-parties to whom the Software is furnished to do so, all
977
+ subject to the following:
978
+
979
+ The copyright notices in the Software and this entire statement,
980
+ including the above license grant, this restriction and the following
981
+ disclaimer, must be included in all copies of the Software, in whole
982
+ or in part, and all derivative works of the Software, unless such
983
+ copies or derivative works are solely in the form of machine-executable
984
+ object code generated by a source language processor.
985
+
986
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
987
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
988
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
989
+ NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
990
+ ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
991
+ OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
992
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
993
+ OTHER DEALINGS IN THE SOFTWARE.
994
+
995
+ 4. Licensee's use of the LLVM third party component is
996
+ subject to the following terms and conditions:
997
+
998
+ ======================================================
999
+ LLVM Release License
1000
+ ======================================================
1001
+ University of Illinois/NCSA
1002
+ Open Source License
1003
+
1004
+ Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign.
1005
+ All rights reserved.
1006
+
1007
+ Developed by:
1008
+
1009
+ LLVM Team
1010
+
1011
+ University of Illinois at Urbana-Champaign
1012
+
1013
+ http://llvm.org
1014
+
1015
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1016
+ of this software and associated documentation files (the "Software"), to
1017
+ deal with the Software without restriction, including without limitation the
1018
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1019
+ sell copies of the Software, and to permit persons to whom the Software is
1020
+ furnished to do so, subject to the following conditions:
1021
+
1022
+ * Redistributions of source code must retain the above copyright notice,
1023
+ this list of conditions and the following disclaimers.
1024
+
1025
+ * Redistributions in binary form must reproduce the above copyright
1026
+ notice, this list of conditions and the following disclaimers in the
1027
+ documentation and/or other materials provided with the distribution.
1028
+
1029
+ * Neither the names of the LLVM Team, University of Illinois at Urbana-
1030
+ Champaign, nor the names of its contributors may be used to endorse or
1031
+ promote products derived from this Software without specific prior
1032
+ written permission.
1033
+
1034
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1035
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1036
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1037
+ THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1038
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1039
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1040
+ DEALINGS WITH THE SOFTWARE.
1041
+
1042
+ 5. Licensee's use (e.g. nvprof) of the PCRE third party
1043
+ component is subject to the following terms and
1044
+ conditions:
1045
+
1046
+ ------------
1047
+ PCRE LICENCE
1048
+ ------------
1049
+ PCRE is a library of functions to support regular expressions whose syntax
1050
+ and semantics are as close as possible to those of the Perl 5 language.
1051
+ Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
1052
+ specified below. The documentation for PCRE, supplied in the "doc"
1053
+ directory, is distributed under the same terms as the software itself. The
1054
+ basic library functions are written in C and are freestanding. Also
1055
+ included in the distribution is a set of C++ wrapper functions, and a just-
1056
+ in-time compiler that can be used to optimize pattern matching. These are
1057
+ both optional features that can be omitted when the library is built.
1058
+
1059
+ THE BASIC LIBRARY FUNCTIONS
1060
+ ---------------------------
1061
+ Written by: Philip Hazel
1062
+ Email local part: ph10
1063
+ Email domain: cam.ac.uk
1064
+ University of Cambridge Computing Service,
1065
+ Cambridge, England.
1066
+ Copyright (c) 1997-2012 University of Cambridge
1067
+ All rights reserved.
1068
+
1069
+ PCRE JUST-IN-TIME COMPILATION SUPPORT
1070
+ -------------------------------------
1071
+ Written by: Zoltan Herczeg
1072
+ Email local part: hzmester
1073
+ Emain domain: freemail.hu
1074
+ Copyright(c) 2010-2012 Zoltan Herczeg
1075
+ All rights reserved.
1076
+
1077
+ STACK-LESS JUST-IN-TIME COMPILER
1078
+ --------------------------------
1079
+ Written by: Zoltan Herczeg
1080
+ Email local part: hzmester
1081
+ Emain domain: freemail.hu
1082
+ Copyright(c) 2009-2012 Zoltan Herczeg
1083
+ All rights reserved.
1084
+
1085
+ THE C++ WRAPPER FUNCTIONS
1086
+ -------------------------
1087
+ Contributed by: Google Inc.
1088
+ Copyright (c) 2007-2012, Google Inc.
1089
+ All rights reserved.
1090
+
1091
+ THE "BSD" LICENCE
1092
+ -----------------
1093
+ Redistribution and use in source and binary forms, with or without
1094
+ modification, are permitted provided that the following conditions are met:
1095
+
1096
+ * Redistributions of source code must retain the above copyright notice,
1097
+ this list of conditions and the following disclaimer.
1098
+
1099
+ * Redistributions in binary form must reproduce the above copyright
1100
+ notice, this list of conditions and the following disclaimer in the
1101
+ documentation and/or other materials provided with the distribution.
1102
+
1103
+ * Neither the name of the University of Cambridge nor the name of Google
1104
+ Inc. nor the names of their contributors may be used to endorse or
1105
+ promote products derived from this software without specific prior
1106
+ written permission.
1107
+
1108
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1109
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1110
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1111
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1112
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1113
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1114
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1115
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1116
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1117
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1118
+ POSSIBILITY OF SUCH DAMAGE.
1119
+
1120
+ 6. Some of the cuBLAS library routines were written by or
1121
+ derived from code written by Vasily Volkov and are subject
1122
+ to the Modified Berkeley Software Distribution License as
1123
+ follows:
1124
+
1125
+ Copyright (c) 2007-2009, Regents of the University of California
1126
+
1127
+ All rights reserved.
1128
+
1129
+ Redistribution and use in source and binary forms, with or without
1130
+ modification, are permitted provided that the following conditions are
1131
+ met:
1132
+ * Redistributions of source code must retain the above copyright
1133
+ notice, this list of conditions and the following disclaimer.
1134
+ * Redistributions in binary form must reproduce the above
1135
+ copyright notice, this list of conditions and the following
1136
+ disclaimer in the documentation and/or other materials provided
1137
+ with the distribution.
1138
+ * Neither the name of the University of California, Berkeley nor
1139
+ the names of its contributors may be used to endorse or promote
1140
+ products derived from this software without specific prior
1141
+ written permission.
1142
+
1143
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
1144
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1145
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1146
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
1147
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1148
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1149
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1150
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1151
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
1152
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1153
+ POSSIBILITY OF SUCH DAMAGE.
1154
+
1155
+ 7. Some of the cuBLAS library routines were written by or
1156
+ derived from code written by Davide Barbieri and are
1157
+ subject to the Modified Berkeley Software Distribution
1158
+ License as follows:
1159
+
1160
+ Copyright (c) 2008-2009 Davide Barbieri @ University of Rome Tor Vergata.
1161
+
1162
+ All rights reserved.
1163
+
1164
+ Redistribution and use in source and binary forms, with or without
1165
+ modification, are permitted provided that the following conditions are
1166
+ met:
1167
+ * Redistributions of source code must retain the above copyright
1168
+ notice, this list of conditions and the following disclaimer.
1169
+ * Redistributions in binary form must reproduce the above
1170
+ copyright notice, this list of conditions and the following
1171
+ disclaimer in the documentation and/or other materials provided
1172
+ with the distribution.
1173
+ * The name of the author may not be used to endorse or promote
1174
+ products derived from this software without specific prior
1175
+ written permission.
1176
+
1177
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
1178
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1179
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1180
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
1181
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1182
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1183
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1184
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1185
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
1186
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1187
+ POSSIBILITY OF SUCH DAMAGE.
1188
+
1189
+ 8. Some of the cuBLAS library routines were derived from
1190
+ code developed by the University of Tennessee and are
1191
+ subject to the Modified Berkeley Software Distribution
1192
+ License as follows:
1193
+
1194
+ Copyright (c) 2010 The University of Tennessee.
1195
+
1196
+ All rights reserved.
1197
+
1198
+ Redistribution and use in source and binary forms, with or without
1199
+ modification, are permitted provided that the following conditions are
1200
+ met:
1201
+ * Redistributions of source code must retain the above copyright
1202
+ notice, this list of conditions and the following disclaimer.
1203
+ * Redistributions in binary form must reproduce the above
1204
+ copyright notice, this list of conditions and the following
1205
+ disclaimer listed in this license in the documentation and/or
1206
+ other materials provided with the distribution.
1207
+ * Neither the name of the copyright holders nor the names of its
1208
+ contributors may be used to endorse or promote products derived
1209
+ from this software without specific prior written permission.
1210
+
1211
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1212
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1213
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1214
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1215
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1216
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1217
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1218
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1219
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1220
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1221
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1222
+
1223
+ 9. Some of the cuBLAS library routines were written by or
1224
+ derived from code written by Jonathan Hogg and are subject
1225
+ to the Modified Berkeley Software Distribution License as
1226
+ follows:
1227
+
1228
+ Copyright (c) 2012, The Science and Technology Facilities Council (STFC).
1229
+
1230
+ All rights reserved.
1231
+
1232
+ Redistribution and use in source and binary forms, with or without
1233
+ modification, are permitted provided that the following conditions are
1234
+ met:
1235
+ * Redistributions of source code must retain the above copyright
1236
+ notice, this list of conditions and the following disclaimer.
1237
+ * Redistributions in binary form must reproduce the above
1238
+ copyright notice, this list of conditions and the following
1239
+ disclaimer in the documentation and/or other materials provided
1240
+ with the distribution.
1241
+ * Neither the name of the STFC nor the names of its contributors
1242
+ may be used to endorse or promote products derived from this
1243
+ software without specific prior written permission.
1244
+
1245
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1246
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1247
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1248
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE STFC BE
1249
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1250
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1251
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1252
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
1253
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
1254
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
1255
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1256
+
1257
+ 10. Some of the cuBLAS library routines were written by or
1258
+ derived from code written by Ahmad M. Abdelfattah, David
1259
+ Keyes, and Hatem Ltaief, and are subject to the Apache
1260
+ License, Version 2.0, as follows:
1261
+
1262
+ -- (C) Copyright 2013 King Abdullah University of Science and Technology
1263
+ Authors:
1264
+ Ahmad Abdelfattah (ahmad.ahmad@kaust.edu.sa)
1265
+ David Keyes (david.keyes@kaust.edu.sa)
1266
+ Hatem Ltaief (hatem.ltaief@kaust.edu.sa)
1267
+
1268
+ Redistribution and use in source and binary forms, with or without
1269
+ modification, are permitted provided that the following conditions
1270
+ are met:
1271
+
1272
+ * Redistributions of source code must retain the above copyright
1273
+ notice, this list of conditions and the following disclaimer.
1274
+ * Redistributions in binary form must reproduce the above copyright
1275
+ notice, this list of conditions and the following disclaimer in the
1276
+ documentation and/or other materials provided with the distribution.
1277
+ * Neither the name of the King Abdullah University of Science and
1278
+ Technology nor the names of its contributors may be used to endorse
1279
+ or promote products derived from this software without specific prior
1280
+ written permission.
1281
+
1282
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1283
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1284
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1285
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1286
+ HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1287
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1288
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1289
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1290
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1291
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1292
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
1293
+
1294
+ 11. Some of the cuSPARSE library routines were written by or
1295
+ derived from code written by Li-Wen Chang and are subject
1296
+ to the NCSA Open Source License as follows:
1297
+
1298
+ Copyright (c) 2012, University of Illinois.
1299
+
1300
+ All rights reserved.
1301
+
1302
+ Developed by: IMPACT Group, University of Illinois, http://impact.crhc.illinois.edu
1303
+
1304
+ Permission is hereby granted, free of charge, to any person obtaining
1305
+ a copy of this software and associated documentation files (the
1306
+ "Software"), to deal with the Software without restriction, including
1307
+ without limitation the rights to use, copy, modify, merge, publish,
1308
+ distribute, sublicense, and/or sell copies of the Software, and to
1309
+ permit persons to whom the Software is furnished to do so, subject to
1310
+ the following conditions:
1311
+ * Redistributions of source code must retain the above copyright
1312
+ notice, this list of conditions and the following disclaimer.
1313
+ * Redistributions in binary form must reproduce the above
1314
+ copyright notice, this list of conditions and the following
1315
+ disclaimers in the documentation and/or other materials provided
1316
+ with the distribution.
1317
+ * Neither the names of IMPACT Group, University of Illinois, nor
1318
+ the names of its contributors may be used to endorse or promote
1319
+ products derived from this Software without specific prior
1320
+ written permission.
1321
+
1322
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1323
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1324
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1325
+ NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
1326
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
1327
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1328
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
1329
+ SOFTWARE.
1330
+
1331
+ 12. Some of the cuRAND library routines were written by or
1332
+ derived from code written by Mutsuo Saito and Makoto
1333
+ Matsumoto and are subject to the following license:
1334
+
1335
+ Copyright (c) 2009, 2010 Mutsuo Saito, Makoto Matsumoto and Hiroshima
1336
+ University. All rights reserved.
1337
+
1338
+ Copyright (c) 2011 Mutsuo Saito, Makoto Matsumoto, Hiroshima
1339
+ University and University of Tokyo. All rights reserved.
1340
+
1341
+ Redistribution and use in source and binary forms, with or without
1342
+ modification, are permitted provided that the following conditions are
1343
+ met:
1344
+ * Redistributions of source code must retain the above copyright
1345
+ notice, this list of conditions and the following disclaimer.
1346
+ * Redistributions in binary form must reproduce the above
1347
+ copyright notice, this list of conditions and the following
1348
+ disclaimer in the documentation and/or other materials provided
1349
+ with the distribution.
1350
+ * Neither the name of the Hiroshima University nor the names of
1351
+ its contributors may be used to endorse or promote products
1352
+ derived from this software without specific prior written
1353
+ permission.
1354
+
1355
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1356
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1357
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1358
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1359
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1360
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1361
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1362
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1363
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1364
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1365
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1366
+
1367
+ 13. Some of the cuRAND library routines were derived from
1368
+ code developed by D. E. Shaw Research and are subject to
1369
+ the following license:
1370
+
1371
+ Copyright 2010-2011, D. E. Shaw Research.
1372
+
1373
+ All rights reserved.
1374
+
1375
+ Redistribution and use in source and binary forms, with or without
1376
+ modification, are permitted provided that the following conditions are
1377
+ met:
1378
+ * Redistributions of source code must retain the above copyright
1379
+ notice, this list of conditions, and the following disclaimer.
1380
+ * Redistributions in binary form must reproduce the above
1381
+ copyright notice, this list of conditions, and the following
1382
+ disclaimer in the documentation and/or other materials provided
1383
+ with the distribution.
1384
+ * Neither the name of D. E. Shaw Research nor the names of its
1385
+ contributors may be used to endorse or promote products derived
1386
+ from this software without specific prior written permission.
1387
+
1388
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1389
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1390
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1391
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1392
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1393
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1394
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1395
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1396
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1397
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1398
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1399
+
1400
+ 14. Some of the Math library routines were written by or
1401
+ derived from code developed by Norbert Juffa and are
1402
+ subject to the following license:
1403
+
1404
+ Copyright (c) 2015-2017, Norbert Juffa
1405
+ All rights reserved.
1406
+
1407
+ Redistribution and use in source and binary forms, with or without
1408
+ modification, are permitted provided that the following conditions
1409
+ are met:
1410
+
1411
+ 1. Redistributions of source code must retain the above copyright
1412
+ notice, this list of conditions and the following disclaimer.
1413
+
1414
+ 2. Redistributions in binary form must reproduce the above copyright
1415
+ notice, this list of conditions and the following disclaimer in the
1416
+ documentation and/or other materials provided with the distribution.
1417
+
1418
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1419
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1420
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1421
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1422
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1423
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1424
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1425
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1426
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1427
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1428
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1429
+
1430
+ 15. Licensee's use of the lz4 third party component is
1431
+ subject to the following terms and conditions:
1432
+
1433
+ Copyright (C) 2011-2013, Yann Collet.
1434
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
1435
+
1436
+ Redistribution and use in source and binary forms, with or without
1437
+ modification, are permitted provided that the following conditions are
1438
+ met:
1439
+
1440
+ * Redistributions of source code must retain the above copyright
1441
+ notice, this list of conditions and the following disclaimer.
1442
+ * Redistributions in binary form must reproduce the above
1443
+ copyright notice, this list of conditions and the following disclaimer
1444
+ in the documentation and/or other materials provided with the
1445
+ distribution.
1446
+
1447
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1448
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1449
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1450
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1451
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1452
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1453
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1454
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1455
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1456
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1457
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1458
+
1459
+ 16. The NPP library uses code from the Boost Math Toolkit,
1460
+ and is subject to the following license:
1461
+
1462
+ Boost Software License - Version 1.0 - August 17th, 2003
1463
+ . . . .
1464
+
1465
+ Permission is hereby granted, free of charge, to any person or
1466
+ organization obtaining a copy of the software and accompanying
1467
+ documentation covered by this license (the "Software") to use,
1468
+ reproduce, display, distribute, execute, and transmit the Software,
1469
+ and to prepare derivative works of the Software, and to permit
1470
+ third-parties to whom the Software is furnished to do so, all
1471
+ subject to the following:
1472
+
1473
+ The copyright notices in the Software and this entire statement,
1474
+ including the above license grant, this restriction and the following
1475
+ disclaimer, must be included in all copies of the Software, in whole
1476
+ or in part, and all derivative works of the Software, unless such
1477
+ copies or derivative works are solely in the form of machine-executable
1478
+ object code generated by a source language processor.
1479
+
1480
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1481
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1482
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1483
+ NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
1484
+ ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
1485
+ OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
1486
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1487
+ OTHER DEALINGS IN THE SOFTWARE.
1488
+
1489
+ 17. Portions of the Nsight Eclipse Edition is subject to the
1490
+ following license:
1491
+
1492
+ The Eclipse Foundation makes available all content in this plug-in
1493
+ ("Content"). Unless otherwise indicated below, the Content is provided
1494
+ to you under the terms and conditions of the Eclipse Public License
1495
+ Version 1.0 ("EPL"). A copy of the EPL is available at http://
1496
+ www.eclipse.org/legal/epl-v10.html. For purposes of the EPL, "Program"
1497
+ will mean the Content.
1498
+
1499
+ If you did not receive this Content directly from the Eclipse
1500
+ Foundation, the Content is being redistributed by another party
1501
+ ("Redistributor") and different terms and conditions may apply to your
1502
+ use of any object code in the Content. Check the Redistributor's
1503
+ license that was provided with the Content. If no such license exists,
1504
+ contact the Redistributor. Unless otherwise indicated below, the terms
1505
+ and conditions of the EPL still apply to any source code in the
1506
+ Content and such source code may be obtained at http://www.eclipse.org.
1507
+
1508
+ 18. Some of the cuBLAS library routines uses code from
1509
+ OpenAI, which is subject to the following license:
1510
+
1511
+ License URL
1512
+ https://github.com/openai/openai-gemm/blob/master/LICENSE
1513
+
1514
+ License Text
1515
+ The MIT License
1516
+
1517
+ Copyright (c) 2016 OpenAI (http://openai.com), 2016 Google Inc.
1518
+
1519
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1520
+ of this software and associated documentation files (the "Software"), to deal
1521
+ in the Software without restriction, including without limitation the rights
1522
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1523
+ copies of the Software, and to permit persons to whom the Software is
1524
+ furnished to do so, subject to the following conditions:
1525
+
1526
+ The above copyright notice and this permission notice shall be included in
1527
+ all copies or substantial portions of the Software.
1528
+
1529
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1530
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1531
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1532
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1533
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1534
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1535
+ THE SOFTWARE.
1536
+
1537
+ 19. Licensee's use of the Visual Studio Setup Configuration
1538
+ Samples is subject to the following license:
1539
+
1540
+ The MIT License (MIT)
1541
+ Copyright (C) Microsoft Corporation. All rights reserved.
1542
+
1543
+ Permission is hereby granted, free of charge, to any person
1544
+ obtaining a copy of this software and associated documentation
1545
+ files (the "Software"), to deal in the Software without restriction,
1546
+ including without limitation the rights to use, copy, modify, merge,
1547
+ publish, distribute, sublicense, and/or sell copies of the Software,
1548
+ and to permit persons to whom the Software is furnished to do so,
1549
+ subject to the following conditions:
1550
+
1551
+ The above copyright notice and this permission notice shall be included
1552
+ in all copies or substantial portions of the Software.
1553
+
1554
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1555
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1556
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1557
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1558
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1559
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1560
+
1561
+ 20. Licensee's use of linmath.h header for CPU functions for
1562
+ GL vector/matrix operations from lunarG is subject to the
1563
+ Apache License Version 2.0.
1564
+
1565
+ 21. The DX12-CUDA sample uses the d3dx12.h header, which is
1566
+ subject to the MIT license .
1567
+
1568
+ -----------------
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/METADATA ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.2
2
+ Name: nvidia-cusolver-cu12
3
+ Version: 11.7.3.90
4
+ Summary: CUDA solver native runtime libraries
5
+ Home-page: https://developer.nvidia.com/cuda-zone
6
+ Author: Nvidia CUDA Installer Team
7
+ Author-email: compute_installer@nvidia.com
8
+ License: NVIDIA Proprietary Software
9
+ Keywords: cuda,nvidia,runtime,machine learning,deep learning
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Education
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: Other/Proprietary License
15
+ Classifier: Natural Language :: English
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.5
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Classifier: Programming Language :: Python :: 3.7
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Topic :: Scientific/Engineering
26
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
27
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
28
+ Classifier: Topic :: Software Development
29
+ Classifier: Topic :: Software Development :: Libraries
30
+ Classifier: Operating System :: Microsoft :: Windows
31
+ Classifier: Operating System :: POSIX :: Linux
32
+ Requires-Python: >=3
33
+ License-File: License.txt
34
+ Requires-Dist: nvidia-cublas-cu12
35
+ Requires-Dist: nvidia-nvjitlink-cu12
36
+ Requires-Dist: nvidia-cusparse-cu12
37
+ Dynamic: author
38
+ Dynamic: author-email
39
+ Dynamic: classifier
40
+ Dynamic: description
41
+ Dynamic: home-page
42
+ Dynamic: keywords
43
+ Dynamic: license
44
+ Dynamic: requires-dist
45
+ Dynamic: requires-python
46
+ Dynamic: summary
47
+
48
+ CUDA solver native runtime libraries
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/RECORD ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ nvidia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ nvidia/__pycache__/__init__.cpython-312.pyc,,
3
+ nvidia/cusolver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ nvidia/cusolver/__pycache__/__init__.cpython-312.pyc,,
5
+ nvidia/cusolver/include/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ nvidia/cusolver/include/__pycache__/__init__.cpython-312.pyc,,
7
+ nvidia/cusolver/include/cusolverDn.h,sha256=BqiXh-sSll7KxwhjqSuVJvSDxeByqj2xfAK0KyoG3Ks,152029
8
+ nvidia/cusolver/include/cusolverMg.h,sha256=N8989nnS2BleeMyuftbQgBDJ4sMAkLPSnmy_S_7fxng,11549
9
+ nvidia/cusolver/include/cusolverRf.h,sha256=4FN6o6FYml09pS4p-YT5JKbwgZqKLEtf9tQZr50yZo4,14535
10
+ nvidia/cusolver/include/cusolverSp.h,sha256=SzIH2Gt36f_caN1wjF8PnCwYLhwsfJ63n1MPIc0_Ams,32885
11
+ nvidia/cusolver/include/cusolverSp_LOWLEVEL_PREVIEW.h,sha256=mmmXuX_glHBdpgTzIqhXkLMz9UCxxC1uQTbcKA1W6UI,39169
12
+ nvidia/cusolver/include/cusolver_common.h,sha256=k5hHZEZcoxxkTFqbKJWKGuxuHLaSRwWIvYdgvQJ0bdw,8732
13
+ nvidia/cusolver/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ nvidia/cusolver/lib/__pycache__/__init__.cpython-312.pyc,,
15
+ nvidia/cusolver/lib/libcusolver.so.11,sha256=tkuDi_Pi8nNzpZMSr_c6X7fkUjAMQEjbNTp_MNAJodc,243303872
16
+ nvidia/cusolver/lib/libcusolverMg.so.11,sha256=2UdlRjHFNukJmrzJ_lUezpfQ_-uPurFCGJ6iyFvFXo4,161493576
17
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
18
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/License.txt,sha256=rW9YU_ugyg0VnQ9Y1JrkmDDC-Mk_epJki5zpCttMbM0,59262
19
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/METADATA,sha256=HwalXcjyrvnrIPAYBEv6dzESRpi6e0NdEcJQxi6vTcM,1826
20
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/RECORD,,
21
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/WHEEL,sha256=VtFLEVB-VX8niQT4kQ5pcQOOqiKvUvqfZe5V14HmU88,109
22
+ nvidia_cusolver_cu12-11.7.3.90.dist-info/top_level.txt,sha256=fTkAtiFuL16nUrB9ytDDtpytz2t0B4NvYTnRzwAhO14,7
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/WHEEL ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.8.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-manylinux_2_27_x86_64
5
+
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_cusolver_cu12-11.7.3.90.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ nvidia
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/__init__.py ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ __version__ = "0.18.1"
16
+
17
+ from .auto import (
18
+ MODEL_TYPE_TO_PEFT_MODEL_MAPPING,
19
+ AutoPeftModel,
20
+ AutoPeftModelForCausalLM,
21
+ AutoPeftModelForFeatureExtraction,
22
+ AutoPeftModelForQuestionAnswering,
23
+ AutoPeftModelForSeq2SeqLM,
24
+ AutoPeftModelForSequenceClassification,
25
+ AutoPeftModelForTokenClassification,
26
+ )
27
+ from .config import PeftConfig, PromptLearningConfig
28
+ from .mapping import (
29
+ PEFT_TYPE_TO_CONFIG_MAPPING,
30
+ PEFT_TYPE_TO_MIXED_MODEL_MAPPING,
31
+ PEFT_TYPE_TO_TUNER_MAPPING,
32
+ get_peft_config,
33
+ inject_adapter_in_model,
34
+ )
35
+ from .mapping_func import get_peft_model
36
+ from .mixed_model import PeftMixedModel
37
+ from .peft_model import (
38
+ PeftModel,
39
+ PeftModelForCausalLM,
40
+ PeftModelForFeatureExtraction,
41
+ PeftModelForQuestionAnswering,
42
+ PeftModelForSeq2SeqLM,
43
+ PeftModelForSequenceClassification,
44
+ PeftModelForTokenClassification,
45
+ get_layer_status,
46
+ get_model_status,
47
+ )
48
+ from .tuners import (
49
+ AdaLoraConfig,
50
+ AdaLoraModel,
51
+ AdaptionPromptConfig,
52
+ AdaptionPromptModel,
53
+ ArrowConfig,
54
+ BOFTConfig,
55
+ BOFTModel,
56
+ BoneConfig,
57
+ BoneModel,
58
+ C3AConfig,
59
+ C3AModel,
60
+ CPTConfig,
61
+ CPTEmbedding,
62
+ DeloraConfig,
63
+ DeloraModel,
64
+ EvaConfig,
65
+ FourierFTConfig,
66
+ FourierFTModel,
67
+ HRAConfig,
68
+ HRAModel,
69
+ IA3Config,
70
+ IA3Model,
71
+ LNTuningConfig,
72
+ LNTuningModel,
73
+ LoftQConfig,
74
+ LoHaConfig,
75
+ LoHaModel,
76
+ LoKrConfig,
77
+ LoKrModel,
78
+ LoraConfig,
79
+ LoraModel,
80
+ LoraRuntimeConfig,
81
+ MissConfig,
82
+ MissModel,
83
+ MultitaskPromptTuningConfig,
84
+ MultitaskPromptTuningInit,
85
+ OFTConfig,
86
+ OFTModel,
87
+ OSFConfig,
88
+ OSFModel,
89
+ PolyConfig,
90
+ PolyModel,
91
+ PrefixEncoder,
92
+ PrefixTuningConfig,
93
+ PromptEmbedding,
94
+ PromptEncoder,
95
+ PromptEncoderConfig,
96
+ PromptEncoderReparameterizationType,
97
+ PromptTuningConfig,
98
+ PromptTuningInit,
99
+ RandLoraConfig,
100
+ RandLoraModel,
101
+ RoadConfig,
102
+ RoadModel,
103
+ ShiraConfig,
104
+ ShiraModel,
105
+ TrainableTokensConfig,
106
+ TrainableTokensModel,
107
+ VBLoRAConfig,
108
+ VBLoRAModel,
109
+ VeraConfig,
110
+ VeraModel,
111
+ WaveFTConfig,
112
+ WaveFTModel,
113
+ XLoraConfig,
114
+ XLoraModel,
115
+ create_arrow_model,
116
+ get_eva_state_dict,
117
+ initialize_lora_eva_weights,
118
+ )
119
+ from .utils import (
120
+ TRANSFORMERS_MODELS_TO_PREFIX_TUNING_POSTPROCESS_MAPPING,
121
+ PeftType,
122
+ PeftWarning,
123
+ TaskType,
124
+ bloom_model_postprocess_past_key_value,
125
+ cast_mixed_precision_params,
126
+ get_peft_model_state_dict,
127
+ load_peft_weights,
128
+ prepare_model_for_kbit_training,
129
+ replace_lora_weights_loftq,
130
+ set_peft_model_state_dict,
131
+ shift_tokens_right,
132
+ )
133
+
134
+
135
+ __all__ = [
136
+ "MODEL_TYPE_TO_PEFT_MODEL_MAPPING",
137
+ "PEFT_TYPE_TO_CONFIG_MAPPING",
138
+ "PEFT_TYPE_TO_MIXED_MODEL_MAPPING",
139
+ "PEFT_TYPE_TO_TUNER_MAPPING",
140
+ "TRANSFORMERS_MODELS_TO_PREFIX_TUNING_POSTPROCESS_MAPPING",
141
+ "AdaLoraConfig",
142
+ "AdaLoraModel",
143
+ "AdaptionPromptConfig",
144
+ "AdaptionPromptModel",
145
+ "ArrowConfig",
146
+ "AutoPeftModel",
147
+ "AutoPeftModelForCausalLM",
148
+ "AutoPeftModelForFeatureExtraction",
149
+ "AutoPeftModelForQuestionAnswering",
150
+ "AutoPeftModelForSeq2SeqLM",
151
+ "AutoPeftModelForSequenceClassification",
152
+ "AutoPeftModelForTokenClassification",
153
+ "BOFTConfig",
154
+ "BOFTModel",
155
+ "BoneConfig",
156
+ "BoneModel",
157
+ "C3AConfig",
158
+ "C3AModel",
159
+ "CPTConfig",
160
+ "CPTEmbedding",
161
+ "DeloraConfig",
162
+ "DeloraModel",
163
+ "EvaConfig",
164
+ "FourierFTConfig",
165
+ "FourierFTModel",
166
+ "HRAConfig",
167
+ "HRAModel",
168
+ "IA3Config",
169
+ "IA3Model",
170
+ "LNTuningConfig",
171
+ "LNTuningModel",
172
+ "LoHaConfig",
173
+ "LoHaModel",
174
+ "LoKrConfig",
175
+ "LoKrModel",
176
+ "LoftQConfig",
177
+ "LoraConfig",
178
+ "LoraModel",
179
+ "LoraRuntimeConfig",
180
+ "MissConfig",
181
+ "MissModel",
182
+ "MultitaskPromptTuningConfig",
183
+ "MultitaskPromptTuningInit",
184
+ "OFTConfig",
185
+ "OFTModel",
186
+ "OSFConfig",
187
+ "OSFModel",
188
+ "PeftConfig",
189
+ "PeftMixedModel",
190
+ "PeftModel",
191
+ "PeftModelForCausalLM",
192
+ "PeftModelForFeatureExtraction",
193
+ "PeftModelForQuestionAnswering",
194
+ "PeftModelForSeq2SeqLM",
195
+ "PeftModelForSequenceClassification",
196
+ "PeftModelForTokenClassification",
197
+ "PeftType",
198
+ "PeftWarning",
199
+ "PolyConfig",
200
+ "PolyModel",
201
+ "PrefixEncoder",
202
+ "PrefixTuningConfig",
203
+ "PromptEmbedding",
204
+ "PromptEncoder",
205
+ "PromptEncoderConfig",
206
+ "PromptEncoderReparameterizationType",
207
+ "PromptLearningConfig",
208
+ "PromptTuningConfig",
209
+ "PromptTuningInit",
210
+ "RandLoraConfig",
211
+ "RandLoraModel",
212
+ "RoadConfig",
213
+ "RoadModel",
214
+ "ShiraConfig",
215
+ "ShiraModel",
216
+ "TaskType",
217
+ "TrainableTokensConfig",
218
+ "TrainableTokensModel",
219
+ "VBLoRAConfig",
220
+ "VBLoRAConfig",
221
+ "VBLoRAModel",
222
+ "VeraConfig",
223
+ "VeraModel",
224
+ "WaveFTConfig",
225
+ "WaveFTModel",
226
+ "XLoraConfig",
227
+ "XLoraModel",
228
+ "bloom_model_postprocess_past_key_value",
229
+ "cast_mixed_precision_params",
230
+ "create_arrow_model",
231
+ "get_eva_state_dict",
232
+ "get_layer_status",
233
+ "get_model_status",
234
+ "get_peft_config",
235
+ "get_peft_model",
236
+ "get_peft_model_state_dict",
237
+ "initialize_lora_eva_weights",
238
+ "inject_adapter_in_model",
239
+ "load_peft_weights",
240
+ "prepare_model_for_kbit_training",
241
+ "replace_lora_weights_loftq",
242
+ "set_peft_model_state_dict",
243
+ "shift_tokens_right",
244
+ ]
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/auto.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import importlib
18
+ import os
19
+ from typing import Optional
20
+
21
+ from transformers import (
22
+ AutoModel,
23
+ AutoModelForCausalLM,
24
+ AutoModelForQuestionAnswering,
25
+ AutoModelForSeq2SeqLM,
26
+ AutoModelForSequenceClassification,
27
+ AutoModelForTokenClassification,
28
+ AutoTokenizer,
29
+ )
30
+
31
+ from .config import PeftConfig
32
+ from .peft_model import (
33
+ PeftModel,
34
+ PeftModelForCausalLM,
35
+ PeftModelForFeatureExtraction,
36
+ PeftModelForQuestionAnswering,
37
+ PeftModelForSeq2SeqLM,
38
+ PeftModelForSequenceClassification,
39
+ PeftModelForTokenClassification,
40
+ )
41
+ from .utils.constants import TOKENIZER_CONFIG_NAME
42
+ from .utils.other import check_file_exists_on_hf_hub
43
+
44
+
45
+ MODEL_TYPE_TO_PEFT_MODEL_MAPPING: dict[str, type[PeftModel]] = {
46
+ "SEQ_CLS": PeftModelForSequenceClassification,
47
+ "SEQ_2_SEQ_LM": PeftModelForSeq2SeqLM,
48
+ "CAUSAL_LM": PeftModelForCausalLM,
49
+ "TOKEN_CLS": PeftModelForTokenClassification,
50
+ "QUESTION_ANS": PeftModelForQuestionAnswering,
51
+ "FEATURE_EXTRACTION": PeftModelForFeatureExtraction,
52
+ }
53
+
54
+
55
+ class _BaseAutoPeftModel:
56
+ _target_class = None
57
+ _target_peft_class = None
58
+
59
+ def __init__(self, *args, **kwargs):
60
+ # For consistency with transformers: https://github.com/huggingface/transformers/blob/91d7df58b6537d385e90578dac40204cb550f706/src/transformers/models/auto/auto_factory.py#L400
61
+ raise EnvironmentError( # noqa: UP024
62
+ f"{self.__class__.__name__} is designed to be instantiated "
63
+ f"using the `{self.__class__.__name__}.from_pretrained(pretrained_model_name_or_path)` or "
64
+ f"`{self.__class__.__name__}.from_config(config)` methods."
65
+ )
66
+
67
+ @classmethod
68
+ def from_pretrained(
69
+ cls,
70
+ pretrained_model_name_or_path,
71
+ adapter_name: str = "default",
72
+ is_trainable: bool = False,
73
+ config: Optional[PeftConfig] = None,
74
+ revision: Optional[str] = None,
75
+ **kwargs,
76
+ ):
77
+ r"""
78
+ A wrapper around all the preprocessing steps a user needs to perform in order to load a PEFT model. The kwargs
79
+ are passed along to `PeftConfig` that automatically takes care of filtering the kwargs of the Hub methods and
80
+ the config object init.
81
+ """
82
+ peft_config = PeftConfig.from_pretrained(pretrained_model_name_or_path, revision=revision, **kwargs)
83
+ base_model_path = peft_config.base_model_name_or_path
84
+ base_model_revision = peft_config.revision
85
+
86
+ task_type = getattr(peft_config, "task_type", None)
87
+
88
+ if cls._target_class is not None:
89
+ target_class = cls._target_class
90
+ elif cls._target_class is None and task_type is not None:
91
+ # this is only in the case where we use `AutoPeftModel`
92
+ raise ValueError(
93
+ "Cannot use `AutoPeftModel` with a task type, please use a specific class for your task type. (e.g. `AutoPeftModelForCausalLM` for `task_type='CAUSAL_LM'`)"
94
+ )
95
+
96
+ if task_type is not None:
97
+ expected_target_class = MODEL_TYPE_TO_PEFT_MODEL_MAPPING[task_type]
98
+ if cls._target_peft_class.__name__ != expected_target_class.__name__:
99
+ raise ValueError(
100
+ f"Expected target PEFT class: {expected_target_class.__name__}, but you have asked for: {cls._target_peft_class.__name__}"
101
+ " make sure that you are loading the correct model for your task type."
102
+ )
103
+ elif task_type is None and getattr(peft_config, "auto_mapping", None) is not None:
104
+ auto_mapping = getattr(peft_config, "auto_mapping", None)
105
+ base_model_class = auto_mapping["base_model_class"]
106
+ parent_library_name = auto_mapping["parent_library"]
107
+
108
+ parent_library = importlib.import_module(parent_library_name)
109
+ target_class = getattr(parent_library, base_model_class)
110
+ else:
111
+ raise ValueError(
112
+ "Cannot infer the auto class from the config, please make sure that you are loading the correct model for your task type."
113
+ )
114
+
115
+ base_model = target_class.from_pretrained(base_model_path, revision=base_model_revision, **kwargs)
116
+
117
+ tokenizer_exists = False
118
+ if os.path.exists(os.path.join(pretrained_model_name_or_path, TOKENIZER_CONFIG_NAME)):
119
+ tokenizer_exists = True
120
+ else:
121
+ token = kwargs.get("token", None)
122
+ if token is None:
123
+ token = kwargs.get("use_auth_token", None)
124
+
125
+ tokenizer_exists = check_file_exists_on_hf_hub(
126
+ repo_id=pretrained_model_name_or_path,
127
+ filename=TOKENIZER_CONFIG_NAME,
128
+ revision=revision,
129
+ repo_type=kwargs.get("repo_type", None),
130
+ token=token,
131
+ )
132
+
133
+ if tokenizer_exists and hasattr(base_model, "get_input_embeddings"):
134
+ tokenizer = AutoTokenizer.from_pretrained(
135
+ pretrained_model_name_or_path, trust_remote_code=kwargs.get("trust_remote_code", False)
136
+ )
137
+ embedding_size = base_model.get_input_embeddings().weight.shape[0]
138
+ if len(tokenizer) > embedding_size:
139
+ # only resize if the tokenizer has a larger vocab size than there are embeddings
140
+ base_model.resize_token_embeddings(len(tokenizer))
141
+
142
+ return cls._target_peft_class.from_pretrained(
143
+ base_model,
144
+ pretrained_model_name_or_path,
145
+ adapter_name=adapter_name,
146
+ is_trainable=is_trainable,
147
+ config=config,
148
+ **kwargs,
149
+ )
150
+
151
+
152
+ class AutoPeftModel(_BaseAutoPeftModel):
153
+ _target_class = None
154
+ _target_peft_class = PeftModel
155
+
156
+
157
+ class AutoPeftModelForCausalLM(_BaseAutoPeftModel):
158
+ _target_class = AutoModelForCausalLM
159
+ _target_peft_class = PeftModelForCausalLM
160
+
161
+
162
+ class AutoPeftModelForSeq2SeqLM(_BaseAutoPeftModel):
163
+ _target_class = AutoModelForSeq2SeqLM
164
+ _target_peft_class = PeftModelForSeq2SeqLM
165
+
166
+
167
+ class AutoPeftModelForSequenceClassification(_BaseAutoPeftModel):
168
+ _target_class = AutoModelForSequenceClassification
169
+ _target_peft_class = PeftModelForSequenceClassification
170
+
171
+
172
+ class AutoPeftModelForTokenClassification(_BaseAutoPeftModel):
173
+ _target_class = AutoModelForTokenClassification
174
+ _target_peft_class = PeftModelForTokenClassification
175
+
176
+
177
+ class AutoPeftModelForQuestionAnswering(_BaseAutoPeftModel):
178
+ _target_class = AutoModelForQuestionAnswering
179
+ _target_peft_class = PeftModelForQuestionAnswering
180
+
181
+
182
+ class AutoPeftModelForFeatureExtraction(_BaseAutoPeftModel):
183
+ _target_class = AutoModel
184
+ _target_peft_class = PeftModelForFeatureExtraction
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/config.py ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from __future__ import annotations
15
+
16
+ import importlib.metadata
17
+ import inspect
18
+ import json
19
+ import os
20
+ import warnings
21
+ from dataclasses import asdict, dataclass, field
22
+ from typing import Optional, Union
23
+
24
+ import packaging.version
25
+ from huggingface_hub import hf_hub_download
26
+ from transformers.utils import PushToHubMixin, http_user_agent
27
+
28
+ from peft import __version__
29
+
30
+ from .utils import CONFIG_NAME, PeftType, TaskType
31
+
32
+
33
+ # we expect at least these keys to be present in a PEFT adapter_config.json
34
+ MIN_EXPECTED_CONFIG_KEYS = {"peft_type"}
35
+
36
+
37
+ def _check_and_remove_unused_kwargs(cls, kwargs):
38
+ """Make PEFT configs forward-compatible by removing unused kwargs that were added in later PEFT versions.
39
+
40
+ This assumes that removing the unused kwargs will not affect the default behavior.
41
+
42
+ Returns the filtered kwargs and the set of removed keys.
43
+ """
44
+ # it's not pretty but eh
45
+ signature_parameters = inspect.signature(cls.__init__).parameters
46
+ unexpected_kwargs = set(kwargs.keys()) - set(signature_parameters.keys())
47
+ for key in unexpected_kwargs:
48
+ del kwargs[key]
49
+ return kwargs, unexpected_kwargs
50
+
51
+
52
+ def _is_dev_version(version: str) -> bool:
53
+ # check if the given version is a dev version
54
+ return packaging.version.Version(version).dev is not None
55
+
56
+
57
+ def _get_commit_hash(pkg_name: str) -> str | None:
58
+ # If PEFT was installed from a specific commit hash, try to get it. This works e.g. when installing PEFT with `pip
59
+ # install git+https://github.com/huggingface/peft.git@<HASH>`. This works not for other means, like editable
60
+ # installs.
61
+ try:
62
+ dist = importlib.metadata.distribution(pkg_name)
63
+ except importlib.metadata.PackageNotFoundError:
64
+ return None
65
+
66
+ # See: https://packaging.python.org/en/latest/specifications/direct-url/
67
+ for path in dist.files or []:
68
+ if path.name == "direct_url.json":
69
+ direct_url = json.loads((dist.locate_file(path)).read_text())
70
+ vcs_info = direct_url.get("vcs_info")
71
+ if vcs_info and "commit_id" in vcs_info:
72
+ return vcs_info["commit_id"]
73
+ return None
74
+
75
+
76
+ @dataclass
77
+ class PeftConfigMixin(PushToHubMixin):
78
+ r"""
79
+ This is the base configuration class for PEFT adapter models. It contains all the methods that are common to all
80
+ PEFT adapter models. This class inherits from [`~transformers.utils.PushToHubMixin`] which contains the methods to
81
+ push your model to the Hub. The method `save_pretrained` will save the configuration of your adapter model in a
82
+ directory. The method `from_pretrained` will load the configuration of your adapter model from a directory.
83
+
84
+ Args:
85
+ peft_type (Union[[`~peft.utils.config.PeftType`], `str`]): The type of Peft method to use.
86
+ """
87
+
88
+ task_type: Optional[TaskType] = field(default=None, metadata={"help": "The type of task."})
89
+ peft_type: Optional[PeftType] = field(default=None, metadata={"help": "The type of PEFT model."})
90
+ auto_mapping: Optional[dict] = field(
91
+ default=None, metadata={"help": "An auto mapping dict to help retrieve the base model class if needed."}
92
+ )
93
+ peft_version: Optional[str] = field(default=None, metadata={"help": "PEFT version, leave empty to auto-fill."})
94
+
95
+ def __post_init__(self):
96
+ # check for invalid task type
97
+ if (self.task_type is not None) and (self.task_type not in list(TaskType)):
98
+ raise ValueError(
99
+ f"Invalid task type: '{self.task_type}'. Must be one of the following task types: {', '.join(TaskType)}."
100
+ )
101
+ if self.peft_version is None:
102
+ self.peft_version = self._get_peft_version()
103
+
104
+ @staticmethod
105
+ def _get_peft_version() -> str:
106
+ # gets the current peft version; if it's a dev version, try to get the commit hash too, as the dev version is
107
+ # ambiguous
108
+ version = __version__
109
+ if not _is_dev_version(version):
110
+ return version
111
+
112
+ try:
113
+ git_hash = _get_commit_hash("peft")
114
+ if git_hash is None:
115
+ git_hash = "UNKNOWN"
116
+ except Exception:
117
+ # Broad exception: We never want to break user code just because the git_hash could not be determined
118
+ warnings.warn(
119
+ "A dev version of PEFT is used but there was an error while trying to determine the commit hash. "
120
+ "Please open an issue: https://github.com/huggingface/peft/issues"
121
+ )
122
+ git_hash = "UNKNOWN"
123
+ version = version + f"@{git_hash}"
124
+ return version
125
+
126
+ def to_dict(self) -> dict:
127
+ r"""
128
+ Returns the configuration for your adapter model as a dictionary.
129
+ """
130
+ return asdict(self)
131
+
132
+ def save_pretrained(self, save_directory: str, **kwargs) -> None:
133
+ r"""
134
+ This method saves the configuration of your adapter model in a directory.
135
+
136
+ Args:
137
+ save_directory (`str`):
138
+ The directory where the configuration will be saved.
139
+ kwargs (additional keyword arguments, *optional*):
140
+ Additional keyword arguments passed along to the [`~transformers.utils.PushToHubMixin.push_to_hub`]
141
+ method.
142
+ """
143
+ if os.path.isfile(save_directory):
144
+ raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")
145
+
146
+ os.makedirs(save_directory, exist_ok=True)
147
+ auto_mapping_dict = kwargs.pop("auto_mapping_dict", None)
148
+
149
+ output_dict = self.to_dict()
150
+ # converting set type to list
151
+ for key, value in output_dict.items():
152
+ if isinstance(value, set):
153
+ output_dict[key] = list(value)
154
+
155
+ output_path = os.path.join(save_directory, CONFIG_NAME)
156
+
157
+ # Add auto mapping details for custom models.
158
+ if auto_mapping_dict is not None:
159
+ output_dict["auto_mapping"] = auto_mapping_dict
160
+
161
+ # save it
162
+ with open(output_path, "w") as writer:
163
+ writer.write(json.dumps(output_dict, indent=2, sort_keys=True))
164
+
165
+ @classmethod
166
+ def from_peft_type(cls, **kwargs):
167
+ r"""
168
+ This method loads the configuration of your adapter model from a set of kwargs.
169
+
170
+ The appropriate configuration type is determined by the `peft_type` argument. If `peft_type` is not provided,
171
+ the calling class type is instantiated.
172
+
173
+ Args:
174
+ kwargs (configuration keyword arguments):
175
+ Keyword arguments passed along to the configuration initialization.
176
+ """
177
+ # Avoid circular dependency .. TODO: fix this with a larger refactor
178
+ from peft.mapping import PEFT_TYPE_TO_CONFIG_MAPPING
179
+
180
+ # TODO: this hack is needed to fix the following issue (on commit 702f937):
181
+ # if someone saves a default config and loads it back with `PeftConfig` class it yields to
182
+ # not loading the correct config class.
183
+ #
184
+ # from peft import AdaLoraConfig, PeftConfig
185
+ # peft_config = AdaLoraConfig()
186
+ # print(peft_config)
187
+ # >>> AdaLoraConfig(peft_type=<PeftType.ADALORA: 'ADALORA'>, auto_mapping=None, base_model_name_or_path=None,
188
+ # revision=None, task_type=None, inference_mode=False, r=8, target_modules=None, lora_alpha=8, lora_dropout=0.0, ...
189
+ #
190
+ # peft_config.save_pretrained("./test_config")
191
+ # peft_config = PeftConfig.from_pretrained("./test_config")
192
+ # print(peft_config)
193
+ # >>> PeftConfig(peft_type='ADALORA', auto_mapping=None, base_model_name_or_path=None, revision=None, task_type=None, inference_mode=False)
194
+
195
+ if "peft_type" in kwargs:
196
+ peft_type = kwargs["peft_type"]
197
+ config_cls = PEFT_TYPE_TO_CONFIG_MAPPING[peft_type]
198
+ else:
199
+ config_cls = cls
200
+
201
+ try:
202
+ config = config_cls(**kwargs)
203
+ except TypeError as exc:
204
+ # Here we potentially handle forward compatibility. Sometimes new keywords are added to configs, which makes
205
+ # new configs incompatible with older PEFT versions. We catch these and remove them to allow the program to
206
+ # continue, but warn the user about it.
207
+
208
+ # First check if the error is due to unexpected keyword arguments, we don't want to accidentally catch
209
+ # other TypeErrors.
210
+ if "got an unexpected keyword argument" not in str(exc):
211
+ raise exc
212
+
213
+ filtered_kwargs, unexpected_kwargs = _check_and_remove_unused_kwargs(config_cls, kwargs)
214
+ if not MIN_EXPECTED_CONFIG_KEYS.issubset(set(filtered_kwargs.keys())):
215
+ raise TypeError(
216
+ f"The {cls.__name__} config that is trying to be loaded is missing required keys: "
217
+ f"{MIN_EXPECTED_CONFIG_KEYS}."
218
+ )
219
+
220
+ warnings.warn(
221
+ f"Unexpected keyword arguments {sorted(unexpected_kwargs)} for class {config_cls.__name__}, these are "
222
+ "ignored. This probably means that you're loading a configuration file that was saved using a "
223
+ "higher version of the library and additional parameters have been introduced since. It is "
224
+ "highly recommended to upgrade the PEFT version before continuing (e.g. by running `pip install "
225
+ "-U peft`)."
226
+ )
227
+ config = config_cls.from_peft_type(**filtered_kwargs)
228
+ return config
229
+
230
+ @classmethod
231
+ def from_pretrained(cls, pretrained_model_name_or_path: str, subfolder: Optional[str] = None, **kwargs):
232
+ r"""
233
+ This method loads the configuration of your adapter model from a directory.
234
+
235
+ Args:
236
+ pretrained_model_name_or_path (`str`):
237
+ The directory or the Hub repository id where the configuration is saved.
238
+ kwargs (additional keyword arguments, *optional*):
239
+ Additional keyword arguments passed along to the child class initialization.
240
+ """
241
+ path = (
242
+ os.path.join(pretrained_model_name_or_path, subfolder)
243
+ if subfolder is not None
244
+ else pretrained_model_name_or_path
245
+ )
246
+
247
+ hf_hub_download_kwargs, class_kwargs, _ = cls._split_kwargs(kwargs)
248
+ if "user_agent" not in hf_hub_download_kwargs:
249
+ hf_hub_download_kwargs["user_agent"] = http_user_agent()
250
+
251
+ if os.path.isfile(os.path.join(path, CONFIG_NAME)):
252
+ config_file = os.path.join(path, CONFIG_NAME)
253
+ else:
254
+ try:
255
+ config_file = hf_hub_download(
256
+ pretrained_model_name_or_path, CONFIG_NAME, subfolder=subfolder, **hf_hub_download_kwargs
257
+ )
258
+ except Exception as exc:
259
+ raise ValueError(f"Can't find '{CONFIG_NAME}' at '{pretrained_model_name_or_path}'") from exc
260
+
261
+ loaded_attributes = cls.from_json_file(config_file)
262
+ kwargs = {**class_kwargs, **loaded_attributes}
263
+ kwargs = cls.check_kwargs(**kwargs)
264
+ return cls.from_peft_type(**kwargs)
265
+
266
+ @classmethod
267
+ def from_json_file(cls, path_json_file: str, **kwargs):
268
+ r"""
269
+ Loads a configuration file from a json file.
270
+
271
+ Args:
272
+ path_json_file (`str`):
273
+ The path to the json file.
274
+ """
275
+ with open(path_json_file) as file:
276
+ json_object = json.load(file)
277
+
278
+ # Sanity check that config does not contain a runtime_config
279
+ if "runtime_config" in json_object:
280
+ warnings.warn(
281
+ "The configuration file contains a `runtime_config` key. This is ignored. Runtime configurations are only valid at runtime."
282
+ )
283
+ del json_object["runtime_config"]
284
+
285
+ return json_object
286
+
287
+ @classmethod
288
+ def _split_kwargs(cls, kwargs):
289
+ hf_hub_download_kwargs = {}
290
+ class_kwargs = {}
291
+ other_kwargs = {}
292
+
293
+ for key, value in kwargs.items():
294
+ if key in inspect.signature(hf_hub_download).parameters:
295
+ hf_hub_download_kwargs[key] = value
296
+ elif key in list(cls.__annotations__):
297
+ class_kwargs[key] = value
298
+ else:
299
+ other_kwargs[key] = value
300
+
301
+ return hf_hub_download_kwargs, class_kwargs, other_kwargs
302
+
303
+ @classmethod
304
+ def _get_peft_type(
305
+ cls,
306
+ model_id: str,
307
+ **hf_hub_download_kwargs,
308
+ ):
309
+ subfolder = hf_hub_download_kwargs.get("subfolder", None)
310
+
311
+ path = os.path.join(model_id, subfolder) if subfolder is not None else model_id
312
+
313
+ if os.path.isfile(os.path.join(path, CONFIG_NAME)):
314
+ config_file = os.path.join(path, CONFIG_NAME)
315
+ else:
316
+ try:
317
+ config_file = hf_hub_download(
318
+ model_id,
319
+ CONFIG_NAME,
320
+ **hf_hub_download_kwargs,
321
+ )
322
+ except Exception:
323
+ raise ValueError(f"Can't find '{CONFIG_NAME}' at '{model_id}'")
324
+
325
+ loaded_attributes = cls.from_json_file(config_file)
326
+ return loaded_attributes["peft_type"]
327
+
328
+ @classmethod
329
+ def check_kwargs(cls, **kwargs):
330
+ """Check kwargs before initializing the config instance.
331
+
332
+ Subclasses can override this method to add specific checks.
333
+
334
+ """
335
+ return kwargs
336
+
337
+ @property
338
+ def is_prompt_learning(self) -> bool:
339
+ r"""
340
+ Utility method to check if the configuration is for prompt learning.
341
+ """
342
+ return False
343
+
344
+ @property
345
+ def is_adaption_prompt(self) -> bool:
346
+ """Return True if this is an adaption prompt config."""
347
+ return False
348
+
349
+
350
+ @dataclass
351
+ class PeftConfig(PeftConfigMixin):
352
+ """
353
+ This is the base configuration class to store the configuration of a [`PeftModel`].
354
+
355
+ Args:
356
+ peft_type (Union[[`~peft.utils.config.PeftType`], `str`]): The type of Peft method to use.
357
+ task_type (Union[[`~peft.utils.config.TaskType`], `str`]): The type of task to perform.
358
+ inference_mode (`bool`, defaults to `False`): Whether to use the Peft model in inference mode.
359
+ """
360
+
361
+ base_model_name_or_path: Optional[str] = field(
362
+ default=None, metadata={"help": "The name of the base model to use."}
363
+ )
364
+ revision: Optional[str] = field(default=None, metadata={"help": "The specific base model version to use."})
365
+ peft_type: Optional[Union[str, PeftType]] = field(default=None, metadata={"help": "Peft type"})
366
+ task_type: Optional[Union[str, TaskType]] = field(default=None, metadata={"help": "Task type"})
367
+ inference_mode: bool = field(default=False, metadata={"help": "Whether to use inference mode"})
368
+
369
+
370
+ @dataclass
371
+ class PromptLearningConfig(PeftConfig):
372
+ """
373
+ This is the base configuration class to store the configuration of [`PrefixTuning`], [`PromptEncoder`], or
374
+ [`PromptTuning`].
375
+
376
+ Args:
377
+ num_virtual_tokens (`int`): The number of virtual tokens to use.
378
+ token_dim (`int`): The hidden embedding dimension of the base transformer model.
379
+ num_transformer_submodules (`int`): The number of transformer submodules in the base transformer model.
380
+ num_attention_heads (`int`): The number of attention heads in the base transformer model.
381
+ num_layers (`int`): The number of layers in the base transformer model.
382
+ """
383
+
384
+ num_virtual_tokens: int = field(default=None, metadata={"help": "Number of virtual tokens"})
385
+ token_dim: int = field(
386
+ default=None, metadata={"help": "The hidden embedding dimension of the base transformer model"}
387
+ )
388
+ num_transformer_submodules: Optional[int] = field(
389
+ default=None, metadata={"help": "Number of transformer submodules"}
390
+ )
391
+ num_attention_heads: Optional[int] = field(default=None, metadata={"help": "Number of attention heads"})
392
+ num_layers: Optional[int] = field(default=None, metadata={"help": "Number of transformer layers"})
393
+ modules_to_save: Optional[list[str]] = field(
394
+ default=None,
395
+ metadata={
396
+ "help": "List of extra modules to be set as trainable and saved in the final checkpoint. "
397
+ "For example, in Sequence Classification or Token Classification tasks, "
398
+ "the final layer `classifier/score` are randomly initialized and as such need to be trainable and saved. "
399
+ "The module(s) will be fully fine-tuned."
400
+ },
401
+ )
402
+
403
+ @property
404
+ def is_prompt_learning(self) -> bool:
405
+ r"""
406
+ Utility method to check if the configuration is for prompt learning.
407
+ """
408
+ return True
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/functional.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Functions that are useful for integration with non-PeftModel models, e.g. transformers or diffusers.
16
+
17
+ The functions provided here can be considered "public API" of PEFT and hence are safe to be used by packages that
18
+ provide PEFT integrations.
19
+ """
20
+
21
+ from peft.mapping import inject_adapter_in_model
22
+ from peft.tuners.tuners_utils import cast_adapter_dtype, delete_adapter, set_adapter, set_requires_grad
23
+ from peft.utils import get_peft_model_state_dict, set_peft_model_state_dict
24
+
25
+
26
+ __all__ = [
27
+ "cast_adapter_dtype",
28
+ "delete_adapter",
29
+ "get_peft_model_state_dict",
30
+ "inject_adapter_in_model",
31
+ "set_adapter",
32
+ "set_peft_model_state_dict",
33
+ "set_requires_grad",
34
+ ]
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/helpers.py ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import inspect
16
+ from contextlib import contextmanager
17
+ from copy import deepcopy
18
+ from functools import update_wrapper
19
+ from types import MethodType
20
+
21
+ from torch import nn
22
+
23
+ from .peft_model import PeftConfig, PeftModel
24
+ from .tuners.lora import LoraLayer
25
+ from .tuners.tuners_utils import BaseTunerLayer
26
+
27
+
28
+ def update_forward_signature(model: PeftModel) -> None:
29
+ """
30
+ Updates the forward signature of the PeftModel to include parents class signature
31
+ model (`PeftModel`): Peft model to update the forward signature
32
+
33
+ Example:
34
+
35
+ ```python
36
+ >>> from transformers import WhisperForConditionalGeneration
37
+ >>> from peft import get_peft_model, LoraConfig, update_forward_signature
38
+
39
+ >>> model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-tiny.en")
40
+ >>> peft_config = LoraConfig(r=8, lora_alpha=32, lora_dropout=0.1, target_modules=["q_proj", "v_proj"])
41
+
42
+ >>> peft_model = get_peft_model(model, peft_config)
43
+ >>> update_forward_signature(peft_model)
44
+ ```
45
+ """
46
+
47
+ # Only update signature when the current forward signature only has *args and **kwargs
48
+ current_signature = inspect.signature(model.forward)
49
+ if (
50
+ len(current_signature.parameters) == 2
51
+ and "args" in current_signature.parameters
52
+ and "kwargs" in current_signature.parameters
53
+ ):
54
+ forward = deepcopy(model.forward.__func__)
55
+ update_wrapper(
56
+ forward, type(model.get_base_model()).forward, assigned=("__doc__", "__name__", "__annotations__")
57
+ )
58
+ model.forward = MethodType(forward, model)
59
+
60
+
61
+ def update_generate_signature(model: PeftModel) -> None:
62
+ """
63
+ Updates the generate signature of a PeftModel with overriding generate to include parents class signature
64
+ model (`PeftModel`): Peft model to update the generate signature
65
+
66
+ Example:
67
+
68
+ ```python
69
+ >>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
70
+ >>> from peft import get_peft_model, LoraConfig, TaskType, update_generate_signature
71
+
72
+ >>> model_name_or_path = "bigscience/mt0-large"
73
+ >>> tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
74
+ >>> model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
75
+
76
+ >>> peft_config = LoraConfig(
77
+ ... task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1
78
+ ... )
79
+ >>> peft_model = get_peft_model(model, peft_config)
80
+ >>> update_generate_signature(peft_model)
81
+ >>> help(peft_model.generate)
82
+ ```
83
+ """
84
+ if not hasattr(model, "generate"):
85
+ return
86
+ current_signature = inspect.signature(model.generate)
87
+ if (
88
+ len(current_signature.parameters) == 2
89
+ and "args" in current_signature.parameters
90
+ and "kwargs" in current_signature.parameters
91
+ ) or (len(current_signature.parameters) == 1 and "kwargs" in current_signature.parameters):
92
+ generate = deepcopy(model.generate.__func__)
93
+ update_wrapper(
94
+ generate,
95
+ type(model.get_base_model()).generate,
96
+ assigned=("__doc__", "__name__", "__annotations__"),
97
+ )
98
+ model.generate = MethodType(generate, model)
99
+
100
+
101
+ def update_signature(model: PeftModel, method: str = "all") -> None:
102
+ """
103
+ Updates the signature of a PeftModel include parents class signature for forward or generate method
104
+ model (`PeftModel`): Peft model to update generate or forward signature method (`str`): method to update
105
+ signature choose one of "forward", "generate", "all"
106
+
107
+ Example:
108
+ ```python
109
+ >>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
110
+ >>> from peft import get_peft_model, LoraConfig, TaskType, update_signature
111
+
112
+ >>> model_name_or_path = "bigscience/mt0-large"
113
+ >>> tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
114
+ >>> model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
115
+
116
+ >>> peft_config = LoraConfig(
117
+ ... task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1
118
+ ... )
119
+ >>> peft_model = get_peft_model(model, peft_config)
120
+ >>> update_signature(peft_model)
121
+ >>> help(peft_model.generate)
122
+ ```
123
+ """
124
+ if method == "forward":
125
+ update_forward_signature(model)
126
+ elif method == "generate":
127
+ update_generate_signature(model)
128
+ elif method == "all":
129
+ update_forward_signature(model)
130
+ update_generate_signature(model)
131
+ else:
132
+ raise ValueError(f"method {method} is not supported please choose one of ['forward', 'generate', 'all']")
133
+
134
+
135
+ def check_if_peft_model(model_name_or_path: str) -> bool:
136
+ """
137
+ Check if the model is a PEFT model.
138
+
139
+ Args:
140
+ model_name_or_path (`str`):
141
+ Model id to check, can be local or on the Hugging Face Hub.
142
+
143
+ Returns:
144
+ `bool`: True if the model is a PEFT model, False otherwise.
145
+ """
146
+ is_peft_model = True
147
+ try:
148
+ PeftConfig.from_pretrained(model_name_or_path)
149
+ except Exception:
150
+ # allow broad exceptions so that this works even if new exceptions are added on HF Hub side
151
+ is_peft_model = False
152
+
153
+ return is_peft_model
154
+
155
+
156
+ @contextmanager
157
+ def rescale_adapter_scale(model, multiplier):
158
+ """
159
+ Context manager to temporarily rescale the scaling of the LoRA adapter in a model.
160
+
161
+ The original scaling values are restored when the context manager exits. This context manager works with the
162
+ transformers and diffusers models that have directly loaded LoRA adapters.
163
+
164
+ For LoRA, applying this context manager with multiplier in [0, 1] is strictly equivalent to applying
165
+ [wise-ft](https://huggingface.co/papers/2109.01903) (see [#1940](https://github.com/huggingface/peft/issues/1940)
166
+ for details). It can improve the performances of the model if there is a distribution shiftbetween the training
167
+ data used for fine-tuning, and the test data used during inference.
168
+
169
+ Warning: It has been reported that when using Apple's MPS backend for PyTorch, it is necessary to add a short sleep
170
+ time after exiting the context before the scales are fully restored.
171
+
172
+ Args:
173
+ model: The model containing `LoraLayer` modules whose scaling is to be adjusted.
174
+ multiplier (float or int):
175
+ The multiplier that rescales the `scaling` attribute. Must be of type float or int.
176
+
177
+ Raises:
178
+ ValueError: If the model does not contain any `LoraLayer`
179
+ instances, indicating that the model does not support scaling.
180
+
181
+ Example:
182
+
183
+ ```python
184
+ >>> model = ModelWithLoraLayer()
185
+ >>> multiplier = 0.5
186
+ >>> with rescale_adapter_scale(model, multiplier):
187
+ ... outputs = model(**inputs) # Perform operations with the scaled model
188
+ >>> outputs = model(**inputs) # The original scaling values are restored here
189
+ ```
190
+ """
191
+ # check if multiplier has a valid data type
192
+ if not isinstance(multiplier, (float, int)):
193
+ raise TypeError(f"Argument multiplier should be of type float, got {type(multiplier)}")
194
+
195
+ # iterate on the model's modules and grab the original scaling attribute
196
+ # from the lora layers if present
197
+ original_scaling = {}
198
+ for module in model.modules():
199
+ if isinstance(module, LoraLayer):
200
+ original_scaling[module] = module.scaling.copy()
201
+ module.scaling = {k: v * multiplier for k, v in module.scaling.items()}
202
+
203
+ # check whether scaling is prohibited on model
204
+ # the original scaling dictionary should be empty
205
+ # if there were no lora layers
206
+ if not original_scaling:
207
+ raise ValueError("scaling is only supported for models with `LoraLayer`s")
208
+ try:
209
+ yield
210
+
211
+ finally:
212
+ # restore original scaling values after exiting the context
213
+ for module, scaling in original_scaling.items():
214
+ module.scaling = scaling
215
+
216
+
217
+ @contextmanager
218
+ def disable_input_dtype_casting(model: nn.Module, active: bool = True):
219
+ """
220
+ Context manager disables input dtype casting to the dtype of the weight.
221
+
222
+ Parameters:
223
+ model (nn.Module):
224
+ The model containing PEFT modules whose input dtype casting is to be adjusted.
225
+ active (bool):
226
+ Whether the context manager is active (default) or inactive.
227
+
228
+ """
229
+ # Additional info: Normally, the dtype of the weight and input need to match, which is why the dtype is cast.
230
+ # However, in certain circumustances, this is handled by forward hooks, e.g. when using layerwise casting in
231
+ # diffusers. In that case, PEFT casting the dtype interferes with the layerwise casting, which is why the option to
232
+ # disable it is given.
233
+ if not active:
234
+ yield
235
+ return
236
+
237
+ original_values = {}
238
+ for name, module in model.named_modules():
239
+ if not isinstance(module, BaseTunerLayer):
240
+ continue
241
+ original_values[name] = module.cast_input_dtype_enabled
242
+ module.cast_input_dtype_enabled = False
243
+
244
+ try:
245
+ yield
246
+ finally:
247
+ for name, module in model.named_modules():
248
+ if not isinstance(module, BaseTunerLayer):
249
+ continue
250
+ if name in original_values:
251
+ module.cast_input_dtype_enabled = original_values[name]
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/import_utils.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import importlib
15
+ import importlib.metadata as importlib_metadata
16
+ import platform
17
+ from functools import lru_cache
18
+
19
+ import packaging.version
20
+ import torch
21
+
22
+
23
+ @lru_cache
24
+ def is_bnb_available() -> bool:
25
+ return importlib.util.find_spec("bitsandbytes") is not None
26
+
27
+
28
+ @lru_cache
29
+ def is_bnb_4bit_available() -> bool:
30
+ if not is_bnb_available():
31
+ return False
32
+
33
+ import bitsandbytes as bnb
34
+
35
+ return hasattr(bnb.nn, "Linear4bit")
36
+
37
+
38
+ @lru_cache
39
+ def is_auto_gptq_available():
40
+ if importlib.util.find_spec("auto_gptq") is not None:
41
+ AUTOGPTQ_MINIMUM_VERSION = packaging.version.parse("0.5.0")
42
+ version_autogptq = packaging.version.parse(importlib_metadata.version("auto_gptq"))
43
+ if AUTOGPTQ_MINIMUM_VERSION <= version_autogptq:
44
+ return True
45
+ else:
46
+ raise ImportError(
47
+ f"Found an incompatible version of auto-gptq. Found version {version_autogptq}, "
48
+ f"but only versions above {AUTOGPTQ_MINIMUM_VERSION} are supported"
49
+ )
50
+
51
+
52
+ @lru_cache
53
+ def is_gptqmodel_available():
54
+ if importlib.util.find_spec("gptqmodel") is not None:
55
+ GPTQMODEL_MINIMUM_VERSION = packaging.version.parse("2.0.0")
56
+ OPTIMUM_MINIMUM_VERSION = packaging.version.parse("1.24.0")
57
+ version_gptqmodel = packaging.version.parse(importlib_metadata.version("gptqmodel"))
58
+ if GPTQMODEL_MINIMUM_VERSION <= version_gptqmodel:
59
+ if is_optimum_available():
60
+ version_optimum = packaging.version.parse(importlib_metadata.version("optimum"))
61
+ if OPTIMUM_MINIMUM_VERSION <= version_optimum:
62
+ return True
63
+ else:
64
+ raise ImportError(
65
+ f"gptqmodel requires optimum version `{OPTIMUM_MINIMUM_VERSION}` or higher. Found version `{version_optimum}`, "
66
+ f"but only versions above `{OPTIMUM_MINIMUM_VERSION}` are supported"
67
+ )
68
+ else:
69
+ raise ImportError(
70
+ f"gptqmodel requires optimum version `{OPTIMUM_MINIMUM_VERSION}` or higher to be installed."
71
+ )
72
+ else:
73
+ raise ImportError(
74
+ f"Found an incompatible version of gptqmodel. Found version `{version_gptqmodel}`, "
75
+ f"but only versions above `{GPTQMODEL_MINIMUM_VERSION}` are supported"
76
+ )
77
+
78
+
79
+ @lru_cache
80
+ def is_optimum_available() -> bool:
81
+ return importlib.util.find_spec("optimum") is not None
82
+
83
+
84
+ @lru_cache
85
+ def is_torch_tpu_available(check_device=True):
86
+ "Checks if `torch_xla` is installed and potentially if a TPU is in the environment"
87
+ if importlib.util.find_spec("torch_xla") is not None:
88
+ if check_device:
89
+ # We need to check if `xla_device` can be found, will raise a RuntimeError if not
90
+ try:
91
+ import torch_xla.core.xla_model as xm
92
+
93
+ _ = xm.xla_device()
94
+ return True
95
+ except RuntimeError:
96
+ return False
97
+ return True
98
+ return False
99
+
100
+
101
+ @lru_cache
102
+ def is_aqlm_available():
103
+ return importlib.util.find_spec("aqlm") is not None
104
+
105
+
106
+ @lru_cache
107
+ def is_auto_awq_available():
108
+ return importlib.util.find_spec("awq") is not None
109
+
110
+
111
+ @lru_cache
112
+ def is_eetq_available():
113
+ return importlib.util.find_spec("eetq") is not None
114
+
115
+
116
+ @lru_cache
117
+ def is_hqq_available():
118
+ return importlib.util.find_spec("hqq") is not None
119
+
120
+
121
+ @lru_cache
122
+ def is_inc_available():
123
+ return importlib.util.find_spec("neural_compressor") is not None
124
+
125
+
126
+ @lru_cache
127
+ def is_torchao_available():
128
+ if importlib.util.find_spec("torchao") is None:
129
+ return False
130
+
131
+ TORCHAO_MINIMUM_VERSION = packaging.version.parse("0.4.0")
132
+ try:
133
+ torchao_version = packaging.version.parse(importlib_metadata.version("torchao"))
134
+ except importlib_metadata.PackageNotFoundError:
135
+ # Same idea as in diffusers:
136
+ # https://github.com/huggingface/diffusers/blob/9f06a0d1a4a998ac6a463c5be728c892f95320a8/src/diffusers/utils/import_utils.py#L351-L357
137
+ # It's not clear under what circumstances `importlib_metadata.version("torchao")` can raise an error even
138
+ # though `importlib.util.find_spec("torchao") is not None` but it has been observed, so adding this for
139
+ # precaution.
140
+ return False
141
+
142
+ if torchao_version < TORCHAO_MINIMUM_VERSION:
143
+ raise ImportError(
144
+ f"Found an incompatible version of torchao. Found version {torchao_version}, "
145
+ f"but only versions above {TORCHAO_MINIMUM_VERSION} are supported"
146
+ )
147
+ return True
148
+
149
+
150
+ @lru_cache
151
+ def is_xpu_available(check_device=False):
152
+ """
153
+ Checks if XPU acceleration is available and potentially if a XPU is in the environment
154
+ """
155
+
156
+ system = platform.system()
157
+ if system == "Darwin":
158
+ return False
159
+ else:
160
+ if check_device:
161
+ try:
162
+ # Will raise a RuntimeError if no XPU is found
163
+ _ = torch.xpu.device_count()
164
+ return torch.xpu.is_available()
165
+ except RuntimeError:
166
+ return False
167
+ return hasattr(torch, "xpu") and torch.xpu.is_available()
168
+
169
+
170
+ @lru_cache
171
+ def is_diffusers_available():
172
+ return importlib.util.find_spec("diffusers") is not None
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mapping.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import TYPE_CHECKING, Any, Optional
18
+
19
+ import torch
20
+
21
+ from .utils import PeftType
22
+
23
+
24
+ if TYPE_CHECKING:
25
+ from .config import PeftConfig
26
+ from .tuners.tuners_utils import BaseTuner
27
+
28
+
29
+ # these will be filled by the register_peft_method function
30
+ PEFT_TYPE_TO_CONFIG_MAPPING: dict[PeftType, type[PeftConfig]] = {}
31
+ PEFT_TYPE_TO_TUNER_MAPPING: dict[PeftType, type[BaseTuner]] = {}
32
+ PEFT_TYPE_TO_MIXED_MODEL_MAPPING: dict[PeftType, type[BaseTuner]] = {}
33
+ PEFT_TYPE_TO_PREFIX_MAPPING: dict[PeftType, str] = {}
34
+
35
+
36
+ def get_peft_config(config_dict: dict[str, Any]) -> PeftConfig:
37
+ """
38
+ Returns a Peft config object from a dictionary.
39
+
40
+ Args:
41
+ config_dict (`Dict[str, Any]`): Dictionary containing the configuration parameters.
42
+ """
43
+
44
+ return PEFT_TYPE_TO_CONFIG_MAPPING[config_dict["peft_type"]](**config_dict)
45
+
46
+
47
+ def inject_adapter_in_model(
48
+ peft_config: PeftConfig,
49
+ model: torch.nn.Module,
50
+ adapter_name: str = "default",
51
+ low_cpu_mem_usage: bool = False,
52
+ state_dict: Optional[dict[str, torch.Tensor]] = None,
53
+ ) -> torch.nn.Module:
54
+ r"""
55
+ Create PEFT layers and inject them into the model in-place.
56
+
57
+ Currently the API does not support prompt learning methods and adaption prompt.
58
+
59
+ This function is similar to [`get_peft_model`] but it does not return a [`PeftModel`] instance. Instead, it returns
60
+ the original, mutated instance of the passed model.
61
+
62
+ Args:
63
+ peft_config (`PeftConfig`):
64
+ Configuration object containing the parameters of the PEFT model.
65
+ model (`torch.nn.Module`):
66
+ The input model where the adapter will be injected.
67
+ adapter_name (`str`, `optional`, defaults to `"default"`):
68
+ The name of the adapter to be injected, if not provided, the default adapter name is used ("default").
69
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
70
+ Create empty adapter weights on meta device. Useful to speed up the loading process.
71
+ state_dict (`dict`, *optional*, defaults to `None`)
72
+ If a `state_dict` is passed here, the adapters will be injected based on the entries of the state_dict.
73
+ This can be useful when the exact `target_modules` of the PEFT method is unknown, for instance because the
74
+ checkpoint was created without meta data. Note that the values from the `state_dict` are not used, only the
75
+ keys are used to determine the correct layers that should be adapted.
76
+ """
77
+ if peft_config.is_prompt_learning or peft_config.is_adaption_prompt:
78
+ raise ValueError("`create_and_replace` does not support prompt learning and adaption prompt yet.")
79
+
80
+ if peft_config.peft_type not in PEFT_TYPE_TO_TUNER_MAPPING.keys():
81
+ raise ValueError(
82
+ f"`inject_adapter_in_model` does not support {peft_config.peft_type} yet. Please use `get_peft_model`."
83
+ )
84
+
85
+ tuner_cls = PEFT_TYPE_TO_TUNER_MAPPING[peft_config.peft_type]
86
+
87
+ # By instantiating a peft model we are injecting randomly initialized LoRA layers into the model's modules.
88
+ peft_model = tuner_cls(
89
+ model, peft_config, adapter_name=adapter_name, low_cpu_mem_usage=low_cpu_mem_usage, state_dict=state_dict
90
+ )
91
+
92
+ return peft_model.model
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mapping_func.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import warnings
18
+ from typing import Optional
19
+
20
+ from transformers import PreTrainedModel
21
+
22
+ from .auto import MODEL_TYPE_TO_PEFT_MODEL_MAPPING
23
+ from .config import PeftConfig
24
+ from .mapping import PEFT_TYPE_TO_CONFIG_MAPPING, PEFT_TYPE_TO_PREFIX_MAPPING
25
+ from .mixed_model import PeftMixedModel
26
+ from .peft_model import PeftModel
27
+ from .tuners.tuners_utils import BaseTuner, BaseTunerLayer
28
+
29
+
30
+ def get_peft_model(
31
+ model: PreTrainedModel,
32
+ peft_config: PeftConfig,
33
+ adapter_name: str = "default",
34
+ mixed: bool = False,
35
+ autocast_adapter_dtype: bool = True,
36
+ revision: Optional[str] = None,
37
+ low_cpu_mem_usage: bool = False,
38
+ ) -> PeftModel | PeftMixedModel:
39
+ """
40
+ Returns a Peft model object from a model and a config, where the model will be modified in-place.
41
+
42
+ Args:
43
+ model ([`transformers.PreTrainedModel`]):
44
+ Model to be wrapped.
45
+ peft_config ([`PeftConfig`]):
46
+ Configuration object containing the parameters of the Peft model.
47
+ adapter_name (`str`, `optional`, defaults to `"default"`):
48
+ The name of the adapter to be injected, if not provided, the default adapter name is used ("default").
49
+ mixed (`bool`, `optional`, defaults to `False`):
50
+ Whether to allow mixing different (compatible) adapter types.
51
+ autocast_adapter_dtype (`bool`, *optional*):
52
+ Whether to autocast the adapter dtype. Defaults to `True`. Right now, this will only cast adapter weights
53
+ using float16 or bfloat16 to float32, as this is typically required for stable training, and only affect
54
+ select PEFT tuners.
55
+ revision (`str`, `optional`, defaults to `main`):
56
+ The revision of the base model. If this isn't set, the saved peft model will load the `main` revision for
57
+ the base model
58
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
59
+ Create empty adapter weights on meta device. Useful to speed up the loading process. Leave this setting as
60
+ False if you intend on training the model, unless the adapter weights will be replaced by different weights
61
+ before training starts.
62
+ """
63
+ model_config = BaseTuner.get_model_config(model)
64
+ old_name = peft_config.base_model_name_or_path
65
+ new_name = model.__dict__.get("name_or_path", None)
66
+ peft_config.base_model_name_or_path = new_name
67
+
68
+ # Especially in notebook environments there could be a case that a user wants to experiment with different
69
+ # configuration values. However, it is likely that there won't be any changes for new configs on an already
70
+ # initialized PEFT model. The best we can do is warn the user about it.
71
+ if any(isinstance(module, BaseTunerLayer) for module in model.modules()):
72
+ warnings.warn(
73
+ "You are trying to modify a model with PEFT for a second time. If you want to reload the model with a "
74
+ "different config, make sure to call `.unload()` before."
75
+ )
76
+
77
+ if (old_name is not None) and (old_name != new_name):
78
+ warnings.warn(
79
+ f"The PEFT config's `base_model_name_or_path` was renamed from '{old_name}' to '{new_name}'. "
80
+ "Please ensure that the correct base model is loaded when loading this checkpoint."
81
+ )
82
+
83
+ if revision is not None:
84
+ if peft_config.revision is not None and peft_config.revision != revision:
85
+ warnings.warn(
86
+ f"peft config has already set base model revision to {peft_config.revision}, overwriting with revision {revision}"
87
+ )
88
+ peft_config.revision = revision
89
+
90
+ if (
91
+ (isinstance(peft_config, PEFT_TYPE_TO_CONFIG_MAPPING["LORA"]))
92
+ and (peft_config.init_lora_weights == "eva")
93
+ and not low_cpu_mem_usage
94
+ ):
95
+ warnings.warn(
96
+ "lora with eva initialization used with low_cpu_mem_usage=False. "
97
+ "Setting low_cpu_mem_usage=True can improve the maximum batch size possible for eva initialization."
98
+ )
99
+
100
+ prefix = PEFT_TYPE_TO_PREFIX_MAPPING.get(peft_config.peft_type)
101
+ if prefix and adapter_name in prefix:
102
+ warnings.warn(
103
+ f"Adapter name '{adapter_name}' should not be contained in the prefix '{prefix}'. "
104
+ "This may lead to reinitialization of the adapter weights during loading."
105
+ )
106
+
107
+ if mixed:
108
+ # note: PeftMixedModel does not support autocast_adapter_dtype, so don't pass it
109
+ return PeftMixedModel(model, peft_config, adapter_name=adapter_name)
110
+
111
+ # We explicitly exclude prompt learning here since prompt learning is specific to the task and needs special
112
+ # handling in the PEFT model's forward method.
113
+ if peft_config.task_type not in MODEL_TYPE_TO_PEFT_MODEL_MAPPING.keys() and not peft_config.is_prompt_learning:
114
+ return PeftModel(
115
+ model,
116
+ peft_config,
117
+ adapter_name=adapter_name,
118
+ autocast_adapter_dtype=autocast_adapter_dtype,
119
+ low_cpu_mem_usage=low_cpu_mem_usage,
120
+ )
121
+
122
+ return MODEL_TYPE_TO_PEFT_MODEL_MAPPING[peft_config.task_type](
123
+ model,
124
+ peft_config,
125
+ adapter_name=adapter_name,
126
+ autocast_adapter_dtype=autocast_adapter_dtype,
127
+ low_cpu_mem_usage=low_cpu_mem_usage,
128
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/mixed_model.py ADDED
@@ -0,0 +1,460 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ from contextlib import contextmanager
19
+ from typing import Any, Optional, Union
20
+
21
+ import torch
22
+ from accelerate.hooks import remove_hook_from_submodules
23
+ from torch import nn
24
+ from transformers.utils import PushToHubMixin
25
+
26
+ from peft.utils.constants import DUMMY_MODEL_CONFIG
27
+
28
+ from .config import PeftConfig
29
+ from .peft_model import PeftModel
30
+ from .tuners import MixedModel
31
+ from .utils import _set_adapter, _set_trainable
32
+
33
+
34
+ def _prepare_model_for_gradient_checkpointing(model: nn.Module) -> None:
35
+ r"""
36
+ Prepares the model for gradient checkpointing if necessary
37
+ """
38
+ # Note: same as PeftModel._prepare_model_for_gradient_checkpointing
39
+ if not getattr(model, "is_gradient_checkpointing", True):
40
+ return model
41
+
42
+ if not (
43
+ getattr(model, "is_loaded_in_8bit", False)
44
+ or getattr(model, "is_loaded_in_4bit", False)
45
+ or getattr(model, "is_quantized", False)
46
+ ):
47
+ if hasattr(model, "enable_input_require_grads"):
48
+ model.enable_input_require_grads()
49
+ elif hasattr(model, "get_input_embeddings"):
50
+
51
+ def make_inputs_require_grad(module, input, output):
52
+ output.requires_grad_(True)
53
+
54
+ model.get_input_embeddings().register_forward_hook(make_inputs_require_grad)
55
+
56
+
57
+ def _check_config_compatible(peft_config: PeftConfig) -> None:
58
+ from .tuners.mixed import COMPATIBLE_TUNER_TYPES
59
+
60
+ if peft_config.peft_type not in COMPATIBLE_TUNER_TYPES:
61
+ raise ValueError(
62
+ f"The provided `peft_type` '{peft_config.peft_type.value}' is not compatible with the `PeftMixedModel`. "
63
+ f"Compatible types are: {COMPATIBLE_TUNER_TYPES}"
64
+ )
65
+
66
+
67
+ class PeftMixedModel(PushToHubMixin, torch.nn.Module):
68
+ """
69
+ PeftMixedModel for loading mixing different types of adapters for inference.
70
+
71
+ This class does not support loading/saving, and it shouldn't usually be initialized directly. Instead, use
72
+ `get_peft_model` with the argument `mixed=True`.
73
+
74
+ > [!TIP] > Read the [Mixed adapter types](https://huggingface.co/docs/peft/en/developer_guides/mixed_models) guide
75
+ to learn > more about using different adapter types.
76
+
77
+ Example:
78
+
79
+ ```py
80
+ >>> base_model = ... # load the base model, e.g. from transformers
81
+ >>> peft_model = PeftMixedModel.from_pretrained(base_model, path_to_adapter1, "adapter1").eval()
82
+ >>> peft_model.load_adapter(path_to_adapter2, "adapter2")
83
+ >>> peft_model.set_adapter(["adapter1", "adapter2"]) # activate both adapters
84
+ >>> peft_model(data) # forward pass using both adapters
85
+ ```
86
+
87
+ Args:
88
+ model (`torch.nn.Module`):
89
+ The model to be tuned.
90
+ config (`PeftConfig`):
91
+ The config of the model to be tuned. The adapter type must be compatible.
92
+ adapter_name (`str`, `optional`, defaults to `"default"`):
93
+ The name of the first adapter.
94
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
95
+ Create empty adapter weights on meta device. Useful to speed up the loading process.
96
+ """
97
+
98
+ def __init__(self, model: nn.Module, peft_config: PeftConfig, adapter_name: str = "default") -> None:
99
+ super().__init__()
100
+ _check_config_compatible(peft_config)
101
+ _prepare_model_for_gradient_checkpointing(model)
102
+ self.modules_to_save = None
103
+ self.base_model = MixedModel(model, {adapter_name: peft_config}, adapter_name)
104
+ self.set_modules_to_save(peft_config, adapter_name)
105
+
106
+ self.config = getattr(model, "config", DUMMY_MODEL_CONFIG)
107
+
108
+ # the `pretraining_tp` is set for some models to simulate Tensor Parallelism during inference to avoid
109
+ # numerical differences, https://github.com/pytorch/pytorch/issues/76232 - to avoid any unexpected
110
+ # behavior we disable that in this line.
111
+ if hasattr(self.base_model, "config") and hasattr(self.base_model.config, "pretraining_tp"):
112
+ self.base_model.config.pretraining_tp = 1
113
+
114
+ @property
115
+ def peft_config(self) -> dict[str, PeftConfig]:
116
+ return self.base_model.peft_config
117
+
118
+ @property
119
+ def active_adapter(self) -> str:
120
+ return self.base_model.active_adapter
121
+
122
+ @property
123
+ def active_adapters(self) -> list[str]:
124
+ return self.base_model.active_adapters
125
+
126
+ def get_nb_trainable_parameters(self):
127
+ r"""
128
+ Returns the number of trainable parameters and number of all parameters in the model.
129
+ """
130
+ # note: same as PeftModel.get_nb_trainable_parameters
131
+ trainable_params = 0
132
+ all_param = 0
133
+ for _, param in self.named_parameters():
134
+ num_params = param.numel()
135
+ # if using DS Zero 3 and the weights are initialized empty
136
+ if num_params == 0 and hasattr(param, "ds_numel"):
137
+ num_params = param.ds_numel
138
+
139
+ # Due to the design of 4bit linear layers from bitsandbytes
140
+ # one needs to multiply the number of parameters by 2 to get
141
+ # the correct number of parameters
142
+ if param.__class__.__name__ == "Params4bit":
143
+ num_params = num_params * 2
144
+
145
+ all_param += num_params
146
+ if param.requires_grad:
147
+ trainable_params += num_params
148
+
149
+ return trainable_params, all_param
150
+
151
+ def print_trainable_parameters(self):
152
+ """
153
+ Prints the number of trainable parameters in the model.
154
+
155
+ Note: print_trainable_parameters() uses get_nb_trainable_parameters() which is different from
156
+ num_parameters(only_trainable=True) from huggingface/transformers. get_nb_trainable_parameters() returns
157
+ (trainable parameters, all parameters) of the Peft Model which includes modified backbone transformer model.
158
+ For techniques like LoRA, the backbone transformer model is modified in place with LoRA modules. However, for
159
+ prompt tuning, the backbone transformer model is unmodified. num_parameters(only_trainable=True) returns number
160
+ of trainable parameters of the backbone transformer model which can be different.
161
+ """
162
+ # note: same as PeftModel.print_trainable_parameters
163
+ trainable_params, all_param = self.get_nb_trainable_parameters()
164
+
165
+ print(
166
+ f"trainable params: {trainable_params:,d} || "
167
+ f"all params: {all_param:,d} || "
168
+ f"trainable%: {100 * trainable_params / all_param:.4f}"
169
+ )
170
+
171
+ def __getattr__(self, name: str):
172
+ """Forward missing attributes to the wrapped module."""
173
+ try:
174
+ return super().__getattr__(name) # defer to nn.Module's logic
175
+ except AttributeError:
176
+ if name == "base_model": # see #1892: prevent infinite recursion if class is not initialized
177
+ raise
178
+ return getattr(self.base_model, name)
179
+
180
+ def forward(self, *args: Any, **kwargs: Any):
181
+ """
182
+ Forward pass of the model.
183
+ """
184
+ return self.base_model(*args, **kwargs)
185
+
186
+ def generate(self, *args: Any, **kwargs: Any):
187
+ """
188
+ Generate output.
189
+ """
190
+ return self.base_model.generate(*args, **kwargs)
191
+
192
+ @contextmanager
193
+ def disable_adapter(self):
194
+ """
195
+ Disables the adapter module.
196
+ """
197
+ try:
198
+ self.base_model.disable_adapter_layers()
199
+ yield
200
+ finally:
201
+ self.base_model.enable_adapter_layers()
202
+
203
+ def add_adapter(self, adapter_name: str, peft_config: PeftConfig, low_cpu_mem_usage: bool = False) -> None:
204
+ """
205
+ Add an adapter to the model based on the passed configuration.
206
+
207
+ This adapter is not trained. To load a trained adapter, check out [`PeftModel.load_adapter`].
208
+
209
+ The name for the new adapter should be unique.
210
+
211
+ The new adapter is not automatically set as the active adapter. Use [`PeftModel.set_adapter`] to set the active
212
+ adapter.
213
+
214
+ Args:
215
+ adapter_name (`str`):
216
+ The name of the adapter to be added.
217
+ peft_config ([`PeftConfig`]):
218
+ The configuration of the adapter to be added.
219
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
220
+ Create empty adapter weights on meta device. Useful to speed up the process when loading saved
221
+ adapters.
222
+
223
+ > [!TIP] > Don't use `low_cpu_mem_usage=True` when creating a new PEFT adapter for training (training
224
+ is untested > and discouraged for PeftMixedModel in general).
225
+ """
226
+ _check_config_compatible(peft_config)
227
+
228
+ try:
229
+ self.peft_config[adapter_name] = peft_config
230
+ self.base_model.inject_adapter(self, adapter_name, low_cpu_mem_usage=low_cpu_mem_usage)
231
+ except Exception: # something went wrong, roll back
232
+ if adapter_name in self.peft_config:
233
+ del self.peft_config[adapter_name]
234
+ raise
235
+
236
+ self.set_modules_to_save(peft_config, adapter_name)
237
+
238
+ def set_modules_to_save(self, peft_config: PeftConfig, adapter_name: str) -> None:
239
+ if (modules_to_save := getattr(peft_config, "modules_to_save", None)) is None:
240
+ return
241
+
242
+ if self.modules_to_save is None:
243
+ self.modules_to_save = set(modules_to_save)
244
+ else:
245
+ self.modules_to_save.update(modules_to_save)
246
+ _set_trainable(
247
+ self,
248
+ adapter_name,
249
+ module_names=getattr(peft_config, "modules_to_save", None),
250
+ inference_mode=peft_config.inference_mode,
251
+ )
252
+
253
+ def set_adapter(self, adapter_name: Union[str, list[str]], inference_mode: bool = False) -> None:
254
+ """
255
+ Sets the active adapter(s) for the model.
256
+
257
+ Note that the order in which the adapters are applied during the forward pass may not be the same as the order
258
+ in which they are passed to this function. Instead, the order during the forward pass is determined by the
259
+ order in which the adapters were loaded into the model. The active adapters only determine which adapters are
260
+ active during the forward pass, but not the order in which they are applied.
261
+
262
+ Additionally, this function will set the specified adapter to trainable (i.e., requires_grad=True) unless
263
+ inference_mode is True.
264
+
265
+ Args:
266
+ adapter_name (str, list[str]):
267
+ The name(s) of the adapter(s) to set as active
268
+ inference_mode (bool, optional):
269
+ Whether the activated adapter should be frozen (i.e. `requires_grad=False`). Default is False.
270
+ """
271
+ if isinstance(adapter_name, str):
272
+ adapter_name = [adapter_name]
273
+
274
+ mismatched = set(adapter_name) - set(self.peft_config.keys())
275
+ if mismatched:
276
+ raise ValueError(
277
+ f"Adapter(s) {sorted(mismatched)} not found, available adapters: {sorted(self.peft_config.keys())}"
278
+ )
279
+
280
+ self.base_model.set_adapter(adapter_name, inference_mode=inference_mode)
281
+ _set_adapter(self, adapter_name, inference_mode=inference_mode)
282
+
283
+ def delete_adapter(self, adapter_name: Union[str, list[str]]) -> None:
284
+ if isinstance(adapter_name, str):
285
+ adapter_name = [adapter_name]
286
+
287
+ mismatched = set(adapter_name) - set(self.peft_config.keys())
288
+ if mismatched:
289
+ raise ValueError(
290
+ f"Adapter(s) {sorted(mismatched)} not found, available adapters: {sorted(self.peft_config.keys())}"
291
+ )
292
+
293
+ self.base_model.delete_adapter(adapter_name)
294
+
295
+ def merge_and_unload(self, *args: Any, **kwargs: Any):
296
+ r"""
297
+ This method merges the adapter layers into the base model. This is needed if someone wants to use the base
298
+ model as a standalone model.
299
+
300
+ Args:
301
+ progressbar (`bool`):
302
+ whether to show a progressbar indicating the unload and merge process
303
+ safe_merge (`bool`):
304
+ whether to activate the safe merging check to check if there is any potential Nan in the adapter
305
+ weights
306
+ adapter_names (`List[str]`, *optional*):
307
+ The list of adapter names that should be merged. If None, all active adapters will be merged. Defaults
308
+ to `None`.
309
+ """
310
+ return self.base_model.merge_and_unload(*args, **kwargs)
311
+
312
+ def unload(self, *args: Any, **kwargs: Any):
313
+ """
314
+ Gets back the base model by removing all the adapter modules without merging. This gives back the original base
315
+ model.
316
+ """
317
+ return self.base_model.unload(*args, **kwargs)
318
+
319
+ def get_layer_status(self):
320
+ raise TypeError(f"get_layer_status is not supported for {self.__class__.__name__}.")
321
+
322
+ def get_model_status(self):
323
+ raise TypeError(f"get_model_status is not supported for {self.__class__.__name__}.")
324
+
325
+ @classmethod
326
+ def _split_kwargs(cls, kwargs: dict[str, Any]):
327
+ return PeftModel._split_kwargs(kwargs)
328
+
329
+ def _check_new_adapter_config(self, peft_config: PeftConfig, is_trainable: bool) -> None:
330
+ return PeftModel._check_new_adapter_config(self, peft_config, is_trainable=is_trainable)
331
+
332
+ def load_adapter(self, model_id: str, adapter_name: str, *args: Any, **kwargs: Any):
333
+ """
334
+ Load a trained adapter into the model.
335
+
336
+ The name for the new adapter should be unique.
337
+
338
+ The new adapter is not automatically set as the active adapter. Use [`PeftModel.set_adapter`] to set the active
339
+ adapter.
340
+
341
+ Args:
342
+ adapter_name (`str`):
343
+ The name of the adapter to be added.
344
+ peft_config ([`PeftConfig`]):
345
+ The configuration of the adapter to be added.
346
+ is_trainable (`bool`, *optional*, defaults to `False`):
347
+ Whether the adapter should be trainable or not. If `False`, the adapter will be frozen and can only be
348
+ used for inference.
349
+ torch_device (`str`, *optional*, defaults to None):
350
+ The device to load the adapter on. If `None`, the device will be inferred.
351
+ autocast_adapter_dtype (`bool`, *optional*, defaults to `True`):
352
+ Whether to autocast the adapter dtype. Defaults to `True`. Right now, this will only cast adapter
353
+ weights using float16 and bfloat16 to float32, as this is typically required for stable training, and
354
+ only affect select PEFT tuners.
355
+ ephemeral_gpu_offload (`bool`, *optional*, defaults to `False`):
356
+ Whether to use ephemeral GPU offloading for partially loaded modules. Defaults to `False`.
357
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
358
+ Create empty adapter weights on meta device before loading the saved weights. Useful to speed up the
359
+ process.
360
+ kwargs: (`optional`):
361
+ Additional arguments to modify the way the adapter is loaded, e.g. the token for Hugging Face Hub.
362
+ """
363
+ # the low_cpu_mem_usage option is handled through kwargs
364
+ output = PeftModel.load_adapter(self, model_id, adapter_name, *args, **kwargs)
365
+ # TODO: not quite clear why this is necessary but tests fail without it
366
+ self.set_adapter(self.active_adapters)
367
+ return output
368
+
369
+ def create_or_update_model_card(self, output_dir: str):
370
+ raise NotImplementedError(f"Model card creation is not supported for {self.__class__.__name__} (yet).")
371
+
372
+ def save_pretrained(
373
+ self,
374
+ save_directory: str,
375
+ safe_serialization: bool = False,
376
+ selected_adapters: Optional[list[str]] = None,
377
+ **kwargs: Any,
378
+ ):
379
+ raise NotImplementedError(f"Saving is not supported for {self.__class__.__name__} (yet).")
380
+
381
+ @classmethod
382
+ def from_pretrained(
383
+ cls,
384
+ model: nn.Module,
385
+ model_id: str | os.PathLike,
386
+ adapter_name: str = "default",
387
+ is_trainable: bool = False,
388
+ config: Optional[PeftConfig] = None,
389
+ **kwargs: Any,
390
+ ):
391
+ r"""
392
+ Instantiate a PEFT mixed model from a pretrained model and loaded PEFT weights.
393
+
394
+ Note that the passed `model` may be modified inplace.
395
+
396
+ Args:
397
+ model (`nn.Module`):
398
+ The model to be adapted.
399
+ model_id (`str` or `os.PathLike`):
400
+ The name of the PEFT configuration to use. Can be either:
401
+ - A string, the `model id` of a PEFT configuration hosted inside a model repo on the Hugging Face
402
+ Hub.
403
+ - A path to a directory containing a PEFT configuration file saved using the `save_pretrained`
404
+ method (`./my_peft_config_directory/`).
405
+ adapter_name (`str`, *optional*, defaults to `"default"`):
406
+ The name of the adapter to be loaded. This is useful for loading multiple adapters.
407
+ is_trainable (`bool`, *optional*, defaults to `False`):
408
+ Whether the adapter should be trainable or not. If `False`, the adapter will be frozen and use for
409
+ inference
410
+ config ([`~peft.PeftConfig`], *optional*):
411
+ The configuration object to use instead of an automatically loaded configuration. This configuration
412
+ object is mutually exclusive with `model_id` and `kwargs`. This is useful when configuration is already
413
+ loaded before calling `from_pretrained`.
414
+ low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
415
+ Create empty adapter weights on meta device before loading the saved weights. Useful to speed up the
416
+ process.
417
+ kwargs: (`optional`):
418
+ Additional keyword arguments passed along to the specific PEFT configuration class.
419
+ """
420
+ # note: adapted from PeftModel.from_pretrained
421
+ from .mapping import PEFT_TYPE_TO_CONFIG_MAPPING, PEFT_TYPE_TO_MIXED_MODEL_MAPPING
422
+
423
+ # load the config
424
+ if config is None:
425
+ hf_kwargs = {
426
+ "subfolder": kwargs.get("subfolder", None),
427
+ "revision": kwargs.get("revision", None),
428
+ "cache_dir": kwargs.get("cache_dir", None),
429
+ "token": kwargs.get("token", None),
430
+ }
431
+ if use_auth_token := kwargs.get("use_auth_token", None):
432
+ hf_kwargs["use_auth_token"] = use_auth_token
433
+ config = PEFT_TYPE_TO_CONFIG_MAPPING[PeftConfig._get_peft_type(model_id, **hf_kwargs)].from_pretrained(
434
+ model_id, **kwargs
435
+ )
436
+ elif isinstance(config, PeftConfig):
437
+ config.inference_mode = not is_trainable
438
+ else:
439
+ raise ValueError(f"The input config must be a PeftConfig, got {config.__class__}")
440
+
441
+ # note: this is different from PeftModel.from_pretrained
442
+ if config.peft_type not in PEFT_TYPE_TO_MIXED_MODEL_MAPPING:
443
+ raise ValueError(f"Adapter of type {config.peft_type} is not supported for mixed models.")
444
+
445
+ if (getattr(model, "hf_device_map", None) is not None) and len(
446
+ set(model.hf_device_map.values()).intersection({"cpu", "disk"})
447
+ ) > 0:
448
+ remove_hook_from_submodules(model)
449
+
450
+ if config.is_prompt_learning and is_trainable:
451
+ # note: should not be possible to reach, but just in case
452
+ raise ValueError("Cannot set a prompt learning adapter to trainable when loading pretrained adapter.")
453
+ else:
454
+ config.inference_mode = not is_trainable
455
+
456
+ # note: this is different from PeftModel.from_pretrained, we always return a PeftMixedModel
457
+ model = cls(model, config, adapter_name)
458
+ # the low_cpu_mem_usage option is handled through kwargs
459
+ model.load_adapter(model_id, adapter_name, is_trainable=is_trainable, **kwargs)
460
+ return model
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/peft_model.py ADDED
The diff for this file is too large to render. See raw diff
 
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/peft/py.typed ADDED
File without changes
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_csv.pxd ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ from pyarrow.includes.libarrow cimport *
21
+ from pyarrow.lib cimport _Weakrefable
22
+
23
+
24
+ cdef class ConvertOptions(_Weakrefable):
25
+ cdef:
26
+ unique_ptr[CCSVConvertOptions] options
27
+
28
+ @staticmethod
29
+ cdef ConvertOptions wrap(CCSVConvertOptions options)
30
+
31
+
32
+ cdef class ParseOptions(_Weakrefable):
33
+ cdef:
34
+ unique_ptr[CCSVParseOptions] options
35
+ object _invalid_row_handler
36
+
37
+ @staticmethod
38
+ cdef ParseOptions wrap(CCSVParseOptions options)
39
+
40
+
41
+ cdef class ReadOptions(_Weakrefable):
42
+ cdef:
43
+ unique_ptr[CCSVReadOptions] options
44
+ public object encoding
45
+
46
+ @staticmethod
47
+ cdef ReadOptions wrap(CCSVReadOptions options)
48
+
49
+
50
+ cdef class WriteOptions(_Weakrefable):
51
+ cdef:
52
+ unique_ptr[CCSVWriteOptions] options
53
+
54
+ @staticmethod
55
+ cdef WriteOptions wrap(CCSVWriteOptions options)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_cuda.pxd ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ from pyarrow.lib cimport *
21
+ from pyarrow.includes.common cimport *
22
+ from pyarrow.includes.libarrow cimport *
23
+ from pyarrow.includes.libarrow_cuda cimport *
24
+
25
+
26
+ cdef class Context(_Weakrefable):
27
+ cdef:
28
+ shared_ptr[CCudaContext] context
29
+ int device_number
30
+
31
+ cdef void init(self, const shared_ptr[CCudaContext]& ctx)
32
+
33
+
34
+ cdef class IpcMemHandle(_Weakrefable):
35
+ cdef:
36
+ shared_ptr[CCudaIpcMemHandle] handle
37
+
38
+ cdef void init(self, shared_ptr[CCudaIpcMemHandle]& h)
39
+
40
+
41
+ cdef class CudaBuffer(Buffer):
42
+ cdef:
43
+ shared_ptr[CCudaBuffer] cuda_buffer
44
+ object base
45
+
46
+ cdef void init_cuda(self,
47
+ const shared_ptr[CCudaBuffer]& buffer,
48
+ object base)
49
+
50
+
51
+ cdef class HostBuffer(Buffer):
52
+ cdef:
53
+ shared_ptr[CCudaHostBuffer] host_buffer
54
+
55
+ cdef void init_host(self, const shared_ptr[CCudaHostBuffer]& buffer)
56
+
57
+
58
+ cdef class BufferReader(NativeFile):
59
+ cdef:
60
+ CCudaBufferReader* reader
61
+ CudaBuffer buffer
62
+
63
+
64
+ cdef class BufferWriter(NativeFile):
65
+ cdef:
66
+ CCudaBufferWriter* writer
67
+ CudaBuffer buffer
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_dataset.pxd ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ """Dataset is currently unstable. APIs subject to change without notice."""
21
+
22
+ from pyarrow.includes.common cimport *
23
+ from pyarrow.includes.libarrow_dataset cimport *
24
+ from pyarrow.lib cimport *
25
+ from pyarrow._fs cimport FileSystem, FileInfo
26
+
27
+
28
+ cdef CFileSource _make_file_source(object file, FileSystem filesystem=*, object file_size=*)
29
+
30
+ cdef class DatasetFactory(_Weakrefable):
31
+
32
+ cdef:
33
+ SharedPtrNoGIL[CDatasetFactory] wrapped
34
+ CDatasetFactory* factory
35
+
36
+ cdef init(self, const shared_ptr[CDatasetFactory]& sp)
37
+
38
+ @staticmethod
39
+ cdef wrap(const shared_ptr[CDatasetFactory]& sp)
40
+
41
+ cdef inline shared_ptr[CDatasetFactory] unwrap(self) nogil
42
+
43
+
44
+ cdef class Dataset(_Weakrefable):
45
+
46
+ cdef:
47
+ SharedPtrNoGIL[CDataset] wrapped
48
+ CDataset* dataset
49
+ public dict _scan_options
50
+
51
+ cdef void init(self, const shared_ptr[CDataset]& sp)
52
+
53
+ @staticmethod
54
+ cdef wrap(const shared_ptr[CDataset]& sp)
55
+
56
+ cdef shared_ptr[CDataset] unwrap(self) nogil
57
+
58
+
59
+ cdef class Scanner(_Weakrefable):
60
+ cdef:
61
+ SharedPtrNoGIL[CScanner] wrapped
62
+ CScanner* scanner
63
+
64
+ cdef void init(self, const shared_ptr[CScanner]& sp)
65
+
66
+ @staticmethod
67
+ cdef wrap(const shared_ptr[CScanner]& sp)
68
+
69
+ cdef shared_ptr[CScanner] unwrap(self)
70
+
71
+ @staticmethod
72
+ cdef shared_ptr[CScanOptions] _make_scan_options(Dataset dataset, dict py_scanoptions) except *
73
+
74
+
75
+ cdef class FragmentScanOptions(_Weakrefable):
76
+
77
+ cdef:
78
+ shared_ptr[CFragmentScanOptions] wrapped
79
+
80
+ cdef void init(self, const shared_ptr[CFragmentScanOptions]& sp)
81
+
82
+ @staticmethod
83
+ cdef wrap(const shared_ptr[CFragmentScanOptions]& sp)
84
+
85
+
86
+ cdef class FileFormat(_Weakrefable):
87
+
88
+ cdef:
89
+ shared_ptr[CFileFormat] wrapped
90
+ CFileFormat* format
91
+
92
+ cdef void init(self, const shared_ptr[CFileFormat]& sp)
93
+
94
+ @staticmethod
95
+ cdef wrap(const shared_ptr[CFileFormat]& sp)
96
+
97
+ cdef inline shared_ptr[CFileFormat] unwrap(self)
98
+
99
+ cdef _set_default_fragment_scan_options(self, FragmentScanOptions options)
100
+
101
+ # Return a WrittenFile after a file was written.
102
+ # May be overridden by subclasses, e.g. to add metadata.
103
+ cdef WrittenFile _finish_write(self, path, base_dir,
104
+ CFileWriter* file_writer)
105
+
106
+
107
+ cdef class FileWriteOptions(_Weakrefable):
108
+
109
+ cdef:
110
+ shared_ptr[CFileWriteOptions] wrapped
111
+ CFileWriteOptions* c_options
112
+
113
+ cdef void init(self, const shared_ptr[CFileWriteOptions]& sp)
114
+
115
+ @staticmethod
116
+ cdef wrap(const shared_ptr[CFileWriteOptions]& sp)
117
+
118
+ cdef inline shared_ptr[CFileWriteOptions] unwrap(self)
119
+
120
+
121
+ cdef class Fragment(_Weakrefable):
122
+
123
+ cdef:
124
+ SharedPtrNoGIL[CFragment] wrapped
125
+ CFragment* fragment
126
+
127
+ cdef void init(self, const shared_ptr[CFragment]& sp)
128
+
129
+ @staticmethod
130
+ cdef wrap(const shared_ptr[CFragment]& sp)
131
+
132
+ cdef inline shared_ptr[CFragment] unwrap(self)
133
+
134
+
135
+ cdef class FileFragment(Fragment):
136
+
137
+ cdef:
138
+ CFileFragment* file_fragment
139
+
140
+ cdef void init(self, const shared_ptr[CFragment]& sp)
141
+
142
+
143
+ cdef class Partitioning(_Weakrefable):
144
+
145
+ cdef:
146
+ shared_ptr[CPartitioning] wrapped
147
+ CPartitioning* partitioning
148
+
149
+ cdef init(self, const shared_ptr[CPartitioning]& sp)
150
+
151
+ @staticmethod
152
+ cdef wrap(const shared_ptr[CPartitioning]& sp)
153
+
154
+ cdef inline shared_ptr[CPartitioning] unwrap(self)
155
+
156
+
157
+ cdef class PartitioningFactory(_Weakrefable):
158
+
159
+ cdef:
160
+ shared_ptr[CPartitioningFactory] wrapped
161
+ CPartitioningFactory* factory
162
+ object constructor
163
+ object options
164
+
165
+ cdef init(self, const shared_ptr[CPartitioningFactory]& sp)
166
+
167
+ @staticmethod
168
+ cdef wrap(const shared_ptr[CPartitioningFactory]& sp,
169
+ object constructor, object options)
170
+
171
+ cdef inline shared_ptr[CPartitioningFactory] unwrap(self)
172
+
173
+
174
+ cdef class WrittenFile(_Weakrefable):
175
+
176
+ # The full path to the created file
177
+ cdef public str path
178
+ # Optional Parquet metadata
179
+ # This metadata will have the file path attribute set to the path of
180
+ # the written file.
181
+ cdef public object metadata
182
+ # The size of the file in bytes
183
+ cdef public int64_t size
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_dataset_parquet.pxd ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ """Dataset support for Parquet file format."""
21
+
22
+ from pyarrow.includes.libarrow_dataset cimport *
23
+ from pyarrow.includes.libarrow_dataset_parquet cimport *
24
+
25
+ from pyarrow._dataset cimport FragmentScanOptions, FileWriteOptions
26
+
27
+
28
+ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
29
+ cdef:
30
+ CParquetFragmentScanOptions* parquet_options
31
+ object _parquet_decryption_config
32
+ object _decryption_properties
33
+
34
+ cdef void init(self, const shared_ptr[CFragmentScanOptions]& sp)
35
+ cdef CReaderProperties* reader_properties(self)
36
+ cdef ArrowReaderProperties* arrow_reader_properties(self)
37
+
38
+
39
+ cdef class ParquetFileWriteOptions(FileWriteOptions):
40
+
41
+ cdef:
42
+ CParquetFileWriteOptions* parquet_options
43
+ object _properties
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_feather.pyx ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # ---------------------------------------------------------------------
19
+ # Implement Feather file format
20
+
21
+ # cython: profile=False
22
+ # distutils: language = c++
23
+ # cython: language_level=3
24
+
25
+ from cython.operator cimport dereference as deref
26
+ from pyarrow.includes.common cimport *
27
+ from pyarrow.includes.libarrow cimport *
28
+ from pyarrow.includes.libarrow_feather cimport *
29
+ from pyarrow.lib cimport (check_status, Table, _Weakrefable,
30
+ get_writer, get_reader, pyarrow_wrap_table)
31
+ from pyarrow.lib import tobytes
32
+
33
+
34
+ class FeatherError(Exception):
35
+ pass
36
+
37
+
38
+ def write_feather(Table table, object dest, compression=None,
39
+ compression_level=None, chunksize=None, version=2):
40
+ cdef shared_ptr[COutputStream] sink
41
+ get_writer(dest, &sink)
42
+
43
+ cdef CFeatherProperties properties
44
+ if version == 2:
45
+ properties.version = kFeatherV2Version
46
+ else:
47
+ properties.version = kFeatherV1Version
48
+
49
+ if compression == 'zstd':
50
+ properties.compression = CCompressionType_ZSTD
51
+ elif compression == 'lz4':
52
+ properties.compression = CCompressionType_LZ4_FRAME
53
+ else:
54
+ properties.compression = CCompressionType_UNCOMPRESSED
55
+
56
+ if chunksize is not None:
57
+ properties.chunksize = chunksize
58
+
59
+ if compression_level is not None:
60
+ properties.compression_level = compression_level
61
+
62
+ with nogil:
63
+ check_status(WriteFeather(deref(table.table), sink.get(),
64
+ properties))
65
+
66
+
67
+ cdef class FeatherReader(_Weakrefable):
68
+ cdef:
69
+ shared_ptr[CFeatherReader] reader
70
+
71
+ def __cinit__(self, source, c_bool use_memory_map, c_bool use_threads):
72
+ cdef:
73
+ shared_ptr[CRandomAccessFile] reader
74
+ CIpcReadOptions options = CIpcReadOptions.Defaults()
75
+ options.use_threads = use_threads
76
+
77
+ get_reader(source, use_memory_map, &reader)
78
+ with nogil:
79
+ self.reader = GetResultValue(CFeatherReader.Open(reader, options))
80
+
81
+ @property
82
+ def version(self):
83
+ return self.reader.get().version()
84
+
85
+ def read(self):
86
+ cdef shared_ptr[CTable] sp_table
87
+ with nogil:
88
+ check_status(self.reader.get()
89
+ .Read(&sp_table))
90
+
91
+ return pyarrow_wrap_table(sp_table)
92
+
93
+ def read_indices(self, indices):
94
+ cdef:
95
+ shared_ptr[CTable] sp_table
96
+ vector[int] c_indices
97
+
98
+ for index in indices:
99
+ c_indices.push_back(index)
100
+ with nogil:
101
+ check_status(self.reader.get()
102
+ .Read(c_indices, &sp_table))
103
+
104
+ return pyarrow_wrap_table(sp_table)
105
+
106
+ def read_names(self, names):
107
+ cdef:
108
+ shared_ptr[CTable] sp_table
109
+ vector[c_string] c_names
110
+
111
+ for name in names:
112
+ c_names.push_back(tobytes(name))
113
+ with nogil:
114
+ check_status(self.reader.get()
115
+ .Read(c_names, &sp_table))
116
+
117
+ return pyarrow_wrap_table(sp_table)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_fs.pyx ADDED
@@ -0,0 +1,1628 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ from cpython.datetime cimport datetime, PyDateTime_DateTime
21
+ from cython cimport binding
22
+
23
+ from pyarrow.includes.common cimport *
24
+ from pyarrow.includes.libarrow_python cimport PyDateTime_to_TimePoint
25
+ from pyarrow.lib import _detect_compression, frombytes, tobytes
26
+ from pyarrow.lib cimport *
27
+ from pyarrow.util import _stringify_path
28
+
29
+ from abc import ABC, abstractmethod
30
+ from datetime import datetime, timezone
31
+ import os
32
+ import pathlib
33
+ import sys
34
+
35
+
36
+ cdef _init_ca_paths():
37
+ cdef CFileSystemGlobalOptions options
38
+
39
+ import ssl
40
+ paths = ssl.get_default_verify_paths()
41
+ if paths.cafile:
42
+ options.tls_ca_file_path = os.fsencode(paths.cafile)
43
+ if paths.capath:
44
+ options.tls_ca_dir_path = os.fsencode(paths.capath)
45
+ check_status(CFileSystemsInitialize(options))
46
+
47
+
48
+ if sys.platform == 'linux':
49
+ # ARROW-9261: On Linux, we may need to fixup the paths to TLS CA certs
50
+ # (especially in manylinux packages) since the values hardcoded at
51
+ # compile-time in libcurl may be wrong.
52
+ _init_ca_paths()
53
+
54
+
55
+ cdef inline c_string _path_as_bytes(path) except *:
56
+ # handle only abstract paths, not bound to any filesystem like pathlib is,
57
+ # so we only accept plain strings
58
+ if not isinstance(path, (bytes, str)):
59
+ raise TypeError('Path must be a string')
60
+ # tobytes always uses utf-8, which is more or less ok, at least on Windows
61
+ # since the C++ side then decodes from utf-8. On Unix, os.fsencode may be
62
+ # better.
63
+ return tobytes(path)
64
+
65
+
66
+ cdef object _wrap_file_type(CFileType ty):
67
+ return FileType(<int8_t> ty)
68
+
69
+
70
+ cdef CFileType _unwrap_file_type(FileType ty) except *:
71
+ if ty == FileType.Unknown:
72
+ return CFileType_Unknown
73
+ elif ty == FileType.NotFound:
74
+ return CFileType_NotFound
75
+ elif ty == FileType.File:
76
+ return CFileType_File
77
+ elif ty == FileType.Directory:
78
+ return CFileType_Directory
79
+ assert 0
80
+
81
+
82
+ def _file_type_to_string(ty):
83
+ # Python 3.11 changed str(IntEnum) to return the string representation
84
+ # of the integer value: https://github.com/python/cpython/issues/94763
85
+ return f"{ty.__class__.__name__}.{ty._name_}"
86
+
87
+
88
+ cdef class FileInfo(_Weakrefable):
89
+ """
90
+ FileSystem entry info.
91
+
92
+ Parameters
93
+ ----------
94
+ path : str
95
+ The full path to the filesystem entry.
96
+ type : FileType
97
+ The type of the filesystem entry.
98
+ mtime : datetime or float, default None
99
+ If given, the modification time of the filesystem entry.
100
+ If a float is given, it is the number of seconds since the
101
+ Unix epoch.
102
+ mtime_ns : int, default None
103
+ If given, the modification time of the filesystem entry,
104
+ in nanoseconds since the Unix epoch.
105
+ `mtime` and `mtime_ns` are mutually exclusive.
106
+ size : int, default None
107
+ If given, the filesystem entry size in bytes. This should only
108
+ be given if `type` is `FileType.File`.
109
+
110
+ Examples
111
+ --------
112
+ Generate a file:
113
+
114
+ >>> from pyarrow import fs
115
+ >>> local = fs.LocalFileSystem()
116
+ >>> path_fs = local_path + '/pyarrow-fs-example.dat'
117
+ >>> with local.open_output_stream(path_fs) as stream:
118
+ ... stream.write(b'data')
119
+ 4
120
+
121
+ Get FileInfo object using ``get_file_info()``:
122
+
123
+ >>> file_info = local.get_file_info(path_fs)
124
+ >>> file_info
125
+ <FileInfo for '.../pyarrow-fs-example.dat': type=FileType.File, size=4>
126
+
127
+ Inspect FileInfo attributes:
128
+
129
+ >>> file_info.type
130
+ <FileType.File: 2>
131
+
132
+ >>> file_info.is_file
133
+ True
134
+
135
+ >>> file_info.path
136
+ '/.../pyarrow-fs-example.dat'
137
+
138
+ >>> file_info.base_name
139
+ 'pyarrow-fs-example.dat'
140
+
141
+ >>> file_info.size
142
+ 4
143
+
144
+ >>> file_info.extension
145
+ 'dat'
146
+
147
+ >>> file_info.mtime # doctest: +SKIP
148
+ datetime.datetime(2022, 6, 29, 7, 56, 10, 873922, tzinfo=datetime.timezone.utc)
149
+
150
+ >>> file_info.mtime_ns # doctest: +SKIP
151
+ 1656489370873922073
152
+ """
153
+
154
+ def __init__(self, path, FileType type=FileType.Unknown, *,
155
+ mtime=None, mtime_ns=None, size=None):
156
+ self.info.set_path(tobytes(path))
157
+ self.info.set_type(_unwrap_file_type(type))
158
+ if mtime is not None:
159
+ if mtime_ns is not None:
160
+ raise TypeError("Only one of mtime and mtime_ns "
161
+ "can be given")
162
+ if isinstance(mtime, datetime):
163
+ self.info.set_mtime(PyDateTime_to_TimePoint(
164
+ <PyDateTime_DateTime*> mtime))
165
+ else:
166
+ self.info.set_mtime(TimePoint_from_s(mtime))
167
+ elif mtime_ns is not None:
168
+ self.info.set_mtime(TimePoint_from_ns(mtime_ns))
169
+ if size is not None:
170
+ self.info.set_size(size)
171
+
172
+ @staticmethod
173
+ cdef wrap(CFileInfo info):
174
+ cdef FileInfo self = FileInfo.__new__(FileInfo)
175
+ self.info = move(info)
176
+ return self
177
+
178
+ cdef inline CFileInfo unwrap(self) nogil:
179
+ return self.info
180
+
181
+ @staticmethod
182
+ cdef CFileInfo unwrap_safe(obj):
183
+ if not isinstance(obj, FileInfo):
184
+ raise TypeError("Expected FileInfo instance, got {0}"
185
+ .format(type(obj)))
186
+ return (<FileInfo> obj).unwrap()
187
+
188
+ def __repr__(self):
189
+ def getvalue(attr):
190
+ try:
191
+ return getattr(self, attr)
192
+ except ValueError:
193
+ return ''
194
+
195
+ s = (f'<FileInfo for {self.path!r}: '
196
+ f'type={_file_type_to_string(self.type)}')
197
+ if self.is_file:
198
+ s += f', size={self.size}'
199
+ s += '>'
200
+ return s
201
+
202
+ @property
203
+ def type(self):
204
+ """
205
+ Type of the file.
206
+
207
+ The returned enum values can be the following:
208
+
209
+ - FileType.NotFound: target does not exist
210
+ - FileType.Unknown: target exists but its type is unknown (could be a
211
+ special file such as a Unix socket or character device, or
212
+ Windows NUL / CON / ...)
213
+ - FileType.File: target is a regular file
214
+ - FileType.Directory: target is a regular directory
215
+
216
+ Returns
217
+ -------
218
+ type : FileType
219
+ """
220
+ return _wrap_file_type(self.info.type())
221
+
222
+ @property
223
+ def is_file(self):
224
+ """
225
+ """
226
+ return self.type == FileType.File
227
+
228
+ @property
229
+ def path(self):
230
+ """
231
+ The full file path in the filesystem.
232
+
233
+ Examples
234
+ --------
235
+ >>> file_info = local.get_file_info(path)
236
+ >>> file_info.path
237
+ '/.../pyarrow-fs-example.dat'
238
+ """
239
+ return frombytes(self.info.path())
240
+
241
+ @property
242
+ def base_name(self):
243
+ """
244
+ The file base name.
245
+
246
+ Component after the last directory separator.
247
+
248
+ Examples
249
+ --------
250
+ >>> file_info = local.get_file_info(path)
251
+ >>> file_info.base_name
252
+ 'pyarrow-fs-example.dat'
253
+ """
254
+ return frombytes(self.info.base_name())
255
+
256
+ @property
257
+ def size(self):
258
+ """
259
+ The size in bytes, if available.
260
+
261
+ Only regular files are guaranteed to have a size.
262
+
263
+ Returns
264
+ -------
265
+ size : int or None
266
+ """
267
+ cdef int64_t size
268
+ size = self.info.size()
269
+ return (size if size != -1 else None)
270
+
271
+ @property
272
+ def extension(self):
273
+ """
274
+ The file extension.
275
+
276
+ Examples
277
+ --------
278
+ >>> file_info = local.get_file_info(path)
279
+ >>> file_info.extension
280
+ 'dat'
281
+ """
282
+ return frombytes(self.info.extension())
283
+
284
+ @property
285
+ def mtime(self):
286
+ """
287
+ The time of last modification, if available.
288
+
289
+ Returns
290
+ -------
291
+ mtime : datetime.datetime or None
292
+
293
+ Examples
294
+ --------
295
+ >>> file_info = local.get_file_info(path)
296
+ >>> file_info.mtime # doctest: +SKIP
297
+ datetime.datetime(2022, 6, 29, 7, 56, 10, 873922, tzinfo=datetime.timezone.utc)
298
+ """
299
+ cdef int64_t nanoseconds
300
+ nanoseconds = TimePoint_to_ns(self.info.mtime())
301
+ return (datetime.fromtimestamp(nanoseconds / 1.0e9, timezone.utc)
302
+ if nanoseconds != -1 else None)
303
+
304
+ @property
305
+ def mtime_ns(self):
306
+ """
307
+ The time of last modification, if available, expressed in nanoseconds
308
+ since the Unix epoch.
309
+
310
+ Returns
311
+ -------
312
+ mtime_ns : int or None
313
+
314
+ Examples
315
+ --------
316
+ >>> file_info = local.get_file_info(path)
317
+ >>> file_info.mtime_ns # doctest: +SKIP
318
+ 1656489370873922073
319
+ """
320
+ cdef int64_t nanoseconds
321
+ nanoseconds = TimePoint_to_ns(self.info.mtime())
322
+ return (nanoseconds if nanoseconds != -1 else None)
323
+
324
+
325
+ cdef class FileSelector(_Weakrefable):
326
+ """
327
+ File and directory selector.
328
+
329
+ It contains a set of options that describes how to search for files and
330
+ directories.
331
+
332
+ Parameters
333
+ ----------
334
+ base_dir : str
335
+ The directory in which to select files. Relative paths also work, use
336
+ '.' for the current directory and '..' for the parent.
337
+ allow_not_found : bool, default False
338
+ The behavior if `base_dir` doesn't exist in the filesystem.
339
+ If false, an error is returned.
340
+ If true, an empty selection is returned.
341
+ recursive : bool, default False
342
+ Whether to recurse into subdirectories.
343
+
344
+ Examples
345
+ --------
346
+ List the contents of a directory and subdirectories:
347
+
348
+ >>> selector_1 = fs.FileSelector(local_path, recursive=True)
349
+ >>> local.get_file_info(selector_1) # doctest: +SKIP
350
+ [<FileInfo for 'tmp/alphabet/example.dat': type=FileType.File, size=4>,
351
+ <FileInfo for 'tmp/alphabet/subdir': type=FileType.Directory>,
352
+ <FileInfo for 'tmp/alphabet/subdir/example_copy.dat': type=FileType.File, size=4>]
353
+
354
+ List only the contents of the base directory:
355
+
356
+ >>> selector_2 = fs.FileSelector(local_path)
357
+ >>> local.get_file_info(selector_2) # doctest: +SKIP
358
+ [<FileInfo for 'tmp/alphabet/example.dat': type=FileType.File, size=4>,
359
+ <FileInfo for 'tmp/alphabet/subdir': type=FileType.Directory>]
360
+
361
+ Return empty selection if the directory doesn't exist:
362
+
363
+ >>> selector_not_found = fs.FileSelector(local_path + '/missing',
364
+ ... recursive=True,
365
+ ... allow_not_found=True)
366
+ >>> local.get_file_info(selector_not_found)
367
+ []
368
+ """
369
+
370
+ def __init__(self, base_dir, bint allow_not_found=False,
371
+ bint recursive=False):
372
+ self.base_dir = base_dir
373
+ self.recursive = recursive
374
+ self.allow_not_found = allow_not_found
375
+
376
+ @staticmethod
377
+ cdef FileSelector wrap(CFileSelector wrapped):
378
+ cdef FileSelector self = FileSelector.__new__(FileSelector)
379
+ self.selector = move(wrapped)
380
+ return self
381
+
382
+ cdef inline CFileSelector unwrap(self) nogil:
383
+ return self.selector
384
+
385
+ @property
386
+ def base_dir(self):
387
+ return frombytes(self.selector.base_dir)
388
+
389
+ @base_dir.setter
390
+ def base_dir(self, base_dir):
391
+ self.selector.base_dir = _path_as_bytes(base_dir)
392
+
393
+ @property
394
+ def allow_not_found(self):
395
+ return self.selector.allow_not_found
396
+
397
+ @allow_not_found.setter
398
+ def allow_not_found(self, bint allow_not_found):
399
+ self.selector.allow_not_found = allow_not_found
400
+
401
+ @property
402
+ def recursive(self):
403
+ return self.selector.recursive
404
+
405
+ @recursive.setter
406
+ def recursive(self, bint recursive):
407
+ self.selector.recursive = recursive
408
+
409
+ def __repr__(self):
410
+ return ("<FileSelector base_dir={0.base_dir!r} "
411
+ "recursive={0.recursive}>".format(self))
412
+
413
+
414
+ cdef class FileSystem(_Weakrefable):
415
+ """
416
+ Abstract file system API.
417
+ """
418
+
419
+ def __init__(self):
420
+ raise TypeError("FileSystem is an abstract class, instantiate one of "
421
+ "the subclasses instead: LocalFileSystem or "
422
+ "SubTreeFileSystem")
423
+
424
+ @staticmethod
425
+ @binding(True) # Required for cython < 3
426
+ def _from_uri(uri):
427
+ fs, _path = FileSystem.from_uri(uri)
428
+ return fs
429
+
430
+ @staticmethod
431
+ def from_uri(uri):
432
+ """
433
+ Create a new FileSystem from URI or Path.
434
+
435
+ Recognized URI schemes are "file", "mock", "s3fs", "gs", "gcs", "hdfs" and "viewfs".
436
+ In addition, the argument can be a pathlib.Path object, or a string
437
+ describing an absolute local path.
438
+
439
+ Parameters
440
+ ----------
441
+ uri : string
442
+ URI-based path, for example: file:///some/local/path.
443
+
444
+ Returns
445
+ -------
446
+ tuple of (FileSystem, str path)
447
+ With (filesystem, path) tuple where path is the abstract path
448
+ inside the FileSystem instance.
449
+
450
+ Examples
451
+ --------
452
+ Create a new FileSystem subclass from a URI:
453
+
454
+ >>> uri = 'file:///{}/pyarrow-fs-example.dat'.format(local_path)
455
+ >>> local_new, path_new = fs.FileSystem.from_uri(uri)
456
+ >>> local_new
457
+ <pyarrow._fs.LocalFileSystem object at ...
458
+ >>> path_new
459
+ '/.../pyarrow-fs-example.dat'
460
+
461
+ Or from a s3 bucket:
462
+
463
+ >>> fs.FileSystem.from_uri("s3://usgs-landsat/collection02/")
464
+ (<pyarrow._s3fs.S3FileSystem object at ...>, 'usgs-landsat/collection02')
465
+ """
466
+ cdef:
467
+ c_string c_path
468
+ c_string c_uri
469
+ CResult[shared_ptr[CFileSystem]] result
470
+
471
+ if isinstance(uri, pathlib.Path):
472
+ # Make absolute
473
+ uri = uri.resolve().absolute()
474
+ c_uri = tobytes(_stringify_path(uri))
475
+ with nogil:
476
+ result = CFileSystemFromUriOrPath(c_uri, &c_path)
477
+ return FileSystem.wrap(GetResultValue(result)), frombytes(c_path)
478
+
479
+ cdef init(self, const shared_ptr[CFileSystem]& wrapped):
480
+ self.wrapped = wrapped
481
+ self.fs = wrapped.get()
482
+
483
+ @staticmethod
484
+ cdef wrap(const shared_ptr[CFileSystem]& sp):
485
+ cdef FileSystem self
486
+
487
+ typ = frombytes(sp.get().type_name())
488
+ if typ == 'local':
489
+ self = LocalFileSystem.__new__(LocalFileSystem)
490
+ elif typ == 'mock':
491
+ self = _MockFileSystem.__new__(_MockFileSystem)
492
+ elif typ == 'subtree':
493
+ self = SubTreeFileSystem.__new__(SubTreeFileSystem)
494
+ elif typ == 's3':
495
+ from pyarrow._s3fs import S3FileSystem
496
+ self = S3FileSystem.__new__(S3FileSystem)
497
+ elif typ == 'gcs':
498
+ from pyarrow._gcsfs import GcsFileSystem
499
+ self = GcsFileSystem.__new__(GcsFileSystem)
500
+ elif typ == 'abfs':
501
+ from pyarrow._azurefs import AzureFileSystem
502
+ self = AzureFileSystem.__new__(AzureFileSystem)
503
+ elif typ == 'hdfs':
504
+ from pyarrow._hdfs import HadoopFileSystem
505
+ self = HadoopFileSystem.__new__(HadoopFileSystem)
506
+ elif typ.startswith('py::'):
507
+ self = PyFileSystem.__new__(PyFileSystem)
508
+ else:
509
+ raise TypeError('Cannot wrap FileSystem pointer')
510
+
511
+ self.init(sp)
512
+ return self
513
+
514
+ cdef inline shared_ptr[CFileSystem] unwrap(self) nogil:
515
+ return self.wrapped
516
+
517
+ def equals(self, FileSystem other not None):
518
+ """
519
+ Parameters
520
+ ----------
521
+ other : pyarrow.fs.FileSystem
522
+
523
+ Returns
524
+ -------
525
+ bool
526
+ """
527
+ return self.fs.Equals(other.unwrap())
528
+
529
+ def __eq__(self, other):
530
+ try:
531
+ return self.equals(other)
532
+ except TypeError:
533
+ return NotImplemented
534
+
535
+ @property
536
+ def type_name(self):
537
+ """
538
+ The filesystem's type name.
539
+ """
540
+ return frombytes(self.fs.type_name())
541
+
542
+ def get_file_info(self, paths_or_selector):
543
+ """
544
+ Get info for the given files.
545
+
546
+ Any symlink is automatically dereferenced, recursively. A non-existing
547
+ or unreachable file returns a FileStat object and has a FileType of
548
+ value NotFound. An exception indicates a truly exceptional condition
549
+ (low-level I/O error, etc.).
550
+
551
+ Parameters
552
+ ----------
553
+ paths_or_selector : FileSelector, path-like or list of path-likes
554
+ Either a selector object, a path-like object or a list of
555
+ path-like objects. The selector's base directory will not be
556
+ part of the results, even if it exists. If it doesn't exist,
557
+ use `allow_not_found`.
558
+
559
+ Returns
560
+ -------
561
+ FileInfo or list of FileInfo
562
+ Single FileInfo object is returned for a single path, otherwise
563
+ a list of FileInfo objects is returned.
564
+
565
+ Examples
566
+ --------
567
+ >>> local
568
+ <pyarrow._fs.LocalFileSystem object at ...>
569
+ >>> local.get_file_info("/{}/pyarrow-fs-example.dat".format(local_path))
570
+ <FileInfo for '/.../pyarrow-fs-example.dat': type=FileType.File, size=4>
571
+ """
572
+ cdef:
573
+ CFileInfo info
574
+ c_string path
575
+ vector[CFileInfo] infos
576
+ vector[c_string] paths
577
+ CFileSelector selector
578
+
579
+ if isinstance(paths_or_selector, FileSelector):
580
+ with nogil:
581
+ selector = (<FileSelector>paths_or_selector).selector
582
+ infos = GetResultValue(self.fs.GetFileInfo(selector))
583
+ elif isinstance(paths_or_selector, (list, tuple)):
584
+ paths = [_path_as_bytes(s) for s in paths_or_selector]
585
+ with nogil:
586
+ infos = GetResultValue(self.fs.GetFileInfo(paths))
587
+ elif isinstance(paths_or_selector, (bytes, str)):
588
+ path =_path_as_bytes(paths_or_selector)
589
+ with nogil:
590
+ info = GetResultValue(self.fs.GetFileInfo(path))
591
+ return FileInfo.wrap(info)
592
+ else:
593
+ raise TypeError('Must pass either path(s) or a FileSelector')
594
+
595
+ return [FileInfo.wrap(info) for info in infos]
596
+
597
+ def create_dir(self, path, *, bint recursive=True):
598
+ """
599
+ Create a directory and subdirectories.
600
+
601
+ This function succeeds if the directory already exists.
602
+
603
+ Parameters
604
+ ----------
605
+ path : str
606
+ The path of the new directory.
607
+ recursive : bool, default True
608
+ Create nested directories as well.
609
+ """
610
+ cdef c_string directory = _path_as_bytes(path)
611
+ with nogil:
612
+ check_status(self.fs.CreateDir(directory, recursive=recursive))
613
+
614
+ def delete_dir(self, path):
615
+ """
616
+ Delete a directory and its contents, recursively.
617
+
618
+ Parameters
619
+ ----------
620
+ path : str
621
+ The path of the directory to be deleted.
622
+ """
623
+ cdef c_string directory = _path_as_bytes(path)
624
+ with nogil:
625
+ check_status(self.fs.DeleteDir(directory))
626
+
627
+ def delete_dir_contents(self, path, *,
628
+ bint accept_root_dir=False,
629
+ bint missing_dir_ok=False):
630
+ """
631
+ Delete a directory's contents, recursively.
632
+
633
+ Like delete_dir, but doesn't delete the directory itself.
634
+
635
+ Parameters
636
+ ----------
637
+ path : str
638
+ The path of the directory to be deleted.
639
+ accept_root_dir : boolean, default False
640
+ Allow deleting the root directory's contents
641
+ (if path is empty or "/")
642
+ missing_dir_ok : boolean, default False
643
+ If False then an error is raised if path does
644
+ not exist
645
+ """
646
+ cdef c_string directory = _path_as_bytes(path)
647
+ if accept_root_dir and directory.strip(b"/") == b"":
648
+ with nogil:
649
+ check_status(self.fs.DeleteRootDirContents())
650
+ else:
651
+ with nogil:
652
+ check_status(self.fs.DeleteDirContents(directory,
653
+ missing_dir_ok))
654
+
655
+ def move(self, src, dest):
656
+ """
657
+ Move / rename a file or directory.
658
+
659
+ If the destination exists:
660
+ - if it is a non-empty directory, an error is returned
661
+ - otherwise, if it has the same type as the source, it is replaced
662
+ - otherwise, behavior is unspecified (implementation-dependent).
663
+
664
+ Parameters
665
+ ----------
666
+ src : str
667
+ The path of the file or the directory to be moved.
668
+ dest : str
669
+ The destination path where the file or directory is moved to.
670
+
671
+ Examples
672
+ --------
673
+ Create a new folder with a file:
674
+
675
+ >>> local.create_dir('/tmp/other_dir')
676
+ >>> local.copy_file(path,'/tmp/move_example.dat')
677
+
678
+ Move the file:
679
+
680
+ >>> local.move('/tmp/move_example.dat',
681
+ ... '/tmp/other_dir/move_example_2.dat')
682
+
683
+ Inspect the file info:
684
+
685
+ >>> local.get_file_info('/tmp/other_dir/move_example_2.dat')
686
+ <FileInfo for '/tmp/other_dir/move_example_2.dat': type=FileType.File, size=4>
687
+ >>> local.get_file_info('/tmp/move_example.dat')
688
+ <FileInfo for '/tmp/move_example.dat': type=FileType.NotFound>
689
+
690
+ Delete the folder:
691
+ >>> local.delete_dir('/tmp/other_dir')
692
+ """
693
+ cdef:
694
+ c_string source = _path_as_bytes(src)
695
+ c_string destination = _path_as_bytes(dest)
696
+ with nogil:
697
+ check_status(self.fs.Move(source, destination))
698
+
699
+ def copy_file(self, src, dest):
700
+ """
701
+ Copy a file.
702
+
703
+ If the destination exists and is a directory, an error is returned.
704
+ Otherwise, it is replaced.
705
+
706
+ Parameters
707
+ ----------
708
+ src : str
709
+ The path of the file to be copied from.
710
+ dest : str
711
+ The destination path where the file is copied to.
712
+
713
+ Examples
714
+ --------
715
+ >>> local.copy_file(path,
716
+ ... local_path + '/pyarrow-fs-example_copy.dat')
717
+
718
+ Inspect the file info:
719
+
720
+ >>> local.get_file_info(local_path + '/pyarrow-fs-example_copy.dat')
721
+ <FileInfo for '/.../pyarrow-fs-example_copy.dat': type=FileType.File, size=4>
722
+ >>> local.get_file_info(path)
723
+ <FileInfo for '/.../pyarrow-fs-example.dat': type=FileType.File, size=4>
724
+ """
725
+ cdef:
726
+ c_string source = _path_as_bytes(src)
727
+ c_string destination = _path_as_bytes(dest)
728
+ with nogil:
729
+ check_status(self.fs.CopyFile(source, destination))
730
+
731
+ def delete_file(self, path):
732
+ """
733
+ Delete a file.
734
+
735
+ Parameters
736
+ ----------
737
+ path : str
738
+ The path of the file to be deleted.
739
+ """
740
+ cdef c_string file = _path_as_bytes(path)
741
+ with nogil:
742
+ check_status(self.fs.DeleteFile(file))
743
+
744
+ def _wrap_input_stream(self, stream, path, compression, buffer_size):
745
+ if buffer_size is not None and buffer_size != 0:
746
+ stream = BufferedInputStream(stream, buffer_size)
747
+ if compression == 'detect':
748
+ compression = _detect_compression(path)
749
+ if compression is not None:
750
+ stream = CompressedInputStream(stream, compression)
751
+ return stream
752
+
753
+ def _wrap_output_stream(self, stream, path, compression, buffer_size):
754
+ if buffer_size is not None and buffer_size != 0:
755
+ stream = BufferedOutputStream(stream, buffer_size)
756
+ if compression == 'detect':
757
+ compression = _detect_compression(path)
758
+ if compression is not None:
759
+ stream = CompressedOutputStream(stream, compression)
760
+ return stream
761
+
762
+ def open_input_file(self, path):
763
+ """
764
+ Open an input file for random access reading.
765
+
766
+ Parameters
767
+ ----------
768
+ path : str
769
+ The source to open for reading.
770
+
771
+ Returns
772
+ -------
773
+ stream : NativeFile
774
+
775
+ Examples
776
+ --------
777
+ Print the data from the file with `open_input_file()`:
778
+
779
+ >>> with local.open_input_file(path) as f:
780
+ ... print(f.readall())
781
+ b'data'
782
+ """
783
+ cdef:
784
+ c_string pathstr = _path_as_bytes(path)
785
+ NativeFile stream = NativeFile()
786
+ shared_ptr[CRandomAccessFile] in_handle
787
+
788
+ with nogil:
789
+ in_handle = GetResultValue(self.fs.OpenInputFile(pathstr))
790
+
791
+ stream.set_random_access_file(in_handle)
792
+ stream.is_readable = True
793
+ return stream
794
+
795
+ def open_input_stream(self, path, compression='detect', buffer_size=None):
796
+ """
797
+ Open an input stream for sequential reading.
798
+
799
+ Parameters
800
+ ----------
801
+ path : str
802
+ The source to open for reading.
803
+ compression : str optional, default 'detect'
804
+ The compression algorithm to use for on-the-fly decompression.
805
+ If "detect" and source is a file path, then compression will be
806
+ chosen based on the file extension.
807
+ If None, no compression will be applied. Otherwise, a well-known
808
+ algorithm name must be supplied (e.g. "gzip").
809
+ buffer_size : int optional, default None
810
+ If None or 0, no buffering will happen. Otherwise the size of the
811
+ temporary read buffer.
812
+
813
+ Returns
814
+ -------
815
+ stream : NativeFile
816
+
817
+ Examples
818
+ --------
819
+ Print the data from the file with `open_input_stream()`:
820
+
821
+ >>> with local.open_input_stream(path) as f:
822
+ ... print(f.readall())
823
+ b'data'
824
+ """
825
+ cdef:
826
+ c_string pathstr = _path_as_bytes(path)
827
+ NativeFile stream = NativeFile()
828
+ shared_ptr[CInputStream] in_handle
829
+
830
+ with nogil:
831
+ in_handle = GetResultValue(self.fs.OpenInputStream(pathstr))
832
+
833
+ stream.set_input_stream(in_handle)
834
+ stream.is_readable = True
835
+
836
+ return self._wrap_input_stream(
837
+ stream, path=path, compression=compression, buffer_size=buffer_size
838
+ )
839
+
840
+ def open_output_stream(self, path, compression='detect',
841
+ buffer_size=None, metadata=None):
842
+ """
843
+ Open an output stream for sequential writing.
844
+
845
+ If the target already exists, existing data is truncated.
846
+
847
+ Parameters
848
+ ----------
849
+ path : str
850
+ The source to open for writing.
851
+ compression : str optional, default 'detect'
852
+ The compression algorithm to use for on-the-fly compression.
853
+ If "detect" and source is a file path, then compression will be
854
+ chosen based on the file extension.
855
+ If None, no compression will be applied. Otherwise, a well-known
856
+ algorithm name must be supplied (e.g. "gzip").
857
+ buffer_size : int optional, default None
858
+ If None or 0, no buffering will happen. Otherwise the size of the
859
+ temporary write buffer.
860
+ metadata : dict optional, default None
861
+ If not None, a mapping of string keys to string values.
862
+ Some filesystems support storing metadata along the file
863
+ (such as "Content-Type").
864
+ Unsupported metadata keys will be ignored.
865
+
866
+ Returns
867
+ -------
868
+ stream : NativeFile
869
+
870
+ Examples
871
+ --------
872
+ >>> local = fs.LocalFileSystem()
873
+ >>> with local.open_output_stream(path) as stream:
874
+ ... stream.write(b'data')
875
+ 4
876
+ """
877
+ cdef:
878
+ c_string pathstr = _path_as_bytes(path)
879
+ NativeFile stream = NativeFile()
880
+ shared_ptr[COutputStream] out_handle
881
+ shared_ptr[const CKeyValueMetadata] c_metadata
882
+
883
+ if metadata is not None:
884
+ c_metadata = pyarrow_unwrap_metadata(KeyValueMetadata(metadata))
885
+
886
+ with nogil:
887
+ out_handle = GetResultValue(
888
+ self.fs.OpenOutputStream(pathstr, c_metadata))
889
+
890
+ stream.set_output_stream(out_handle)
891
+ stream.is_writable = True
892
+
893
+ return self._wrap_output_stream(
894
+ stream, path=path, compression=compression, buffer_size=buffer_size
895
+ )
896
+
897
+ def open_append_stream(self, path, compression='detect',
898
+ buffer_size=None, metadata=None):
899
+ """
900
+ Open an output stream for appending.
901
+
902
+ If the target doesn't exist, a new empty file is created.
903
+
904
+ .. note::
905
+ Some filesystem implementations do not support efficient
906
+ appending to an existing file, in which case this method will
907
+ raise NotImplementedError.
908
+ Consider writing to multiple files (using e.g. the dataset layer)
909
+ instead.
910
+
911
+ Parameters
912
+ ----------
913
+ path : str
914
+ The source to open for writing.
915
+ compression : str optional, default 'detect'
916
+ The compression algorithm to use for on-the-fly compression.
917
+ If "detect" and source is a file path, then compression will be
918
+ chosen based on the file extension.
919
+ If None, no compression will be applied. Otherwise, a well-known
920
+ algorithm name must be supplied (e.g. "gzip").
921
+ buffer_size : int optional, default None
922
+ If None or 0, no buffering will happen. Otherwise the size of the
923
+ temporary write buffer.
924
+ metadata : dict optional, default None
925
+ If not None, a mapping of string keys to string values.
926
+ Some filesystems support storing metadata along the file
927
+ (such as "Content-Type").
928
+ Unsupported metadata keys will be ignored.
929
+
930
+ Returns
931
+ -------
932
+ stream : NativeFile
933
+
934
+ Examples
935
+ --------
936
+ Append new data to a FileSystem subclass with nonempty file:
937
+
938
+ >>> with local.open_append_stream(path) as f:
939
+ ... f.write(b'+newly added')
940
+ 12
941
+
942
+ Print out the content to the file:
943
+
944
+ >>> with local.open_input_file(path) as f:
945
+ ... print(f.readall())
946
+ b'data+newly added'
947
+ """
948
+ cdef:
949
+ c_string pathstr = _path_as_bytes(path)
950
+ NativeFile stream = NativeFile()
951
+ shared_ptr[COutputStream] out_handle
952
+ shared_ptr[const CKeyValueMetadata] c_metadata
953
+
954
+ if metadata is not None:
955
+ c_metadata = pyarrow_unwrap_metadata(KeyValueMetadata(metadata))
956
+
957
+ with nogil:
958
+ out_handle = GetResultValue(
959
+ self.fs.OpenAppendStream(pathstr, c_metadata))
960
+
961
+ stream.set_output_stream(out_handle)
962
+ stream.is_writable = True
963
+
964
+ return self._wrap_output_stream(
965
+ stream, path=path, compression=compression, buffer_size=buffer_size
966
+ )
967
+
968
+ def normalize_path(self, path):
969
+ """
970
+ Normalize filesystem path.
971
+
972
+ Parameters
973
+ ----------
974
+ path : str
975
+ The path to normalize
976
+
977
+ Returns
978
+ -------
979
+ normalized_path : str
980
+ The normalized path
981
+ """
982
+ cdef:
983
+ c_string c_path = _path_as_bytes(path)
984
+ c_string c_path_normalized
985
+
986
+ c_path_normalized = GetResultValue(self.fs.NormalizePath(c_path))
987
+ return frombytes(c_path_normalized)
988
+
989
+
990
+ cdef class LocalFileSystem(FileSystem):
991
+ """
992
+ A FileSystem implementation accessing files on the local machine.
993
+
994
+ Details such as symlinks are abstracted away (symlinks are always followed,
995
+ except when deleting an entry).
996
+
997
+ Parameters
998
+ ----------
999
+ use_mmap : bool, default False
1000
+ Whether open_input_stream and open_input_file should return
1001
+ a mmap'ed file or a regular file.
1002
+
1003
+ Examples
1004
+ --------
1005
+ Create a FileSystem object with LocalFileSystem constructor:
1006
+
1007
+ >>> from pyarrow import fs
1008
+ >>> local = fs.LocalFileSystem()
1009
+ >>> local
1010
+ <pyarrow._fs.LocalFileSystem object at ...>
1011
+
1012
+ and write data on to the file:
1013
+
1014
+ >>> with local.open_output_stream('/tmp/local_fs.dat') as stream:
1015
+ ... stream.write(b'data')
1016
+ 4
1017
+ >>> with local.open_input_stream('/tmp/local_fs.dat') as stream:
1018
+ ... print(stream.readall())
1019
+ b'data'
1020
+
1021
+ Create a FileSystem object inferred from a URI of the saved file:
1022
+
1023
+ >>> local_new, path = fs.LocalFileSystem().from_uri('/tmp/local_fs.dat')
1024
+ >>> local_new
1025
+ <pyarrow._fs.LocalFileSystem object at ...
1026
+ >>> path
1027
+ '/tmp/local_fs.dat'
1028
+
1029
+ Check if FileSystems `local` and `local_new` are equal:
1030
+
1031
+ >>> local.equals(local_new)
1032
+ True
1033
+
1034
+ Compare two different FileSystems:
1035
+
1036
+ >>> local2 = fs.LocalFileSystem(use_mmap=True)
1037
+ >>> local.equals(local2)
1038
+ False
1039
+
1040
+ Copy a file and print out the data:
1041
+
1042
+ >>> local.copy_file('/tmp/local_fs.dat', '/tmp/local_fs-copy.dat')
1043
+ >>> with local.open_input_stream('/tmp/local_fs-copy.dat') as stream:
1044
+ ... print(stream.readall())
1045
+ ...
1046
+ b'data'
1047
+
1048
+ Open an output stream for appending, add text and print the new data:
1049
+
1050
+ >>> with local.open_append_stream('/tmp/local_fs-copy.dat') as f:
1051
+ ... f.write(b'+newly added')
1052
+ 12
1053
+
1054
+ >>> with local.open_input_stream('/tmp/local_fs-copy.dat') as f:
1055
+ ... print(f.readall())
1056
+ b'data+newly added'
1057
+
1058
+ Create a directory, copy a file into it and then delete the whole directory:
1059
+
1060
+ >>> local.create_dir('/tmp/new_folder')
1061
+ >>> local.copy_file('/tmp/local_fs.dat', '/tmp/new_folder/local_fs.dat')
1062
+ >>> local.get_file_info('/tmp/new_folder')
1063
+ <FileInfo for '/tmp/new_folder': type=FileType.Directory>
1064
+ >>> local.delete_dir('/tmp/new_folder')
1065
+ >>> local.get_file_info('/tmp/new_folder')
1066
+ <FileInfo for '/tmp/new_folder': type=FileType.NotFound>
1067
+
1068
+ Create a directory, copy a file into it and then delete
1069
+ the content of the directory:
1070
+
1071
+ >>> local.create_dir('/tmp/new_folder')
1072
+ >>> local.copy_file('/tmp/local_fs.dat', '/tmp/new_folder/local_fs.dat')
1073
+ >>> local.get_file_info('/tmp/new_folder/local_fs.dat')
1074
+ <FileInfo for '/tmp/new_folder/local_fs.dat': type=FileType.File, size=4>
1075
+ >>> local.delete_dir_contents('/tmp/new_folder')
1076
+ >>> local.get_file_info('/tmp/new_folder')
1077
+ <FileInfo for '/tmp/new_folder': type=FileType.Directory>
1078
+ >>> local.get_file_info('/tmp/new_folder/local_fs.dat')
1079
+ <FileInfo for '/tmp/new_folder/local_fs.dat': type=FileType.NotFound>
1080
+
1081
+ Create a directory, copy a file into it and then delete
1082
+ the file from the directory:
1083
+
1084
+ >>> local.create_dir('/tmp/new_folder')
1085
+ >>> local.copy_file('/tmp/local_fs.dat', '/tmp/new_folder/local_fs.dat')
1086
+ >>> local.delete_file('/tmp/new_folder/local_fs.dat')
1087
+ >>> local.get_file_info('/tmp/new_folder/local_fs.dat')
1088
+ <FileInfo for '/tmp/new_folder/local_fs.dat': type=FileType.NotFound>
1089
+ >>> local.get_file_info('/tmp/new_folder')
1090
+ <FileInfo for '/tmp/new_folder': type=FileType.Directory>
1091
+
1092
+ Move the file:
1093
+
1094
+ >>> local.move('/tmp/local_fs-copy.dat', '/tmp/new_folder/local_fs-copy.dat')
1095
+ >>> local.get_file_info('/tmp/new_folder/local_fs-copy.dat')
1096
+ <FileInfo for '/tmp/new_folder/local_fs-copy.dat': type=FileType.File, size=16>
1097
+ >>> local.get_file_info('/tmp/local_fs-copy.dat')
1098
+ <FileInfo for '/tmp/local_fs-copy.dat': type=FileType.NotFound>
1099
+
1100
+ To finish delete the file left:
1101
+ >>> local.delete_file('/tmp/local_fs.dat')
1102
+ """
1103
+
1104
+ def __init__(self, *, use_mmap=False):
1105
+ cdef:
1106
+ shared_ptr[CFileSystem] fs
1107
+ c_string c_uri
1108
+
1109
+ # from_uri needs a non-empty path, so just use a placeholder of /_
1110
+ c_uri = tobytes(f"file:///_?use_mmap={int(use_mmap)}")
1111
+ with nogil:
1112
+ fs = GetResultValue(CFileSystemFromUri(c_uri))
1113
+ self.init(<shared_ptr[CFileSystem]> fs)
1114
+
1115
+ def __reduce__(self):
1116
+ uri = frombytes(GetResultValue(self.fs.MakeUri(b"/_")))
1117
+ return FileSystem._from_uri, (uri,)
1118
+
1119
+
1120
+ cdef class SubTreeFileSystem(FileSystem):
1121
+ """
1122
+ Delegates to another implementation after prepending a fixed base path.
1123
+
1124
+ This is useful to expose a logical view of a subtree of a filesystem,
1125
+ for example a directory in a LocalFileSystem.
1126
+
1127
+ Note, that this makes no security guarantee. For example, symlinks may
1128
+ allow to "escape" the subtree and access other parts of the underlying
1129
+ filesystem.
1130
+
1131
+ Parameters
1132
+ ----------
1133
+ base_path : str
1134
+ The root of the subtree.
1135
+ base_fs : FileSystem
1136
+ FileSystem object the operations delegated to.
1137
+
1138
+ Examples
1139
+ --------
1140
+ Create a LocalFileSystem instance:
1141
+
1142
+ >>> from pyarrow import fs
1143
+ >>> local = fs.LocalFileSystem()
1144
+ >>> with local.open_output_stream('/tmp/local_fs.dat') as stream:
1145
+ ... stream.write(b'data')
1146
+ 4
1147
+
1148
+ Create a directory and a SubTreeFileSystem instance:
1149
+
1150
+ >>> local.create_dir('/tmp/sub_tree')
1151
+ >>> subtree = fs.SubTreeFileSystem('/tmp/sub_tree', local)
1152
+
1153
+ Write data into the existing file:
1154
+
1155
+ >>> with subtree.open_append_stream('sub_tree_fs.dat') as f:
1156
+ ... f.write(b'+newly added')
1157
+ 12
1158
+
1159
+ Print out the attributes:
1160
+
1161
+ >>> subtree.base_fs
1162
+ <pyarrow._fs.LocalFileSystem object at ...>
1163
+ >>> subtree.base_path
1164
+ '/tmp/sub_tree/'
1165
+
1166
+ Get info for the given directory or given file:
1167
+
1168
+ >>> subtree.get_file_info('')
1169
+ <FileInfo for '': type=FileType.Directory>
1170
+ >>> subtree.get_file_info('sub_tree_fs.dat')
1171
+ <FileInfo for 'sub_tree_fs.dat': type=FileType.File, size=12>
1172
+
1173
+ Delete the file and directory:
1174
+
1175
+ >>> subtree.delete_file('sub_tree_fs.dat')
1176
+ >>> local.delete_dir('/tmp/sub_tree')
1177
+ >>> local.delete_file('/tmp/local_fs.dat')
1178
+
1179
+ For usage of the methods see examples for :func:`~pyarrow.fs.LocalFileSystem`.
1180
+ """
1181
+
1182
+ def __init__(self, base_path, FileSystem base_fs):
1183
+ cdef:
1184
+ c_string pathstr
1185
+ shared_ptr[CSubTreeFileSystem] wrapped
1186
+
1187
+ pathstr = _path_as_bytes(base_path)
1188
+ wrapped = make_shared[CSubTreeFileSystem](pathstr, base_fs.wrapped)
1189
+
1190
+ self.init(<shared_ptr[CFileSystem]> wrapped)
1191
+
1192
+ cdef init(self, const shared_ptr[CFileSystem]& wrapped):
1193
+ FileSystem.init(self, wrapped)
1194
+ self.subtreefs = <CSubTreeFileSystem*> wrapped.get()
1195
+
1196
+ def __repr__(self):
1197
+ return ("SubTreeFileSystem(base_path={}, base_fs={}"
1198
+ .format(self.base_path, self.base_fs))
1199
+
1200
+ def __reduce__(self):
1201
+ return SubTreeFileSystem, (
1202
+ frombytes(self.subtreefs.base_path()),
1203
+ FileSystem.wrap(self.subtreefs.base_fs())
1204
+ )
1205
+
1206
+ @property
1207
+ def base_path(self):
1208
+ return frombytes(self.subtreefs.base_path())
1209
+
1210
+ @property
1211
+ def base_fs(self):
1212
+ return FileSystem.wrap(self.subtreefs.base_fs())
1213
+
1214
+
1215
+ cdef class _MockFileSystem(FileSystem):
1216
+
1217
+ def __init__(self, datetime current_time=None):
1218
+ cdef shared_ptr[CMockFileSystem] wrapped
1219
+
1220
+ current_time = current_time or datetime.now()
1221
+ wrapped = make_shared[CMockFileSystem](
1222
+ PyDateTime_to_TimePoint(<PyDateTime_DateTime*> current_time)
1223
+ )
1224
+
1225
+ self.init(<shared_ptr[CFileSystem]> wrapped)
1226
+
1227
+ cdef init(self, const shared_ptr[CFileSystem]& wrapped):
1228
+ FileSystem.init(self, wrapped)
1229
+ self.mockfs = <CMockFileSystem*> wrapped.get()
1230
+
1231
+
1232
+ cdef class PyFileSystem(FileSystem):
1233
+ """
1234
+ A FileSystem with behavior implemented in Python.
1235
+
1236
+ Parameters
1237
+ ----------
1238
+ handler : FileSystemHandler
1239
+ The handler object implementing custom filesystem behavior.
1240
+
1241
+ Examples
1242
+ --------
1243
+ Create an fsspec-based filesystem object for GitHub:
1244
+
1245
+ >>> from fsspec.implementations import github
1246
+ >>> gfs = github.GithubFileSystem('apache', 'arrow') # doctest: +SKIP
1247
+
1248
+ Get a PyArrow FileSystem object:
1249
+
1250
+ >>> from pyarrow.fs import PyFileSystem, FSSpecHandler
1251
+ >>> pa_fs = PyFileSystem(FSSpecHandler(gfs)) # doctest: +SKIP
1252
+
1253
+ Use :func:`~pyarrow.fs.FileSystem` functionality ``get_file_info()``:
1254
+
1255
+ >>> pa_fs.get_file_info('README.md') # doctest: +SKIP
1256
+ <FileInfo for 'README.md': type=FileType.File, size=...>
1257
+ """
1258
+
1259
+ def __init__(self, handler):
1260
+ cdef:
1261
+ CPyFileSystemVtable vtable
1262
+ shared_ptr[CPyFileSystem] wrapped
1263
+
1264
+ if not isinstance(handler, FileSystemHandler):
1265
+ raise TypeError("Expected a FileSystemHandler instance, got {0}"
1266
+ .format(type(handler)))
1267
+
1268
+ vtable.get_type_name = _cb_get_type_name
1269
+ vtable.equals = _cb_equals
1270
+ vtable.get_file_info = _cb_get_file_info
1271
+ vtable.get_file_info_vector = _cb_get_file_info_vector
1272
+ vtable.get_file_info_selector = _cb_get_file_info_selector
1273
+ vtable.create_dir = _cb_create_dir
1274
+ vtable.delete_dir = _cb_delete_dir
1275
+ vtable.delete_dir_contents = _cb_delete_dir_contents
1276
+ vtable.delete_root_dir_contents = _cb_delete_root_dir_contents
1277
+ vtable.delete_file = _cb_delete_file
1278
+ vtable.move = _cb_move
1279
+ vtable.copy_file = _cb_copy_file
1280
+ vtable.open_input_stream = _cb_open_input_stream
1281
+ vtable.open_input_file = _cb_open_input_file
1282
+ vtable.open_output_stream = _cb_open_output_stream
1283
+ vtable.open_append_stream = _cb_open_append_stream
1284
+ vtable.normalize_path = _cb_normalize_path
1285
+
1286
+ wrapped = CPyFileSystem.Make(handler, move(vtable))
1287
+ self.init(<shared_ptr[CFileSystem]> wrapped)
1288
+
1289
+ cdef init(self, const shared_ptr[CFileSystem]& wrapped):
1290
+ FileSystem.init(self, wrapped)
1291
+ self.pyfs = <CPyFileSystem*> wrapped.get()
1292
+
1293
+ @property
1294
+ def handler(self):
1295
+ """
1296
+ The filesystem's underlying handler.
1297
+
1298
+ Returns
1299
+ -------
1300
+ handler : FileSystemHandler
1301
+ """
1302
+ return <object> self.pyfs.handler()
1303
+
1304
+ def __reduce__(self):
1305
+ return PyFileSystem, (self.handler,)
1306
+
1307
+
1308
+ class FileSystemHandler(ABC):
1309
+ """
1310
+ An abstract class exposing methods to implement PyFileSystem's behavior.
1311
+ """
1312
+
1313
+ @abstractmethod
1314
+ def get_type_name(self):
1315
+ """
1316
+ Implement PyFileSystem.type_name.
1317
+ """
1318
+
1319
+ @abstractmethod
1320
+ def get_file_info(self, paths):
1321
+ """
1322
+ Implement PyFileSystem.get_file_info(paths).
1323
+
1324
+ Parameters
1325
+ ----------
1326
+ paths : list of str
1327
+ paths for which we want to retrieve the info.
1328
+ """
1329
+
1330
+ @abstractmethod
1331
+ def get_file_info_selector(self, selector):
1332
+ """
1333
+ Implement PyFileSystem.get_file_info(selector).
1334
+
1335
+ Parameters
1336
+ ----------
1337
+ selector : FileSelector
1338
+ selector for which we want to retrieve the info.
1339
+ """
1340
+
1341
+ @abstractmethod
1342
+ def create_dir(self, path, recursive):
1343
+ """
1344
+ Implement PyFileSystem.create_dir(...).
1345
+
1346
+ Parameters
1347
+ ----------
1348
+ path : str
1349
+ path of the directory.
1350
+ recursive : bool
1351
+ if the parent directories should be created too.
1352
+ """
1353
+
1354
+ @abstractmethod
1355
+ def delete_dir(self, path):
1356
+ """
1357
+ Implement PyFileSystem.delete_dir(...).
1358
+
1359
+ Parameters
1360
+ ----------
1361
+ path : str
1362
+ path of the directory.
1363
+ """
1364
+
1365
+ @abstractmethod
1366
+ def delete_dir_contents(self, path, missing_dir_ok=False):
1367
+ """
1368
+ Implement PyFileSystem.delete_dir_contents(...).
1369
+
1370
+ Parameters
1371
+ ----------
1372
+ path : str
1373
+ path of the directory.
1374
+ missing_dir_ok : bool
1375
+ if False an error should be raised if path does not exist
1376
+ """
1377
+
1378
+ @abstractmethod
1379
+ def delete_root_dir_contents(self):
1380
+ """
1381
+ Implement PyFileSystem.delete_dir_contents("/", accept_root_dir=True).
1382
+ """
1383
+
1384
+ @abstractmethod
1385
+ def delete_file(self, path):
1386
+ """
1387
+ Implement PyFileSystem.delete_file(...).
1388
+
1389
+ Parameters
1390
+ ----------
1391
+ path : str
1392
+ path of the file.
1393
+ """
1394
+
1395
+ @abstractmethod
1396
+ def move(self, src, dest):
1397
+ """
1398
+ Implement PyFileSystem.move(...).
1399
+
1400
+ Parameters
1401
+ ----------
1402
+ src : str
1403
+ path of what should be moved.
1404
+ dest : str
1405
+ path of where it should be moved to.
1406
+ """
1407
+
1408
+ @abstractmethod
1409
+ def copy_file(self, src, dest):
1410
+ """
1411
+ Implement PyFileSystem.copy_file(...).
1412
+
1413
+ Parameters
1414
+ ----------
1415
+ src : str
1416
+ path of what should be copied.
1417
+ dest : str
1418
+ path of where it should be copied to.
1419
+ """
1420
+
1421
+ @abstractmethod
1422
+ def open_input_stream(self, path):
1423
+ """
1424
+ Implement PyFileSystem.open_input_stream(...).
1425
+
1426
+ Parameters
1427
+ ----------
1428
+ path : str
1429
+ path of what should be opened.
1430
+ """
1431
+
1432
+ @abstractmethod
1433
+ def open_input_file(self, path):
1434
+ """
1435
+ Implement PyFileSystem.open_input_file(...).
1436
+
1437
+ Parameters
1438
+ ----------
1439
+ path : str
1440
+ path of what should be opened.
1441
+ """
1442
+
1443
+ @abstractmethod
1444
+ def open_output_stream(self, path, metadata):
1445
+ """
1446
+ Implement PyFileSystem.open_output_stream(...).
1447
+
1448
+ Parameters
1449
+ ----------
1450
+ path : str
1451
+ path of what should be opened.
1452
+ metadata : mapping
1453
+ Mapping of string keys to string values.
1454
+ Some filesystems support storing metadata along the file
1455
+ (such as "Content-Type").
1456
+ """
1457
+
1458
+ @abstractmethod
1459
+ def open_append_stream(self, path, metadata):
1460
+ """
1461
+ Implement PyFileSystem.open_append_stream(...).
1462
+
1463
+ Parameters
1464
+ ----------
1465
+ path : str
1466
+ path of what should be opened.
1467
+ metadata : mapping
1468
+ Mapping of string keys to string values.
1469
+ Some filesystems support storing metadata along the file
1470
+ (such as "Content-Type").
1471
+ """
1472
+
1473
+ @abstractmethod
1474
+ def normalize_path(self, path):
1475
+ """
1476
+ Implement PyFileSystem.normalize_path(...).
1477
+
1478
+ Parameters
1479
+ ----------
1480
+ path : str
1481
+ path of what should be normalized.
1482
+ """
1483
+
1484
+ # Callback definitions for CPyFileSystemVtable
1485
+
1486
+
1487
+ cdef void _cb_get_type_name(handler, c_string* out) except *:
1488
+ out[0] = tobytes("py::" + handler.get_type_name())
1489
+
1490
+ cdef c_bool _cb_equals(handler, const CFileSystem& c_other) except False:
1491
+ if c_other.type_name().startswith(b"py::"):
1492
+ return <object> (<const CPyFileSystem&> c_other).handler() == handler
1493
+
1494
+ return False
1495
+
1496
+ cdef void _cb_get_file_info(handler, const c_string& path,
1497
+ CFileInfo* out) except *:
1498
+ infos = handler.get_file_info([frombytes(path)])
1499
+ if not isinstance(infos, list) or len(infos) != 1:
1500
+ raise TypeError("get_file_info should have returned a 1-element list")
1501
+ out[0] = FileInfo.unwrap_safe(infos[0])
1502
+
1503
+ cdef void _cb_get_file_info_vector(handler, const vector[c_string]& paths,
1504
+ vector[CFileInfo]* out) except *:
1505
+ py_paths = [frombytes(paths[i]) for i in range(len(paths))]
1506
+ infos = handler.get_file_info(py_paths)
1507
+ if not isinstance(infos, list):
1508
+ raise TypeError("get_file_info should have returned a list")
1509
+ out[0].clear()
1510
+ out[0].reserve(len(infos))
1511
+ for info in infos:
1512
+ out[0].push_back(FileInfo.unwrap_safe(info))
1513
+
1514
+ cdef void _cb_get_file_info_selector(handler, const CFileSelector& selector,
1515
+ vector[CFileInfo]* out) except *:
1516
+ infos = handler.get_file_info_selector(FileSelector.wrap(selector))
1517
+ if not isinstance(infos, list):
1518
+ raise TypeError("get_file_info_selector should have returned a list")
1519
+ out[0].clear()
1520
+ out[0].reserve(len(infos))
1521
+ for info in infos:
1522
+ out[0].push_back(FileInfo.unwrap_safe(info))
1523
+
1524
+ cdef void _cb_create_dir(handler, const c_string& path,
1525
+ c_bool recursive) except *:
1526
+ handler.create_dir(frombytes(path), recursive)
1527
+
1528
+ cdef void _cb_delete_dir(handler, const c_string& path) except *:
1529
+ handler.delete_dir(frombytes(path))
1530
+
1531
+ cdef void _cb_delete_dir_contents(handler, const c_string& path,
1532
+ c_bool missing_dir_ok) except *:
1533
+ handler.delete_dir_contents(frombytes(path), missing_dir_ok)
1534
+
1535
+ cdef void _cb_delete_root_dir_contents(handler) except *:
1536
+ handler.delete_root_dir_contents()
1537
+
1538
+ cdef void _cb_delete_file(handler, const c_string& path) except *:
1539
+ handler.delete_file(frombytes(path))
1540
+
1541
+ cdef void _cb_move(handler, const c_string& src,
1542
+ const c_string& dest) except *:
1543
+ handler.move(frombytes(src), frombytes(dest))
1544
+
1545
+ cdef void _cb_copy_file(handler, const c_string& src,
1546
+ const c_string& dest) except *:
1547
+ handler.copy_file(frombytes(src), frombytes(dest))
1548
+
1549
+ cdef void _cb_open_input_stream(handler, const c_string& path,
1550
+ shared_ptr[CInputStream]* out) except *:
1551
+ stream = handler.open_input_stream(frombytes(path))
1552
+ if not isinstance(stream, NativeFile):
1553
+ raise TypeError("open_input_stream should have returned "
1554
+ "a PyArrow file")
1555
+ out[0] = (<NativeFile> stream).get_input_stream()
1556
+
1557
+ cdef void _cb_open_input_file(handler, const c_string& path,
1558
+ shared_ptr[CRandomAccessFile]* out) except *:
1559
+ stream = handler.open_input_file(frombytes(path))
1560
+ if not isinstance(stream, NativeFile):
1561
+ raise TypeError("open_input_file should have returned "
1562
+ "a PyArrow file")
1563
+ out[0] = (<NativeFile> stream).get_random_access_file()
1564
+
1565
+ cdef void _cb_open_output_stream(
1566
+ handler, const c_string& path,
1567
+ const shared_ptr[const CKeyValueMetadata]& metadata,
1568
+ shared_ptr[COutputStream]* out) except *:
1569
+ stream = handler.open_output_stream(
1570
+ frombytes(path), pyarrow_wrap_metadata(metadata))
1571
+ if not isinstance(stream, NativeFile):
1572
+ raise TypeError("open_output_stream should have returned "
1573
+ "a PyArrow file")
1574
+ out[0] = (<NativeFile> stream).get_output_stream()
1575
+
1576
+ cdef void _cb_open_append_stream(
1577
+ handler, const c_string& path,
1578
+ const shared_ptr[const CKeyValueMetadata]& metadata,
1579
+ shared_ptr[COutputStream]* out) except *:
1580
+ stream = handler.open_append_stream(
1581
+ frombytes(path), pyarrow_wrap_metadata(metadata))
1582
+ if not isinstance(stream, NativeFile):
1583
+ raise TypeError("open_append_stream should have returned "
1584
+ "a PyArrow file")
1585
+ out[0] = (<NativeFile> stream).get_output_stream()
1586
+
1587
+ cdef void _cb_normalize_path(handler, const c_string& path,
1588
+ c_string* out) except *:
1589
+ out[0] = tobytes(handler.normalize_path(frombytes(path)))
1590
+
1591
+
1592
+ def _copy_files(FileSystem source_fs, str source_path,
1593
+ FileSystem destination_fs, str destination_path,
1594
+ int64_t chunk_size, c_bool use_threads):
1595
+ # low-level helper exposed through pyarrow/fs.py::copy_files
1596
+ cdef:
1597
+ CFileLocator c_source
1598
+ vector[CFileLocator] c_sources
1599
+ CFileLocator c_destination
1600
+ vector[CFileLocator] c_destinations
1601
+
1602
+ c_source.filesystem = source_fs.unwrap()
1603
+ c_source.path = tobytes(source_path)
1604
+ c_sources.push_back(c_source)
1605
+
1606
+ c_destination.filesystem = destination_fs.unwrap()
1607
+ c_destination.path = tobytes(destination_path)
1608
+ c_destinations.push_back(c_destination)
1609
+
1610
+ with nogil:
1611
+ check_status(CCopyFiles(
1612
+ c_sources, c_destinations,
1613
+ c_default_io_context(), chunk_size, use_threads,
1614
+ ))
1615
+
1616
+
1617
+ def _copy_files_selector(FileSystem source_fs, FileSelector source_sel,
1618
+ FileSystem destination_fs, str destination_base_dir,
1619
+ int64_t chunk_size, c_bool use_threads):
1620
+ # low-level helper exposed through pyarrow/fs.py::copy_files
1621
+ cdef c_string c_destination_base_dir = tobytes(destination_base_dir)
1622
+
1623
+ with nogil:
1624
+ check_status(CCopyFilesWithSelector(
1625
+ source_fs.unwrap(), source_sel.unwrap(),
1626
+ destination_fs.unwrap(), c_destination_base_dir,
1627
+ c_default_io_context(), chunk_size, use_threads,
1628
+ ))
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_orc.pxd ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # distutils: language = c++
19
+ # cython: language_level = 3
20
+
21
+ from libcpp cimport bool as c_bool
22
+ from libc.string cimport const_char
23
+ from libcpp.vector cimport vector as std_vector
24
+ from pyarrow.includes.common cimport *
25
+ from pyarrow.includes.libarrow cimport (CArray, CSchema, CStatus,
26
+ CResult, CTable, CMemoryPool,
27
+ CKeyValueMetadata,
28
+ CRecordBatch,
29
+ CTable, CCompressionType,
30
+ CRandomAccessFile, COutputStream,
31
+ TimeUnit)
32
+
33
+ cdef extern from "arrow/adapters/orc/options.h" \
34
+ namespace "arrow::adapters::orc" nogil:
35
+ cdef enum CompressionStrategy \
36
+ " arrow::adapters::orc::CompressionStrategy":
37
+ _CompressionStrategy_SPEED \
38
+ " arrow::adapters::orc::CompressionStrategy::kSpeed"
39
+ _CompressionStrategy_COMPRESSION \
40
+ " arrow::adapters::orc::CompressionStrategy::kCompression"
41
+
42
+ cdef enum WriterId" arrow::adapters::orc::WriterId":
43
+ _WriterId_ORC_JAVA_WRITER" arrow::adapters::orc::WriterId::kOrcJava"
44
+ _WriterId_ORC_CPP_WRITER" arrow::adapters::orc::WriterId::kOrcCpp"
45
+ _WriterId_PRESTO_WRITER" arrow::adapters::orc::WriterId::kPresto"
46
+ _WriterId_SCRITCHLEY_GO \
47
+ " arrow::adapters::orc::WriterId::kScritchleyGo"
48
+ _WriterId_TRINO_WRITER" arrow::adapters::orc::WriterId::kTrino"
49
+ _WriterId_UNKNOWN_WRITER" arrow::adapters::orc::WriterId::kUnknown"
50
+
51
+ cdef enum WriterVersion" arrow::adapters::orc::WriterVersion":
52
+ _WriterVersion_ORIGINAL \
53
+ " arrow::adapters::orc::WriterVersion::kOriginal"
54
+ _WriterVersion_HIVE_8732 \
55
+ " arrow::adapters::orc::WriterVersion::kHive8732"
56
+ _WriterVersion_HIVE_4243 \
57
+ " arrow::adapters::orc::WriterVersion::kHive4243"
58
+ _WriterVersion_HIVE_12055 \
59
+ " arrow::adapters::orc::WriterVersion::kHive12055"
60
+ _WriterVersion_HIVE_13083 \
61
+ " arrow::adapters::orc::WriterVersion::kHive13083"
62
+ _WriterVersion_ORC_101" arrow::adapters::orc::WriterVersion::kOrc101"
63
+ _WriterVersion_ORC_135" arrow::adapters::orc::WriterVersion::kOrc135"
64
+ _WriterVersion_ORC_517" arrow::adapters::orc::WriterVersion::kOrc517"
65
+ _WriterVersion_ORC_203" arrow::adapters::orc::WriterVersion::kOrc203"
66
+ _WriterVersion_ORC_14" arrow::adapters::orc::WriterVersion::kOrc14"
67
+ _WriterVersion_MAX" arrow::adapters::orc::WriterVersion::kMax"
68
+
69
+ cdef cppclass FileVersion" arrow::adapters::orc::FileVersion":
70
+ FileVersion(uint32_t major_version, uint32_t minor_version)
71
+ uint32_t major_version()
72
+ uint32_t minor_version()
73
+ c_string ToString()
74
+
75
+ cdef struct WriteOptions" arrow::adapters::orc::WriteOptions":
76
+ int64_t batch_size
77
+ FileVersion file_version
78
+ int64_t stripe_size
79
+ CCompressionType compression
80
+ int64_t compression_block_size
81
+ CompressionStrategy compression_strategy
82
+ int64_t row_index_stride
83
+ double padding_tolerance
84
+ double dictionary_key_size_threshold
85
+ std_vector[int64_t] bloom_filter_columns
86
+ double bloom_filter_fpp
87
+
88
+
89
+ cdef extern from "arrow/adapters/orc/adapter.h" \
90
+ namespace "arrow::adapters::orc" nogil:
91
+
92
+ cdef cppclass ORCFileReader:
93
+ @staticmethod
94
+ CResult[unique_ptr[ORCFileReader]] Open(
95
+ const shared_ptr[CRandomAccessFile]& file,
96
+ CMemoryPool* pool)
97
+
98
+ CResult[shared_ptr[const CKeyValueMetadata]] ReadMetadata()
99
+
100
+ CResult[shared_ptr[CSchema]] ReadSchema()
101
+
102
+ CResult[shared_ptr[CRecordBatch]] ReadStripe(int64_t stripe)
103
+ CResult[shared_ptr[CRecordBatch]] ReadStripe(
104
+ int64_t stripe, std_vector[c_string])
105
+
106
+ CResult[shared_ptr[CTable]] Read()
107
+ CResult[shared_ptr[CTable]] Read(std_vector[c_string])
108
+
109
+ int64_t NumberOfStripes()
110
+ int64_t NumberOfRows()
111
+ FileVersion GetFileVersion()
112
+ c_string GetSoftwareVersion()
113
+ CResult[CCompressionType] GetCompression()
114
+ int64_t GetCompressionSize()
115
+ int64_t GetRowIndexStride()
116
+ WriterId GetWriterId()
117
+ int32_t GetWriterIdValue()
118
+ WriterVersion GetWriterVersion()
119
+ int64_t GetNumberOfStripeStatistics()
120
+ int64_t GetContentLength()
121
+ int64_t GetStripeStatisticsLength()
122
+ int64_t GetFileFooterLength()
123
+ int64_t GetFilePostscriptLength()
124
+ int64_t GetFileLength()
125
+ c_string GetSerializedFileTail()
126
+
127
+ cdef cppclass ORCFileWriter:
128
+ @staticmethod
129
+ CResult[unique_ptr[ORCFileWriter]] Open(
130
+ COutputStream* output_stream, const WriteOptions& writer_options)
131
+
132
+ CStatus Write(const CTable& table)
133
+
134
+ CStatus Close()
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/_s3fs.pyx ADDED
@@ -0,0 +1,479 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # cython: language_level = 3
19
+
20
+ from cython cimport binding
21
+
22
+ from pyarrow.lib cimport (check_status, pyarrow_wrap_metadata,
23
+ pyarrow_unwrap_metadata)
24
+ from pyarrow.lib import frombytes, tobytes, KeyValueMetadata
25
+ from pyarrow.includes.common cimport *
26
+ from pyarrow.includes.libarrow cimport *
27
+ from pyarrow.includes.libarrow_fs cimport *
28
+ from pyarrow._fs cimport FileSystem
29
+
30
+
31
+ cpdef enum S3LogLevel:
32
+ Off = <int8_t> CS3LogLevel_Off
33
+ Fatal = <int8_t> CS3LogLevel_Fatal
34
+ Error = <int8_t> CS3LogLevel_Error
35
+ Warn = <int8_t> CS3LogLevel_Warn
36
+ Info = <int8_t> CS3LogLevel_Info
37
+ Debug = <int8_t> CS3LogLevel_Debug
38
+ Trace = <int8_t> CS3LogLevel_Trace
39
+
40
+
41
+ def initialize_s3(S3LogLevel log_level=S3LogLevel.Fatal, int num_event_loop_threads=1):
42
+ """
43
+ Initialize S3 support
44
+
45
+ Parameters
46
+ ----------
47
+ log_level : S3LogLevel
48
+ level of logging
49
+ num_event_loop_threads : int, default 1
50
+ how many threads to use for the AWS SDK's I/O event loop
51
+
52
+ Examples
53
+ --------
54
+ >>> fs.initialize_s3(fs.S3LogLevel.Error) # doctest: +SKIP
55
+ """
56
+ cdef CS3GlobalOptions options
57
+ options.log_level = <CS3LogLevel> log_level
58
+ options.num_event_loop_threads = num_event_loop_threads
59
+ check_status(CInitializeS3(options))
60
+
61
+
62
+ def ensure_s3_initialized():
63
+ """
64
+ Initialize S3 (with default options) if not already initialized
65
+ """
66
+ check_status(CEnsureS3Initialized())
67
+
68
+
69
+ def finalize_s3():
70
+ check_status(CFinalizeS3())
71
+
72
+
73
+ def ensure_s3_finalized():
74
+ """
75
+ Finalize S3 if already initialized
76
+ """
77
+ check_status(CEnsureS3Finalized())
78
+
79
+
80
+ def resolve_s3_region(bucket):
81
+ """
82
+ Resolve the S3 region of a bucket.
83
+
84
+ Parameters
85
+ ----------
86
+ bucket : str
87
+ A S3 bucket name
88
+
89
+ Returns
90
+ -------
91
+ region : str
92
+ A S3 region name
93
+
94
+ Examples
95
+ --------
96
+ >>> fs.resolve_s3_region('voltrondata-labs-datasets')
97
+ 'us-east-2'
98
+ """
99
+ cdef:
100
+ c_string c_bucket
101
+ c_string c_region
102
+
103
+ ensure_s3_initialized()
104
+
105
+ c_bucket = tobytes(bucket)
106
+ with nogil:
107
+ c_region = GetResultValue(ResolveS3BucketRegion(c_bucket))
108
+
109
+ return frombytes(c_region)
110
+
111
+
112
+ class S3RetryStrategy:
113
+ """
114
+ Base class for AWS retry strategies for use with S3.
115
+
116
+ Parameters
117
+ ----------
118
+ max_attempts : int, default 3
119
+ The maximum number of retry attempts to attempt before failing.
120
+ """
121
+
122
+ def __init__(self, max_attempts=3):
123
+ self.max_attempts = max_attempts
124
+
125
+
126
+ class AwsStandardS3RetryStrategy(S3RetryStrategy):
127
+ """
128
+ Represents an AWS Standard retry strategy for use with S3.
129
+
130
+ Parameters
131
+ ----------
132
+ max_attempts : int, default 3
133
+ The maximum number of retry attempts to attempt before failing.
134
+ """
135
+ pass
136
+
137
+
138
+ class AwsDefaultS3RetryStrategy(S3RetryStrategy):
139
+ """
140
+ Represents an AWS Default retry strategy for use with S3.
141
+
142
+ Parameters
143
+ ----------
144
+ max_attempts : int, default 3
145
+ The maximum number of retry attempts to attempt before failing.
146
+ """
147
+ pass
148
+
149
+
150
+ cdef class S3FileSystem(FileSystem):
151
+ """
152
+ S3-backed FileSystem implementation
153
+
154
+ AWS access_key and secret_key can be provided explicitly.
155
+
156
+ If role_arn is provided instead of access_key and secret_key, temporary
157
+ credentials will be fetched by issuing a request to STS to assume the
158
+ specified role.
159
+
160
+ If neither access_key nor secret_key are provided, and role_arn is also not
161
+ provided, then attempts to establish the credentials automatically.
162
+ S3FileSystem will try the following methods, in order:
163
+
164
+ * ``AWS_ACCESS_KEY_ID``, ``AWS_SECRET_ACCESS_KEY``, and ``AWS_SESSION_TOKEN`` environment variables
165
+ * configuration files such as ``~/.aws/credentials`` and ``~/.aws/config``
166
+ * for nodes on Amazon EC2, the EC2 Instance Metadata Service
167
+
168
+ Note: S3 buckets are special and the operations available on them may be
169
+ limited or more expensive than desired.
170
+
171
+ When S3FileSystem creates new buckets (assuming allow_bucket_creation is
172
+ True), it does not pass any non-default settings. In AWS S3, the bucket and
173
+ all objects will be not publicly visible, and will have no bucket policies
174
+ and no resource tags. To have more control over how buckets are created,
175
+ use a different API to create them.
176
+
177
+ Parameters
178
+ ----------
179
+ access_key : str, default None
180
+ AWS Access Key ID. Pass None to use the standard AWS environment
181
+ variables and/or configuration file.
182
+ secret_key : str, default None
183
+ AWS Secret Access key. Pass None to use the standard AWS environment
184
+ variables and/or configuration file.
185
+ session_token : str, default None
186
+ AWS Session Token. An optional session token, required if access_key
187
+ and secret_key are temporary credentials from STS.
188
+ anonymous : bool, default False
189
+ Whether to connect anonymously if access_key and secret_key are None.
190
+ If true, will not attempt to look up credentials using standard AWS
191
+ configuration methods.
192
+ role_arn : str, default None
193
+ AWS Role ARN. If provided instead of access_key and secret_key,
194
+ temporary credentials will be fetched by assuming this role.
195
+ session_name : str, default None
196
+ An optional identifier for the assumed role session.
197
+ external_id : str, default None
198
+ An optional unique identifier that might be required when you assume
199
+ a role in another account.
200
+ load_frequency : int, default 900
201
+ The frequency (in seconds) with which temporary credentials from an
202
+ assumed role session will be refreshed.
203
+ region : str, default None
204
+ AWS region to connect to. If not set, the AWS SDK will attempt to
205
+ determine the region using heuristics such as environment variables,
206
+ configuration profile, EC2 metadata, or default to 'us-east-1' when SDK
207
+ version <1.8. One can also use :func:`pyarrow.fs.resolve_s3_region` to
208
+ automatically resolve the region from a bucket name.
209
+ request_timeout : double, default None
210
+ Socket read timeouts on Windows and macOS, in seconds.
211
+ If omitted, the AWS SDK default value is used (typically 3 seconds).
212
+ This option is ignored on non-Windows, non-macOS systems.
213
+ connect_timeout : double, default None
214
+ Socket connection timeout, in seconds.
215
+ If omitted, the AWS SDK default value is used (typically 1 second).
216
+ scheme : str, default 'https'
217
+ S3 connection transport scheme.
218
+ endpoint_override : str, default None
219
+ Override region with a connect string such as "localhost:9000"
220
+ background_writes : bool, default True
221
+ Whether file writes will be issued in the background, without
222
+ blocking.
223
+ default_metadata : mapping or pyarrow.KeyValueMetadata, default None
224
+ Default metadata for open_output_stream. This will be ignored if
225
+ non-empty metadata is passed to open_output_stream.
226
+ proxy_options : dict or str, default None
227
+ If a proxy is used, provide the options here. Supported options are:
228
+ 'scheme' (str: 'http' or 'https'; required), 'host' (str; required),
229
+ 'port' (int; required), 'username' (str; optional),
230
+ 'password' (str; optional).
231
+ A proxy URI (str) can also be provided, in which case these options
232
+ will be derived from the provided URI.
233
+ The following are equivalent::
234
+
235
+ S3FileSystem(proxy_options='http://username:password@localhost:8020')
236
+ S3FileSystem(proxy_options={'scheme': 'http', 'host': 'localhost',
237
+ 'port': 8020, 'username': 'username',
238
+ 'password': 'password'})
239
+ allow_bucket_creation : bool, default False
240
+ Whether to allow directory creation at the bucket-level. This option may also be
241
+ passed in a URI query parameter.
242
+ allow_bucket_deletion : bool, default False
243
+ Whether to allow directory deletion at the bucket-level. This option may also be
244
+ passed in a URI query parameter.
245
+ check_directory_existence_before_creation : bool, default false
246
+ Whether to check the directory existence before creating it.
247
+ If false, when creating a directory the code will not check if it already
248
+ exists or not. It's an optimization to try directory creation and catch the error,
249
+ rather than issue two dependent I/O calls.
250
+ If true, when creating a directory the code will only create the directory when necessary
251
+ at the cost of extra I/O calls. This can be used for key/value cloud storage which has
252
+ a hard rate limit to number of object mutation operations or scenarios such as
253
+ the directories already exist and you do not have creation access.
254
+ retry_strategy : S3RetryStrategy, default AwsStandardS3RetryStrategy(max_attempts=3)
255
+ The retry strategy to use with S3; fail after max_attempts. Available
256
+ strategies are AwsStandardS3RetryStrategy, AwsDefaultS3RetryStrategy.
257
+ force_virtual_addressing : bool, default False
258
+ Whether to use virtual addressing of buckets.
259
+ If true, then virtual addressing is always enabled.
260
+ If false, then virtual addressing is only enabled if `endpoint_override` is empty.
261
+ This can be used for non-AWS backends that only support virtual hosted-style access.
262
+
263
+ Examples
264
+ --------
265
+ >>> from pyarrow import fs
266
+ >>> s3 = fs.S3FileSystem(region='us-west-2')
267
+ >>> s3.get_file_info(fs.FileSelector(
268
+ ... 'power-analysis-ready-datastore/power_901_constants.zarr/FROCEAN', recursive=True
269
+ ... ))
270
+ [<FileInfo for 'power-analysis-ready-datastore/power_901_constants.zarr/FROCEAN/.zarray...
271
+
272
+ For usage of the methods see examples for :func:`~pyarrow.fs.LocalFileSystem`.
273
+ """
274
+
275
+ cdef:
276
+ CS3FileSystem* s3fs
277
+
278
+ def __init__(self, *, access_key=None, secret_key=None, session_token=None,
279
+ bint anonymous=False, region=None, request_timeout=None,
280
+ connect_timeout=None, scheme=None, endpoint_override=None,
281
+ bint background_writes=True, default_metadata=None,
282
+ role_arn=None, session_name=None, external_id=None,
283
+ load_frequency=900, proxy_options=None,
284
+ allow_bucket_creation=False, allow_bucket_deletion=False,
285
+ check_directory_existence_before_creation=False,
286
+ retry_strategy: S3RetryStrategy = AwsStandardS3RetryStrategy(
287
+ max_attempts=3),
288
+ force_virtual_addressing=False):
289
+ cdef:
290
+ optional[CS3Options] options
291
+ shared_ptr[CS3FileSystem] wrapped
292
+
293
+ # Need to do this before initializing `options` as the S3Options
294
+ # constructor has a debug check against use after S3 finalization.
295
+ ensure_s3_initialized()
296
+
297
+ if access_key is not None and secret_key is None:
298
+ raise ValueError(
299
+ 'In order to initialize with explicit credentials both '
300
+ 'access_key and secret_key must be provided, '
301
+ '`secret_key` is not set.'
302
+ )
303
+ elif access_key is None and secret_key is not None:
304
+ raise ValueError(
305
+ 'In order to initialize with explicit credentials both '
306
+ 'access_key and secret_key must be provided, '
307
+ '`access_key` is not set.'
308
+ )
309
+
310
+ elif session_token is not None and (access_key is None or
311
+ secret_key is None):
312
+ raise ValueError(
313
+ 'In order to initialize a session with temporary credentials, '
314
+ 'both secret_key and access_key must be provided in addition '
315
+ 'to session_token.'
316
+ )
317
+
318
+ elif (access_key is not None or secret_key is not None):
319
+ if anonymous:
320
+ raise ValueError(
321
+ 'Cannot pass anonymous=True together with access_key '
322
+ 'and secret_key.')
323
+
324
+ if role_arn:
325
+ raise ValueError(
326
+ 'Cannot provide role_arn with access_key and secret_key')
327
+
328
+ if session_token is None:
329
+ session_token = ""
330
+
331
+ options = CS3Options.FromAccessKey(
332
+ tobytes(access_key),
333
+ tobytes(secret_key),
334
+ tobytes(session_token)
335
+ )
336
+ elif anonymous:
337
+ if role_arn:
338
+ raise ValueError(
339
+ 'Cannot provide role_arn with anonymous=True')
340
+
341
+ options = CS3Options.Anonymous()
342
+ elif role_arn:
343
+ if session_name is None:
344
+ session_name = ''
345
+ if external_id is None:
346
+ external_id = ''
347
+
348
+ options = CS3Options.FromAssumeRole(
349
+ tobytes(role_arn),
350
+ tobytes(session_name),
351
+ tobytes(external_id),
352
+ load_frequency
353
+ )
354
+ else:
355
+ options = CS3Options.Defaults()
356
+
357
+ if region is not None:
358
+ options.value().region = tobytes(region)
359
+ if request_timeout is not None:
360
+ options.value().request_timeout = request_timeout
361
+ if connect_timeout is not None:
362
+ options.value().connect_timeout = connect_timeout
363
+ if scheme is not None:
364
+ options.value().scheme = tobytes(scheme)
365
+ if endpoint_override is not None:
366
+ options.value().endpoint_override = tobytes(endpoint_override)
367
+ if background_writes is not None:
368
+ options.value().background_writes = background_writes
369
+ if default_metadata is not None:
370
+ if not isinstance(default_metadata, KeyValueMetadata):
371
+ default_metadata = KeyValueMetadata(default_metadata)
372
+ options.value().default_metadata = pyarrow_unwrap_metadata(
373
+ default_metadata)
374
+
375
+ if proxy_options is not None:
376
+ if isinstance(proxy_options, dict):
377
+ options.value().proxy_options.scheme = tobytes(
378
+ proxy_options["scheme"])
379
+ options.value().proxy_options.host = tobytes(
380
+ proxy_options["host"])
381
+ options.value().proxy_options.port = proxy_options["port"]
382
+ proxy_username = proxy_options.get("username", None)
383
+ if proxy_username:
384
+ options.value().proxy_options.username = tobytes(
385
+ proxy_username)
386
+ proxy_password = proxy_options.get("password", None)
387
+ if proxy_password:
388
+ options.value().proxy_options.password = tobytes(
389
+ proxy_password)
390
+ elif isinstance(proxy_options, str):
391
+ options.value().proxy_options = GetResultValue(
392
+ CS3ProxyOptions.FromUriString(tobytes(proxy_options)))
393
+ else:
394
+ raise TypeError(
395
+ "'proxy_options': expected 'dict' or 'str', "
396
+ f"got {type(proxy_options)} instead.")
397
+
398
+ options.value().allow_bucket_creation = allow_bucket_creation
399
+ options.value().allow_bucket_deletion = allow_bucket_deletion
400
+ options.value().check_directory_existence_before_creation = check_directory_existence_before_creation
401
+ options.value().force_virtual_addressing = force_virtual_addressing
402
+
403
+ if isinstance(retry_strategy, AwsStandardS3RetryStrategy):
404
+ options.value().retry_strategy = CS3RetryStrategy.GetAwsStandardRetryStrategy(
405
+ retry_strategy.max_attempts)
406
+ elif isinstance(retry_strategy, AwsDefaultS3RetryStrategy):
407
+ options.value().retry_strategy = CS3RetryStrategy.GetAwsDefaultRetryStrategy(
408
+ retry_strategy.max_attempts)
409
+ else:
410
+ raise ValueError(f'Invalid retry_strategy {retry_strategy!r}')
411
+
412
+ with nogil:
413
+ wrapped = GetResultValue(CS3FileSystem.Make(options.value()))
414
+
415
+ self.init(<shared_ptr[CFileSystem]> wrapped)
416
+
417
+ cdef init(self, const shared_ptr[CFileSystem]& wrapped):
418
+ FileSystem.init(self, wrapped)
419
+ self.s3fs = <CS3FileSystem*> wrapped.get()
420
+
421
+ @staticmethod
422
+ @binding(True) # Required for cython < 3
423
+ def _reconstruct(kwargs):
424
+ # __reduce__ doesn't allow passing named arguments directly to the
425
+ # reconstructor, hence this wrapper.
426
+ return S3FileSystem(**kwargs)
427
+
428
+ def __reduce__(self):
429
+ cdef CS3Options opts = self.s3fs.options()
430
+
431
+ # if creds were explicitly provided, then use them
432
+ # else obtain them as they were last time.
433
+ if opts.credentials_kind == CS3CredentialsKind_Explicit:
434
+ access_key = frombytes(opts.GetAccessKey())
435
+ secret_key = frombytes(opts.GetSecretKey())
436
+ session_token = frombytes(opts.GetSessionToken())
437
+ else:
438
+ access_key = None
439
+ secret_key = None
440
+ session_token = None
441
+
442
+ return (
443
+ S3FileSystem._reconstruct, (dict(
444
+ access_key=access_key,
445
+ secret_key=secret_key,
446
+ session_token=session_token,
447
+ anonymous=(opts.credentials_kind ==
448
+ CS3CredentialsKind_Anonymous),
449
+ region=frombytes(opts.region),
450
+ scheme=frombytes(opts.scheme),
451
+ connect_timeout=opts.connect_timeout,
452
+ request_timeout=opts.request_timeout,
453
+ endpoint_override=frombytes(opts.endpoint_override),
454
+ role_arn=frombytes(opts.role_arn),
455
+ session_name=frombytes(opts.session_name),
456
+ external_id=frombytes(opts.external_id),
457
+ load_frequency=opts.load_frequency,
458
+ background_writes=opts.background_writes,
459
+ allow_bucket_creation=opts.allow_bucket_creation,
460
+ allow_bucket_deletion=opts.allow_bucket_deletion,
461
+ check_directory_existence_before_creation=opts.check_directory_existence_before_creation,
462
+ default_metadata=pyarrow_wrap_metadata(opts.default_metadata),
463
+ proxy_options={'scheme': frombytes(opts.proxy_options.scheme),
464
+ 'host': frombytes(opts.proxy_options.host),
465
+ 'port': opts.proxy_options.port,
466
+ 'username': frombytes(
467
+ opts.proxy_options.username),
468
+ 'password': frombytes(
469
+ opts.proxy_options.password)},
470
+ force_virtual_addressing=opts.force_virtual_addressing,
471
+ ),)
472
+ )
473
+
474
+ @property
475
+ def region(self):
476
+ """
477
+ The AWS region this filesystem connects to.
478
+ """
479
+ return frombytes(self.s3fs.region())
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/benchmark.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # flake8: noqa
19
+
20
+
21
+ from pyarrow.lib import benchmark_PandasObjectIsNull
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/conftest.py ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import pytest
19
+
20
+ import os
21
+ import pyarrow as pa
22
+ from pyarrow import Codec
23
+ from pyarrow import fs
24
+ from pyarrow.lib import is_threading_enabled
25
+ from pyarrow.tests.util import windows_has_tzdata
26
+ import sys
27
+
28
+
29
+ groups = [
30
+ 'acero',
31
+ 'azure',
32
+ 'brotli',
33
+ 'bz2',
34
+ 'cython',
35
+ 'dataset',
36
+ 'hypothesis',
37
+ 'fastparquet',
38
+ 'flight',
39
+ 'gandiva',
40
+ 'gcs',
41
+ 'gdb',
42
+ 'gzip',
43
+ 'hdfs',
44
+ 'large_memory',
45
+ 'lz4',
46
+ 'memory_leak',
47
+ 'nopandas',
48
+ 'nonumpy',
49
+ 'numpy',
50
+ 'orc',
51
+ 'pandas',
52
+ 'parquet',
53
+ 'parquet_encryption',
54
+ 'processes',
55
+ 'requires_testing_data',
56
+ 's3',
57
+ 'slow',
58
+ 'snappy',
59
+ 'sockets',
60
+ 'substrait',
61
+ 'threading',
62
+ 'timezone_data',
63
+ 'zstd',
64
+ ]
65
+
66
+ defaults = {
67
+ 'acero': False,
68
+ 'azure': False,
69
+ 'brotli': Codec.is_available('brotli'),
70
+ 'bz2': Codec.is_available('bz2'),
71
+ 'cython': False,
72
+ 'dataset': False,
73
+ 'fastparquet': False,
74
+ 'flight': False,
75
+ 'gandiva': False,
76
+ 'gcs': False,
77
+ 'gdb': True,
78
+ 'gzip': Codec.is_available('gzip'),
79
+ 'hdfs': False,
80
+ 'hypothesis': False,
81
+ 'large_memory': False,
82
+ 'lz4': Codec.is_available('lz4'),
83
+ 'memory_leak': False,
84
+ 'nopandas': False,
85
+ 'nonumpy': False,
86
+ 'numpy': False,
87
+ 'orc': False,
88
+ 'pandas': False,
89
+ 'parquet': False,
90
+ 'parquet_encryption': False,
91
+ 'processes': True,
92
+ 'requires_testing_data': True,
93
+ 's3': False,
94
+ 'slow': False,
95
+ 'snappy': Codec.is_available('snappy'),
96
+ 'sockets': True,
97
+ 'substrait': False,
98
+ 'threading': is_threading_enabled(),
99
+ 'timezone_data': True,
100
+ 'zstd': Codec.is_available('zstd'),
101
+ }
102
+
103
+ if sys.platform == "emscripten":
104
+ # Emscripten doesn't support subprocess,
105
+ # multiprocessing, gdb or socket based
106
+ # networking
107
+ defaults['gdb'] = False
108
+ defaults['processes'] = False
109
+ defaults['sockets'] = False
110
+
111
+ if sys.platform == "win32":
112
+ defaults['timezone_data'] = windows_has_tzdata()
113
+ elif sys.platform == "emscripten":
114
+ defaults['timezone_data'] = os.path.exists("/usr/share/zoneinfo")
115
+
116
+ try:
117
+ import cython # noqa
118
+ defaults['cython'] = True
119
+ except ImportError:
120
+ pass
121
+
122
+ try:
123
+ import fastparquet # noqa
124
+ defaults['fastparquet'] = True
125
+ except ImportError:
126
+ pass
127
+
128
+ try:
129
+ import pyarrow.gandiva # noqa
130
+ defaults['gandiva'] = True
131
+ except ImportError:
132
+ pass
133
+
134
+ try:
135
+ import pyarrow.acero # noqa
136
+ defaults['acero'] = True
137
+ except ImportError:
138
+ pass
139
+
140
+ try:
141
+ import pyarrow.dataset # noqa
142
+ defaults['dataset'] = True
143
+ except ImportError:
144
+ pass
145
+
146
+ try:
147
+ import pyarrow.orc # noqa
148
+ if sys.platform == "win32":
149
+ defaults['orc'] = True
150
+ else:
151
+ # orc tests on non-Windows platforms only work
152
+ # if timezone data exists, so skip them if
153
+ # not.
154
+ defaults['orc'] = defaults['timezone_data']
155
+ except ImportError:
156
+ pass
157
+
158
+ try:
159
+ import pandas # noqa
160
+ defaults['pandas'] = True
161
+ except ImportError:
162
+ defaults['nopandas'] = True
163
+
164
+ try:
165
+ import numpy # noqa
166
+ defaults['numpy'] = True
167
+ except ImportError:
168
+ defaults['nonumpy'] = True
169
+
170
+ try:
171
+ import pyarrow.parquet # noqa
172
+ defaults['parquet'] = True
173
+ except ImportError:
174
+ pass
175
+
176
+ try:
177
+ import pyarrow.parquet.encryption # noqa
178
+ defaults['parquet_encryption'] = True
179
+ except ImportError:
180
+ pass
181
+
182
+ try:
183
+ import pyarrow.flight # noqa
184
+ defaults['flight'] = True
185
+ except ImportError:
186
+ pass
187
+
188
+ try:
189
+ from pyarrow.fs import AzureFileSystem # noqa
190
+ defaults['azure'] = True
191
+ except ImportError:
192
+ pass
193
+
194
+ try:
195
+ from pyarrow.fs import GcsFileSystem # noqa
196
+ defaults['gcs'] = True
197
+ except ImportError:
198
+ pass
199
+
200
+ try:
201
+ from pyarrow.fs import S3FileSystem # noqa
202
+ defaults['s3'] = True
203
+ except ImportError:
204
+ pass
205
+
206
+ try:
207
+ from pyarrow.fs import HadoopFileSystem # noqa
208
+ defaults['hdfs'] = True
209
+ except ImportError:
210
+ pass
211
+
212
+ try:
213
+ import pyarrow.substrait # noqa
214
+ defaults['substrait'] = True
215
+ except ImportError:
216
+ pass
217
+
218
+
219
+ # Doctest should ignore files for the modules that are not built
220
+ def pytest_ignore_collect(path, config):
221
+ if config.option.doctestmodules:
222
+ # don't try to run doctests on the /tests directory
223
+ if "/pyarrow/tests/" in str(path):
224
+ return True
225
+
226
+ doctest_groups = [
227
+ 'dataset',
228
+ 'orc',
229
+ 'parquet',
230
+ 'flight',
231
+ 'substrait',
232
+ ]
233
+
234
+ # handle cuda, flight, etc
235
+ for group in doctest_groups:
236
+ if 'pyarrow/{}'.format(group) in str(path):
237
+ if not defaults[group]:
238
+ return True
239
+
240
+ if 'pyarrow/parquet/encryption' in str(path):
241
+ if not defaults['parquet_encryption']:
242
+ return True
243
+
244
+ if 'pyarrow/cuda' in str(path):
245
+ try:
246
+ import pyarrow.cuda # noqa
247
+ return False
248
+ except ImportError:
249
+ return True
250
+
251
+ if 'pyarrow/fs' in str(path):
252
+ try:
253
+ from pyarrow.fs import S3FileSystem # noqa
254
+ return False
255
+ except ImportError:
256
+ return True
257
+
258
+ if getattr(config.option, "doctest_cython", False):
259
+ if "/pyarrow/tests/" in str(path):
260
+ return True
261
+ if "/pyarrow/_parquet_encryption" in str(path):
262
+ return True
263
+
264
+ return False
265
+
266
+
267
+ # Save output files from doctest examples into temp dir
268
+ @pytest.fixture(autouse=True)
269
+ def _docdir(request):
270
+
271
+ # Trigger ONLY for the doctests
272
+ doctest_m = request.config.option.doctestmodules
273
+ doctest_c = getattr(request.config.option, "doctest_cython", False)
274
+
275
+ if doctest_m or doctest_c:
276
+
277
+ # Get the fixture dynamically by its name.
278
+ tmpdir = request.getfixturevalue('tmpdir')
279
+
280
+ # Chdir only for the duration of the test.
281
+ with tmpdir.as_cwd():
282
+ yield
283
+
284
+ else:
285
+ yield
286
+
287
+
288
+ # Define doctest_namespace for fs module docstring import
289
+ @pytest.fixture(autouse=True)
290
+ def add_fs(doctest_namespace, request, tmp_path):
291
+
292
+ # Trigger ONLY for the doctests
293
+ doctest_m = request.config.option.doctestmodules
294
+ doctest_c = getattr(request.config.option, "doctest_cython", False)
295
+
296
+ if doctest_m or doctest_c:
297
+ # fs import
298
+ doctest_namespace["fs"] = fs
299
+
300
+ # Creation of an object and file with data
301
+ local = fs.LocalFileSystem()
302
+ path = tmp_path / 'pyarrow-fs-example.dat'
303
+ with local.open_output_stream(str(path)) as stream:
304
+ stream.write(b'data')
305
+ doctest_namespace["local"] = local
306
+ doctest_namespace["local_path"] = str(tmp_path)
307
+ doctest_namespace["path"] = str(path)
308
+ yield
309
+
310
+
311
+ # Define udf fixture for test_udf.py and test_substrait.py
312
+ @pytest.fixture(scope="session")
313
+ def unary_func_fixture():
314
+ """
315
+ Register a unary scalar function.
316
+ """
317
+ from pyarrow import compute as pc
318
+
319
+ def unary_function(ctx, x):
320
+ return pc.call_function("add", [x, 1],
321
+ memory_pool=ctx.memory_pool)
322
+ func_name = "y=x+1"
323
+ unary_doc = {"summary": "add function",
324
+ "description": "test add function"}
325
+ pc.register_scalar_function(unary_function,
326
+ func_name,
327
+ unary_doc,
328
+ {"array": pa.int64()},
329
+ pa.int64())
330
+ return unary_function, func_name
331
+
332
+
333
+ @pytest.fixture(scope="session")
334
+ def unary_agg_func_fixture():
335
+ """
336
+ Register a unary aggregate function (mean)
337
+ """
338
+ from pyarrow import compute as pc
339
+ import numpy as np
340
+
341
+ def func(ctx, x):
342
+ return pa.scalar(np.nanmean(x))
343
+
344
+ func_name = "mean_udf"
345
+ func_doc = {"summary": "y=avg(x)",
346
+ "description": "find mean of x"}
347
+
348
+ pc.register_aggregate_function(func,
349
+ func_name,
350
+ func_doc,
351
+ {
352
+ "x": pa.float64(),
353
+ },
354
+ pa.float64()
355
+ )
356
+ return func, func_name
357
+
358
+
359
+ @pytest.fixture(scope="session")
360
+ def varargs_agg_func_fixture():
361
+ """
362
+ Register a unary aggregate function
363
+ """
364
+ from pyarrow import compute as pc
365
+ import numpy as np
366
+
367
+ def func(ctx, *args):
368
+ sum = 0.0
369
+ for arg in args:
370
+ sum += np.nanmean(arg)
371
+ return pa.scalar(sum)
372
+
373
+ func_name = "sum_mean"
374
+ func_doc = {"summary": "Varargs aggregate",
375
+ "description": "Varargs aggregate"}
376
+
377
+ pc.register_aggregate_function(func,
378
+ func_name,
379
+ func_doc,
380
+ {
381
+ "x": pa.int64(),
382
+ "y": pa.float64()
383
+ },
384
+ pa.float64()
385
+ )
386
+ return func, func_name
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/json.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ from pyarrow._json import ReadOptions, ParseOptions, read_json # noqa
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/libarrow_python_parquet_encryption.so.1900.1.0 ADDED
Binary file (37.4 kB). View file
 
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/orc.py ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ from numbers import Integral
20
+ import warnings
21
+
22
+ from pyarrow.lib import Table
23
+ import pyarrow._orc as _orc
24
+ from pyarrow.fs import _resolve_filesystem_and_path
25
+
26
+
27
+ class ORCFile:
28
+ """
29
+ Reader interface for a single ORC file
30
+
31
+ Parameters
32
+ ----------
33
+ source : str or pyarrow.NativeFile
34
+ Readable source. For passing Python file objects or byte buffers,
35
+ see pyarrow.io.PythonFileInterface or pyarrow.io.BufferReader.
36
+ """
37
+
38
+ def __init__(self, source):
39
+ self.reader = _orc.ORCReader()
40
+ self.reader.open(source)
41
+
42
+ @property
43
+ def metadata(self):
44
+ """The file metadata, as an arrow KeyValueMetadata"""
45
+ return self.reader.metadata()
46
+
47
+ @property
48
+ def schema(self):
49
+ """The file schema, as an arrow schema"""
50
+ return self.reader.schema()
51
+
52
+ @property
53
+ def nrows(self):
54
+ """The number of rows in the file"""
55
+ return self.reader.nrows()
56
+
57
+ @property
58
+ def nstripes(self):
59
+ """The number of stripes in the file"""
60
+ return self.reader.nstripes()
61
+
62
+ @property
63
+ def file_version(self):
64
+ """Format version of the ORC file, must be 0.11 or 0.12"""
65
+ return self.reader.file_version()
66
+
67
+ @property
68
+ def software_version(self):
69
+ """Software instance and version that wrote this file"""
70
+ return self.reader.software_version()
71
+
72
+ @property
73
+ def compression(self):
74
+ """Compression codec of the file"""
75
+ return self.reader.compression()
76
+
77
+ @property
78
+ def compression_size(self):
79
+ """Number of bytes to buffer for the compression codec in the file"""
80
+ return self.reader.compression_size()
81
+
82
+ @property
83
+ def writer(self):
84
+ """Name of the writer that wrote this file.
85
+ If the writer is unknown then its Writer ID
86
+ (a number) is returned"""
87
+ return self.reader.writer()
88
+
89
+ @property
90
+ def writer_version(self):
91
+ """Version of the writer"""
92
+ return self.reader.writer_version()
93
+
94
+ @property
95
+ def row_index_stride(self):
96
+ """Number of rows per an entry in the row index or 0
97
+ if there is no row index"""
98
+ return self.reader.row_index_stride()
99
+
100
+ @property
101
+ def nstripe_statistics(self):
102
+ """Number of stripe statistics"""
103
+ return self.reader.nstripe_statistics()
104
+
105
+ @property
106
+ def content_length(self):
107
+ """Length of the data stripes in the file in bytes"""
108
+ return self.reader.content_length()
109
+
110
+ @property
111
+ def stripe_statistics_length(self):
112
+ """The number of compressed bytes in the file stripe statistics"""
113
+ return self.reader.stripe_statistics_length()
114
+
115
+ @property
116
+ def file_footer_length(self):
117
+ """The number of compressed bytes in the file footer"""
118
+ return self.reader.file_footer_length()
119
+
120
+ @property
121
+ def file_postscript_length(self):
122
+ """The number of bytes in the file postscript"""
123
+ return self.reader.file_postscript_length()
124
+
125
+ @property
126
+ def file_length(self):
127
+ """The number of bytes in the file"""
128
+ return self.reader.file_length()
129
+
130
+ def _select_names(self, columns=None):
131
+ if columns is None:
132
+ return None
133
+
134
+ schema = self.schema
135
+ names = []
136
+ for col in columns:
137
+ if isinstance(col, Integral):
138
+ col = int(col)
139
+ if 0 <= col < len(schema):
140
+ col = schema[col].name
141
+ names.append(col)
142
+ else:
143
+ raise ValueError("Column indices must be in 0 <= ind < %d,"
144
+ " got %d" % (len(schema), col))
145
+ else:
146
+ return columns
147
+
148
+ return names
149
+
150
+ def read_stripe(self, n, columns=None):
151
+ """Read a single stripe from the file.
152
+
153
+ Parameters
154
+ ----------
155
+ n : int
156
+ The stripe index
157
+ columns : list
158
+ If not None, only these columns will be read from the stripe. A
159
+ column name may be a prefix of a nested field, e.g. 'a' will select
160
+ 'a.b', 'a.c', and 'a.d.e'
161
+
162
+ Returns
163
+ -------
164
+ pyarrow.RecordBatch
165
+ Content of the stripe as a RecordBatch.
166
+ """
167
+ columns = self._select_names(columns)
168
+ return self.reader.read_stripe(n, columns=columns)
169
+
170
+ def read(self, columns=None):
171
+ """Read the whole file.
172
+
173
+ Parameters
174
+ ----------
175
+ columns : list
176
+ If not None, only these columns will be read from the file. A
177
+ column name may be a prefix of a nested field, e.g. 'a' will select
178
+ 'a.b', 'a.c', and 'a.d.e'. Output always follows the
179
+ ordering of the file and not the `columns` list.
180
+
181
+ Returns
182
+ -------
183
+ pyarrow.Table
184
+ Content of the file as a Table.
185
+ """
186
+ columns = self._select_names(columns)
187
+ return self.reader.read(columns=columns)
188
+
189
+
190
+ _orc_writer_args_docs = """file_version : {"0.11", "0.12"}, default "0.12"
191
+ Determine which ORC file version to use.
192
+ `Hive 0.11 / ORC v0 <https://orc.apache.org/specification/ORCv0/>`_
193
+ is the older version
194
+ while `Hive 0.12 / ORC v1 <https://orc.apache.org/specification/ORCv1/>`_
195
+ is the newer one.
196
+ batch_size : int, default 1024
197
+ Number of rows the ORC writer writes at a time.
198
+ stripe_size : int, default 64 * 1024 * 1024
199
+ Size of each ORC stripe in bytes.
200
+ compression : string, default 'uncompressed'
201
+ The compression codec.
202
+ Valid values: {'UNCOMPRESSED', 'SNAPPY', 'ZLIB', 'LZ4', 'ZSTD'}
203
+ Note that LZ0 is currently not supported.
204
+ compression_block_size : int, default 64 * 1024
205
+ Size of each compression block in bytes.
206
+ compression_strategy : string, default 'speed'
207
+ The compression strategy i.e. speed vs size reduction.
208
+ Valid values: {'SPEED', 'COMPRESSION'}
209
+ row_index_stride : int, default 10000
210
+ The row index stride i.e. the number of rows per
211
+ an entry in the row index.
212
+ padding_tolerance : double, default 0.0
213
+ The padding tolerance.
214
+ dictionary_key_size_threshold : double, default 0.0
215
+ The dictionary key size threshold. 0 to disable dictionary encoding.
216
+ 1 to always enable dictionary encoding.
217
+ bloom_filter_columns : None, set-like or list-like, default None
218
+ Columns that use the bloom filter.
219
+ bloom_filter_fpp : double, default 0.05
220
+ Upper limit of the false-positive rate of the bloom filter.
221
+ """
222
+
223
+
224
+ class ORCWriter:
225
+ __doc__ = """
226
+ Writer interface for a single ORC file
227
+
228
+ Parameters
229
+ ----------
230
+ where : str or pyarrow.io.NativeFile
231
+ Writable target. For passing Python file objects or byte buffers,
232
+ see pyarrow.io.PythonFileInterface, pyarrow.io.BufferOutputStream
233
+ or pyarrow.io.FixedSizeBufferWriter.
234
+ {}
235
+ """.format(_orc_writer_args_docs)
236
+
237
+ is_open = False
238
+
239
+ def __init__(self, where, *,
240
+ file_version='0.12',
241
+ batch_size=1024,
242
+ stripe_size=64 * 1024 * 1024,
243
+ compression='uncompressed',
244
+ compression_block_size=65536,
245
+ compression_strategy='speed',
246
+ row_index_stride=10000,
247
+ padding_tolerance=0.0,
248
+ dictionary_key_size_threshold=0.0,
249
+ bloom_filter_columns=None,
250
+ bloom_filter_fpp=0.05,
251
+ ):
252
+ self.writer = _orc.ORCWriter()
253
+ self.writer.open(
254
+ where,
255
+ file_version=file_version,
256
+ batch_size=batch_size,
257
+ stripe_size=stripe_size,
258
+ compression=compression,
259
+ compression_block_size=compression_block_size,
260
+ compression_strategy=compression_strategy,
261
+ row_index_stride=row_index_stride,
262
+ padding_tolerance=padding_tolerance,
263
+ dictionary_key_size_threshold=dictionary_key_size_threshold,
264
+ bloom_filter_columns=bloom_filter_columns,
265
+ bloom_filter_fpp=bloom_filter_fpp
266
+ )
267
+ self.is_open = True
268
+
269
+ def __del__(self):
270
+ self.close()
271
+
272
+ def __enter__(self):
273
+ return self
274
+
275
+ def __exit__(self, *args, **kwargs):
276
+ self.close()
277
+
278
+ def write(self, table):
279
+ """
280
+ Write the table into an ORC file. The schema of the table must
281
+ be equal to the schema used when opening the ORC file.
282
+
283
+ Parameters
284
+ ----------
285
+ table : pyarrow.Table
286
+ The table to be written into the ORC file
287
+ """
288
+ assert self.is_open
289
+ self.writer.write(table)
290
+
291
+ def close(self):
292
+ """
293
+ Close the ORC file
294
+ """
295
+ if self.is_open:
296
+ self.writer.close()
297
+ self.is_open = False
298
+
299
+
300
+ def read_table(source, columns=None, filesystem=None):
301
+ filesystem, path = _resolve_filesystem_and_path(source, filesystem)
302
+ if filesystem is not None:
303
+ source = filesystem.open_input_file(path)
304
+
305
+ if columns is not None and len(columns) == 0:
306
+ result = ORCFile(source).read().select(columns)
307
+ else:
308
+ result = ORCFile(source).read(columns=columns)
309
+
310
+ return result
311
+
312
+
313
+ read_table.__doc__ = """
314
+ Read a Table from an ORC file.
315
+
316
+ Parameters
317
+ ----------
318
+ source : str, pyarrow.NativeFile, or file-like object
319
+ If a string passed, can be a single file name. For file-like objects,
320
+ only read a single file. Use pyarrow.BufferReader to read a file
321
+ contained in a bytes or buffer-like object.
322
+ columns : list
323
+ If not None, only these columns will be read from the file. A column
324
+ name may be a prefix of a nested field, e.g. 'a' will select 'a.b',
325
+ 'a.c', and 'a.d.e'. Output always follows the ordering of the file and
326
+ not the `columns` list. If empty, no columns will be read. Note
327
+ that the table will still have the correct num_rows set despite having
328
+ no columns.
329
+ filesystem : FileSystem, default None
330
+ If nothing passed, will be inferred based on path.
331
+ Path will try to be found in the local on-disk filesystem otherwise
332
+ it will be parsed as an URI to determine the filesystem.
333
+ """
334
+
335
+
336
+ def write_table(table, where, *,
337
+ file_version='0.12',
338
+ batch_size=1024,
339
+ stripe_size=64 * 1024 * 1024,
340
+ compression='uncompressed',
341
+ compression_block_size=65536,
342
+ compression_strategy='speed',
343
+ row_index_stride=10000,
344
+ padding_tolerance=0.0,
345
+ dictionary_key_size_threshold=0.0,
346
+ bloom_filter_columns=None,
347
+ bloom_filter_fpp=0.05):
348
+ if isinstance(where, Table):
349
+ warnings.warn(
350
+ "The order of the arguments has changed. Pass as "
351
+ "'write_table(table, where)' instead. The old order will raise "
352
+ "an error in the future.", FutureWarning, stacklevel=2
353
+ )
354
+ table, where = where, table
355
+ with ORCWriter(
356
+ where,
357
+ file_version=file_version,
358
+ batch_size=batch_size,
359
+ stripe_size=stripe_size,
360
+ compression=compression,
361
+ compression_block_size=compression_block_size,
362
+ compression_strategy=compression_strategy,
363
+ row_index_stride=row_index_stride,
364
+ padding_tolerance=padding_tolerance,
365
+ dictionary_key_size_threshold=dictionary_key_size_threshold,
366
+ bloom_filter_columns=bloom_filter_columns,
367
+ bloom_filter_fpp=bloom_filter_fpp
368
+ ) as writer:
369
+ writer.write(table)
370
+
371
+
372
+ write_table.__doc__ = """
373
+ Write a table into an ORC file.
374
+
375
+ Parameters
376
+ ----------
377
+ table : pyarrow.lib.Table
378
+ The table to be written into the ORC file
379
+ where : str or pyarrow.io.NativeFile
380
+ Writable target. For passing Python file objects or byte buffers,
381
+ see pyarrow.io.PythonFileInterface, pyarrow.io.BufferOutputStream
382
+ or pyarrow.io.FixedSizeBufferWriter.
383
+ {}
384
+ """.format(_orc_writer_args_docs)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pyarrow/pandas_compat.py ADDED
@@ -0,0 +1,1277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ import ast
20
+ from collections.abc import Sequence
21
+ from concurrent import futures
22
+ # import threading submodule upfront to avoid partially initialized
23
+ # module bug (ARROW-11983)
24
+ import concurrent.futures.thread # noqa
25
+ from copy import deepcopy
26
+ import decimal
27
+ from itertools import zip_longest
28
+ import json
29
+ import operator
30
+ import re
31
+ import warnings
32
+
33
+ try:
34
+ import numpy as np
35
+ except ImportError:
36
+ np = None
37
+ import pyarrow as pa
38
+ from pyarrow.lib import _pandas_api, frombytes, is_threading_enabled # noqa
39
+
40
+
41
+ _logical_type_map = {}
42
+ _numpy_logical_type_map = {}
43
+ _pandas_logical_type_map = {}
44
+
45
+
46
+ def get_logical_type_map():
47
+ global _logical_type_map
48
+
49
+ if not _logical_type_map:
50
+ _logical_type_map.update({
51
+ pa.lib.Type_NA: 'empty',
52
+ pa.lib.Type_BOOL: 'bool',
53
+ pa.lib.Type_INT8: 'int8',
54
+ pa.lib.Type_INT16: 'int16',
55
+ pa.lib.Type_INT32: 'int32',
56
+ pa.lib.Type_INT64: 'int64',
57
+ pa.lib.Type_UINT8: 'uint8',
58
+ pa.lib.Type_UINT16: 'uint16',
59
+ pa.lib.Type_UINT32: 'uint32',
60
+ pa.lib.Type_UINT64: 'uint64',
61
+ pa.lib.Type_HALF_FLOAT: 'float16',
62
+ pa.lib.Type_FLOAT: 'float32',
63
+ pa.lib.Type_DOUBLE: 'float64',
64
+ pa.lib.Type_DATE32: 'date',
65
+ pa.lib.Type_DATE64: 'date',
66
+ pa.lib.Type_TIME32: 'time',
67
+ pa.lib.Type_TIME64: 'time',
68
+ pa.lib.Type_BINARY: 'bytes',
69
+ pa.lib.Type_FIXED_SIZE_BINARY: 'bytes',
70
+ pa.lib.Type_STRING: 'unicode',
71
+ })
72
+ return _logical_type_map
73
+
74
+
75
+ def get_logical_type(arrow_type):
76
+ logical_type_map = get_logical_type_map()
77
+
78
+ try:
79
+ return logical_type_map[arrow_type.id]
80
+ except KeyError:
81
+ if isinstance(arrow_type, pa.lib.DictionaryType):
82
+ return 'categorical'
83
+ elif isinstance(arrow_type, pa.lib.ListType):
84
+ return 'list[{}]'.format(get_logical_type(arrow_type.value_type))
85
+ elif isinstance(arrow_type, pa.lib.TimestampType):
86
+ return 'datetimetz' if arrow_type.tz is not None else 'datetime'
87
+ elif isinstance(arrow_type, pa.lib.Decimal128Type):
88
+ return 'decimal'
89
+ return 'object'
90
+
91
+
92
+ def get_numpy_logical_type_map():
93
+ global _numpy_logical_type_map
94
+ if not _numpy_logical_type_map:
95
+ _numpy_logical_type_map.update({
96
+ np.bool_: 'bool',
97
+ np.int8: 'int8',
98
+ np.int16: 'int16',
99
+ np.int32: 'int32',
100
+ np.int64: 'int64',
101
+ np.uint8: 'uint8',
102
+ np.uint16: 'uint16',
103
+ np.uint32: 'uint32',
104
+ np.uint64: 'uint64',
105
+ np.float32: 'float32',
106
+ np.float64: 'float64',
107
+ 'datetime64[D]': 'date',
108
+ np.str_: 'string',
109
+ np.bytes_: 'bytes',
110
+ })
111
+ return _numpy_logical_type_map
112
+
113
+
114
+ def get_logical_type_from_numpy(pandas_collection):
115
+ numpy_logical_type_map = get_numpy_logical_type_map()
116
+ try:
117
+ return numpy_logical_type_map[pandas_collection.dtype.type]
118
+ except KeyError:
119
+ if hasattr(pandas_collection.dtype, 'tz'):
120
+ return 'datetimetz'
121
+ # See https://github.com/pandas-dev/pandas/issues/24739 (infer_dtype will
122
+ # result in "datetime64" without unit, while pandas astype requires a unit)
123
+ if str(pandas_collection.dtype).startswith('datetime64'):
124
+ return str(pandas_collection.dtype)
125
+ result = _pandas_api.infer_dtype(pandas_collection)
126
+ if result == 'string':
127
+ return 'unicode'
128
+ return result
129
+
130
+
131
+ def get_extension_dtype_info(column):
132
+ dtype = column.dtype
133
+ if str(dtype) == 'category':
134
+ cats = getattr(column, 'cat', column)
135
+ assert cats is not None
136
+ metadata = {
137
+ 'num_categories': len(cats.categories),
138
+ 'ordered': cats.ordered,
139
+ }
140
+ physical_dtype = str(cats.codes.dtype)
141
+ elif hasattr(dtype, 'tz'):
142
+ metadata = {'timezone': pa.lib.tzinfo_to_string(dtype.tz)}
143
+ physical_dtype = 'datetime64[ns]'
144
+ else:
145
+ metadata = None
146
+ physical_dtype = str(dtype)
147
+ return physical_dtype, metadata
148
+
149
+
150
+ def get_column_metadata(column, name, arrow_type, field_name):
151
+ """Construct the metadata for a given column
152
+
153
+ Parameters
154
+ ----------
155
+ column : pandas.Series or pandas.Index
156
+ name : str
157
+ arrow_type : pyarrow.DataType
158
+ field_name : str
159
+ Equivalent to `name` when `column` is a `Series`, otherwise if `column`
160
+ is a pandas Index then `field_name` will not be the same as `name`.
161
+ This is the name of the field in the arrow Table's schema.
162
+
163
+ Returns
164
+ -------
165
+ dict
166
+ """
167
+ logical_type = get_logical_type(arrow_type)
168
+
169
+ string_dtype, extra_metadata = get_extension_dtype_info(column)
170
+ if logical_type == 'decimal':
171
+ extra_metadata = {
172
+ 'precision': arrow_type.precision,
173
+ 'scale': arrow_type.scale,
174
+ }
175
+ string_dtype = 'object'
176
+
177
+ if (
178
+ name is not None
179
+ and not (isinstance(name, float) and np.isnan(name))
180
+ and not isinstance(name, str)
181
+ ):
182
+ raise TypeError(
183
+ 'Column name must be a string. Got column {} of type {}'.format(
184
+ name, type(name).__name__
185
+ )
186
+ )
187
+
188
+ assert isinstance(field_name, str), str(type(field_name))
189
+ return {
190
+ 'name': name,
191
+ 'field_name': field_name,
192
+ 'pandas_type': logical_type,
193
+ 'numpy_type': string_dtype,
194
+ 'metadata': extra_metadata,
195
+ }
196
+
197
+
198
+ def construct_metadata(columns_to_convert, df, column_names, index_levels,
199
+ index_descriptors, preserve_index, types,
200
+ column_field_names=None):
201
+ """Returns a dictionary containing enough metadata to reconstruct a pandas
202
+ DataFrame as an Arrow Table, including index columns.
203
+
204
+ Parameters
205
+ ----------
206
+ columns_to_convert : list[pd.Series]
207
+ df : pandas.DataFrame
208
+ column_names : list[str | None]
209
+ column_field_names: list[str]
210
+ index_levels : List[pd.Index]
211
+ index_descriptors : List[Dict]
212
+ preserve_index : bool
213
+ types : List[pyarrow.DataType]
214
+
215
+ Returns
216
+ -------
217
+ dict
218
+ """
219
+ if column_field_names is None:
220
+ # backwards compatibility for external projects that are using
221
+ # `construct_metadata` such as cudf
222
+ # see https://github.com/apache/arrow/pull/44963#discussion_r1875771953
223
+ column_field_names = [str(name) for name in column_names]
224
+
225
+ num_serialized_index_levels = len([descr for descr in index_descriptors
226
+ if not isinstance(descr, dict)])
227
+ # Use ntypes instead of Python shorthand notation [:-len(x)] as [:-0]
228
+ # behaves differently to what we want.
229
+ ntypes = len(types)
230
+ df_types = types[:ntypes - num_serialized_index_levels]
231
+ index_types = types[ntypes - num_serialized_index_levels:]
232
+
233
+ column_metadata = []
234
+ for col, name, field_name, arrow_type in zip(columns_to_convert, column_names,
235
+ column_field_names, df_types):
236
+ metadata = get_column_metadata(col, name=name,
237
+ arrow_type=arrow_type,
238
+ field_name=field_name)
239
+ column_metadata.append(metadata)
240
+
241
+ index_column_metadata = []
242
+ if preserve_index is not False:
243
+ non_str_index_names = []
244
+ for level, arrow_type, descriptor in zip(index_levels, index_types,
245
+ index_descriptors):
246
+ if isinstance(descriptor, dict):
247
+ # The index is represented in a non-serialized fashion,
248
+ # e.g. RangeIndex
249
+ continue
250
+
251
+ if level.name is not None and not isinstance(level.name, str):
252
+ non_str_index_names.append(level.name)
253
+
254
+ metadata = get_column_metadata(
255
+ level,
256
+ name=_column_name_to_strings(level.name),
257
+ arrow_type=arrow_type,
258
+ field_name=descriptor,
259
+ )
260
+ index_column_metadata.append(metadata)
261
+
262
+ if len(non_str_index_names) > 0:
263
+ warnings.warn(
264
+ f"The DataFrame has non-str index name `{non_str_index_names}`"
265
+ " which will be converted to string"
266
+ " and not roundtrip correctly.",
267
+ UserWarning, stacklevel=4)
268
+
269
+ column_indexes = []
270
+
271
+ levels = getattr(df.columns, 'levels', [df.columns])
272
+ names = getattr(df.columns, 'names', [df.columns.name])
273
+ for level, name in zip(levels, names):
274
+ metadata = _get_simple_index_descriptor(level, name)
275
+ column_indexes.append(metadata)
276
+ else:
277
+ index_descriptors = index_column_metadata = column_indexes = []
278
+
279
+ return {
280
+ b'pandas': json.dumps({
281
+ 'index_columns': index_descriptors,
282
+ 'column_indexes': column_indexes,
283
+ 'columns': column_metadata + index_column_metadata,
284
+ 'creator': {
285
+ 'library': 'pyarrow',
286
+ 'version': pa.__version__
287
+ },
288
+ 'pandas_version': _pandas_api.version
289
+ }).encode('utf8')
290
+ }
291
+
292
+
293
+ def _get_simple_index_descriptor(level, name):
294
+ string_dtype, extra_metadata = get_extension_dtype_info(level)
295
+ pandas_type = get_logical_type_from_numpy(level)
296
+ if 'mixed' in pandas_type:
297
+ warnings.warn(
298
+ "The DataFrame has column names of mixed type. They will be "
299
+ "converted to strings and not roundtrip correctly.",
300
+ UserWarning, stacklevel=4)
301
+ if pandas_type == 'unicode':
302
+ assert not extra_metadata
303
+ extra_metadata = {'encoding': 'UTF-8'}
304
+ return {
305
+ 'name': name,
306
+ 'field_name': name,
307
+ 'pandas_type': pandas_type,
308
+ 'numpy_type': string_dtype,
309
+ 'metadata': extra_metadata,
310
+ }
311
+
312
+
313
+ def _column_name_to_strings(name):
314
+ """Convert a column name (or level) to either a string or a recursive
315
+ collection of strings.
316
+
317
+ Parameters
318
+ ----------
319
+ name : str or tuple
320
+
321
+ Returns
322
+ -------
323
+ value : str or tuple
324
+
325
+ Examples
326
+ --------
327
+ >>> name = 'foo'
328
+ >>> _column_name_to_strings(name)
329
+ 'foo'
330
+ >>> name = ('foo', 'bar')
331
+ >>> _column_name_to_strings(name)
332
+ "('foo', 'bar')"
333
+ >>> import pandas as pd
334
+ >>> name = (1, pd.Timestamp('2017-02-01 00:00:00'))
335
+ >>> _column_name_to_strings(name)
336
+ "('1', '2017-02-01 00:00:00')"
337
+ """
338
+ if isinstance(name, str):
339
+ return name
340
+ elif isinstance(name, bytes):
341
+ # XXX: should we assume that bytes in Python 3 are UTF-8?
342
+ return name.decode('utf8')
343
+ elif isinstance(name, tuple):
344
+ return str(tuple(map(_column_name_to_strings, name)))
345
+ elif isinstance(name, Sequence):
346
+ raise TypeError("Unsupported type for MultiIndex level")
347
+ elif name is None or (isinstance(name, float) and np.isnan(name)):
348
+ return name
349
+ return str(name)
350
+
351
+
352
+ def _index_level_name(index, i, column_names):
353
+ """Return the name of an index level or a default name if `index.name` is
354
+ None or is already a column name.
355
+
356
+ Parameters
357
+ ----------
358
+ index : pandas.Index
359
+ i : int
360
+
361
+ Returns
362
+ -------
363
+ name : str
364
+ """
365
+ if index.name is not None and index.name not in column_names:
366
+ return _column_name_to_strings(index.name)
367
+ else:
368
+ return '__index_level_{:d}__'.format(i)
369
+
370
+
371
+ def _get_columns_to_convert(df, schema, preserve_index, columns):
372
+ columns = _resolve_columns_of_interest(df, schema, columns)
373
+
374
+ if not df.columns.is_unique:
375
+ raise ValueError(
376
+ 'Duplicate column names found: {}'.format(list(df.columns))
377
+ )
378
+
379
+ if schema is not None:
380
+ return _get_columns_to_convert_given_schema(df, schema, preserve_index)
381
+
382
+ column_names = []
383
+ column_field_names = []
384
+
385
+ index_levels = (
386
+ _get_index_level_values(df.index) if preserve_index is not False
387
+ else []
388
+ )
389
+
390
+ columns_to_convert = []
391
+ convert_fields = []
392
+
393
+ for name in columns:
394
+ col = df[name]
395
+ name = _column_name_to_strings(name)
396
+
397
+ if _pandas_api.is_sparse(col):
398
+ raise TypeError(
399
+ "Sparse pandas data (column {}) not supported.".format(name))
400
+
401
+ columns_to_convert.append(col)
402
+ convert_fields.append(None)
403
+ column_names.append(name)
404
+ column_field_names.append(str(name))
405
+
406
+ index_descriptors = []
407
+ index_column_names = []
408
+ for i, index_level in enumerate(index_levels):
409
+ name = _index_level_name(index_level, i, column_names)
410
+ if (isinstance(index_level, _pandas_api.pd.RangeIndex) and
411
+ preserve_index is None):
412
+ descr = _get_range_index_descriptor(index_level)
413
+ else:
414
+ columns_to_convert.append(index_level)
415
+ convert_fields.append(None)
416
+ descr = name
417
+ index_column_names.append(name)
418
+ index_descriptors.append(descr)
419
+
420
+ all_names = column_field_names + index_column_names
421
+
422
+ # all_names : all of the columns in the resulting table including the data
423
+ # columns and serialized index columns
424
+ # column_names : the names of the data columns
425
+ # index_column_names : the names of the serialized index columns
426
+ # index_descriptors : descriptions of each index to be used for
427
+ # reconstruction
428
+ # index_levels : the extracted index level values
429
+ # columns_to_convert : assembled raw data (both data columns and indexes)
430
+ # to be converted to Arrow format
431
+ # columns_fields : specified column to use for coercion / casting
432
+ # during serialization, if a Schema was provided
433
+ return (all_names, column_names, column_field_names, index_column_names,
434
+ index_descriptors, index_levels, columns_to_convert, convert_fields)
435
+
436
+
437
+ def _get_columns_to_convert_given_schema(df, schema, preserve_index):
438
+ """
439
+ Specialized version of _get_columns_to_convert in case a Schema is
440
+ specified.
441
+ In that case, the Schema is used as the single point of truth for the
442
+ table structure (types, which columns are included, order of columns, ...).
443
+ """
444
+ column_names = []
445
+ columns_to_convert = []
446
+ convert_fields = []
447
+ index_descriptors = []
448
+ index_column_names = []
449
+ index_levels = []
450
+
451
+ for name in schema.names:
452
+ try:
453
+ col = df[name]
454
+ is_index = False
455
+ except KeyError:
456
+ try:
457
+ col = _get_index_level(df, name)
458
+ except (KeyError, IndexError):
459
+ # name not found as index level
460
+ raise KeyError(
461
+ "name '{}' present in the specified schema is not found "
462
+ "in the columns or index".format(name))
463
+ if preserve_index is False:
464
+ raise ValueError(
465
+ "name '{}' present in the specified schema corresponds "
466
+ "to the index, but 'preserve_index=False' was "
467
+ "specified".format(name))
468
+ elif (preserve_index is None and
469
+ isinstance(col, _pandas_api.pd.RangeIndex)):
470
+ raise ValueError(
471
+ "name '{}' is present in the schema, but it is a "
472
+ "RangeIndex which will not be converted as a column "
473
+ "in the Table, but saved as metadata-only not in "
474
+ "columns. Specify 'preserve_index=True' to force it "
475
+ "being added as a column, or remove it from the "
476
+ "specified schema".format(name))
477
+ is_index = True
478
+
479
+ if _pandas_api.is_sparse(col):
480
+ raise TypeError(
481
+ "Sparse pandas data (column {}) not supported.".format(name))
482
+
483
+ field = schema.field(name)
484
+ columns_to_convert.append(col)
485
+ convert_fields.append(field)
486
+ column_names.append(name)
487
+
488
+ if is_index:
489
+ index_column_names.append(name)
490
+ index_descriptors.append(name)
491
+ index_levels.append(col)
492
+
493
+ all_names = column_names + index_column_names
494
+
495
+ return (all_names, column_names, column_names, index_column_names,
496
+ index_descriptors, index_levels, columns_to_convert, convert_fields)
497
+
498
+
499
+ def _get_index_level(df, name):
500
+ """
501
+ Get the index level of a DataFrame given 'name' (column name in an arrow
502
+ Schema).
503
+ """
504
+ key = name
505
+ if name not in df.index.names and _is_generated_index_name(name):
506
+ # we know we have an autogenerated name => extract number and get
507
+ # the index level positionally
508
+ key = int(name[len("__index_level_"):-2])
509
+ return df.index.get_level_values(key)
510
+
511
+
512
+ def _level_name(name):
513
+ # preserve type when default serializable, otherwise str it
514
+ try:
515
+ json.dumps(name)
516
+ return name
517
+ except TypeError:
518
+ return str(name)
519
+
520
+
521
+ def _get_range_index_descriptor(level):
522
+ # public start/stop/step attributes added in pandas 0.25.0
523
+ return {
524
+ 'kind': 'range',
525
+ 'name': _level_name(level.name),
526
+ 'start': _pandas_api.get_rangeindex_attribute(level, 'start'),
527
+ 'stop': _pandas_api.get_rangeindex_attribute(level, 'stop'),
528
+ 'step': _pandas_api.get_rangeindex_attribute(level, 'step')
529
+ }
530
+
531
+
532
+ def _get_index_level_values(index):
533
+ n = len(getattr(index, 'levels', [index]))
534
+ return [index.get_level_values(i) for i in range(n)]
535
+
536
+
537
+ def _resolve_columns_of_interest(df, schema, columns):
538
+ if schema is not None and columns is not None:
539
+ raise ValueError('Schema and columns arguments are mutually '
540
+ 'exclusive, pass only one of them')
541
+ elif schema is not None:
542
+ columns = schema.names
543
+ elif columns is not None:
544
+ columns = [c for c in columns if c in df.columns]
545
+ else:
546
+ columns = df.columns
547
+
548
+ return columns
549
+
550
+
551
+ def dataframe_to_types(df, preserve_index, columns=None):
552
+ (all_names,
553
+ column_names,
554
+ column_field_names,
555
+ _,
556
+ index_descriptors,
557
+ index_columns,
558
+ columns_to_convert,
559
+ _) = _get_columns_to_convert(df, None, preserve_index, columns)
560
+
561
+ types = []
562
+ # If pandas knows type, skip conversion
563
+ for c in columns_to_convert:
564
+ values = c.values
565
+ if _pandas_api.is_categorical(values):
566
+ type_ = pa.array(c, from_pandas=True).type
567
+ elif _pandas_api.is_extension_array_dtype(values):
568
+ empty = c.head(0) if isinstance(
569
+ c, _pandas_api.pd.Series) else c[:0]
570
+ type_ = pa.array(empty, from_pandas=True).type
571
+ else:
572
+ values, type_ = get_datetimetz_type(values, c.dtype, None)
573
+ type_ = pa.lib._ndarray_to_arrow_type(values, type_)
574
+ if type_ is None:
575
+ type_ = pa.array(c, from_pandas=True).type
576
+ types.append(type_)
577
+
578
+ metadata = construct_metadata(
579
+ columns_to_convert, df, column_names, index_columns, index_descriptors,
580
+ preserve_index, types, column_field_names=column_field_names
581
+ )
582
+
583
+ return all_names, types, metadata
584
+
585
+
586
+ def dataframe_to_arrays(df, schema, preserve_index, nthreads=1, columns=None,
587
+ safe=True):
588
+ (all_names,
589
+ column_names,
590
+ column_field_names,
591
+ index_column_names,
592
+ index_descriptors,
593
+ index_columns,
594
+ columns_to_convert,
595
+ convert_fields) = _get_columns_to_convert(df, schema, preserve_index,
596
+ columns)
597
+
598
+ # NOTE(wesm): If nthreads=None, then we use a heuristic to decide whether
599
+ # using a thread pool is worth it. Currently the heuristic is whether the
600
+ # nrows > 100 * ncols and ncols > 1.
601
+ if nthreads is None:
602
+ nrows, ncols = len(df), len(df.columns)
603
+ if nrows > ncols * 100 and ncols > 1:
604
+ nthreads = pa.cpu_count()
605
+ else:
606
+ nthreads = 1
607
+ # if we don't have threading in libarrow, don't use threading here either
608
+ if not is_threading_enabled():
609
+ nthreads = 1
610
+
611
+ def convert_column(col, field):
612
+ if field is None:
613
+ field_nullable = True
614
+ type_ = None
615
+ else:
616
+ field_nullable = field.nullable
617
+ type_ = field.type
618
+
619
+ try:
620
+ result = pa.array(col, type=type_, from_pandas=True, safe=safe)
621
+ except (pa.ArrowInvalid,
622
+ pa.ArrowNotImplementedError,
623
+ pa.ArrowTypeError) as e:
624
+ e.args += ("Conversion failed for column {!s} with type {!s}"
625
+ .format(col.name, col.dtype),)
626
+ raise e
627
+ if not field_nullable and result.null_count > 0:
628
+ raise ValueError("Field {} was non-nullable but pandas column "
629
+ "had {} null values".format(str(field),
630
+ result.null_count))
631
+ return result
632
+
633
+ def _can_definitely_zero_copy(arr):
634
+ return (isinstance(arr, np.ndarray) and
635
+ arr.flags.contiguous and
636
+ issubclass(arr.dtype.type, np.integer))
637
+
638
+ if nthreads == 1:
639
+ arrays = [convert_column(c, f)
640
+ for c, f in zip(columns_to_convert, convert_fields)]
641
+ else:
642
+ arrays = []
643
+ with futures.ThreadPoolExecutor(nthreads) as executor:
644
+ for c, f in zip(columns_to_convert, convert_fields):
645
+ if _can_definitely_zero_copy(c.values):
646
+ arrays.append(convert_column(c, f))
647
+ else:
648
+ arrays.append(executor.submit(convert_column, c, f))
649
+
650
+ for i, maybe_fut in enumerate(arrays):
651
+ if isinstance(maybe_fut, futures.Future):
652
+ arrays[i] = maybe_fut.result()
653
+
654
+ types = [x.type for x in arrays]
655
+
656
+ if schema is None:
657
+ fields = []
658
+ for name, type_ in zip(all_names, types):
659
+ fields.append(pa.field(name, type_))
660
+ schema = pa.schema(fields)
661
+
662
+ pandas_metadata = construct_metadata(
663
+ columns_to_convert, df, column_names, index_columns, index_descriptors,
664
+ preserve_index, types, column_field_names=column_field_names
665
+ )
666
+ metadata = deepcopy(schema.metadata) if schema.metadata else dict()
667
+ metadata.update(pandas_metadata)
668
+ schema = schema.with_metadata(metadata)
669
+
670
+ # If dataframe is empty but with RangeIndex ->
671
+ # remember the length of the indexes
672
+ n_rows = None
673
+ if len(arrays) == 0:
674
+ try:
675
+ kind = index_descriptors[0]["kind"]
676
+ if kind == "range":
677
+ start = index_descriptors[0]["start"]
678
+ stop = index_descriptors[0]["stop"]
679
+ step = index_descriptors[0]["step"]
680
+ n_rows = len(range(start, stop, step))
681
+ except IndexError:
682
+ pass
683
+
684
+ return arrays, schema, n_rows
685
+
686
+
687
+ def get_datetimetz_type(values, dtype, type_):
688
+ if values.dtype.type != np.datetime64:
689
+ return values, type_
690
+
691
+ if _pandas_api.is_datetimetz(dtype) and type_ is None:
692
+ # If no user type passed, construct a tz-aware timestamp type
693
+ tz = dtype.tz
694
+ unit = dtype.unit
695
+ type_ = pa.timestamp(unit, tz)
696
+ elif type_ is None:
697
+ # Trust the NumPy dtype
698
+ type_ = pa.from_numpy_dtype(values.dtype)
699
+
700
+ return values, type_
701
+
702
+ # ----------------------------------------------------------------------
703
+ # Converting pyarrow.Table efficiently to pandas.DataFrame
704
+
705
+
706
+ def _reconstruct_block(item, columns=None, extension_columns=None, return_block=True):
707
+ """
708
+ Construct a pandas Block from the `item` dictionary coming from pyarrow's
709
+ serialization or returned by arrow::python::ConvertTableToPandas.
710
+
711
+ This function takes care of converting dictionary types to pandas
712
+ categorical, Timestamp-with-timezones to the proper pandas Block, and
713
+ conversion to pandas ExtensionBlock
714
+
715
+ Parameters
716
+ ----------
717
+ item : dict
718
+ For basic types, this is a dictionary in the form of
719
+ {'block': np.ndarray of values, 'placement': pandas block placement}.
720
+ Additional keys are present for other types (dictionary, timezone,
721
+ object).
722
+ columns :
723
+ Column names of the table being constructed, used for extension types
724
+ extension_columns : dict
725
+ Dictionary of {column_name: pandas_dtype} that includes all columns
726
+ and corresponding dtypes that will be converted to a pandas
727
+ ExtensionBlock.
728
+
729
+ Returns
730
+ -------
731
+ pandas Block
732
+
733
+ """
734
+ import pandas.core.internals as _int
735
+
736
+ block_arr = item.get('block', None)
737
+ placement = item['placement']
738
+ if 'dictionary' in item:
739
+ arr = _pandas_api.categorical_type.from_codes(
740
+ block_arr, categories=item['dictionary'],
741
+ ordered=item['ordered'])
742
+ elif 'timezone' in item:
743
+ unit, _ = np.datetime_data(block_arr.dtype)
744
+ dtype = make_datetimetz(unit, item['timezone'])
745
+ if _pandas_api.is_ge_v21():
746
+ arr = _pandas_api.pd.array(
747
+ block_arr.view("int64"), dtype=dtype, copy=False
748
+ )
749
+ else:
750
+ arr = block_arr
751
+ if return_block:
752
+ block = _int.make_block(block_arr, placement=placement,
753
+ klass=_int.DatetimeTZBlock,
754
+ dtype=dtype)
755
+ return block
756
+ elif 'py_array' in item:
757
+ # create ExtensionBlock
758
+ arr = item['py_array']
759
+ assert len(placement) == 1
760
+ name = columns[placement[0]]
761
+ pandas_dtype = extension_columns[name]
762
+ if not hasattr(pandas_dtype, '__from_arrow__'):
763
+ raise ValueError("This column does not support to be converted "
764
+ "to a pandas ExtensionArray")
765
+ arr = pandas_dtype.__from_arrow__(arr)
766
+ else:
767
+ arr = block_arr
768
+
769
+ if return_block:
770
+ return _int.make_block(arr, placement=placement)
771
+ else:
772
+ return arr, placement
773
+
774
+
775
+ def make_datetimetz(unit, tz):
776
+ if _pandas_api.is_v1():
777
+ unit = 'ns' # ARROW-3789: Coerce date/timestamp types to datetime64[ns]
778
+ tz = pa.lib.string_to_tzinfo(tz)
779
+ return _pandas_api.datetimetz_type(unit, tz=tz)
780
+
781
+
782
+ def table_to_dataframe(
783
+ options, table, categories=None, ignore_metadata=False, types_mapper=None
784
+ ):
785
+ all_columns = []
786
+ column_indexes = []
787
+ pandas_metadata = table.schema.pandas_metadata
788
+
789
+ if not ignore_metadata and pandas_metadata is not None:
790
+ all_columns = pandas_metadata['columns']
791
+ column_indexes = pandas_metadata.get('column_indexes', [])
792
+ index_descriptors = pandas_metadata['index_columns']
793
+ table = _add_any_metadata(table, pandas_metadata)
794
+ table, index = _reconstruct_index(table, index_descriptors,
795
+ all_columns, types_mapper)
796
+ ext_columns_dtypes = _get_extension_dtypes(
797
+ table, all_columns, types_mapper, options, categories)
798
+ else:
799
+ index = _pandas_api.pd.RangeIndex(table.num_rows)
800
+ ext_columns_dtypes = _get_extension_dtypes(
801
+ table, [], types_mapper, options, categories
802
+ )
803
+
804
+ _check_data_column_metadata_consistency(all_columns)
805
+ columns = _deserialize_column_index(table, all_columns, column_indexes)
806
+
807
+ column_names = table.column_names
808
+ result = pa.lib.table_to_blocks(options, table, categories,
809
+ list(ext_columns_dtypes.keys()))
810
+ if _pandas_api.is_ge_v3():
811
+ from pandas.api.internals import create_dataframe_from_blocks
812
+
813
+ blocks = [
814
+ _reconstruct_block(
815
+ item, column_names, ext_columns_dtypes, return_block=False)
816
+ for item in result
817
+ ]
818
+ df = create_dataframe_from_blocks(blocks, index=index, columns=columns)
819
+ return df
820
+ else:
821
+ from pandas.core.internals import BlockManager
822
+ from pandas import DataFrame
823
+
824
+ blocks = [
825
+ _reconstruct_block(item, column_names, ext_columns_dtypes)
826
+ for item in result
827
+ ]
828
+ axes = [columns, index]
829
+ mgr = BlockManager(blocks, axes)
830
+ if _pandas_api.is_ge_v21():
831
+ df = DataFrame._from_mgr(mgr, mgr.axes)
832
+ else:
833
+ df = DataFrame(mgr)
834
+ return df
835
+
836
+
837
+ # Set of the string repr of all numpy dtypes that can be stored in a pandas
838
+ # dataframe (complex not included since not supported by Arrow)
839
+ _pandas_supported_numpy_types = {
840
+ "int8", "int16", "int32", "int64",
841
+ "uint8", "uint16", "uint32", "uint64",
842
+ "float16", "float32", "float64",
843
+ "object", "bool"
844
+ }
845
+
846
+
847
+ def _get_extension_dtypes(table, columns_metadata, types_mapper, options, categories):
848
+ """
849
+ Based on the stored column pandas metadata and the extension types
850
+ in the arrow schema, infer which columns should be converted to a
851
+ pandas extension dtype.
852
+
853
+ The 'numpy_type' field in the column metadata stores the string
854
+ representation of the original pandas dtype (and, despite its name,
855
+ not the 'pandas_type' field).
856
+ Based on this string representation, a pandas/numpy dtype is constructed
857
+ and then we can check if this dtype supports conversion from arrow.
858
+
859
+ """
860
+ strings_to_categorical = options["strings_to_categorical"]
861
+ categories = categories or []
862
+
863
+ ext_columns = {}
864
+
865
+ # older pandas version that does not yet support extension dtypes
866
+ if _pandas_api.extension_dtype is None:
867
+ return ext_columns
868
+
869
+ # use the specified mapping of built-in arrow types to pandas dtypes
870
+ if types_mapper:
871
+ for field in table.schema:
872
+ typ = field.type
873
+ pandas_dtype = types_mapper(typ)
874
+ if pandas_dtype is not None:
875
+ ext_columns[field.name] = pandas_dtype
876
+
877
+ # infer from extension type in the schema
878
+ for field in table.schema:
879
+ typ = field.type
880
+ if field.name not in ext_columns and isinstance(typ, pa.BaseExtensionType):
881
+ try:
882
+ pandas_dtype = typ.to_pandas_dtype()
883
+ except NotImplementedError:
884
+ pass
885
+ else:
886
+ ext_columns[field.name] = pandas_dtype
887
+
888
+ # infer the extension columns from the pandas metadata
889
+ for col_meta in columns_metadata:
890
+ try:
891
+ name = col_meta['field_name']
892
+ except KeyError:
893
+ name = col_meta['name']
894
+ dtype = col_meta['numpy_type']
895
+
896
+ if name not in ext_columns and dtype not in _pandas_supported_numpy_types:
897
+ # pandas_dtype is expensive, so avoid doing this for types
898
+ # that are certainly numpy dtypes
899
+ pandas_dtype = _pandas_api.pandas_dtype(dtype)
900
+ if isinstance(pandas_dtype, _pandas_api.extension_dtype):
901
+ if isinstance(pandas_dtype, _pandas_api.pd.StringDtype):
902
+ # when the metadata indicate to use the string dtype,
903
+ # ignore this in case:
904
+ # - it is specified to convert strings / this column to categorical
905
+ # - the column itself is dictionary encoded and would otherwise be
906
+ # converted to categorical
907
+ if strings_to_categorical or name in categories:
908
+ continue
909
+ try:
910
+ if pa.types.is_dictionary(table.schema.field(name).type):
911
+ continue
912
+ except KeyError:
913
+ pass
914
+ if hasattr(pandas_dtype, "__from_arrow__"):
915
+ ext_columns[name] = pandas_dtype
916
+
917
+ # for pandas 3.0+, use pandas' new default string dtype
918
+ if _pandas_api.uses_string_dtype() and not strings_to_categorical:
919
+ for field in table.schema:
920
+ if field.name not in ext_columns and (
921
+ pa.types.is_string(field.type)
922
+ or pa.types.is_large_string(field.type)
923
+ or pa.types.is_string_view(field.type)
924
+ ) and field.name not in categories:
925
+ ext_columns[field.name] = _pandas_api.pd.StringDtype(na_value=np.nan)
926
+
927
+ return ext_columns
928
+
929
+
930
+ def _check_data_column_metadata_consistency(all_columns):
931
+ # It can never be the case in a released version of pyarrow that
932
+ # c['name'] is None *and* 'field_name' is not a key in the column metadata,
933
+ # because the change to allow c['name'] to be None and the change to add
934
+ # 'field_name' are in the same release (0.8.0)
935
+ assert all(
936
+ (c['name'] is None and 'field_name' in c) or c['name'] is not None
937
+ for c in all_columns
938
+ )
939
+
940
+
941
+ def _deserialize_column_index(block_table, all_columns, column_indexes):
942
+ if all_columns:
943
+ columns_name_dict = {
944
+ c.get('field_name', _column_name_to_strings(c['name'])): c['name']
945
+ for c in all_columns
946
+ }
947
+ columns_values = [
948
+ columns_name_dict.get(name, name) for name in block_table.column_names
949
+ ]
950
+ else:
951
+ columns_values = block_table.column_names
952
+
953
+ # Construct the base index
954
+ if len(column_indexes) > 1:
955
+ # If we're passed multiple column indexes then evaluate with
956
+ # ast.literal_eval, since the column index values show up as a list of
957
+ # tuples
958
+ columns = _pandas_api.pd.MultiIndex.from_tuples(
959
+ list(map(ast.literal_eval, columns_values)),
960
+ names=[col_index['name'] for col_index in column_indexes],
961
+ )
962
+ else:
963
+ columns = _pandas_api.pd.Index(
964
+ columns_values, name=column_indexes[0]["name"] if column_indexes else None
965
+ )
966
+
967
+ # if we're reconstructing the index
968
+ if len(column_indexes) > 0:
969
+ columns = _reconstruct_columns_from_metadata(columns, column_indexes)
970
+
971
+ return columns
972
+
973
+
974
+ def _reconstruct_index(table, index_descriptors, all_columns, types_mapper=None):
975
+ # 0. 'field_name' is the name of the column in the arrow Table
976
+ # 1. 'name' is the user-facing name of the column, that is, it came from
977
+ # pandas
978
+ # 2. 'field_name' and 'name' differ for index columns
979
+ # 3. We fall back on c['name'] for backwards compatibility
980
+ field_name_to_metadata = {
981
+ c.get('field_name', c['name']): c
982
+ for c in all_columns
983
+ }
984
+
985
+ # Build up a list of index columns and names while removing those columns
986
+ # from the original table
987
+ index_arrays = []
988
+ index_names = []
989
+ result_table = table
990
+ for descr in index_descriptors:
991
+ if isinstance(descr, str):
992
+ result_table, index_level, index_name = _extract_index_level(
993
+ table, result_table, descr, field_name_to_metadata, types_mapper)
994
+ if index_level is None:
995
+ # ARROW-1883: the serialized index column was not found
996
+ continue
997
+ elif descr['kind'] == 'range':
998
+ index_name = descr['name']
999
+ index_level = _pandas_api.pd.RangeIndex(descr['start'],
1000
+ descr['stop'],
1001
+ step=descr['step'],
1002
+ name=index_name)
1003
+ if len(index_level) != len(table):
1004
+ # Possibly the result of munged metadata
1005
+ continue
1006
+ else:
1007
+ raise ValueError("Unrecognized index kind: {}"
1008
+ .format(descr['kind']))
1009
+ index_arrays.append(index_level)
1010
+ index_names.append(index_name)
1011
+
1012
+ pd = _pandas_api.pd
1013
+
1014
+ # Reconstruct the row index
1015
+ if len(index_arrays) > 1:
1016
+ index = pd.MultiIndex.from_arrays(index_arrays, names=index_names)
1017
+ elif len(index_arrays) == 1:
1018
+ index = index_arrays[0]
1019
+ if not isinstance(index, pd.Index):
1020
+ # Box anything that wasn't boxed above
1021
+ index = pd.Index(index, name=index_names[0])
1022
+ else:
1023
+ index = pd.RangeIndex(table.num_rows)
1024
+
1025
+ return result_table, index
1026
+
1027
+
1028
+ def _extract_index_level(table, result_table, field_name,
1029
+ field_name_to_metadata, types_mapper=None):
1030
+ logical_name = field_name_to_metadata[field_name]['name']
1031
+ index_name = _backwards_compatible_index_name(field_name, logical_name)
1032
+ i = table.schema.get_field_index(field_name)
1033
+
1034
+ if i == -1:
1035
+ # The serialized index column was removed by the user
1036
+ return result_table, None, None
1037
+
1038
+ col = table.column(i)
1039
+ index_level = col.to_pandas(types_mapper=types_mapper)
1040
+ index_level.name = None
1041
+ result_table = result_table.remove_column(
1042
+ result_table.schema.get_field_index(field_name)
1043
+ )
1044
+ return result_table, index_level, index_name
1045
+
1046
+
1047
+ def _backwards_compatible_index_name(raw_name, logical_name):
1048
+ """Compute the name of an index column that is compatible with older
1049
+ versions of :mod:`pyarrow`.
1050
+
1051
+ Parameters
1052
+ ----------
1053
+ raw_name : str
1054
+ logical_name : str
1055
+
1056
+ Returns
1057
+ -------
1058
+ result : str
1059
+
1060
+ Notes
1061
+ -----
1062
+ * Part of :func:`~pyarrow.pandas_compat.table_to_blockmanager`
1063
+ """
1064
+ # Part of table_to_blockmanager
1065
+ if raw_name == logical_name and _is_generated_index_name(raw_name):
1066
+ return None
1067
+ else:
1068
+ return logical_name
1069
+
1070
+
1071
+ def _is_generated_index_name(name):
1072
+ pattern = r'^__index_level_\d+__$'
1073
+ return re.match(pattern, name) is not None
1074
+
1075
+
1076
+ def get_pandas_logical_type_map():
1077
+ global _pandas_logical_type_map
1078
+
1079
+ if not _pandas_logical_type_map:
1080
+ _pandas_logical_type_map.update({
1081
+ 'date': 'datetime64[D]',
1082
+ 'datetime': 'datetime64[ns]',
1083
+ 'datetimetz': 'datetime64[ns]',
1084
+ 'unicode': 'str',
1085
+ 'bytes': np.bytes_,
1086
+ 'string': 'str',
1087
+ 'integer': np.int64,
1088
+ 'floating': np.float64,
1089
+ 'decimal': np.object_,
1090
+ 'empty': np.object_,
1091
+ })
1092
+ return _pandas_logical_type_map
1093
+
1094
+
1095
+ def _pandas_type_to_numpy_type(pandas_type):
1096
+ """Get the numpy dtype that corresponds to a pandas type.
1097
+
1098
+ Parameters
1099
+ ----------
1100
+ pandas_type : str
1101
+ The result of a call to pandas.lib.infer_dtype.
1102
+
1103
+ Returns
1104
+ -------
1105
+ dtype : np.dtype
1106
+ The dtype that corresponds to `pandas_type`.
1107
+ """
1108
+ pandas_logical_type_map = get_pandas_logical_type_map()
1109
+ try:
1110
+ return pandas_logical_type_map[pandas_type]
1111
+ except KeyError:
1112
+ if 'mixed' in pandas_type:
1113
+ # catching 'mixed', 'mixed-integer' and 'mixed-integer-float'
1114
+ return np.object_
1115
+ return np.dtype(pandas_type)
1116
+
1117
+
1118
+ def _reconstruct_columns_from_metadata(columns, column_indexes):
1119
+ """Construct a pandas MultiIndex from `columns` and column index metadata
1120
+ in `column_indexes`.
1121
+
1122
+ Parameters
1123
+ ----------
1124
+ columns : List[pd.Index]
1125
+ The columns coming from a pyarrow.Table
1126
+ column_indexes : List[Dict[str, str]]
1127
+ The column index metadata deserialized from the JSON schema metadata
1128
+ in a :class:`~pyarrow.Table`.
1129
+
1130
+ Returns
1131
+ -------
1132
+ result : MultiIndex
1133
+ The index reconstructed using `column_indexes` metadata with levels of
1134
+ the correct type.
1135
+
1136
+ Notes
1137
+ -----
1138
+ * Part of :func:`~pyarrow.pandas_compat.table_to_blockmanager`
1139
+ """
1140
+ pd = _pandas_api.pd
1141
+ # Get levels and labels, and provide sane defaults if the index has a
1142
+ # single level to avoid if/else spaghetti.
1143
+ levels = getattr(columns, 'levels', None) or [columns]
1144
+ labels = getattr(columns, 'codes', None) or [None]
1145
+
1146
+ # Convert each level to the dtype provided in the metadata
1147
+ levels_dtypes = [
1148
+ (level, col_index.get('pandas_type', str(level.dtype)),
1149
+ col_index.get('numpy_type', None))
1150
+ for level, col_index in zip_longest(
1151
+ levels, column_indexes, fillvalue={}
1152
+ )
1153
+ ]
1154
+
1155
+ new_levels = []
1156
+ encoder = operator.methodcaller('encode', 'UTF-8')
1157
+
1158
+ for level, pandas_dtype, numpy_dtype in levels_dtypes:
1159
+ dtype = _pandas_type_to_numpy_type(pandas_dtype)
1160
+ # Since our metadata is UTF-8 encoded, Python turns things that were
1161
+ # bytes into unicode strings when json.loads-ing them. We need to
1162
+ # convert them back to bytes to preserve metadata.
1163
+ if dtype == np.bytes_:
1164
+ level = level.map(encoder)
1165
+ # ARROW-13756: if index is timezone aware DataTimeIndex
1166
+ if pandas_dtype == "datetimetz":
1167
+ tz = pa.lib.string_to_tzinfo(
1168
+ column_indexes[0]['metadata']['timezone'])
1169
+ level = pd.to_datetime(level, utc=True).tz_convert(tz)
1170
+ if _pandas_api.is_ge_v3():
1171
+ # with pandas 3+, to_datetime returns a unit depending on the string
1172
+ # data, so we restore it to the original unit from the metadata
1173
+ level = level.as_unit(np.datetime_data(dtype)[0])
1174
+ # GH-41503: if the column index was decimal, restore to decimal
1175
+ elif pandas_dtype == "decimal":
1176
+ level = _pandas_api.pd.Index([decimal.Decimal(i) for i in level])
1177
+ elif (
1178
+ level.dtype == "str" and numpy_dtype == "object"
1179
+ and ("mixed" in pandas_dtype or pandas_dtype in ["unicode", "string"])
1180
+ ):
1181
+ # the metadata indicate that the original dataframe used object dtype,
1182
+ # but ignore this and keep string dtype if:
1183
+ # - the original columns used mixed types -> we don't attempt to faithfully
1184
+ # roundtrip in this case, but keep the column names as strings
1185
+ # - the original columns were inferred to be strings but stored in object
1186
+ # dtype -> we don't restore the object dtype because all metadata
1187
+ # generated using pandas < 3 will have this case by default, and
1188
+ # for pandas >= 3 we want to use the default string dtype for .columns
1189
+ new_levels.append(level)
1190
+ continue
1191
+ elif level.dtype != dtype:
1192
+ level = level.astype(dtype)
1193
+ # ARROW-9096: if original DataFrame was upcast we keep that
1194
+ if level.dtype != numpy_dtype and pandas_dtype != "datetimetz":
1195
+ level = level.astype(numpy_dtype)
1196
+
1197
+ new_levels.append(level)
1198
+
1199
+ if len(new_levels) > 1:
1200
+ return pd.MultiIndex(new_levels, labels, names=columns.names)
1201
+ else:
1202
+ return pd.Index(new_levels[0], dtype=new_levels[0].dtype, name=columns.name)
1203
+
1204
+
1205
+ def _add_any_metadata(table, pandas_metadata):
1206
+ modified_columns = {}
1207
+ modified_fields = {}
1208
+
1209
+ schema = table.schema
1210
+
1211
+ index_columns = pandas_metadata['index_columns']
1212
+ # only take index columns into account if they are an actual table column
1213
+ index_columns = [idx_col for idx_col in index_columns
1214
+ if isinstance(idx_col, str)]
1215
+ n_index_levels = len(index_columns)
1216
+ n_columns = len(pandas_metadata['columns']) - n_index_levels
1217
+
1218
+ # Add time zones
1219
+ for i, col_meta in enumerate(pandas_metadata['columns']):
1220
+
1221
+ raw_name = col_meta.get('field_name')
1222
+ if not raw_name:
1223
+ # deal with metadata written with arrow < 0.8 or fastparquet
1224
+ raw_name = col_meta['name']
1225
+ if i >= n_columns:
1226
+ # index columns
1227
+ raw_name = index_columns[i - n_columns]
1228
+ if raw_name is None:
1229
+ raw_name = 'None'
1230
+
1231
+ idx = schema.get_field_index(raw_name)
1232
+ if idx != -1:
1233
+ if col_meta['pandas_type'] == 'datetimetz':
1234
+ col = table[idx]
1235
+ if not isinstance(col.type, pa.lib.TimestampType):
1236
+ continue
1237
+ metadata = col_meta['metadata']
1238
+ if not metadata:
1239
+ continue
1240
+ metadata_tz = metadata.get('timezone')
1241
+ if metadata_tz and metadata_tz != col.type.tz:
1242
+ converted = col.to_pandas()
1243
+ tz_aware_type = pa.timestamp('ns', tz=metadata_tz)
1244
+ with_metadata = pa.Array.from_pandas(converted,
1245
+ type=tz_aware_type)
1246
+
1247
+ modified_fields[idx] = pa.field(schema[idx].name,
1248
+ tz_aware_type)
1249
+ modified_columns[idx] = with_metadata
1250
+
1251
+ if len(modified_columns) > 0:
1252
+ columns = []
1253
+ fields = []
1254
+ for i in range(len(table.schema)):
1255
+ if i in modified_columns:
1256
+ columns.append(modified_columns[i])
1257
+ fields.append(modified_fields[i])
1258
+ else:
1259
+ columns.append(table[i])
1260
+ fields.append(table.schema[i])
1261
+ return pa.Table.from_arrays(columns, schema=pa.schema(fields))
1262
+ else:
1263
+ return table
1264
+
1265
+
1266
+ # ----------------------------------------------------------------------
1267
+ # Helper functions used in lib
1268
+
1269
+
1270
+ def make_tz_aware(series, tz):
1271
+ """
1272
+ Make a datetime64 Series timezone-aware for the given tz
1273
+ """
1274
+ tz = pa.lib.string_to_tzinfo(tz)
1275
+ series = (series.dt.tz_localize('utc')
1276
+ .dt.tz_convert(tz))
1277
+ return series
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/configuration_utils.py ADDED
@@ -0,0 +1,1380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team.
2
+ # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Configuration base class and utilities."""
16
+
17
+ import copy
18
+ import json
19
+ import os
20
+ import warnings
21
+ from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
22
+
23
+ from packaging import version
24
+
25
+ from . import __version__
26
+ from .dynamic_module_utils import custom_object_save
27
+ from .modeling_gguf_pytorch_utils import load_gguf_checkpoint
28
+ from .utils import (
29
+ CONFIG_NAME,
30
+ PushToHubMixin,
31
+ cached_file,
32
+ copy_func,
33
+ download_url,
34
+ extract_commit_hash,
35
+ is_remote_url,
36
+ is_torch_available,
37
+ logging,
38
+ )
39
+ from .utils.generic import is_timm_config_dict
40
+
41
+
42
+ if TYPE_CHECKING:
43
+ import torch
44
+
45
+
46
+ logger = logging.get_logger(__name__)
47
+
48
+
49
+ # type hinting: specifying the type of config class that inherits from PretrainedConfig
50
+ SpecificPretrainedConfigType = TypeVar("SpecificPretrainedConfigType", bound="PretrainedConfig")
51
+
52
+
53
+ class PretrainedConfig(PushToHubMixin):
54
+ # no-format
55
+ r"""
56
+ Base class for all configuration classes. Handles a few parameters common to all models' configurations as well as
57
+ methods for loading/downloading/saving configurations.
58
+
59
+ <Tip>
60
+
61
+ A configuration file can be loaded and saved to disk. Loading the configuration file and using this file to
62
+ initialize a model does **not** load the model weights. It only affects the model's configuration.
63
+
64
+ </Tip>
65
+
66
+ Class attributes (overridden by derived classes):
67
+
68
+ - **model_type** (`str`) -- An identifier for the model type, serialized into the JSON file, and used to recreate
69
+ the correct object in [`~transformers.AutoConfig`].
70
+ - **has_no_defaults_at_init** (`bool`) -- Whether the config class can be initialized without providing input arguments.
71
+ Some configurations requires inputs to be defined at init and have no default values, usually these are composite configs,
72
+ (but not necessarily) such as [`~transformers.EncoderDecoderConfig`] or [`~RagConfig`]. They have to be initialized from
73
+ two or more configs of type [`~transformers.PretrainedConfig`].
74
+ - **keys_to_ignore_at_inference** (`list[str]`) -- A list of keys to ignore by default when looking at dictionary
75
+ outputs of the model during inference.
76
+ - **attribute_map** (`dict[str, str]`) -- A dict that maps model specific attribute names to the standardized
77
+ naming of attributes.
78
+ - **base_model_tp_plan** (`dict[str, Any]`) -- A dict that maps sub-modules FQNs of a base model to a tensor
79
+ parallel plan applied to the sub-module when `model.tensor_parallel` is called.
80
+ - **base_model_pp_plan** (`dict[str, tuple[list[str]]]`) -- A dict that maps child-modules of a base model to a
81
+ pipeline parallel plan that enables users to place the child-module on the appropriate device.
82
+
83
+ Common attributes (present in all subclasses):
84
+
85
+ - **vocab_size** (`int`) -- The number of tokens in the vocabulary, which is also the first dimension of the
86
+ embeddings matrix (this attribute may be missing for models that don't have a text modality like ViT).
87
+ - **hidden_size** (`int`) -- The hidden size of the model.
88
+ - **num_attention_heads** (`int`) -- The number of attention heads used in the multi-head attention layers of the
89
+ model.
90
+ - **num_hidden_layers** (`int`) -- The number of blocks in the model.
91
+
92
+ <Tip warning={true}>
93
+
94
+ Setting parameters for sequence generation in the model config is deprecated. For backward compatibility, loading
95
+ some of them will still be possible, but attempting to overwrite them will throw an exception -- you should set
96
+ them in a [~transformers.GenerationConfig]. Check the documentation of [~transformers.GenerationConfig] for more
97
+ information about the individual parameters.
98
+
99
+ </Tip>
100
+
101
+ Arg:
102
+ name_or_path (`str`, *optional*, defaults to `""`):
103
+ Store the string that was passed to [`PreTrainedModel.from_pretrained`] or
104
+ [`TFPreTrainedModel.from_pretrained`] as `pretrained_model_name_or_path` if the configuration was created
105
+ with such a method.
106
+ output_hidden_states (`bool`, *optional*, defaults to `False`):
107
+ Whether or not the model should return all hidden-states.
108
+ output_attentions (`bool`, *optional*, defaults to `False`):
109
+ Whether or not the model should returns all attentions.
110
+ return_dict (`bool`, *optional*, defaults to `True`):
111
+ Whether or not the model should return a [`~transformers.utils.ModelOutput`] instead of a plain tuple.
112
+ is_encoder_decoder (`bool`, *optional*, defaults to `False`):
113
+ Whether the model is used as an encoder/decoder or not.
114
+ is_decoder (`bool`, *optional*, defaults to `False`):
115
+ Whether to only use the decoder in an encoder-decoder architecture, otherwise it has no effect on
116
+ decoder-only or encoder-only architectures.
117
+ cross_attention_hidden_size (`bool`, *optional*):
118
+ The hidden size of the cross-attention layer in case the model is used as a decoder in an encoder-decoder
119
+ setting and the cross-attention hidden dimension differs from `self.config.hidden_size`.
120
+ add_cross_attention (`bool`, *optional*, defaults to `False`):
121
+ Whether cross-attention layers should be added to the model. Note, this option is only relevant for models
122
+ that can be used as decoder models within the [`EncoderDecoderModel`] class, which consists of all models
123
+ in `AUTO_MODELS_FOR_CAUSAL_LM`.
124
+ tie_encoder_decoder (`bool`, *optional*, defaults to `False`):
125
+ Whether all encoder weights should be tied to their equivalent decoder weights. This requires the encoder
126
+ and decoder model to have the exact same parameter names.
127
+ prune_heads (`dict[int, list[int]]`, *optional*, defaults to `{}`):
128
+ Pruned heads of the model. The keys are the selected layer indices and the associated values, the list of
129
+ heads to prune in said layer.
130
+
131
+ For instance `{1: [0, 2], 2: [2, 3]}` will prune heads 0 and 2 on layer 1 and heads 2 and 3 on layer 2.
132
+ chunk_size_feed_forward (`int`, *optional*, defaults to `0`):
133
+ The chunk size of all feed forward layers in the residual attention blocks. A chunk size of `0` means that
134
+ the feed forward layer is not chunked. A chunk size of n means that the feed forward layer processes `n` <
135
+ sequence_length embeddings at a time. For more information on feed forward chunking, see [How does Feed
136
+ Forward Chunking work?](../glossary.html#feed-forward-chunking).
137
+
138
+ > Parameters for fine-tuning tasks
139
+
140
+ architectures (`list[str]`, *optional*):
141
+ Model architectures that can be used with the model pretrained weights.
142
+ finetuning_task (`str`, *optional*):
143
+ Name of the task used to fine-tune the model. This can be used when converting from an original (TensorFlow
144
+ or PyTorch) checkpoint.
145
+ id2label (`dict[int, str]`, *optional*):
146
+ A map from index (for instance prediction index, or target index) to label.
147
+ label2id (`dict[str, int]`, *optional*):
148
+ A map from label to index for the model.
149
+ num_labels (`int`, *optional*):
150
+ Number of labels to use in the last layer added to the model, typically for a classification task.
151
+ task_specific_params (`dict[str, Any]`, *optional*):
152
+ Additional keyword arguments to store for the current task.
153
+ problem_type (`str`, *optional*):
154
+ Problem type for `XxxForSequenceClassification` models. Can be one of `"regression"`,
155
+ `"single_label_classification"` or `"multi_label_classification"`.
156
+
157
+ > Parameters linked to the tokenizer
158
+
159
+ tokenizer_class (`str`, *optional*):
160
+ The name of the associated tokenizer class to use (if none is set, will use the tokenizer associated to the
161
+ model by default).
162
+ prefix (`str`, *optional*):
163
+ A specific prompt that should be added at the beginning of each text before calling the model.
164
+ bos_token_id (`int`, *optional*):
165
+ The id of the _beginning-of-stream_ token.
166
+ pad_token_id (`int`, *optional*):
167
+ The id of the _padding_ token.
168
+ eos_token_id (`int`, *optional*):
169
+ The id of the _end-of-stream_ token.
170
+ decoder_start_token_id (`int`, *optional*):
171
+ If an encoder-decoder model starts decoding with a different token than _bos_, the id of that token.
172
+ sep_token_id (`int`, *optional*):
173
+ The id of the _separation_ token.
174
+
175
+ > PyTorch specific parameters
176
+
177
+ torchscript (`bool`, *optional*, defaults to `False`):
178
+ Whether or not the model should be used with Torchscript.
179
+ tie_word_embeddings (`bool`, *optional*, defaults to `True`):
180
+ Whether the model's input and output word embeddings should be tied. Note that this is only relevant if the
181
+ model has a output word embedding layer.
182
+ dtype (`str`, *optional*):
183
+ The `dtype` of the weights. This attribute can be used to initialize the model to a non-default `dtype`
184
+ (which is normally `float32`) and thus allow for optimal storage allocation. For example, if the saved
185
+ model is `float16`, ideally we want to load it back using the minimal amount of memory needed to load
186
+ `float16` weights.
187
+ """
188
+
189
+ model_type: str = ""
190
+ base_config_key: str = ""
191
+ sub_configs: dict[str, type["PretrainedConfig"]] = {}
192
+ has_no_defaults_at_init: bool = False
193
+ attribute_map: dict[str, str] = {}
194
+ base_model_tp_plan: Optional[dict[str, Any]] = None
195
+ base_model_pp_plan: Optional[dict[str, tuple[list[str]]]] = None
196
+ base_model_ep_plan: Optional[dict[str, tuple[list[str]]]] = None
197
+ _auto_class: Optional[str] = None
198
+
199
+ def __setattr__(self, key, value):
200
+ if key in super().__getattribute__("attribute_map"):
201
+ key = super().__getattribute__("attribute_map")[key]
202
+ super().__setattr__(key, value)
203
+
204
+ def __getattribute__(self, key):
205
+ if key != "attribute_map" and key in super().__getattribute__("attribute_map"):
206
+ key = super().__getattribute__("attribute_map")[key]
207
+ return super().__getattribute__(key)
208
+
209
+ def __init__(
210
+ self,
211
+ *,
212
+ # All models common arguments
213
+ output_hidden_states: bool = False,
214
+ output_attentions: bool = False,
215
+ return_dict: bool = True,
216
+ torchscript: bool = False,
217
+ dtype: Optional[Union[str, "torch.dtype"]] = None,
218
+ # Common arguments
219
+ pruned_heads: Optional[dict[int, list[int]]] = None,
220
+ tie_word_embeddings: bool = True,
221
+ chunk_size_feed_forward: int = 0,
222
+ is_encoder_decoder: bool = False,
223
+ is_decoder: bool = False,
224
+ cross_attention_hidden_size: Optional[int] = None,
225
+ add_cross_attention: bool = False,
226
+ tie_encoder_decoder: bool = False,
227
+ # Fine-tuning task arguments
228
+ architectures: Optional[list[str]] = None,
229
+ finetuning_task: Optional[str] = None,
230
+ id2label: Optional[dict[int, str]] = None,
231
+ label2id: Optional[dict[str, int]] = None,
232
+ num_labels: Optional[int] = None,
233
+ task_specific_params: Optional[dict[str, Any]] = None,
234
+ problem_type: Optional[str] = None,
235
+ # Tokenizer kwargs
236
+ tokenizer_class: Optional[str] = None,
237
+ prefix: Optional[str] = None,
238
+ bos_token_id: Optional[int] = None,
239
+ pad_token_id: Optional[int] = None,
240
+ eos_token_id: Optional[int] = None,
241
+ sep_token_id: Optional[int] = None,
242
+ decoder_start_token_id: Optional[int] = None,
243
+ **kwargs,
244
+ ):
245
+ # Validation for some arguments
246
+ if label2id is not None and not isinstance(label2id, dict):
247
+ raise ValueError("Argument label2id should be a dictionary.")
248
+ if id2label is not None and not isinstance(id2label, dict):
249
+ raise ValueError("Argument id2label should be a dictionary.")
250
+ if num_labels is not None and id2label is not None and len(id2label) != num_labels:
251
+ logger.warning(
252
+ f"You passed `num_labels={num_labels}` which is incompatible to "
253
+ f"the `id2label` map of length `{len(id2label)}`."
254
+ )
255
+ if problem_type is not None and problem_type not in (
256
+ "regression",
257
+ "single_label_classification",
258
+ "multi_label_classification",
259
+ ):
260
+ raise ValueError(
261
+ f"The config parameter `problem_type` was not understood: received {problem_type} "
262
+ "but only 'regression', 'single_label_classification' and 'multi_label_classification' are valid."
263
+ )
264
+ # BC for the `torch_dtype` argument instead of the simpler `dtype`
265
+ # Do not warn, as it would otherwise always be triggered since most configs on the hub have `torch_dtype`
266
+ if (torch_dtype := kwargs.pop("torch_dtype", None)) is not None:
267
+ # If both are provided, keep `dtype`
268
+ dtype = dtype if dtype is not None else torch_dtype
269
+ if dtype is not None and isinstance(dtype, str) and is_torch_available():
270
+ # we will start using self.dtype in v5, but to be consistent with
271
+ # from_pretrained's dtype arg convert it to an actual torch.dtype object
272
+ import torch
273
+
274
+ dtype = getattr(torch, dtype)
275
+
276
+ # Attributes common for all models
277
+ self.return_dict = return_dict
278
+ self.output_hidden_states = output_hidden_states
279
+ self.torchscript = torchscript
280
+ self.dtype = dtype
281
+ self._output_attentions = output_attentions # has public property
282
+
283
+ # Less common kwargs, only used by some models
284
+ self.pruned_heads = pruned_heads if pruned_heads is not None else {}
285
+ self.tie_word_embeddings = tie_word_embeddings
286
+ self.chunk_size_feed_forward = chunk_size_feed_forward
287
+
288
+ # Encoder-decoder models attributes
289
+ self.is_encoder_decoder = is_encoder_decoder
290
+ self.is_decoder = is_decoder # used in encoder-decoder models to differentiate encoder from decoder
291
+ self.cross_attention_hidden_size = cross_attention_hidden_size
292
+ self.add_cross_attention = add_cross_attention
293
+ self.tie_encoder_decoder = tie_encoder_decoder
294
+
295
+ # Fine-tuning task attributes
296
+ self.architectures = architectures
297
+ self.finetuning_task = finetuning_task
298
+ self.id2label = id2label
299
+ self.label2id = label2id
300
+ self.task_specific_params = task_specific_params
301
+ self.problem_type = problem_type
302
+
303
+ if self.id2label is None:
304
+ self._create_id_label_maps(num_labels if num_labels is not None else 2)
305
+ else:
306
+ # Keys are always strings in JSON so convert ids to int here.
307
+ self.id2label = {int(key): value for key, value in self.id2label.items()}
308
+
309
+ # Tokenizer attributes
310
+ self.tokenizer_class = tokenizer_class
311
+ self.prefix = prefix
312
+ self.bos_token_id = bos_token_id
313
+ self.pad_token_id = pad_token_id
314
+ self.eos_token_id = eos_token_id
315
+ self.sep_token_id = sep_token_id
316
+ self.decoder_start_token_id = decoder_start_token_id
317
+
318
+ # Retrocompatibility: Parameters for sequence generation. While we will keep the ability to load these
319
+ # parameters, saving them will be deprecated. In a distant future, we won't need to load them.
320
+ for parameter_name, default_value in self._get_global_generation_defaults().items():
321
+ setattr(self, parameter_name, kwargs.pop(parameter_name, default_value))
322
+
323
+ # Name or path to the pretrained checkpoint
324
+ self._name_or_path = str(kwargs.pop("name_or_path", ""))
325
+ self._commit_hash = kwargs.pop("_commit_hash", None)
326
+
327
+ # Attention implementation to use, if relevant (it sets it recursively on sub-configs)
328
+ self._attn_implementation = kwargs.pop("attn_implementation", None)
329
+
330
+ # Drop the transformers version info
331
+ self.transformers_version = kwargs.pop("transformers_version", None)
332
+
333
+ # Deal with gradient checkpointing
334
+ if kwargs.get("gradient_checkpointing", False):
335
+ warnings.warn(
336
+ "Passing `gradient_checkpointing` to a config initialization is deprecated and will be removed in v5 "
337
+ "Transformers. Using `model.gradient_checkpointing_enable()` instead, or if you are using the "
338
+ "`Trainer` API, pass `gradient_checkpointing=True` in your `TrainingArguments`."
339
+ )
340
+
341
+ # Additional attributes without default values
342
+ for key, value in kwargs.items():
343
+ try:
344
+ setattr(self, key, value)
345
+ except AttributeError as err:
346
+ logger.error(f"Can't set {key} with value {value} for {self}")
347
+ raise err
348
+
349
+ # TODO: remove later, deprecated arguments for TF models
350
+ self.tf_legacy_loss = kwargs.pop("tf_legacy_loss", False)
351
+ self.use_bfloat16 = kwargs.pop("use_bfloat16", False)
352
+
353
+ def _create_id_label_maps(self, num_labels: int):
354
+ self.id2label = {i: f"LABEL_{i}" for i in range(num_labels)}
355
+ self.label2id = dict(zip(self.id2label.values(), self.id2label.keys()))
356
+
357
+ @property
358
+ def name_or_path(self) -> Optional[str]:
359
+ return getattr(self, "_name_or_path", None)
360
+
361
+ @name_or_path.setter
362
+ def name_or_path(self, value):
363
+ self._name_or_path = str(value) # Make sure that name_or_path is a string (for JSON encoding)
364
+
365
+ @property
366
+ def output_attentions(self):
367
+ """
368
+ `bool`: Whether or not the model should returns all attentions.
369
+ """
370
+ return self._output_attentions
371
+
372
+ @output_attentions.setter
373
+ def output_attentions(self, value: bool):
374
+ # If we set `output_attentions` explicitly before the attn implementation, dispatch eager
375
+ if value and self._attn_implementation is None:
376
+ self._attn_implementation = "eager"
377
+ if value and self._attn_implementation != "eager":
378
+ raise ValueError(
379
+ "The `output_attentions` attribute is not supported when using the `attn_implementation` set to "
380
+ f"{self._attn_implementation}. Please set it to 'eager' instead."
381
+ )
382
+ self._output_attentions = value
383
+
384
+ @property
385
+ def use_return_dict(self) -> bool:
386
+ """
387
+ `bool`: Whether or not return [`~utils.ModelOutput`] instead of tuples.
388
+ """
389
+ # If torchscript is set, force `return_dict=False` to avoid jit errors
390
+ return self.return_dict and not self.torchscript
391
+
392
+ @property
393
+ def num_labels(self) -> int:
394
+ """
395
+ `int`: The number of labels for classification models.
396
+ """
397
+ return len(self.id2label)
398
+
399
+ @num_labels.setter
400
+ def num_labels(self, num_labels: int):
401
+ # we do not store `num_labels` attribute in config, but instead
402
+ # compute it based on the length of the `id2label` map
403
+ if self.id2label is None or self.num_labels != num_labels:
404
+ self._create_id_label_maps(num_labels)
405
+
406
+ @property
407
+ def _attn_implementation(self):
408
+ return self._attn_implementation_internal
409
+
410
+ @_attn_implementation.setter
411
+ def _attn_implementation(self, value: Optional[Union[str, dict]]):
412
+ """We set it recursively on the sub-configs as well"""
413
+ # Set if for current config
414
+ current_attn = getattr(self, "_attn_implementation", None)
415
+ attn_implementation = value if not isinstance(value, dict) else value.get("", current_attn)
416
+ self._attn_implementation_internal = attn_implementation
417
+
418
+ # Set it recursively on the subconfigs
419
+ for subconfig_key in self.sub_configs:
420
+ subconfig = getattr(self, subconfig_key, None)
421
+ if subconfig is not None:
422
+ current_subconfig_attn = getattr(subconfig, "_attn_implementation", None)
423
+ sub_implementation = (
424
+ value if not isinstance(value, dict) else value.get(subconfig_key, current_subconfig_attn)
425
+ )
426
+ subconfig._attn_implementation = sub_implementation
427
+
428
+ @property
429
+ def torch_dtype(self):
430
+ logger.warning_once("`torch_dtype` is deprecated! Use `dtype` instead!")
431
+ return self.dtype
432
+
433
+ @torch_dtype.setter
434
+ def torch_dtype(self, value):
435
+ logger.warning_once("`torch_dtype` is deprecated! Use `dtype` instead!")
436
+ self.dtype = value
437
+
438
+ def save_pretrained(self, save_directory: Union[str, os.PathLike], push_to_hub: bool = False, **kwargs):
439
+ """
440
+ Save a configuration object to the directory `save_directory`, so that it can be re-loaded using the
441
+ [`~PretrainedConfig.from_pretrained`] class method.
442
+
443
+ Args:
444
+ save_directory (`str` or `os.PathLike`):
445
+ Directory where the configuration JSON file will be saved (will be created if it does not exist).
446
+ push_to_hub (`bool`, *optional*, defaults to `False`):
447
+ Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
448
+ repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
449
+ namespace).
450
+ kwargs (`dict[str, Any]`, *optional*):
451
+ Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
452
+ """
453
+ self._set_token_in_kwargs(kwargs)
454
+
455
+ if os.path.isfile(save_directory):
456
+ raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")
457
+
458
+ non_default_generation_parameters = self._get_non_default_generation_parameters()
459
+ if len(non_default_generation_parameters) > 0:
460
+ # TODO (joao): this should be an exception if the user has modified the loaded config. See #33886
461
+ warnings.warn(
462
+ "Some non-default generation parameters are set in the model config. These should go into either a) "
463
+ "`model.generation_config` (as opposed to `model.config`); OR b) a GenerationConfig file "
464
+ "(https://huggingface.co/docs/transformers/generation_strategies#save-a-custom-decoding-strategy-with-your-model)."
465
+ "This warning will become an exception in the future."
466
+ f"\nNon-default generation parameters: {str(non_default_generation_parameters)}",
467
+ UserWarning,
468
+ )
469
+
470
+ os.makedirs(save_directory, exist_ok=True)
471
+
472
+ if push_to_hub:
473
+ commit_message = kwargs.pop("commit_message", None)
474
+ repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])
475
+ repo_id = self._create_repo(repo_id, **kwargs)
476
+ files_timestamps = self._get_files_timestamps(save_directory)
477
+
478
+ # This attribute is important to know on load, but should not be serialized on save.
479
+ if "transformers_weights" in self:
480
+ delattr(self, "transformers_weights")
481
+
482
+ # If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
483
+ # loaded from the Hub.
484
+ if self._auto_class is not None:
485
+ custom_object_save(self, save_directory, config=self)
486
+
487
+ # If we save using the predefined names, we can load using `from_pretrained`
488
+ output_config_file = os.path.join(save_directory, CONFIG_NAME)
489
+
490
+ self.to_json_file(output_config_file, use_diff=True)
491
+ logger.info(f"Configuration saved in {output_config_file}")
492
+
493
+ if push_to_hub:
494
+ self._upload_modified_files(
495
+ save_directory,
496
+ repo_id,
497
+ files_timestamps,
498
+ commit_message=commit_message,
499
+ token=kwargs.get("token"),
500
+ )
501
+
502
+ @staticmethod
503
+ def _set_token_in_kwargs(kwargs, token=None):
504
+ """Temporary method to deal with `token` and `use_auth_token`.
505
+
506
+ This method is to avoid apply the same changes in all model config classes that overwrite `from_pretrained`.
507
+
508
+ Need to clean up `use_auth_token` in a follow PR.
509
+ """
510
+ # Some model config classes like CLIP define their own `from_pretrained` without the new argument `token` yet.
511
+ if token is None:
512
+ token = kwargs.pop("token", None)
513
+ use_auth_token = kwargs.pop("use_auth_token", None)
514
+
515
+ if use_auth_token is not None:
516
+ warnings.warn(
517
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
518
+ FutureWarning,
519
+ )
520
+ if token is not None:
521
+ raise ValueError(
522
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
523
+ )
524
+ token = use_auth_token
525
+
526
+ if token is not None:
527
+ kwargs["token"] = token
528
+
529
+ @classmethod
530
+ def from_pretrained(
531
+ cls: type[SpecificPretrainedConfigType],
532
+ pretrained_model_name_or_path: Union[str, os.PathLike],
533
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
534
+ force_download: bool = False,
535
+ local_files_only: bool = False,
536
+ token: Optional[Union[str, bool]] = None,
537
+ revision: str = "main",
538
+ **kwargs,
539
+ ) -> SpecificPretrainedConfigType:
540
+ r"""
541
+ Instantiate a [`PretrainedConfig`] (or a derived class) from a pretrained model configuration.
542
+
543
+ Args:
544
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
545
+ This can be either:
546
+
547
+ - a string, the *model id* of a pretrained model configuration hosted inside a model repo on
548
+ huggingface.co.
549
+ - a path to a *directory* containing a configuration file saved using the
550
+ [`~PretrainedConfig.save_pretrained`] method, e.g., `./my_model_directory/`.
551
+ - a path or url to a saved configuration JSON *file*, e.g., `./my_model_directory/configuration.json`.
552
+ cache_dir (`str` or `os.PathLike`, *optional*):
553
+ Path to a directory in which a downloaded pretrained model configuration should be cached if the
554
+ standard cache should not be used.
555
+ force_download (`bool`, *optional*, defaults to `False`):
556
+ Whether or not to force to (re-)download the configuration files and override the cached versions if
557
+ they exist.
558
+ resume_download:
559
+ Deprecated and ignored. All downloads are now resumed by default when possible.
560
+ Will be removed in v5 of Transformers.
561
+ proxies (`dict[str, str]`, *optional*):
562
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
563
+ 'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
564
+ token (`str` or `bool`, *optional*):
565
+ The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use
566
+ the token generated when running `hf auth login` (stored in `~/.huggingface`).
567
+ revision (`str`, *optional*, defaults to `"main"`):
568
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
569
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
570
+ identifier allowed by git.
571
+
572
+ <Tip>
573
+
574
+ To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>"`.
575
+
576
+ </Tip>
577
+
578
+ return_unused_kwargs (`bool`, *optional*, defaults to `False`):
579
+ If `False`, then this function returns just the final configuration object.
580
+
581
+ If `True`, then this functions returns a `Tuple(config, unused_kwargs)` where *unused_kwargs* is a
582
+ dictionary consisting of the key/value pairs whose keys are not configuration attributes: i.e., the
583
+ part of `kwargs` which has not been used to update `config` and is otherwise ignored.
584
+ subfolder (`str`, *optional*, defaults to `""`):
585
+ In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can
586
+ specify the folder name here.
587
+ kwargs (`dict[str, Any]`, *optional*):
588
+ The values in kwargs of any keys which are configuration attributes will be used to override the loaded
589
+ values. Behavior concerning key/value pairs whose keys are *not* configuration attributes is controlled
590
+ by the `return_unused_kwargs` keyword parameter.
591
+
592
+ Returns:
593
+ [`PretrainedConfig`]: The configuration object instantiated from this pretrained model.
594
+
595
+ Examples:
596
+
597
+ ```python
598
+ # We can't instantiate directly the base class *PretrainedConfig* so let's show the examples on a
599
+ # derived class: BertConfig
600
+ config = BertConfig.from_pretrained(
601
+ "google-bert/bert-base-uncased"
602
+ ) # Download configuration from huggingface.co and cache.
603
+ config = BertConfig.from_pretrained(
604
+ "./test/saved_model/"
605
+ ) # E.g. config (or model) was saved using *save_pretrained('./test/saved_model/')*
606
+ config = BertConfig.from_pretrained("./test/saved_model/my_configuration.json")
607
+ config = BertConfig.from_pretrained("google-bert/bert-base-uncased", output_attentions=True, foo=False)
608
+ assert config.output_attentions == True
609
+ config, unused_kwargs = BertConfig.from_pretrained(
610
+ "google-bert/bert-base-uncased", output_attentions=True, foo=False, return_unused_kwargs=True
611
+ )
612
+ assert config.output_attentions == True
613
+ assert unused_kwargs == {"foo": False}
614
+ ```"""
615
+ kwargs["cache_dir"] = cache_dir
616
+ kwargs["force_download"] = force_download
617
+ kwargs["local_files_only"] = local_files_only
618
+ kwargs["revision"] = revision
619
+
620
+ cls._set_token_in_kwargs(kwargs, token)
621
+
622
+ config_dict, kwargs = cls.get_config_dict(pretrained_model_name_or_path, **kwargs)
623
+ if cls.base_config_key and cls.base_config_key in config_dict:
624
+ config_dict = config_dict[cls.base_config_key]
625
+
626
+ if "model_type" in config_dict and hasattr(cls, "model_type") and config_dict["model_type"] != cls.model_type:
627
+ # sometimes the config has no `base_config_key` if the config is used in several composite models
628
+ # e.g. LlamaConfig. In that case we try to see if there is match in `model_type` before raising a warning
629
+ for v in config_dict.values():
630
+ if isinstance(v, dict) and v.get("model_type") == cls.model_type:
631
+ config_dict = v
632
+
633
+ # raise warning only if we still can't see a match in `model_type`
634
+ if config_dict["model_type"] != cls.model_type:
635
+ logger.warning(
636
+ f"You are using a model of type {config_dict['model_type']} to instantiate a model of type "
637
+ f"{cls.model_type}. This is not supported for all configurations of models and can yield errors."
638
+ )
639
+
640
+ return cls.from_dict(config_dict, **kwargs)
641
+
642
+ @classmethod
643
+ def get_config_dict(
644
+ cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs
645
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
646
+ """
647
+ From a `pretrained_model_name_or_path`, resolve to a dictionary of parameters, to be used for instantiating a
648
+ [`PretrainedConfig`] using `from_dict`.
649
+
650
+ Parameters:
651
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
652
+ The identifier of the pre-trained checkpoint from which we want the dictionary of parameters.
653
+
654
+ Returns:
655
+ `tuple[Dict, Dict]`: The dictionary(ies) that will be used to instantiate the configuration object.
656
+
657
+ """
658
+ cls._set_token_in_kwargs(kwargs)
659
+
660
+ original_kwargs = copy.deepcopy(kwargs)
661
+ # Get config dict associated with the base config file
662
+ config_dict, kwargs = cls._get_config_dict(pretrained_model_name_or_path, **kwargs)
663
+ if config_dict is None:
664
+ return {}, kwargs
665
+ if "_commit_hash" in config_dict:
666
+ original_kwargs["_commit_hash"] = config_dict["_commit_hash"]
667
+
668
+ # That config file may point us toward another config file to use.
669
+ if "configuration_files" in config_dict:
670
+ configuration_file = get_configuration_file(config_dict["configuration_files"])
671
+ config_dict, kwargs = cls._get_config_dict(
672
+ pretrained_model_name_or_path, _configuration_file=configuration_file, **original_kwargs
673
+ )
674
+
675
+ return config_dict, kwargs
676
+
677
+ @classmethod
678
+ def _get_config_dict(
679
+ cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs
680
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
681
+ cache_dir = kwargs.pop("cache_dir", None)
682
+ force_download = kwargs.pop("force_download", False)
683
+ resume_download = kwargs.pop("resume_download", None)
684
+ proxies = kwargs.pop("proxies", None)
685
+ token = kwargs.pop("token", None)
686
+ local_files_only = kwargs.pop("local_files_only", False)
687
+ revision = kwargs.pop("revision", None)
688
+ trust_remote_code = kwargs.pop("trust_remote_code", None)
689
+ subfolder = kwargs.pop("subfolder", "")
690
+ from_pipeline = kwargs.pop("_from_pipeline", None)
691
+ from_auto_class = kwargs.pop("_from_auto", False)
692
+ commit_hash = kwargs.pop("_commit_hash", None)
693
+
694
+ gguf_file = kwargs.get("gguf_file")
695
+
696
+ if trust_remote_code is True:
697
+ logger.warning(
698
+ "The argument `trust_remote_code` is to be used with Auto classes. It has no effect here and is"
699
+ " ignored."
700
+ )
701
+
702
+ user_agent = {"file_type": "config", "from_auto_class": from_auto_class}
703
+ if from_pipeline is not None:
704
+ user_agent["using_pipeline"] = from_pipeline
705
+
706
+ pretrained_model_name_or_path = str(pretrained_model_name_or_path)
707
+
708
+ is_local = os.path.isdir(pretrained_model_name_or_path)
709
+ if os.path.isfile(os.path.join(subfolder, pretrained_model_name_or_path)):
710
+ # Special case when pretrained_model_name_or_path is a local file
711
+ resolved_config_file = pretrained_model_name_or_path
712
+ is_local = True
713
+ elif is_remote_url(pretrained_model_name_or_path):
714
+ configuration_file = pretrained_model_name_or_path if gguf_file is None else gguf_file
715
+ resolved_config_file = download_url(pretrained_model_name_or_path)
716
+ else:
717
+ configuration_file = kwargs.pop("_configuration_file", CONFIG_NAME) if gguf_file is None else gguf_file
718
+
719
+ try:
720
+ # Load from local folder or from cache or download from model Hub and cache
721
+ resolved_config_file = cached_file(
722
+ pretrained_model_name_or_path,
723
+ configuration_file,
724
+ cache_dir=cache_dir,
725
+ force_download=force_download,
726
+ proxies=proxies,
727
+ resume_download=resume_download,
728
+ local_files_only=local_files_only,
729
+ token=token,
730
+ user_agent=user_agent,
731
+ revision=revision,
732
+ subfolder=subfolder,
733
+ _commit_hash=commit_hash,
734
+ )
735
+ if resolved_config_file is None:
736
+ return None, kwargs
737
+ commit_hash = extract_commit_hash(resolved_config_file, commit_hash)
738
+ except OSError:
739
+ # Raise any environment error raise by `cached_file`. It will have a helpful error message adapted to
740
+ # the original exception.
741
+ raise
742
+ except Exception:
743
+ # For any other exception, we throw a generic error.
744
+ raise OSError(
745
+ f"Can't load the configuration of '{pretrained_model_name_or_path}'. If you were trying to load it"
746
+ " from 'https://huggingface.co/models', make sure you don't have a local directory with the same"
747
+ f" name. Otherwise, make sure '{pretrained_model_name_or_path}' is the correct path to a directory"
748
+ f" containing a {configuration_file} file"
749
+ )
750
+
751
+ try:
752
+ if gguf_file:
753
+ config_dict = load_gguf_checkpoint(resolved_config_file, return_tensors=False)["config"]
754
+ else:
755
+ # Load config dict
756
+ config_dict = cls._dict_from_json_file(resolved_config_file)
757
+
758
+ config_dict["_commit_hash"] = commit_hash
759
+ except (json.JSONDecodeError, UnicodeDecodeError):
760
+ raise OSError(f"It looks like the config file at '{resolved_config_file}' is not a valid JSON file.")
761
+
762
+ if is_local:
763
+ logger.info(f"loading configuration file {resolved_config_file}")
764
+ else:
765
+ logger.info(f"loading configuration file {configuration_file} from cache at {resolved_config_file}")
766
+
767
+ # timm models are not saved with the model_type in the config file
768
+ if "model_type" not in config_dict and is_timm_config_dict(config_dict):
769
+ config_dict["model_type"] = "timm_wrapper"
770
+
771
+ return config_dict, kwargs
772
+
773
+ @classmethod
774
+ def from_dict(
775
+ cls: type[SpecificPretrainedConfigType], config_dict: dict[str, Any], **kwargs
776
+ ) -> SpecificPretrainedConfigType:
777
+ """
778
+ Instantiates a [`PretrainedConfig`] from a Python dictionary of parameters.
779
+
780
+ Args:
781
+ config_dict (`dict[str, Any]`):
782
+ Dictionary that will be used to instantiate the configuration object. Such a dictionary can be
783
+ retrieved from a pretrained checkpoint by leveraging the [`~PretrainedConfig.get_config_dict`] method.
784
+ kwargs (`dict[str, Any]`):
785
+ Additional parameters from which to initialize the configuration object.
786
+
787
+ Returns:
788
+ [`PretrainedConfig`]: The configuration object instantiated from those parameters.
789
+ """
790
+ return_unused_kwargs = kwargs.pop("return_unused_kwargs", False)
791
+ # Those arguments may be passed along for our internal telemetry.
792
+ # We remove them so they don't appear in `return_unused_kwargs`.
793
+ kwargs.pop("_from_auto", None)
794
+ kwargs.pop("_from_pipeline", None)
795
+ # The commit hash might have been updated in the `config_dict`, we don't want the kwargs to erase that update.
796
+ if "_commit_hash" in kwargs and "_commit_hash" in config_dict:
797
+ kwargs["_commit_hash"] = config_dict["_commit_hash"]
798
+
799
+ # For BC on the old `torch_dtype`
800
+ if (torch_dtype := kwargs.pop("torch_dtype", None)) is not None:
801
+ logger.warning_once("`torch_dtype` is deprecated! Use `dtype` instead!")
802
+ # If both are present, use `dtype`
803
+ kwargs["dtype"] = kwargs.get("dtype", torch_dtype)
804
+
805
+ # We remove it from kwargs so that it does not appear in `return_unused_kwargs`.
806
+ config_dict["attn_implementation"] = kwargs.pop("attn_implementation", None)
807
+
808
+ config = cls(**config_dict)
809
+
810
+ if hasattr(config, "pruned_heads"):
811
+ config.pruned_heads = {int(key): value for key, value in config.pruned_heads.items()}
812
+
813
+ # Update config with kwargs if needed
814
+ if "num_labels" in kwargs and "id2label" in kwargs:
815
+ num_labels = kwargs["num_labels"]
816
+ id2label = kwargs["id2label"] if kwargs["id2label"] is not None else []
817
+ if len(id2label) != num_labels:
818
+ raise ValueError(
819
+ f"You passed along `num_labels={num_labels}` with an incompatible id to label map: "
820
+ f"{kwargs['id2label']}. Since those arguments are inconsistent with each other, you should remove "
821
+ "one of them."
822
+ )
823
+ to_remove = []
824
+ for key, value in kwargs.items():
825
+ if hasattr(config, key):
826
+ current_attr = getattr(config, key)
827
+ # To authorize passing a custom subconfig as kwarg in models that have nested configs.
828
+ # We need to update only custom kwarg values instead and keep other attributes in subconfig.
829
+ if isinstance(current_attr, PretrainedConfig) and isinstance(value, dict):
830
+ current_attr_updated = current_attr.to_dict()
831
+ current_attr_updated.update(value)
832
+ value = current_attr.__class__(**current_attr_updated)
833
+ setattr(config, key, value)
834
+ if key != "dtype":
835
+ to_remove.append(key)
836
+ for key in to_remove:
837
+ kwargs.pop(key, None)
838
+
839
+ logger.info(f"Model config {config}")
840
+ if return_unused_kwargs:
841
+ return config, kwargs
842
+ else:
843
+ return config
844
+
845
+ @classmethod
846
+ def from_json_file(
847
+ cls: type[SpecificPretrainedConfigType], json_file: Union[str, os.PathLike]
848
+ ) -> SpecificPretrainedConfigType:
849
+ """
850
+ Instantiates a [`PretrainedConfig`] from the path to a JSON file of parameters.
851
+
852
+ Args:
853
+ json_file (`str` or `os.PathLike`):
854
+ Path to the JSON file containing the parameters.
855
+
856
+ Returns:
857
+ [`PretrainedConfig`]: The configuration object instantiated from that JSON file.
858
+
859
+ """
860
+ config_dict = cls._dict_from_json_file(json_file)
861
+ return cls(**config_dict)
862
+
863
+ @classmethod
864
+ def _dict_from_json_file(cls, json_file: Union[str, os.PathLike]):
865
+ with open(json_file, encoding="utf-8") as reader:
866
+ text = reader.read()
867
+ return json.loads(text)
868
+
869
+ def __eq__(self, other):
870
+ return isinstance(other, PretrainedConfig) and (self.__dict__ == other.__dict__)
871
+
872
+ def __repr__(self):
873
+ return f"{self.__class__.__name__} {self.to_json_string()}"
874
+
875
+ def __iter__(self):
876
+ yield from self.__dict__
877
+
878
+ def to_diff_dict(self) -> dict[str, Any]:
879
+ """
880
+ Removes all attributes from the configuration that correspond to the default config attributes for
881
+ better readability, while always retaining the `config` attribute from the class. Serializes to a
882
+ Python dictionary.
883
+
884
+ Returns:
885
+ dict[str, Any]: Dictionary of all the attributes that make up this configuration instance.
886
+ """
887
+ config_dict = self.to_dict()
888
+
889
+ # Get the default config dict (from a fresh PreTrainedConfig instance)
890
+ default_config_dict = PretrainedConfig().to_dict()
891
+
892
+ # get class specific config dict
893
+ class_config_dict = self.__class__().to_dict() if not self.has_no_defaults_at_init else {}
894
+
895
+ serializable_config_dict = {}
896
+
897
+ # Only serialize values that differ from the default config,
898
+ # except always keep the 'config' attribute.
899
+ for key, value in config_dict.items():
900
+ if (
901
+ isinstance(getattr(self, key, None), PretrainedConfig)
902
+ and key in class_config_dict
903
+ and isinstance(class_config_dict[key], dict)
904
+ or key in self.sub_configs
905
+ ):
906
+ # For nested configs we need to clean the diff recursively
907
+ diff = recursive_diff_dict(value, default_config_dict, config_obj=getattr(self, key, None))
908
+ if "model_type" in value:
909
+ # Needs to be set even if it's not in the diff
910
+ diff["model_type"] = value["model_type"]
911
+
912
+ serializable_config_dict[key] = diff
913
+ elif (
914
+ key not in default_config_dict
915
+ or key == "transformers_version"
916
+ or key == "vocab_file"
917
+ or value != default_config_dict[key]
918
+ or (key in default_config_dict and value != class_config_dict.get(key, value))
919
+ ):
920
+ serializable_config_dict[key] = value
921
+
922
+ self._remove_keys_not_serialized(serializable_config_dict)
923
+
924
+ # Key removed only in diff dict
925
+ if "_name_or_path" in serializable_config_dict:
926
+ del serializable_config_dict["_name_or_path"]
927
+
928
+ if hasattr(self, "quantization_config"):
929
+ serializable_config_dict["quantization_config"] = (
930
+ self.quantization_config.to_dict()
931
+ if not isinstance(self.quantization_config, dict)
932
+ else self.quantization_config
933
+ )
934
+ self.dict_dtype_to_str(serializable_config_dict)
935
+
936
+ return serializable_config_dict
937
+
938
+ def to_dict(self) -> dict[str, Any]:
939
+ """
940
+ Serializes this instance to a Python dictionary.
941
+
942
+ Returns:
943
+ `dict[str, Any]`: Dictionary of all the attributes that make up this configuration instance.
944
+ """
945
+ output = copy.deepcopy(self.__dict__)
946
+ if hasattr(self.__class__, "model_type"):
947
+ output["model_type"] = self.__class__.model_type
948
+
949
+ # Transformers version when serializing the model
950
+ output["transformers_version"] = __version__
951
+
952
+ for key, value in output.items():
953
+ # Deal with nested configs like CLIP
954
+ if isinstance(value, PretrainedConfig):
955
+ value = value.to_dict()
956
+ del value["transformers_version"]
957
+
958
+ output[key] = value
959
+
960
+ self._remove_keys_not_serialized(output)
961
+
962
+ if hasattr(self, "quantization_config"):
963
+ output["quantization_config"] = (
964
+ self.quantization_config.to_dict()
965
+ if not isinstance(self.quantization_config, dict)
966
+ else self.quantization_config
967
+ )
968
+ self.dict_dtype_to_str(output)
969
+
970
+ return output
971
+
972
+ def to_json_string(self, use_diff: bool = True) -> str:
973
+ """
974
+ Serializes this instance to a JSON string.
975
+
976
+ Args:
977
+ use_diff (`bool`, *optional*, defaults to `True`):
978
+ If set to `True`, only the difference between the config instance and the default `PretrainedConfig()`
979
+ is serialized to JSON string.
980
+
981
+ Returns:
982
+ `str`: String containing all the attributes that make up this configuration instance in JSON format.
983
+ """
984
+ if use_diff is True:
985
+ config_dict = self.to_diff_dict()
986
+ else:
987
+ config_dict = self.to_dict()
988
+ return json.dumps(config_dict, indent=2, sort_keys=True) + "\n"
989
+
990
+ def to_json_file(self, json_file_path: Union[str, os.PathLike], use_diff: bool = True):
991
+ """
992
+ Save this instance to a JSON file.
993
+
994
+ Args:
995
+ json_file_path (`str` or `os.PathLike`):
996
+ Path to the JSON file in which this configuration instance's parameters will be saved.
997
+ use_diff (`bool`, *optional*, defaults to `True`):
998
+ If set to `True`, only the difference between the config instance and the default `PretrainedConfig()`
999
+ is serialized to JSON file.
1000
+ """
1001
+ with open(json_file_path, "w", encoding="utf-8") as writer:
1002
+ writer.write(self.to_json_string(use_diff=use_diff))
1003
+
1004
+ def update(self, config_dict: dict[str, Any]):
1005
+ """
1006
+ Updates attributes of this class with attributes from `config_dict`.
1007
+
1008
+ Args:
1009
+ config_dict (`dict[str, Any]`): Dictionary of attributes that should be updated for this class.
1010
+ """
1011
+ for key, value in config_dict.items():
1012
+ setattr(self, key, value)
1013
+
1014
+ def update_from_string(self, update_str: str):
1015
+ """
1016
+ Updates attributes of this class with attributes from `update_str`.
1017
+
1018
+ The expected format is ints, floats and strings as is, and for booleans use `true` or `false`. For example:
1019
+ "n_embd=10,resid_pdrop=0.2,scale_attn_weights=false,summary_type=cls_index"
1020
+
1021
+ The keys to change have to already exist in the config object.
1022
+
1023
+ Args:
1024
+ update_str (`str`): String with attributes that should be updated for this class.
1025
+
1026
+ """
1027
+
1028
+ d = dict(x.split("=") for x in update_str.split(","))
1029
+ for k, v in d.items():
1030
+ if not hasattr(self, k):
1031
+ raise ValueError(f"key {k} isn't in the original config dict")
1032
+
1033
+ old_v = getattr(self, k)
1034
+ if isinstance(old_v, bool):
1035
+ if v.lower() in ["true", "1", "y", "yes"]:
1036
+ v = True
1037
+ elif v.lower() in ["false", "0", "n", "no"]:
1038
+ v = False
1039
+ else:
1040
+ raise ValueError(f"can't derive true or false from {v} (key {k})")
1041
+ elif isinstance(old_v, int):
1042
+ v = int(v)
1043
+ elif isinstance(old_v, float):
1044
+ v = float(v)
1045
+ elif not isinstance(old_v, str):
1046
+ raise TypeError(
1047
+ f"You can only update int, float, bool or string values in the config, got {v} for key {k}"
1048
+ )
1049
+
1050
+ setattr(self, k, v)
1051
+
1052
+ def dict_dtype_to_str(self, d: dict[str, Any]) -> None:
1053
+ """
1054
+ Checks whether the passed dictionary and its nested dicts have a *dtype* key and if it's not None,
1055
+ converts torch.dtype to a string of just the type. For example, `torch.float32` get converted into *"float32"*
1056
+ string, which can then be stored in the json format.
1057
+ """
1058
+ if d.get("dtype") is not None:
1059
+ if isinstance(d["dtype"], dict):
1060
+ d["dtype"] = {k: str(v).split(".")[-1] for k, v in d["dtype"].items()}
1061
+ # models like Emu3 can have "dtype" as token in config's vocabulary map,
1062
+ # so we also exclude int type here to avoid error in this special case.
1063
+ elif not isinstance(d["dtype"], (str, int)):
1064
+ d["dtype"] = str(d["dtype"]).split(".")[1]
1065
+ for value in d.values():
1066
+ if isinstance(value, dict):
1067
+ self.dict_dtype_to_str(value)
1068
+
1069
+ def _remove_keys_not_serialized(self, d: dict[str, Any]) -> None:
1070
+ """
1071
+ Checks and removes if there are any keys in the dict that should not be serialized when saving the config.
1072
+ Runs recursive check on the dict, to remove from all sub configs.
1073
+ """
1074
+ if hasattr(self, "quantization_config"):
1075
+ # Pop the `_pre_quantization_dtype` as torch.dtypes are not serializable.
1076
+ _ = d.pop("_pre_quantization_dtype", None)
1077
+
1078
+ if "_auto_class" in d:
1079
+ del d["_auto_class"]
1080
+ if "_output_attentions" in d:
1081
+ d["output_attentions"] = d.pop("_output_attentions")
1082
+ if "_commit_hash" in d:
1083
+ del d["_commit_hash"]
1084
+ if "_attn_implementation_internal" in d:
1085
+ del d["_attn_implementation_internal"]
1086
+ # Do not serialize `base_model_tp_plan` for now
1087
+ if "base_model_tp_plan" in d:
1088
+ del d["base_model_tp_plan"]
1089
+ # Do not serialize `base_model_pp_plan` for now
1090
+ if "base_model_pp_plan" in d:
1091
+ del d["base_model_pp_plan"]
1092
+ for value in d.values():
1093
+ if isinstance(value, dict):
1094
+ self._remove_keys_not_serialized(value)
1095
+
1096
+ @classmethod
1097
+ def register_for_auto_class(cls, auto_class="AutoConfig"):
1098
+ """
1099
+ Register this class with a given auto class. This should only be used for custom configurations as the ones in
1100
+ the library are already mapped with `AutoConfig`.
1101
+
1102
+
1103
+
1104
+ Args:
1105
+ auto_class (`str` or `type`, *optional*, defaults to `"AutoConfig"`):
1106
+ The auto class to register this new configuration with.
1107
+ """
1108
+ if not isinstance(auto_class, str):
1109
+ auto_class = auto_class.__name__
1110
+
1111
+ import transformers.models.auto as auto_module
1112
+
1113
+ if not hasattr(auto_module, auto_class):
1114
+ raise ValueError(f"{auto_class} is not a valid auto class.")
1115
+
1116
+ cls._auto_class = auto_class
1117
+
1118
+ @staticmethod
1119
+ def _get_global_generation_defaults() -> dict[str, Any]:
1120
+ return {
1121
+ "max_length": 20,
1122
+ "min_length": 0,
1123
+ "do_sample": False,
1124
+ "early_stopping": False,
1125
+ "num_beams": 1,
1126
+ "temperature": 1.0,
1127
+ "top_k": 50,
1128
+ "top_p": 1.0,
1129
+ "typical_p": 1.0,
1130
+ "repetition_penalty": 1.0,
1131
+ "length_penalty": 1.0,
1132
+ "no_repeat_ngram_size": 0,
1133
+ "encoder_no_repeat_ngram_size": 0,
1134
+ "bad_words_ids": None,
1135
+ "num_return_sequences": 1,
1136
+ "output_scores": False,
1137
+ "return_dict_in_generate": False,
1138
+ "forced_bos_token_id": None,
1139
+ "forced_eos_token_id": None,
1140
+ "remove_invalid_values": False,
1141
+ "exponential_decay_length_penalty": None,
1142
+ "suppress_tokens": None,
1143
+ "begin_suppress_tokens": None,
1144
+ # Deprecated arguments (moved to the Hub). TODO joao, manuel: remove in v4.62.0
1145
+ "num_beam_groups": 1,
1146
+ "diversity_penalty": 0.0,
1147
+ }
1148
+
1149
+ def _get_non_default_generation_parameters(self) -> dict[str, Any]:
1150
+ """
1151
+ Gets the non-default generation parameters on the PretrainedConfig instance
1152
+ """
1153
+ non_default_generation_parameters = {}
1154
+ decoder_attribute_name = None
1155
+
1156
+ # Composite models don't have a default config, use their decoder config as a fallback for default values
1157
+ # If no known pattern is matched, then `default_config = None` -> check against the global generation defaults
1158
+ try:
1159
+ default_config = self.__class__()
1160
+ except ValueError:
1161
+ decoder_config = self.get_text_config(decoder=True)
1162
+ if decoder_config is not self:
1163
+ default_config = decoder_config.__class__()
1164
+ else:
1165
+ default_config = None
1166
+
1167
+ # If it is a composite model, we want to check the subconfig that will be used for generation
1168
+ self_decoder_config = self if decoder_attribute_name is None else getattr(self, decoder_attribute_name)
1169
+
1170
+ for parameter_name, default_global_value in self._get_global_generation_defaults().items():
1171
+ if hasattr(self_decoder_config, parameter_name):
1172
+ is_default_in_config = is_default_generation_value = None
1173
+ parameter_value = getattr(self_decoder_config, parameter_name)
1174
+ # Three cases in which is okay for the model config to hold generation config parameters:
1175
+ # 1. The parameter is set to `None`, effectively delegating its value to the generation config
1176
+ if parameter_value is None:
1177
+ continue
1178
+ # 2. If we have a default config, then the instance should hold the same generation defaults
1179
+ if default_config is not None:
1180
+ is_default_in_config = parameter_value == getattr(default_config, parameter_name)
1181
+ # 3. if we don't have a default config, then the instance should hold the global generation defaults
1182
+ else:
1183
+ is_default_generation_value = parameter_value == default_global_value
1184
+
1185
+ is_non_default = (is_default_in_config is False) or (
1186
+ is_default_in_config is None and is_default_generation_value is False
1187
+ )
1188
+ if is_non_default:
1189
+ non_default_generation_parameters[parameter_name] = getattr(self_decoder_config, parameter_name)
1190
+
1191
+ return non_default_generation_parameters
1192
+
1193
+ def get_text_config(self, decoder=None, encoder=None) -> "PretrainedConfig":
1194
+ """
1195
+ Returns the text config related to the text input (encoder) or text output (decoder) of the model. The
1196
+ `decoder` and `encoder` input arguments can be used to specify which end of the model we are interested in,
1197
+ which is useful on models that have both text input and output modalities.
1198
+
1199
+ There are three possible outcomes of using this method:
1200
+ 1. On most models, it returns the original config instance itself.
1201
+ 2. On newer (2024+) composite models, it returns the text section of the config, which is nested under a set
1202
+ of valid names.
1203
+ 3. On older (2023-) composite models, it discards decoder-only parameters when `encoder=True` and vice-versa.
1204
+
1205
+ Args:
1206
+ decoder (`Optional[bool]`, *optional*):
1207
+ If set to `True`, then only search for decoder config names.
1208
+ encoder (`Optional[bool]`, *optional*):
1209
+ If set to `True`, then only search for encoder config names.
1210
+ """
1211
+ return_both = decoder == encoder # both unset or both set -> search all possible names
1212
+
1213
+ decoder_possible_text_config_names = ("decoder", "generator", "text_config")
1214
+ encoder_possible_text_config_names = ("text_encoder",)
1215
+ if return_both:
1216
+ possible_text_config_names = encoder_possible_text_config_names + decoder_possible_text_config_names
1217
+ elif decoder:
1218
+ possible_text_config_names = decoder_possible_text_config_names
1219
+ else:
1220
+ possible_text_config_names = encoder_possible_text_config_names
1221
+
1222
+ valid_text_config_names = []
1223
+ for text_config_name in possible_text_config_names:
1224
+ if hasattr(self, text_config_name):
1225
+ text_config = getattr(self, text_config_name, None)
1226
+ if text_config is not None:
1227
+ valid_text_config_names += [text_config_name]
1228
+
1229
+ if len(valid_text_config_names) > 1:
1230
+ raise ValueError(
1231
+ f"Multiple valid text configs were found in the model config: {valid_text_config_names}. In this "
1232
+ "case, using `get_text_config()` would be ambiguous. Please specify the desired text config directly, "
1233
+ "e.g. `text_config = config.sub_config_name`"
1234
+ )
1235
+ elif len(valid_text_config_names) == 1:
1236
+ config_to_return = getattr(self, valid_text_config_names[0])
1237
+ else:
1238
+ config_to_return = self
1239
+
1240
+ # handle legacy models with flat config structure, when we only want one of the configs
1241
+ if not return_both and len(valid_text_config_names) == 0 and config_to_return.is_encoder_decoder:
1242
+ config_to_return = copy.deepcopy(config_to_return)
1243
+ prefix_to_discard = "encoder" if decoder else "decoder"
1244
+ prefix_to_keep = "decoder" if decoder else "encoder"
1245
+ for key in config_to_return.to_dict():
1246
+ # NOTE: We don't want to discard the key if it is mapped from a different attribute name at read time
1247
+ if key.startswith(prefix_to_discard) and key not in config_to_return.attribute_map.values():
1248
+ delattr(config_to_return, key)
1249
+ if key.startswith(prefix_to_keep):
1250
+ # [encoder/decoder]_layers -> num_hidden_layers
1251
+ if key == prefix_to_keep + "_layers":
1252
+ new_key = "num_hidden_layers"
1253
+ # [encoder/decoder]_attention_heads -> num_attention_heads
1254
+ elif key == prefix_to_keep + "_attention_heads":
1255
+ new_key = "num_attention_heads"
1256
+ # e.g. encoder_hidden_act -> hidden_act
1257
+ else:
1258
+ new_key = key[len(prefix_to_keep) + 1 :]
1259
+
1260
+ # Does the class map the new key into a different attribute name at read time? if so, let's write
1261
+ # into that attribute instead
1262
+ if new_key in config_to_return.attribute_map:
1263
+ new_key = config_to_return.attribute_map[new_key]
1264
+
1265
+ value = getattr(config_to_return, key)
1266
+ delattr(config_to_return, key)
1267
+ setattr(config_to_return, new_key, value)
1268
+
1269
+ return config_to_return
1270
+
1271
+ @classmethod
1272
+ def from_text_vision_configs(cls, text_config, vision_config, **kwargs):
1273
+ r"""
1274
+ Instantiate a model config (or a derived class) from text model configuration and vision model
1275
+ configuration.
1276
+
1277
+ Returns:
1278
+ [`PreTrainedConfig`]: An instance of a configuration object
1279
+ """
1280
+
1281
+ warnings.warn(
1282
+ "The `from_text_vision_configs` method is deprecated and will be removed in v4.60 of Transformers. Please instantiate "
1283
+ "the config class directly with `MyConfig(text_config=text_config, vision_config=vision_config, **kwargs)` instead.",
1284
+ FutureWarning,
1285
+ )
1286
+
1287
+ return cls(text_config=text_config.to_dict(), vision_config=vision_config.to_dict(), **kwargs)
1288
+
1289
+ @classmethod
1290
+ def from_text_audio_configs(cls, text_config, audio_config, **kwargs):
1291
+ r"""
1292
+ Instantiate a model config (or a derived class) from text model configuration and audio model
1293
+ configuration.
1294
+
1295
+ Returns:
1296
+ [`PreTrainedConfig`]: An instance of a configuration object
1297
+ """
1298
+
1299
+ warnings.warn(
1300
+ "The `from_text_audio_configs` method is deprecated and will be removed in v4.60 of Transformers. Please instantiate "
1301
+ "the config class directly with `MyConfig(text_config=text_config, audio_config=audio_config, **kwargs)` instead.",
1302
+ FutureWarning,
1303
+ )
1304
+
1305
+ return cls(text_config=text_config.to_dict(), audio_config=audio_config.to_dict(), **kwargs)
1306
+
1307
+
1308
+ def get_configuration_file(configuration_files: list[str]) -> str:
1309
+ """
1310
+ Get the configuration file to use for this version of transformers.
1311
+
1312
+ Args:
1313
+ configuration_files (`list[str]`): The list of available configuration files.
1314
+
1315
+ Returns:
1316
+ `str`: The configuration file to use.
1317
+ """
1318
+ configuration_files_map = {}
1319
+ for file_name in configuration_files:
1320
+ if file_name.startswith("config.") and file_name.endswith(".json") and file_name != "config.json":
1321
+ v = file_name.removeprefix("config.").removesuffix(".json")
1322
+ configuration_files_map[v] = file_name
1323
+ available_versions = sorted(configuration_files_map.keys())
1324
+
1325
+ # Defaults to FULL_CONFIGURATION_FILE and then try to look at some newer versions.
1326
+ configuration_file = CONFIG_NAME
1327
+ transformers_version = version.parse(__version__)
1328
+ for v in available_versions:
1329
+ if version.parse(v) <= transformers_version:
1330
+ configuration_file = configuration_files_map[v]
1331
+ else:
1332
+ # No point going further since the versions are sorted.
1333
+ break
1334
+
1335
+ return configuration_file
1336
+
1337
+
1338
+ def recursive_diff_dict(dict_a, dict_b, config_obj=None):
1339
+ """
1340
+ Helper function to recursively take the diff between two nested dictionaries. The resulting diff only contains the
1341
+ values from `dict_a` that are different from values in `dict_b`.
1342
+
1343
+ dict_b : the default config dictionary. We want to remove values that are in this one
1344
+ """
1345
+ diff = {}
1346
+ default = config_obj.__class__().to_dict() if config_obj is not None else {}
1347
+ for key, value in dict_a.items():
1348
+ obj_value = getattr(config_obj, str(key), None)
1349
+ if isinstance(obj_value, PretrainedConfig) and key in dict_b and isinstance(dict_b[key], dict):
1350
+ diff_value = recursive_diff_dict(value, dict_b[key], config_obj=obj_value)
1351
+ diff[key] = diff_value
1352
+ elif key not in dict_b or (value != default[key]):
1353
+ diff[key] = value
1354
+ return diff
1355
+
1356
+
1357
+ PretrainedConfig.push_to_hub = copy_func(PretrainedConfig.push_to_hub)
1358
+ if PretrainedConfig.push_to_hub.__doc__ is not None:
1359
+ PretrainedConfig.push_to_hub.__doc__ = PretrainedConfig.push_to_hub.__doc__.format(
1360
+ object="config", object_class="AutoConfig", object_files="configuration file"
1361
+ )
1362
+
1363
+
1364
+ ALLOWED_LAYER_TYPES = (
1365
+ "full_attention",
1366
+ "sliding_attention",
1367
+ "chunked_attention",
1368
+ "linear_attention", # used in minimax
1369
+ )
1370
+
1371
+
1372
+ def layer_type_validation(layer_types: list[str], num_hidden_layers: Optional[int] = None):
1373
+ """Check that `layer_types` is correctly defined."""
1374
+ if not all(layer_type in ALLOWED_LAYER_TYPES for layer_type in layer_types):
1375
+ raise ValueError(f"The `layer_types` entries must be in {ALLOWED_LAYER_TYPES}")
1376
+ if num_hidden_layers is not None and num_hidden_layers != len(layer_types):
1377
+ raise ValueError(
1378
+ f"`num_hidden_layers` ({num_hidden_layers}) must be equal to the number of layer types "
1379
+ f"({len(layer_types)})"
1380
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_graph_to_onnx.py ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import warnings
16
+ from argparse import ArgumentParser
17
+ from os import listdir, makedirs
18
+ from pathlib import Path
19
+ from typing import Optional
20
+
21
+ from packaging.version import Version, parse
22
+
23
+ from transformers.pipelines import Pipeline, pipeline
24
+ from transformers.tokenization_utils import BatchEncoding
25
+ from transformers.utils import ModelOutput, is_tf_available, is_torch_available
26
+
27
+
28
+ # This is the minimal required version to
29
+ # support some ONNX Runtime features
30
+ ORT_QUANTIZE_MINIMUM_VERSION = parse("1.4.0")
31
+
32
+
33
+ SUPPORTED_PIPELINES = [
34
+ "feature-extraction",
35
+ "ner",
36
+ "sentiment-analysis",
37
+ "fill-mask",
38
+ "question-answering",
39
+ "text-generation",
40
+ "translation_en_to_fr",
41
+ "translation_en_to_de",
42
+ "translation_en_to_ro",
43
+ ]
44
+
45
+
46
+ class OnnxConverterArgumentParser(ArgumentParser):
47
+ """
48
+ Wraps all the script arguments supported to export transformers models to ONNX IR
49
+ """
50
+
51
+ def __init__(self):
52
+ super().__init__("ONNX Converter")
53
+
54
+ self.add_argument(
55
+ "--pipeline",
56
+ type=str,
57
+ choices=SUPPORTED_PIPELINES,
58
+ default="feature-extraction",
59
+ )
60
+ self.add_argument(
61
+ "--model",
62
+ type=str,
63
+ required=True,
64
+ help="Model's id or path (ex: google-bert/bert-base-cased)",
65
+ )
66
+ self.add_argument("--tokenizer", type=str, help="Tokenizer's id or path (ex: google-bert/bert-base-cased)")
67
+ self.add_argument(
68
+ "--framework",
69
+ type=str,
70
+ choices=["pt", "tf"],
71
+ help="Framework for loading the model",
72
+ )
73
+ self.add_argument("--opset", type=int, default=11, help="ONNX opset to use")
74
+ self.add_argument(
75
+ "--check-loading",
76
+ action="store_true",
77
+ help="Check ONNX is able to load the model",
78
+ )
79
+ self.add_argument(
80
+ "--use-external-format",
81
+ action="store_true",
82
+ help="Allow exporting model >= than 2Gb",
83
+ )
84
+ self.add_argument(
85
+ "--quantize",
86
+ action="store_true",
87
+ help="Quantize the neural network to be run with int8",
88
+ )
89
+ self.add_argument("output")
90
+
91
+
92
+ def generate_identified_filename(filename: Path, identifier: str) -> Path:
93
+ """
94
+ Append a string-identifier at the end (before the extension, if any) to the provided filepath
95
+
96
+ Args:
97
+ filename: pathlib.Path The actual path object we would like to add an identifier suffix
98
+ identifier: The suffix to add
99
+
100
+ Returns: String with concatenated identifier at the end of the filename
101
+ """
102
+ return filename.parent.joinpath(filename.stem + identifier).with_suffix(filename.suffix)
103
+
104
+
105
+ def check_onnxruntime_requirements(minimum_version: Version):
106
+ """
107
+ Check onnxruntime is installed and if the installed version match is recent enough
108
+
109
+ Raises:
110
+ ImportError: If onnxruntime is not installed or too old version is found
111
+ """
112
+ try:
113
+ import onnxruntime
114
+
115
+ # Parse the version of the installed onnxruntime
116
+ ort_version = parse(onnxruntime.__version__)
117
+
118
+ # We require 1.4.0 minimum
119
+ if ort_version < ORT_QUANTIZE_MINIMUM_VERSION:
120
+ raise ImportError(
121
+ f"We found an older version of onnxruntime ({onnxruntime.__version__}) "
122
+ f"but we require onnxruntime to be >= {minimum_version} to enable all the conversions options.\n"
123
+ "Please update onnxruntime by running `pip install --upgrade onnxruntime`"
124
+ )
125
+
126
+ except ImportError:
127
+ raise ImportError(
128
+ "onnxruntime doesn't seem to be currently installed. "
129
+ "Please install the onnxruntime by running `pip install onnxruntime`"
130
+ " and relaunch the conversion."
131
+ )
132
+
133
+
134
+ def ensure_valid_input(model, tokens, input_names):
135
+ """
136
+ Ensure inputs are presented in the correct order, without any Non
137
+
138
+ Args:
139
+ model: The model used to forward the input data
140
+ tokens: BatchEncoding holding the input data
141
+ input_names: The name of the inputs
142
+
143
+ Returns: Tuple
144
+
145
+ """
146
+ print("Ensuring inputs are in correct order")
147
+
148
+ model_args_name = model.forward.__code__.co_varnames
149
+ model_args, ordered_input_names = [], []
150
+ for arg_name in model_args_name[1:]: # start at index 1 to skip "self" argument
151
+ if arg_name in input_names:
152
+ ordered_input_names.append(arg_name)
153
+ model_args.append(tokens[arg_name])
154
+ else:
155
+ print(f"{arg_name} is not present in the generated input list.")
156
+ break
157
+
158
+ print(f"Generated inputs order: {ordered_input_names}")
159
+ return ordered_input_names, tuple(model_args)
160
+
161
+
162
+ def infer_shapes(nlp: Pipeline, framework: str) -> tuple[list[str], list[str], dict, BatchEncoding]:
163
+ """
164
+ Attempt to infer the static vs dynamic axes for each input and output tensors for a specific model
165
+
166
+ Args:
167
+ nlp: The pipeline object holding the model to be exported
168
+ framework: The framework identifier to dispatch to the correct inference scheme (pt/tf)
169
+
170
+ Returns:
171
+
172
+ - List of the inferred input variable names
173
+ - List of the inferred output variable names
174
+ - Dictionary with input/output variables names as key and shape tensor as value
175
+ - a BatchEncoding reference which was used to infer all the above information
176
+ """
177
+
178
+ def build_shape_dict(name: str, tensor, is_input: bool, seq_len: int):
179
+ if isinstance(tensor, (tuple, list)):
180
+ return [build_shape_dict(name, t, is_input, seq_len) for t in tensor]
181
+
182
+ else:
183
+ # Let's assume batch is the first axis with only 1 element (~~ might not be always true ...)
184
+ axes = {[axis for axis, numel in enumerate(tensor.shape) if numel == 1][0]: "batch"}
185
+ if is_input:
186
+ if len(tensor.shape) == 2:
187
+ axes[1] = "sequence"
188
+ else:
189
+ raise ValueError(f"Unable to infer tensor axes ({len(tensor.shape)})")
190
+ else:
191
+ seq_axes = [dim for dim, shape in enumerate(tensor.shape) if shape == seq_len]
192
+ axes.update(dict.fromkeys(seq_axes, "sequence"))
193
+
194
+ print(f"Found {'input' if is_input else 'output'} {name} with shape: {axes}")
195
+ return axes
196
+
197
+ tokens = nlp.tokenizer("This is a sample output", return_tensors=framework)
198
+ seq_len = tokens.input_ids.shape[-1]
199
+ outputs = nlp.model(**tokens) if framework == "pt" else nlp.model(tokens)
200
+ if isinstance(outputs, ModelOutput):
201
+ outputs = outputs.to_tuple()
202
+ if not isinstance(outputs, (list, tuple)):
203
+ outputs = (outputs,)
204
+
205
+ # Generate input names & axes
206
+ input_vars = list(tokens.keys())
207
+ input_dynamic_axes = {k: build_shape_dict(k, v, True, seq_len) for k, v in tokens.items()}
208
+
209
+ # flatten potentially grouped outputs (past for gpt2, attentions)
210
+ outputs_flat = []
211
+ for output in outputs:
212
+ if isinstance(output, (tuple, list)):
213
+ outputs_flat.extend(output)
214
+ else:
215
+ outputs_flat.append(output)
216
+
217
+ # Generate output names & axes
218
+ output_names = [f"output_{i}" for i in range(len(outputs_flat))]
219
+ output_dynamic_axes = {k: build_shape_dict(k, v, False, seq_len) for k, v in zip(output_names, outputs_flat)}
220
+
221
+ # Create the aggregated axes representation
222
+ dynamic_axes = dict(input_dynamic_axes, **output_dynamic_axes)
223
+ return input_vars, output_names, dynamic_axes, tokens
224
+
225
+
226
+ def load_graph_from_args(
227
+ pipeline_name: str, framework: str, model: str, tokenizer: Optional[str] = None, **models_kwargs
228
+ ) -> Pipeline:
229
+ """
230
+ Convert the set of arguments provided through the CLI to an actual pipeline reference (tokenizer + model
231
+
232
+ Args:
233
+ pipeline_name: The kind of pipeline to use (ner, question-answering, etc.)
234
+ framework: The actual model to convert the pipeline from ("pt" or "tf")
235
+ model: The model name which will be loaded by the pipeline
236
+ tokenizer: The tokenizer name which will be loaded by the pipeline, default to the model's value
237
+
238
+ Returns: Pipeline object
239
+
240
+ """
241
+ # If no tokenizer provided
242
+ if tokenizer is None:
243
+ tokenizer = model
244
+
245
+ # Check the wanted framework is available
246
+ if framework == "pt" and not is_torch_available():
247
+ raise Exception("Cannot convert because PyTorch is not installed. Please install torch first.")
248
+ if framework == "tf" and not is_tf_available():
249
+ raise Exception("Cannot convert because TF is not installed. Please install tensorflow first.")
250
+
251
+ print(f"Loading pipeline (model: {model}, tokenizer: {tokenizer})")
252
+
253
+ # Allocate tokenizer and model
254
+ return pipeline(pipeline_name, model=model, tokenizer=tokenizer, framework=framework, model_kwargs=models_kwargs)
255
+
256
+
257
+ def convert_pytorch(nlp: Pipeline, opset: int, output: Path, use_external_format: bool):
258
+ """
259
+ Export a PyTorch backed pipeline to ONNX Intermediate Representation (IR
260
+
261
+ Args:
262
+ nlp: The pipeline to be exported
263
+ opset: The actual version of the ONNX operator set to use
264
+ output: Path where will be stored the generated ONNX model
265
+ use_external_format: Split the model definition from its parameters to allow model bigger than 2GB
266
+
267
+ Returns:
268
+
269
+ """
270
+ if not is_torch_available():
271
+ raise Exception("Cannot convert because PyTorch is not installed. Please install torch first.")
272
+
273
+ import torch
274
+ from torch.onnx import export
275
+
276
+ print(f"Using framework PyTorch: {torch.__version__}")
277
+
278
+ with torch.no_grad():
279
+ input_names, output_names, dynamic_axes, tokens = infer_shapes(nlp, "pt")
280
+ ordered_input_names, model_args = ensure_valid_input(nlp.model, tokens, input_names)
281
+
282
+ export(
283
+ nlp.model,
284
+ model_args,
285
+ f=output.as_posix(),
286
+ input_names=ordered_input_names,
287
+ output_names=output_names,
288
+ dynamic_axes=dynamic_axes,
289
+ do_constant_folding=True,
290
+ opset_version=opset,
291
+ )
292
+
293
+
294
+ def convert_tensorflow(nlp: Pipeline, opset: int, output: Path):
295
+ """
296
+ Export a TensorFlow backed pipeline to ONNX Intermediate Representation (IR)
297
+
298
+ Args:
299
+ nlp: The pipeline to be exported
300
+ opset: The actual version of the ONNX operator set to use
301
+ output: Path where will be stored the generated ONNX model
302
+
303
+ Notes: TensorFlow cannot export model bigger than 2GB due to internal constraint from TensorFlow
304
+
305
+ """
306
+ if not is_tf_available():
307
+ raise Exception("Cannot convert because TF is not installed. Please install tensorflow first.")
308
+
309
+ print("/!\\ Please note TensorFlow doesn't support exporting model > 2Gb /!\\")
310
+
311
+ try:
312
+ import tensorflow as tf
313
+ import tf2onnx
314
+ from tf2onnx import __version__ as t2ov
315
+
316
+ print(f"Using framework TensorFlow: {tf.version.VERSION}, tf2onnx: {t2ov}")
317
+
318
+ # Build
319
+ input_names, output_names, dynamic_axes, tokens = infer_shapes(nlp, "tf")
320
+
321
+ # Forward
322
+ nlp.model.predict(tokens.data)
323
+ input_signature = [tf.TensorSpec.from_tensor(tensor, name=key) for key, tensor in tokens.items()]
324
+ model_proto, _ = tf2onnx.convert.from_keras(
325
+ nlp.model, input_signature, opset=opset, output_path=output.as_posix()
326
+ )
327
+
328
+ except ImportError as e:
329
+ raise Exception(
330
+ f"Cannot import {e.name} required to convert TF model to ONNX. Please install {e.name} first. {e}"
331
+ )
332
+
333
+
334
+ def convert(
335
+ framework: str,
336
+ model: str,
337
+ output: Path,
338
+ opset: int,
339
+ tokenizer: Optional[str] = None,
340
+ use_external_format: bool = False,
341
+ pipeline_name: str = "feature-extraction",
342
+ **model_kwargs,
343
+ ):
344
+ """
345
+ Convert the pipeline object to the ONNX Intermediate Representation (IR) format
346
+
347
+ Args:
348
+ framework: The framework the pipeline is backed by ("pt" or "tf")
349
+ model: The name of the model to load for the pipeline
350
+ output: The path where the ONNX graph will be stored
351
+ opset: The actual version of the ONNX operator set to use
352
+ tokenizer: The name of the model to load for the pipeline, default to the model's name if not provided
353
+ use_external_format:
354
+ Split the model definition from its parameters to allow model bigger than 2GB (PyTorch only)
355
+ pipeline_name: The kind of pipeline to instantiate (ner, question-answering, etc.)
356
+ model_kwargs: Keyword arguments to be forwarded to the model constructor
357
+
358
+ Returns:
359
+
360
+ """
361
+ warnings.warn(
362
+ "The `transformers.convert_graph_to_onnx` package is deprecated and will be removed in version 5 of"
363
+ " Transformers",
364
+ FutureWarning,
365
+ )
366
+ print(f"ONNX opset version set to: {opset}")
367
+
368
+ # Load the pipeline
369
+ nlp = load_graph_from_args(pipeline_name, framework, model, tokenizer, **model_kwargs)
370
+
371
+ if not output.parent.exists():
372
+ print(f"Creating folder {output.parent}")
373
+ makedirs(output.parent.as_posix())
374
+ elif len(listdir(output.parent.as_posix())) > 0:
375
+ raise Exception(f"Folder {output.parent.as_posix()} is not empty, aborting conversion")
376
+
377
+ # Export the graph
378
+ if framework == "pt":
379
+ convert_pytorch(nlp, opset, output, use_external_format)
380
+ else:
381
+ convert_tensorflow(nlp, opset, output)
382
+
383
+
384
+ def optimize(onnx_model_path: Path) -> Path:
385
+ """
386
+ Load the model at the specified path and let onnxruntime look at transformations on the graph to enable all the
387
+ optimizations possible
388
+
389
+ Args:
390
+ onnx_model_path: filepath where the model binary description is stored
391
+
392
+ Returns: Path where the optimized model binary description has been saved
393
+
394
+ """
395
+ from onnxruntime import InferenceSession, SessionOptions
396
+
397
+ # Generate model name with suffix "optimized"
398
+ opt_model_path = generate_identified_filename(onnx_model_path, "-optimized")
399
+ sess_option = SessionOptions()
400
+ sess_option.optimized_model_filepath = opt_model_path.as_posix()
401
+ _ = InferenceSession(onnx_model_path.as_posix(), sess_option)
402
+
403
+ print(f"Optimized model has been written at {opt_model_path}: \N{HEAVY CHECK MARK}")
404
+ print("/!\\ Optimized model contains hardware specific operators which might not be portable. /!\\")
405
+
406
+ return opt_model_path
407
+
408
+
409
+ def quantize(onnx_model_path: Path) -> Path:
410
+ """
411
+ Quantize the weights of the model from float32 to in8 to allow very efficient inference on modern CPU
412
+
413
+ Args:
414
+ onnx_model_path: Path to location the exported ONNX model is stored
415
+
416
+ Returns: The Path generated for the quantized
417
+ """
418
+ import onnx
419
+ import onnxruntime
420
+ from onnx.onnx_pb import ModelProto
421
+ from onnxruntime.quantization import QuantizationMode
422
+ from onnxruntime.quantization.onnx_quantizer import ONNXQuantizer
423
+ from onnxruntime.quantization.registry import IntegerOpsRegistry
424
+
425
+ # Load the ONNX model
426
+ onnx_model = onnx.load(onnx_model_path.as_posix())
427
+
428
+ if parse(onnx.__version__) < parse("1.5.0"):
429
+ print(
430
+ "Models larger than 2GB will fail to quantize due to protobuf constraint.\n"
431
+ "Please upgrade to onnxruntime >= 1.5.0."
432
+ )
433
+
434
+ # Copy it
435
+ copy_model = ModelProto()
436
+ copy_model.CopyFrom(onnx_model)
437
+
438
+ # Construct quantizer
439
+ # onnxruntime renamed input_qType to activation_qType in v1.13.1, so we
440
+ # check the onnxruntime version to ensure backward compatibility.
441
+ # See also: https://github.com/microsoft/onnxruntime/pull/12873
442
+ if parse(onnxruntime.__version__) < parse("1.13.1"):
443
+ quantizer = ONNXQuantizer(
444
+ model=copy_model,
445
+ per_channel=False,
446
+ reduce_range=False,
447
+ mode=QuantizationMode.IntegerOps,
448
+ static=False,
449
+ weight_qType=True,
450
+ input_qType=False,
451
+ tensors_range=None,
452
+ nodes_to_quantize=None,
453
+ nodes_to_exclude=None,
454
+ op_types_to_quantize=list(IntegerOpsRegistry),
455
+ )
456
+ else:
457
+ quantizer = ONNXQuantizer(
458
+ model=copy_model,
459
+ per_channel=False,
460
+ reduce_range=False,
461
+ mode=QuantizationMode.IntegerOps,
462
+ static=False,
463
+ weight_qType=True,
464
+ activation_qType=False,
465
+ tensors_range=None,
466
+ nodes_to_quantize=None,
467
+ nodes_to_exclude=None,
468
+ op_types_to_quantize=list(IntegerOpsRegistry),
469
+ )
470
+
471
+ # Quantize and export
472
+ quantizer.quantize_model()
473
+
474
+ # Append "-quantized" at the end of the model's name
475
+ quantized_model_path = generate_identified_filename(onnx_model_path, "-quantized")
476
+
477
+ # Save model
478
+ print(f"Quantized model has been written at {quantized_model_path}: \N{HEAVY CHECK MARK}")
479
+ onnx.save_model(quantizer.model.model, quantized_model_path.as_posix())
480
+
481
+ return quantized_model_path
482
+
483
+
484
+ def verify(path: Path):
485
+ from onnxruntime import InferenceSession, SessionOptions
486
+ from onnxruntime.capi.onnxruntime_pybind11_state import RuntimeException
487
+
488
+ print(f"Checking ONNX model loading from: {path} ...")
489
+ try:
490
+ onnx_options = SessionOptions()
491
+ _ = InferenceSession(path.as_posix(), onnx_options, providers=["CPUExecutionProvider"])
492
+ print(f"Model {path} correctly loaded: \N{HEAVY CHECK MARK}")
493
+ except RuntimeException as re:
494
+ print(f"Error while loading the model {re}: \N{HEAVY BALLOT X}")
495
+
496
+
497
+ if __name__ == "__main__":
498
+ parser = OnnxConverterArgumentParser()
499
+ args = parser.parse_args()
500
+
501
+ # Make sure output is absolute path
502
+ args.output = Path(args.output).absolute()
503
+
504
+ try:
505
+ print("\n====== Converting model to ONNX ======")
506
+ # Convert
507
+ convert(
508
+ args.framework,
509
+ args.model,
510
+ args.output,
511
+ args.opset,
512
+ args.tokenizer,
513
+ args.use_external_format,
514
+ args.pipeline,
515
+ )
516
+
517
+ if args.quantize:
518
+ # Ensure requirements for quantization on onnxruntime is met
519
+ check_onnxruntime_requirements(ORT_QUANTIZE_MINIMUM_VERSION)
520
+
521
+ # onnxruntime optimizations doesn't provide the same level of performances on TensorFlow than PyTorch
522
+ if args.framework == "tf":
523
+ print(
524
+ "\t Using TensorFlow might not provide the same optimization level compared to PyTorch.\n"
525
+ "\t For TensorFlow users you can try optimizing the model directly through onnxruntime_tools.\n"
526
+ "\t For more information, please refer to the onnxruntime documentation:\n"
527
+ "\t\thttps://github.com/microsoft/onnxruntime/tree/master/onnxruntime/python/tools/transformers\n"
528
+ )
529
+
530
+ print("\n====== Optimizing ONNX model ======")
531
+
532
+ # Quantization works best when using the optimized version of the model
533
+ args.optimized_output = optimize(args.output)
534
+
535
+ # Do the quantization on the right graph
536
+ args.quantized_output = quantize(args.optimized_output)
537
+
538
+ # And verify
539
+ if args.check_loading:
540
+ print("\n====== Check exported ONNX model(s) ======")
541
+ verify(args.output)
542
+
543
+ if hasattr(args, "optimized_output"):
544
+ verify(args.optimized_output)
545
+
546
+ if hasattr(args, "quantized_output"):
547
+ verify(args.quantized_output)
548
+
549
+ except Exception as e:
550
+ print(f"Error while converting the model: {e}")
551
+ exit(1)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_slow_tokenizer.py ADDED
@@ -0,0 +1,1873 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2018 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Utilities to convert slow tokenizers in their fast tokenizers counterparts.
16
+
17
+ All the conversions are grouped here to gather SentencePiece dependencies outside of the fast tokenizers files and
18
+ allow to make our dependency on SentencePiece optional.
19
+ """
20
+
21
+ import warnings
22
+ from functools import lru_cache
23
+ from typing import Optional
24
+
25
+ from packaging import version
26
+ from tokenizers import AddedToken, Regex, Tokenizer, decoders, normalizers, pre_tokenizers, processors
27
+ from tokenizers.models import BPE, Unigram, WordPiece
28
+ from tqdm import tqdm
29
+
30
+ from .utils import is_protobuf_available, is_sentencepiece_available, logging, requires_backends
31
+ from .utils.import_utils import PROTOBUF_IMPORT_ERROR
32
+
33
+
34
+ logger = logging.get_logger(__name__)
35
+
36
+
37
+ def import_protobuf(error_message=""):
38
+ if is_sentencepiece_available():
39
+ from sentencepiece import sentencepiece_model_pb2
40
+
41
+ return sentencepiece_model_pb2
42
+ if is_protobuf_available():
43
+ import google.protobuf
44
+
45
+ if version.parse(google.protobuf.__version__) < version.parse("4.0.0"):
46
+ from transformers.utils import sentencepiece_model_pb2
47
+ else:
48
+ from transformers.utils import sentencepiece_model_pb2_new as sentencepiece_model_pb2
49
+ return sentencepiece_model_pb2
50
+ else:
51
+ raise ImportError(PROTOBUF_IMPORT_ERROR.format(error_message))
52
+
53
+
54
+ def _get_prepend_scheme(add_prefix_space: bool, original_tokenizer) -> str:
55
+ if add_prefix_space:
56
+ prepend_scheme = "always"
57
+ if not getattr(original_tokenizer, "legacy", True):
58
+ prepend_scheme = "first"
59
+ else:
60
+ prepend_scheme = "never"
61
+ return prepend_scheme
62
+
63
+
64
+ def generate_merges(vocab, vocab_scores):
65
+ reverse = vocab_scores is not None
66
+ vocab_scores = dict(vocab_scores) if reverse else vocab
67
+
68
+ merges = []
69
+ for merge, piece_score in vocab_scores.items():
70
+ local = []
71
+ for index in range(1, len(merge)):
72
+ piece_l, piece_r = merge[:index], merge[index:]
73
+ if piece_l in vocab and piece_r in vocab:
74
+ local.append((piece_l, piece_r, piece_score))
75
+ local = sorted(local, key=lambda x: (vocab[x[0]], vocab[x[1]]))
76
+ merges.extend(local)
77
+
78
+ merges = sorted(merges, key=lambda val: (val[2], len(val[0]), len(val[1])), reverse=reverse)
79
+ merges = [(val[0], val[1]) for val in merges]
80
+ return merges
81
+
82
+
83
+ class SentencePieceExtractor:
84
+ """
85
+ Extractor implementation for SentencePiece trained models. https://github.com/google/sentencepiece
86
+ """
87
+
88
+ def __init__(self, model: str):
89
+ requires_backends(self, "sentencepiece")
90
+ from sentencepiece import SentencePieceProcessor
91
+
92
+ self.sp = SentencePieceProcessor()
93
+ self.sp.Load(model)
94
+
95
+ def extract(self, vocab_scores=None) -> tuple[dict[str, int], list[tuple]]:
96
+ """
97
+ By default will return vocab and merges with respect to their order, by sending `vocab_scores` we're going to
98
+ order the merges with respect to the piece scores instead.
99
+ """
100
+ sp = self.sp
101
+ vocab = {sp.id_to_piece(index): index for index in range(sp.GetPieceSize())}
102
+
103
+ merges = generate_merges(vocab, vocab_scores)
104
+
105
+ return vocab, merges
106
+
107
+
108
+ class GemmaSentencePieceExtractor(SentencePieceExtractor):
109
+ def extract(self, vocab_scores=None) -> tuple[dict[str, int], list[tuple]]:
110
+ """
111
+ By default will return vocab and merges with respect to their order, by sending `vocab_scores` we're going to
112
+ order the merges with respect to the piece scores instead.
113
+ """
114
+ sp = self.sp
115
+ vocab = {sp.id_to_piece(index): index for index in range(sp.GetPieceSize())}
116
+
117
+ # If "\t" is missing in the vocab, we have to do this to support merges
118
+ # "<0x09>" is the bytefallback for `\t`
119
+ if "\t" not in vocab:
120
+ vocab["\t"] = vocab.get("<0x09>")
121
+ merges = generate_merges(vocab, vocab_scores)
122
+ return vocab, merges
123
+
124
+
125
+ def check_number_comma(piece: str) -> bool:
126
+ return len(piece) < 2 or piece[-1] != "," or not piece[-2].isdigit()
127
+
128
+
129
+ class Converter:
130
+ def __init__(self, original_tokenizer):
131
+ self.original_tokenizer = original_tokenizer
132
+
133
+ def converted(self) -> Tokenizer:
134
+ raise NotImplementedError()
135
+
136
+
137
+ class BertConverter(Converter):
138
+ def converted(self) -> Tokenizer:
139
+ vocab = self.original_tokenizer.vocab
140
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
141
+
142
+ tokenize_chinese_chars = False
143
+ strip_accents = False
144
+ do_lower_case = False
145
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
146
+ tokenize_chinese_chars = self.original_tokenizer.basic_tokenizer.tokenize_chinese_chars
147
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
148
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
149
+
150
+ tokenizer.normalizer = normalizers.BertNormalizer(
151
+ clean_text=True,
152
+ handle_chinese_chars=tokenize_chinese_chars,
153
+ strip_accents=strip_accents,
154
+ lowercase=do_lower_case,
155
+ )
156
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
157
+
158
+ cls = str(self.original_tokenizer.cls_token)
159
+ sep = str(self.original_tokenizer.sep_token)
160
+ cls_token_id = self.original_tokenizer.cls_token_id
161
+ sep_token_id = self.original_tokenizer.sep_token_id
162
+
163
+ tokenizer.post_processor = processors.TemplateProcessing(
164
+ single=f"{cls}:0 $A:0 {sep}:0",
165
+ pair=f"{cls}:0 $A:0 {sep}:0 $B:1 {sep}:1",
166
+ special_tokens=[
167
+ (cls, cls_token_id),
168
+ (sep, sep_token_id),
169
+ ],
170
+ )
171
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
172
+
173
+ return tokenizer
174
+
175
+
176
+ class SplinterConverter(Converter):
177
+ def converted(self) -> Tokenizer:
178
+ vocab = self.original_tokenizer.vocab
179
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
180
+
181
+ tokenize_chinese_chars = False
182
+ strip_accents = False
183
+ do_lower_case = False
184
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
185
+ tokenize_chinese_chars = self.original_tokenizer.basic_tokenizer.tokenize_chinese_chars
186
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
187
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
188
+
189
+ tokenizer.normalizer = normalizers.BertNormalizer(
190
+ clean_text=True,
191
+ handle_chinese_chars=tokenize_chinese_chars,
192
+ strip_accents=strip_accents,
193
+ lowercase=do_lower_case,
194
+ )
195
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
196
+
197
+ cls = str(self.original_tokenizer.cls_token)
198
+ sep = str(self.original_tokenizer.sep_token)
199
+ question = str(self.original_tokenizer.question_token)
200
+ dot = "."
201
+ cls_token_id = self.original_tokenizer.cls_token_id
202
+ sep_token_id = self.original_tokenizer.sep_token_id
203
+ question_token_id = self.original_tokenizer.question_token_id
204
+ dot_token_id = self.original_tokenizer.convert_tokens_to_ids(".")
205
+
206
+ if self.original_tokenizer.padding_side == "right":
207
+ pair = f"{cls}:0 $A:0 {question} {dot} {sep}:0 $B:1 {sep}:1"
208
+ else:
209
+ pair = f"{cls}:0 $A:0 {sep}:0 $B:1 {question} {dot} {sep}:1"
210
+
211
+ tokenizer.post_processor = processors.TemplateProcessing(
212
+ single=f"{cls}:0 $A:0 {sep}:0",
213
+ pair=pair,
214
+ special_tokens=[
215
+ (cls, cls_token_id),
216
+ (sep, sep_token_id),
217
+ (question, question_token_id),
218
+ (dot, dot_token_id),
219
+ ],
220
+ )
221
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
222
+
223
+ return tokenizer
224
+
225
+
226
+ class FunnelConverter(Converter):
227
+ def converted(self) -> Tokenizer:
228
+ vocab = self.original_tokenizer.vocab
229
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
230
+
231
+ tokenize_chinese_chars = False
232
+ strip_accents = False
233
+ do_lower_case = False
234
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
235
+ tokenize_chinese_chars = self.original_tokenizer.basic_tokenizer.tokenize_chinese_chars
236
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
237
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
238
+
239
+ tokenizer.normalizer = normalizers.BertNormalizer(
240
+ clean_text=True,
241
+ handle_chinese_chars=tokenize_chinese_chars,
242
+ strip_accents=strip_accents,
243
+ lowercase=do_lower_case,
244
+ )
245
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
246
+
247
+ cls = str(self.original_tokenizer.cls_token)
248
+ sep = str(self.original_tokenizer.sep_token)
249
+ cls_token_id = self.original_tokenizer.cls_token_id
250
+ sep_token_id = self.original_tokenizer.sep_token_id
251
+
252
+ tokenizer.post_processor = processors.TemplateProcessing(
253
+ single=f"{cls}:2 $A:0 {sep}:0", # token_type_id is 2 for Funnel transformer
254
+ pair=f"{cls}:2 $A:0 {sep}:0 $B:1 {sep}:1",
255
+ special_tokens=[
256
+ (cls, cls_token_id),
257
+ (sep, sep_token_id),
258
+ ],
259
+ )
260
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
261
+
262
+ return tokenizer
263
+
264
+
265
+ class MPNetConverter(Converter):
266
+ def converted(self) -> Tokenizer:
267
+ vocab = self.original_tokenizer.vocab
268
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
269
+
270
+ tokenize_chinese_chars = False
271
+ strip_accents = False
272
+ do_lower_case = False
273
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
274
+ tokenize_chinese_chars = self.original_tokenizer.basic_tokenizer.tokenize_chinese_chars
275
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
276
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
277
+
278
+ tokenizer.normalizer = normalizers.BertNormalizer(
279
+ clean_text=True,
280
+ handle_chinese_chars=tokenize_chinese_chars,
281
+ strip_accents=strip_accents,
282
+ lowercase=do_lower_case,
283
+ )
284
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
285
+
286
+ cls = str(self.original_tokenizer.cls_token)
287
+ sep = str(self.original_tokenizer.sep_token)
288
+ cls_token_id = self.original_tokenizer.cls_token_id
289
+ sep_token_id = self.original_tokenizer.sep_token_id
290
+
291
+ tokenizer.post_processor = processors.TemplateProcessing(
292
+ single=f"{cls}:0 $A:0 {sep}:0",
293
+ pair=f"{cls}:0 $A:0 {sep}:0 {sep}:0 $B:1 {sep}:1", # MPNet uses two [SEP] tokens
294
+ special_tokens=[
295
+ (cls, cls_token_id),
296
+ (sep, sep_token_id),
297
+ ],
298
+ )
299
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
300
+
301
+ return tokenizer
302
+
303
+
304
+ class OpenAIGPTConverter(Converter):
305
+ def converted(self) -> Tokenizer:
306
+ vocab = self.original_tokenizer.encoder
307
+ merges = list(self.original_tokenizer.bpe_ranks.keys())
308
+ unk_token = self.original_tokenizer.unk_token
309
+
310
+ tokenizer = Tokenizer(
311
+ BPE(
312
+ vocab=vocab,
313
+ merges=merges,
314
+ dropout=None,
315
+ unk_token=str(unk_token),
316
+ end_of_word_suffix="</w>",
317
+ fuse_unk=False,
318
+ )
319
+ )
320
+
321
+ if tokenizer.token_to_id(str(unk_token)) is not None:
322
+ tokenizer.add_special_tokens([str(unk_token)])
323
+
324
+ tokenizer.normalizer = normalizers.BertNormalizer(lowercase=True)
325
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
326
+ tokenizer.decoder = decoders.BPEDecoder(suffix="</w>")
327
+
328
+ return tokenizer
329
+
330
+
331
+ class GPT2Converter(Converter):
332
+ def converted(
333
+ self, vocab: Optional[dict[str, int]] = None, merges: Optional[list[tuple[str, str]]] = None
334
+ ) -> Tokenizer:
335
+ if not vocab:
336
+ vocab = self.original_tokenizer.encoder
337
+ if not merges:
338
+ merges = list(self.original_tokenizer.bpe_ranks)
339
+
340
+ tokenizer = Tokenizer(
341
+ BPE(
342
+ vocab=vocab,
343
+ merges=merges,
344
+ dropout=None,
345
+ continuing_subword_prefix="",
346
+ end_of_word_suffix="",
347
+ fuse_unk=False,
348
+ )
349
+ )
350
+
351
+ add_prefix_space = getattr(self.original_tokenizer, "add_prefix_space", False)
352
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=add_prefix_space)
353
+ tokenizer.decoder = decoders.ByteLevel()
354
+ if getattr(self.original_tokenizer, "add_bos_token", False):
355
+ bos = self.original_tokenizer.bos_token
356
+ bos_token_id = self.original_tokenizer.bos_token_id
357
+ tokenizer.post_processor = processors.TemplateProcessing(
358
+ single=f"{bos}:0 $A:0",
359
+ pair=f"{bos}:0 $A:0 $B:1",
360
+ special_tokens=[
361
+ (bos, bos_token_id),
362
+ ],
363
+ )
364
+ else:
365
+ # XXX trim_offsets=False actually means this post_processor doesn't
366
+ # really do anything.
367
+ tokenizer.post_processor = processors.ByteLevel(trim_offsets=False)
368
+ return tokenizer
369
+
370
+
371
+ class HerbertConverter(Converter):
372
+ def converted(self) -> Tokenizer:
373
+ tokenizer_info_str = "#version:"
374
+ token_suffix = "</w>"
375
+
376
+ vocab = self.original_tokenizer.encoder
377
+ merges = list(self.original_tokenizer.bpe_ranks.keys())
378
+ if tokenizer_info_str in merges[0][0]:
379
+ merges = merges[1:]
380
+
381
+ tokenizer = Tokenizer(
382
+ BPE(
383
+ vocab,
384
+ merges,
385
+ dropout=None,
386
+ unk_token=self.original_tokenizer.unk_token,
387
+ end_of_word_suffix=token_suffix,
388
+ )
389
+ )
390
+
391
+ tokenizer.normalizer = normalizers.BertNormalizer(lowercase=False, strip_accents=False)
392
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
393
+ tokenizer.decoder = decoders.BPEDecoder(suffix=token_suffix)
394
+ tokenizer.post_processor = processors.BertProcessing(
395
+ sep=(self.original_tokenizer.sep_token, self.original_tokenizer.sep_token_id),
396
+ cls=(self.original_tokenizer.cls_token, self.original_tokenizer.cls_token_id),
397
+ )
398
+
399
+ return tokenizer
400
+
401
+
402
+ class Qwen2Converter(Converter):
403
+ def converted(
404
+ self, vocab: Optional[dict[str, int]] = None, merges: Optional[list[tuple[str, str]]] = None
405
+ ) -> Tokenizer:
406
+ if not vocab:
407
+ vocab = self.original_tokenizer.encoder
408
+ if not merges:
409
+ merges = list(self.original_tokenizer.bpe_ranks.keys())
410
+
411
+ tokenizer = Tokenizer(
412
+ BPE(
413
+ vocab=vocab,
414
+ merges=merges,
415
+ dropout=None,
416
+ unk_token=None,
417
+ continuing_subword_prefix="",
418
+ end_of_word_suffix="",
419
+ fuse_unk=False,
420
+ byte_fallback=False,
421
+ )
422
+ )
423
+
424
+ tokenizer.normalizer = normalizers.NFC()
425
+
426
+ tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
427
+ [
428
+ pre_tokenizers.Split(
429
+ Regex(
430
+ r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+"""
431
+ ),
432
+ behavior="isolated",
433
+ invert=False,
434
+ ),
435
+ pre_tokenizers.ByteLevel(
436
+ add_prefix_space=getattr(self.original_tokenizer, "add_prefix_space", False),
437
+ use_regex=False,
438
+ ),
439
+ ]
440
+ )
441
+
442
+ tokenizer.decoder = decoders.ByteLevel()
443
+ tokenizer.post_processor = processors.ByteLevel(trim_offsets=False)
444
+
445
+ return tokenizer
446
+
447
+
448
+ class RobertaConverter(Converter):
449
+ def converted(self) -> Tokenizer:
450
+ ot = self.original_tokenizer
451
+ vocab = ot.encoder
452
+ merges = list(ot.bpe_ranks.keys())
453
+
454
+ tokenizer = Tokenizer(
455
+ BPE(
456
+ vocab=vocab,
457
+ merges=merges,
458
+ dropout=None,
459
+ continuing_subword_prefix="",
460
+ end_of_word_suffix="",
461
+ fuse_unk=False,
462
+ )
463
+ )
464
+
465
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=ot.add_prefix_space)
466
+ tokenizer.decoder = decoders.ByteLevel()
467
+ tokenizer.post_processor = processors.RobertaProcessing(
468
+ sep=(ot.sep_token, ot.sep_token_id),
469
+ cls=(ot.cls_token, ot.cls_token_id),
470
+ add_prefix_space=ot.add_prefix_space,
471
+ trim_offsets=True, # True by default on Roberta (historical)
472
+ )
473
+
474
+ return tokenizer
475
+
476
+
477
+ class RoFormerConverter(Converter):
478
+ def converted(self) -> Tokenizer:
479
+ from .models.roformer.tokenization_utils import JiebaPreTokenizer
480
+
481
+ vocab = self.original_tokenizer.vocab
482
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
483
+
484
+ strip_accents = False
485
+ do_lower_case = False
486
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
487
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
488
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
489
+
490
+ tokenizer.normalizer = normalizers.BertNormalizer(
491
+ clean_text=True,
492
+ handle_chinese_chars=False,
493
+ strip_accents=strip_accents,
494
+ lowercase=do_lower_case,
495
+ )
496
+ tokenizer.pre_tokenizer = pre_tokenizers.PreTokenizer.custom(JiebaPreTokenizer(vocab))
497
+
498
+ cls = str(self.original_tokenizer.cls_token)
499
+ sep = str(self.original_tokenizer.sep_token)
500
+ cls_token_id = self.original_tokenizer.cls_token_id
501
+ sep_token_id = self.original_tokenizer.sep_token_id
502
+
503
+ tokenizer.post_processor = processors.TemplateProcessing(
504
+ single=f"{cls}:0 $A:0 {sep}:0",
505
+ pair=f"{cls}:0 $A:0 {sep}:0 $B:1 {sep}:1",
506
+ special_tokens=[
507
+ (cls, cls_token_id),
508
+ (sep, sep_token_id),
509
+ ],
510
+ )
511
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
512
+
513
+ return tokenizer
514
+
515
+
516
+ class DebertaConverter(Converter):
517
+ def converted(self) -> Tokenizer:
518
+ ot = self.original_tokenizer
519
+ vocab = ot.encoder
520
+ merges = list(ot.bpe_ranks.keys())
521
+
522
+ tokenizer = Tokenizer(
523
+ BPE(
524
+ vocab=vocab,
525
+ merges=merges,
526
+ dropout=None,
527
+ continuing_subword_prefix="",
528
+ end_of_word_suffix="",
529
+ fuse_unk=False,
530
+ )
531
+ )
532
+
533
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=ot.add_prefix_space)
534
+ tokenizer.decoder = decoders.ByteLevel()
535
+ tokenizer.post_processor = processors.TemplateProcessing(
536
+ single="[CLS]:0 $A:0 [SEP]:0",
537
+ pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
538
+ special_tokens=[
539
+ ("[CLS]", self.original_tokenizer.convert_tokens_to_ids("[CLS]")),
540
+ ("[SEP]", self.original_tokenizer.convert_tokens_to_ids("[SEP]")),
541
+ ],
542
+ )
543
+
544
+ return tokenizer
545
+
546
+
547
+ class SpmConverter(Converter):
548
+ handle_byte_fallback = False
549
+ SpmExtractor = SentencePieceExtractor
550
+ special_tokens = {}
551
+
552
+ def __init__(self, *args):
553
+ requires_backends(self, "protobuf")
554
+
555
+ super().__init__(*args)
556
+
557
+ # from .utils import sentencepiece_model_pb2 as model_pb2
558
+ model_pb2 = import_protobuf()
559
+
560
+ m = model_pb2.ModelProto()
561
+ with open(self.original_tokenizer.vocab_file, "rb") as f:
562
+ m.ParseFromString(f.read())
563
+ self.proto = m
564
+
565
+ if self.proto.trainer_spec.byte_fallback and not self.handle_byte_fallback:
566
+ warnings.warn(
567
+ "The sentencepiece tokenizer that you are converting to a fast tokenizer uses the byte fallback option"
568
+ " which is not implemented in the fast tokenizers. In practice this means that the fast version of the"
569
+ " tokenizer can produce unknown tokens whereas the sentencepiece version would have converted these "
570
+ "unknown tokens into a sequence of byte tokens matching the original piece of text."
571
+ )
572
+
573
+ def vocab(self, proto):
574
+ return [(piece.piece, piece.score) for piece in proto.pieces]
575
+
576
+ def unk_id(self, proto):
577
+ return proto.trainer_spec.unk_id
578
+
579
+ def tokenizer(self, proto):
580
+ model_type = proto.trainer_spec.model_type
581
+ vocab_scores = self.vocab(proto)
582
+
583
+ if model_type == 1:
584
+ tokenizer = Tokenizer(
585
+ Unigram(
586
+ vocab_scores,
587
+ unk_id=self.unk_id(proto),
588
+ byte_fallback=self.handle_byte_fallback,
589
+ )
590
+ )
591
+
592
+ elif model_type == 2:
593
+ _, merges = self.SpmExtractor(self.original_tokenizer.vocab_file).extract(vocab_scores)
594
+ bpe_vocab = {word: i for i, (word, score) in enumerate(vocab_scores)}
595
+ tokenizer = Tokenizer(
596
+ BPE(
597
+ bpe_vocab,
598
+ merges,
599
+ unk_token=proto.trainer_spec.unk_piece,
600
+ fuse_unk=True,
601
+ byte_fallback=self.handle_byte_fallback,
602
+ dropout=None,
603
+ )
604
+ )
605
+
606
+ else:
607
+ raise Exception(
608
+ "You're trying to run a `Unigram` model but you're file was trained with a different algorithm"
609
+ )
610
+
611
+ # control tokens are special
612
+ # user defined symbols are not
613
+ # both user and control tokens are AddedTokens
614
+ # Add user defined symbols (type == 4) from sentencepiece (https://github.com/google/sentencepiece/blob/6225e08edb2577757163b3f5dbba4c0b670ef445/src/sentencepiece_model.proto#L299C29-L299C33)
615
+ spm_added_tokens = [
616
+ (id, p.piece, p.type == 3 or p.piece in self.special_tokens)
617
+ for id, p in enumerate(proto.pieces)
618
+ if p.type in [3, 4]
619
+ ]
620
+ tokenizer.add_tokens(
621
+ [
622
+ AddedToken(token, normalized=False, special=special)
623
+ for id, token, special in sorted(spm_added_tokens, key=lambda x: x[0])
624
+ ]
625
+ )
626
+
627
+ return tokenizer
628
+
629
+ def normalizer(self, proto):
630
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
631
+ _normalizers = [
632
+ normalizers.Strip(left=False, right=True), # stripping is important
633
+ normalizers.Replace(Regex(" {2,}"), "▁"),
634
+ ]
635
+ if not precompiled_charsmap:
636
+ return normalizers.Sequence(_normalizers)
637
+ else:
638
+ return normalizers.Sequence([normalizers.Precompiled(precompiled_charsmap)] + _normalizers)
639
+
640
+ def pre_tokenizer(self, replacement, add_prefix_space):
641
+ prepend_scheme = _get_prepend_scheme(add_prefix_space, self.original_tokenizer)
642
+ return pre_tokenizers.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme)
643
+
644
+ def post_processor(self):
645
+ return None
646
+
647
+ def decoder(self, replacement, add_prefix_space):
648
+ prepend_scheme = _get_prepend_scheme(add_prefix_space, self.original_tokenizer)
649
+ return decoders.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme)
650
+
651
+ def converted(self) -> Tokenizer:
652
+ tokenizer = self.tokenizer(self.proto)
653
+
654
+ # Tokenizer assemble
655
+ normalizer = self.normalizer(self.proto)
656
+ if normalizer is not None:
657
+ tokenizer.normalizer = normalizer
658
+
659
+ replacement = "▁"
660
+ add_prefix_space = True
661
+ if hasattr(self.original_tokenizer, "add_prefix_space"):
662
+ add_prefix_space = self.original_tokenizer.add_prefix_space
663
+
664
+ pre_tokenizer = self.pre_tokenizer(replacement, add_prefix_space)
665
+ if pre_tokenizer is not None:
666
+ tokenizer.pre_tokenizer = pre_tokenizer
667
+
668
+ tokenizer.decoder = self.decoder(replacement, add_prefix_space)
669
+ post_processor = self.post_processor()
670
+ if post_processor:
671
+ tokenizer.post_processor = post_processor
672
+
673
+ return tokenizer
674
+
675
+
676
+ class AlbertConverter(SpmConverter):
677
+ def vocab(self, proto):
678
+ return [
679
+ (piece.piece, piece.score) if check_number_comma(piece.piece) else (piece.piece, piece.score - 100)
680
+ for piece in proto.pieces
681
+ ]
682
+
683
+ def normalizer(self, proto):
684
+ list_normalizers = [
685
+ normalizers.Replace("``", '"'),
686
+ normalizers.Replace("''", '"'),
687
+ ]
688
+ if not self.original_tokenizer.keep_accents:
689
+ list_normalizers.append(normalizers.NFKD())
690
+ list_normalizers.append(normalizers.StripAccents())
691
+ if self.original_tokenizer.do_lower_case:
692
+ list_normalizers.append(normalizers.Lowercase())
693
+
694
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
695
+
696
+ if precompiled_charsmap:
697
+ list_normalizers.append(normalizers.Precompiled(precompiled_charsmap))
698
+
699
+ list_normalizers.append(normalizers.Replace(Regex(" {2,}"), " "))
700
+ return normalizers.Sequence(list_normalizers)
701
+
702
+ def post_processor(self):
703
+ return processors.TemplateProcessing(
704
+ single="[CLS]:0 $A:0 [SEP]:0",
705
+ pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
706
+ special_tokens=[
707
+ ("[CLS]", self.original_tokenizer.convert_tokens_to_ids("[CLS]")),
708
+ ("[SEP]", self.original_tokenizer.convert_tokens_to_ids("[SEP]")),
709
+ ],
710
+ )
711
+
712
+
713
+ class BarthezConverter(SpmConverter):
714
+ def unk_id(self, proto):
715
+ unk_id = 3
716
+ return unk_id
717
+
718
+ def post_processor(self):
719
+ return processors.TemplateProcessing(
720
+ single="<s> $A </s>",
721
+ pair="<s> $A </s> </s> $B </s>",
722
+ special_tokens=[
723
+ ("<s>", self.original_tokenizer.convert_tokens_to_ids("<s>")),
724
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
725
+ ],
726
+ )
727
+
728
+
729
+ class CamembertConverter(SpmConverter):
730
+ def vocab(self, proto):
731
+ vocab = [
732
+ ("<s>NOTUSED", 0.0),
733
+ ("<pad>", 0.0),
734
+ ("</s>NOTUSED", 0.0),
735
+ ("<unk>", 0.0),
736
+ ("<unk>NOTUSED", -100),
737
+ ]
738
+ # We down-grade the original SentencePiece by -100 to avoid using it and use our added token instead
739
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[1:]]
740
+ vocab += [("<mask>", 0.0)]
741
+ return vocab
742
+
743
+ def unk_id(self, proto):
744
+ # See vocab unk position
745
+ return 3
746
+
747
+ def post_processor(self):
748
+ return processors.TemplateProcessing(
749
+ single="<s> $A </s>",
750
+ pair="<s> $A </s> </s> $B </s>",
751
+ special_tokens=[
752
+ ("<s>", self.original_tokenizer.convert_tokens_to_ids("<s>")),
753
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
754
+ ],
755
+ )
756
+
757
+
758
+ class DebertaV2Converter(SpmConverter):
759
+ def pre_tokenizer(self, replacement, add_prefix_space):
760
+ list_pretokenizers = []
761
+ if self.original_tokenizer.split_by_punct:
762
+ list_pretokenizers.append(pre_tokenizers.Punctuation(behavior="isolated"))
763
+ prepend_scheme = _get_prepend_scheme(add_prefix_space, self.original_tokenizer)
764
+ list_pretokenizers.append(pre_tokenizers.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme))
765
+ return pre_tokenizers.Sequence(list_pretokenizers)
766
+
767
+ def normalizer(self, proto):
768
+ list_normalizers = []
769
+ if self.original_tokenizer.do_lower_case:
770
+ list_normalizers.append(normalizers.Lowercase())
771
+ list_normalizers.append(normalizers.Strip())
772
+
773
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
774
+ if precompiled_charsmap:
775
+ list_normalizers.append(normalizers.Precompiled(precompiled_charsmap))
776
+ list_normalizers.append(normalizers.Replace(Regex(" {2,}"), " "))
777
+
778
+ return normalizers.Sequence(list_normalizers)
779
+
780
+ def post_processor(self):
781
+ return processors.TemplateProcessing(
782
+ single="[CLS]:0 $A:0 [SEP]:0",
783
+ pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
784
+ special_tokens=[
785
+ ("[CLS]", self.original_tokenizer.convert_tokens_to_ids("[CLS]")),
786
+ ("[SEP]", self.original_tokenizer.convert_tokens_to_ids("[SEP]")),
787
+ ],
788
+ )
789
+
790
+
791
+ class MBartConverter(SpmConverter):
792
+ def vocab(self, proto):
793
+ vocab = [
794
+ ("<s>", 0.0),
795
+ ("<pad>", 0.0),
796
+ ("</s>", 0.0),
797
+ ("<unk>", 0.0),
798
+ ]
799
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
800
+ vocab += [
801
+ ("ar_AR", 0.0),
802
+ ("cs_CZ", 0.0),
803
+ ("de_DE", 0.0),
804
+ ("en_XX", 0.0),
805
+ ("es_XX", 0.0),
806
+ ("et_EE", 0.0),
807
+ ("fi_FI", 0.0),
808
+ ("fr_XX", 0.0),
809
+ ("gu_IN", 0.0),
810
+ ("hi_IN", 0.0),
811
+ ("it_IT", 0.0),
812
+ ("ja_XX", 0.0),
813
+ ("kk_KZ", 0.0),
814
+ ("ko_KR", 0.0),
815
+ ("lt_LT", 0.0),
816
+ ("lv_LV", 0.0),
817
+ ("my_MM", 0.0),
818
+ ("ne_NP", 0.0),
819
+ ("nl_XX", 0.0),
820
+ ("ro_RO", 0.0),
821
+ ("ru_RU", 0.0),
822
+ ("si_LK", 0.0),
823
+ ("tr_TR", 0.0),
824
+ ("vi_VN", 0.0),
825
+ ("zh_CN", 0.0),
826
+ ]
827
+ vocab += [("<mask>", 0.0)]
828
+ return vocab
829
+
830
+ def unk_id(self, proto):
831
+ return 3
832
+
833
+ def post_processor(self):
834
+ return processors.TemplateProcessing(
835
+ single="$A </s> en_XX",
836
+ pair="$A $B </s> en_XX",
837
+ special_tokens=[
838
+ ("en_XX", self.original_tokenizer.convert_tokens_to_ids("en_XX")),
839
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
840
+ ],
841
+ )
842
+
843
+
844
+ class MBart50Converter(SpmConverter):
845
+ def vocab(self, proto):
846
+ vocab = [
847
+ ("<s>", 0.0),
848
+ ("<pad>", 0.0),
849
+ ("</s>", 0.0),
850
+ ("<unk>", 0.0),
851
+ ]
852
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
853
+ vocab += [("ar_AR", 0.0), ("cs_CZ", 0.0), ("de_DE", 0.0), ("en_XX", 0.0), ("es_XX", 0.0), ("et_EE", 0.0), ("fi_FI", 0.0), ("fr_XX", 0.0), ("gu_IN", 0.0), ("hi_IN", 0.0), ("it_IT", 0.0), ("ja_XX", 0.0), ("kk_KZ", 0.0), ("ko_KR", 0.0), ("lt_LT", 0.0), ("lv_LV", 0.0), ("my_MM", 0.0), ("ne_NP", 0.0), ("nl_XX", 0.0), ("ro_RO", 0.0), ("ru_RU", 0.0), ("si_LK", 0.0), ("tr_TR", 0.0), ("vi_VN", 0.0), ("zh_CN", 0.0), ("af_ZA", 0.0), ("az_AZ", 0.0), ("bn_IN", 0.0), ("fa_IR", 0.0), ("he_IL", 0.0), ("hr_HR", 0.0), ("id_ID", 0.0), ("ka_GE", 0.0), ("km_KH", 0.0), ("mk_MK", 0.0), ("ml_IN", 0.0), ("mn_MN", 0.0), ("mr_IN", 0.0), ("pl_PL", 0.0), ("ps_AF", 0.0), ("pt_XX", 0.0), ("sv_SE", 0.0), ("sw_KE", 0.0), ("ta_IN", 0.0), ("te_IN", 0.0), ("th_TH", 0.0), ("tl_XX", 0.0), ("uk_UA", 0.0), ("ur_PK", 0.0), ("xh_ZA", 0.0), ("gl_ES", 0.0), ("sl_SI", 0.0)] # fmt: skip
854
+ vocab += [("<mask>", 0.0)]
855
+ return vocab
856
+
857
+ def unk_id(self, proto):
858
+ return 3
859
+
860
+ def post_processor(self):
861
+ return processors.TemplateProcessing(
862
+ single="en_XX $A </s>",
863
+ pair="en_XX $A $B </s>",
864
+ special_tokens=[
865
+ ("en_XX", self.original_tokenizer.convert_tokens_to_ids("en_XX")),
866
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
867
+ ],
868
+ )
869
+
870
+
871
+ class NllbConverter(SpmConverter):
872
+ def vocab(self, proto):
873
+ vocab = [
874
+ ("<s>", 0.0),
875
+ ("<pad>", 0.0),
876
+ ("</s>", 0.0),
877
+ ("<unk>", 0.0),
878
+ ]
879
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
880
+ return vocab
881
+
882
+ def unk_id(self, proto):
883
+ return 3
884
+
885
+ def post_processor(self):
886
+ return processors.TemplateProcessing(
887
+ single="eng_Latn $A </s>",
888
+ pair="eng_Latn $A $B </s>",
889
+ special_tokens=[
890
+ ("eng_Latn", self.original_tokenizer.convert_tokens_to_ids("eng_Latn")),
891
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
892
+ ],
893
+ )
894
+
895
+
896
+ class SeamlessM4TConverter(SpmConverter):
897
+ def vocab(self, proto):
898
+ vocab = [
899
+ ("<pad>", 0.0),
900
+ ("<unk>", 0.0),
901
+ ("<s>", 0.0),
902
+ ("</s>", 0.0),
903
+ ]
904
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
905
+ return vocab
906
+
907
+ def unk_id(self, proto):
908
+ return self.original_tokenizer.unk_token_id
909
+
910
+ def post_processor(self):
911
+ return processors.TemplateProcessing(
912
+ single="__eng__ $A </s>",
913
+ pair="__eng__ $A $B </s>",
914
+ special_tokens=[
915
+ ("__eng__", self.original_tokenizer.convert_tokens_to_ids("__eng__")),
916
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
917
+ ],
918
+ )
919
+
920
+
921
+ class XLMRobertaConverter(SpmConverter):
922
+ def vocab(self, proto):
923
+ vocab = [
924
+ ("<s>", 0.0),
925
+ ("<pad>", 0.0),
926
+ ("</s>", 0.0),
927
+ ("<unk>", 0.0),
928
+ ]
929
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
930
+ vocab += [("<mask>", 0.0)]
931
+ return vocab
932
+
933
+ def unk_id(self, proto):
934
+ unk_id = 3
935
+ return unk_id
936
+
937
+ def post_processor(self):
938
+ return processors.TemplateProcessing(
939
+ single="<s> $A </s>",
940
+ pair="<s> $A </s> </s> $B </s>",
941
+ special_tokens=[
942
+ ("<s>", self.original_tokenizer.convert_tokens_to_ids("<s>")),
943
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
944
+ ],
945
+ )
946
+
947
+
948
+ class XLNetConverter(SpmConverter):
949
+ def vocab(self, proto):
950
+ return [
951
+ (piece.piece, piece.score) if check_number_comma(piece.piece) else (piece.piece, piece.score - 100)
952
+ for piece in proto.pieces
953
+ ]
954
+
955
+ def normalizer(self, proto):
956
+ list_normalizers = [
957
+ normalizers.Replace("``", '"'),
958
+ normalizers.Replace("''", '"'),
959
+ ]
960
+ if not self.original_tokenizer.keep_accents:
961
+ list_normalizers.append(normalizers.NFKD())
962
+ list_normalizers.append(normalizers.StripAccents())
963
+ if self.original_tokenizer.do_lower_case:
964
+ list_normalizers.append(normalizers.Lowercase())
965
+
966
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
967
+
968
+ if precompiled_charsmap:
969
+ list_normalizers.append(normalizers.Precompiled(precompiled_charsmap))
970
+
971
+ list_normalizers.append(normalizers.Replace(Regex(" {2,}"), " "))
972
+ return normalizers.Sequence(list_normalizers)
973
+
974
+ def post_processor(self):
975
+ return processors.TemplateProcessing(
976
+ single="$A:0 <sep>:0 <cls>:2",
977
+ pair="$A:0 <sep>:0 $B:1 <sep>:1 <cls>:2",
978
+ special_tokens=[
979
+ ("<sep>", self.original_tokenizer.convert_tokens_to_ids("<sep>")),
980
+ ("<cls>", self.original_tokenizer.convert_tokens_to_ids("<cls>")),
981
+ ],
982
+ )
983
+
984
+
985
+ class ReformerConverter(SpmConverter):
986
+ pass
987
+
988
+
989
+ class RemBertConverter(SpmConverter):
990
+ # Inspired from AlbertConverter
991
+ def normalizer(self, proto):
992
+ list_normalizers = [
993
+ normalizers.Replace("``", '"'),
994
+ normalizers.Replace("''", '"'),
995
+ normalizers.Replace(Regex(" {2,}"), " "),
996
+ ]
997
+ if not self.original_tokenizer.keep_accents:
998
+ list_normalizers.append(normalizers.NFKD())
999
+ list_normalizers.append(normalizers.StripAccents())
1000
+ if self.original_tokenizer.do_lower_case:
1001
+ list_normalizers.append(normalizers.Lowercase())
1002
+
1003
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
1004
+
1005
+ if precompiled_charsmap:
1006
+ list_normalizers.append(normalizers.Precompiled(precompiled_charsmap))
1007
+
1008
+ return normalizers.Sequence(list_normalizers)
1009
+
1010
+ def post_processor(self):
1011
+ return processors.TemplateProcessing(
1012
+ single="[CLS]:0 $A:0 [SEP]:0",
1013
+ pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
1014
+ special_tokens=[
1015
+ ("[CLS]", self.original_tokenizer.convert_tokens_to_ids("[CLS]")),
1016
+ ("[SEP]", self.original_tokenizer.convert_tokens_to_ids("[SEP]")),
1017
+ ],
1018
+ )
1019
+
1020
+
1021
+ class BertGenerationConverter(SpmConverter):
1022
+ pass
1023
+
1024
+
1025
+ class PegasusConverter(SpmConverter):
1026
+ def vocab(self, proto):
1027
+ vocab = [
1028
+ (self.original_tokenizer.pad_token, 0.0),
1029
+ (self.original_tokenizer.eos_token, 0.0),
1030
+ ]
1031
+
1032
+ if self.original_tokenizer.mask_token_sent is not None:
1033
+ vocab += [(self.original_tokenizer.mask_token_sent, 0.0)]
1034
+
1035
+ if (
1036
+ self.original_tokenizer.mask_token is not None
1037
+ and self.original_tokenizer.mask_token_id < self.original_tokenizer.offset
1038
+ ):
1039
+ vocab += [(self.original_tokenizer.mask_token, 0.0)]
1040
+
1041
+ vocab += [(f"<unk_{i}>", -100.0) for i in range(2, self.original_tokenizer.offset)]
1042
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[2:]]
1043
+ return vocab
1044
+
1045
+ def unk_id(self, proto):
1046
+ return proto.trainer_spec.unk_id + self.original_tokenizer.offset
1047
+
1048
+ def pre_tokenizer(self, replacement, add_prefix_space):
1049
+ prepend_scheme = _get_prepend_scheme(add_prefix_space, self.original_tokenizer)
1050
+ return pre_tokenizers.Sequence(
1051
+ [
1052
+ pre_tokenizers.WhitespaceSplit(),
1053
+ pre_tokenizers.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme),
1054
+ ]
1055
+ )
1056
+
1057
+ def post_processor(self):
1058
+ eos = self.original_tokenizer.eos_token
1059
+ special_tokens = [
1060
+ (eos, self.original_tokenizer.eos_token_id),
1061
+ ]
1062
+ return processors.TemplateProcessing(single=["$A", eos], pair=["$A", "$B", eos], special_tokens=special_tokens)
1063
+
1064
+
1065
+ class T5Converter(SpmConverter):
1066
+ def vocab(self, proto):
1067
+ num_extra_ids = self.original_tokenizer._extra_ids
1068
+ vocab = [(piece.piece, piece.score) for piece in proto.pieces]
1069
+ vocab += [(f"<extra_id_{i}>", 0.0) for i in range(num_extra_ids - 1, -1, -1)]
1070
+ return vocab
1071
+
1072
+ def post_processor(self):
1073
+ return processors.TemplateProcessing(
1074
+ single=["$A", "</s>"],
1075
+ pair=["$A", "</s>", "$B", "</s>"],
1076
+ special_tokens=[
1077
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
1078
+ ],
1079
+ )
1080
+
1081
+
1082
+ class UdopConverter(SpmConverter):
1083
+ def post_processor(self):
1084
+ return processors.TemplateProcessing(
1085
+ single=["$A", "</s>"],
1086
+ pair=["$A", "</s>", "$B", "</s>"],
1087
+ special_tokens=[
1088
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
1089
+ ],
1090
+ )
1091
+
1092
+
1093
+ class WhisperConverter(Converter):
1094
+ def converted(self) -> Tokenizer:
1095
+ vocab = self.original_tokenizer.encoder
1096
+ merges = list(self.original_tokenizer.bpe_ranks.keys())
1097
+
1098
+ tokenizer = Tokenizer(
1099
+ BPE(
1100
+ vocab=vocab,
1101
+ merges=merges,
1102
+ dropout=None,
1103
+ continuing_subword_prefix="",
1104
+ end_of_word_suffix="",
1105
+ fuse_unk=False,
1106
+ )
1107
+ )
1108
+
1109
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=self.original_tokenizer.add_prefix_space)
1110
+ tokenizer.decoder = decoders.ByteLevel()
1111
+
1112
+ prefix_token_ids = self.original_tokenizer.prefix_tokens
1113
+ prefixes = self.original_tokenizer.convert_ids_to_tokens(prefix_token_ids)
1114
+ eos = self.original_tokenizer.eos_token
1115
+ eos_token_id = self.original_tokenizer.eos_token_id
1116
+ prefix_template = " ".join([f"{token}:0" for token in prefixes])
1117
+ tokenizer.post_processor = processors.TemplateProcessing(
1118
+ single=f"{prefix_template} $A:0 {eos}:0",
1119
+ pair=f"{prefix_template} $A:0 $B:1 {eos}:1",
1120
+ special_tokens=[
1121
+ (eos, eos_token_id),
1122
+ *zip(prefixes, prefix_token_ids),
1123
+ ],
1124
+ )
1125
+
1126
+ return tokenizer
1127
+
1128
+
1129
+ class BigBirdConverter(SpmConverter):
1130
+ def post_processor(self):
1131
+ return processors.TemplateProcessing(
1132
+ single="[CLS]:0 $A:0 [SEP]:0",
1133
+ pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
1134
+ special_tokens=[
1135
+ ("[CLS]", self.original_tokenizer.convert_tokens_to_ids("[CLS]")),
1136
+ ("[SEP]", self.original_tokenizer.convert_tokens_to_ids("[SEP]")),
1137
+ ],
1138
+ )
1139
+
1140
+
1141
+ class CLIPConverter(Converter):
1142
+ def converted(self) -> Tokenizer:
1143
+ vocab = self.original_tokenizer.encoder
1144
+ merges = list(self.original_tokenizer.bpe_ranks.keys())
1145
+ unk_token = self.original_tokenizer.unk_token
1146
+
1147
+ tokenizer = Tokenizer(
1148
+ BPE(
1149
+ vocab=vocab,
1150
+ merges=merges,
1151
+ dropout=None,
1152
+ continuing_subword_prefix="",
1153
+ end_of_word_suffix="</w>",
1154
+ fuse_unk=False,
1155
+ unk_token=str(unk_token),
1156
+ )
1157
+ )
1158
+
1159
+ tokenizer.normalizer = normalizers.Sequence(
1160
+ [normalizers.NFC(), normalizers.Replace(Regex(r"\s+"), " "), normalizers.Lowercase()]
1161
+ )
1162
+ tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
1163
+ [
1164
+ pre_tokenizers.Split(
1165
+ Regex(r"""'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]|[^\s\p{L}\p{N}]+"""),
1166
+ behavior="removed",
1167
+ invert=True,
1168
+ ),
1169
+ pre_tokenizers.ByteLevel(add_prefix_space=False),
1170
+ ]
1171
+ )
1172
+ tokenizer.decoder = decoders.ByteLevel()
1173
+
1174
+ # Hack to have a ByteLevel and TemplaceProcessor
1175
+ tokenizer.post_processor = processors.RobertaProcessing(
1176
+ sep=(self.original_tokenizer.eos_token, self.original_tokenizer.eos_token_id),
1177
+ cls=(self.original_tokenizer.bos_token, self.original_tokenizer.bos_token_id),
1178
+ add_prefix_space=False,
1179
+ trim_offsets=False,
1180
+ )
1181
+ return tokenizer
1182
+
1183
+
1184
+ class LayoutLMv2Converter(Converter):
1185
+ def converted(self) -> Tokenizer:
1186
+ vocab = self.original_tokenizer.vocab
1187
+ tokenizer = Tokenizer(WordPiece(vocab, unk_token=str(self.original_tokenizer.unk_token)))
1188
+
1189
+ tokenize_chinese_chars = False
1190
+ strip_accents = False
1191
+ do_lower_case = True
1192
+ if hasattr(self.original_tokenizer, "basic_tokenizer"):
1193
+ tokenize_chinese_chars = self.original_tokenizer.basic_tokenizer.tokenize_chinese_chars
1194
+ strip_accents = self.original_tokenizer.basic_tokenizer.strip_accents
1195
+ do_lower_case = self.original_tokenizer.basic_tokenizer.do_lower_case
1196
+
1197
+ tokenizer.normalizer = normalizers.BertNormalizer(
1198
+ clean_text=True,
1199
+ handle_chinese_chars=tokenize_chinese_chars,
1200
+ strip_accents=strip_accents,
1201
+ lowercase=do_lower_case,
1202
+ )
1203
+ tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
1204
+
1205
+ cls = str(self.original_tokenizer.cls_token)
1206
+ sep = str(self.original_tokenizer.sep_token)
1207
+ cls_token_id = self.original_tokenizer.cls_token_id
1208
+ sep_token_id = self.original_tokenizer.sep_token_id
1209
+
1210
+ tokenizer.post_processor = processors.TemplateProcessing(
1211
+ single=f"{cls}:0 $A:0 {sep}:0",
1212
+ pair=f"{cls}:0 $A:0 {sep}:0 $B:1 {sep}:1",
1213
+ special_tokens=[
1214
+ (cls, cls_token_id),
1215
+ (sep, sep_token_id),
1216
+ ],
1217
+ )
1218
+ tokenizer.decoder = decoders.WordPiece(prefix="##")
1219
+
1220
+ return tokenizer
1221
+
1222
+
1223
+ class BlenderbotConverter(Converter):
1224
+ def converted(self) -> Tokenizer:
1225
+ ot = self.original_tokenizer
1226
+ vocab = ot.encoder
1227
+ merges = list(ot.bpe_ranks.keys())
1228
+
1229
+ tokenizer = Tokenizer(
1230
+ BPE(
1231
+ vocab=vocab,
1232
+ merges=merges,
1233
+ dropout=None,
1234
+ continuing_subword_prefix="",
1235
+ end_of_word_suffix="",
1236
+ fuse_unk=False,
1237
+ )
1238
+ )
1239
+
1240
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=ot.add_prefix_space)
1241
+ tokenizer.decoder = decoders.ByteLevel()
1242
+ tokenizer.post_processor = processors.TemplateProcessing(
1243
+ single=f"$A:0 {ot.eos_token}:0",
1244
+ special_tokens=[
1245
+ (ot.eos_token, ot.eos_token_id),
1246
+ ],
1247
+ )
1248
+
1249
+ return tokenizer
1250
+
1251
+
1252
+ class XGLMConverter(SpmConverter):
1253
+ def vocab(self, proto):
1254
+ vocab = [
1255
+ ("<s>", 0.0),
1256
+ ("<pad>", 0.0),
1257
+ ("</s>", 0.0),
1258
+ ("<unk>", 0.0),
1259
+ ]
1260
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
1261
+ vocab += [("<madeupword0>", 0.0), ("<madeupword1>", 0.0), ("<madeupword2>", 0.0), ("<madeupword3>", 0.0), ("<madeupword4>", 0.0), ("<madeupword5>", 0.0), ("<madeupword6>", 0.0)] # fmt: skip
1262
+ return vocab
1263
+
1264
+ def unk_id(self, proto):
1265
+ unk_id = 3
1266
+ return unk_id
1267
+
1268
+ def post_processor(self):
1269
+ return processors.TemplateProcessing(
1270
+ single="</s> $A",
1271
+ pair="</s> $A </s> </s> $B",
1272
+ special_tokens=[
1273
+ ("<s>", self.original_tokenizer.convert_tokens_to_ids("<s>")),
1274
+ ("</s>", self.original_tokenizer.convert_tokens_to_ids("</s>")),
1275
+ ],
1276
+ )
1277
+
1278
+
1279
+ class GemmaConverter(SpmConverter):
1280
+ handle_byte_fallback = True
1281
+ SpmExtractor = GemmaSentencePieceExtractor
1282
+ # start and end of turn tokens must be marked as special
1283
+ special_tokens = {"<start_of_turn>", "<end_of_turn>"}
1284
+
1285
+ """"
1286
+ split_by_unicode_script: true
1287
+ split_by_number: true
1288
+ split_by_whitespace: true
1289
+ treat_whitespace_as_suffix: false
1290
+ allow_whitespace_only_pieces: true
1291
+ split_digits: true
1292
+ byte_fallback: true
1293
+ """
1294
+
1295
+ def normalizer(self, proto):
1296
+ return normalizers.Replace(" ", "▁")
1297
+
1298
+ def vocab(self, proto):
1299
+ vocab = [
1300
+ (self.original_tokenizer.pad_token, 0.0),
1301
+ (self.original_tokenizer.eos_token, 0.0),
1302
+ (self.original_tokenizer.bos_token, 0.0),
1303
+ ]
1304
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
1305
+
1306
+ # Older gemma tokenizers had a missing tab token, so we fix that here
1307
+ if not any(x[0] == "\t" for x in vocab):
1308
+ override_index = next((i for i, x in enumerate(vocab) if x[0] == "<0x09>"), None)
1309
+ if override_index is not None:
1310
+ vocab[override_index] = ("\t", 0.0)
1311
+
1312
+ return vocab
1313
+
1314
+ def pre_tokenizer(self, replacement, add_prefix_space):
1315
+ return pre_tokenizers.Split(" ", "merged_with_previous")
1316
+
1317
+ def unk_id(self, proto):
1318
+ unk_id = 3
1319
+ return unk_id
1320
+
1321
+ def decoder(self, replacement, add_prefix_space):
1322
+ return decoders.Sequence(
1323
+ [
1324
+ decoders.Replace("▁", " "),
1325
+ decoders.ByteFallback(),
1326
+ decoders.Fuse(),
1327
+ ]
1328
+ )
1329
+
1330
+
1331
+ class LlamaConverter(SpmConverter):
1332
+ handle_byte_fallback = True
1333
+
1334
+ def vocab(self, proto):
1335
+ vocab = [
1336
+ (self.original_tokenizer.convert_ids_to_tokens(0), 0.0),
1337
+ (self.original_tokenizer.convert_ids_to_tokens(1), 0.0),
1338
+ (self.original_tokenizer.convert_ids_to_tokens(2), 0.0),
1339
+ ]
1340
+ vocab += [(piece.piece, piece.score) for piece in proto.pieces[3:]]
1341
+ return vocab
1342
+
1343
+ def unk_id(self, proto):
1344
+ unk_id = 0
1345
+ return unk_id
1346
+
1347
+ def decoder(self, replacement, add_prefix_space):
1348
+ sequence = [
1349
+ decoders.Replace("▁", " "),
1350
+ decoders.ByteFallback(),
1351
+ decoders.Fuse(),
1352
+ ]
1353
+ if add_prefix_space:
1354
+ sequence += [decoders.Strip(content=" ", left=1)]
1355
+ return decoders.Sequence(sequence)
1356
+
1357
+ def normalizer(self, proto):
1358
+ if getattr(self.original_tokenizer, "legacy", True):
1359
+ sequence = []
1360
+ if getattr(self.original_tokenizer, "add_prefix_space", True):
1361
+ sequence += [normalizers.Prepend(prepend="▁")]
1362
+ sequence += [normalizers.Replace(pattern=" ", content="▁")]
1363
+ return normalizers.Sequence(sequence)
1364
+ return None # non-legacy, no normalizer
1365
+
1366
+ def pre_tokenizer(self, replacement, add_prefix_space):
1367
+ if not getattr(self.original_tokenizer, "legacy", True): # non-legacy, we need a replace
1368
+ prepend_scheme = _get_prepend_scheme(add_prefix_space, self.original_tokenizer)
1369
+ return pre_tokenizers.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme, split=False)
1370
+ return None
1371
+
1372
+ def post_processor(self):
1373
+ # the processor is defined in the LlamaTokenizerFast class.
1374
+ return None
1375
+
1376
+
1377
+ class MarkupLMConverter(Converter):
1378
+ def converted(self) -> Tokenizer:
1379
+ ot = self.original_tokenizer
1380
+ vocab = ot.encoder
1381
+ merges = list(ot.bpe_ranks.keys())
1382
+
1383
+ tokenizer = Tokenizer(
1384
+ BPE(
1385
+ vocab=vocab,
1386
+ merges=merges,
1387
+ dropout=None,
1388
+ continuing_subword_prefix="",
1389
+ end_of_word_suffix="",
1390
+ fuse_unk=False,
1391
+ unk_token=self.original_tokenizer.unk_token,
1392
+ )
1393
+ )
1394
+
1395
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=ot.add_prefix_space)
1396
+ tokenizer.decoder = decoders.ByteLevel()
1397
+
1398
+ cls = str(self.original_tokenizer.cls_token)
1399
+ sep = str(self.original_tokenizer.sep_token)
1400
+ cls_token_id = self.original_tokenizer.cls_token_id
1401
+ sep_token_id = self.original_tokenizer.sep_token_id
1402
+
1403
+ tokenizer.post_processor = processors.TemplateProcessing(
1404
+ single=f"{cls} $A {sep}",
1405
+ pair=f"{cls} $A {sep} $B {sep}",
1406
+ special_tokens=[
1407
+ (cls, cls_token_id),
1408
+ (sep, sep_token_id),
1409
+ ],
1410
+ )
1411
+
1412
+ return tokenizer
1413
+
1414
+
1415
+ class MoshiConverter(SpmConverter):
1416
+ handle_byte_fallback = True
1417
+
1418
+ def __init__(self, vocab_file, model_max_length=None, **kwargs):
1419
+ requires_backends(self, "protobuf")
1420
+
1421
+ Converter.__init__(self, vocab_file)
1422
+
1423
+ # from .utils import sentencepiece_model_pb2 as model_pb2
1424
+ model_pb2 = import_protobuf()
1425
+
1426
+ m = model_pb2.ModelProto()
1427
+ with open(vocab_file, "rb") as f:
1428
+ m.ParseFromString(f.read())
1429
+ self.proto = m
1430
+
1431
+ def normalizer(self, proto):
1432
+ precompiled_charsmap = proto.normalizer_spec.precompiled_charsmap
1433
+ _normalizers = [
1434
+ normalizers.Replace(" ", "▁"),
1435
+ ]
1436
+ if not precompiled_charsmap:
1437
+ return normalizers.Sequence(_normalizers)
1438
+ else:
1439
+ return normalizers.Sequence([normalizers.Precompiled(precompiled_charsmap)] + _normalizers)
1440
+
1441
+ def decoder(self, replacement, add_prefix_space):
1442
+ sequence = [
1443
+ decoders.Replace("▁", " "),
1444
+ decoders.ByteFallback(),
1445
+ decoders.Fuse(),
1446
+ ]
1447
+ if add_prefix_space:
1448
+ sequence += [decoders.Strip(content=" ", left=1)]
1449
+ return decoders.Sequence(sequence)
1450
+
1451
+ def pre_tokenizer(self, replacement, add_prefix_space):
1452
+ prepend_scheme = "first"
1453
+ return pre_tokenizers.Metaspace(replacement=replacement, prepend_scheme=prepend_scheme, split=False)
1454
+
1455
+
1456
+ class HeliumConverter(SpmConverter):
1457
+ handle_byte_fallback = True
1458
+
1459
+ def __init__(self, vocab_file=None, **kwargs):
1460
+ requires_backends(self, "protobuf")
1461
+
1462
+ Converter.__init__(self, vocab_file)
1463
+
1464
+ model_pb2 = import_protobuf()
1465
+
1466
+ m = model_pb2.ModelProto()
1467
+ with open(vocab_file, "rb") as f:
1468
+ m.ParseFromString(f.read())
1469
+ self.proto = m
1470
+
1471
+ def tokenizer(self, proto):
1472
+ vocab_scores = self.vocab(proto)
1473
+ tokenizer = Tokenizer(
1474
+ Unigram(
1475
+ vocab_scores,
1476
+ unk_id=self.unk_id(proto),
1477
+ byte_fallback=self.handle_byte_fallback,
1478
+ )
1479
+ )
1480
+ # control tokens are special
1481
+ # user defined symbols are not
1482
+ # both user and control tokens are AddedTokens
1483
+ # Add user defined symbols (type == 4) from sentencepiece (https://github.com/google/sentencepiece/blob/6225e08edb2577757163b3f5dbba4c0b670ef445/src/sentencepiece_model.proto#L299C29-L299C33)
1484
+ spm_added_tokens = [
1485
+ (id, p.piece, p.type == 3 or p.piece in self.special_tokens)
1486
+ for id, p in enumerate(proto.pieces)
1487
+ if p.type in [3, 4]
1488
+ ]
1489
+ tokenizer.add_tokens(
1490
+ [
1491
+ AddedToken(token, normalized=False, special=special, single_word=True)
1492
+ for id, token, special in sorted(spm_added_tokens, key=lambda x: x[0])
1493
+ ]
1494
+ )
1495
+ tokenizer.add_tokens([AddedToken("\n", normalized=False, special=False)])
1496
+ tokenizer.enable_padding(pad_token="<pad>", pad_id=3)
1497
+ return tokenizer
1498
+
1499
+ def vocab(self, proto):
1500
+ vocab = []
1501
+ for piece in proto.pieces:
1502
+ if piece.piece == "<0x0A>":
1503
+ vocab += [("\n", piece.score)]
1504
+ else:
1505
+ vocab += [(piece.piece, piece.score)]
1506
+ return vocab
1507
+
1508
+ def unk_id(self, proto):
1509
+ unk_id = 0
1510
+ return unk_id
1511
+
1512
+ def decoder(self, replacement, add_prefix_space):
1513
+ sequence = [
1514
+ decoders.Replace("▁", " "),
1515
+ decoders.ByteFallback(),
1516
+ decoders.Fuse(),
1517
+ ]
1518
+ sequence += [decoders.Strip(content=" ", left=1)]
1519
+ return decoders.Sequence(sequence)
1520
+
1521
+ def normalizer(self, proto):
1522
+ return normalizers.Sequence([normalizers.Prepend(" "), normalizers.Replace(r" ", "▁")])
1523
+
1524
+ def pre_tokenizer(self, replacement, add_prefix_space):
1525
+ return pre_tokenizers.Sequence([pre_tokenizers.Split("\n", "contiguous")])
1526
+
1527
+ def post_processor(self):
1528
+ return processors.TemplateProcessing(
1529
+ single=[
1530
+ "<s>",
1531
+ "$A",
1532
+ ],
1533
+ pair=[
1534
+ "<s>",
1535
+ "$A",
1536
+ "<s>",
1537
+ "$B",
1538
+ ],
1539
+ special_tokens=[
1540
+ ("<s>", 1),
1541
+ ],
1542
+ )
1543
+
1544
+
1545
+ class ParakeetConverter(SpmConverter):
1546
+ handle_byte_fallback = True
1547
+
1548
+ def __init__(self, vocab_file=None, *args):
1549
+ self.vocab_file = vocab_file
1550
+
1551
+ requires_backends(self, "protobuf")
1552
+
1553
+ Converter.__init__(self, vocab_file)
1554
+
1555
+ model_pb2 = import_protobuf()
1556
+ m = model_pb2.ModelProto()
1557
+ with open(vocab_file, "rb") as f:
1558
+ m.ParseFromString(f.read())
1559
+ self.proto = m
1560
+
1561
+ def tokenizer(self, proto):
1562
+ vocab_scores = self.vocab(proto)
1563
+
1564
+ _, merges = self.SpmExtractor(self.vocab_file).extract(vocab_scores)
1565
+ bpe_vocab = {word: i for i, (word, score) in enumerate(vocab_scores)}
1566
+ tokenizer = Tokenizer(
1567
+ BPE(
1568
+ bpe_vocab,
1569
+ merges,
1570
+ unk_token=proto.trainer_spec.unk_piece,
1571
+ fuse_unk=True,
1572
+ byte_fallback=self.handle_byte_fallback,
1573
+ dropout=None,
1574
+ )
1575
+ )
1576
+
1577
+ # Add user defined symbols and control tokens from sentencepiece model
1578
+ spm_added_tokens = [
1579
+ (id, p.piece, p.type == 3 or p.piece in self.special_tokens)
1580
+ for id, p in enumerate(proto.pieces)
1581
+ if p.type in [3, 4]
1582
+ ]
1583
+ tokenizer.add_tokens(
1584
+ [
1585
+ AddedToken(token, normalized=False, special=special)
1586
+ for id, token, special in sorted(spm_added_tokens, key=lambda x: x[0])
1587
+ ]
1588
+ )
1589
+
1590
+ return tokenizer
1591
+
1592
+
1593
+ # Copied from transformers.models.gpt2.tokenization_gpt2.bytes_to_unicode
1594
+ def bytes_to_unicode():
1595
+ """
1596
+ Returns list of utf-8 byte and a mapping to unicode strings. We specifically avoids mapping to whitespace/control
1597
+ characters the bpe code barfs on.
1598
+
1599
+ The reversible bpe codes work on unicode strings. This means you need a large # of unicode characters in your vocab
1600
+ if you want to avoid UNKs. When you're at something like a 10B token dataset you end up needing around 5K for
1601
+ decent coverage. This is a significant percentage of your normal, say, 32K bpe vocab. To avoid that, we want lookup
1602
+ tables between utf-8 bytes and unicode strings.
1603
+ """
1604
+ bs = (
1605
+ list(range(ord("!"), ord("~") + 1)) + list(range(ord("¡"), ord("¬") + 1)) + list(range(ord("®"), ord("ÿ") + 1))
1606
+ )
1607
+ cs = bs[:]
1608
+ n = 0
1609
+ for b in range(2**8):
1610
+ if b not in bs:
1611
+ bs.append(b)
1612
+ cs.append(2**8 + n)
1613
+ n += 1
1614
+ cs = [chr(n) for n in cs]
1615
+ return dict(zip(bs, cs))
1616
+
1617
+
1618
+ class TikTokenConverter:
1619
+ """
1620
+ A general tiktoken converter.
1621
+ """
1622
+
1623
+ def __init__(
1624
+ self,
1625
+ vocab_file=None,
1626
+ pattern=r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+""",
1627
+ add_prefix_space=False,
1628
+ additional_special_tokens=None,
1629
+ **kwargs,
1630
+ ):
1631
+ self.vocab_file = vocab_file
1632
+ self.pattern = pattern
1633
+ self.add_prefix_space = add_prefix_space
1634
+ self.additional_special_tokens = (
1635
+ additional_special_tokens.keys()
1636
+ if isinstance(additional_special_tokens, dict)
1637
+ else additional_special_tokens
1638
+ )
1639
+
1640
+ def extract_vocab_merges_from_model(self, tiktoken_url: str):
1641
+ try:
1642
+ from tiktoken.load import load_tiktoken_bpe
1643
+ except Exception:
1644
+ raise ValueError(
1645
+ "`tiktoken` is required to read a `tiktoken` file. Install it with `pip install tiktoken`."
1646
+ )
1647
+
1648
+ bpe_ranks = load_tiktoken_bpe(tiktoken_url)
1649
+ byte_encoder = bytes_to_unicode()
1650
+
1651
+ def token_bytes_to_string(b):
1652
+ return "".join([byte_encoder[ord(char)] for char in b.decode("latin-1")])
1653
+
1654
+ merges = []
1655
+ vocab = {}
1656
+ for token, rank in bpe_ranks.items():
1657
+ vocab[token_bytes_to_string(token)] = rank
1658
+ if len(token) == 1:
1659
+ continue
1660
+ local = []
1661
+ for index in range(1, len(token)):
1662
+ piece_l, piece_r = token[:index], token[index:]
1663
+ if piece_l in bpe_ranks and piece_r in bpe_ranks and (piece_l + piece_r) in bpe_ranks:
1664
+ local.append((piece_l, piece_r, rank))
1665
+ local = sorted(local, key=lambda x: (bpe_ranks[x[0]], bpe_ranks[x[1]]), reverse=False)
1666
+ merges.extend(local)
1667
+ merges = sorted(merges, key=lambda val: val[2], reverse=False)
1668
+ merges = [(token_bytes_to_string(val[0]), token_bytes_to_string(val[1])) for val in merges]
1669
+ return vocab, merges
1670
+
1671
+ def tokenizer(self):
1672
+ vocab_scores, merges = self.extract_vocab_merges_from_model(self.vocab_file)
1673
+ tokenizer = Tokenizer(BPE(vocab_scores, merges, fuse_unk=False))
1674
+ if hasattr(tokenizer.model, "ignore_merges"):
1675
+ tokenizer.model.ignore_merges = True
1676
+ return tokenizer
1677
+
1678
+ def converted(self) -> Tokenizer:
1679
+ tokenizer = self.tokenizer()
1680
+ tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
1681
+ [
1682
+ pre_tokenizers.Split(Regex(self.pattern), behavior="isolated", invert=False),
1683
+ pre_tokenizers.ByteLevel(add_prefix_space=self.add_prefix_space, use_regex=False),
1684
+ ]
1685
+ )
1686
+ tokenizer.decoder = decoders.ByteLevel()
1687
+
1688
+ tokenizer.add_special_tokens(
1689
+ [AddedToken(token, normalized=False, special=True) for token in self.additional_special_tokens]
1690
+ )
1691
+
1692
+ tokenizer.post_processor = processors.ByteLevel(trim_offsets=False)
1693
+
1694
+ return tokenizer
1695
+
1696
+
1697
+ class MistralConverter:
1698
+ def __init__(
1699
+ self,
1700
+ vocab_file=None,
1701
+ pattern=r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+""",
1702
+ add_prefix_space=False,
1703
+ additional_special_tokens=None,
1704
+ **kwargs,
1705
+ ):
1706
+ self.vocab_file = vocab_file
1707
+ self.pattern = pattern
1708
+ self.add_prefix_space = add_prefix_space
1709
+ self.additional_special_tokens = (
1710
+ additional_special_tokens.keys()
1711
+ if isinstance(additional_special_tokens, dict)
1712
+ else additional_special_tokens
1713
+ )
1714
+
1715
+ def extract_vocab_merges_from_model(self, tiktoken_url: str):
1716
+ import base64
1717
+ import json
1718
+
1719
+ with open(self.vocab_file, "r", encoding="utf-8") as f:
1720
+ untyped = json.load(f)
1721
+ self.pattern = untyped["config"]["pattern"]
1722
+ self.additional_special_tokens = [
1723
+ AddedToken(k["token_str"], special=k["is_control"]) for k in untyped["special_tokens"]
1724
+ ]
1725
+ bpe_ranks = untyped["vocab"]
1726
+ byte_encoder = bytes_to_unicode()
1727
+
1728
+ @lru_cache
1729
+ def token_bytes_to_string(b):
1730
+ return "".join([byte_encoder[ord(char)] for char in b.decode("latin-1")])
1731
+
1732
+ merges = []
1733
+ vocab = {}
1734
+ for idx, token in enumerate(self.additional_special_tokens):
1735
+ vocab[token.content] = idx
1736
+ bpe_ranks = [base64.b64decode(k["token_bytes"]) for k in bpe_ranks]
1737
+ rank_set = set(bpe_ranks)
1738
+ for rank, token in enumerate(tqdm(bpe_ranks, desc="Converting tekken.json to tokenizer.json")):
1739
+ vocab[token_bytes_to_string(token)] = rank
1740
+ if len(token) == 1:
1741
+ continue
1742
+ local = []
1743
+ for index in range(1, len(token)):
1744
+ piece_l, piece_r = token[:index], token[index:]
1745
+ if piece_l in rank_set and piece_r in rank_set and (piece_l + piece_r) in rank_set:
1746
+ local.append((piece_l, piece_r, rank))
1747
+ local = sorted(local, key=lambda x: (bpe_ranks.index(x[0]), bpe_ranks.index(x[1])), reverse=False)
1748
+ merges.extend(local)
1749
+ merges = sorted(merges, key=lambda val: val[2], reverse=False)
1750
+ merges = [(token_bytes_to_string(val[0]), token_bytes_to_string(val[1])) for val in merges]
1751
+ return vocab, merges
1752
+
1753
+ def tokenizer(self):
1754
+ vocab_scores, merges = self.extract_vocab_merges_from_model(self.vocab_file)
1755
+ tokenizer = Tokenizer(BPE(vocab_scores, merges, fuse_unk=False))
1756
+ if hasattr(tokenizer.model, "ignore_merges"):
1757
+ tokenizer.model.ignore_merges = True
1758
+ return tokenizer
1759
+
1760
+ def converted(self) -> Tokenizer:
1761
+ tokenizer = self.tokenizer()
1762
+ tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
1763
+ [
1764
+ pre_tokenizers.Split(Regex(self.pattern), behavior="isolated", invert=False),
1765
+ pre_tokenizers.ByteLevel(add_prefix_space=self.add_prefix_space, use_regex=False),
1766
+ ]
1767
+ )
1768
+ tokenizer.decoder = decoders.ByteLevel()
1769
+
1770
+ tokenizer.add_tokens(self.additional_special_tokens)
1771
+ tokenizer.post_processor = processors.ByteLevel(trim_offsets=False)
1772
+
1773
+ return tokenizer
1774
+
1775
+
1776
+ SLOW_TO_FAST_CONVERTERS = {
1777
+ "AlbertTokenizer": AlbertConverter,
1778
+ "BartTokenizer": RobertaConverter,
1779
+ "BarthezTokenizer": BarthezConverter,
1780
+ "BertTokenizer": BertConverter,
1781
+ "BigBirdTokenizer": BigBirdConverter,
1782
+ "BlenderbotTokenizer": BlenderbotConverter,
1783
+ "CamembertTokenizer": CamembertConverter,
1784
+ "CLIPTokenizer": CLIPConverter,
1785
+ "CodeGenTokenizer": GPT2Converter,
1786
+ "ConvBertTokenizer": BertConverter,
1787
+ "DebertaTokenizer": DebertaConverter,
1788
+ "DebertaV2Tokenizer": DebertaV2Converter,
1789
+ "DistilBertTokenizer": BertConverter,
1790
+ "DPRReaderTokenizer": BertConverter,
1791
+ "DPRQuestionEncoderTokenizer": BertConverter,
1792
+ "DPRContextEncoderTokenizer": BertConverter,
1793
+ "ElectraTokenizer": BertConverter,
1794
+ "FNetTokenizer": AlbertConverter,
1795
+ "FunnelTokenizer": FunnelConverter,
1796
+ "GPT2Tokenizer": GPT2Converter,
1797
+ "HerbertTokenizer": HerbertConverter,
1798
+ "LayoutLMTokenizer": BertConverter,
1799
+ "LayoutLMv2Tokenizer": BertConverter,
1800
+ "LayoutLMv3Tokenizer": RobertaConverter,
1801
+ "LayoutXLMTokenizer": XLMRobertaConverter,
1802
+ "LongformerTokenizer": RobertaConverter,
1803
+ "LEDTokenizer": RobertaConverter,
1804
+ "LxmertTokenizer": BertConverter,
1805
+ "MarkupLMTokenizer": MarkupLMConverter,
1806
+ "MBartTokenizer": MBartConverter,
1807
+ "MBart50Tokenizer": MBart50Converter,
1808
+ "MPNetTokenizer": MPNetConverter,
1809
+ "MobileBertTokenizer": BertConverter,
1810
+ "MvpTokenizer": RobertaConverter,
1811
+ "NllbTokenizer": NllbConverter,
1812
+ "OpenAIGPTTokenizer": OpenAIGPTConverter,
1813
+ "PegasusTokenizer": PegasusConverter,
1814
+ "Qwen2Tokenizer": Qwen2Converter,
1815
+ "RealmTokenizer": BertConverter,
1816
+ "ReformerTokenizer": ReformerConverter,
1817
+ "RemBertTokenizer": RemBertConverter,
1818
+ "RetriBertTokenizer": BertConverter,
1819
+ "RobertaTokenizer": RobertaConverter,
1820
+ "RoFormerTokenizer": RoFormerConverter,
1821
+ "SeamlessM4TTokenizer": SeamlessM4TConverter,
1822
+ "SqueezeBertTokenizer": BertConverter,
1823
+ "T5Tokenizer": T5Converter,
1824
+ "UdopTokenizer": UdopConverter,
1825
+ "WhisperTokenizer": WhisperConverter,
1826
+ "XLMRobertaTokenizer": XLMRobertaConverter,
1827
+ "XLNetTokenizer": XLNetConverter,
1828
+ "SplinterTokenizer": SplinterConverter,
1829
+ "XGLMTokenizer": XGLMConverter,
1830
+ "LlamaTokenizer": LlamaConverter,
1831
+ "CodeLlamaTokenizer": LlamaConverter,
1832
+ "GemmaTokenizer": GemmaConverter,
1833
+ "Phi3Tokenizer": LlamaConverter,
1834
+ }
1835
+
1836
+
1837
+ def convert_slow_tokenizer(transformer_tokenizer, from_tiktoken=False) -> Tokenizer:
1838
+ """
1839
+ Utilities to convert a slow tokenizer instance in a fast tokenizer instance.
1840
+
1841
+ Args:
1842
+ transformer_tokenizer ([`~tokenization_utils_base.PreTrainedTokenizer`]):
1843
+ Instance of a slow tokenizer to convert in the backend tokenizer for
1844
+ [`~tokenization_utils_base.PreTrainedTokenizerFast`].
1845
+ from_tiktoken (bool, optional): Whether to use the `tiktoken` library to convert the tokenizer instead of sentencepiece.
1846
+ Defaults to False.
1847
+
1848
+ Return:
1849
+ A instance of [`~tokenizers.Tokenizer`] to be used as the backend tokenizer of a
1850
+ [`~tokenization_utils_base.PreTrainedTokenizerFast`]
1851
+ """
1852
+
1853
+ tokenizer_class_name = transformer_tokenizer.__class__.__name__
1854
+ if tokenizer_class_name in SLOW_TO_FAST_CONVERTERS and not from_tiktoken:
1855
+ converter_class = SLOW_TO_FAST_CONVERTERS[tokenizer_class_name]
1856
+ return converter_class(transformer_tokenizer).converted()
1857
+ elif transformer_tokenizer.vocab_file.endswith("tekken.json"):
1858
+ transformer_tokenizer.original_tokenizer = transformer_tokenizer
1859
+ logger.info("Converting from Mistral tekken.json")
1860
+ return MistralConverter(transformer_tokenizer.vocab_file).converted()
1861
+ else:
1862
+ try:
1863
+ logger.info("Converting from Tiktoken")
1864
+ return TikTokenConverter(
1865
+ vocab_file=transformer_tokenizer.vocab_file,
1866
+ additional_special_tokens=transformer_tokenizer.additional_special_tokens,
1867
+ ).converted()
1868
+ except Exception:
1869
+ raise ValueError(
1870
+ f"Converting from SentencePiece and Tiktoken failed, if a converter for SentencePiece is available, provide a model path "
1871
+ f"with a SentencePiece tokenizer.model file."
1872
+ f"Currently available slow->fast converters: {list(SLOW_TO_FAST_CONVERTERS.keys())}"
1873
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_slow_tokenizers_checkpoints_to_fast.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2018 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Convert slow tokenizers checkpoints in fast (serialization format of the `tokenizers` library)"""
15
+
16
+ import argparse
17
+ import os
18
+
19
+ import transformers
20
+
21
+ from .convert_slow_tokenizer import SLOW_TO_FAST_CONVERTERS
22
+ from .utils import logging
23
+
24
+
25
+ logging.set_verbosity_info()
26
+
27
+ logger = logging.get_logger(__name__)
28
+
29
+
30
+ TOKENIZER_CLASSES = {
31
+ # Phi3 uses Llama tokenizer
32
+ name: getattr(transformers, "LlamaTokenizerFast" if name == "Phi3Tokenizer" else name + "Fast")
33
+ for name in SLOW_TO_FAST_CONVERTERS
34
+ }
35
+
36
+
37
+ def convert_slow_checkpoint_to_fast(tokenizer_name, checkpoint_name, dump_path, force_download):
38
+ if tokenizer_name is not None and tokenizer_name not in TOKENIZER_CLASSES:
39
+ raise ValueError(f"Unrecognized tokenizer name, should be one of {list(TOKENIZER_CLASSES.keys())}.")
40
+
41
+ if tokenizer_name is None:
42
+ tokenizer_names = TOKENIZER_CLASSES
43
+ else:
44
+ tokenizer_names = {tokenizer_name: getattr(transformers, tokenizer_name + "Fast")}
45
+
46
+ logger.info(f"Loading tokenizer classes: {tokenizer_names}")
47
+
48
+ for tokenizer_name in tokenizer_names:
49
+ tokenizer_class = TOKENIZER_CLASSES[tokenizer_name]
50
+
51
+ add_prefix = True
52
+ if checkpoint_name is None:
53
+ checkpoint_names = list(tokenizer_class.max_model_input_sizes.keys())
54
+ else:
55
+ checkpoint_names = [checkpoint_name]
56
+
57
+ logger.info(f"For tokenizer {tokenizer_class.__class__.__name__} loading checkpoints: {checkpoint_names}")
58
+
59
+ for checkpoint in checkpoint_names:
60
+ logger.info(f"Loading {tokenizer_class.__class__.__name__} {checkpoint}")
61
+
62
+ # Load tokenizer
63
+ tokenizer = tokenizer_class.from_pretrained(checkpoint, force_download=force_download)
64
+
65
+ # Save fast tokenizer
66
+ logger.info(f"Save fast tokenizer to {dump_path} with prefix {checkpoint} add_prefix {add_prefix}")
67
+
68
+ # For organization names we create sub-directories
69
+ if "/" in checkpoint:
70
+ checkpoint_directory, checkpoint_prefix_name = checkpoint.split("/")
71
+ dump_path_full = os.path.join(dump_path, checkpoint_directory)
72
+ elif add_prefix:
73
+ checkpoint_prefix_name = checkpoint
74
+ dump_path_full = dump_path
75
+ else:
76
+ checkpoint_prefix_name = None
77
+ dump_path_full = dump_path
78
+
79
+ logger.info(f"=> {dump_path_full} with prefix {checkpoint_prefix_name}, add_prefix {add_prefix}")
80
+
81
+ if checkpoint in list(tokenizer.pretrained_vocab_files_map.values())[0]:
82
+ file_path = list(tokenizer.pretrained_vocab_files_map.values())[0][checkpoint]
83
+ next_char = file_path.split(checkpoint)[-1][0]
84
+ if next_char == "/":
85
+ dump_path_full = os.path.join(dump_path_full, checkpoint_prefix_name)
86
+ checkpoint_prefix_name = None
87
+
88
+ logger.info(f"=> {dump_path_full} with prefix {checkpoint_prefix_name}, add_prefix {add_prefix}")
89
+
90
+ file_names = tokenizer.save_pretrained(
91
+ dump_path_full, legacy_format=False, filename_prefix=checkpoint_prefix_name
92
+ )
93
+ logger.info(f"=> File names {file_names}")
94
+
95
+ for file_name in file_names:
96
+ if not file_name.endswith("tokenizer.json"):
97
+ os.remove(file_name)
98
+ logger.info(f"=> removing {file_name}")
99
+
100
+
101
+ if __name__ == "__main__":
102
+ parser = argparse.ArgumentParser()
103
+ # Required parameters
104
+ parser.add_argument(
105
+ "--dump_path", default=None, type=str, required=True, help="Path to output generated fast tokenizer files."
106
+ )
107
+ parser.add_argument(
108
+ "--tokenizer_name",
109
+ default=None,
110
+ type=str,
111
+ help=(
112
+ f"Optional tokenizer type selected in the list of {list(TOKENIZER_CLASSES.keys())}. If not given, will "
113
+ "download and convert all the checkpoints from AWS."
114
+ ),
115
+ )
116
+ parser.add_argument(
117
+ "--checkpoint_name",
118
+ default=None,
119
+ type=str,
120
+ help="Optional checkpoint name. If not given, will download and convert the canonical checkpoints from AWS.",
121
+ )
122
+ parser.add_argument(
123
+ "--force_download",
124
+ action="store_true",
125
+ help="Re-download checkpoints.",
126
+ )
127
+ args = parser.parse_args()
128
+
129
+ convert_slow_checkpoint_to_fast(args.tokenizer_name, args.checkpoint_name, args.dump_path, args.force_download)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dependency_versions_check.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .dependency_versions_table import deps
16
+ from .utils.versions import require_version, require_version_core
17
+
18
+
19
+ # define which module versions we always want to check at run time
20
+ # (usually the ones defined in `install_requires` in setup.py)
21
+ #
22
+ # order specific notes:
23
+ # - tqdm must be checked before tokenizers
24
+
25
+ pkgs_to_check_at_runtime = [
26
+ "python",
27
+ "tqdm",
28
+ "regex",
29
+ "requests",
30
+ "packaging",
31
+ "filelock",
32
+ "numpy",
33
+ "tokenizers",
34
+ "huggingface-hub",
35
+ "safetensors",
36
+ "accelerate",
37
+ "pyyaml",
38
+ ]
39
+
40
+ for pkg in pkgs_to_check_at_runtime:
41
+ if pkg in deps:
42
+ if pkg == "tokenizers":
43
+ # must be loaded here, or else tqdm check may fail
44
+ from .utils import is_tokenizers_available
45
+
46
+ if not is_tokenizers_available():
47
+ continue # not required, check version only if installed
48
+ elif pkg == "accelerate":
49
+ # must be loaded here, or else tqdm check may fail
50
+ from .utils import is_accelerate_available
51
+
52
+ # Maybe switch to is_torch_available in the future here so that Accelerate is hard dep of
53
+ # Transformers with PyTorch
54
+ if not is_accelerate_available():
55
+ continue # not required, check version only if installed
56
+
57
+ require_version_core(deps[pkg])
58
+ else:
59
+ raise ValueError(f"can't find {pkg} in {deps.keys()}, check dependency_versions_table.py")
60
+
61
+
62
+ def dep_version_check(pkg, hint=None):
63
+ require_version(deps[pkg], hint)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/hf_argparser.py ADDED
@@ -0,0 +1,430 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import dataclasses
16
+ import json
17
+ import os
18
+ import sys
19
+ import types
20
+ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError
21
+ from collections.abc import Iterable
22
+ from copy import copy
23
+ from enum import Enum
24
+ from inspect import isclass
25
+ from pathlib import Path
26
+ from typing import Any, Callable, Literal, NewType, Optional, Union, get_type_hints
27
+
28
+ import yaml
29
+
30
+
31
+ DataClass = NewType("DataClass", Any)
32
+ DataClassType = NewType("DataClassType", Any)
33
+
34
+
35
+ # From https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse
36
+ def string_to_bool(v):
37
+ if isinstance(v, bool):
38
+ return v
39
+ if v.lower() in ("yes", "true", "t", "y", "1"):
40
+ return True
41
+ elif v.lower() in ("no", "false", "f", "n", "0"):
42
+ return False
43
+ else:
44
+ raise ArgumentTypeError(
45
+ f"Truthy value expected: got {v} but expected one of yes/no, true/false, t/f, y/n, 1/0 (case insensitive)."
46
+ )
47
+
48
+
49
+ def make_choice_type_function(choices: list) -> Callable[[str], Any]:
50
+ """
51
+ Creates a mapping function from each choices string representation to the actual value. Used to support multiple
52
+ value types for a single argument.
53
+
54
+ Args:
55
+ choices (list): List of choices.
56
+
57
+ Returns:
58
+ Callable[[str], Any]: Mapping function from string representation to actual value for each choice.
59
+ """
60
+ str_to_choice = {str(choice): choice for choice in choices}
61
+ return lambda arg: str_to_choice.get(arg, arg)
62
+
63
+
64
+ def HfArg(
65
+ *,
66
+ aliases: Optional[Union[str, list[str]]] = None,
67
+ help: Optional[str] = None,
68
+ default: Any = dataclasses.MISSING,
69
+ default_factory: Callable[[], Any] = dataclasses.MISSING,
70
+ metadata: Optional[dict] = None,
71
+ **kwargs,
72
+ ) -> dataclasses.Field:
73
+ """Argument helper enabling a concise syntax to create dataclass fields for parsing with `HfArgumentParser`.
74
+
75
+ Example comparing the use of `HfArg` and `dataclasses.field`:
76
+ ```
77
+ @dataclass
78
+ class Args:
79
+ regular_arg: str = dataclasses.field(default="Huggingface", metadata={"aliases": ["--example", "-e"], "help": "This syntax could be better!"})
80
+ hf_arg: str = HfArg(default="Huggingface", aliases=["--example", "-e"], help="What a nice syntax!")
81
+ ```
82
+
83
+ Args:
84
+ aliases (Union[str, list[str]], optional):
85
+ Single string or list of strings of aliases to pass on to argparse, e.g. `aliases=["--example", "-e"]`.
86
+ Defaults to None.
87
+ help (str, optional): Help string to pass on to argparse that can be displayed with --help. Defaults to None.
88
+ default (Any, optional):
89
+ Default value for the argument. If not default or default_factory is specified, the argument is required.
90
+ Defaults to dataclasses.MISSING.
91
+ default_factory (Callable[[], Any], optional):
92
+ The default_factory is a 0-argument function called to initialize a field's value. It is useful to provide
93
+ default values for mutable types, e.g. lists: `default_factory=list`. Mutually exclusive with `default=`.
94
+ Defaults to dataclasses.MISSING.
95
+ metadata (dict, optional): Further metadata to pass on to `dataclasses.field`. Defaults to None.
96
+
97
+ Returns:
98
+ Field: A `dataclasses.Field` with the desired properties.
99
+ """
100
+ if metadata is None:
101
+ # Important, don't use as default param in function signature because dict is mutable and shared across function calls
102
+ metadata = {}
103
+ if aliases is not None:
104
+ metadata["aliases"] = aliases
105
+ if help is not None:
106
+ metadata["help"] = help
107
+
108
+ return dataclasses.field(metadata=metadata, default=default, default_factory=default_factory, **kwargs)
109
+
110
+
111
+ class HfArgumentParser(ArgumentParser):
112
+ """
113
+ This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments.
114
+
115
+ The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed)
116
+ arguments to the parser after initialization and you'll get the output back after parsing as an additional
117
+ namespace. Optional: To create sub argument groups use the `_argument_group_name` attribute in the dataclass.
118
+
119
+ Args:
120
+ dataclass_types (`DataClassType` or `Iterable[DataClassType]`, *optional*):
121
+ Dataclass type, or list of dataclass types for which we will "fill" instances with the parsed args.
122
+ kwargs (`dict[str, Any]`, *optional*):
123
+ Passed to `argparse.ArgumentParser()` in the regular way.
124
+ """
125
+
126
+ dataclass_types: Iterable[DataClassType]
127
+
128
+ def __init__(self, dataclass_types: Optional[Union[DataClassType, Iterable[DataClassType]]] = None, **kwargs):
129
+ # Make sure dataclass_types is an iterable
130
+ if dataclass_types is None:
131
+ dataclass_types = []
132
+ elif not isinstance(dataclass_types, Iterable):
133
+ dataclass_types = [dataclass_types]
134
+
135
+ # To make the default appear when using --help
136
+ if "formatter_class" not in kwargs:
137
+ kwargs["formatter_class"] = ArgumentDefaultsHelpFormatter
138
+ super().__init__(**kwargs)
139
+ if dataclasses.is_dataclass(dataclass_types):
140
+ dataclass_types = [dataclass_types]
141
+ self.dataclass_types = list(dataclass_types)
142
+ for dtype in self.dataclass_types:
143
+ self._add_dataclass_arguments(dtype)
144
+
145
+ @staticmethod
146
+ def _parse_dataclass_field(parser: ArgumentParser, field: dataclasses.Field):
147
+ # Long-option strings are conventionlly separated by hyphens rather
148
+ # than underscores, e.g., "--long-format" rather than "--long_format".
149
+ # Argparse converts hyphens to underscores so that the destination
150
+ # string is a valid attribute name. Hf_argparser should do the same.
151
+ long_options = [f"--{field.name}"]
152
+ if "_" in field.name:
153
+ long_options.append(f"--{field.name.replace('_', '-')}")
154
+
155
+ kwargs = field.metadata.copy()
156
+ # field.metadata is not used at all by Data Classes,
157
+ # it is provided as a third-party extension mechanism.
158
+ if isinstance(field.type, str):
159
+ raise RuntimeError(
160
+ "Unresolved type detected, which should have been done with the help of "
161
+ "`typing.get_type_hints` method by default"
162
+ )
163
+
164
+ aliases = kwargs.pop("aliases", [])
165
+ if isinstance(aliases, str):
166
+ aliases = [aliases]
167
+
168
+ origin_type = getattr(field.type, "__origin__", field.type)
169
+ if origin_type is Union or (hasattr(types, "UnionType") and isinstance(origin_type, types.UnionType)):
170
+ if str not in field.type.__args__ and (
171
+ len(field.type.__args__) != 2 or type(None) not in field.type.__args__
172
+ ):
173
+ raise ValueError(
174
+ "Only `Union[X, NoneType]` (i.e., `Optional[X]`) is allowed for `Union` because"
175
+ " the argument parser only supports one type per argument."
176
+ f" Problem encountered in field '{field.name}'."
177
+ )
178
+ if type(None) not in field.type.__args__:
179
+ # filter `str` in Union
180
+ field.type = field.type.__args__[0] if field.type.__args__[1] is str else field.type.__args__[1]
181
+ origin_type = getattr(field.type, "__origin__", field.type)
182
+ elif bool not in field.type.__args__:
183
+ # filter `NoneType` in Union (except for `Union[bool, NoneType]`)
184
+ field.type = (
185
+ field.type.__args__[0] if isinstance(None, field.type.__args__[1]) else field.type.__args__[1]
186
+ )
187
+ origin_type = getattr(field.type, "__origin__", field.type)
188
+
189
+ # A variable to store kwargs for a boolean field, if needed
190
+ # so that we can init a `no_*` complement argument (see below)
191
+ bool_kwargs = {}
192
+ if origin_type is Literal or (isinstance(field.type, type) and issubclass(field.type, Enum)):
193
+ if origin_type is Literal:
194
+ kwargs["choices"] = field.type.__args__
195
+ else:
196
+ kwargs["choices"] = [x.value for x in field.type]
197
+
198
+ kwargs["type"] = make_choice_type_function(kwargs["choices"])
199
+
200
+ if field.default is not dataclasses.MISSING:
201
+ kwargs["default"] = field.default
202
+ else:
203
+ kwargs["required"] = True
204
+ elif field.type is bool or field.type == Optional[bool]:
205
+ # Copy the correct kwargs to use to instantiate a `no_*` complement argument below.
206
+ # We do not initialize it here because the `no_*` alternative must be instantiated after the real argument
207
+ bool_kwargs = copy(kwargs)
208
+
209
+ # Hack because type=bool in argparse does not behave as we want.
210
+ kwargs["type"] = string_to_bool
211
+ if field.type is bool or (field.default is not None and field.default is not dataclasses.MISSING):
212
+ # Default value is False if we have no default when of type bool.
213
+ default = False if field.default is dataclasses.MISSING else field.default
214
+ # This is the value that will get picked if we don't include --{field.name} in any way
215
+ kwargs["default"] = default
216
+ # This tells argparse we accept 0 or 1 value after --{field.name}
217
+ kwargs["nargs"] = "?"
218
+ # This is the value that will get picked if we do --{field.name} (without value)
219
+ kwargs["const"] = True
220
+ elif isclass(origin_type) and issubclass(origin_type, list):
221
+ kwargs["type"] = field.type.__args__[0]
222
+ kwargs["nargs"] = "+"
223
+ if field.default_factory is not dataclasses.MISSING:
224
+ kwargs["default"] = field.default_factory()
225
+ elif field.default is dataclasses.MISSING:
226
+ kwargs["required"] = True
227
+ else:
228
+ kwargs["type"] = field.type
229
+ if field.default is not dataclasses.MISSING:
230
+ kwargs["default"] = field.default
231
+ elif field.default_factory is not dataclasses.MISSING:
232
+ kwargs["default"] = field.default_factory()
233
+ else:
234
+ kwargs["required"] = True
235
+ parser.add_argument(*long_options, *aliases, **kwargs)
236
+
237
+ # Add a complement `no_*` argument for a boolean field AFTER the initial field has already been added.
238
+ # Order is important for arguments with the same destination!
239
+ # We use a copy of earlier kwargs because the original kwargs have changed a lot before reaching down
240
+ # here and we do not need those changes/additional keys.
241
+ if field.default is True and (field.type is bool or field.type == Optional[bool]):
242
+ bool_kwargs["default"] = False
243
+ parser.add_argument(
244
+ f"--no_{field.name}",
245
+ f"--no-{field.name.replace('_', '-')}",
246
+ action="store_false",
247
+ dest=field.name,
248
+ **bool_kwargs,
249
+ )
250
+
251
+ def _add_dataclass_arguments(self, dtype: DataClassType):
252
+ if hasattr(dtype, "_argument_group_name"):
253
+ parser = self.add_argument_group(dtype._argument_group_name)
254
+ else:
255
+ parser = self
256
+
257
+ try:
258
+ type_hints: dict[str, type] = get_type_hints(dtype)
259
+ except NameError:
260
+ raise RuntimeError(
261
+ f"Type resolution failed for {dtype}. Try declaring the class in global scope or "
262
+ "removing line of `from __future__ import annotations` which opts in Postponed "
263
+ "Evaluation of Annotations (PEP 563)"
264
+ )
265
+
266
+ for field in dataclasses.fields(dtype):
267
+ if not field.init:
268
+ continue
269
+ field.type = type_hints[field.name]
270
+ self._parse_dataclass_field(parser, field)
271
+
272
+ def parse_args_into_dataclasses(
273
+ self,
274
+ args=None,
275
+ return_remaining_strings=False,
276
+ look_for_args_file=True,
277
+ args_filename=None,
278
+ args_file_flag=None,
279
+ ) -> tuple[DataClass, ...]:
280
+ """
281
+ Parse command-line args into instances of the specified dataclass types.
282
+
283
+ This relies on argparse's `ArgumentParser.parse_known_args`. See the doc at:
284
+ docs.python.org/3/library/argparse.html#argparse.ArgumentParser.parse_args
285
+
286
+ Args:
287
+ args:
288
+ List of strings to parse. The default is taken from sys.argv. (same as argparse.ArgumentParser)
289
+ return_remaining_strings:
290
+ If true, also return a list of remaining argument strings.
291
+ look_for_args_file:
292
+ If true, will look for a ".args" file with the same base name as the entry point script for this
293
+ process, and will append its potential content to the command line args.
294
+ args_filename:
295
+ If not None, will uses this file instead of the ".args" file specified in the previous argument.
296
+ args_file_flag:
297
+ If not None, will look for a file in the command-line args specified with this flag. The flag can be
298
+ specified multiple times and precedence is determined by the order (last one wins).
299
+
300
+ Returns:
301
+ Tuple consisting of:
302
+
303
+ - the dataclass instances in the same order as they were passed to the initializer.abspath
304
+ - if applicable, an additional namespace for more (non-dataclass backed) arguments added to the parser
305
+ after initialization.
306
+ - The potential list of remaining argument strings. (same as argparse.ArgumentParser.parse_known_args)
307
+ """
308
+
309
+ if args_file_flag or args_filename or (look_for_args_file and len(sys.argv)):
310
+ args_files = []
311
+
312
+ if args_filename:
313
+ args_files.append(Path(args_filename))
314
+ elif look_for_args_file and len(sys.argv):
315
+ args_files.append(Path(sys.argv[0]).with_suffix(".args"))
316
+
317
+ # args files specified via command line flag should overwrite default args files so we add them last
318
+ if args_file_flag:
319
+ # Create special parser just to extract the args_file_flag values
320
+ args_file_parser = ArgumentParser()
321
+ args_file_parser.add_argument(args_file_flag, type=str, action="append")
322
+
323
+ # Use only remaining args for further parsing (remove the args_file_flag)
324
+ cfg, args = args_file_parser.parse_known_args(args=args)
325
+ cmd_args_file_paths = vars(cfg).get(args_file_flag.lstrip("-"), None)
326
+
327
+ if cmd_args_file_paths:
328
+ args_files.extend([Path(p) for p in cmd_args_file_paths])
329
+
330
+ file_args = []
331
+ for args_file in args_files:
332
+ if args_file.exists():
333
+ file_args += args_file.read_text().split()
334
+
335
+ # in case of duplicate arguments the last one has precedence
336
+ # args specified via the command line should overwrite args from files, so we add them last
337
+ args = file_args + args if args is not None else file_args + sys.argv[1:]
338
+ namespace, remaining_args = self.parse_known_args(args=args)
339
+ outputs = []
340
+ for dtype in self.dataclass_types:
341
+ keys = {f.name for f in dataclasses.fields(dtype) if f.init}
342
+ inputs = {k: v for k, v in vars(namespace).items() if k in keys}
343
+ for k in keys:
344
+ delattr(namespace, k)
345
+ obj = dtype(**inputs)
346
+ outputs.append(obj)
347
+ if len(namespace.__dict__) > 0:
348
+ # additional namespace.
349
+ outputs.append(namespace)
350
+ if return_remaining_strings:
351
+ return (*outputs, remaining_args)
352
+ else:
353
+ if remaining_args:
354
+ raise ValueError(f"Some specified arguments are not used by the HfArgumentParser: {remaining_args}")
355
+
356
+ return (*outputs,)
357
+
358
+ def parse_dict(self, args: dict[str, Any], allow_extra_keys: bool = False) -> tuple[DataClass, ...]:
359
+ """
360
+ Alternative helper method that does not use `argparse` at all, instead uses a dict and populating the dataclass
361
+ types.
362
+
363
+ Args:
364
+ args (`dict`):
365
+ dict containing config values
366
+ allow_extra_keys (`bool`, *optional*, defaults to `False`):
367
+ Defaults to False. If False, will raise an exception if the dict contains keys that are not parsed.
368
+
369
+ Returns:
370
+ Tuple consisting of:
371
+
372
+ - the dataclass instances in the same order as they were passed to the initializer.
373
+ """
374
+ unused_keys = set(args.keys())
375
+ outputs = []
376
+ for dtype in self.dataclass_types:
377
+ keys = {f.name for f in dataclasses.fields(dtype) if f.init}
378
+ inputs = {k: v for k, v in args.items() if k in keys}
379
+ unused_keys.difference_update(inputs.keys())
380
+ obj = dtype(**inputs)
381
+ outputs.append(obj)
382
+ if not allow_extra_keys and unused_keys:
383
+ raise ValueError(f"Some keys are not used by the HfArgumentParser: {sorted(unused_keys)}")
384
+ return tuple(outputs)
385
+
386
+ def parse_json_file(
387
+ self, json_file: Union[str, os.PathLike], allow_extra_keys: bool = False
388
+ ) -> tuple[DataClass, ...]:
389
+ """
390
+ Alternative helper method that does not use `argparse` at all, instead loading a json file and populating the
391
+ dataclass types.
392
+
393
+ Args:
394
+ json_file (`str` or `os.PathLike`):
395
+ File name of the json file to parse
396
+ allow_extra_keys (`bool`, *optional*, defaults to `False`):
397
+ Defaults to False. If False, will raise an exception if the json file contains keys that are not
398
+ parsed.
399
+
400
+ Returns:
401
+ Tuple consisting of:
402
+
403
+ - the dataclass instances in the same order as they were passed to the initializer.
404
+ """
405
+ with open(Path(json_file), encoding="utf-8") as open_json_file:
406
+ data = json.loads(open_json_file.read())
407
+ outputs = self.parse_dict(data, allow_extra_keys=allow_extra_keys)
408
+ return tuple(outputs)
409
+
410
+ def parse_yaml_file(
411
+ self, yaml_file: Union[str, os.PathLike], allow_extra_keys: bool = False
412
+ ) -> tuple[DataClass, ...]:
413
+ """
414
+ Alternative helper method that does not use `argparse` at all, instead loading a yaml file and populating the
415
+ dataclass types.
416
+
417
+ Args:
418
+ yaml_file (`str` or `os.PathLike`):
419
+ File name of the yaml file to parse
420
+ allow_extra_keys (`bool`, *optional*, defaults to `False`):
421
+ Defaults to False. If False, will raise an exception if the json file contains keys that are not
422
+ parsed.
423
+
424
+ Returns:
425
+ Tuple consisting of:
426
+
427
+ - the dataclass instances in the same order as they were passed to the initializer.
428
+ """
429
+ outputs = self.parse_dict(yaml.safe_load(Path(yaml_file).read_text()), allow_extra_keys=allow_extra_keys)
430
+ return tuple(outputs)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_utils_fast.py ADDED
@@ -0,0 +1,833 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from collections.abc import Iterable
16
+ from copy import deepcopy
17
+ from functools import lru_cache, partial
18
+ from typing import Any, Optional, TypedDict, Union
19
+
20
+ import numpy as np
21
+
22
+ from .image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict
23
+ from .image_transforms import (
24
+ convert_to_rgb,
25
+ get_resize_output_image_size,
26
+ get_size_with_aspect_ratio,
27
+ group_images_by_shape,
28
+ reorder_images,
29
+ )
30
+ from .image_utils import (
31
+ ChannelDimension,
32
+ ImageInput,
33
+ ImageType,
34
+ SizeDict,
35
+ get_image_size,
36
+ get_image_size_for_max_height_width,
37
+ get_image_type,
38
+ infer_channel_dimension_format,
39
+ make_flat_list_of_images,
40
+ validate_kwargs,
41
+ validate_preprocess_arguments,
42
+ )
43
+ from .processing_utils import Unpack
44
+ from .utils import (
45
+ TensorType,
46
+ auto_docstring,
47
+ is_torch_available,
48
+ is_torchvision_available,
49
+ is_vision_available,
50
+ logging,
51
+ )
52
+ from .utils.import_utils import is_rocm_platform
53
+
54
+
55
+ if is_vision_available():
56
+ from .image_utils import PILImageResampling
57
+
58
+ if is_torch_available():
59
+ import torch
60
+
61
+ if is_torchvision_available():
62
+ from torchvision.transforms.v2 import functional as F
63
+
64
+ from .image_utils import pil_torch_interpolation_mapping
65
+
66
+ else:
67
+ pil_torch_interpolation_mapping = None
68
+
69
+
70
+ logger = logging.get_logger(__name__)
71
+
72
+
73
+ @lru_cache(maxsize=10)
74
+ def validate_fast_preprocess_arguments(
75
+ do_rescale: Optional[bool] = None,
76
+ rescale_factor: Optional[float] = None,
77
+ do_normalize: Optional[bool] = None,
78
+ image_mean: Optional[Union[float, list[float]]] = None,
79
+ image_std: Optional[Union[float, list[float]]] = None,
80
+ do_center_crop: Optional[bool] = None,
81
+ crop_size: Optional[SizeDict] = None,
82
+ do_resize: Optional[bool] = None,
83
+ size: Optional[SizeDict] = None,
84
+ interpolation: Optional["F.InterpolationMode"] = None,
85
+ return_tensors: Optional[Union[str, TensorType]] = None,
86
+ data_format: ChannelDimension = ChannelDimension.FIRST,
87
+ ):
88
+ """
89
+ Checks validity of typically used arguments in an `ImageProcessorFast` `preprocess` method.
90
+ Raises `ValueError` if arguments incompatibility is caught.
91
+ """
92
+ validate_preprocess_arguments(
93
+ do_rescale=do_rescale,
94
+ rescale_factor=rescale_factor,
95
+ do_normalize=do_normalize,
96
+ image_mean=image_mean,
97
+ image_std=image_std,
98
+ do_center_crop=do_center_crop,
99
+ crop_size=crop_size,
100
+ do_resize=do_resize,
101
+ size=size,
102
+ interpolation=interpolation,
103
+ )
104
+ # Extra checks for ImageProcessorFast
105
+ if return_tensors is not None and return_tensors != "pt":
106
+ raise ValueError("Only returning PyTorch tensors is currently supported.")
107
+
108
+ if data_format != ChannelDimension.FIRST:
109
+ raise ValueError("Only channel first data format is currently supported.")
110
+
111
+
112
+ def safe_squeeze(tensor: "torch.Tensor", axis: Optional[int] = None) -> "torch.Tensor":
113
+ """
114
+ Squeezes a tensor, but only if the axis specified has dim 1.
115
+ """
116
+ if axis is None:
117
+ return tensor.squeeze()
118
+
119
+ try:
120
+ return tensor.squeeze(axis=axis)
121
+ except ValueError:
122
+ return tensor
123
+
124
+
125
+ def max_across_indices(values: Iterable[Any]) -> list[Any]:
126
+ """
127
+ Return the maximum value across all indices of an iterable of values.
128
+ """
129
+ return [max(values_i) for values_i in zip(*values)]
130
+
131
+
132
+ def get_max_height_width(images: list["torch.Tensor"]) -> tuple[int, ...]:
133
+ """
134
+ Get the maximum height and width across all images in a batch.
135
+ """
136
+
137
+ _, max_height, max_width = max_across_indices([img.shape for img in images])
138
+
139
+ return (max_height, max_width)
140
+
141
+
142
+ def divide_to_patches(
143
+ image: Union[np.ndarray, "torch.Tensor"], patch_size: int
144
+ ) -> list[Union[np.ndarray, "torch.Tensor"]]:
145
+ """
146
+ Divides an image into patches of a specified size.
147
+
148
+ Args:
149
+ image (`Union[np.array, "torch.Tensor"]`):
150
+ The input image.
151
+ patch_size (`int`):
152
+ The size of each patch.
153
+ Returns:
154
+ list: A list of Union[np.array, "torch.Tensor"] representing the patches.
155
+ """
156
+ patches = []
157
+ height, width = get_image_size(image, channel_dim=ChannelDimension.FIRST)
158
+ for i in range(0, height, patch_size):
159
+ for j in range(0, width, patch_size):
160
+ patch = image[:, i : i + patch_size, j : j + patch_size]
161
+ patches.append(patch)
162
+
163
+ return patches
164
+
165
+
166
+ class DefaultFastImageProcessorKwargs(TypedDict, total=False):
167
+ do_resize: Optional[bool]
168
+ size: Optional[dict[str, int]]
169
+ default_to_square: Optional[bool]
170
+ resample: Optional[Union["PILImageResampling", "F.InterpolationMode"]]
171
+ do_center_crop: Optional[bool]
172
+ crop_size: Optional[dict[str, int]]
173
+ do_rescale: Optional[bool]
174
+ rescale_factor: Optional[Union[int, float]]
175
+ do_normalize: Optional[bool]
176
+ image_mean: Optional[Union[float, list[float]]]
177
+ image_std: Optional[Union[float, list[float]]]
178
+ do_pad: Optional[bool]
179
+ pad_size: Optional[dict[str, int]]
180
+ do_convert_rgb: Optional[bool]
181
+ return_tensors: Optional[Union[str, TensorType]]
182
+ data_format: Optional[ChannelDimension]
183
+ input_data_format: Optional[Union[str, ChannelDimension]]
184
+ device: Optional["torch.device"]
185
+ disable_grouping: Optional[bool]
186
+
187
+
188
+ @auto_docstring
189
+ class BaseImageProcessorFast(BaseImageProcessor):
190
+ resample = None
191
+ image_mean = None
192
+ image_std = None
193
+ size = None
194
+ default_to_square = True
195
+ crop_size = None
196
+ do_resize = None
197
+ do_center_crop = None
198
+ do_pad = None
199
+ pad_size = None
200
+ do_rescale = None
201
+ rescale_factor = 1 / 255
202
+ do_normalize = None
203
+ do_convert_rgb = None
204
+ return_tensors = None
205
+ data_format = ChannelDimension.FIRST
206
+ input_data_format = None
207
+ device = None
208
+ model_input_names = ["pixel_values"]
209
+ valid_kwargs = DefaultFastImageProcessorKwargs
210
+ unused_kwargs = None
211
+
212
+ def __init__(self, **kwargs: Unpack[DefaultFastImageProcessorKwargs]):
213
+ super().__init__(**kwargs)
214
+ kwargs = self.filter_out_unused_kwargs(kwargs)
215
+ size = kwargs.pop("size", self.size)
216
+ self.size = (
217
+ get_size_dict(size=size, default_to_square=kwargs.pop("default_to_square", self.default_to_square))
218
+ if size is not None
219
+ else None
220
+ )
221
+ crop_size = kwargs.pop("crop_size", self.crop_size)
222
+ self.crop_size = get_size_dict(crop_size, param_name="crop_size") if crop_size is not None else None
223
+ pad_size = kwargs.pop("pad_size", self.pad_size)
224
+ self.pad_size = get_size_dict(size=pad_size, param_name="pad_size") if pad_size is not None else None
225
+
226
+ for key in self.valid_kwargs.__annotations__:
227
+ kwarg = kwargs.pop(key, None)
228
+ if kwarg is not None:
229
+ setattr(self, key, kwarg)
230
+ else:
231
+ setattr(self, key, deepcopy(getattr(self, key, None)))
232
+
233
+ # get valid kwargs names
234
+ self._valid_kwargs_names = list(self.valid_kwargs.__annotations__.keys())
235
+
236
+ @property
237
+ def is_fast(self) -> bool:
238
+ """
239
+ `bool`: Whether or not this image processor is a fast processor (backed by PyTorch and TorchVision).
240
+ """
241
+ return True
242
+
243
+ def pad(
244
+ self,
245
+ images: "torch.Tensor",
246
+ pad_size: SizeDict = None,
247
+ fill_value: Optional[int] = 0,
248
+ padding_mode: Optional[str] = "constant",
249
+ return_mask: bool = False,
250
+ disable_grouping: Optional[bool] = False,
251
+ **kwargs,
252
+ ) -> "torch.Tensor":
253
+ """
254
+ Pads images to `(pad_size["height"], pad_size["width"])` or to the largest size in the batch.
255
+
256
+ Args:
257
+ images (`torch.Tensor`):
258
+ Images to pad.
259
+ pad_size (`SizeDict`, *optional*):
260
+ Dictionary in the format `{"height": int, "width": int}` specifying the size of the output image.
261
+ fill_value (`int`, *optional*, defaults to `0`):
262
+ The constant value used to fill the padded area.
263
+ padding_mode (`str`, *optional*, defaults to "constant"):
264
+ The padding mode to use. Can be any of the modes supported by
265
+ `torch.nn.functional.pad` (e.g. constant, reflection, replication).
266
+ return_mask (`bool`, *optional*, defaults to `False`):
267
+ Whether to return a pixel mask to denote padded regions.
268
+ disable_grouping (`bool`, *optional*, defaults to `False`):
269
+ Whether to disable grouping of images by size.
270
+
271
+ Returns:
272
+ `torch.Tensor`: The resized image.
273
+ """
274
+ if pad_size is not None:
275
+ if not (pad_size.height and pad_size.width):
276
+ raise ValueError(f"Pad size must contain 'height' and 'width' keys only. Got pad_size={pad_size}.")
277
+ pad_size = (pad_size.height, pad_size.width)
278
+ else:
279
+ pad_size = get_max_height_width(images)
280
+
281
+ grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
282
+ processed_images_grouped = {}
283
+ processed_masks_grouped = {}
284
+ for shape, stacked_images in grouped_images.items():
285
+ image_size = stacked_images.shape[-2:]
286
+ padding_height = pad_size[0] - image_size[0]
287
+ padding_width = pad_size[1] - image_size[1]
288
+ if padding_height < 0 or padding_width < 0:
289
+ raise ValueError(
290
+ f"Padding dimensions are negative. Please make sure that the `pad_size` is larger than the "
291
+ f"image size. Got pad_size={pad_size}, image_size={image_size}."
292
+ )
293
+ if image_size != pad_size:
294
+ padding = (0, 0, padding_width, padding_height)
295
+ stacked_images = F.pad(stacked_images, padding, fill=fill_value, padding_mode=padding_mode)
296
+ processed_images_grouped[shape] = stacked_images
297
+
298
+ if return_mask:
299
+ # keep only one from the channel dimension in pixel mask
300
+ stacked_masks = torch.zeros_like(stacked_images, dtype=torch.int64)[..., 0, :, :]
301
+ stacked_masks[..., : image_size[0], : image_size[1]] = 1
302
+ processed_masks_grouped[shape] = stacked_masks
303
+
304
+ processed_images = reorder_images(processed_images_grouped, grouped_images_index)
305
+ if return_mask:
306
+ processed_masks = reorder_images(processed_masks_grouped, grouped_images_index)
307
+ return processed_images, processed_masks
308
+
309
+ return processed_images
310
+
311
+ def resize(
312
+ self,
313
+ image: "torch.Tensor",
314
+ size: SizeDict,
315
+ interpolation: Optional["F.InterpolationMode"] = None,
316
+ antialias: bool = True,
317
+ **kwargs,
318
+ ) -> "torch.Tensor":
319
+ """
320
+ Resize an image to `(size["height"], size["width"])`.
321
+
322
+ Args:
323
+ image (`torch.Tensor`):
324
+ Image to resize.
325
+ size (`SizeDict`):
326
+ Dictionary in the format `{"height": int, "width": int}` specifying the size of the output image.
327
+ interpolation (`InterpolationMode`, *optional*, defaults to `InterpolationMode.BILINEAR`):
328
+ `InterpolationMode` filter to use when resizing the image e.g. `InterpolationMode.BICUBIC`.
329
+
330
+ Returns:
331
+ `torch.Tensor`: The resized image.
332
+ """
333
+ interpolation = interpolation if interpolation is not None else F.InterpolationMode.BILINEAR
334
+ if size.shortest_edge and size.longest_edge:
335
+ # Resize the image so that the shortest edge or the longest edge is of the given size
336
+ # while maintaining the aspect ratio of the original image.
337
+ new_size = get_size_with_aspect_ratio(
338
+ image.size()[-2:],
339
+ size.shortest_edge,
340
+ size.longest_edge,
341
+ )
342
+ elif size.shortest_edge:
343
+ new_size = get_resize_output_image_size(
344
+ image,
345
+ size=size.shortest_edge,
346
+ default_to_square=False,
347
+ input_data_format=ChannelDimension.FIRST,
348
+ )
349
+ elif size.max_height and size.max_width:
350
+ new_size = get_image_size_for_max_height_width(image.size()[-2:], size.max_height, size.max_width)
351
+ elif size.height and size.width:
352
+ new_size = (size.height, size.width)
353
+ else:
354
+ raise ValueError(
355
+ "Size must contain 'height' and 'width' keys, or 'max_height' and 'max_width', or 'shortest_edge' key. Got"
356
+ f" {size}."
357
+ )
358
+ # This is a workaround to avoid a bug in torch.compile when dealing with uint8 on AMD MI3XX GPUs
359
+ # Tracked in PyTorch issue: https://github.com/pytorch/pytorch/issues/155209
360
+ # TODO: remove this once the bug is fixed (detected with torch==2.7.0+git1fee196, torchvision==0.22.0+9eb57cd)
361
+ if torch.compiler.is_compiling() and is_rocm_platform():
362
+ return self.compile_friendly_resize(image, new_size, interpolation, antialias)
363
+ return F.resize(image, new_size, interpolation=interpolation, antialias=antialias)
364
+
365
+ @staticmethod
366
+ def compile_friendly_resize(
367
+ image: "torch.Tensor",
368
+ new_size: tuple[int, int],
369
+ interpolation: Optional["F.InterpolationMode"] = None,
370
+ antialias: bool = True,
371
+ ) -> "torch.Tensor":
372
+ """
373
+ A wrapper around `F.resize` so that it is compatible with torch.compile when the image is a uint8 tensor.
374
+ """
375
+ if image.dtype == torch.uint8:
376
+ # 256 is used on purpose instead of 255 to avoid numerical differences
377
+ # see https://github.com/huggingface/transformers/pull/38540#discussion_r2127165652
378
+ image = image.float() / 256
379
+ image = F.resize(image, new_size, interpolation=interpolation, antialias=antialias)
380
+ image = image * 256
381
+ # torch.where is used on purpose instead of torch.clamp to avoid bug in torch.compile
382
+ # see https://github.com/huggingface/transformers/pull/38540#discussion_r2126888471
383
+ image = torch.where(image > 255, 255, image)
384
+ image = torch.where(image < 0, 0, image)
385
+ image = image.round().to(torch.uint8)
386
+ else:
387
+ image = F.resize(image, new_size, interpolation=interpolation, antialias=antialias)
388
+ return image
389
+
390
+ def rescale(
391
+ self,
392
+ image: "torch.Tensor",
393
+ scale: float,
394
+ **kwargs,
395
+ ) -> "torch.Tensor":
396
+ """
397
+ Rescale an image by a scale factor. image = image * scale.
398
+
399
+ Args:
400
+ image (`torch.Tensor`):
401
+ Image to rescale.
402
+ scale (`float`):
403
+ The scaling factor to rescale pixel values by.
404
+
405
+ Returns:
406
+ `torch.Tensor`: The rescaled image.
407
+ """
408
+ return image * scale
409
+
410
+ def normalize(
411
+ self,
412
+ image: "torch.Tensor",
413
+ mean: Union[float, Iterable[float]],
414
+ std: Union[float, Iterable[float]],
415
+ **kwargs,
416
+ ) -> "torch.Tensor":
417
+ """
418
+ Normalize an image. image = (image - image_mean) / image_std.
419
+
420
+ Args:
421
+ image (`torch.Tensor`):
422
+ Image to normalize.
423
+ mean (`torch.Tensor`, `float` or `Iterable[float]`):
424
+ Image mean to use for normalization.
425
+ std (`torch.Tensor`, `float` or `Iterable[float]`):
426
+ Image standard deviation to use for normalization.
427
+
428
+ Returns:
429
+ `torch.Tensor`: The normalized image.
430
+ """
431
+ return F.normalize(image, mean, std)
432
+
433
+ @lru_cache(maxsize=10)
434
+ def _fuse_mean_std_and_rescale_factor(
435
+ self,
436
+ do_normalize: Optional[bool] = None,
437
+ image_mean: Optional[Union[float, list[float]]] = None,
438
+ image_std: Optional[Union[float, list[float]]] = None,
439
+ do_rescale: Optional[bool] = None,
440
+ rescale_factor: Optional[float] = None,
441
+ device: Optional["torch.device"] = None,
442
+ ) -> tuple:
443
+ if do_rescale and do_normalize:
444
+ # Fused rescale and normalize
445
+ image_mean = torch.tensor(image_mean, device=device) * (1.0 / rescale_factor)
446
+ image_std = torch.tensor(image_std, device=device) * (1.0 / rescale_factor)
447
+ do_rescale = False
448
+ return image_mean, image_std, do_rescale
449
+
450
+ def rescale_and_normalize(
451
+ self,
452
+ images: "torch.Tensor",
453
+ do_rescale: bool,
454
+ rescale_factor: float,
455
+ do_normalize: bool,
456
+ image_mean: Union[float, list[float]],
457
+ image_std: Union[float, list[float]],
458
+ ) -> "torch.Tensor":
459
+ """
460
+ Rescale and normalize images.
461
+ """
462
+ image_mean, image_std, do_rescale = self._fuse_mean_std_and_rescale_factor(
463
+ do_normalize=do_normalize,
464
+ image_mean=image_mean,
465
+ image_std=image_std,
466
+ do_rescale=do_rescale,
467
+ rescale_factor=rescale_factor,
468
+ device=images.device,
469
+ )
470
+ # if/elif as we use fused rescale and normalize if both are set to True
471
+ if do_normalize:
472
+ images = self.normalize(images.to(dtype=torch.float32), image_mean, image_std)
473
+ elif do_rescale:
474
+ images = self.rescale(images, rescale_factor)
475
+
476
+ return images
477
+
478
+ def center_crop(
479
+ self,
480
+ image: "torch.Tensor",
481
+ size: SizeDict,
482
+ **kwargs,
483
+ ) -> "torch.Tensor":
484
+ """
485
+ Note: override torchvision's center_crop to have the same behavior as the slow processor.
486
+ Center crop an image to `(size["height"], size["width"])`. If the input size is smaller than `crop_size` along
487
+ any edge, the image is padded with 0's and then center cropped.
488
+
489
+ Args:
490
+ image (`"torch.Tensor"`):
491
+ Image to center crop.
492
+ size (`dict[str, int]`):
493
+ Size of the output image.
494
+
495
+ Returns:
496
+ `torch.Tensor`: The center cropped image.
497
+ """
498
+ if size.height is None or size.width is None:
499
+ raise ValueError(f"The size dictionary must have keys 'height' and 'width'. Got {size.keys()}")
500
+ image_height, image_width = image.shape[-2:]
501
+ crop_height, crop_width = size.height, size.width
502
+
503
+ if crop_width > image_width or crop_height > image_height:
504
+ padding_ltrb = [
505
+ (crop_width - image_width) // 2 if crop_width > image_width else 0,
506
+ (crop_height - image_height) // 2 if crop_height > image_height else 0,
507
+ (crop_width - image_width + 1) // 2 if crop_width > image_width else 0,
508
+ (crop_height - image_height + 1) // 2 if crop_height > image_height else 0,
509
+ ]
510
+ image = F.pad(image, padding_ltrb, fill=0) # PIL uses fill value 0
511
+ image_height, image_width = image.shape[-2:]
512
+ if crop_width == image_width and crop_height == image_height:
513
+ return image
514
+
515
+ crop_top = int((image_height - crop_height) / 2.0)
516
+ crop_left = int((image_width - crop_width) / 2.0)
517
+ return F.crop(image, crop_top, crop_left, crop_height, crop_width)
518
+
519
+ def convert_to_rgb(
520
+ self,
521
+ image: ImageInput,
522
+ ) -> ImageInput:
523
+ """
524
+ Converts an image to RGB format. Only converts if the image is of type PIL.Image.Image, otherwise returns the image
525
+ as is.
526
+ Args:
527
+ image (ImageInput):
528
+ The image to convert.
529
+
530
+ Returns:
531
+ ImageInput: The converted image.
532
+ """
533
+ return convert_to_rgb(image)
534
+
535
+ def filter_out_unused_kwargs(self, kwargs: dict):
536
+ """
537
+ Filter out the unused kwargs from the kwargs dictionary.
538
+ """
539
+ if self.unused_kwargs is None:
540
+ return kwargs
541
+
542
+ for kwarg_name in self.unused_kwargs:
543
+ if kwarg_name in kwargs:
544
+ logger.warning_once(f"This processor does not use the `{kwarg_name}` parameter. It will be ignored.")
545
+ kwargs.pop(kwarg_name)
546
+ return kwargs
547
+
548
+ def _prepare_images_structure(
549
+ self,
550
+ images: ImageInput,
551
+ expected_ndims: int = 3,
552
+ ) -> ImageInput:
553
+ """
554
+ Prepare the images structure for processing.
555
+
556
+ Args:
557
+ images (`ImageInput`):
558
+ The input images to process.
559
+
560
+ Returns:
561
+ `ImageInput`: The images with a valid nesting.
562
+ """
563
+ # Checks for `str` in case of URL/local path and optionally loads images
564
+ images = self.fetch_images(images)
565
+ return make_flat_list_of_images(images, expected_ndims=expected_ndims)
566
+
567
+ def _process_image(
568
+ self,
569
+ image: ImageInput,
570
+ do_convert_rgb: Optional[bool] = None,
571
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
572
+ device: Optional["torch.device"] = None,
573
+ ) -> "torch.Tensor":
574
+ image_type = get_image_type(image)
575
+ if image_type not in [ImageType.PIL, ImageType.TORCH, ImageType.NUMPY]:
576
+ raise ValueError(f"Unsupported input image type {image_type}")
577
+
578
+ if do_convert_rgb:
579
+ image = self.convert_to_rgb(image)
580
+
581
+ if image_type == ImageType.PIL:
582
+ image = F.pil_to_tensor(image)
583
+ elif image_type == ImageType.NUMPY:
584
+ # not using F.to_tensor as it doesn't handle (C, H, W) numpy arrays
585
+ image = torch.from_numpy(image).contiguous()
586
+
587
+ # If the image is 2D, we need to unsqueeze it to add a channel dimension for processing
588
+ if image.ndim == 2:
589
+ image = image.unsqueeze(0)
590
+
591
+ # Infer the channel dimension format if not provided
592
+ if input_data_format is None:
593
+ input_data_format = infer_channel_dimension_format(image)
594
+
595
+ if input_data_format == ChannelDimension.LAST:
596
+ # We force the channel dimension to be first for torch tensors as this is what torchvision expects.
597
+ image = image.permute(2, 0, 1).contiguous()
598
+
599
+ # Now that we have torch tensors, we can move them to the right device
600
+ if device is not None:
601
+ image = image.to(device)
602
+
603
+ return image
604
+
605
+ def _prepare_image_like_inputs(
606
+ self,
607
+ images: ImageInput,
608
+ do_convert_rgb: Optional[bool] = None,
609
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
610
+ device: Optional["torch.device"] = None,
611
+ expected_ndims: int = 3,
612
+ ) -> list["torch.Tensor"]:
613
+ """
614
+ Prepare image-like inputs for processing.
615
+
616
+ Args:
617
+ images (`ImageInput`):
618
+ The image-like inputs to process.
619
+ do_convert_rgb (`bool`, *optional*):
620
+ Whether to convert the images to RGB.
621
+ input_data_format (`str` or `ChannelDimension`, *optional*):
622
+ The input data format of the images.
623
+ device (`torch.device`, *optional*):
624
+ The device to put the processed images on.
625
+ expected_ndims (`int`, *optional*):
626
+ The expected number of dimensions for the images. (can be 2 for segmentation maps etc.)
627
+
628
+ Returns:
629
+ List[`torch.Tensor`]: The processed images.
630
+ """
631
+
632
+ # Get structured images (potentially nested)
633
+ images = self._prepare_images_structure(images, expected_ndims=expected_ndims)
634
+
635
+ process_image_partial = partial(
636
+ self._process_image, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device
637
+ )
638
+
639
+ # Check if we have nested structure, assuming the nesting is consistent
640
+ has_nested_structure = len(images) > 0 and isinstance(images[0], (list, tuple))
641
+
642
+ if has_nested_structure:
643
+ processed_images = [[process_image_partial(img) for img in nested_list] for nested_list in images]
644
+ else:
645
+ processed_images = [process_image_partial(img) for img in images]
646
+
647
+ return processed_images
648
+
649
+ def _further_process_kwargs(
650
+ self,
651
+ size: Optional[SizeDict] = None,
652
+ crop_size: Optional[SizeDict] = None,
653
+ pad_size: Optional[SizeDict] = None,
654
+ default_to_square: Optional[bool] = None,
655
+ image_mean: Optional[Union[float, list[float]]] = None,
656
+ image_std: Optional[Union[float, list[float]]] = None,
657
+ data_format: Optional[ChannelDimension] = None,
658
+ **kwargs,
659
+ ) -> dict:
660
+ """
661
+ Update kwargs that need further processing before being validated
662
+ Can be overridden by subclasses to customize the processing of kwargs.
663
+ """
664
+ if kwargs is None:
665
+ kwargs = {}
666
+ if size is not None:
667
+ size = SizeDict(**get_size_dict(size=size, default_to_square=default_to_square))
668
+ if crop_size is not None:
669
+ crop_size = SizeDict(**get_size_dict(crop_size, param_name="crop_size"))
670
+ if pad_size is not None:
671
+ pad_size = SizeDict(**get_size_dict(size=pad_size, param_name="pad_size"))
672
+ if isinstance(image_mean, list):
673
+ image_mean = tuple(image_mean)
674
+ if isinstance(image_std, list):
675
+ image_std = tuple(image_std)
676
+ if data_format is None:
677
+ data_format = ChannelDimension.FIRST
678
+
679
+ kwargs["size"] = size
680
+ kwargs["crop_size"] = crop_size
681
+ kwargs["pad_size"] = pad_size
682
+ kwargs["image_mean"] = image_mean
683
+ kwargs["image_std"] = image_std
684
+ kwargs["data_format"] = data_format
685
+
686
+ # torch resize uses interpolation instead of resample
687
+ # Check if resample is an int before checking if it's an instance of PILImageResampling
688
+ # because if pillow < 9.1.0, resample is an int and PILImageResampling is a module.
689
+ # Checking PILImageResampling will fail with error `TypeError: isinstance() arg 2 must be a type or tuple of types`.
690
+ resample = kwargs.pop("resample")
691
+ kwargs["interpolation"] = (
692
+ pil_torch_interpolation_mapping[resample] if isinstance(resample, (PILImageResampling, int)) else resample
693
+ )
694
+
695
+ return kwargs
696
+
697
+ def _validate_preprocess_kwargs(
698
+ self,
699
+ do_rescale: Optional[bool] = None,
700
+ rescale_factor: Optional[float] = None,
701
+ do_normalize: Optional[bool] = None,
702
+ image_mean: Optional[Union[float, tuple[float]]] = None,
703
+ image_std: Optional[Union[float, tuple[float]]] = None,
704
+ do_resize: Optional[bool] = None,
705
+ size: Optional[SizeDict] = None,
706
+ do_center_crop: Optional[bool] = None,
707
+ crop_size: Optional[SizeDict] = None,
708
+ interpolation: Optional["F.InterpolationMode"] = None,
709
+ return_tensors: Optional[Union[str, TensorType]] = None,
710
+ data_format: Optional[ChannelDimension] = None,
711
+ **kwargs,
712
+ ):
713
+ """
714
+ validate the kwargs for the preprocess method.
715
+ """
716
+ validate_fast_preprocess_arguments(
717
+ do_rescale=do_rescale,
718
+ rescale_factor=rescale_factor,
719
+ do_normalize=do_normalize,
720
+ image_mean=image_mean,
721
+ image_std=image_std,
722
+ do_resize=do_resize,
723
+ size=size,
724
+ do_center_crop=do_center_crop,
725
+ crop_size=crop_size,
726
+ interpolation=interpolation,
727
+ return_tensors=return_tensors,
728
+ data_format=data_format,
729
+ )
730
+
731
+ def __call__(self, images: ImageInput, *args, **kwargs: Unpack[DefaultFastImageProcessorKwargs]) -> BatchFeature:
732
+ return self.preprocess(images, *args, **kwargs)
733
+
734
+ @auto_docstring
735
+ def preprocess(self, images: ImageInput, *args, **kwargs: Unpack[DefaultFastImageProcessorKwargs]) -> BatchFeature:
736
+ # args are not validated, but their order in the `preprocess` and `_preprocess` signatures must be the same
737
+ validate_kwargs(captured_kwargs=kwargs.keys(), valid_processor_keys=self._valid_kwargs_names)
738
+ # Set default kwargs from self. This ensures that if a kwarg is not provided
739
+ # by the user, it gets its default value from the instance, or is set to None.
740
+ for kwarg_name in self._valid_kwargs_names:
741
+ kwargs.setdefault(kwarg_name, getattr(self, kwarg_name, None))
742
+
743
+ # Extract parameters that are only used for preparing the input images
744
+ do_convert_rgb = kwargs.pop("do_convert_rgb")
745
+ input_data_format = kwargs.pop("input_data_format")
746
+ device = kwargs.pop("device")
747
+
748
+ # Update kwargs that need further processing before being validated
749
+ kwargs = self._further_process_kwargs(**kwargs)
750
+
751
+ # Validate kwargs
752
+ self._validate_preprocess_kwargs(**kwargs)
753
+
754
+ # Pop kwargs that are not needed in _preprocess
755
+ kwargs.pop("data_format")
756
+
757
+ return self._preprocess_image_like_inputs(
758
+ images, *args, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device, **kwargs
759
+ )
760
+
761
+ def _preprocess_image_like_inputs(
762
+ self,
763
+ images: ImageInput,
764
+ *args,
765
+ do_convert_rgb: bool,
766
+ input_data_format: ChannelDimension,
767
+ device: Optional[Union[str, "torch.device"]] = None,
768
+ **kwargs: Unpack[DefaultFastImageProcessorKwargs],
769
+ ) -> BatchFeature:
770
+ """
771
+ Preprocess image-like inputs.
772
+ To be overridden by subclasses when image-like inputs other than images should be processed.
773
+ It can be used for segmentation maps, depth maps, etc.
774
+ """
775
+ # Prepare input images
776
+ images = self._prepare_image_like_inputs(
777
+ images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device
778
+ )
779
+ return self._preprocess(images, *args, **kwargs)
780
+
781
+ def _preprocess(
782
+ self,
783
+ images: list["torch.Tensor"],
784
+ do_resize: bool,
785
+ size: SizeDict,
786
+ interpolation: Optional["F.InterpolationMode"],
787
+ do_center_crop: bool,
788
+ crop_size: SizeDict,
789
+ do_rescale: bool,
790
+ rescale_factor: float,
791
+ do_normalize: bool,
792
+ image_mean: Optional[Union[float, list[float]]],
793
+ image_std: Optional[Union[float, list[float]]],
794
+ do_pad: Optional[bool],
795
+ pad_size: Optional[SizeDict],
796
+ disable_grouping: Optional[bool],
797
+ return_tensors: Optional[Union[str, TensorType]],
798
+ **kwargs,
799
+ ) -> BatchFeature:
800
+ # Group images by size for batched resizing
801
+ grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
802
+ resized_images_grouped = {}
803
+ for shape, stacked_images in grouped_images.items():
804
+ if do_resize:
805
+ stacked_images = self.resize(image=stacked_images, size=size, interpolation=interpolation)
806
+ resized_images_grouped[shape] = stacked_images
807
+ resized_images = reorder_images(resized_images_grouped, grouped_images_index)
808
+
809
+ # Group images by size for further processing
810
+ # Needed in case do_resize is False, or resize returns images with different sizes
811
+ grouped_images, grouped_images_index = group_images_by_shape(resized_images, disable_grouping=disable_grouping)
812
+ processed_images_grouped = {}
813
+ for shape, stacked_images in grouped_images.items():
814
+ if do_center_crop:
815
+ stacked_images = self.center_crop(stacked_images, crop_size)
816
+ # Fused rescale and normalize
817
+ stacked_images = self.rescale_and_normalize(
818
+ stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
819
+ )
820
+ processed_images_grouped[shape] = stacked_images
821
+ processed_images = reorder_images(processed_images_grouped, grouped_images_index)
822
+
823
+ if do_pad:
824
+ processed_images = self.pad(processed_images, pad_size=pad_size, disable_grouping=disable_grouping)
825
+
826
+ processed_images = torch.stack(processed_images, dim=0) if return_tensors else processed_images
827
+ return BatchFeature(data={"pixel_values": processed_images}, tensor_type=return_tensors)
828
+
829
+ def to_dict(self):
830
+ encoder_dict = super().to_dict()
831
+ encoder_dict.pop("_valid_processor_keys", None)
832
+ encoder_dict.pop("_valid_kwargs_names", None)
833
+ return encoder_dict
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_transforms.py ADDED
@@ -0,0 +1,977 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from collections import defaultdict
16
+ from collections.abc import Collection, Iterable
17
+ from math import ceil
18
+ from typing import Optional, Union
19
+
20
+ import numpy as np
21
+
22
+ from .image_utils import (
23
+ ChannelDimension,
24
+ ImageInput,
25
+ get_channel_dimension_axis,
26
+ get_image_size,
27
+ infer_channel_dimension_format,
28
+ )
29
+ from .utils import ExplicitEnum, TensorType, is_jax_tensor, is_tf_tensor, is_torch_tensor
30
+ from .utils.import_utils import (
31
+ is_flax_available,
32
+ is_tf_available,
33
+ is_torch_available,
34
+ is_vision_available,
35
+ requires_backends,
36
+ )
37
+
38
+
39
+ if is_vision_available():
40
+ import PIL
41
+
42
+ from .image_utils import PILImageResampling
43
+
44
+ if is_torch_available():
45
+ import torch
46
+
47
+ if is_tf_available():
48
+ import tensorflow as tf
49
+
50
+ if is_flax_available():
51
+ import jax.numpy as jnp
52
+
53
+
54
+ def to_channel_dimension_format(
55
+ image: np.ndarray,
56
+ channel_dim: Union[ChannelDimension, str],
57
+ input_channel_dim: Optional[Union[ChannelDimension, str]] = None,
58
+ ) -> np.ndarray:
59
+ """
60
+ Converts `image` to the channel dimension format specified by `channel_dim`. The input
61
+ can have arbitrary number of leading dimensions. Only last three dimension will be permuted
62
+ to format the `image`.
63
+
64
+ Args:
65
+ image (`numpy.ndarray`):
66
+ The image to have its channel dimension set.
67
+ channel_dim (`ChannelDimension`):
68
+ The channel dimension format to use.
69
+ input_channel_dim (`ChannelDimension`, *optional*):
70
+ The channel dimension format of the input image. If not provided, it will be inferred from the input image.
71
+
72
+ Returns:
73
+ `np.ndarray`: The image with the channel dimension set to `channel_dim`.
74
+ """
75
+ if not isinstance(image, np.ndarray):
76
+ raise TypeError(f"Input image must be of type np.ndarray, got {type(image)}")
77
+
78
+ if input_channel_dim is None:
79
+ input_channel_dim = infer_channel_dimension_format(image)
80
+
81
+ target_channel_dim = ChannelDimension(channel_dim)
82
+ if input_channel_dim == target_channel_dim:
83
+ return image
84
+
85
+ if target_channel_dim == ChannelDimension.FIRST:
86
+ axes = list(range(image.ndim - 3)) + [image.ndim - 1, image.ndim - 3, image.ndim - 2]
87
+ image = image.transpose(axes)
88
+ elif target_channel_dim == ChannelDimension.LAST:
89
+ axes = list(range(image.ndim - 3)) + [image.ndim - 2, image.ndim - 1, image.ndim - 3]
90
+ image = image.transpose(axes)
91
+ else:
92
+ raise ValueError(f"Unsupported channel dimension format: {channel_dim}")
93
+
94
+ return image
95
+
96
+
97
+ def rescale(
98
+ image: np.ndarray,
99
+ scale: float,
100
+ data_format: Optional[ChannelDimension] = None,
101
+ dtype: np.dtype = np.float32,
102
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
103
+ ) -> np.ndarray:
104
+ """
105
+ Rescales `image` by `scale`.
106
+
107
+ Args:
108
+ image (`np.ndarray`):
109
+ The image to rescale.
110
+ scale (`float`):
111
+ The scale to use for rescaling the image.
112
+ data_format (`ChannelDimension`, *optional*):
113
+ The channel dimension format of the image. If not provided, it will be the same as the input image.
114
+ dtype (`np.dtype`, *optional*, defaults to `np.float32`):
115
+ The dtype of the output image. Defaults to `np.float32`. Used for backwards compatibility with feature
116
+ extractors.
117
+ input_data_format (`ChannelDimension`, *optional*):
118
+ The channel dimension format of the input image. If not provided, it will be inferred from the input image.
119
+
120
+ Returns:
121
+ `np.ndarray`: The rescaled image.
122
+ """
123
+ if not isinstance(image, np.ndarray):
124
+ raise TypeError(f"Input image must be of type np.ndarray, got {type(image)}")
125
+
126
+ rescaled_image = image.astype(np.float64) * scale # Numpy type promotion has changed, so always upcast first
127
+ if data_format is not None:
128
+ rescaled_image = to_channel_dimension_format(rescaled_image, data_format, input_data_format)
129
+
130
+ rescaled_image = rescaled_image.astype(dtype) # Finally downcast to the desired dtype at the end
131
+
132
+ return rescaled_image
133
+
134
+
135
+ def _rescale_for_pil_conversion(image):
136
+ """
137
+ Detects whether or not the image needs to be rescaled before being converted to a PIL image.
138
+
139
+ The assumption is that if the image is of type `np.float` and all values are between 0 and 1, it needs to be
140
+ rescaled.
141
+ """
142
+ if image.dtype == np.uint8:
143
+ do_rescale = False
144
+ elif np.allclose(image, image.astype(int)):
145
+ if np.all(0 <= image) and np.all(image <= 255):
146
+ do_rescale = False
147
+ else:
148
+ raise ValueError(
149
+ "The image to be converted to a PIL image contains values outside the range [0, 255], "
150
+ f"got [{image.min()}, {image.max()}] which cannot be converted to uint8."
151
+ )
152
+ elif np.all(0 <= image) and np.all(image <= 1):
153
+ do_rescale = True
154
+ else:
155
+ raise ValueError(
156
+ "The image to be converted to a PIL image contains values outside the range [0, 1], "
157
+ f"got [{image.min()}, {image.max()}] which cannot be converted to uint8."
158
+ )
159
+ return do_rescale
160
+
161
+
162
+ def to_pil_image(
163
+ image: Union[np.ndarray, "PIL.Image.Image", "torch.Tensor", "tf.Tensor", "jnp.ndarray"],
164
+ do_rescale: Optional[bool] = None,
165
+ image_mode: Optional[str] = None,
166
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
167
+ ) -> "PIL.Image.Image":
168
+ """
169
+ Converts `image` to a PIL Image. Optionally rescales it and puts the channel dimension back as the last axis if
170
+ needed.
171
+
172
+ Args:
173
+ image (`PIL.Image.Image` or `numpy.ndarray` or `torch.Tensor` or `tf.Tensor`):
174
+ The image to convert to the `PIL.Image` format.
175
+ do_rescale (`bool`, *optional*):
176
+ Whether or not to apply the scaling factor (to make pixel values integers between 0 and 255). Will default
177
+ to `True` if the image type is a floating type and casting to `int` would result in a loss of precision,
178
+ and `False` otherwise.
179
+ image_mode (`str`, *optional*):
180
+ The mode to use for the PIL image. If unset, will use the default mode for the input image type.
181
+ input_data_format (`ChannelDimension`, *optional*):
182
+ The channel dimension format of the input image. If unset, will use the inferred format from the input.
183
+
184
+ Returns:
185
+ `PIL.Image.Image`: The converted image.
186
+ """
187
+ requires_backends(to_pil_image, ["vision"])
188
+
189
+ if isinstance(image, PIL.Image.Image):
190
+ return image
191
+
192
+ # Convert all tensors to numpy arrays before converting to PIL image
193
+ if is_torch_tensor(image) or is_tf_tensor(image):
194
+ image = image.numpy()
195
+ elif is_jax_tensor(image):
196
+ image = np.array(image)
197
+ elif not isinstance(image, np.ndarray):
198
+ raise ValueError(f"Input image type not supported: {type(image)}")
199
+
200
+ # If the channel has been moved to first dim, we put it back at the end.
201
+ image = to_channel_dimension_format(image, ChannelDimension.LAST, input_data_format)
202
+
203
+ # If there is a single channel, we squeeze it, as otherwise PIL can't handle it.
204
+ image = np.squeeze(image, axis=-1) if image.shape[-1] == 1 else image
205
+
206
+ # PIL.Image can only store uint8 values so we rescale the image to be between 0 and 255 if needed.
207
+ do_rescale = _rescale_for_pil_conversion(image) if do_rescale is None else do_rescale
208
+
209
+ if do_rescale:
210
+ image = rescale(image, 255)
211
+
212
+ image = image.astype(np.uint8)
213
+ return PIL.Image.fromarray(image, mode=image_mode)
214
+
215
+
216
+ def get_size_with_aspect_ratio(image_size, size, max_size=None) -> tuple[int, int]:
217
+ """
218
+ Computes the output image size given the input image size and the desired output size.
219
+
220
+ Args:
221
+ image_size (`tuple[int, int]`):
222
+ The input image size.
223
+ size (`int`):
224
+ The desired output size.
225
+ max_size (`int`, *optional*):
226
+ The maximum allowed output size.
227
+ """
228
+ height, width = image_size
229
+ raw_size = None
230
+ if max_size is not None:
231
+ min_original_size = float(min((height, width)))
232
+ max_original_size = float(max((height, width)))
233
+ if max_original_size / min_original_size * size > max_size:
234
+ raw_size = max_size * min_original_size / max_original_size
235
+ size = int(round(raw_size))
236
+
237
+ if (height <= width and height == size) or (width <= height and width == size):
238
+ oh, ow = height, width
239
+ elif width < height:
240
+ ow = size
241
+ if max_size is not None and raw_size is not None:
242
+ oh = int(raw_size * height / width)
243
+ else:
244
+ oh = int(size * height / width)
245
+ else:
246
+ oh = size
247
+ if max_size is not None and raw_size is not None:
248
+ ow = int(raw_size * width / height)
249
+ else:
250
+ ow = int(size * width / height)
251
+
252
+ return (oh, ow)
253
+
254
+
255
+ # Logic adapted from torchvision resizing logic: https://github.com/pytorch/vision/blob/511924c1ced4ce0461197e5caa64ce5b9e558aab/torchvision/transforms/functional.py#L366
256
+ def get_resize_output_image_size(
257
+ input_image: np.ndarray,
258
+ size: Union[int, tuple[int, int], list[int], tuple[int, ...]],
259
+ default_to_square: bool = True,
260
+ max_size: Optional[int] = None,
261
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
262
+ ) -> tuple:
263
+ """
264
+ Find the target (height, width) dimension of the output image after resizing given the input image and the desired
265
+ size.
266
+
267
+ Args:
268
+ input_image (`np.ndarray`):
269
+ The image to resize.
270
+ size (`int` or `tuple[int, int]` or list[int] or `tuple[int]`):
271
+ The size to use for resizing the image. If `size` is a sequence like (h, w), output size will be matched to
272
+ this.
273
+
274
+ If `size` is an int and `default_to_square` is `True`, then image will be resized to (size, size). If
275
+ `size` is an int and `default_to_square` is `False`, then smaller edge of the image will be matched to this
276
+ number. i.e, if height > width, then image will be rescaled to (size * height / width, size).
277
+ default_to_square (`bool`, *optional*, defaults to `True`):
278
+ How to convert `size` when it is a single int. If set to `True`, the `size` will be converted to a square
279
+ (`size`,`size`). If set to `False`, will replicate
280
+ [`torchvision.transforms.Resize`](https://pytorch.org/vision/stable/transforms.html#torchvision.transforms.Resize)
281
+ with support for resizing only the smallest edge and providing an optional `max_size`.
282
+ max_size (`int`, *optional*):
283
+ The maximum allowed for the longer edge of the resized image: if the longer edge of the image is greater
284
+ than `max_size` after being resized according to `size`, then the image is resized again so that the longer
285
+ edge is equal to `max_size`. As a result, `size` might be overruled, i.e the smaller edge may be shorter
286
+ than `size`. Only used if `default_to_square` is `False`.
287
+ input_data_format (`ChannelDimension`, *optional*):
288
+ The channel dimension format of the input image. If unset, will use the inferred format from the input.
289
+
290
+ Returns:
291
+ `tuple`: The target (height, width) dimension of the output image after resizing.
292
+ """
293
+ if isinstance(size, (tuple, list)):
294
+ if len(size) == 2:
295
+ return tuple(size)
296
+ elif len(size) == 1:
297
+ # Perform same logic as if size was an int
298
+ size = size[0]
299
+ else:
300
+ raise ValueError("size must have 1 or 2 elements if it is a list or tuple")
301
+
302
+ if default_to_square:
303
+ return (size, size)
304
+
305
+ height, width = get_image_size(input_image, input_data_format)
306
+ short, long = (width, height) if width <= height else (height, width)
307
+ requested_new_short = size
308
+
309
+ new_short, new_long = requested_new_short, int(requested_new_short * long / short)
310
+
311
+ if max_size is not None:
312
+ if max_size <= requested_new_short:
313
+ raise ValueError(
314
+ f"max_size = {max_size} must be strictly greater than the requested "
315
+ f"size for the smaller edge size = {size}"
316
+ )
317
+ if new_long > max_size:
318
+ new_short, new_long = int(max_size * new_short / new_long), max_size
319
+
320
+ return (new_long, new_short) if width <= height else (new_short, new_long)
321
+
322
+
323
+ def resize(
324
+ image: np.ndarray,
325
+ size: tuple[int, int],
326
+ resample: Optional["PILImageResampling"] = None,
327
+ reducing_gap: Optional[int] = None,
328
+ data_format: Optional[ChannelDimension] = None,
329
+ return_numpy: bool = True,
330
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
331
+ ) -> np.ndarray:
332
+ """
333
+ Resizes `image` to `(height, width)` specified by `size` using the PIL library.
334
+
335
+ Args:
336
+ image (`np.ndarray`):
337
+ The image to resize.
338
+ size (`tuple[int, int]`):
339
+ The size to use for resizing the image.
340
+ resample (`int`, *optional*, defaults to `PILImageResampling.BILINEAR`):
341
+ The filter to user for resampling.
342
+ reducing_gap (`int`, *optional*):
343
+ Apply optimization by resizing the image in two steps. The bigger `reducing_gap`, the closer the result to
344
+ the fair resampling. See corresponding Pillow documentation for more details.
345
+ data_format (`ChannelDimension`, *optional*):
346
+ The channel dimension format of the output image. If unset, will use the inferred format from the input.
347
+ return_numpy (`bool`, *optional*, defaults to `True`):
348
+ Whether or not to return the resized image as a numpy array. If False a `PIL.Image.Image` object is
349
+ returned.
350
+ input_data_format (`ChannelDimension`, *optional*):
351
+ The channel dimension format of the input image. If unset, will use the inferred format from the input.
352
+
353
+ Returns:
354
+ `np.ndarray`: The resized image.
355
+ """
356
+ requires_backends(resize, ["vision"])
357
+
358
+ resample = resample if resample is not None else PILImageResampling.BILINEAR
359
+
360
+ if not len(size) == 2:
361
+ raise ValueError("size must have 2 elements")
362
+
363
+ # For all transformations, we want to keep the same data format as the input image unless otherwise specified.
364
+ # The resized image from PIL will always have channels last, so find the input format first.
365
+ if input_data_format is None:
366
+ input_data_format = infer_channel_dimension_format(image)
367
+ data_format = input_data_format if data_format is None else data_format
368
+
369
+ # To maintain backwards compatibility with the resizing done in previous image feature extractors, we use
370
+ # the pillow library to resize the image and then convert back to numpy
371
+ do_rescale = False
372
+ if not isinstance(image, PIL.Image.Image):
373
+ do_rescale = _rescale_for_pil_conversion(image)
374
+ image = to_pil_image(image, do_rescale=do_rescale, input_data_format=input_data_format)
375
+ height, width = size
376
+ # PIL images are in the format (width, height)
377
+ resized_image = image.resize((width, height), resample=resample, reducing_gap=reducing_gap)
378
+
379
+ if return_numpy:
380
+ resized_image = np.array(resized_image)
381
+ # If the input image channel dimension was of size 1, then it is dropped when converting to a PIL image
382
+ # so we need to add it back if necessary.
383
+ resized_image = np.expand_dims(resized_image, axis=-1) if resized_image.ndim == 2 else resized_image
384
+ # The image is always in channels last format after converting from a PIL image
385
+ resized_image = to_channel_dimension_format(
386
+ resized_image, data_format, input_channel_dim=ChannelDimension.LAST
387
+ )
388
+ # If an image was rescaled to be in the range [0, 255] before converting to a PIL image, then we need to
389
+ # rescale it back to the original range.
390
+ resized_image = rescale(resized_image, 1 / 255) if do_rescale else resized_image
391
+ return resized_image
392
+
393
+
394
+ def normalize(
395
+ image: np.ndarray,
396
+ mean: Union[float, Collection[float]],
397
+ std: Union[float, Collection[float]],
398
+ data_format: Optional[ChannelDimension] = None,
399
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
400
+ ) -> np.ndarray:
401
+ """
402
+ Normalizes `image` using the mean and standard deviation specified by `mean` and `std`.
403
+
404
+ image = (image - mean) / std
405
+
406
+ Args:
407
+ image (`np.ndarray`):
408
+ The image to normalize.
409
+ mean (`float` or `Collection[float]`):
410
+ The mean to use for normalization.
411
+ std (`float` or `Collection[float]`):
412
+ The standard deviation to use for normalization.
413
+ data_format (`ChannelDimension`, *optional*):
414
+ The channel dimension format of the output image. If unset, will use the inferred format from the input.
415
+ input_data_format (`ChannelDimension`, *optional*):
416
+ The channel dimension format of the input image. If unset, will use the inferred format from the input.
417
+ """
418
+ if not isinstance(image, np.ndarray):
419
+ raise TypeError("image must be a numpy array")
420
+
421
+ if input_data_format is None:
422
+ input_data_format = infer_channel_dimension_format(image)
423
+
424
+ channel_axis = get_channel_dimension_axis(image, input_data_format=input_data_format)
425
+ num_channels = image.shape[channel_axis]
426
+
427
+ # We cast to float32 to avoid errors that can occur when subtracting uint8 values.
428
+ # We preserve the original dtype if it is a float type to prevent upcasting float16.
429
+ if not np.issubdtype(image.dtype, np.floating):
430
+ image = image.astype(np.float32)
431
+
432
+ if isinstance(mean, Collection):
433
+ if len(mean) != num_channels:
434
+ raise ValueError(f"mean must have {num_channels} elements if it is an iterable, got {len(mean)}")
435
+ else:
436
+ mean = [mean] * num_channels
437
+ mean = np.array(mean, dtype=image.dtype)
438
+
439
+ if isinstance(std, Collection):
440
+ if len(std) != num_channels:
441
+ raise ValueError(f"std must have {num_channels} elements if it is an iterable, got {len(std)}")
442
+ else:
443
+ std = [std] * num_channels
444
+ std = np.array(std, dtype=image.dtype)
445
+
446
+ if input_data_format == ChannelDimension.LAST:
447
+ image = (image - mean) / std
448
+ else:
449
+ image = ((image.T - mean) / std).T
450
+
451
+ image = to_channel_dimension_format(image, data_format, input_data_format) if data_format is not None else image
452
+ return image
453
+
454
+
455
+ def center_crop(
456
+ image: np.ndarray,
457
+ size: tuple[int, int],
458
+ data_format: Optional[Union[str, ChannelDimension]] = None,
459
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
460
+ ) -> np.ndarray:
461
+ """
462
+ Crops the `image` to the specified `size` using a center crop. Note that if the image is too small to be cropped to
463
+ the size given, it will be padded (so the returned result will always be of size `size`).
464
+
465
+ Args:
466
+ image (`np.ndarray`):
467
+ The image to crop.
468
+ size (`tuple[int, int]`):
469
+ The target size for the cropped image.
470
+ data_format (`str` or `ChannelDimension`, *optional*):
471
+ The channel dimension format for the output image. Can be one of:
472
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
473
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
474
+ If unset, will use the inferred format of the input image.
475
+ input_data_format (`str` or `ChannelDimension`, *optional*):
476
+ The channel dimension format for the input image. Can be one of:
477
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
478
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
479
+ If unset, will use the inferred format of the input image.
480
+ Returns:
481
+ `np.ndarray`: The cropped image.
482
+ """
483
+ requires_backends(center_crop, ["vision"])
484
+
485
+ if not isinstance(image, np.ndarray):
486
+ raise TypeError(f"Input image must be of type np.ndarray, got {type(image)}")
487
+
488
+ if not isinstance(size, Iterable) or len(size) != 2:
489
+ raise ValueError("size must have 2 elements representing the height and width of the output image")
490
+
491
+ if input_data_format is None:
492
+ input_data_format = infer_channel_dimension_format(image)
493
+ output_data_format = data_format if data_format is not None else input_data_format
494
+
495
+ # We perform the crop in (C, H, W) format and then convert to the output format
496
+ image = to_channel_dimension_format(image, ChannelDimension.FIRST, input_data_format)
497
+
498
+ orig_height, orig_width = get_image_size(image, ChannelDimension.FIRST)
499
+ crop_height, crop_width = size
500
+ crop_height, crop_width = int(crop_height), int(crop_width)
501
+
502
+ # In case size is odd, (image_shape[0] + size[0]) // 2 won't give the proper result.
503
+ top = (orig_height - crop_height) // 2
504
+ bottom = top + crop_height
505
+ # In case size is odd, (image_shape[1] + size[1]) // 2 won't give the proper result.
506
+ left = (orig_width - crop_width) // 2
507
+ right = left + crop_width
508
+
509
+ # Check if cropped area is within image boundaries
510
+ if top >= 0 and bottom <= orig_height and left >= 0 and right <= orig_width:
511
+ image = image[..., top:bottom, left:right]
512
+ image = to_channel_dimension_format(image, output_data_format, ChannelDimension.FIRST)
513
+ return image
514
+
515
+ # Otherwise, we may need to pad if the image is too small. Oh joy...
516
+ new_height = max(crop_height, orig_height)
517
+ new_width = max(crop_width, orig_width)
518
+ new_shape = image.shape[:-2] + (new_height, new_width)
519
+ new_image = np.zeros_like(image, shape=new_shape)
520
+
521
+ # If the image is too small, pad it with zeros
522
+ top_pad = ceil((new_height - orig_height) / 2)
523
+ bottom_pad = top_pad + orig_height
524
+ left_pad = ceil((new_width - orig_width) / 2)
525
+ right_pad = left_pad + orig_width
526
+ new_image[..., top_pad:bottom_pad, left_pad:right_pad] = image
527
+
528
+ top += top_pad
529
+ bottom += top_pad
530
+ left += left_pad
531
+ right += left_pad
532
+
533
+ new_image = new_image[..., max(0, top) : min(new_height, bottom), max(0, left) : min(new_width, right)]
534
+ new_image = to_channel_dimension_format(new_image, output_data_format, ChannelDimension.FIRST)
535
+
536
+ return new_image
537
+
538
+
539
+ def _center_to_corners_format_torch(bboxes_center: "torch.Tensor") -> "torch.Tensor":
540
+ center_x, center_y, width, height = bboxes_center.unbind(-1)
541
+ bbox_corners = torch.stack(
542
+ # top left x, top left y, bottom right x, bottom right y
543
+ [(center_x - 0.5 * width), (center_y - 0.5 * height), (center_x + 0.5 * width), (center_y + 0.5 * height)],
544
+ dim=-1,
545
+ )
546
+ return bbox_corners
547
+
548
+
549
+ def _center_to_corners_format_numpy(bboxes_center: np.ndarray) -> np.ndarray:
550
+ center_x, center_y, width, height = bboxes_center.T
551
+ bboxes_corners = np.stack(
552
+ # top left x, top left y, bottom right x, bottom right y
553
+ [center_x - 0.5 * width, center_y - 0.5 * height, center_x + 0.5 * width, center_y + 0.5 * height],
554
+ axis=-1,
555
+ )
556
+ return bboxes_corners
557
+
558
+
559
+ def _center_to_corners_format_tf(bboxes_center: "tf.Tensor") -> "tf.Tensor":
560
+ center_x, center_y, width, height = tf.unstack(bboxes_center, axis=-1)
561
+ bboxes_corners = tf.stack(
562
+ # top left x, top left y, bottom right x, bottom right y
563
+ [center_x - 0.5 * width, center_y - 0.5 * height, center_x + 0.5 * width, center_y + 0.5 * height],
564
+ axis=-1,
565
+ )
566
+ return bboxes_corners
567
+
568
+
569
+ # 2 functions below inspired by https://github.com/facebookresearch/detr/blob/master/util/box_ops.py
570
+ def center_to_corners_format(bboxes_center: TensorType) -> TensorType:
571
+ """
572
+ Converts bounding boxes from center format to corners format.
573
+
574
+ center format: contains the coordinate for the center of the box and its width, height dimensions
575
+ (center_x, center_y, width, height)
576
+ corners format: contains the coordinates for the top-left and bottom-right corners of the box
577
+ (top_left_x, top_left_y, bottom_right_x, bottom_right_y)
578
+ """
579
+ # Function is used during model forward pass, so we use the input framework if possible, without
580
+ # converting to numpy
581
+ if is_torch_tensor(bboxes_center):
582
+ return _center_to_corners_format_torch(bboxes_center)
583
+ elif isinstance(bboxes_center, np.ndarray):
584
+ return _center_to_corners_format_numpy(bboxes_center)
585
+ elif is_tf_tensor(bboxes_center):
586
+ return _center_to_corners_format_tf(bboxes_center)
587
+
588
+ raise ValueError(f"Unsupported input type {type(bboxes_center)}")
589
+
590
+
591
+ def _corners_to_center_format_torch(bboxes_corners: "torch.Tensor") -> "torch.Tensor":
592
+ top_left_x, top_left_y, bottom_right_x, bottom_right_y = bboxes_corners.unbind(-1)
593
+ b = [
594
+ (top_left_x + bottom_right_x) / 2, # center x
595
+ (top_left_y + bottom_right_y) / 2, # center y
596
+ (bottom_right_x - top_left_x), # width
597
+ (bottom_right_y - top_left_y), # height
598
+ ]
599
+ return torch.stack(b, dim=-1)
600
+
601
+
602
+ def _corners_to_center_format_numpy(bboxes_corners: np.ndarray) -> np.ndarray:
603
+ top_left_x, top_left_y, bottom_right_x, bottom_right_y = bboxes_corners.T
604
+ bboxes_center = np.stack(
605
+ [
606
+ (top_left_x + bottom_right_x) / 2, # center x
607
+ (top_left_y + bottom_right_y) / 2, # center y
608
+ (bottom_right_x - top_left_x), # width
609
+ (bottom_right_y - top_left_y), # height
610
+ ],
611
+ axis=-1,
612
+ )
613
+ return bboxes_center
614
+
615
+
616
+ def _corners_to_center_format_tf(bboxes_corners: "tf.Tensor") -> "tf.Tensor":
617
+ top_left_x, top_left_y, bottom_right_x, bottom_right_y = tf.unstack(bboxes_corners, axis=-1)
618
+ bboxes_center = tf.stack(
619
+ [
620
+ (top_left_x + bottom_right_x) / 2, # center x
621
+ (top_left_y + bottom_right_y) / 2, # center y
622
+ (bottom_right_x - top_left_x), # width
623
+ (bottom_right_y - top_left_y), # height
624
+ ],
625
+ axis=-1,
626
+ )
627
+ return bboxes_center
628
+
629
+
630
+ def corners_to_center_format(bboxes_corners: TensorType) -> TensorType:
631
+ """
632
+ Converts bounding boxes from corners format to center format.
633
+
634
+ corners format: contains the coordinates for the top-left and bottom-right corners of the box
635
+ (top_left_x, top_left_y, bottom_right_x, bottom_right_y)
636
+ center format: contains the coordinate for the center of the box and its the width, height dimensions
637
+ (center_x, center_y, width, height)
638
+ """
639
+ # Inverse function accepts different input types so implemented here too
640
+ if is_torch_tensor(bboxes_corners):
641
+ return _corners_to_center_format_torch(bboxes_corners)
642
+ elif isinstance(bboxes_corners, np.ndarray):
643
+ return _corners_to_center_format_numpy(bboxes_corners)
644
+ elif is_tf_tensor(bboxes_corners):
645
+ return _corners_to_center_format_tf(bboxes_corners)
646
+
647
+ raise ValueError(f"Unsupported input type {type(bboxes_corners)}")
648
+
649
+
650
+ # 2 functions below copied from https://github.com/cocodataset/panopticapi/blob/master/panopticapi/utils.py
651
+ # Copyright (c) 2018, Alexander Kirillov
652
+ # All rights reserved.
653
+ def rgb_to_id(color):
654
+ """
655
+ Converts RGB color to unique ID.
656
+ """
657
+ if isinstance(color, np.ndarray) and len(color.shape) == 3:
658
+ if color.dtype == np.uint8:
659
+ color = color.astype(np.int32)
660
+ return color[:, :, 0] + 256 * color[:, :, 1] + 256 * 256 * color[:, :, 2]
661
+ return int(color[0] + 256 * color[1] + 256 * 256 * color[2])
662
+
663
+
664
+ def id_to_rgb(id_map):
665
+ """
666
+ Converts unique ID to RGB color.
667
+ """
668
+ if isinstance(id_map, np.ndarray):
669
+ id_map_copy = id_map.copy()
670
+ rgb_shape = tuple(list(id_map.shape) + [3])
671
+ rgb_map = np.zeros(rgb_shape, dtype=np.uint8)
672
+ for i in range(3):
673
+ rgb_map[..., i] = id_map_copy % 256
674
+ id_map_copy //= 256
675
+ return rgb_map
676
+ color = []
677
+ for _ in range(3):
678
+ color.append(id_map % 256)
679
+ id_map //= 256
680
+ return color
681
+
682
+
683
+ class PaddingMode(ExplicitEnum):
684
+ """
685
+ Enum class for the different padding modes to use when padding images.
686
+ """
687
+
688
+ CONSTANT = "constant"
689
+ REFLECT = "reflect"
690
+ REPLICATE = "replicate"
691
+ SYMMETRIC = "symmetric"
692
+
693
+
694
+ def pad(
695
+ image: np.ndarray,
696
+ padding: Union[int, tuple[int, int], Iterable[tuple[int, int]]],
697
+ mode: PaddingMode = PaddingMode.CONSTANT,
698
+ constant_values: Union[float, Iterable[float]] = 0.0,
699
+ data_format: Optional[Union[str, ChannelDimension]] = None,
700
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
701
+ ) -> np.ndarray:
702
+ """
703
+ Pads the `image` with the specified (height, width) `padding` and `mode`.
704
+
705
+ Args:
706
+ image (`np.ndarray`):
707
+ The image to pad.
708
+ padding (`int` or `tuple[int, int]` or `Iterable[tuple[int, int]]`):
709
+ Padding to apply to the edges of the height, width axes. Can be one of three formats:
710
+ - `((before_height, after_height), (before_width, after_width))` unique pad widths for each axis.
711
+ - `((before, after),)` yields same before and after pad for height and width.
712
+ - `(pad,)` or int is a shortcut for before = after = pad width for all axes.
713
+ mode (`PaddingMode`):
714
+ The padding mode to use. Can be one of:
715
+ - `"constant"`: pads with a constant value.
716
+ - `"reflect"`: pads with the reflection of the vector mirrored on the first and last values of the
717
+ vector along each axis.
718
+ - `"replicate"`: pads with the replication of the last value on the edge of the array along each axis.
719
+ - `"symmetric"`: pads with the reflection of the vector mirrored along the edge of the array.
720
+ constant_values (`float` or `Iterable[float]`, *optional*):
721
+ The value to use for the padding if `mode` is `"constant"`.
722
+ data_format (`str` or `ChannelDimension`, *optional*):
723
+ The channel dimension format for the output image. Can be one of:
724
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
725
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
726
+ If unset, will use same as the input image.
727
+ input_data_format (`str` or `ChannelDimension`, *optional*):
728
+ The channel dimension format for the input image. Can be one of:
729
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
730
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
731
+ If unset, will use the inferred format of the input image.
732
+
733
+ Returns:
734
+ `np.ndarray`: The padded image.
735
+
736
+ """
737
+ if input_data_format is None:
738
+ input_data_format = infer_channel_dimension_format(image)
739
+
740
+ def _expand_for_data_format(values):
741
+ """
742
+ Convert values to be in the format expected by np.pad based on the data format.
743
+ """
744
+ if isinstance(values, (int, float)):
745
+ values = ((values, values), (values, values))
746
+ elif isinstance(values, tuple) and len(values) == 1:
747
+ values = ((values[0], values[0]), (values[0], values[0]))
748
+ elif isinstance(values, tuple) and len(values) == 2 and isinstance(values[0], int):
749
+ values = (values, values)
750
+ elif isinstance(values, tuple) and len(values) == 2 and isinstance(values[0], tuple):
751
+ pass
752
+ else:
753
+ raise ValueError(f"Unsupported format: {values}")
754
+
755
+ # add 0 for channel dimension
756
+ values = ((0, 0), *values) if input_data_format == ChannelDimension.FIRST else (*values, (0, 0))
757
+
758
+ # Add additional padding if there's a batch dimension
759
+ values = ((0, 0), *values) if image.ndim == 4 else values
760
+ return values
761
+
762
+ padding = _expand_for_data_format(padding)
763
+
764
+ if mode == PaddingMode.CONSTANT:
765
+ constant_values = _expand_for_data_format(constant_values)
766
+ image = np.pad(image, padding, mode="constant", constant_values=constant_values)
767
+ elif mode == PaddingMode.REFLECT:
768
+ image = np.pad(image, padding, mode="reflect")
769
+ elif mode == PaddingMode.REPLICATE:
770
+ image = np.pad(image, padding, mode="edge")
771
+ elif mode == PaddingMode.SYMMETRIC:
772
+ image = np.pad(image, padding, mode="symmetric")
773
+ else:
774
+ raise ValueError(f"Invalid padding mode: {mode}")
775
+
776
+ image = to_channel_dimension_format(image, data_format, input_data_format) if data_format is not None else image
777
+ return image
778
+
779
+
780
+ # TODO (Amy): Accept 1/3/4 channel numpy array as input and return np.array as default
781
+ def convert_to_rgb(image: ImageInput) -> ImageInput:
782
+ """
783
+ Converts an image to RGB format. Only converts if the image is of type PIL.Image.Image, otherwise returns the image
784
+ as is.
785
+ Args:
786
+ image (Image):
787
+ The image to convert.
788
+ """
789
+ requires_backends(convert_to_rgb, ["vision"])
790
+
791
+ if not isinstance(image, PIL.Image.Image):
792
+ return image
793
+
794
+ if image.mode == "RGB":
795
+ return image
796
+
797
+ image = image.convert("RGB")
798
+ return image
799
+
800
+
801
+ def flip_channel_order(
802
+ image: np.ndarray,
803
+ data_format: Optional[ChannelDimension] = None,
804
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
805
+ ) -> np.ndarray:
806
+ """
807
+ Flips the channel order of the image.
808
+
809
+ If the image is in RGB format, it will be converted to BGR and vice versa.
810
+
811
+ Args:
812
+ image (`np.ndarray`):
813
+ The image to flip.
814
+ data_format (`ChannelDimension`, *optional*):
815
+ The channel dimension format for the output image. Can be one of:
816
+ - `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
817
+ - `ChannelDimension.LAST`: image in (height, width, num_channels) format.
818
+ If unset, will use same as the input image.
819
+ input_data_format (`ChannelDimension`, *optional*):
820
+ The channel dimension format for the input image. Can be one of:
821
+ - `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
822
+ - `ChannelDimension.LAST`: image in (height, width, num_channels) format.
823
+ If unset, will use the inferred format of the input image.
824
+ """
825
+ input_data_format = infer_channel_dimension_format(image) if input_data_format is None else input_data_format
826
+
827
+ if input_data_format == ChannelDimension.LAST:
828
+ image = image[..., ::-1]
829
+ elif input_data_format == ChannelDimension.FIRST:
830
+ image = image[::-1, ...]
831
+ else:
832
+ raise ValueError(f"Unsupported channel dimension: {input_data_format}")
833
+
834
+ if data_format is not None:
835
+ image = to_channel_dimension_format(image, data_format, input_channel_dim=input_data_format)
836
+ return image
837
+
838
+
839
+ def _cast_tensor_to_float(x):
840
+ if x.is_floating_point():
841
+ return x
842
+ return x.float()
843
+
844
+
845
+ def _group_images_by_shape(nested_images, is_nested: bool = False):
846
+ """Helper function to flatten a single level of nested image structures and group by shape."""
847
+ grouped_images = defaultdict(list)
848
+ grouped_images_index = {}
849
+ nested_images = [nested_images] if not is_nested else nested_images
850
+ for i, sublist in enumerate(nested_images):
851
+ for j, image in enumerate(sublist):
852
+ key = (i, j) if is_nested else j
853
+ shape = image.shape[1:]
854
+ grouped_images[shape].append(image)
855
+ grouped_images_index[key] = (shape, len(grouped_images[shape]) - 1)
856
+
857
+ return grouped_images, grouped_images_index
858
+
859
+
860
+ def _reconstruct_nested_structure(indices, processed_images):
861
+ """Helper function to reconstruct a single level nested structure."""
862
+ # Find the maximum outer index
863
+ max_outer_idx = max(idx[0] for idx in indices)
864
+
865
+ # Create the outer list
866
+ result = [None] * (max_outer_idx + 1)
867
+
868
+ # Group indices by outer index
869
+ nested_indices = defaultdict(list)
870
+ for i, j in indices:
871
+ nested_indices[i].append(j)
872
+
873
+ for i in range(max_outer_idx + 1):
874
+ if i in nested_indices:
875
+ inner_max_idx = max(nested_indices[i])
876
+ inner_list = [None] * (inner_max_idx + 1)
877
+ for j in range(inner_max_idx + 1):
878
+ if (i, j) in indices:
879
+ shape, idx = indices[(i, j)]
880
+ inner_list[j] = processed_images[shape][idx]
881
+ result[i] = inner_list
882
+
883
+ return result
884
+
885
+
886
+ def group_images_by_shape(
887
+ images: Union[list["torch.Tensor"], "torch.Tensor"],
888
+ disable_grouping: bool,
889
+ is_nested: bool = False,
890
+ ) -> tuple[
891
+ dict[tuple[int, int], list["torch.Tensor"]], dict[Union[int, tuple[int, int]], tuple[tuple[int, int], int]]
892
+ ]:
893
+ """
894
+ Groups images by shape.
895
+ Returns a dictionary with the shape as key and a list of images with that shape as value,
896
+ and a dictionary with the index of the image in the original list as key and the shape and index in the grouped list as value.
897
+
898
+ The function supports both flat lists of tensors and nested structures.
899
+ The input must be either all flat or all nested, not a mix of both.
900
+
901
+ Args:
902
+ images (Union[list["torch.Tensor"], "torch.Tensor"]):
903
+ A list of images or a single tensor
904
+ disable_grouping (bool):
905
+ Whether to disable grouping. If None, will be set to True if the images are on CPU, and False otherwise.
906
+ This choice is based on empirical observations, as detailed here: https://github.com/huggingface/transformers/pull/38157
907
+ is_nested (bool, *optional*, defaults to False):
908
+ Whether the images are nested.
909
+
910
+ Returns:
911
+ tuple[dict[tuple[int, int], list["torch.Tensor"]], dict[Union[int, tuple[int, int]], tuple[tuple[int, int], int]]]:
912
+ - A dictionary with shape as key and list of images with that shape as value
913
+ - A dictionary mapping original indices to (shape, index) tuples
914
+ """
915
+ # If disable grouping is not explicitly provided, we favor disabling it if the images are on CPU, and enabling it otherwise.
916
+ if disable_grouping is None:
917
+ device = images[0][0].device if is_nested else images[0].device
918
+ disable_grouping = device == "cpu"
919
+
920
+ if disable_grouping:
921
+ if is_nested:
922
+ return {(i, j): images[i][j].unsqueeze(0) for i in range(len(images)) for j in range(len(images[i]))}, {
923
+ (i, j): ((i, j), 0) for i in range(len(images)) for j in range(len(images[i]))
924
+ }
925
+ else:
926
+ return {i: images[i].unsqueeze(0) for i in range(len(images))}, {i: (i, 0) for i in range(len(images))}
927
+
928
+ # Handle single level nested structure
929
+ grouped_images, grouped_images_index = _group_images_by_shape(images, is_nested)
930
+
931
+ # Stack images with the same shape
932
+ grouped_images = {shape: torch.stack(images_list, dim=0) for shape, images_list in grouped_images.items()}
933
+
934
+ return grouped_images, grouped_images_index
935
+
936
+
937
+ def reorder_images(
938
+ processed_images: dict[tuple[int, int], "torch.Tensor"],
939
+ grouped_images_index: dict[Union[int, tuple[int, int]], tuple[tuple[int, int], int]],
940
+ is_nested: bool = False,
941
+ ) -> Union[list["torch.Tensor"], "torch.Tensor"]:
942
+ """
943
+ Reconstructs images in the original order, preserving the original structure (nested or not).
944
+ The input structure is either all flat or all nested.
945
+
946
+ Args:
947
+ processed_images (dict[tuple[int, int], "torch.Tensor"]):
948
+ Dictionary mapping shapes to batched processed images.
949
+ grouped_images_index (dict[Union[int, tuple[int, int]], tuple[tuple[int, int], int]]):
950
+ Dictionary mapping original indices to (shape, index) tuples.
951
+ is_nested (bool, *optional*, defaults to False):
952
+ Whether the images are nested. Cannot be inferred from the input, as some processing functions outputs nested images.
953
+ even with non nested images,e.g functions splitting images into patches. We thus can't deduce is_nested from the input.
954
+
955
+
956
+ Returns:
957
+ Union[list["torch.Tensor"], "torch.Tensor"]:
958
+ Images in the original structure.
959
+ """
960
+ if not is_nested:
961
+ return [
962
+ processed_images[grouped_images_index[i][0]][grouped_images_index[i][1]]
963
+ for i in range(len(grouped_images_index))
964
+ ]
965
+
966
+ return _reconstruct_nested_structure(grouped_images_index, processed_images)
967
+
968
+
969
+ class NumpyToTensor:
970
+ """
971
+ Convert a numpy array to a PyTorch tensor.
972
+ """
973
+
974
+ def __call__(self, image: np.ndarray):
975
+ # Same as in PyTorch, we assume incoming numpy images are in HWC format
976
+ # c.f. https://github.com/pytorch/vision/blob/61d97f41bc209e1407dcfbd685d2ee2da9c1cdad/torchvision/transforms/functional.py#L154
977
+ return torch.from_numpy(image.transpose(2, 0, 1)).contiguous()
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/masking_utils.py ADDED
@@ -0,0 +1,1256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2025 HuggingFace Inc. team. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import itertools
16
+ from typing import Callable, Optional, Union
17
+
18
+ import torch
19
+ import torch.nn.functional as F
20
+
21
+ from .cache_utils import Cache
22
+ from .configuration_utils import PretrainedConfig
23
+ from .utils import is_torch_xpu_available, logging
24
+ from .utils.generic import GeneralInterface
25
+ from .utils.import_utils import is_torch_flex_attn_available, is_torch_greater_or_equal, is_torchdynamo_compiling
26
+
27
+
28
+ if is_torch_flex_attn_available():
29
+ from torch.nn.attention.flex_attention import _DEFAULT_SPARSE_BLOCK_SIZE as flex_default_block_size
30
+ from torch.nn.attention.flex_attention import BlockMask, create_block_mask
31
+ else:
32
+ # Register a fake type to avoid crashing for annotations and `isinstance` checks
33
+ BlockMask = torch.Tensor
34
+
35
+ _is_torch_greater_or_equal_than_2_5 = is_torch_greater_or_equal("2.5", accept_dev=True)
36
+ _is_torch_greater_or_equal_than_2_6 = is_torch_greater_or_equal("2.6", accept_dev=True)
37
+ _is_torch_xpu_available = is_torch_xpu_available()
38
+
39
+ if _is_torch_greater_or_equal_than_2_6:
40
+ from torch._dynamo._trace_wrapped_higher_order_op import TransformGetItemToIndex
41
+
42
+
43
+ logger = logging.get_logger(__name__)
44
+
45
+
46
+ def and_masks(*mask_functions: Callable) -> Callable:
47
+ """Returns a mask function that is the intersection of provided mask functions"""
48
+ if not all(callable(arg) for arg in mask_functions):
49
+ raise RuntimeError(f"All inputs should be callable mask_functions: {mask_functions}")
50
+
51
+ def and_mask(batch_idx, head_idx, q_idx, kv_idx):
52
+ result = q_idx.new_ones((), dtype=torch.bool)
53
+ for mask in mask_functions:
54
+ result = result & mask(batch_idx, head_idx, q_idx, kv_idx).to(result.device)
55
+ return result
56
+
57
+ return and_mask
58
+
59
+
60
+ def or_masks(*mask_functions: Callable) -> Callable:
61
+ """Returns a mask function that is the union of provided mask functions"""
62
+ if not all(callable(arg) for arg in mask_functions):
63
+ raise RuntimeError(f"All inputs should be callable mask_functions: {mask_functions}")
64
+
65
+ def or_mask(batch_idx, head_idx, q_idx, kv_idx):
66
+ result = q_idx.new_zeros((), dtype=torch.bool)
67
+ for mask in mask_functions:
68
+ result = result | mask(batch_idx, head_idx, q_idx, kv_idx).to(result.device)
69
+ return result
70
+
71
+ return or_mask
72
+
73
+
74
+ def causal_mask_function(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
75
+ """
76
+ This creates a basic lower-diagonal causal mask.
77
+ """
78
+ return kv_idx <= q_idx
79
+
80
+
81
+ def sliding_window_overlay(sliding_window: int) -> Callable:
82
+ """
83
+ This is an overlay depicting a sliding window pattern. Add it on top of a causal mask for a proper sliding
84
+ window mask.
85
+ """
86
+
87
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
88
+ return kv_idx > q_idx - sliding_window
89
+
90
+ return inner_mask
91
+
92
+
93
+ def chunked_overlay(chunk_size: int, left_padding: torch.Tensor) -> Callable:
94
+ """
95
+ This is an overlay depicting a chunked attention pattern. Add it on top of a causal mask for a proper chunked
96
+ attention mask.
97
+ """
98
+
99
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
100
+ return (kv_idx - left_padding[batch_idx]) // chunk_size == (q_idx - left_padding[batch_idx]) // chunk_size
101
+
102
+ return inner_mask
103
+
104
+
105
+ def _legacy_chunked_overlay(chunk_size: int) -> Callable:
106
+ """
107
+ Same as the above function, but do not correctly account for left padding tokens.
108
+ Only kept for compatibility with older torch versions (< 2.6).
109
+ """
110
+
111
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
112
+ return kv_idx // chunk_size == q_idx // chunk_size
113
+
114
+ return inner_mask
115
+
116
+
117
+ def sliding_window_causal_mask_function(sliding_window: int) -> Callable:
118
+ """
119
+ This return the mask_function function to create a sliding window mask.
120
+ """
121
+ return and_masks(sliding_window_overlay(sliding_window), causal_mask_function)
122
+
123
+
124
+ def chunked_causal_mask_function(chunk_size: int, left_padding: torch.Tensor) -> Callable:
125
+ """
126
+ This return the mask_function function to create a chunked attention mask.
127
+ """
128
+ if not _is_torch_greater_or_equal_than_2_6:
129
+ return and_masks(_legacy_chunked_overlay(chunk_size), causal_mask_function)
130
+ return and_masks(chunked_overlay(chunk_size, left_padding), causal_mask_function)
131
+
132
+
133
+ def padding_mask_function(padding_mask: torch.Tensor) -> Callable:
134
+ """
135
+ This return the mask_function function corresponding to a 2D padding mask.
136
+ """
137
+
138
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
139
+ # Note that here the mask should ALWAYS be at least of the max `kv_index` size in the dimension 1. This is because
140
+ # we cannot pad it here in the mask_function as we don't know the final size, and we cannot try/except, as it is not
141
+ # vectorizable on accelerator devices
142
+ return padding_mask[batch_idx, kv_idx]
143
+
144
+ return inner_mask
145
+
146
+
147
+ def packed_sequence_mask_function(packed_sequence_mask: torch.Tensor) -> Callable:
148
+ """
149
+ This return the mask_function function corresponding to a 2D packed sequence mask.
150
+ """
151
+
152
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
153
+ return packed_sequence_mask[batch_idx, q_idx] == packed_sequence_mask[batch_idx, kv_idx]
154
+
155
+ return inner_mask
156
+
157
+
158
+ def add_offsets_to_mask_function(mask_function: Callable, q_offset: int, kv_offset: int) -> Callable:
159
+ """
160
+ This function adds the correct offsets to the `q_idx` and `kv_idx` as the torch API can only accept lengths,
161
+ not start and end indices.
162
+ """
163
+
164
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
165
+ return mask_function(batch_idx, head_idx, q_idx + q_offset, kv_idx + kv_offset)
166
+
167
+ return inner_mask
168
+
169
+
170
+ def _vmap_for_bhqkv(mask_function: Callable, bh_indices: bool = True) -> Callable:
171
+ """
172
+ Used to vmap our mask_functions over the q_idx and kv_idx dimensions of the inputs. Optionally, vmap over
173
+ the batch and head indices as well if `bh_indices=True`.
174
+ Using vmap here allows us to keep the performance of vectorized ops, while having a single set of primitive
175
+ functions between attention interfaces (i.e. between flex and sdpa/eager, FA2 being a bit different).
176
+
177
+ Args:
178
+ mask_function (`Callable`):
179
+ The mask_function to vmap.
180
+ bh_indices (`bool`, optional):
181
+ Whether to vmap over the batch and head indices as well, or only q and kv indices.
182
+
183
+ Returns:
184
+ Callable: The vmapped function.
185
+ """
186
+ # We vmap the function 2 times, broadcasting the [q_idx, kv_idx] dimensions
187
+ dimensions = [(None, None, None, 0), (None, None, 0, None)]
188
+ if bh_indices:
189
+ # We extend broadcasting over the [batch_idx, head_idx] dimensions
190
+ dimensions.extend([(None, 0, None, None), (0, None, None, None)])
191
+
192
+ for dims in dimensions:
193
+ mask_function = torch.vmap(mask_function, in_dims=dims, out_dims=0)
194
+ return mask_function
195
+
196
+
197
+ def prepare_padding_mask(
198
+ attention_mask: Optional[torch.Tensor], kv_length: int, kv_offset: int, _slice: bool = True
199
+ ) -> Optional[torch.Tensor]:
200
+ """
201
+ From the 2D attention mask, prepare the correct padding mask to use by potentially padding it, and slicing
202
+ according to the `kv_offset` if `_slice` is `True`.
203
+ """
204
+ local_padding_mask = attention_mask
205
+ if attention_mask is not None:
206
+ # Pad it if necessary
207
+ if (padding_length := kv_length + kv_offset - attention_mask.shape[-1]) > 0:
208
+ local_padding_mask = torch.nn.functional.pad(attention_mask, (0, padding_length))
209
+ # For flex, we should not slice them, only use an offset
210
+ if _slice:
211
+ # Equivalent to: `local_padding_mask = attention_mask[:, kv_offset : kv_offset + kv_length]`,
212
+ # but without data-dependent slicing (i.e. torch.compile friendly)
213
+ mask_indices = torch.arange(kv_length, device=local_padding_mask.device)
214
+ mask_indices += kv_offset
215
+ local_padding_mask = local_padding_mask[:, mask_indices]
216
+ return local_padding_mask
217
+
218
+
219
+ def _ignore_causal_mask_sdpa(
220
+ padding_mask: Optional[torch.Tensor],
221
+ query_length: int,
222
+ kv_length: int,
223
+ kv_offset: int,
224
+ local_attention_size: Optional[int] = None,
225
+ ) -> bool:
226
+ """
227
+ Detects whether the causal mask can be ignored in case PyTorch's SDPA is used, rather relying on SDPA's `is_causal` argument.
228
+
229
+ In case no token is masked in the 2D `padding_mask` argument, if `query_length == 1` or
230
+ `key_value_length == query_length`, we rather rely on SDPA `is_causal` argument to use causal/non-causal masks,
231
+ allowing to dispatch to the flash attention kernel (that can otherwise not be used if a custom `attn_mask` is
232
+ passed).
233
+ """
234
+ is_tracing = torch.jit.is_tracing() or isinstance(padding_mask, torch.fx.Proxy) or is_torchdynamo_compiling()
235
+ if padding_mask is not None and padding_mask.shape[-1] > kv_length:
236
+ mask_indices = torch.arange(kv_length, device=padding_mask.device)
237
+ mask_indices += kv_offset
238
+ padding_mask = padding_mask[:, mask_indices]
239
+
240
+ # When using `torch.export` or `torch.onnx.dynamo_export`, we must pass an example input, and `is_causal` behavior is
241
+ # hard-coded to the forward. If a user exports a model with query_length > 1, the exported model will hard-code `is_causal=True`
242
+ # which is in general wrong (see https://github.com/pytorch/pytorch/issues/108108). Thus, we only set
243
+ # `ignore_causal_mask = True` if we are not tracing
244
+ if (
245
+ not is_tracing
246
+ # only cases when lower and upper diags are the same, see https://github.com/pytorch/pytorch/issues/108108
247
+ and (query_length == 1 or (kv_length == query_length or _is_torch_xpu_available))
248
+ # in this case we need to add special patterns to the mask so cannot be skipped otherwise
249
+ and (local_attention_size is None or kv_length < local_attention_size)
250
+ # In this case, we need to add padding to the mask, so cannot be skipped otherwise
251
+ and (
252
+ padding_mask is None
253
+ or (
254
+ padding_mask.all()
255
+ if not _is_torch_xpu_available or query_length == 1
256
+ else padding_mask[:, :query_length].all()
257
+ )
258
+ )
259
+ ):
260
+ return True
261
+
262
+ return False
263
+
264
+
265
+ def sdpa_mask_recent_torch(
266
+ batch_size: int,
267
+ cache_position: torch.Tensor,
268
+ kv_length: int,
269
+ kv_offset: int = 0,
270
+ mask_function: Callable = causal_mask_function,
271
+ attention_mask: Optional[torch.Tensor] = None,
272
+ local_size: Optional[int] = None,
273
+ allow_is_causal_skip: bool = True,
274
+ **kwargs,
275
+ ) -> Optional[torch.Tensor]:
276
+ """
277
+ Create a 4D boolean mask of shape `(batch_size, 1, query_length, kv_length)` where a value of True indicates that
278
+ the element should take part in the attention computation, and False that it should not.
279
+ This function can only be used with torch>=2.5, as the context manager is otherwise not available.
280
+
281
+ Args:
282
+ batch_size (`int`):
283
+ The batch size of the input sequence.
284
+ cache_position (`torch.Tensor`):
285
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
286
+ kv_length (`int`):
287
+ The size that the key and value states will have during the attention computation.
288
+ kv_offset (`int`, optional):
289
+ An optional offset to indicate at which first position the key and values states will refer to.
290
+ mask_function (`Callable`):
291
+ The mask factory function describing the mask pattern.
292
+ attention_mask (`torch.Tensor`, optional):
293
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
294
+ local_size (`int`, optional):
295
+ The size of the local attention, if we do not use full attention. This is used only if `allow_is_causal_skip=True`
296
+ to try to skip mask creation if possible.
297
+ allow_is_causal_skip (`bool`, optional):
298
+ Whether to allow to return `None` for the mask under conditions where we can use the `is_causal` argument in
299
+ `torch.sdpa` instead. Default to `True`.
300
+ allow_torch_fix (`bool`, optional):
301
+ Whether to update the mask in case a query is not attending to any tokens, to solve a bug in torch's older
302
+ versions. We need an arg to skip it when using eager. By default `True`.
303
+
304
+
305
+ ## Creating a simple causal mask:
306
+
307
+ To create the following causal mask:
308
+
309
+ 0 ■ ⬚ ⬚ ⬚ ⬚
310
+ 1 ■ ■ ⬚ ⬚ ⬚
311
+ 2 ■ ■ ■ ⬚ ⬚
312
+ 3 ■ ■ ■ ■ ⬚
313
+ 4 ■ ■ ■ ■ ■
314
+
315
+ You can do
316
+
317
+ ```python
318
+ >>> sdpa_mask(batch_size=1, cache_position=torch.arange(5), kv_length=5)
319
+ >>> tensor([[[[ True, False, False, False, False],
320
+ [ True, True, False, False, False],
321
+ [ True, True, True, False, False],
322
+ [ True, True, True, True, False],
323
+ [ True, True, True, True, True]]]])
324
+ ```
325
+
326
+ ## Creating a sliding window mask:
327
+
328
+ To create the following sliding window mask (`sliding_window=3`):
329
+
330
+ 0 ■ ⬚ ⬚ ⬚ ⬚
331
+ 1 ■ ■ ⬚ ⬚ ⬚
332
+ 2 ■ ■ ■ ⬚ ⬚
333
+ 3 ⬚ ■ ■ ■ ⬚
334
+ 4 ⬚ ⬚ ■ ■ ■
335
+
336
+ You can do
337
+
338
+ ```python
339
+ >>> sdpa_mask(batch_size=1, cache_position=torch.arange(5), kv_length=5, mask_function=sliding_window_causal_mask_function(3))
340
+ >>> tensor([[[[ True, False, False, False, False],
341
+ [ True, True, False, False, False],
342
+ [ True, True, True, False, False],
343
+ [False, True, True, True, False],
344
+ [False, False, True, True, True]]]])
345
+ ```
346
+
347
+ ## Creating a chunked attention mask
348
+
349
+ To create the following chunked attention mask (`chunk_size=3`):
350
+
351
+ 0 ■ ⬚ ⬚ ⬚ ⬚
352
+ 1 ■ ■ ⬚ ⬚ ⬚
353
+ 2 ■ ■ ■ ⬚ ⬚
354
+ 3 ⬚ ⬚ ⬚ ■ ⬚
355
+ 4 ⬚ ⬚ ⬚ ■ ■
356
+
357
+ You can do
358
+
359
+ ```python
360
+ >>> sdpa_mask(batch_size=1, cache_position=torch.arange(5), kv_length=5, mask_function=chunked_causal_mask_function(3, torch.zeros(1, dtype=int)))
361
+ >>> tensor([[[[ True, False, False, False, False],
362
+ [ True, True, False, False, False],
363
+ [ True, True, True, False, False],
364
+ [False, False, False, True, False],
365
+ [False, False, False, True, True]]]])
366
+ ```
367
+
368
+ """
369
+ q_length = cache_position.shape[0]
370
+ # Potentially pad the 2D mask, and slice it correctly
371
+ padding_mask = prepare_padding_mask(attention_mask, kv_length, kv_offset, _slice=False)
372
+
373
+ # Under specific conditions, we can avoid materializing the mask, instead relying on the `is_causal` argument
374
+ if allow_is_causal_skip and _ignore_causal_mask_sdpa(padding_mask, q_length, kv_length, kv_offset, local_size):
375
+ return None
376
+
377
+ # Similar to `kv_arange = torch.arange(start=kv_offset, end=kv_offset + kv_length, device=cache_position.device)`
378
+ # but without data-dependent slicing (i.e. torch.compile friendly)
379
+ kv_arange = torch.arange(kv_length, device=cache_position.device)
380
+ kv_arange += kv_offset
381
+
382
+ # Potentially add the padding 2D mask
383
+ if padding_mask is not None:
384
+ mask_function = and_masks(mask_function, padding_mask_function(padding_mask))
385
+
386
+ batch_arange = torch.arange(batch_size, device=cache_position.device)
387
+ head_arange = torch.arange(1, device=cache_position.device)
388
+ # This creates the 4D mask easily. Note that we need this context manager as vmap cannot handle slicing a tensor from
389
+ # scalar tensor (it internally calls `.item()` which vmap does not allow, but this context works around it
390
+ # We don't need to add an offset to the mask_function either, as we vmap directly the correct indices for k and kv indices
391
+ with TransformGetItemToIndex():
392
+ causal_mask = _vmap_for_bhqkv(mask_function)(batch_arange, head_arange, cache_position, kv_arange)
393
+
394
+ return causal_mask
395
+
396
+
397
+ def sdpa_mask_older_torch(
398
+ batch_size: int,
399
+ cache_position: torch.Tensor,
400
+ kv_length: int,
401
+ kv_offset: int = 0,
402
+ mask_function: Callable = causal_mask_function,
403
+ attention_mask: Optional[torch.Tensor] = None,
404
+ local_size: Optional[int] = None,
405
+ allow_is_causal_skip: bool = True,
406
+ allow_torch_fix: bool = True,
407
+ **kwargs,
408
+ ) -> Optional[torch.Tensor]:
409
+ """
410
+ NOTE: This function is only used when torch version is torch<2.5 - see `sdpa_mask_recent_torch` otherwise.
411
+
412
+ Create a 4D boolean mask of shape `(batch_size, 1, query_length, kv_length)` where a value of True indicates that
413
+ the element should take part in the attention computation, and False that it should not.
414
+ If `allow_torch_fix=True` (the default), rows corresponding to query tokens that do not attend
415
+ to any other tokens (due to padding) will be fully attended to instead, in order to avoid `nan` propagation (this does
416
+ not change the final result).
417
+
418
+ Args:
419
+ batch_size (`int`):
420
+ The batch size of the input sequence.
421
+ cache_position (`torch.Tensor`):
422
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
423
+ kv_length (`int`):
424
+ The size that the key and value states will have during the attention computation.
425
+ kv_offset (`int`, optional):
426
+ An optional offset to indicate at which first position the key and values states will refer to.
427
+ mask_function (`Callable`):
428
+ The mask factory function describing the mask pattern.
429
+ attention_mask (`torch.Tensor`, optional):
430
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
431
+ local_size (`int`, optional):
432
+ The size of the local attention, if we do not use full attention. This is used only if `allow_is_causal_skip=True`
433
+ to try to skip mask creation if possible.
434
+ allow_is_causal_skip (`bool`, optional):
435
+ Whether to allow to return `None` for the mask under conditions where we can use the `is_causal` argument in
436
+ `torch.sdpa` instead. Default to `True`.
437
+ allow_torch_fix (`bool`, optional):
438
+ Whether to update the mask in case a query is not attending to any tokens, to solve a bug in torch's older
439
+ versions. We need an arg to skip it when using eager. By default `True`.
440
+ """
441
+ q_length = cache_position.shape[0]
442
+ # Potentially pad the 2D mask, and slice it correctly
443
+ padding_mask = prepare_padding_mask(attention_mask, kv_length, kv_offset)
444
+
445
+ # Under specific conditions, we can avoid materializing the mask, instead relying on the `is_causal` argument
446
+ if allow_is_causal_skip and _ignore_causal_mask_sdpa(padding_mask, q_length, kv_length, kv_offset, local_size):
447
+ return None
448
+
449
+ # Similar to `kv_arange = torch.arange(start=kv_offset, end=kv_offset + kv_length, device=cache_position.device)`
450
+ # but without data-dependent slicing (i.e. torch.compile friendly)
451
+ kv_arange = torch.arange(kv_length, device=cache_position.device)
452
+ kv_arange += kv_offset
453
+
454
+ # This creates the 4D mask easily. Note that we do not include vmap over the batch_idx dimension as well,
455
+ # as vmap cannot handle slicing a tensor from scalar tensor (it internally calls `.item()` which vmap does not allow
456
+ # However, in more recent version of Pytorch, a trick was introduced to handle it - which is the reason we have
457
+ # `sdpa_mask_recent_torch`, as it allows more general `mask_function`
458
+ causal_mask = _vmap_for_bhqkv(mask_function, bh_indices=False)(None, None, cache_position, kv_arange)
459
+ causal_mask = causal_mask[None, None, :, :].expand(batch_size, -1, -1, -1)
460
+ if padding_mask is not None:
461
+ causal_mask = causal_mask * padding_mask[:, None, None, :]
462
+
463
+ # Due to a bug in versions of torch<2.5, we need to update the mask in case a query is not attending to any
464
+ # tokens (due to padding). See details in https://github.com/pytorch/pytorch/issues/110213
465
+ if not _is_torch_greater_or_equal_than_2_5 and allow_torch_fix:
466
+ causal_mask |= torch.all(~causal_mask, dim=-1, keepdim=True)
467
+ return causal_mask
468
+
469
+
470
+ # We use the version with newer torch whenever possible, as it is more general and can handle arbitrary mask functions
471
+ # (especially mask_function indexing a tensor, such as the padding mask function)
472
+ sdpa_mask = sdpa_mask_recent_torch if _is_torch_greater_or_equal_than_2_6 else sdpa_mask_older_torch
473
+
474
+
475
+ def eager_mask(
476
+ batch_size: int,
477
+ cache_position: torch.Tensor,
478
+ kv_length: int,
479
+ kv_offset: int = 0,
480
+ mask_function: Callable = causal_mask_function,
481
+ attention_mask: Optional[torch.Tensor] = None,
482
+ dtype: torch.dtype = torch.float32,
483
+ **kwargs,
484
+ ) -> torch.Tensor:
485
+ """
486
+ Create a 4D float mask of shape `(batch_size, 1, query_length, kv_length)` where a value of 0 indicates that
487
+ the element should take part in the attention computation, and -inf (minimum value for the given `dtype`) that
488
+ it should not.
489
+
490
+ Args:
491
+ batch_size (`int`):
492
+ The batch size of the input sequence.
493
+ cache_position (`torch.Tensor`):
494
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
495
+ kv_length (`int`):
496
+ The size that the key and value states will have during the attention computation.
497
+ kv_offset (`int`, optional):
498
+ An optional offset to indicate at which first position the key and values states will refer to.
499
+ mask_function (`Callable`):
500
+ The mask factory function describing the mask pattern.
501
+ attention_mask (`torch.Tensor`, optional):
502
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
503
+ dtype (`torch.dtype`, optional):
504
+ The dtype to use for the mask. By default, `torch.float32`.
505
+ """
506
+ # The masks for eager attention are simply boolean mask from sdpa, casted to 0 and -inf
507
+ _ = kwargs.pop("allow_is_causal_skip", None)
508
+ mask = sdpa_mask(
509
+ batch_size=batch_size,
510
+ cache_position=cache_position,
511
+ kv_length=kv_length,
512
+ kv_offset=kv_offset,
513
+ mask_function=mask_function,
514
+ attention_mask=attention_mask,
515
+ allow_is_causal_skip=False,
516
+ allow_torch_fix=False,
517
+ **kwargs,
518
+ )
519
+ min_dtype = torch.finfo(dtype).min
520
+ # we need 0s where the tokens should be taken into account, and -inf otherwise (mask is already of boolean type)
521
+ mask = torch.where(mask, torch.tensor(0.0, device=mask.device, dtype=dtype), min_dtype)
522
+ return mask
523
+
524
+
525
+ def flash_attention_mask(
526
+ batch_size: int,
527
+ cache_position: torch.Tensor,
528
+ kv_length: int,
529
+ kv_offset: int = 0,
530
+ mask_function: Callable = causal_mask_function,
531
+ attention_mask: Optional[torch.Tensor] = None,
532
+ **kwargs,
533
+ ):
534
+ """
535
+ Create the attention mask necessary to use FA2. Since FA2 is un-padded by definition, here we simply return
536
+ `None` if the mask is fully causal, or we return the 2D mask which will then be used to extract the seq_lens.
537
+ We just slice it in case of sliding window.
538
+
539
+ Args:
540
+ batch_size (`int`):
541
+ The batch size of the input sequence.
542
+ cache_position (`torch.Tensor`):
543
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
544
+ kv_length (`int`):
545
+ The size that the key and value states will have during the attention computation.
546
+ kv_offset (`int`, optional):
547
+ An optional offset to indicate at which first position the key and values states will refer to.
548
+ mask_function (`Callable`):
549
+ The mask factory function describing the mask pattern.
550
+ attention_mask (`torch.Tensor`, optional):
551
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
552
+ """
553
+ if attention_mask is not None:
554
+ # Here we need to slice from the right if using sliding or chunked (for full attention, this is equivalent to doing nothing)
555
+ attention_mask = attention_mask[:, -kv_length:]
556
+ # We only return an actual mask if there is at least 1 padding token, otherwise we return `None` and use `is_causal` in FA2
557
+ # (note that the attention_mask is a boolean dtype here)
558
+ if attention_mask.all():
559
+ attention_mask = None
560
+
561
+ return attention_mask
562
+
563
+
564
+ def flex_attention_mask(
565
+ batch_size: int,
566
+ cache_position: torch.Tensor,
567
+ kv_length: int,
568
+ kv_offset: int = 0,
569
+ mask_function: Callable = causal_mask_function,
570
+ attention_mask: Optional[torch.Tensor] = None,
571
+ **kwargs,
572
+ ) -> BlockMask:
573
+ """
574
+ Create a 4D block mask which is a compressed representation of the full 4D block causal mask. BlockMask is essential
575
+ for performant computation of flex attention. See: https://pytorch.org/blog/flexattention/
576
+
577
+ Args:
578
+ batch_size (`int`):
579
+ The batch size of the input sequence.
580
+ cache_position (`torch.Tensor`):
581
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
582
+ kv_length (`int`):
583
+ The size that the key and value states will have during the attention computation.
584
+ kv_offset (`int`, optional):
585
+ An optional offset to indicate at which first position the key and values states will refer to.
586
+ mask_function (`Callable`):
587
+ The mask factory function describing the mask pattern.
588
+ attention_mask (`torch.Tensor`, optional):
589
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
590
+ """
591
+ q_length, q_offset = cache_position.shape[0], cache_position[0]
592
+
593
+ # Potentially add the padding 2D mask
594
+ if attention_mask is not None:
595
+ # Older torch (2.5.x) cannot handle sequences not in multiples of 128 (default block size)
596
+ # Hence we pad to multiples of this as a minimum to ensure this
597
+ pad_len = ((attention_mask.shape[1] // flex_default_block_size) + 1) * flex_default_block_size
598
+ pad_len = pad_len - attention_mask.shape[1]
599
+ if not _is_torch_greater_or_equal_than_2_6 and pad_len > 0:
600
+ attention_mask = torch.nn.functional.pad(attention_mask, value=0, pad=(0, pad_len))
601
+
602
+ padding_mask = prepare_padding_mask(attention_mask, kv_length, kv_offset, _slice=False)
603
+ mask_function = and_masks(mask_function, padding_mask_function(padding_mask))
604
+
605
+ # Add the offsets on top (because flex interface only allows length, not start and end indices)
606
+ mask_function = add_offsets_to_mask_function(mask_function, q_offset, kv_offset)
607
+
608
+ # Finally create the block mask
609
+ block_mask = create_block_mask(
610
+ mask_mod=mask_function,
611
+ B=batch_size,
612
+ H=None,
613
+ Q_LEN=q_length,
614
+ KV_LEN=kv_length,
615
+ device=cache_position.device,
616
+ _compile=_is_torch_greater_or_equal_than_2_6,
617
+ )
618
+ return block_mask
619
+
620
+
621
+ class AttentionMaskInterface(GeneralInterface):
622
+ # Class instance object, so that a call to `register` can be reflected into all other files correctly, even if
623
+ # a new instance is created (in order to locally override a given function)
624
+ _global_mapping = {
625
+ "sdpa": sdpa_mask,
626
+ "eager": eager_mask,
627
+ "flash_attention_2": flash_attention_mask,
628
+ "flash_attention_3": flash_attention_mask,
629
+ "flex_attention": flex_attention_mask,
630
+ }
631
+
632
+
633
+ # Global AttentionMaskInterface shared by all models which do not need to overwrite any of the existing ones
634
+ ALL_MASK_ATTENTION_FUNCTIONS: AttentionMaskInterface = AttentionMaskInterface()
635
+
636
+
637
+ def find_packed_sequence_indices(position_ids: torch.Tensor) -> torch.Tensor:
638
+ """
639
+ Find the indices of the sequence to which each new query token in the sequence belongs when using packed
640
+ tensor format (i.e. several sequences packed in the same batch dimension).
641
+
642
+ Args:
643
+ position_ids (`torch.Tensor`)
644
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
645
+
646
+ Returns:
647
+ A 2D tensor where each similar integer indicates that the tokens belong to the same sequence. For example, if we
648
+ pack 3 sequences of 2, 3 and 1 tokens respectively along a single batch dim, this will return [[0, 0, 1, 1, 1, 2]].
649
+ """
650
+ # What separate different sequences is when 2 consecutive positions_ids are separated by more than 1. So
651
+ # taking the diff (by prepending the first value - 1 to keep correct indexing) and applying cumsum to the result
652
+ # gives exactly the sequence indices
653
+ # Note that we assume that a single sequence cannot span several batch dimensions, i.e. 1 single sequence
654
+ # cannot be part of the end of the first batch dim and the start of the 2nd one for example
655
+ first_dummy_value = position_ids[:, :1] - 1 # We just need the diff on this first value to be 1
656
+ position_diff = torch.diff(position_ids, prepend=first_dummy_value, dim=-1)
657
+ packed_sequence_mask = (position_diff != 1).cumsum(-1)
658
+
659
+ # Here it would be nice to return None if we did not detect packed sequence format, i.e. if `packed_sequence_mask[:, -1] == 0`
660
+ # but it causes issues with export
661
+ return packed_sequence_mask
662
+
663
+
664
+ def _preprocess_mask_arguments(
665
+ config: PretrainedConfig,
666
+ input_embeds: torch.Tensor,
667
+ attention_mask: Optional[Union[torch.Tensor, BlockMask]],
668
+ cache_position: torch.Tensor,
669
+ past_key_values: Optional[Cache],
670
+ position_ids: Optional[torch.Tensor],
671
+ layer_idx: Optional[int],
672
+ ) -> tuple[bool, Optional[Union[torch.Tensor, BlockMask]], int, int]:
673
+ """
674
+ Perform some common pre-processing of the mask arguments we get from the modeling code. Mostly determine the
675
+ key-value length and offsets, and if we should early exit or not.
676
+
677
+ Args:
678
+ config (`PretrainedConfig`):
679
+ The model config.
680
+ input_embeds (`torch.Tensor`):
681
+ The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
682
+ batch size, query length and dtype.
683
+ attention_mask (`torch.Tensor`, optional):
684
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
685
+ It can also be an already prepared 4D mask, in which case it is returned as-is.
686
+ cache_position (`torch.Tensor`):
687
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
688
+ past_key_values (`Cache`, optional):
689
+ The past key values, if we use a cache.
690
+ position_ids (`torch.Tensor`, optional)
691
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
692
+ layer_idx (`int`, optional):
693
+ If `past_key_values` is not None, this is the layer index of the cache from which to get the key-value
694
+ length and offset. Indeed, for hybrid caches, different layers may return different lengths.
695
+
696
+ Returns:
697
+ early_exit (`bool`):
698
+ Whether we should early exit mask creation, and return the mask as-is.
699
+ attention_mask (`torch.Tensor` or `BlockMask` or `None`):
700
+ The attention mask to either return immediately, or to use in downstream mask creation.
701
+ packed_sequence_mask (`torch.Tensor`, optional):
702
+ In case we detected packed sequence format, this is a tensor where each similar integer indicates that
703
+ the tokens belong to the same sequence.
704
+ kv_length (`int`):
705
+ The size that the key and value states will have during the attention computation.
706
+ kv_offset (`int`):
707
+ An offset to indicate at which first position the key and values states will refer to.
708
+ """
709
+ # If the mask is already 4D, simply return as-is (it was already prepared, or it is custom)
710
+ if isinstance(attention_mask, (torch.Tensor, BlockMask)) and len(attention_mask.shape) == 4:
711
+ return True, attention_mask, None, None, None
712
+
713
+ # For TGI/vLLM backends, or other custom attention without equivalent mask creation: we don't need a mask!
714
+ # Note: it's not ideal to check the `_global_mapping` attribute instead of the object itself, however otherwise
715
+ # full graph dynamo tracing (i.e. torch.export or compile with `fullgraph=True`) will fail on Python<3.11
716
+ # with `torch._dynamo.exc.Unsupported: 'inline in skipfiles:Mapping.__contains__ | __contains__, skipped
717
+ # according trace_rules.lookup SKIP_DIRS'` -- can be removed when we require Python>=3.11
718
+ if config._attn_implementation not in ALL_MASK_ATTENTION_FUNCTIONS._global_mapping:
719
+ return True, None, None, None, None
720
+
721
+ # Move the mask to correct device, and potentially switch dtype for efficiency
722
+ if attention_mask is not None and attention_mask.ndim == 2:
723
+ attention_mask = attention_mask.to(device=cache_position.device, dtype=torch.bool)
724
+
725
+ # If using a cache, it can give all information about mask sizes based on seen tokens
726
+ if past_key_values is not None:
727
+ kv_length, kv_offset = past_key_values.get_mask_sizes(cache_position, layer_idx)
728
+ # Otherwise, the sizes are simply the input sizes
729
+ else:
730
+ kv_length, kv_offset = input_embeds.shape[1], 0
731
+
732
+ # We check the position_ids for potential packed sequence format (only if the 2D attention mask is explicitly None,
733
+ # and we don't have past_key_values, i.e. generally a training setup)
734
+ packed_sequence_mask = None
735
+ if position_ids is not None and attention_mask is None and past_key_values is None:
736
+ batch_size = input_embeds.shape[0]
737
+ # The position ids are sometimes just unsqueezed, without being expanded
738
+ if batch_size != position_ids.shape[0]:
739
+ position_ids = position_ids.expand(batch_size, -1)
740
+ packed_sequence_mask = find_packed_sequence_indices(position_ids)
741
+
742
+ return False, attention_mask, packed_sequence_mask, kv_length, kv_offset
743
+
744
+
745
+ def create_causal_mask(
746
+ config: PretrainedConfig,
747
+ input_embeds: torch.Tensor,
748
+ attention_mask: Optional[torch.Tensor],
749
+ cache_position: torch.Tensor,
750
+ past_key_values: Optional[Cache],
751
+ position_ids: Optional[torch.Tensor] = None,
752
+ or_mask_function: Optional[Callable] = None,
753
+ and_mask_function: Optional[Callable] = None,
754
+ ) -> Optional[Union[torch.Tensor, BlockMask]]:
755
+ """
756
+ Create a standard causal mask based on the attention implementation used (stored in the config). If `past_key_values`
757
+ has an hybrid cache structure, this function will return the mask corresponding to one of the "full_attention" layers (to align
758
+ to what is needed in the `modeling_xxx.py` files).
759
+
760
+ Args:
761
+ config (`PretrainedConfig`):
762
+ The model config.
763
+ input_embeds (`torch.Tensor`):
764
+ The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
765
+ batch size, query length and dtype.
766
+ attention_mask (`torch.Tensor`, optional):
767
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
768
+ It can also be an already prepared 4D mask, in which case it is returned as-is.
769
+ cache_position (`torch.Tensor`):
770
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
771
+ past_key_values (`Cache`, optional):
772
+ The past key values, if we use a cache.
773
+ position_ids (`torch.Tensor`, optional)
774
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
775
+ or_mask_function (`Callable`, optional):
776
+ An optional mask function to combine with the causal mask function (by doing the union of both). This is
777
+ useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
778
+ and_mask_function (`Callable`, optional):
779
+ An optional mask function to combine with the causal mask function (by doing the intersection of both). This is
780
+ useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
781
+ """
782
+ # If we have an hybrid cache structure, here we want to create the mask for the full layers
783
+ if hasattr(past_key_values, "is_sliding") and False in past_key_values.is_sliding:
784
+ layer_idx = past_key_values.is_sliding.index(False)
785
+ else:
786
+ layer_idx = 0
787
+
788
+ early_exit, attention_mask, packed_sequence_mask, kv_length, kv_offset = _preprocess_mask_arguments(
789
+ config, input_embeds, attention_mask, cache_position, past_key_values, position_ids, layer_idx
790
+ )
791
+ if early_exit:
792
+ return attention_mask
793
+
794
+ batch_size, dtype = input_embeds.shape[0], input_embeds.dtype
795
+ mask_factory_function = causal_mask_function
796
+ mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
797
+
798
+ # Do not allow skip if we are compiling (this is to match BC)
799
+ # TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
800
+ if _is_torch_xpu_available:
801
+ allow_is_causal_skip = True
802
+ else:
803
+ allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
804
+
805
+ # Allow slight deviations from causal mask
806
+ # Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
807
+ # padding mask, etc) as the resulting mask may otherwise not be correct!
808
+ if or_mask_function is not None:
809
+ if not _is_torch_greater_or_equal_than_2_6:
810
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
811
+ mask_factory_function = or_masks(mask_factory_function, or_mask_function)
812
+ allow_is_causal_skip = False
813
+ if and_mask_function is not None:
814
+ if not _is_torch_greater_or_equal_than_2_6:
815
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
816
+ mask_factory_function = and_masks(mask_factory_function, and_mask_function)
817
+ allow_is_causal_skip = False
818
+
819
+ # If we detected packing format
820
+ if packed_sequence_mask is not None and _is_torch_greater_or_equal_than_2_6:
821
+ mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
822
+ allow_is_causal_skip = False
823
+
824
+ # We now create the mask
825
+ causal_mask = mask_interface(
826
+ batch_size=batch_size,
827
+ cache_position=cache_position,
828
+ kv_length=kv_length,
829
+ kv_offset=kv_offset,
830
+ mask_function=mask_factory_function,
831
+ attention_mask=attention_mask,
832
+ allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
833
+ dtype=dtype, # Additional kwarg for eager
834
+ config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
835
+ )
836
+ return causal_mask
837
+
838
+
839
+ def create_sliding_window_causal_mask(
840
+ config: PretrainedConfig,
841
+ input_embeds: torch.Tensor,
842
+ attention_mask: Optional[torch.Tensor],
843
+ cache_position: torch.Tensor,
844
+ past_key_values: Optional[Cache],
845
+ position_ids: Optional[torch.Tensor] = None,
846
+ or_mask_function: Optional[Callable] = None,
847
+ and_mask_function: Optional[Callable] = None,
848
+ ) -> Optional[Union[torch.Tensor, BlockMask]]:
849
+ """
850
+ Create a sliding window causal mask based on the attention implementation used (stored in the config). This type
851
+ of attention pattern was mostly democratized by Mistral. If `past_key_values` has an hybrid cache structure, this
852
+ function will return the mask corresponding to one of the "sliding_attention" layers (to align to what is needed in the
853
+ `modeling_xxx.py` files).
854
+
855
+ Args:
856
+ config (`PretrainedConfig`):
857
+ The model config.
858
+ input_embeds (`torch.Tensor`):
859
+ The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
860
+ batch size, query length and dtype.
861
+ attention_mask (`torch.Tensor`, optional):
862
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
863
+ It can also be an already prepared 4D mask, in which case it is returned as-is.
864
+ cache_position (`torch.Tensor`):
865
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
866
+ past_key_values (`Cache`, optional):
867
+ The past key values, if we use a cache.
868
+ position_ids (`torch.Tensor`, optional)
869
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
870
+ or_mask_function (`Callable`, optional):
871
+ An optional mask function to combine with the sliding causal mask function (by doing the union of both). This is
872
+ useful to easily overlay another mask on top of the sliding causal one, for example for image tokens handling.
873
+ and_mask_function (`Callable`, optional):
874
+ An optional mask function to combine with the sliding causal mask function (by doing the intersection of both). This is
875
+ useful to easily overlay another mask on top of the sliding causal one, for example for image tokens handling.
876
+ """
877
+ # If we have an hybrid cache structure, here we want to create the mask for the sliding layers
878
+ if hasattr(past_key_values, "is_sliding") and True in past_key_values.is_sliding:
879
+ layer_idx = past_key_values.is_sliding.index(True)
880
+ else:
881
+ layer_idx = 0
882
+
883
+ early_exit, attention_mask, packed_sequence_mask, kv_length, kv_offset = _preprocess_mask_arguments(
884
+ config, input_embeds, attention_mask, cache_position, past_key_values, position_ids, layer_idx
885
+ )
886
+ if early_exit:
887
+ return attention_mask
888
+
889
+ sliding_window = getattr(config, "sliding_window", None)
890
+ if sliding_window is None:
891
+ raise ValueError("Could not find a `sliding_window` argument in the config, or it is not set")
892
+
893
+ batch_size, dtype = input_embeds.shape[0], input_embeds.dtype
894
+ mask_factory_function = sliding_window_causal_mask_function(sliding_window)
895
+ mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
896
+
897
+ # Do not allow skip if we are compiling (this is to match BC)
898
+ # TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
899
+ allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
900
+
901
+ # Allow slight deviations from causal mask
902
+ # Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
903
+ # padding mask, etc) as the resulting mask may otherwise not be correct!
904
+ if or_mask_function is not None:
905
+ if not _is_torch_greater_or_equal_than_2_6:
906
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
907
+ mask_factory_function = or_masks(mask_factory_function, or_mask_function)
908
+ allow_is_causal_skip = False
909
+ if and_mask_function is not None:
910
+ if not _is_torch_greater_or_equal_than_2_6:
911
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
912
+ mask_factory_function = and_masks(mask_factory_function, and_mask_function)
913
+ allow_is_causal_skip = False
914
+
915
+ # If we detected packing format
916
+ if packed_sequence_mask is not None and _is_torch_greater_or_equal_than_2_6:
917
+ mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
918
+ allow_is_causal_skip = False
919
+
920
+ # We now create the mask
921
+ causal_mask = mask_interface(
922
+ batch_size=batch_size,
923
+ cache_position=cache_position,
924
+ kv_length=kv_length,
925
+ kv_offset=kv_offset,
926
+ mask_function=mask_factory_function,
927
+ attention_mask=attention_mask,
928
+ allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
929
+ local_size=sliding_window, # Additional kwarg for sdpa
930
+ dtype=dtype, # Additional kwarg for eager
931
+ config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
932
+ )
933
+ return causal_mask
934
+
935
+
936
+ def create_chunked_causal_mask(
937
+ config: PretrainedConfig,
938
+ input_embeds: torch.Tensor,
939
+ attention_mask: Optional[torch.Tensor],
940
+ cache_position: torch.Tensor,
941
+ past_key_values: Optional[Cache],
942
+ position_ids: Optional[torch.Tensor] = None,
943
+ or_mask_function: Optional[Callable] = None,
944
+ and_mask_function: Optional[Callable] = None,
945
+ ) -> Optional[Union[torch.Tensor, BlockMask]]:
946
+ """
947
+ Create a chunked attention causal mask based on the attention implementation used (stored in the config). This type
948
+ of attention pattern was mostly democratized by Llama4. If `past_key_values` has an hybrid cache structure, this
949
+ function will return the mask corresponding to one of the "chunked_attention" layers (to align to what is needed in the
950
+ `modeling_xxx.py` files).
951
+
952
+ Args:
953
+ config (`PretrainedConfig`):
954
+ The model config.
955
+ input_embeds (`torch.Tensor`):
956
+ The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
957
+ batch size, query length and dtype.
958
+ attention_mask (`torch.Tensor`, optional):
959
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
960
+ It can also be an already prepared 4D mask, in which case it is returned as-is.
961
+ cache_position (`torch.Tensor`):
962
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
963
+ past_key_values (`Cache`, optional):
964
+ The past key values, if we use a cache.
965
+ position_ids (`torch.Tensor`, optional)
966
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
967
+ or_mask_function (`Callable`, optional):
968
+ An optional mask function to combine with the chunked causal mask function (by doing the union of both). This is
969
+ useful to easily overlay another mask on top of the chunked causal one, for example for image tokens handling.
970
+ and_mask_function (`Callable`, optional):
971
+ An optional mask function to combine with the chunked causal mask function (by doing the intersection of both). This is
972
+ useful to easily overlay another mask on top of the chunked causal one, for example for image tokens handling.
973
+ """
974
+ # If we have an hybrid cache structure, here we want to create the mask for the sliding layers
975
+ if hasattr(past_key_values, "is_sliding") and True in past_key_values.is_sliding:
976
+ layer_idx = past_key_values.is_sliding.index(True)
977
+ else:
978
+ layer_idx = 0
979
+
980
+ early_exit, attention_mask, packed_sequence_mask, kv_length, kv_offset = _preprocess_mask_arguments(
981
+ config, input_embeds, attention_mask, cache_position, past_key_values, position_ids, layer_idx
982
+ )
983
+ if early_exit:
984
+ return attention_mask
985
+
986
+ chunk_size = getattr(config, "attention_chunk_size", None)
987
+ if chunk_size is None:
988
+ raise ValueError("Could not find an `attention_chunk_size` argument in the config, or it is not set")
989
+
990
+ # Raise if using chunked attention on context too large with FA2
991
+ if config._attn_implementation == "flash_attention_2" and kv_length + kv_offset > chunk_size:
992
+ raise ValueError(
993
+ "Flash attention 2 cannot handle chunked attention, and the key-value length is larger than the chunk size so the "
994
+ "chunked pattern cannot be respected. You should use another `attn_implementation` when instantiating the model"
995
+ )
996
+
997
+ batch_size, dtype = input_embeds.shape[0], input_embeds.dtype
998
+ # For chunked attention and batched inputs, we need to take the number of left padding tokens into account
999
+ # to start the chunk from the actual start of the sequence for the padded sequence
1000
+ if attention_mask is not None:
1001
+ # Only count the left padding tokens, not all of them
1002
+ left_padding_tokens = (attention_mask.cumsum(dim=-1) == torch.zeros_like(attention_mask)).sum(dim=-1)
1003
+ else:
1004
+ left_padding_tokens = torch.zeros(batch_size, device=cache_position.device, dtype=int)
1005
+ # Raise a warning for older versions if the problematic left-padding situation arises
1006
+ if (
1007
+ not _is_torch_greater_or_equal_than_2_6
1008
+ and kv_length + kv_offset > chunk_size
1009
+ and (left_padding_tokens > 0).any()
1010
+ ):
1011
+ logger.warning_once(
1012
+ "Due to limitations of your current torch version, we cannot correctly account for the left-padding "
1013
+ "when computing the chunked attention pattern. This will lead to a wrong attention mask for the padded "
1014
+ "sequences. Behavior will be undefined. Please upgrade to `torch>=2.6` to solve this issue."
1015
+ )
1016
+ mask_factory_function = chunked_causal_mask_function(chunk_size, left_padding_tokens)
1017
+ mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
1018
+
1019
+ # Do not allow skip if we are compiling (this is to match BC)
1020
+ # TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
1021
+ allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
1022
+
1023
+ # Allow slight deviations from causal mask
1024
+ # Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
1025
+ # padding mask, etc) as the resulting mask may otherwise not be correct!
1026
+ if or_mask_function is not None:
1027
+ if not _is_torch_greater_or_equal_than_2_6:
1028
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
1029
+ mask_factory_function = or_masks(mask_factory_function, or_mask_function)
1030
+ allow_is_causal_skip = False
1031
+ if and_mask_function is not None:
1032
+ if not _is_torch_greater_or_equal_than_2_6:
1033
+ raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
1034
+ mask_factory_function = and_masks(mask_factory_function, and_mask_function)
1035
+ allow_is_causal_skip = False
1036
+
1037
+ # If we detected packing format
1038
+ if packed_sequence_mask is not None and _is_torch_greater_or_equal_than_2_6:
1039
+ mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
1040
+ allow_is_causal_skip = False
1041
+
1042
+ # We now create the mask
1043
+ causal_mask = mask_interface(
1044
+ batch_size=batch_size,
1045
+ cache_position=cache_position,
1046
+ kv_length=kv_length,
1047
+ kv_offset=kv_offset,
1048
+ mask_function=mask_factory_function,
1049
+ attention_mask=attention_mask,
1050
+ allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
1051
+ local_size=chunk_size, # Additional kwarg for sdpa
1052
+ dtype=dtype, # Additional kwarg for eager
1053
+ config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
1054
+ )
1055
+ return causal_mask
1056
+
1057
+
1058
+ LAYER_PATTERN_TO_MASK_FUNCTION_MAPPING = {
1059
+ "full_attention": create_causal_mask,
1060
+ "sliding_attention": create_sliding_window_causal_mask,
1061
+ "chunked_attention": create_chunked_causal_mask,
1062
+ }
1063
+
1064
+
1065
+ def create_masks_for_generate(
1066
+ config: PretrainedConfig,
1067
+ input_embeds: torch.Tensor,
1068
+ attention_mask: Optional[torch.Tensor],
1069
+ cache_position: torch.Tensor,
1070
+ past_key_values: Optional[Cache],
1071
+ position_ids: Optional[torch.Tensor] = None,
1072
+ or_mask_function: Optional[Callable] = None,
1073
+ and_mask_function: Optional[Callable] = None,
1074
+ **kwargs,
1075
+ ):
1076
+ """
1077
+ This function mimics how we create the masks in the `modeling_xxx.py` files, and is used in `generate` in order
1078
+ to easily create the masks in advance, when we compile the forwards with Static caches.
1079
+
1080
+ Args:
1081
+ config (`PretrainedConfig`):
1082
+ The model config.
1083
+ input_embeds (`torch.Tensor`):
1084
+ The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
1085
+ batch size, query length and dtype.
1086
+ attention_mask (`torch.Tensor`, optional):
1087
+ The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
1088
+ It can also be an already prepared 4D mask, in which case it is returned as-is.
1089
+ cache_position (`torch.Tensor`):
1090
+ A tensor of shape (query_length,) indicating the current indices of the input sequence elements.
1091
+ past_key_values (`Cache`, optional):
1092
+ The past key values, if we use a cache.
1093
+ position_ids (`torch.Tensor`, optional)
1094
+ A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
1095
+ or_mask_function (`Callable`, optional):
1096
+ An optional mask function to combine with the other mask function (by doing the union of both). This is
1097
+ useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
1098
+ and_mask_function (`Callable`, optional):
1099
+ An optional mask function to combine with the other mask function (by doing the intersection of both). This is
1100
+ useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
1101
+ """
1102
+ # The attribute reside in the text config for composite models
1103
+ effective_config = config.get_text_config()
1104
+ # Prepare the mask args
1105
+ mask_kwargs = {
1106
+ "config": effective_config,
1107
+ "input_embeds": input_embeds,
1108
+ "attention_mask": attention_mask,
1109
+ "cache_position": cache_position,
1110
+ "past_key_values": past_key_values,
1111
+ "position_ids": position_ids,
1112
+ "or_mask_function": or_mask_function,
1113
+ "and_mask_function": and_mask_function,
1114
+ }
1115
+
1116
+ # If the attribute exist, we need several masks
1117
+ if hasattr(effective_config, "layer_types"):
1118
+ causal_masks = {}
1119
+ for layer_pattern in set(effective_config.layer_types):
1120
+ causal_masks[layer_pattern] = LAYER_PATTERN_TO_MASK_FUNCTION_MAPPING[layer_pattern](**mask_kwargs)
1121
+ return causal_masks
1122
+ # In this case, all layers are sliding
1123
+ elif getattr(effective_config, "sliding_window", None) is not None:
1124
+ return create_sliding_window_causal_mask(**mask_kwargs)
1125
+ # In this case, all layers are chunked
1126
+ elif getattr(effective_config, "attention_chunk_size", None) is not None:
1127
+ return create_chunked_causal_mask(**mask_kwargs)
1128
+ # All layers use standard causal attention
1129
+ return create_causal_mask(**mask_kwargs)
1130
+
1131
+
1132
+ # Below are utilities to pretty-print the different masks
1133
+ # Print the matrix with words as row labels
1134
+ GREEN = "\033[92m"
1135
+ YELLOW = "\033[93m"
1136
+ RESET = "\033[0m"
1137
+ BLACK_SQUARE = "■"
1138
+ WHITE_SQUARE = "⬚"
1139
+ GREY_SQUARE = "∙"
1140
+ LOW_TRIANGLE = "⬕"
1141
+ UPPER_TRIANGLE = "⬔"
1142
+
1143
+
1144
+ def get_style(style):
1145
+ if style == "majong":
1146
+ BLACK_SQUARE = "🀞" # Full block (represents "on" or active)
1147
+ BLACK_SQUARE = "🀙" # Full block (represents "on" or active)
1148
+ WHITE_SQUARE = "🀆" # "▒" # Light shade (represents "off" or inactive)
1149
+ LOW_TRIANGLE = "🀛" # Lower left triangle (stylized indication)
1150
+ UPPER_TRIANGLE = "🀛" # Upper left triangle (stylized indication)
1151
+ else:
1152
+ BLACK_SQUARE = "█" # Full block (represents "on" or active)
1153
+ WHITE_SQUARE = "░" # "▒" # Light shade (represents "off" or inactive)
1154
+ LOW_TRIANGLE = "▙" # Lower left triangle (stylized indication))
1155
+ UPPER_TRIANGLE = "▜" # Upper left triangle (stylized indication)
1156
+
1157
+ return BLACK_SQUARE, WHITE_SQUARE, LOW_TRIANGLE, UPPER_TRIANGLE
1158
+
1159
+
1160
+ # LOW_TRIANGLE = UPPER_TRIANGLE = "⟍" # Upper right triangle (stylized indication)
1161
+
1162
+ YELLOW_SQUARE = f"{YELLOW}{BLACK_SQUARE}{RESET}"
1163
+ GREEN_SQUARE = f"{GREEN}{BLACK_SQUARE}{RESET}"
1164
+
1165
+
1166
+ def tensor_to_mask_visual(original_tensor: torch.Tensor, grid_size=(20, 40), style="majong") -> str:
1167
+ BLACK_SQUARE, WHITE_SQUARE, LOW_TRIANGLE, UPPER_TRIANGLE = get_style(style)
1168
+ h, w = original_tensor.shape
1169
+ max_h, max_w = grid_size
1170
+ if not (h < max_h and w < max_w):
1171
+ # Preserve aspect ratio within max grid size
1172
+ aspect_ratio = 2 * w / h
1173
+ if aspect_ratio > 1:
1174
+ w = max_w
1175
+ h = min(max_h, max(1, round(max_w / aspect_ratio)))
1176
+ else:
1177
+ h = max_h
1178
+ w = max(1, round(max_h * aspect_ratio))
1179
+
1180
+ # Step 1: Rescale tensor by average pooling
1181
+ tensor = original_tensor.unsqueeze(0).unsqueeze(0) # Add batch and channel dimensions
1182
+ tensor = F.adaptive_avg_pool2d(tensor, output_size=(h, w))[0, 0] # Remove extra dims
1183
+ else:
1184
+ tensor = original_tensor
1185
+
1186
+ # Step 3: Build the string representation
1187
+ result = []
1188
+ for i in range(h):
1189
+ row = ""
1190
+ for j in range(w):
1191
+ if tensor[i, j] == 1:
1192
+ row += BLACK_SQUARE
1193
+ elif tensor[i, j] == 0:
1194
+ row += WHITE_SQUARE
1195
+ else:
1196
+ if j > 0:
1197
+ if tensor[i, j - 1] == 1:
1198
+ row += LOW_TRIANGLE
1199
+ elif tensor[i, j - 1] == 0:
1200
+ row += UPPER_TRIANGLE
1201
+ else:
1202
+ row += BLACK_SQUARE if tensor[i, j] == 1 else WHITE_SQUARE
1203
+ else:
1204
+ row += (
1205
+ BLACK_SQUARE
1206
+ if tensor[i, j] == 1
1207
+ else (
1208
+ WHITE_SQUARE
1209
+ if tensor[i, j] == 0
1210
+ else (UPPER_TRIANGLE if tensor[i, j + 1] == 1 else LOW_TRIANGLE)
1211
+ )
1212
+ )
1213
+ result.append(row)
1214
+
1215
+ return "\n".join(result)
1216
+
1217
+
1218
+ class AttentionMask(torch.Tensor):
1219
+ def __new__(cls, data, style=None):
1220
+ # Create a new instance of AttentionMask as a Tensor
1221
+ cls.style = style
1222
+ return torch.Tensor._make_subclass(cls, data, require_grad=False)
1223
+
1224
+ def __init__(self, data):
1225
+ # You can initialize any additional metadata here if needed
1226
+ pass
1227
+
1228
+ def to_string(self, grid_size=(20, 40), limit=4):
1229
+ """Returns a string representation of the block mask."""
1230
+ dense_mask = self
1231
+ *batch_dims, num_rows, num_cols = dense_mask.shape
1232
+ total_vis = []
1233
+
1234
+ for idx, batch_idx in enumerate(itertools.product(*[range(i) for i in batch_dims])):
1235
+ if idx == limit:
1236
+ total_vis.append("...")
1237
+ total_vis.append("To print out more, set AttentionMask.to_string(limit=N)")
1238
+ total_vis.append("You can also index (AttentionMask[batch, head]) to choose a specific batch or head")
1239
+ break
1240
+ block_vis = tensor_to_mask_visual(dense_mask[batch_idx], grid_size=grid_size, style=self.style)
1241
+ total_vis.append(block_vis)
1242
+
1243
+ total_vis.append(f"torch.Tensor(shape={tuple(self.shape)}, dtype={self.dtype})")
1244
+ return "\n".join(total_vis)
1245
+
1246
+ def __repr__(self):
1247
+ return self.to_string()
1248
+
1249
+ def __str__(self):
1250
+ return self.to_string()
1251
+
1252
+ @classmethod
1253
+ def from_tensor(cls, tensor: torch.Tensor, style: Optional[str] = None) -> "AttentionMask":
1254
+ res = cls(tensor)
1255
+ res.style = style
1256
+ return res
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_pytorch_utils.py ADDED
@@ -0,0 +1,491 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2021 The HuggingFace Inc. team.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """PyTorch - Flax general utilities."""
16
+
17
+ import os
18
+ from pickle import UnpicklingError
19
+
20
+ import jax
21
+ import jax.numpy as jnp
22
+ import numpy as np
23
+ from flax.serialization import from_bytes
24
+ from flax.traverse_util import flatten_dict, unflatten_dict
25
+
26
+ import transformers
27
+
28
+ from . import is_safetensors_available, is_torch_available
29
+ from .utils import check_torch_load_is_safe, logging
30
+
31
+
32
+ if is_torch_available():
33
+ import torch
34
+
35
+ if is_safetensors_available():
36
+ from safetensors import safe_open
37
+ from safetensors.flax import load_file as safe_load_file
38
+
39
+
40
+ logger = logging.get_logger(__name__)
41
+
42
+
43
+ #####################
44
+ # PyTorch => Flax #
45
+ #####################
46
+
47
+
48
+ def load_pytorch_checkpoint_in_flax_state_dict(
49
+ flax_model, pytorch_checkpoint_path, is_sharded, allow_missing_keys=False
50
+ ):
51
+ """Load pytorch checkpoints in a flax model"""
52
+
53
+ if not is_sharded:
54
+ pt_path = os.path.abspath(pytorch_checkpoint_path)
55
+ logger.info(f"Loading PyTorch weights from {pt_path}")
56
+
57
+ if pt_path.endswith(".safetensors"):
58
+ pt_state_dict = {}
59
+ with safe_open(pt_path, framework="flax") as f:
60
+ for k in f.keys():
61
+ pt_state_dict[k] = f.get_tensor(k)
62
+ else:
63
+ try:
64
+ import torch # noqa: F401
65
+ except (ImportError, ModuleNotFoundError):
66
+ logger.error(
67
+ "Loading a PyTorch model in Flax, requires both PyTorch and Flax to be installed. Please see"
68
+ " https://pytorch.org/ and https://flax.readthedocs.io/en/latest/index.html#installation for installation"
69
+ " instructions."
70
+ )
71
+ raise
72
+
73
+ check_torch_load_is_safe()
74
+ pt_state_dict = torch.load(pt_path, map_location="cpu", weights_only=True)
75
+ logger.info(f"PyTorch checkpoint contains {sum(t.numel() for t in pt_state_dict.values()):,} parameters.")
76
+
77
+ flax_state_dict = convert_pytorch_state_dict_to_flax(pt_state_dict, flax_model)
78
+ else:
79
+ # model is sharded and pytorch_checkpoint_path already contains the list of .pt shard files
80
+ flax_state_dict = convert_pytorch_sharded_state_dict_to_flax(pytorch_checkpoint_path, flax_model)
81
+ return flax_state_dict
82
+
83
+
84
+ def rename_key_and_reshape_tensor(
85
+ pt_tuple_key: tuple[str],
86
+ pt_tensor: np.ndarray,
87
+ random_flax_state_dict: dict[str, jnp.ndarray],
88
+ model_prefix: str,
89
+ ) -> tuple[tuple[str], np.ndarray]:
90
+ """Rename PT weight names to corresponding Flax weight names and reshape tensor if necessary"""
91
+
92
+ def is_key_or_prefix_key_in_dict(key: tuple[str]) -> bool:
93
+ """Checks if `key` of `(prefix,) + key` is in random_flax_state_dict"""
94
+ return len(set(random_flax_state_dict) & {key, (model_prefix,) + key}) > 0
95
+
96
+ # layer norm
97
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("scale",)
98
+ if pt_tuple_key[-1] in ["weight", "gamma"] and is_key_or_prefix_key_in_dict(renamed_pt_tuple_key):
99
+ return renamed_pt_tuple_key, pt_tensor
100
+
101
+ # batch norm layer mean
102
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("mean",)
103
+ if pt_tuple_key[-1] == "running_mean" and not is_key_or_prefix_key_in_dict(pt_tuple_key):
104
+ return renamed_pt_tuple_key, pt_tensor
105
+
106
+ # batch norm layer var
107
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("var",)
108
+ if pt_tuple_key[-1] == "running_var" and not is_key_or_prefix_key_in_dict(pt_tuple_key):
109
+ return renamed_pt_tuple_key, pt_tensor
110
+
111
+ # embedding
112
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("embedding",)
113
+ if pt_tuple_key[-1] == "weight" and is_key_or_prefix_key_in_dict(renamed_pt_tuple_key):
114
+ return renamed_pt_tuple_key, pt_tensor
115
+
116
+ # conv layer
117
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("kernel",)
118
+ if pt_tuple_key[-1] == "weight" and pt_tensor.ndim == 4 and not is_key_or_prefix_key_in_dict(pt_tuple_key):
119
+ pt_tensor = pt_tensor.transpose(2, 3, 1, 0)
120
+ return renamed_pt_tuple_key, pt_tensor
121
+
122
+ # linear layer
123
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("kernel",)
124
+ if pt_tuple_key[-1] == "weight" and not is_key_or_prefix_key_in_dict(pt_tuple_key):
125
+ pt_tensor = pt_tensor.T
126
+ return renamed_pt_tuple_key, pt_tensor
127
+
128
+ # old PyTorch layer norm weight
129
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("weight",)
130
+ if pt_tuple_key[-1] == "gamma":
131
+ return renamed_pt_tuple_key, pt_tensor
132
+
133
+ # old PyTorch layer norm bias
134
+ renamed_pt_tuple_key = pt_tuple_key[:-1] + ("bias",)
135
+ if pt_tuple_key[-1] == "beta":
136
+ return renamed_pt_tuple_key, pt_tensor
137
+
138
+ # New `weight_norm` from https://github.com/huggingface/transformers/pull/24030
139
+ name = None
140
+ if pt_tuple_key[-3::2] == ("parametrizations", "original0"):
141
+ name = pt_tuple_key[-2] + "_g"
142
+ elif pt_tuple_key[-3::2] == ("parametrizations", "original1"):
143
+ name = pt_tuple_key[-2] + "_v"
144
+ if name is not None:
145
+ renamed_pt_tuple_key = pt_tuple_key[:-3] + (name,)
146
+ return renamed_pt_tuple_key, pt_tensor
147
+
148
+ return pt_tuple_key, pt_tensor
149
+
150
+
151
+ def convert_pytorch_state_dict_to_flax(pt_state_dict, flax_model):
152
+ # convert pytorch tensor to numpy
153
+ from_bin = is_torch_available() and isinstance(next(iter(pt_state_dict.values())), torch.Tensor)
154
+ bfloat16 = torch.bfloat16 if from_bin else "bfloat16"
155
+
156
+ weight_dtypes = {k: v.dtype for k, v in pt_state_dict.items()}
157
+
158
+ if from_bin:
159
+ for k, v in pt_state_dict.items():
160
+ # numpy currently does not support bfloat16, need to go over float32 in this case to not lose precision
161
+ if v.dtype == bfloat16:
162
+ v = v.float()
163
+ pt_state_dict[k] = v.cpu().numpy()
164
+
165
+ model_prefix = flax_model.base_model_prefix
166
+
167
+ # use params dict if the model contains batch norm layers
168
+ if "params" in flax_model.params:
169
+ flax_model_params = flax_model.params["params"]
170
+ else:
171
+ flax_model_params = flax_model.params
172
+ random_flax_state_dict = flatten_dict(flax_model_params)
173
+
174
+ # add batch_stats keys,values to dict
175
+ if "batch_stats" in flax_model.params:
176
+ flax_batch_stats = flatten_dict(flax_model.params["batch_stats"])
177
+ random_flax_state_dict.update(flax_batch_stats)
178
+
179
+ flax_state_dict = {}
180
+
181
+ load_model_with_head_into_base_model = (model_prefix not in flax_model_params) and (
182
+ model_prefix in {k.split(".")[0] for k in pt_state_dict}
183
+ )
184
+ load_base_model_into_model_with_head = (model_prefix in flax_model_params) and (
185
+ model_prefix not in {k.split(".")[0] for k in pt_state_dict}
186
+ )
187
+
188
+ # Need to change some parameters name to match Flax names
189
+ for pt_key, pt_tensor in pt_state_dict.items():
190
+ pt_tuple_key = tuple(pt_key.split("."))
191
+ is_bfloat_16 = weight_dtypes[pt_key] == bfloat16
192
+
193
+ # remove base model prefix if necessary
194
+ has_base_model_prefix = pt_tuple_key[0] == model_prefix
195
+ if load_model_with_head_into_base_model and has_base_model_prefix:
196
+ pt_tuple_key = pt_tuple_key[1:]
197
+
198
+ # Correctly rename weight parameters
199
+ flax_key, flax_tensor = rename_key_and_reshape_tensor(
200
+ pt_tuple_key, pt_tensor, random_flax_state_dict, model_prefix
201
+ )
202
+
203
+ # add model prefix if necessary
204
+ require_base_model_prefix = (model_prefix,) + flax_key in random_flax_state_dict
205
+ if load_base_model_into_model_with_head and require_base_model_prefix:
206
+ flax_key = (model_prefix,) + flax_key
207
+
208
+ if flax_key in random_flax_state_dict:
209
+ if flax_tensor.shape != random_flax_state_dict[flax_key].shape:
210
+ raise ValueError(
211
+ f"PyTorch checkpoint seems to be incorrect. Weight {pt_key} was expected to be of shape "
212
+ f"{random_flax_state_dict[flax_key].shape}, but is {flax_tensor.shape}."
213
+ )
214
+
215
+ # add batch stats if the model contains batchnorm layers
216
+ if "batch_stats" in flax_model.params:
217
+ if "mean" in flax_key[-1] or "var" in flax_key[-1]:
218
+ flax_state_dict[("batch_stats",) + flax_key] = jnp.asarray(flax_tensor)
219
+ continue
220
+ # remove num_batches_tracked key
221
+ if "num_batches_tracked" in flax_key[-1]:
222
+ flax_state_dict.pop(flax_key, None)
223
+ continue
224
+
225
+ # also add unexpected weight so that warning is thrown
226
+ flax_state_dict[("params",) + flax_key] = (
227
+ jnp.asarray(flax_tensor) if not is_bfloat_16 else jnp.asarray(flax_tensor, dtype=jnp.bfloat16)
228
+ )
229
+ else:
230
+ # also add unexpected weight so that warning is thrown
231
+ flax_state_dict[flax_key] = (
232
+ jnp.asarray(flax_tensor) if not is_bfloat_16 else jnp.asarray(flax_tensor, dtype=jnp.bfloat16)
233
+ )
234
+
235
+ return unflatten_dict(flax_state_dict)
236
+
237
+
238
+ ############################
239
+ # Sharded Pytorch => Flax #
240
+ ############################
241
+
242
+
243
+ def convert_pytorch_sharded_state_dict_to_flax(shard_filenames, flax_model):
244
+ import torch
245
+
246
+ # Load the index
247
+ flax_state_dict = {}
248
+ for shard_file in shard_filenames:
249
+ # load using msgpack utils
250
+ check_torch_load_is_safe()
251
+ pt_state_dict = torch.load(shard_file, weights_only=True)
252
+ weight_dtypes = {k: v.dtype for k, v in pt_state_dict.items()}
253
+ pt_state_dict = {
254
+ k: v.numpy() if v.dtype != torch.bfloat16 else v.float().numpy() for k, v in pt_state_dict.items()
255
+ }
256
+
257
+ model_prefix = flax_model.base_model_prefix
258
+
259
+ # use params dict if the model contains batch norm layers and then add batch_stats keys,values to dict
260
+ if "batch_stats" in flax_model.params:
261
+ flax_model_params = flax_model.params["params"]
262
+
263
+ random_flax_state_dict = flatten_dict(flax_model_params)
264
+ random_flax_state_dict.update(flatten_dict(flax_model.params["batch_stats"]))
265
+ else:
266
+ flax_model_params = flax_model.params
267
+ random_flax_state_dict = flatten_dict(flax_model_params)
268
+
269
+ load_model_with_head_into_base_model = (model_prefix not in flax_model_params) and (
270
+ model_prefix in {k.split(".")[0] for k in pt_state_dict}
271
+ )
272
+ load_base_model_into_model_with_head = (model_prefix in flax_model_params) and (
273
+ model_prefix not in {k.split(".")[0] for k in pt_state_dict}
274
+ )
275
+ # Need to change some parameters name to match Flax names
276
+ for pt_key, pt_tensor in pt_state_dict.items():
277
+ pt_tuple_key = tuple(pt_key.split("."))
278
+ is_bfloat_16 = weight_dtypes[pt_key] == torch.bfloat16
279
+
280
+ # remove base model prefix if necessary
281
+ has_base_model_prefix = pt_tuple_key[0] == model_prefix
282
+ if load_model_with_head_into_base_model and has_base_model_prefix:
283
+ pt_tuple_key = pt_tuple_key[1:]
284
+
285
+ # Correctly rename weight parameters
286
+ flax_key, flax_tensor = rename_key_and_reshape_tensor(
287
+ pt_tuple_key, pt_tensor, random_flax_state_dict, model_prefix
288
+ )
289
+ # add model prefix if necessary
290
+ require_base_model_prefix = (model_prefix,) + flax_key in random_flax_state_dict
291
+ if load_base_model_into_model_with_head and require_base_model_prefix:
292
+ flax_key = (model_prefix,) + flax_key
293
+
294
+ if flax_key in random_flax_state_dict:
295
+ if flax_tensor.shape != random_flax_state_dict[flax_key].shape:
296
+ raise ValueError(
297
+ f"PyTorch checkpoint seems to be incorrect. Weight {pt_key} was expected to be of shape "
298
+ f"{random_flax_state_dict[flax_key].shape}, but is {flax_tensor.shape}."
299
+ )
300
+
301
+ # add batch stats if the model contains batchnorm layers
302
+ if "batch_stats" in flax_model.params:
303
+ if "mean" in flax_key[-1]:
304
+ flax_state_dict[("batch_stats",) + flax_key] = jnp.asarray(flax_tensor)
305
+ continue
306
+ if "var" in flax_key[-1]:
307
+ flax_state_dict[("batch_stats",) + flax_key] = jnp.asarray(flax_tensor)
308
+ continue
309
+ # remove num_batches_tracked key
310
+ if "num_batches_tracked" in flax_key[-1]:
311
+ flax_state_dict.pop(flax_key, None)
312
+ continue
313
+
314
+ # also add unexpected weight so that warning is thrown
315
+ flax_state_dict[("params",) + flax_key] = (
316
+ jnp.asarray(flax_tensor) if not is_bfloat_16 else jnp.asarray(flax_tensor, dtype=jnp.bfloat16)
317
+ )
318
+
319
+ else:
320
+ # also add unexpected weight so that warning is thrown
321
+ flax_state_dict[flax_key] = (
322
+ jnp.asarray(flax_tensor) if not is_bfloat_16 else jnp.asarray(flax_tensor, dtype=jnp.bfloat16)
323
+ )
324
+ return unflatten_dict(flax_state_dict)
325
+
326
+
327
+ #####################
328
+ # Flax => PyTorch #
329
+ #####################
330
+
331
+
332
+ def load_flax_checkpoint_in_pytorch_model(model, flax_checkpoint_path):
333
+ """Load flax checkpoints in a PyTorch model"""
334
+ flax_checkpoint_path = os.path.abspath(flax_checkpoint_path)
335
+ logger.info(f"Loading Flax weights from {flax_checkpoint_path}")
336
+
337
+ # import correct flax class
338
+ flax_cls = getattr(transformers, "Flax" + model.__class__.__name__)
339
+
340
+ # load flax weight dict
341
+ if flax_checkpoint_path.endswith(".safetensors"):
342
+ flax_state_dict = safe_load_file(flax_checkpoint_path)
343
+ flax_state_dict = unflatten_dict(flax_state_dict, sep=".")
344
+ else:
345
+ with open(flax_checkpoint_path, "rb") as state_f:
346
+ try:
347
+ flax_state_dict = from_bytes(flax_cls, state_f.read())
348
+ except UnpicklingError:
349
+ raise OSError(f"Unable to convert {flax_checkpoint_path} to Flax deserializable object. ")
350
+
351
+ return load_flax_weights_in_pytorch_model(model, flax_state_dict)
352
+
353
+
354
+ def load_flax_weights_in_pytorch_model(pt_model, flax_state):
355
+ """Load flax checkpoints in a PyTorch model"""
356
+
357
+ try:
358
+ import torch # noqa: F401
359
+ except (ImportError, ModuleNotFoundError):
360
+ logger.error(
361
+ "Loading a Flax weights in PyTorch, requires both PyTorch and Flax to be installed. Please see"
362
+ " https://pytorch.org/ and https://flax.readthedocs.io/en/latest/index.html#installation for installation"
363
+ " instructions."
364
+ )
365
+ raise
366
+
367
+ # check if we have bf16 weights
368
+ is_type_bf16 = flatten_dict(jax.tree_util.tree_map(lambda x: x.dtype == jnp.bfloat16, flax_state)).values()
369
+ if any(is_type_bf16):
370
+ # convert all weights to fp32 if the are bf16 since torch.from_numpy can-not handle bf16
371
+ # and bf16 is not fully supported in PT yet.
372
+ logger.warning(
373
+ "Found ``bfloat16`` weights in Flax model. Casting all ``bfloat16`` weights to ``float32`` "
374
+ "before loading those in PyTorch model."
375
+ )
376
+ flax_state = jax.tree_util.tree_map(
377
+ lambda params: params.astype(np.float32) if params.dtype == jnp.bfloat16 else params, flax_state
378
+ )
379
+
380
+ flax_state_dict = flatten_dict(flax_state)
381
+ pt_model_dict = pt_model.state_dict()
382
+
383
+ load_model_with_head_into_base_model = (pt_model.base_model_prefix in flax_state) and (
384
+ pt_model.base_model_prefix not in {k.split(".")[0] for k in pt_model_dict}
385
+ )
386
+ load_base_model_into_model_with_head = (pt_model.base_model_prefix not in flax_state) and (
387
+ pt_model.base_model_prefix in {k.split(".")[0] for k in pt_model_dict}
388
+ )
389
+
390
+ # keep track of unexpected & missing keys
391
+ unexpected_keys = []
392
+ missing_keys = set(pt_model_dict.keys())
393
+
394
+ for flax_key_tuple, flax_tensor in flax_state_dict.items():
395
+ has_base_model_prefix = flax_key_tuple[0] == pt_model.base_model_prefix
396
+ require_base_model_prefix = ".".join((pt_model.base_model_prefix,) + flax_key_tuple) in pt_model_dict
397
+
398
+ # adapt flax_key to prepare for loading from/to base model only
399
+ if load_model_with_head_into_base_model and has_base_model_prefix:
400
+ flax_key_tuple = flax_key_tuple[1:]
401
+ elif load_base_model_into_model_with_head and require_base_model_prefix:
402
+ flax_key_tuple = (pt_model.base_model_prefix,) + flax_key_tuple
403
+
404
+ # rename flax weights to PyTorch format
405
+ if flax_key_tuple[-1] == "kernel" and flax_tensor.ndim == 4 and ".".join(flax_key_tuple) not in pt_model_dict:
406
+ # conv layer
407
+ flax_key_tuple = flax_key_tuple[:-1] + ("weight",)
408
+ flax_tensor = jnp.transpose(flax_tensor, (3, 2, 0, 1))
409
+ elif flax_key_tuple[-1] == "kernel" and ".".join(flax_key_tuple) not in pt_model_dict:
410
+ # linear layer
411
+ flax_key_tuple = flax_key_tuple[:-1] + ("weight",)
412
+ flax_tensor = flax_tensor.T
413
+ elif flax_key_tuple[-1] in ["scale", "embedding"]:
414
+ flax_key_tuple = flax_key_tuple[:-1] + ("weight",)
415
+
416
+ # adding batch stats from flax batch norm to pt
417
+ elif "mean" in flax_key_tuple[-1]:
418
+ flax_key_tuple = flax_key_tuple[:-1] + ("running_mean",)
419
+ elif "var" in flax_key_tuple[-1]:
420
+ flax_key_tuple = flax_key_tuple[:-1] + ("running_var",)
421
+
422
+ if "batch_stats" in flax_state:
423
+ flax_key = ".".join(flax_key_tuple[1:]) # Remove the params/batch_stats header
424
+ else:
425
+ flax_key = ".".join(flax_key_tuple)
426
+
427
+ # We also need to look at `pt_model_dict` and see if there are keys requiring further transformation.
428
+ special_pt_names = {}
429
+ # New `weight_norm` from https://github.com/huggingface/transformers/pull/24030
430
+ for key in pt_model_dict:
431
+ key_components = key.split(".")
432
+ name = None
433
+ if key_components[-3::2] == ["parametrizations", "original0"]:
434
+ name = key_components[-2] + "_g"
435
+ elif key_components[-3::2] == ["parametrizations", "original1"]:
436
+ name = key_components[-2] + "_v"
437
+ if name is not None:
438
+ key_components = key_components[:-3] + [name]
439
+ key_to_check = ".".join(key_components)
440
+ special_pt_names[key_to_check] = key
441
+
442
+ if flax_key in special_pt_names:
443
+ flax_key = special_pt_names[flax_key]
444
+
445
+ if flax_key in pt_model_dict:
446
+ if flax_tensor.shape != pt_model_dict[flax_key].shape:
447
+ raise ValueError(
448
+ f"Flax checkpoint seems to be incorrect. Weight {flax_key_tuple} was expected "
449
+ f"to be of shape {pt_model_dict[flax_key].shape}, but is {flax_tensor.shape}."
450
+ )
451
+ else:
452
+ # add weight to pytorch dict
453
+ flax_tensor = np.asarray(flax_tensor) if not isinstance(flax_tensor, np.ndarray) else flax_tensor
454
+ pt_model_dict[flax_key] = torch.from_numpy(flax_tensor)
455
+ # remove from missing keys
456
+ missing_keys.remove(flax_key)
457
+ else:
458
+ # weight is not expected by PyTorch model
459
+ unexpected_keys.append(flax_key)
460
+
461
+ pt_model.load_state_dict(pt_model_dict)
462
+
463
+ # re-transform missing_keys to list
464
+ missing_keys = list(missing_keys)
465
+
466
+ if len(unexpected_keys) > 0:
467
+ logger.warning(
468
+ "Some weights of the Flax model were not used when initializing the PyTorch model"
469
+ f" {pt_model.__class__.__name__}: {unexpected_keys}\n- This IS expected if you are initializing"
470
+ f" {pt_model.__class__.__name__} from a Flax model trained on another task or with another architecture"
471
+ " (e.g. initializing a BertForSequenceClassification model from a FlaxBertForPreTraining model).\n- This"
472
+ f" IS NOT expected if you are initializing {pt_model.__class__.__name__} from a Flax model that you expect"
473
+ " to be exactly identical (e.g. initializing a BertForSequenceClassification model from a"
474
+ " FlaxBertForSequenceClassification model)."
475
+ )
476
+ else:
477
+ logger.warning(f"All Flax model weights were used when initializing {pt_model.__class__.__name__}.\n")
478
+ if len(missing_keys) > 0:
479
+ logger.warning(
480
+ f"Some weights of {pt_model.__class__.__name__} were not initialized from the Flax model and are newly"
481
+ f" initialized: {missing_keys}\nYou should probably TRAIN this model on a down-stream task to be able to"
482
+ " use it for predictions and inference."
483
+ )
484
+ else:
485
+ logger.warning(
486
+ f"All the weights of {pt_model.__class__.__name__} were initialized from the Flax model.\n"
487
+ "If your task is similar to the task the model of the checkpoint was trained on, "
488
+ f"you can already use {pt_model.__class__.__name__} for predictions without further training."
489
+ )
490
+
491
+ return pt_model
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_layers.py ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from functools import partial
15
+ from typing import Optional
16
+
17
+ import torch
18
+ import torch.nn as nn
19
+
20
+ from .cache_utils import Cache
21
+ from .modeling_outputs import (
22
+ BaseModelOutputWithPast,
23
+ QuestionAnsweringModelOutput,
24
+ SequenceClassifierOutputWithPast,
25
+ TokenClassifierOutput,
26
+ )
27
+ from .models.auto import AutoModel
28
+ from .processing_utils import Unpack
29
+ from .utils import TransformersKwargs, auto_docstring, can_return_tuple, logging
30
+
31
+
32
+ logger = logging.get_logger(__name__)
33
+
34
+
35
+ class GradientCheckpointingLayer(nn.Module):
36
+ """Base class for layers with gradient checkpointing.
37
+
38
+ This class enables gradient checkpointing functionality for a layer. By default, gradient checkpointing is disabled
39
+ (`gradient_checkpointing = False`). When `model.set_gradient_checkpointing()` is called, gradient checkpointing is
40
+ enabled by setting `gradient_checkpointing = True` and assigning a checkpointing function to `_gradient_checkpointing_func`.
41
+
42
+ Important:
43
+
44
+ When using gradient checkpointing with `use_reentrant=True`, inputs that require gradients (e.g. hidden states)
45
+ must be passed as positional arguments (`*args`) rather than keyword arguments to properly propagate gradients.
46
+
47
+ Example:
48
+
49
+ ```python
50
+ >>> # Correct - hidden_states passed as positional arg
51
+ >>> out = self.layer(hidden_states, attention_mask=attention_mask)
52
+
53
+ >>> # Incorrect - hidden_states passed as keyword arg
54
+ >>> out = self.layer(hidden_states=hidden_states, attention_mask=attention_mask)
55
+ ```
56
+ """
57
+
58
+ gradient_checkpointing = False
59
+
60
+ def __call__(self, *args, **kwargs):
61
+ if self.gradient_checkpointing and self.training:
62
+ do_warn = False
63
+ layer_name = self.__class__.__name__
64
+ message = f"Caching is incompatible with gradient checkpointing in {layer_name}. Setting"
65
+
66
+ if "use_cache" in kwargs and kwargs["use_cache"]:
67
+ kwargs["use_cache"] = False
68
+ message += " `use_cache=False`,"
69
+ do_warn = True
70
+
71
+ # different names for the same thing in different layers
72
+ # TODO cyril: this one without `S` can be removed after deprection cycle
73
+ if "past_key_value" in kwargs and kwargs["past_key_value"] is not None:
74
+ kwargs["past_key_value"] = None
75
+ message += " `past_key_value=None`,"
76
+ do_warn = True
77
+
78
+ if "past_key_values" in kwargs and kwargs["past_key_values"] is not None:
79
+ kwargs["past_key_values"] = None
80
+ message += " `past_key_values=None`,"
81
+ do_warn = True
82
+
83
+ if "layer_past" in kwargs and kwargs["layer_past"] is not None:
84
+ kwargs["layer_past"] = None
85
+ message += " `layer_past=None`,"
86
+ do_warn = True
87
+
88
+ # warn if anything was changed
89
+ if do_warn:
90
+ message = message.rstrip(",") + "."
91
+ logger.warning_once(message)
92
+
93
+ return self._gradient_checkpointing_func(partial(super().__call__, **kwargs), *args)
94
+ return super().__call__(*args, **kwargs)
95
+
96
+
97
+ @auto_docstring
98
+ class GenericForSequenceClassification:
99
+ base_model_prefix = "model"
100
+
101
+ def __init__(self, config):
102
+ super().__init__(config)
103
+ self.num_labels = config.num_labels
104
+ # Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
105
+ setattr(self, self.base_model_prefix, AutoModel.from_config(config))
106
+ self.score = nn.Linear(config.hidden_size, self.num_labels, bias=False)
107
+
108
+ # Initialize weights and apply final processing
109
+ self.post_init()
110
+
111
+ @can_return_tuple
112
+ @auto_docstring
113
+ def forward(
114
+ self,
115
+ input_ids: Optional[torch.LongTensor] = None,
116
+ attention_mask: Optional[torch.Tensor] = None,
117
+ position_ids: Optional[torch.LongTensor] = None,
118
+ past_key_values: Optional[Cache] = None,
119
+ inputs_embeds: Optional[torch.FloatTensor] = None,
120
+ labels: Optional[torch.LongTensor] = None,
121
+ use_cache: Optional[bool] = None,
122
+ **kwargs: Unpack[TransformersKwargs],
123
+ ) -> SequenceClassifierOutputWithPast:
124
+ transformer_outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
125
+ input_ids,
126
+ attention_mask=attention_mask,
127
+ position_ids=position_ids,
128
+ past_key_values=past_key_values,
129
+ inputs_embeds=inputs_embeds,
130
+ use_cache=use_cache,
131
+ **kwargs,
132
+ )
133
+ hidden_states = transformer_outputs.last_hidden_state
134
+ logits = self.score(hidden_states)
135
+
136
+ if input_ids is not None:
137
+ batch_size = input_ids.shape[0]
138
+ else:
139
+ batch_size = inputs_embeds.shape[0]
140
+
141
+ if self.config.pad_token_id is None and batch_size != 1:
142
+ raise ValueError("Cannot handle batch sizes > 1 if no padding token is defined.")
143
+ if self.config.pad_token_id is None:
144
+ last_non_pad_token = -1
145
+ elif input_ids is not None:
146
+ # To handle both left- and right- padding, we take the rightmost token that is not equal to pad_token_id
147
+ non_pad_mask = (input_ids != self.config.pad_token_id).to(logits.device, torch.int32)
148
+ token_indices = torch.arange(input_ids.shape[-1], device=logits.device, dtype=torch.int32)
149
+ last_non_pad_token = (token_indices * non_pad_mask).argmax(-1)
150
+ else:
151
+ last_non_pad_token = -1
152
+ logger.warning_once(
153
+ f"{self.__class__.__name__} will not detect padding tokens in `inputs_embeds`. Results may be "
154
+ "unexpected if using padding tokens in conjunction with `inputs_embeds.`"
155
+ )
156
+
157
+ pooled_logits = logits[torch.arange(batch_size, device=logits.device), last_non_pad_token]
158
+
159
+ loss = None
160
+ if labels is not None:
161
+ loss = self.loss_function(logits=logits, labels=labels, pooled_logits=pooled_logits, config=self.config)
162
+
163
+ return SequenceClassifierOutputWithPast(
164
+ loss=loss,
165
+ logits=pooled_logits,
166
+ past_key_values=transformer_outputs.past_key_values,
167
+ hidden_states=transformer_outputs.hidden_states,
168
+ attentions=transformer_outputs.attentions,
169
+ )
170
+
171
+
172
+ @auto_docstring
173
+ class GenericForQuestionAnswering:
174
+ base_model_prefix = "model"
175
+
176
+ def __init__(self, config):
177
+ super().__init__(config)
178
+ # Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
179
+ setattr(self, self.base_model_prefix, AutoModel.from_config(config))
180
+ self.qa_outputs = nn.Linear(config.hidden_size, 2)
181
+
182
+ # Initialize weights and apply final processing
183
+ self.post_init()
184
+
185
+ def get_input_embeddings(self):
186
+ return getattr(self, self.base_model_prefix).embed_tokens
187
+
188
+ def set_input_embeddings(self, value):
189
+ getattr(self, self.base_model_prefix).embed_tokens = value
190
+
191
+ @can_return_tuple
192
+ @auto_docstring
193
+ def forward(
194
+ self,
195
+ input_ids: Optional[torch.LongTensor] = None,
196
+ attention_mask: Optional[torch.Tensor] = None,
197
+ position_ids: Optional[torch.LongTensor] = None,
198
+ past_key_values: Optional[Cache] = None,
199
+ inputs_embeds: Optional[torch.FloatTensor] = None,
200
+ start_positions: Optional[torch.LongTensor] = None,
201
+ end_positions: Optional[torch.LongTensor] = None,
202
+ **kwargs: Unpack[TransformersKwargs],
203
+ ) -> QuestionAnsweringModelOutput:
204
+ outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
205
+ input_ids,
206
+ attention_mask=attention_mask,
207
+ position_ids=position_ids,
208
+ past_key_values=past_key_values,
209
+ inputs_embeds=inputs_embeds,
210
+ **kwargs,
211
+ )
212
+
213
+ sequence_output = outputs.last_hidden_state
214
+
215
+ logits = self.qa_outputs(sequence_output)
216
+ start_logits, end_logits = logits.split(1, dim=-1)
217
+ start_logits = start_logits.squeeze(-1).contiguous()
218
+ end_logits = end_logits.squeeze(-1).contiguous()
219
+
220
+ loss = None
221
+ if start_positions is not None and end_positions is not None:
222
+ loss = self.loss_function(start_logits, end_logits, start_positions, end_positions, **kwargs)
223
+
224
+ return QuestionAnsweringModelOutput(
225
+ loss=loss,
226
+ start_logits=start_logits,
227
+ end_logits=end_logits,
228
+ hidden_states=outputs.hidden_states,
229
+ attentions=outputs.attentions,
230
+ )
231
+
232
+
233
+ @auto_docstring
234
+ class GenericForTokenClassification:
235
+ base_model_prefix = "model"
236
+
237
+ def __init__(self, config):
238
+ super().__init__(config)
239
+ self.num_labels = config.num_labels
240
+ # Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
241
+ setattr(self, self.base_model_prefix, AutoModel.from_config(config))
242
+ if getattr(config, "classifier_dropout", None) is not None:
243
+ classifier_dropout = config.classifier_dropout
244
+ elif getattr(config, "hidden_dropout", None) is not None:
245
+ classifier_dropout = config.hidden_dropout
246
+ else:
247
+ classifier_dropout = 0.1
248
+ self.dropout = nn.Dropout(classifier_dropout)
249
+ self.score = nn.Linear(config.hidden_size, config.num_labels)
250
+
251
+ # Initialize weights and apply final processing
252
+ self.post_init()
253
+
254
+ @can_return_tuple
255
+ @auto_docstring
256
+ def forward(
257
+ self,
258
+ input_ids: Optional[torch.LongTensor] = None,
259
+ attention_mask: Optional[torch.Tensor] = None,
260
+ position_ids: Optional[torch.LongTensor] = None,
261
+ past_key_values: Optional[Cache] = None,
262
+ inputs_embeds: Optional[torch.FloatTensor] = None,
263
+ labels: Optional[torch.LongTensor] = None,
264
+ use_cache: Optional[bool] = None,
265
+ **kwargs: Unpack[TransformersKwargs],
266
+ ) -> TokenClassifierOutput:
267
+ outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
268
+ input_ids,
269
+ attention_mask=attention_mask,
270
+ position_ids=position_ids,
271
+ past_key_values=past_key_values,
272
+ inputs_embeds=inputs_embeds,
273
+ use_cache=use_cache,
274
+ **kwargs,
275
+ )
276
+ sequence_output = outputs.last_hidden_state
277
+ sequence_output = self.dropout(sequence_output)
278
+ logits = self.score(sequence_output)
279
+
280
+ loss = None
281
+ if labels is not None:
282
+ loss = self.loss_function(logits, labels, self.config)
283
+
284
+ return TokenClassifierOutput(
285
+ loss=loss,
286
+ logits=logits,
287
+ hidden_states=outputs.hidden_states,
288
+ attentions=outputs.attentions,
289
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_utils.py ADDED
The diff for this file is too large to render. See raw diff
 
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/tokenization_mistral_common.py ADDED
@@ -0,0 +1,1883 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 Mistral AI and The HuggingFace Inc. team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import os
16
+ import shutil
17
+ import warnings
18
+ from collections.abc import Mapping, Sized
19
+ from enum import Enum
20
+ from pathlib import Path
21
+ from typing import Any, Callable, Optional, Union, overload
22
+
23
+ import numpy as np
24
+
25
+ from transformers.audio_utils import load_audio_as
26
+ from transformers.tokenization_utils_base import (
27
+ LARGE_INTEGER,
28
+ VERY_LARGE_INTEGER,
29
+ BatchEncoding,
30
+ EncodedInput,
31
+ PreTokenizedInput,
32
+ PreTrainedTokenizerBase,
33
+ TextInput,
34
+ TruncationStrategy,
35
+ )
36
+ from transformers.utils import PaddingStrategy, TensorType, add_end_docstrings, logging, to_py_obj
37
+ from transformers.utils.generic import is_torch_tensor
38
+ from transformers.utils.hub import PushToHubMixin
39
+ from transformers.utils.import_utils import is_mistral_common_available, is_torch_available, requires
40
+
41
+
42
+ if is_mistral_common_available():
43
+ from mistral_common.protocol.instruct.request import ChatCompletionRequest
44
+ from mistral_common.protocol.instruct.validator import ValidationMode
45
+ from mistral_common.tokens.tokenizers.base import SpecialTokenPolicy, TokenizerVersion
46
+ from mistral_common.tokens.tokenizers.image import MultiModalVersion
47
+ from mistral_common.tokens.tokenizers.mistral import MistralTokenizer
48
+ from mistral_common.tokens.tokenizers.tekken import Tekkenizer
49
+ from mistral_common.tokens.tokenizers.utils import download_tokenizer_from_hf_hub
50
+
51
+
52
+ if is_torch_available():
53
+ import torch
54
+
55
+
56
+ logger = logging.get_logger(__name__)
57
+
58
+
59
+ ENCODE_KWARGS_DOCSTRING = r"""
60
+ add_special_tokens (`bool`, *optional*, defaults to `True`):
61
+ Whether or not to add special tokens when encoding the sequences. This will use the underlying
62
+ `PretrainedTokenizerBase.build_inputs_with_special_tokens` function, which defines which tokens are
63
+ automatically added to the input ids. This is useful if you want to add `bos` or `eos` tokens
64
+ automatically.
65
+ padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):
66
+ Activates and controls padding. Accepts the following values:
67
+
68
+ - `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single
69
+ sequence is provided).
70
+ - `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
71
+ acceptable input length for the model if that argument is not provided.
72
+ - `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
73
+ lengths).
74
+ truncation (`bool`, `str` or [`~tokenization_utils_base.TruncationStrategy`], *optional*, defaults to `False`):
75
+ Activates and controls truncation. Accepts the following values:
76
+
77
+ - `True` or `'longest_first'`: Truncate to a maximum length specified with the argument `max_length` or
78
+ to the maximum acceptable input length for the model if that argument is not provided.
79
+ - `False` or `'do_not_truncate'` (default): No truncation (i.e., can output batch with sequence lengths
80
+ greater than the model maximum admissible input size).
81
+ max_length (`int`, *optional*):
82
+ Controls the maximum length to use by one of the truncation/padding parameters.
83
+
84
+ If left unset or set to `None`, this will use the predefined model maximum length if a maximum length
85
+ is required by one of the truncation/padding parameters. If the model has no specific maximum input
86
+ length (like XLNet) truncation/padding to a maximum length will be deactivated.
87
+ stride (`int`, *optional*, defaults to 0):
88
+ If set to a number along with `max_length`, the overflowing tokens returned when
89
+ `return_overflowing_tokens=True` will contain some tokens from the end of the truncated sequence
90
+ returned to provide some overlap between truncated and overflowing sequences. The value of this
91
+ argument defines the number of overlapping tokens.
92
+ pad_to_multiple_of (`int`, *optional*):
93
+ If set will pad the sequence to a multiple of the provided value. Requires `padding` to be activated.
94
+ This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability
95
+ `>= 7.5` (Volta).
96
+ padding_side (`str`, *optional*):
97
+ The side on which the model should have padding applied. Should be selected between ['right', 'left'].
98
+ Default value is picked from the class attribute of the same name.
99
+ return_tensors (`str` or [`~utils.TensorType`], *optional*):
100
+ If set, will return tensors instead of list of python integers. Acceptable values are:
101
+
102
+ - `'pt'`: Return PyTorch `torch.Tensor` objects.
103
+ """
104
+
105
+ ENCODE_PLUS_ADDITIONAL_KWARGS_DOCSTRING = r"""
106
+ return_attention_mask (`bool`, *optional*):
107
+ Whether to return the attention mask. If left to the default, will return the attention mask according
108
+ to the specific tokenizer's default, defined by the `return_outputs` attribute.
109
+
110
+ [What are attention masks?](../glossary#attention-mask)
111
+ return_overflowing_tokens (`bool`, *optional*, defaults to `False`):
112
+ Whether or not to return overflowing token sequences. If a pair of sequences of input ids (or a batch
113
+ of pairs) is provided with `truncation_strategy = longest_first` or `True`, an error is raised instead
114
+ of returning overflowing tokens.
115
+ return_special_tokens_mask (`bool`, *optional*, defaults to `False`):
116
+ Whether or not to return special tokens mask information.
117
+ return_offsets_mapping (`bool`, *optional*, defaults to `False`):
118
+ Whether or not to return `(char_start, char_end)` for each token.
119
+
120
+ This is only available on fast tokenizers inheriting from [`PreTrainedTokenizerFast`], if using
121
+ Python's tokenizer, this method will raise `NotImplementedError`.
122
+ return_length (`bool`, *optional*, defaults to `False`):
123
+ Whether or not to return the lengths of the encoded inputs.
124
+ verbose (`bool`, *optional*, defaults to `True`):
125
+ Whether or not to print more information and warnings.
126
+ **kwargs: passed to the `self.tokenize()` method
127
+
128
+ Return:
129
+ [`BatchEncoding`]: A [`BatchEncoding`] with the following fields:
130
+
131
+ - **input_ids** -- List of token ids to be fed to a model.
132
+
133
+ [What are input IDs?](../glossary#input-ids)
134
+
135
+ - **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
136
+ `return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names`).
137
+
138
+ [What are attention masks?](../glossary#attention-mask)
139
+
140
+ - **overflowing_tokens** -- List of overflowing tokens sequences (when a `max_length` is specified and
141
+ `return_overflowing_tokens=True`).
142
+ - **num_truncated_tokens** -- Number of tokens truncated (when a `max_length` is specified and
143
+ `return_overflowing_tokens=True`).
144
+ - **special_tokens_mask** -- List of 0s and 1s, with 1 specifying added special tokens and 0 specifying
145
+ regular sequence tokens (when `add_special_tokens=True` and `return_special_tokens_mask=True`).
146
+ - **length** -- The length of the inputs (when `return_length=True`)
147
+ """
148
+
149
+
150
+ class MistralTokenizerType(str, Enum):
151
+ """Enum for the different type of tokenizer."""
152
+
153
+ spm = "spm"
154
+ tekken = "tekken"
155
+
156
+
157
+ @requires(backends=("mistral-common",))
158
+ class MistralCommonTokenizer(PushToHubMixin):
159
+ """
160
+ Class to wrap `mistral-common` tokenizers.
161
+
162
+ `mistral-common` is the official tokenizer library for Mistral AI models. To use it, you need to install it with:
163
+
164
+ ```bash
165
+ pip install transformers[mistral-common]
166
+ ```
167
+
168
+ Otherwise the tokenizer falls back to the Transformers implementation of the tokenizer.
169
+
170
+ For more info on `mistral-common`, see [mistral-common](https://github.com/mistralai/mistral-common).
171
+
172
+ This class is a wrapper around a `mistral_common.tokens.tokenizers.mistral.MistralTokenizer`.
173
+ It provides a Hugging Face compatible interface to tokenize using the official mistral-common tokenizer.
174
+
175
+ Supports the following methods from the `PreTrainedTokenizerBase` class:
176
+
177
+ - [`~MistralCommonTokenizer.get_vocab`]: Returns the vocabulary as a dictionary of token to index.
178
+ - [`~MistralCommonTokenizer.encode`]: Encode a string to a list of integers.
179
+ - [`~MistralCommonTokenizer.decode`]: Decode a list of integers to a string.
180
+ - [`~MistralCommonTokenizer.batch_decode`]: Decode a batch of list of integers to a list of strings.
181
+ - [`~MistralCommonTokenizer.convert_tokens_to_ids`]: Convert a list of tokens to a list of integers.
182
+ - [`~MistralCommonTokenizer.convert_ids_to_tokens`]: Convert a list of integers to a list of tokens.
183
+ - [`~MistralCommonTokenizer.tokenize`]: Tokenize a string.
184
+ - [`~MistralCommonTokenizer.get_special_tokens_mask`]: Get the special tokens mask for a list of tokens.
185
+ - [`~MistralCommonTokenizer.prepare_for_model`]: Prepare a list of inputs for the model.
186
+ - [`~MistralCommonTokenizer.pad`]: Pad a list of inputs to the same length.
187
+ - [`~MistralCommonTokenizer.truncate_sequences`]: Truncate a list of sequences to the same length.
188
+ - [`~MistralCommonTokenizer.apply_chat_template`]: Apply a chat template to a list of messages.
189
+ - [`~MistralCommonTokenizer.__call__`]: Tokenize a string or a list of strings.
190
+ - [`~MistralCommonTokenizer.from_pretrained`]: Download and cache a pretrained tokenizer from the Hugging Face model hub or local directory.
191
+ - [`~MistralCommonTokenizer.save_pretrained`]: Save a tokenizer to a directory, so it can be reloaded using the `from_pretrained` class method.
192
+ - [`~MistralCommonTokenizer.push_to_hub`]: Upload tokenizer to the Hugging Face model hub.
193
+
194
+ Here are the key differences with the `PreTrainedTokenizerBase` class:
195
+
196
+ - Pair of sequences are not supported. The signature have been kept for compatibility but all arguments related to pair of sequences are ignored. The return values of pairs are returned as `None`.
197
+ - The `is_split_into_words` argument is not supported.
198
+ - The `return_token_type_ids` argument is not supported.
199
+ - It is not possible to add new tokens to the tokenizer. Also the special tokens are handled differently from Transformers. In `mistral-common`, special tokens are never encoded directly. This means that: `tokenizer.encode("<s>")` will not return the ID of the `<s>` token. Instead, it will return a list of IDs corresponding to the tokenization of the string `"<s>"`. For more information, see the [mistral-common documentation](https://mistralai.github.io/mistral-common/usage/tokenizers/#special-tokens).
200
+
201
+ If you have suggestions to improve this class, please open an issue on the [mistral-common GitHub repository](https://github.com/mistralai/mistral-common/issues) if it is related to the tokenizer or on the [Transformers GitHub repository](https://github.com/huggingface/transformers/issues) if it is related to the Hugging Face interface.
202
+ """
203
+
204
+ model_input_names: list[str] = ["input_ids", "attention_mask"]
205
+ padding_side: str = "left"
206
+ truncation_side: str = "right"
207
+
208
+ def __init__(
209
+ self,
210
+ tokenizer_path: Union[str, os.PathLike, Path],
211
+ mode: ValidationMode = ValidationMode.test,
212
+ model_max_length: int = VERY_LARGE_INTEGER,
213
+ padding_side: str = "left",
214
+ truncation_side: str = "right",
215
+ model_input_names: Optional[list[str]] = None,
216
+ clean_up_tokenization_spaces: bool = False,
217
+ **kwargs,
218
+ ):
219
+ """
220
+ Constructs a `MistralCommonTokenizer`.
221
+
222
+ - **model_input_names** (`List[str]`) -- A list of inputs expected in the forward pass of the model.
223
+ - **padding_side** (`str`) -- The default value for the side on which the model should have padding applied.
224
+ Should be `'right'` or `'left'`.
225
+ - **truncation_side** (`str`) -- The default value for the side on which the model should have truncation
226
+ applied. Should be `'right'` or `'left'`.
227
+
228
+ Args:
229
+ tokenizer_path (`str` or `os.PathLike` or `Path`):
230
+ Path to the tokenizer file to load the `MistralTokenizer`.
231
+ mode (`ValidationMode`, *optional*, defaults to `ValidationMode.test`):
232
+ The mode to use for the tokenizer. This will be passed to the `MistralTokenizer` constructor.
233
+ model_max_length (`int`, *optional*):
234
+ The maximum length (in number of tokens) for the inputs to the transformer model. When the tokenizer is
235
+ loaded with [`~tokenization_utils_base.PreTrainedTokenizerBase.from_pretrained`], this will be set to the
236
+ value stored for the associated model in `max_model_input_sizes` (see above). If no value is provided, will
237
+ default to VERY_LARGE_INTEGER (`int(1e30)`).
238
+ padding_side (`str`, *optional*):
239
+ The side on which the model should have padding applied. Should be selected between ['right', 'left'].
240
+ Default value is picked from the class attribute of the same name.
241
+ truncation_side (`str`, *optional*):
242
+ The side on which the model should have truncation applied. Should be selected between ['right', 'left'].
243
+ Default value is picked from the class attribute of the same name.
244
+ model_input_names (`List[string]`, *optional*):
245
+ The list of inputs accepted by the forward pass of the model (like `"token_type_ids"` or
246
+ `"attention_mask"`). Default value is picked from the class attribute of the same name.
247
+ clean_up_tokenization_spaces (`bool`, *optional*, defaults to `False`):
248
+ Whether or not the model should cleanup the spaces that were added when splitting the input text during the
249
+ tokenization process.
250
+ """
251
+ if kwargs:
252
+ raise ValueError(f"Kwargs {list(kwargs.keys())} are not supported to init `MistralCommonTokenizer`.")
253
+
254
+ self._tokenizer_path = Path(tokenizer_path)
255
+ self.tokenizer: MistralTokenizer = MistralTokenizer.from_file(str(self._tokenizer_path), mode=mode)
256
+ self._tokenizer_type = (
257
+ MistralTokenizerType.tekken
258
+ if isinstance(self.tokenizer.instruct_tokenizer.tokenizer, Tekkenizer)
259
+ else MistralTokenizerType.spm
260
+ )
261
+ self.truncation_side = truncation_side
262
+ self.padding_side = padding_side
263
+ self.model_max_length = model_max_length
264
+ self.cleanup_tokenization_spaces = clean_up_tokenization_spaces
265
+ self.deprecation_warnings = {} # Use to store when we have already noticed a deprecation warning (avoid overlogging).
266
+
267
+ if model_input_names is not None:
268
+ if (
269
+ not isinstance(model_input_names, (list, tuple))
270
+ and len(model_input_names) == 0
271
+ and not all(isinstance(i, str) for i in model_input_names)
272
+ ):
273
+ raise ValueError(
274
+ "`model_input_names` should be a non-empty list or tuple of str but got an empty value."
275
+ )
276
+ self.model_input_names = model_input_names
277
+
278
+ self._cache_get_vocab: Optional[dict[str, int]] = None
279
+
280
+ @property
281
+ def bos_token_id(self) -> int:
282
+ """
283
+ Id of the beginning of sentence token in the vocabulary.
284
+ """
285
+ return self.tokenizer.instruct_tokenizer.tokenizer.bos_id
286
+
287
+ @property
288
+ def eos_token_id(self) -> int:
289
+ """
290
+ Id of the end of sentence token in the vocabulary.
291
+ """
292
+ return self.tokenizer.instruct_tokenizer.tokenizer.eos_id
293
+
294
+ @property
295
+ def unk_token_id(self) -> int:
296
+ """
297
+ Id of the unknown token in the vocabulary.
298
+ """
299
+ return self.tokenizer.instruct_tokenizer.tokenizer.unk_id
300
+
301
+ @property
302
+ def pad_token_id(self) -> int:
303
+ """
304
+ Id of the padding token in the vocabulary.
305
+ """
306
+ return self.tokenizer.instruct_tokenizer.tokenizer.pad_id
307
+
308
+ @property
309
+ def bos_token(self) -> str:
310
+ """
311
+ String associated to the beginning of sentence token in the vocabulary.
312
+ """
313
+ return self.convert_ids_to_tokens(self.bos_token_id)
314
+
315
+ @property
316
+ def eos_token(self) -> str:
317
+ """
318
+ String associated to the end of sentence token in the vocabulary.
319
+ """
320
+ return self.convert_ids_to_tokens(self.eos_token_id)
321
+
322
+ @property
323
+ def unk_token(self) -> str:
324
+ """
325
+ String associated to the unknown token in the vocabulary.
326
+ """
327
+ return self.convert_ids_to_tokens(self.unk_token_id)
328
+
329
+ @property
330
+ def pad_token(self) -> str:
331
+ """
332
+ String associated to the padding token in the vocabulary.
333
+ """
334
+ return self.convert_ids_to_tokens(self.pad_token_id)
335
+
336
+ @property
337
+ def vocab_size(self) -> int:
338
+ """
339
+ Returns the size of the vocabulary.
340
+
341
+ `int`: Size of the vocabulary.
342
+ """
343
+ return self.tokenizer.instruct_tokenizer.tokenizer.n_words
344
+
345
+ def get_vocab(self) -> dict[str, int]:
346
+ """
347
+ Returns the vocabulary as a dictionary of token to index.
348
+
349
+ This is a lossy conversion. There may be multiple token ids that decode to the same
350
+ string due to partial UTF-8 byte sequences being converted to �.
351
+
352
+ Returns:
353
+ `Dict[str, int]`: The vocabulary.
354
+ """
355
+ if self._cache_get_vocab is None:
356
+ self._cache_get_vocab = {
357
+ token: idx for idx, token in enumerate(self.tokenizer.instruct_tokenizer.tokenizer.vocab())
358
+ }
359
+ return self._cache_get_vocab
360
+
361
+ def __len__(self):
362
+ """
363
+ Size of the full vocabulary with the added tokens.
364
+ """
365
+ return self.vocab_size
366
+
367
+ @add_end_docstrings(
368
+ ENCODE_KWARGS_DOCSTRING,
369
+ """
370
+ **kwargs: Not supported by `MistralCommonTokenizer.encode`.
371
+ Will raise an error if used.
372
+ """,
373
+ """
374
+ Returns:
375
+ `List[int]`, `torch.Tensor`: The tokenized ids of the text.
376
+ """,
377
+ )
378
+ def encode(
379
+ self,
380
+ text: Union[TextInput, EncodedInput],
381
+ text_pair: None = None,
382
+ add_special_tokens: bool = True,
383
+ padding: Union[bool, str, PaddingStrategy] = False,
384
+ truncation: Union[bool, str, TruncationStrategy, None] = None,
385
+ max_length: Optional[int] = None,
386
+ stride: int = 0,
387
+ pad_to_multiple_of: Optional[int] = None,
388
+ padding_side: Optional[str] = None,
389
+ return_tensors: Optional[Union[str, TensorType]] = None,
390
+ verbose: bool = True,
391
+ **kwargs,
392
+ ) -> list[int]:
393
+ """
394
+ Converts a string to a sequence of ids (integer), using the tokenizer and vocabulary.
395
+
396
+ Args:
397
+ text (`str` or `List[int]`):
398
+ The first sequence to be encoded. This can be a string or a list of integers (tokenized string ids).
399
+ text_pair (`None`, *optional*):
400
+ Not supported by `MistralCommonTokenizer.encode`. Kept to match `PreTrainedTokenizerBase.encode` signature.
401
+ """
402
+ if kwargs:
403
+ raise ValueError(f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.encode`.")
404
+ if text_pair:
405
+ raise ValueError("`MistralCommonTokenizer.encode` does not support `text_pair`.")
406
+
407
+ padding_strategy, truncation_strategy, max_length, _ = self._get_padding_truncation_strategies(
408
+ padding=padding,
409
+ truncation=truncation,
410
+ max_length=max_length,
411
+ pad_to_multiple_of=pad_to_multiple_of,
412
+ verbose=verbose,
413
+ )
414
+
415
+ encoded_inputs = self._encode_plus(
416
+ text,
417
+ add_special_tokens=add_special_tokens,
418
+ padding_strategy=padding_strategy,
419
+ truncation_strategy=truncation_strategy,
420
+ max_length=max_length,
421
+ stride=stride,
422
+ pad_to_multiple_of=pad_to_multiple_of,
423
+ padding_side=padding_side,
424
+ return_tensors=return_tensors,
425
+ return_attention_mask=False,
426
+ return_overflowing_tokens=False,
427
+ return_special_tokens_mask=False,
428
+ return_length=False,
429
+ verbose=verbose,
430
+ )
431
+
432
+ return encoded_inputs["input_ids"]
433
+
434
+ def decode(
435
+ self,
436
+ token_ids: Union[int, list[int], np.ndarray, "torch.Tensor"],
437
+ skip_special_tokens: bool = False,
438
+ clean_up_tokenization_spaces: Optional[bool] = None,
439
+ **kwargs,
440
+ ) -> str:
441
+ """
442
+ Converts a sequence of ids in a string, using the tokenizer and vocabulary with options to remove special
443
+ tokens and clean up tokenization spaces.
444
+
445
+ Args:
446
+ token_ids (`Union[int, List[int], np.ndarray, torch.Tensor]`):
447
+ List of tokenized input ids. Can be obtained using the `__call__` method.
448
+ skip_special_tokens (`bool`, *optional*, defaults to `False`):
449
+ Whether or not to remove special tokens in the decoding.
450
+ clean_up_tokenization_spaces (`bool`, *optional*):
451
+ Whether or not to clean up the tokenization spaces. If `None`, will default to
452
+ `self.clean_up_tokenization_spaces`.
453
+ kwargs (additional keyword arguments, *optional*):
454
+ Not supported by `MistralCommonTokenizer.decode`.
455
+ Will raise an error if used.
456
+
457
+ Returns:
458
+ `str`: The decoded sentence.
459
+ """
460
+ if kwargs:
461
+ raise ValueError(f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.decode`.")
462
+
463
+ clean_up_tokenization_spaces = clean_up_tokenization_spaces or self.cleanup_tokenization_spaces
464
+
465
+ # Convert inputs to python lists
466
+ token_ids = to_py_obj(token_ids)
467
+
468
+ special_token_policy = SpecialTokenPolicy.IGNORE if skip_special_tokens else SpecialTokenPolicy.KEEP
469
+
470
+ decoded_string = self.tokenizer.decode(token_ids, special_token_policy=special_token_policy)
471
+ if clean_up_tokenization_spaces:
472
+ decoded_string = PreTrainedTokenizerBase.clean_up_tokenization(decoded_string)
473
+
474
+ return decoded_string
475
+
476
+ def batch_decode(
477
+ self,
478
+ sequences: Union[list[int], list[list[int]], np.ndarray, "torch.Tensor"],
479
+ skip_special_tokens: bool = False,
480
+ clean_up_tokenization_spaces: Optional[bool] = None,
481
+ **kwargs,
482
+ ) -> list[str]:
483
+ """
484
+ Convert a list of lists of token ids into a list of strings by calling decode.
485
+
486
+ Args:
487
+ sequences (`Union[List[int], List[List[int]], np.ndarray, torch.Tensor]`):
488
+ List of tokenized input ids. Can be obtained using the `__call__` method.
489
+ skip_special_tokens (`bool`, *optional*, defaults to `False`):
490
+ Whether or not to remove special tokens in the decoding.
491
+ clean_up_tokenization_spaces (`bool`, *optional*):
492
+ Whether or not to clean up the tokenization spaces. If `None`, will default to
493
+ `self.clean_up_tokenization_spaces`.
494
+ kwargs (additional keyword arguments, *optional*):
495
+ Not supported by `MistralCommonTokenizer.batch_decode`.
496
+ Will raise an error if used.
497
+
498
+ Returns:
499
+ `List[str]`: The list of decoded sentences.
500
+ """
501
+ return [
502
+ self.decode(
503
+ seq,
504
+ skip_special_tokens=skip_special_tokens,
505
+ clean_up_tokenization_spaces=clean_up_tokenization_spaces,
506
+ **kwargs,
507
+ )
508
+ for seq in sequences
509
+ ]
510
+
511
+ def _is_control_token(self, token_id: int) -> bool:
512
+ if self._tokenizer_type == MistralTokenizerType.spm:
513
+ return token_id in self.tokenizer.instruct_tokenizer.tokenizer._control_tokens()
514
+ elif self._tokenizer_type == MistralTokenizerType.tekken:
515
+ return token_id < self.tokenizer.instruct_tokenizer.tokenizer.num_special_tokens
516
+ else:
517
+ raise ValueError(f"Unknown tokenizer type: {self._tokenizer_type}")
518
+
519
+ @overload
520
+ def convert_ids_to_tokens(self, ids: int, skip_special_tokens: bool = False) -> str: ...
521
+ @overload
522
+ def convert_ids_to_tokens(self, ids: list[int], skip_special_tokens: bool = False) -> list[str]: ...
523
+ def convert_ids_to_tokens(
524
+ self, ids: Union[int, list[int]], skip_special_tokens: bool = False
525
+ ) -> Union[str, list[str]]:
526
+ """
527
+ Converts a single index or a sequence of indices in a token or a sequence of tokens, using the vocabulary and
528
+ added tokens.
529
+
530
+ Args:
531
+ ids (`int` or `List[int]`):
532
+ The token id (or token ids) to convert to tokens.
533
+ skip_special_tokens (`bool`, *optional*, defaults to `False`):
534
+ Whether or not to remove special tokens in the decoding.
535
+
536
+ Returns:
537
+ `str` or `List[str]`: The decoded token(s).
538
+ """
539
+
540
+ if isinstance(ids, int):
541
+ one_token = True
542
+ ids = [ids]
543
+ else:
544
+ one_token = False
545
+
546
+ tokens: list[str] = []
547
+ for token_id in ids:
548
+ if self._is_control_token(token_id) and skip_special_tokens:
549
+ continue
550
+ tokens.append(self.tokenizer.instruct_tokenizer.tokenizer.id_to_piece(token_id))
551
+
552
+ if one_token:
553
+ if tokens == []:
554
+ raise ValueError(f"Invalid token id {ids}.")
555
+
556
+ return tokens[0]
557
+ return tokens
558
+
559
+ def _piece_to_id(self, piece: str) -> int:
560
+ if self._tokenizer_type == MistralTokenizerType.spm:
561
+ return self.tokenizer.instruct_tokenizer.tokenizer._model.piece_to_id(piece)
562
+ elif self._tokenizer_type == MistralTokenizerType.tekken:
563
+ pieces = self.tokenizer.instruct_tokenizer.tokenizer._model.encode(
564
+ piece, allowed_special="all", disallowed_special=set()
565
+ )
566
+ assert len(pieces) == 1, f"Expected to decode 1 token, got {len(pieces)}"
567
+ return pieces[0]
568
+ else:
569
+ raise ValueError(f"Unknown tokenizer type: {self._tokenizer_type}")
570
+
571
+ def convert_tokens_to_ids(self, tokens: Union[str, list[str]]) -> Union[int, list[int]]:
572
+ """
573
+ Converts a token string (or a sequence of tokens) in a single integer id (or a sequence of ids), using the
574
+ vocabulary.
575
+
576
+ Args:
577
+ tokens (`str` or `List[str]`): One or several token(s) to convert to token id(s).
578
+
579
+ Returns:
580
+ `int` or `List[int]`: The token id or list of token ids.
581
+ """
582
+
583
+ if isinstance(tokens, str):
584
+ one_token = True
585
+ tokens = [tokens]
586
+ else:
587
+ one_token = False
588
+
589
+ ids: list[int] = []
590
+ for token in tokens:
591
+ ids.append(self._piece_to_id(token))
592
+
593
+ if one_token:
594
+ return ids[0]
595
+ return ids
596
+
597
+ def _text_to_ids(self, text: TextInput, add_special_tokens: bool) -> list[int]:
598
+ """
599
+ Converts a string into a sequence of tokens ids, using the tokenizer.
600
+ """
601
+ tokens_ids = self.tokenizer.instruct_tokenizer.tokenizer.encode(
602
+ text, bos=add_special_tokens, eos=add_special_tokens
603
+ )
604
+ return tokens_ids
605
+
606
+ def tokenize(self, text: TextInput, **kwargs) -> list[str]:
607
+ """
608
+ Converts a string into a sequence of tokens, using the tokenizer.
609
+
610
+ Split in words for word-based vocabulary or sub-words for sub-word-based vocabularies.
611
+
612
+ Args:
613
+ text (`str`):
614
+ The sequence to be encoded.
615
+ **kwargs (additional keyword arguments):
616
+ Not supported by `MistralCommonTokenizer.tokenize`.
617
+ Will raise an error if used.
618
+
619
+ Returns:
620
+ `List[str]`: The list of tokens.
621
+ """
622
+ if kwargs:
623
+ raise ValueError(f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.tokenize`.")
624
+
625
+ return self.convert_ids_to_tokens(self._text_to_ids(text, add_special_tokens=False), skip_special_tokens=False)
626
+
627
+ def _encode_plus(
628
+ self,
629
+ text: Union[TextInput, EncodedInput],
630
+ add_special_tokens: bool = True,
631
+ padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
632
+ truncation_strategy: TruncationStrategy = TruncationStrategy.DO_NOT_TRUNCATE,
633
+ max_length: Optional[int] = None,
634
+ stride: int = 0,
635
+ pad_to_multiple_of: Optional[int] = None,
636
+ padding_side: Optional[str] = None,
637
+ return_tensors: Optional[Union[str, TensorType]] = None,
638
+ return_attention_mask: Optional[bool] = None,
639
+ return_overflowing_tokens: bool = False,
640
+ return_special_tokens_mask: bool = False,
641
+ return_length: bool = False,
642
+ verbose: bool = True,
643
+ **kwargs,
644
+ ) -> BatchEncoding:
645
+ if kwargs:
646
+ raise ValueError(
647
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer._encode_plus`."
648
+ )
649
+
650
+ def get_input_ids(text):
651
+ if isinstance(text, str):
652
+ return self._text_to_ids(text, add_special_tokens)
653
+ elif isinstance(text, (list, tuple)) and len(text) > 0 and isinstance(text[0], int):
654
+ return text
655
+ else:
656
+ raise ValueError(f"Input {text} is not valid. Should be a string, or a list/tuple of integers.")
657
+
658
+ ids = get_input_ids(text)
659
+
660
+ return self.prepare_for_model(
661
+ ids,
662
+ add_special_tokens=add_special_tokens,
663
+ padding=padding_strategy.value,
664
+ truncation=truncation_strategy.value,
665
+ max_length=max_length,
666
+ stride=stride,
667
+ pad_to_multiple_of=pad_to_multiple_of,
668
+ padding_side=padding_side,
669
+ return_tensors=return_tensors,
670
+ prepend_batch_axis=True,
671
+ return_attention_mask=return_attention_mask,
672
+ return_overflowing_tokens=return_overflowing_tokens,
673
+ return_special_tokens_mask=return_special_tokens_mask,
674
+ return_length=return_length,
675
+ verbose=verbose,
676
+ )
677
+
678
+ def _batch_encode_plus(
679
+ self,
680
+ batch_text: Union[
681
+ list[TextInput],
682
+ list[EncodedInput],
683
+ ],
684
+ add_special_tokens: bool = True,
685
+ padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
686
+ truncation_strategy: TruncationStrategy = TruncationStrategy.DO_NOT_TRUNCATE,
687
+ max_length: Optional[int] = None,
688
+ stride: int = 0,
689
+ pad_to_multiple_of: Optional[int] = None,
690
+ padding_side: Optional[str] = None,
691
+ return_tensors: Optional[Union[str, TensorType]] = None,
692
+ return_attention_mask: Optional[bool] = None,
693
+ return_overflowing_tokens: bool = False,
694
+ return_special_tokens_mask: bool = False,
695
+ return_offsets_mapping: bool = False,
696
+ return_length: bool = False,
697
+ verbose: bool = True,
698
+ **kwargs,
699
+ ) -> BatchEncoding:
700
+ def get_input_ids(text):
701
+ if isinstance(text, str):
702
+ return self._text_to_ids(text, add_special_tokens)
703
+ elif isinstance(text, (list, tuple)) and len(text) > 0 and isinstance(text[0], int):
704
+ return text
705
+ else:
706
+ raise ValueError("Input is not valid. Should be a string or a list/tuple of integers.")
707
+
708
+ if return_offsets_mapping:
709
+ raise NotImplementedError(
710
+ "return_offset_mapping is not available when using Python tokenizers. "
711
+ "To use this feature, change your tokenizer to one deriving from "
712
+ "transformers.PreTrainedTokenizerFast."
713
+ )
714
+
715
+ input_ids = []
716
+ for ids in batch_text:
717
+ input_ids.append(get_input_ids(ids))
718
+
719
+ batch_outputs = self._batch_prepare_for_model(
720
+ input_ids,
721
+ add_special_tokens=add_special_tokens,
722
+ padding_strategy=padding_strategy,
723
+ truncation_strategy=truncation_strategy,
724
+ max_length=max_length,
725
+ stride=stride,
726
+ pad_to_multiple_of=pad_to_multiple_of,
727
+ padding_side=padding_side,
728
+ return_attention_mask=return_attention_mask,
729
+ return_overflowing_tokens=return_overflowing_tokens,
730
+ return_special_tokens_mask=return_special_tokens_mask,
731
+ return_length=return_length,
732
+ return_tensors=return_tensors,
733
+ verbose=verbose,
734
+ )
735
+
736
+ return BatchEncoding(batch_outputs)
737
+
738
+ def _all_special_ids(self) -> set[int]:
739
+ if self._tokenizer_type == MistralTokenizerType.tekken:
740
+ return {t["rank"] for t in self.tokenizer.instruct_tokenizer.tokenizer._all_special_tokens}
741
+ elif self._tokenizer_type == MistralTokenizerType.spm:
742
+ return self.tokenizer.instruct_tokenizer.tokenizer._control_tokens()
743
+ else:
744
+ raise ValueError(f"Unknown tokenizer type: {self._tokenizer_type}")
745
+
746
+ def get_special_tokens_mask(
747
+ self, token_ids_0: list, token_ids_1: None = None, already_has_special_tokens: bool = False
748
+ ) -> list[int]:
749
+ """
750
+ Retrieves sequence ids from a token list that has no special tokens added. This method is called when adding
751
+ special tokens using the tokenizer `prepare_for_model` or `encode_plus` methods.
752
+
753
+ Args:
754
+ token_ids_0 (`List[int]`):
755
+ List of ids of the sequence.
756
+ token_ids_1 (`List[int]`, *optional*):
757
+ Not supported by `MistralCommonTokenizer`. Kept to match the interface of `PreTrainedTokenizerBase`.
758
+ already_has_special_tokens (`bool`, *optional*, defaults to `False`):
759
+ Whether or not the token list is already formatted with special tokens for the model.
760
+
761
+ Returns:
762
+ A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
763
+ """
764
+ if token_ids_1 is not None:
765
+ raise ValueError(
766
+ "`token_ids_1` is not supported by `MistralCommonTokenizer` and should be `None`, kept for compatibility."
767
+ )
768
+ if already_has_special_tokens:
769
+ raise ValueError(
770
+ "`already_has_special_tokens` is not supported by `MistralCommonTokenizer` and should be `False`."
771
+ )
772
+
773
+ all_special_ids = self._all_special_ids() # cache the ids
774
+
775
+ special_tokens_mask = [1 if token in all_special_ids else 0 for token in token_ids_0]
776
+ return special_tokens_mask
777
+
778
+ def _batch_prepare_for_model(
779
+ self,
780
+ batch_ids: list[Union[PreTokenizedInput, list[int]]],
781
+ add_special_tokens: bool = True,
782
+ padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
783
+ truncation_strategy: TruncationStrategy = TruncationStrategy.DO_NOT_TRUNCATE,
784
+ max_length: Optional[int] = None,
785
+ stride: int = 0,
786
+ pad_to_multiple_of: Optional[int] = None,
787
+ padding_side: Optional[str] = None,
788
+ return_tensors: Optional[str] = None,
789
+ return_attention_mask: Optional[bool] = None,
790
+ return_overflowing_tokens: bool = False,
791
+ return_special_tokens_mask: bool = False,
792
+ return_length: bool = False,
793
+ verbose: bool = True,
794
+ ) -> BatchEncoding:
795
+ """
796
+ Prepares a sequence of input id so that it can be used by the model. It
797
+ adds special tokens, truncates sequences if overflowing while taking into account the special tokens and
798
+ manages a moving window (with user defined stride) for overflowing tokens.
799
+
800
+ Args:
801
+ batch_ids: list of tokenized input ids
802
+ """
803
+
804
+ batch_outputs = {}
805
+ for ids in batch_ids:
806
+ outputs = self.prepare_for_model(
807
+ ids,
808
+ add_special_tokens=add_special_tokens,
809
+ padding=PaddingStrategy.DO_NOT_PAD.value, # we pad in batch afterward
810
+ truncation=truncation_strategy.value,
811
+ max_length=max_length,
812
+ stride=stride,
813
+ pad_to_multiple_of=None, # we pad in batch afterward
814
+ padding_side=None, # we pad in batch afterward
815
+ return_attention_mask=False, # we pad in batch afterward
816
+ return_overflowing_tokens=return_overflowing_tokens,
817
+ return_special_tokens_mask=return_special_tokens_mask,
818
+ return_length=return_length,
819
+ return_tensors=None, # We convert the whole batch to tensors at the end
820
+ prepend_batch_axis=False,
821
+ verbose=verbose,
822
+ )
823
+
824
+ for key, value in outputs.items():
825
+ if key not in batch_outputs:
826
+ batch_outputs[key] = []
827
+ batch_outputs[key].append(value)
828
+
829
+ batch_outputs = self.pad(
830
+ batch_outputs,
831
+ padding=padding_strategy.value,
832
+ max_length=max_length,
833
+ pad_to_multiple_of=pad_to_multiple_of,
834
+ padding_side=padding_side,
835
+ return_attention_mask=return_attention_mask,
836
+ )
837
+
838
+ batch_outputs = BatchEncoding(batch_outputs, tensor_type=return_tensors)
839
+
840
+ return batch_outputs
841
+
842
+ @add_end_docstrings(ENCODE_KWARGS_DOCSTRING, ENCODE_PLUS_ADDITIONAL_KWARGS_DOCSTRING)
843
+ def prepare_for_model(
844
+ self,
845
+ ids: list[int],
846
+ pair_ids: None = None,
847
+ add_special_tokens: bool = True,
848
+ padding: Union[bool, str, PaddingStrategy] = False,
849
+ truncation: Union[bool, str, TruncationStrategy, None] = None,
850
+ max_length: Optional[int] = None,
851
+ stride: int = 0,
852
+ pad_to_multiple_of: Optional[int] = None,
853
+ padding_side: Optional[str] = None,
854
+ return_tensors: Optional[Union[str, TensorType]] = None,
855
+ return_attention_mask: Optional[bool] = None,
856
+ return_overflowing_tokens: bool = False,
857
+ return_special_tokens_mask: bool = False,
858
+ return_length: bool = False,
859
+ verbose: bool = True,
860
+ prepend_batch_axis: bool = False,
861
+ **kwargs,
862
+ ) -> BatchEncoding:
863
+ """
864
+ Prepares a sequence of input id so that it can be used by the model. It
865
+ adds special tokens, truncates sequences if overflowing while taking into account the special tokens and
866
+ manages a moving window (with user defined stride) for overflowing tokens.
867
+
868
+ Args:
869
+ ids (`List[int]`):
870
+ Tokenized input ids of the first sequence.
871
+ pair_ids (`None`, *optional*):
872
+ Not supported by `MistralCommonTokenizer`. Kept to match the interface of `PreTrainedTokenizerBase`.
873
+ """
874
+ if pair_ids is not None:
875
+ raise ValueError(
876
+ "`pair_ids` is not supported by `MistralCommonTokenizer` and should be `None`, kept for compatibility."
877
+ )
878
+ if kwargs:
879
+ raise ValueError(
880
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.prepare_for_model`."
881
+ )
882
+
883
+ padding_strategy, truncation_strategy, max_length, _ = self._get_padding_truncation_strategies(
884
+ padding=padding,
885
+ truncation=truncation,
886
+ max_length=max_length,
887
+ pad_to_multiple_of=pad_to_multiple_of,
888
+ verbose=verbose,
889
+ )
890
+
891
+ len_ids = len(ids)
892
+
893
+ # Load from model defaults
894
+ if return_attention_mask is None:
895
+ return_attention_mask = "attention_mask" in self.model_input_names
896
+
897
+ encoded_inputs = {}
898
+
899
+ # Truncation: Handle max sequence length
900
+ overflowing_tokens = []
901
+ if truncation_strategy != TruncationStrategy.DO_NOT_TRUNCATE and max_length and len_ids > max_length:
902
+ ids, _, overflowing_tokens = self.truncate_sequences(
903
+ ids,
904
+ num_tokens_to_remove=len_ids - max_length,
905
+ truncation_strategy=truncation_strategy,
906
+ stride=stride,
907
+ )
908
+
909
+ if return_overflowing_tokens:
910
+ encoded_inputs["overflowing_tokens"] = overflowing_tokens
911
+ encoded_inputs["num_truncated_tokens"] = len_ids - max_length
912
+
913
+ # Build output dictionary
914
+ encoded_inputs[self.model_input_names[0]] = ids
915
+ if return_special_tokens_mask:
916
+ if add_special_tokens:
917
+ encoded_inputs["special_tokens_mask"] = self.get_special_tokens_mask(ids, None)
918
+ else:
919
+ encoded_inputs["special_tokens_mask"] = [0] * len(ids)
920
+
921
+ # Padding
922
+ if padding_strategy != PaddingStrategy.DO_NOT_PAD or return_attention_mask:
923
+ encoded_inputs = self.pad(
924
+ encoded_inputs,
925
+ max_length=max_length,
926
+ padding=padding_strategy.value,
927
+ pad_to_multiple_of=pad_to_multiple_of,
928
+ padding_side=padding_side,
929
+ return_attention_mask=return_attention_mask,
930
+ )
931
+
932
+ if return_length:
933
+ encoded_inputs["length"] = len(encoded_inputs["input_ids"])
934
+
935
+ batch_outputs = BatchEncoding(
936
+ encoded_inputs, tensor_type=return_tensors, prepend_batch_axis=prepend_batch_axis
937
+ )
938
+
939
+ return batch_outputs
940
+
941
+ def _get_padding_truncation_strategies(
942
+ self,
943
+ padding: Union[str, PaddingStrategy, bool] = False,
944
+ truncation: Optional[Union[str, TruncationStrategy, bool]] = None,
945
+ max_length: Optional[int] = None,
946
+ pad_to_multiple_of: Optional[int] = None,
947
+ verbose: bool = True,
948
+ **kwargs,
949
+ ):
950
+ """
951
+ Find the correct padding/truncation strategy.
952
+ """
953
+
954
+ # Backward compatibility for previous behavior, maybe we should deprecate it:
955
+ # If you only set max_length, it activates truncation for max_length
956
+ if max_length is not None and padding is False and truncation is None:
957
+ if verbose:
958
+ if not self.deprecation_warnings.get("Truncation-not-explicitly-activated", False):
959
+ logger.warning(
960
+ "Truncation was not explicitly activated but `max_length` is provided a specific value, please"
961
+ " use `truncation=True` to explicitly truncate examples to max length. Defaulting to"
962
+ " 'longest_first' truncation strategy. If you encode pairs of sequences (GLUE-style) with the"
963
+ " tokenizer you can select this strategy more precisely by providing a specific strategy to"
964
+ " `truncation`."
965
+ )
966
+ self.deprecation_warnings["Truncation-not-explicitly-activated"] = True
967
+ truncation = "longest_first"
968
+
969
+ # Get padding strategy
970
+ if padding is not False:
971
+ if padding is True:
972
+ if verbose:
973
+ if max_length is not None and (
974
+ truncation is None or truncation is False or truncation == "do_not_truncate"
975
+ ):
976
+ warnings.warn(
977
+ "`max_length` is ignored when `padding`=`True` and there is no truncation strategy. "
978
+ "To pad to max length, use `padding='max_length'`."
979
+ )
980
+ padding_strategy = PaddingStrategy.LONGEST # Default to pad to the longest sequence in the batch
981
+ elif not isinstance(padding, PaddingStrategy):
982
+ padding_strategy = PaddingStrategy(padding)
983
+ elif isinstance(padding, PaddingStrategy):
984
+ padding_strategy = padding
985
+ else:
986
+ padding_strategy = PaddingStrategy.DO_NOT_PAD
987
+
988
+ # Get truncation strategy
989
+ if truncation is not False and truncation is not None:
990
+ if truncation is True:
991
+ truncation_strategy = (
992
+ TruncationStrategy.LONGEST_FIRST
993
+ ) # Default to truncate the longest sequences in pairs of inputs
994
+ elif not isinstance(truncation, TruncationStrategy):
995
+ truncation_strategy = TruncationStrategy(truncation)
996
+ elif isinstance(truncation, TruncationStrategy):
997
+ truncation_strategy = truncation
998
+ if truncation in [TruncationStrategy.ONLY_FIRST, TruncationStrategy.ONLY_SECOND]:
999
+ raise ValueError(
1000
+ "Truncation strategy `only_first` and `only_second` are not supported by `MistralCommonTokenizer`."
1001
+ )
1002
+ else:
1003
+ truncation_strategy = TruncationStrategy.DO_NOT_TRUNCATE
1004
+
1005
+ # Set max length if needed
1006
+ if max_length is None:
1007
+ if padding_strategy == PaddingStrategy.MAX_LENGTH:
1008
+ if self.model_max_length > LARGE_INTEGER:
1009
+ if verbose:
1010
+ if not self.deprecation_warnings.get("Asking-to-pad-to-max_length", False):
1011
+ logger.warning(
1012
+ "Asking to pad to max_length but no maximum length is provided and the model has no"
1013
+ " predefined maximum length. Default to no padding."
1014
+ )
1015
+ self.deprecation_warnings["Asking-to-pad-to-max_length"] = True
1016
+ padding_strategy = PaddingStrategy.DO_NOT_PAD
1017
+ else:
1018
+ max_length = self.model_max_length
1019
+
1020
+ if truncation_strategy != TruncationStrategy.DO_NOT_TRUNCATE:
1021
+ if self.model_max_length > LARGE_INTEGER:
1022
+ if verbose:
1023
+ if not self.deprecation_warnings.get("Asking-to-truncate-to-max_length", False):
1024
+ logger.warning(
1025
+ "Asking to truncate to max_length but no maximum length is provided and the model has"
1026
+ " no predefined maximum length. Default to no truncation."
1027
+ )
1028
+ self.deprecation_warnings["Asking-to-truncate-to-max_length"] = True
1029
+ truncation_strategy = TruncationStrategy.DO_NOT_TRUNCATE
1030
+ else:
1031
+ max_length = self.model_max_length
1032
+
1033
+ # Test if we have a padding token
1034
+ if padding_strategy != PaddingStrategy.DO_NOT_PAD and (self.pad_token is None or self.pad_token_id < 0):
1035
+ raise ValueError(
1036
+ "Asking to pad but the tokenizer does not have a padding token. "
1037
+ "Please select a token to use as `pad_token` `(tokenizer.pad_token = tokenizer.eos_token e.g.)` "
1038
+ "or add a new pad token via `tokenizer.add_special_tokens({'pad_token': '[PAD]'})`."
1039
+ )
1040
+
1041
+ # Check that we will truncate to a multiple of pad_to_multiple_of if both are provided
1042
+ if (
1043
+ truncation_strategy != TruncationStrategy.DO_NOT_TRUNCATE
1044
+ and padding_strategy != PaddingStrategy.DO_NOT_PAD
1045
+ and pad_to_multiple_of is not None
1046
+ and max_length is not None
1047
+ and (max_length % pad_to_multiple_of != 0)
1048
+ ):
1049
+ raise ValueError(
1050
+ "Truncation and padding are both activated but "
1051
+ f"truncation length ({max_length}) is not a multiple of pad_to_multiple_of ({pad_to_multiple_of})."
1052
+ )
1053
+
1054
+ return padding_strategy, truncation_strategy, max_length, kwargs
1055
+
1056
+ def _pad(
1057
+ self,
1058
+ encoded_inputs: Union[dict[str, EncodedInput], BatchEncoding],
1059
+ max_length: Optional[int] = None,
1060
+ padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
1061
+ pad_to_multiple_of: Optional[int] = None,
1062
+ padding_side: Optional[str] = None,
1063
+ return_attention_mask: Optional[bool] = None,
1064
+ ) -> dict:
1065
+ """
1066
+ Pad encoded inputs (on left/right and up to predefined length or max length in the batch)
1067
+
1068
+ Args:
1069
+ encoded_inputs:
1070
+ Dictionary of tokenized inputs (`List[int]`) or batch of tokenized inputs (`List[List[int]]`).
1071
+ max_length: maximum length of the returned list and optionally padding length (see below).
1072
+ Will truncate by taking into account the special tokens.
1073
+ padding_strategy: PaddingStrategy to use for padding.
1074
+
1075
+ - PaddingStrategy.LONGEST Pad to the longest sequence in the batch
1076
+ - PaddingStrategy.MAX_LENGTH: Pad to the max length (default)
1077
+ - PaddingStrategy.DO_NOT_PAD: Do not pad
1078
+ The tokenizer padding sides are defined in `padding_side` argument:
1079
+
1080
+ - 'left': pads on the left of the sequences
1081
+ - 'right': pads on the right of the sequences
1082
+ pad_to_multiple_of: (optional) Integer if set will pad the sequence to a multiple of the provided value.
1083
+ This is especially useful to enable the use of Tensor Core on NVIDIA hardware with compute capability
1084
+ `>= 7.5` (Volta).
1085
+ padding_side:
1086
+ The side on which the model should have padding applied. Should be selected between ['right', 'left'].
1087
+ Default value is picked from the class attribute of the same name.
1088
+ return_attention_mask:
1089
+ (optional) Set to False to avoid returning attention mask (default: set to model specifics)
1090
+ """
1091
+ # Load from model defaults
1092
+ if return_attention_mask is None:
1093
+ return_attention_mask = "attention_mask" in self.model_input_names
1094
+
1095
+ required_input = encoded_inputs[self.model_input_names[0]]
1096
+
1097
+ if padding_strategy == PaddingStrategy.LONGEST:
1098
+ max_length = len(required_input)
1099
+
1100
+ if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
1101
+ max_length = ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of
1102
+
1103
+ needs_to_be_padded = padding_strategy != PaddingStrategy.DO_NOT_PAD and len(required_input) != max_length
1104
+
1105
+ # Initialize attention mask if not present.
1106
+ if return_attention_mask and "attention_mask" not in encoded_inputs:
1107
+ encoded_inputs["attention_mask"] = [1] * len(required_input)
1108
+
1109
+ if needs_to_be_padded:
1110
+ difference = max_length - len(required_input)
1111
+ padding_side = padding_side if padding_side is not None else self.padding_side
1112
+
1113
+ if padding_side == "right":
1114
+ if return_attention_mask:
1115
+ encoded_inputs["attention_mask"] = encoded_inputs["attention_mask"] + [0] * difference
1116
+ if "special_tokens_mask" in encoded_inputs:
1117
+ encoded_inputs["special_tokens_mask"] = encoded_inputs["special_tokens_mask"] + [1] * difference
1118
+ encoded_inputs[self.model_input_names[0]] = required_input + [self.pad_token_id] * difference
1119
+ elif padding_side == "left":
1120
+ if return_attention_mask:
1121
+ encoded_inputs["attention_mask"] = [0] * difference + encoded_inputs["attention_mask"]
1122
+ if "special_tokens_mask" in encoded_inputs:
1123
+ encoded_inputs["special_tokens_mask"] = [1] * difference + encoded_inputs["special_tokens_mask"]
1124
+ encoded_inputs[self.model_input_names[0]] = [self.pad_token_id] * difference + required_input
1125
+ else:
1126
+ raise ValueError(f"Invalid padding strategy:{padding_side}")
1127
+
1128
+ return encoded_inputs
1129
+
1130
+ def pad(
1131
+ self,
1132
+ encoded_inputs: Union[
1133
+ BatchEncoding,
1134
+ list[BatchEncoding],
1135
+ dict[str, EncodedInput],
1136
+ dict[str, list[EncodedInput]],
1137
+ list[dict[str, EncodedInput]],
1138
+ ],
1139
+ padding: Union[bool, str, PaddingStrategy] = True,
1140
+ max_length: Optional[int] = None,
1141
+ pad_to_multiple_of: Optional[int] = None,
1142
+ padding_side: Optional[str] = None,
1143
+ return_attention_mask: Optional[bool] = None,
1144
+ return_tensors: Optional[Union[str, TensorType]] = None,
1145
+ verbose: bool = True,
1146
+ ) -> BatchEncoding:
1147
+ """
1148
+ Pad a single encoded input or a batch of encoded inputs up to predefined length or to the max sequence length
1149
+ in the batch.
1150
+
1151
+ Padding side (left/right) padding token ids are defined at the tokenizer level (with `self.padding_side`,
1152
+ `self.pad_token_id`).
1153
+ <Tip>
1154
+
1155
+ If the `encoded_inputs` passed are dictionary of numpy arrays, PyTorch tensors, the
1156
+ result will use the same type unless you provide a different tensor type with `return_tensors`. In the case of
1157
+ PyTorch tensors, you will lose the specific device of your tensors however.
1158
+
1159
+ </Tip>
1160
+
1161
+ Args:
1162
+ encoded_inputs ([`BatchEncoding`], list of [`BatchEncoding`], `Dict[str, List[int]]`, `Dict[str, List[List[int]]` or `List[Dict[str, List[int]]]`):
1163
+ Tokenized inputs. Can represent one input ([`BatchEncoding`] or `Dict[str, List[int]]`) or a batch of
1164
+ tokenized inputs (list of [`BatchEncoding`], *Dict[str, List[List[int]]]* or *List[Dict[str,
1165
+ List[int]]]*) so you can use this method during preprocessing as well as in a PyTorch Dataloader
1166
+ collate function.
1167
+
1168
+ Instead of `List[int]` you can have tensors (numpy arrays, PyTorch tensors), see
1169
+ the note above for the return type.
1170
+ padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `True`):
1171
+ Select a strategy to pad the returned sequences (according to the model's padding side and padding
1172
+ index) among:
1173
+
1174
+ - `True` or `'longest'` (default): Pad to the longest sequence in the batch (or no padding if only a single
1175
+ sequence if provided).
1176
+ - `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
1177
+ acceptable input length for the model if that argument is not provided.
1178
+ - `False` or `'do_not_pad'`: No padding (i.e., can output a batch with sequences of different
1179
+ lengths).
1180
+ max_length (`int`, *optional*):
1181
+ Maximum length of the returned list and optionally padding length (see above).
1182
+ pad_to_multiple_of (`int`, *optional*):
1183
+ If set will pad the sequence to a multiple of the provided value.
1184
+
1185
+ This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability
1186
+ `>= 7.5` (Volta).
1187
+ padding_side (`str`, *optional*):
1188
+ The side on which the model should have padding applied. Should be selected between ['right', 'left'].
1189
+ Default value is picked from the class attribute of the same name.
1190
+ return_attention_mask (`bool`, *optional*):
1191
+ Whether to return the attention mask. If left to the default, will return the attention mask according
1192
+ to the specific tokenizer's default, defined by the `return_outputs` attribute.
1193
+
1194
+ [What are attention masks?](../glossary#attention-mask)
1195
+ return_tensors (`str` or [`~utils.TensorType`], *optional*):
1196
+ If set, will return tensors instead of list of python integers. Acceptable values are:
1197
+
1198
+ - `'pt'`: Return PyTorch `torch.Tensor` objects.
1199
+ - `'np'`: Return Numpy `np.ndarray` objects.
1200
+ verbose (`bool`, *optional*, defaults to `True`):
1201
+ Whether or not to print more information and warnings.
1202
+ """
1203
+ # If we have a list of dicts, let's convert it in a dict of lists
1204
+ # We do this to allow using this method as a collate_fn function in PyTorch Dataloader
1205
+ if isinstance(encoded_inputs, (list, tuple)) and isinstance(encoded_inputs[0], Mapping):
1206
+ encoded_inputs = {key: [example[key] for example in encoded_inputs] for key in encoded_inputs[0]}
1207
+
1208
+ # The model's main input name, usually `input_ids`, has been passed for padding
1209
+ if self.model_input_names[0] not in encoded_inputs:
1210
+ raise ValueError(
1211
+ "You should supply an encoding or a list of encodings to this method "
1212
+ f"that includes {self.model_input_names[0]}, but you provided {list(encoded_inputs.keys())}"
1213
+ )
1214
+
1215
+ required_input = encoded_inputs[self.model_input_names[0]]
1216
+
1217
+ if required_input is None or (isinstance(required_input, Sized) and len(required_input) == 0):
1218
+ if return_attention_mask:
1219
+ encoded_inputs["attention_mask"] = []
1220
+ return encoded_inputs
1221
+
1222
+ # If we have PyTorch/TF/NumPy tensors/arrays as inputs, we cast them as python objects
1223
+ # and rebuild them afterwards if no return_tensors is specified
1224
+ # Note that we lose the specific device the tensor may be on for PyTorch
1225
+
1226
+ first_element = required_input[0]
1227
+ if isinstance(first_element, (list, tuple)):
1228
+ # first_element might be an empty list/tuple in some edge cases so we grab the first non empty element.
1229
+ for item in required_input:
1230
+ if len(item) != 0:
1231
+ first_element = item[0]
1232
+ break
1233
+ # At this state, if `first_element` is still a list/tuple, it's an empty one so there is nothing to do.
1234
+ if not isinstance(first_element, (int, list, tuple)):
1235
+ if is_torch_tensor(first_element):
1236
+ return_tensors = "pt" if return_tensors is None else return_tensors
1237
+ elif isinstance(first_element, np.ndarray):
1238
+ return_tensors = "np" if return_tensors is None else return_tensors
1239
+ else:
1240
+ raise ValueError(
1241
+ f"type of {first_element} unknown: {type(first_element)}. "
1242
+ "Should be one of a python, numpy, pytorch or tensorflow object."
1243
+ )
1244
+
1245
+ for key, value in encoded_inputs.items():
1246
+ encoded_inputs[key] = to_py_obj(value)
1247
+
1248
+ # Convert padding_strategy in PaddingStrategy
1249
+ padding_strategy, _, max_length, _ = self._get_padding_truncation_strategies(
1250
+ padding=padding, max_length=max_length, verbose=verbose
1251
+ )
1252
+
1253
+ required_input = encoded_inputs[self.model_input_names[0]]
1254
+ if required_input and not isinstance(required_input[0], (list, tuple)):
1255
+ encoded_inputs = self._pad(
1256
+ encoded_inputs,
1257
+ max_length=max_length,
1258
+ padding_strategy=padding_strategy,
1259
+ pad_to_multiple_of=pad_to_multiple_of,
1260
+ padding_side=padding_side,
1261
+ return_attention_mask=return_attention_mask,
1262
+ )
1263
+ return BatchEncoding(encoded_inputs, tensor_type=return_tensors)
1264
+
1265
+ batch_size = len(required_input)
1266
+ assert all(len(v) == batch_size for v in encoded_inputs.values()), (
1267
+ "Some items in the output dictionary have a different batch size than others."
1268
+ )
1269
+
1270
+ if padding_strategy == PaddingStrategy.LONGEST:
1271
+ max_length = max(len(inputs) for inputs in required_input)
1272
+ padding_strategy = PaddingStrategy.MAX_LENGTH
1273
+
1274
+ batch_outputs = {}
1275
+ for i in range(batch_size):
1276
+ inputs = {k: v[i] for k, v in encoded_inputs.items()}
1277
+ outputs = self._pad(
1278
+ inputs,
1279
+ max_length=max_length,
1280
+ padding_strategy=padding_strategy,
1281
+ pad_to_multiple_of=pad_to_multiple_of,
1282
+ padding_side=padding_side,
1283
+ return_attention_mask=return_attention_mask,
1284
+ )
1285
+
1286
+ for key, value in outputs.items():
1287
+ if key not in batch_outputs:
1288
+ batch_outputs[key] = []
1289
+ batch_outputs[key].append(value)
1290
+
1291
+ return BatchEncoding(batch_outputs, tensor_type=return_tensors)
1292
+
1293
+ def truncate_sequences(
1294
+ self,
1295
+ ids: list[int],
1296
+ pair_ids: None = None,
1297
+ num_tokens_to_remove: int = 0,
1298
+ truncation_strategy: Union[str, TruncationStrategy] = "longest_first",
1299
+ stride: int = 0,
1300
+ **kwargs,
1301
+ ) -> tuple[list[int], None, list[int]]:
1302
+ """
1303
+ Truncates a sequence pair in-place following the strategy.
1304
+
1305
+ Args:
1306
+ ids (`List[int]`):
1307
+ Tokenized input ids. Can be obtained from a string by chaining the `tokenize` and
1308
+ `convert_tokens_to_ids` methods.
1309
+ pair_ids (`None`, *optional*):
1310
+ Not supported by `MistralCommonTokenizer`. Kept to match the signature of `PreTrainedTokenizerBase.truncate_sequences`.
1311
+ num_tokens_to_remove (`int`, *optional*, defaults to 0):
1312
+ Number of tokens to remove using the truncation strategy.
1313
+ truncation_strategy (`str` or [`~tokenization_utils_base.TruncationStrategy`], *optional*, defaults to `'longest_first'`):
1314
+ The strategy to follow for truncation. Can be:
1315
+
1316
+ - `'longest_first'`: Truncate to a maximum length specified with the argument `max_length` or to the
1317
+ maximum acceptable input length for the model if that argument is not provided.
1318
+ - `'do_not_truncate'` (default): No truncation (i.e., can output batch with sequence lengths greater
1319
+ than the model maximum admissible input size).
1320
+ stride (`int`, *optional*, defaults to 0):
1321
+ If set to a positive number, the overflowing tokens returned will contain some tokens from the main
1322
+ sequence returned. The value of this argument defines the number of additional tokens.
1323
+
1324
+ Returns:
1325
+ `Tuple[List[int], None, List[int]]`: The truncated `ids` and the list of
1326
+ overflowing tokens. `None` is returned to match Transformers signature.
1327
+ """
1328
+ if kwargs:
1329
+ raise ValueError(
1330
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.truncate_sequences`."
1331
+ )
1332
+ if pair_ids:
1333
+ raise ValueError("`pair_ids` is not supported by `MistralCommonTokenizer.truncate_sequences`.")
1334
+
1335
+ if num_tokens_to_remove <= 0:
1336
+ return (ids, None, [])
1337
+
1338
+ if not isinstance(truncation_strategy, TruncationStrategy):
1339
+ truncation_strategy = TruncationStrategy(truncation_strategy)
1340
+
1341
+ if truncation_strategy in [TruncationStrategy.ONLY_FIRST, TruncationStrategy.ONLY_SECOND]:
1342
+ raise ValueError(
1343
+ f"Only {TruncationStrategy.LONGEST_FIRST} and {TruncationStrategy.DO_NOT_TRUNCATE} are supported."
1344
+ )
1345
+
1346
+ overflowing_tokens = []
1347
+ if truncation_strategy == TruncationStrategy.LONGEST_FIRST:
1348
+ if len(ids) > num_tokens_to_remove:
1349
+ window_len = min(len(ids), stride + num_tokens_to_remove)
1350
+ if self.truncation_side == "left":
1351
+ overflowing_tokens = ids[:window_len]
1352
+ ids = ids[num_tokens_to_remove:]
1353
+ elif self.truncation_side == "right":
1354
+ overflowing_tokens = ids[-window_len:]
1355
+ ids = ids[:-num_tokens_to_remove]
1356
+ else:
1357
+ raise ValueError(f"invalid truncation strategy: {self.truncation_side}, use 'left' or 'right'.")
1358
+
1359
+ else:
1360
+ error_msg = (
1361
+ f"We need to remove {num_tokens_to_remove} to truncate the input "
1362
+ f"but the first sequence has a length {len(ids)}. "
1363
+ )
1364
+ logger.error(error_msg)
1365
+
1366
+ return (ids, None, overflowing_tokens)
1367
+
1368
+ def apply_chat_template(
1369
+ self,
1370
+ conversation: Union[list[dict[str, str]], list[list[dict[str, str]]]],
1371
+ tools: Optional[list[Union[dict, Callable]]] = None,
1372
+ continue_final_message: bool = False,
1373
+ tokenize: bool = True,
1374
+ padding: Union[bool, str, PaddingStrategy] = False,
1375
+ truncation: bool = False,
1376
+ max_length: Optional[int] = None,
1377
+ return_tensors: Optional[Union[str, TensorType]] = None,
1378
+ return_dict: bool = False,
1379
+ **kwargs,
1380
+ ) -> Union[str, list[int], list[str], list[list[int]], BatchEncoding]:
1381
+ """
1382
+ Converts a list of dictionaries with `"role"` and `"content"` keys to a list of token
1383
+ ids.
1384
+
1385
+ Args:
1386
+ conversation (Union[List[Dict[str, str]], List[List[Dict[str, str]]]]): A list of dicts
1387
+ with "role" and "content" keys, representing the chat history so far.
1388
+ tools (`List[Union[Dict, Callable]]`, *optional*):
1389
+ A list of tools (callable functions) that will be accessible to the model. If the template does not
1390
+ support function calling, this argument will have no effect. Each tool should be passed as a JSON Schema,
1391
+ giving the name, description and argument types for the tool. See our
1392
+ [chat templating guide](https://huggingface.co/docs/transformers/main/en/chat_templating#automated-function-conversion-for-tool-use)
1393
+ for more information.
1394
+ continue_final_message (bool, *optional*):
1395
+ If this is set, the chat will be formatted so that the final
1396
+ message in the chat is open-ended, without any EOS tokens. The model will continue this message
1397
+ rather than starting a new one. This allows you to "prefill" part of
1398
+ the model's response for it. Cannot be used at the same time as `add_generation_prompt`.
1399
+ tokenize (`bool`, defaults to `True`):
1400
+ Whether to tokenize the output. If `False`, the output will be a string.
1401
+ padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):
1402
+ Select a strategy to pad the returned sequences (according to the model's padding side and padding
1403
+ index) among:
1404
+
1405
+ - `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single
1406
+ sequence if provided).
1407
+ - `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
1408
+ acceptable input length for the model if that argument is not provided.
1409
+ - `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
1410
+ lengths).
1411
+ truncation (`bool`, defaults to `False`):
1412
+ Whether to truncate sequences at the maximum length. Has no effect if tokenize is `False`.
1413
+ max_length (`int`, *optional*):
1414
+ Maximum length (in tokens) to use for padding or truncation. Has no effect if tokenize is `False`. If
1415
+ not specified, the tokenizer's `max_length` attribute will be used as a default.
1416
+ return_tensors (`str` or [`~utils.TensorType`], *optional*):
1417
+ If set, will return tensors of a particular framework. Has no effect if tokenize is `False`. Acceptable
1418
+ values are:
1419
+ - `'pt'`: Return PyTorch `torch.Tensor` objects.
1420
+ return_dict (`bool`, defaults to `False`):
1421
+ Whether to return a dictionary with named outputs. Has no effect if tokenize is `False`.
1422
+ If at least one conversation contains an image, its pixel values will be returned in the `pixel_values` key.
1423
+ kwargs (additional keyword arguments, *optional*):
1424
+ Not supported by `MistralCommonTokenizer.apply_chat_template`.
1425
+ Will raise an error if used.
1426
+
1427
+ Returns:
1428
+ `Union[str, List[int], List[str], List[List[int]], BatchEncoding]`: A list of token ids representing the tokenized chat so far, including control
1429
+ tokens. This output is ready to pass to the model, either directly or via methods like `generate()`.
1430
+ """
1431
+ if kwargs:
1432
+ raise ValueError(
1433
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.apply_chat_template`."
1434
+ )
1435
+ if not isinstance(truncation, bool):
1436
+ raise ValueError("`truncation` must be a boolean for `apply_chat_template` method.")
1437
+
1438
+ if isinstance(conversation, (list, tuple)) and (
1439
+ isinstance(conversation[0], (list, tuple)) or hasattr(conversation[0], "messages")
1440
+ ):
1441
+ conversations = conversation
1442
+ is_batched = True
1443
+ else:
1444
+ conversations = [conversation]
1445
+ is_batched = False
1446
+
1447
+ def _maybe_adapt_message(message: dict[str, Any]) -> None:
1448
+ """Adapt message to `mistral-common` format and leave validation to `mistral-common`."""
1449
+ if not isinstance(message, dict):
1450
+ return
1451
+ maybe_list_content: Optional[Union[str, list[dict[str, Union[str, dict[str, Any]]]]]] = message.get(
1452
+ "content"
1453
+ )
1454
+ if not maybe_list_content or isinstance(maybe_list_content, str):
1455
+ return
1456
+
1457
+ normalized_content: list[dict[str, Union[str, dict[str, Any]]]] = []
1458
+ for content in maybe_list_content:
1459
+ content_type = content.get("type", None)
1460
+ if not content_type:
1461
+ continue
1462
+ elif content_type == "image":
1463
+ maybe_url: Optional[str] = content.get("url")
1464
+ maybe_path: Optional[str] = content.get("path")
1465
+ maybe_base64: Optional[str] = content.get("base64")
1466
+ if maybe_url:
1467
+ image_content = maybe_url
1468
+ elif maybe_path:
1469
+ if not maybe_path.startswith("file://"):
1470
+ maybe_path = Path(maybe_path).resolve().as_uri()
1471
+ image_content = maybe_path
1472
+ elif maybe_base64:
1473
+ if not maybe_base64.startswith("data:image"):
1474
+ maybe_base64 = "data:image/unk;base64," + maybe_base64
1475
+ image_content = maybe_base64
1476
+ else:
1477
+ raise ValueError("Image content must be specified.")
1478
+ normalized_content.append({"type": "image_url", "image_url": {"url": image_content}})
1479
+ elif content_type == "audio":
1480
+ maybe_url: Optional[str] = content.get("url")
1481
+ maybe_path: Optional[str] = content.get("path")
1482
+ maybe_base64: Optional[str] = content.get("base64")
1483
+ if maybe_url or maybe_path:
1484
+ audio_data = load_audio_as(maybe_url or maybe_path, return_format="dict", force_mono=True)
1485
+ normalized_content.append({"type": "input_audio", "input_audio": audio_data})
1486
+ continue
1487
+ if not maybe_base64:
1488
+ raise ValueError("Audio content must be specified.")
1489
+ normalized_content.append({"type": "audio_url", "audio_url": {"url": maybe_base64}})
1490
+ else:
1491
+ normalized_content.append(content)
1492
+ message["content"] = normalized_content
1493
+
1494
+ outputs = []
1495
+ images: list[np.ndarray] = []
1496
+ audios: list[np.ndarray] = []
1497
+
1498
+ for conversation in conversations:
1499
+ messages: list[dict[str, Union[str, list[dict[str, Union[str, dict[str, Any]]]]]]] = []
1500
+ for message in conversation:
1501
+ _maybe_adapt_message(message)
1502
+ messages.append(message)
1503
+
1504
+ chat_request = ChatCompletionRequest.from_openai(
1505
+ messages=messages,
1506
+ tools=tools,
1507
+ continue_final_message=continue_final_message,
1508
+ )
1509
+
1510
+ tokenized_request = self.tokenizer.encode_chat_completion(chat_request)
1511
+ if tokenize:
1512
+ outputs.append(tokenized_request.tokens)
1513
+ else:
1514
+ outputs.append(tokenized_request.text)
1515
+ images.extend(tokenized_request.images)
1516
+ audios.extend([el.audio_array for el in tokenized_request.audios])
1517
+
1518
+ if not is_batched:
1519
+ outputs = outputs[0]
1520
+
1521
+ if tokenize:
1522
+ out = self(
1523
+ outputs,
1524
+ padding=padding,
1525
+ truncation=truncation,
1526
+ max_length=max_length,
1527
+ add_special_tokens=False,
1528
+ return_tensors=return_tensors,
1529
+ )
1530
+ if return_dict:
1531
+ if images:
1532
+ pixel_values: Union[list[np.ndarray], np.ndarray, torch.Tensor]
1533
+ if return_tensors == "pt":
1534
+ if not is_torch_available():
1535
+ raise ImportError(
1536
+ "Unable to convert output to PyTorch tensors format, PyTorch is not installed."
1537
+ )
1538
+
1539
+ pixel_values = torch.tensor(images)
1540
+ elif return_tensors == "np":
1541
+ pixel_values = np.array(images)
1542
+ elif return_tensors is None:
1543
+ pixel_values = images
1544
+ else:
1545
+ raise ValueError(f"Unsupported return_tensors type: {return_tensors}")
1546
+ out.data["pixel_values"] = pixel_values
1547
+ if audios:
1548
+ if return_tensors is not None:
1549
+ raise NotImplementedError(
1550
+ "When passing audio content in apply_chat_template, `return_tensors` must be None since we cannot batch the audio inputs. The returned audio will be a list of numpy arrays."
1551
+ )
1552
+ # Transformers convention is audio for plural audio (audio does not take a "s")
1553
+ out.data["audio"] = audios
1554
+ return out
1555
+ else:
1556
+ return out["input_ids"]
1557
+
1558
+ else:
1559
+ logger.warning(
1560
+ "`MistralCommonTokenizer.apply_chat_template(..., tokenize=False)` is unsafe and may lead to unexpected behavior."
1561
+ " Please consider using `tokenize=True` instead and don't encode the output manually."
1562
+ )
1563
+ return outputs
1564
+
1565
+ @add_end_docstrings(ENCODE_KWARGS_DOCSTRING, ENCODE_PLUS_ADDITIONAL_KWARGS_DOCSTRING)
1566
+ def __call__(
1567
+ self,
1568
+ text: Union[TextInput, EncodedInput, list[TextInput], list[EncodedInput], None] = None,
1569
+ text_pair: None = None,
1570
+ text_target: None = None,
1571
+ text_pair_target: None = None,
1572
+ add_special_tokens: bool = True,
1573
+ padding: Union[bool, str, PaddingStrategy] = False,
1574
+ truncation: Union[bool, str, TruncationStrategy, None] = None,
1575
+ max_length: Optional[int] = None,
1576
+ stride: int = 0,
1577
+ pad_to_multiple_of: Optional[int] = None,
1578
+ padding_side: Optional[str] = None,
1579
+ return_tensors: Optional[Union[str, TensorType]] = None,
1580
+ return_attention_mask: Optional[bool] = None,
1581
+ return_overflowing_tokens: bool = False,
1582
+ return_special_tokens_mask: bool = False,
1583
+ return_length: bool = False,
1584
+ verbose: bool = True,
1585
+ **kwargs,
1586
+ ) -> BatchEncoding:
1587
+ """
1588
+ Main method to tokenize and prepare for the model one or several sequence(s) or one or several pair(s) of
1589
+ sequences.
1590
+
1591
+ Args:
1592
+ text (`str`, `List[str]`, `List[List[str]]`, *optional*):
1593
+ The sequence or batch of sequences to be encoded. Each sequence can be a string or a list of int
1594
+ (encoded strings).
1595
+ text_pair (`None`, *optional*):
1596
+ Not supported by `MistralCommonTokenizer`. Kept to match the signature of `PreTrainedTokenizerBase.__call__`.
1597
+ text_target (`None`, *optional*):
1598
+ Not supported by `MistralCommonTokenizer`. Kept to match the signature of `PreTrainedTokenizerBase.__call__`.
1599
+ text_pair_target (`None`, *optional*):
1600
+ Not supported by `MistralCommonTokenizer`. Kept to match the signature of `PreTrainedTokenizerBase.__call__`.
1601
+ """
1602
+ if kwargs:
1603
+ raise ValueError(f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.__call__`.")
1604
+
1605
+ if text_pair or text_target or text_pair_target:
1606
+ raise ValueError(
1607
+ "`text_pair`, `text_target` and `text_pair_target` are not supported by `MistralCommonTokenizer`."
1608
+ )
1609
+
1610
+ if return_tensors in ("tf", "jax"):
1611
+ raise ValueError(
1612
+ "`MistralCommonTokenizer` does not support `return_tensors='tf'` or `return_tensors='jax'`."
1613
+ )
1614
+
1615
+ def _is_valid_text_input(t):
1616
+ if isinstance(t, str):
1617
+ # Strings are fine
1618
+ return True
1619
+ elif isinstance(t, (list, tuple)):
1620
+ # List are fine as long as they are...
1621
+ if len(t) == 0:
1622
+ # ... empty
1623
+ return True
1624
+ elif isinstance(t[0], (str, int)):
1625
+ # ... list of strings or int
1626
+ return True
1627
+ elif isinstance(t[0], (list, tuple)):
1628
+ # ... list with an empty list or with a list of strings or with a list of ints
1629
+ return len(t[0]) == 0 or isinstance(t[0][0], (str, int))
1630
+ else:
1631
+ return False
1632
+ else:
1633
+ return False
1634
+
1635
+ if not _is_valid_text_input(text):
1636
+ raise ValueError(
1637
+ "text input must be of type `str` (single example), `List[str]` (batch or single encoded example) "
1638
+ "or `List[List[int]]` (batch of encoded examples)."
1639
+ )
1640
+
1641
+ is_batched = isinstance(text, (list, tuple)) and isinstance(text[0], (str, list, tuple))
1642
+
1643
+ padding_strategy, truncation_strategy, max_length, kwargs = self._get_padding_truncation_strategies(
1644
+ padding=padding,
1645
+ truncation=truncation,
1646
+ max_length=max_length,
1647
+ pad_to_multiple_of=pad_to_multiple_of,
1648
+ verbose=verbose,
1649
+ **kwargs,
1650
+ )
1651
+
1652
+ if is_batched:
1653
+ return self._batch_encode_plus(
1654
+ batch_text=text,
1655
+ add_special_tokens=add_special_tokens,
1656
+ padding_strategy=padding_strategy,
1657
+ truncation_strategy=truncation_strategy,
1658
+ max_length=max_length,
1659
+ stride=stride,
1660
+ pad_to_multiple_of=pad_to_multiple_of,
1661
+ padding_side=padding_side,
1662
+ return_tensors=return_tensors,
1663
+ return_attention_mask=return_attention_mask,
1664
+ return_overflowing_tokens=return_overflowing_tokens,
1665
+ return_special_tokens_mask=return_special_tokens_mask,
1666
+ return_length=return_length,
1667
+ verbose=verbose,
1668
+ **kwargs,
1669
+ )
1670
+ else:
1671
+ return self._encode_plus(
1672
+ text=text,
1673
+ add_special_tokens=add_special_tokens,
1674
+ padding_strategy=padding_strategy,
1675
+ truncation_strategy=truncation_strategy,
1676
+ max_length=max_length,
1677
+ stride=stride,
1678
+ pad_to_multiple_of=pad_to_multiple_of,
1679
+ padding_side=padding_side,
1680
+ return_tensors=return_tensors,
1681
+ return_attention_mask=return_attention_mask,
1682
+ return_overflowing_tokens=return_overflowing_tokens,
1683
+ return_special_tokens_mask=return_special_tokens_mask,
1684
+ return_length=return_length,
1685
+ verbose=verbose,
1686
+ **kwargs,
1687
+ )
1688
+
1689
+ @classmethod
1690
+ def from_pretrained(
1691
+ cls,
1692
+ pretrained_model_name_or_path: Union[str, os.PathLike],
1693
+ *init_inputs,
1694
+ mode: ValidationMode = ValidationMode.test,
1695
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
1696
+ force_download: bool = False,
1697
+ local_files_only: bool = False,
1698
+ token: Optional[Union[str, bool]] = None,
1699
+ revision: str = "main",
1700
+ model_max_length: int = VERY_LARGE_INTEGER,
1701
+ padding_side: str = "left",
1702
+ truncation_side: str = "right",
1703
+ model_input_names: Optional[list[str]] = None,
1704
+ clean_up_tokenization_spaces: bool = False,
1705
+ **kwargs,
1706
+ ):
1707
+ r"""
1708
+ Instantiate a `MistralCommonTokenizer` from a predefined
1709
+ tokenizer.
1710
+
1711
+ Args:
1712
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
1713
+ Can be either:
1714
+
1715
+ - A string, the *model id* of a predefined tokenizer hosted inside a model repo on huggingface.co.
1716
+ - A path to a *directory* containing the tokenizer config, for instance saved
1717
+ using the [`MistralCommonTokenizer.tokenization_mistral_common.save_pretrained`] method, e.g.,
1718
+ `./my_model_directory/`.
1719
+ mode (`ValidationMode`, *optional*, defaults to `ValidationMode.test`):
1720
+ Validation mode for the `MistralTokenizer` tokenizer.
1721
+ cache_dir (`str` or `os.PathLike`, *optional*):
1722
+ Path to a directory in which a downloaded predefined tokenizer vocabulary files should be cached if the
1723
+ standard cache should not be used.
1724
+ force_download (`bool`, *optional*, defaults to `False`):
1725
+ Whether or not to force the (re-)download the vocabulary files and override the cached versions if they
1726
+ exist.
1727
+ token (`str` or *bool*, *optional*):
1728
+ The token to use as HTTP bearer authorization for remote files. If `True`, will use the token generated
1729
+ when running `hf auth login` (stored in `~/.huggingface`).
1730
+ local_files_only (`bool`, *optional*, defaults to `False`):
1731
+ Whether or not to only rely on local files and not to attempt to download any files.
1732
+ revision (`str`, *optional*, defaults to `"main"`):
1733
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
1734
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
1735
+ identifier allowed by git.
1736
+ max_length (`int`, *optional*):
1737
+ Controls the maximum length to use by one of the truncation/padding parameters.
1738
+
1739
+ If left unset or set to `None`, this will use the predefined model maximum length if a maximum length
1740
+ is required by one of the truncation/padding parameters. If the model has no specific maximum input
1741
+ length (like XLNet) truncation/padding to a maximum length will be deactivated.
1742
+ padding_side (`str`, *optional*, defaults to `"left"`):
1743
+ The side on which the model should have padding applied. Should be selected between ['right', 'left'].
1744
+ Default value is picked from the class attribute of the same name.
1745
+ truncation_side (`str`, *optional*, defaults to `"right"`):
1746
+ The side on which the model should have truncation applied. Should be selected between ['right', 'left'].
1747
+ model_input_names (`List[string]`, *optional*):
1748
+ The list of inputs accepted by the forward pass of the model (like `"token_type_ids"` or
1749
+ `"attention_mask"`). Default value is picked from the class attribute of the same name.
1750
+ clean_up_tokenization_spaces (`bool`, *optional*, defaults to `False`):
1751
+ Whether or not the model should cleanup the spaces that were added when splitting the input text during the
1752
+ tokenization process.
1753
+ kwargs (additional keyword arguments, *optional*):
1754
+ Not supported by `MistralCommonTokenizer.from_pretrained`.
1755
+ Will raise an error if used.
1756
+ """
1757
+ if init_inputs:
1758
+ raise ValueError("`init_inputs` are not supported by `MistralCommonTokenizer.from_pretrained`.")
1759
+
1760
+ # Handle kwargs and AutoTokenizer case
1761
+ if kwargs and not set(kwargs.keys()).issubset({"_from_auto", "trust_remote_code"}):
1762
+ raise ValueError(
1763
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.from_pretrained`."
1764
+ )
1765
+
1766
+ if not os.path.isdir(pretrained_model_name_or_path):
1767
+ tokenizer_path = download_tokenizer_from_hf_hub(
1768
+ repo_id=pretrained_model_name_or_path,
1769
+ cache_dir=cache_dir,
1770
+ token=token,
1771
+ revision=revision,
1772
+ force_download=force_download,
1773
+ local_files_only=local_files_only,
1774
+ )
1775
+ else:
1776
+ valid_tokenizer_files = []
1777
+ tokenizer_file: str
1778
+
1779
+ instruct_versions = list(TokenizerVersion.__members__)
1780
+ mm_versions = list(MultiModalVersion.__members__) + [""] # allow no mm version
1781
+ sentencepiece_suffixes = [f".model.{v}{m}" for v in instruct_versions for m in mm_versions] + [".model"]
1782
+
1783
+ for path in os.listdir(pretrained_model_name_or_path):
1784
+ pathlib_repo_file = Path(path)
1785
+ file_name = pathlib_repo_file.name
1786
+ suffix = "".join(pathlib_repo_file.suffixes)
1787
+ if file_name == "tekken.json" or suffix in sentencepiece_suffixes:
1788
+ valid_tokenizer_files.append(file_name)
1789
+
1790
+ if len(valid_tokenizer_files) == 0:
1791
+ raise ValueError(f"No tokenizer file found in directory: {pretrained_model_name_or_path}")
1792
+ # If there are multiple tokenizer files, we use tekken.json if it exists, otherwise the versioned one.
1793
+ if len(valid_tokenizer_files) > 1:
1794
+ if "tekken.json" in valid_tokenizer_files:
1795
+ tokenizer_file = "tekken.json"
1796
+ else:
1797
+ tokenizer_file = max(valid_tokenizer_files)
1798
+ logger.warning(
1799
+ f"Multiple tokenizer files found in directory: {pretrained_model_name_or_path}. Using {tokenizer_file}."
1800
+ )
1801
+ else:
1802
+ tokenizer_file = valid_tokenizer_files[0]
1803
+
1804
+ tokenizer_path = os.path.join(pretrained_model_name_or_path, tokenizer_file)
1805
+
1806
+ return cls(
1807
+ tokenizer_path=tokenizer_path,
1808
+ mode=mode,
1809
+ model_max_length=model_max_length,
1810
+ padding_side=padding_side,
1811
+ truncation_side=truncation_side,
1812
+ model_input_names=model_input_names,
1813
+ clean_up_tokenization_spaces=clean_up_tokenization_spaces,
1814
+ )
1815
+
1816
+ def save_pretrained(
1817
+ self,
1818
+ save_directory: Union[str, os.PathLike, Path],
1819
+ push_to_hub: bool = False,
1820
+ token: Optional[Union[str, bool]] = None,
1821
+ commit_message: Optional[str] = None,
1822
+ repo_id: Optional[str] = None,
1823
+ private: Optional[bool] = None,
1824
+ repo_url: Optional[str] = None,
1825
+ organization: Optional[str] = None,
1826
+ **kwargs,
1827
+ ) -> tuple[str, ...]:
1828
+ """
1829
+ Save the full tokenizer state.
1830
+
1831
+
1832
+ This method make sure the full tokenizer can then be re-loaded using the
1833
+ [`~MistralCommonTokenizer.tokenization_mistral_common.from_pretrained`] class method.
1834
+
1835
+ Args:
1836
+ save_directory (`str` or `os.PathLike`): The path to a directory where the tokenizer will be saved.
1837
+ push_to_hub (`bool`, *optional*, defaults to `False`):
1838
+ Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
1839
+ repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
1840
+ namespace).
1841
+ token (`str` or *bool*, *optional*, defaults to `None`):
1842
+ The token to use to push to the model hub. If `True`, will use the token in the `HF_TOKEN` environment
1843
+ variable.
1844
+ commit_message (`str`, *optional*): The commit message to use when pushing to the hub.
1845
+ repo_id (`str`, *optional*): The name of the repository to which push to the Hub.
1846
+ private (`bool`, *optional*): Whether the model repository is private or not.
1847
+ repo_url (`str`, *optional*): The URL to the Git repository to which push to the Hub.
1848
+ organization (`str`, *optional*): The name of the organization in which you would like to push your model.
1849
+ kwargs (`Dict[str, Any]`, *optional*):
1850
+ Not supported by `MistralCommonTokenizer.save_pretrained`.
1851
+ Will raise an error if used.
1852
+
1853
+ Returns:
1854
+ A tuple of `str`: The files saved.
1855
+ """
1856
+ # `save_jinja_files`` must be skipped to be able to save from a processor
1857
+ kwargs.pop("save_jinja_files", None)
1858
+ if kwargs:
1859
+ raise ValueError(
1860
+ f"Kwargs {list(kwargs.keys())} are not supported by `MistralCommonTokenizer.save_pretrained`."
1861
+ )
1862
+
1863
+ save_directory = Path(save_directory)
1864
+ save_directory.mkdir(parents=True, exist_ok=True)
1865
+
1866
+ shutil.copy(self._tokenizer_path, save_directory)
1867
+
1868
+ if push_to_hub:
1869
+ repo_id = repo_id or str(save_directory).split(os.path.sep)[-1]
1870
+ repo_id = self._create_repo(
1871
+ repo_id, token=token, private=private, repo_url=repo_url, organization=organization
1872
+ )
1873
+ files_timestamps = self._get_files_timestamps(save_directory)
1874
+
1875
+ self._upload_modified_files(
1876
+ save_directory,
1877
+ repo_id,
1878
+ files_timestamps,
1879
+ commit_message=commit_message,
1880
+ token=token,
1881
+ )
1882
+
1883
+ return (str(save_directory / self._tokenizer_path.name),)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/trainer_pt_utils.py ADDED
@@ -0,0 +1,1406 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Torch utilities for the Trainer class.
16
+ """
17
+
18
+ import copy
19
+ import datetime
20
+ import io
21
+ import json
22
+ import math
23
+ import os
24
+ import re
25
+ import sys
26
+ import warnings
27
+ from collections.abc import Iterator, Mapping
28
+ from contextlib import contextmanager
29
+ from dataclasses import dataclass, field
30
+ from itertools import chain
31
+ from logging import StreamHandler
32
+ from typing import Any, Optional, Union
33
+
34
+ import numpy as np
35
+ import torch
36
+ import torch.distributed as dist
37
+ from torch import nn
38
+ from torch.utils.data import Dataset, IterableDataset, RandomSampler, Sampler
39
+ from torch.utils.data.distributed import DistributedSampler
40
+
41
+ from .integrations.deepspeed import is_deepspeed_zero3_enabled
42
+ from .tokenization_utils_base import BatchEncoding
43
+ from .utils import (
44
+ is_sagemaker_mp_enabled,
45
+ is_torch_available,
46
+ is_torch_xla_available,
47
+ is_training_run_on_sagemaker,
48
+ logging,
49
+ )
50
+
51
+
52
+ if is_training_run_on_sagemaker():
53
+ logging.add_handler(StreamHandler(sys.stdout))
54
+
55
+ if is_torch_xla_available():
56
+ import torch_xla.runtime as xr
57
+
58
+ if is_torch_available():
59
+ from torch.optim.lr_scheduler import LRScheduler
60
+
61
+
62
+ logger = logging.get_logger(__name__)
63
+
64
+
65
+ def get_dataloader_sampler(dataloader):
66
+ if hasattr(dataloader, "batch_sampler") and dataloader.batch_sampler is not None:
67
+ return get_dataloader_sampler(dataloader.batch_sampler)
68
+ elif hasattr(dataloader, "sampler"):
69
+ return dataloader.sampler
70
+
71
+
72
+ def atleast_1d(tensor_or_array: Union[torch.Tensor, np.ndarray]):
73
+ if isinstance(tensor_or_array, torch.Tensor):
74
+ if hasattr(torch, "atleast_1d"):
75
+ tensor_or_array = torch.atleast_1d(tensor_or_array)
76
+ elif tensor_or_array.ndim < 1:
77
+ tensor_or_array = tensor_or_array[None]
78
+ else:
79
+ tensor_or_array = np.atleast_1d(tensor_or_array)
80
+ return tensor_or_array
81
+
82
+
83
+ def torch_pad_and_concatenate(tensor1, tensor2, padding_index=-100):
84
+ """Concatenates `tensor1` and `tensor2` on first axis, applying padding on the second if necessary."""
85
+ tensor1 = atleast_1d(tensor1)
86
+ tensor2 = atleast_1d(tensor2)
87
+
88
+ if len(tensor1.shape) == 1 or tensor1.shape[1] == tensor2.shape[1]:
89
+ return torch.cat((tensor1, tensor2), dim=0)
90
+
91
+ # Let's figure out the new shape
92
+ new_shape = (tensor1.shape[0] + tensor2.shape[0], max(tensor1.shape[1], tensor2.shape[1])) + tensor1.shape[2:]
93
+
94
+ # Now let's fill the result tensor
95
+ result = tensor1.new_full(new_shape, padding_index)
96
+ result[: tensor1.shape[0], : tensor1.shape[1]] = tensor1
97
+ result[tensor1.shape[0] :, : tensor2.shape[1]] = tensor2
98
+ return result
99
+
100
+
101
+ def numpy_pad_and_concatenate(array1, array2, padding_index=-100):
102
+ """Concatenates `array1` and `array2` on first axis, applying padding on the second if necessary."""
103
+ array1 = atleast_1d(array1)
104
+ array2 = atleast_1d(array2)
105
+
106
+ if len(array1.shape) == 1 or array1.shape[1] == array2.shape[1]:
107
+ return np.concatenate((array1, array2), axis=0)
108
+
109
+ # Let's figure out the new shape
110
+ new_shape = (array1.shape[0] + array2.shape[0], max(array1.shape[1], array2.shape[1])) + array1.shape[2:]
111
+
112
+ # Now let's fill the result tensor
113
+ result = np.full_like(array1, padding_index, shape=new_shape)
114
+ result[: array1.shape[0], : array1.shape[1]] = array1
115
+ result[array1.shape[0] :, : array2.shape[1]] = array2
116
+ return result
117
+
118
+
119
+ def nested_concat(tensors, new_tensors, padding_index=-100):
120
+ """
121
+ Concat the `new_tensors` to `tensors` on the first dim and pad them on the second if needed. Works for tensors or
122
+ nested list/tuples/dict of tensors.
123
+ """
124
+ if not (isinstance(tensors, torch.Tensor) and isinstance(new_tensors, torch.Tensor)):
125
+ assert type(tensors) is type(new_tensors), (
126
+ f"Expected `tensors` and `new_tensors` to have the same type but found {type(tensors)} and {type(new_tensors)}."
127
+ )
128
+ if isinstance(tensors, (list, tuple)):
129
+ return type(tensors)(nested_concat(t, n, padding_index=padding_index) for t, n in zip(tensors, new_tensors))
130
+ elif isinstance(tensors, torch.Tensor):
131
+ return torch_pad_and_concatenate(tensors, new_tensors, padding_index=padding_index)
132
+ elif isinstance(tensors, Mapping):
133
+ return type(tensors)(
134
+ {k: nested_concat(t, new_tensors[k], padding_index=padding_index) for k, t in tensors.items()}
135
+ )
136
+ elif isinstance(tensors, np.ndarray):
137
+ return numpy_pad_and_concatenate(tensors, new_tensors, padding_index=padding_index)
138
+ else:
139
+ raise TypeError(f"Unsupported type for concatenation: got {type(tensors)}")
140
+
141
+
142
+ def find_batch_size(tensors):
143
+ """
144
+ Find the first dimension of a tensor in a nested list/tuple/dict of tensors.
145
+ """
146
+ if isinstance(tensors, (list, tuple)):
147
+ for t in tensors:
148
+ result = find_batch_size(t)
149
+ if result is not None:
150
+ return result
151
+ elif isinstance(tensors, Mapping):
152
+ for value in tensors.values():
153
+ result = find_batch_size(value)
154
+ if result is not None:
155
+ return result
156
+ elif isinstance(tensors, (torch.Tensor, np.ndarray)):
157
+ return tensors.shape[0] if len(tensors.shape) >= 1 else None
158
+
159
+
160
+ def nested_numpify(tensors):
161
+ "Numpify `tensors` (even if it's a nested list/tuple/dict of tensors)."
162
+ if isinstance(tensors, (list, tuple)):
163
+ return type(tensors)(nested_numpify(t) for t in tensors)
164
+ if isinstance(tensors, Mapping):
165
+ return type(tensors)({k: nested_numpify(t) for k, t in tensors.items()})
166
+
167
+ t = tensors.cpu()
168
+ if t.dtype == torch.bfloat16:
169
+ # As of Numpy 1.21.4, NumPy does not support bfloat16 (see
170
+ # https://github.com/numpy/numpy/blob/a47ecdea856986cd60eabbd53265c2ca5916ad5d/doc/source/user/basics.types.rst ).
171
+ # Until Numpy adds bfloat16, we must convert float32.
172
+ t = t.to(torch.float32)
173
+ return t.numpy()
174
+
175
+
176
+ def nested_detach(tensors):
177
+ "Detach `tensors` (even if it's a nested list/tuple/dict of tensors)."
178
+ if isinstance(tensors, (list, tuple)):
179
+ return type(tensors)(nested_detach(t) for t in tensors)
180
+ elif isinstance(tensors, Mapping):
181
+ return type(tensors)({k: nested_detach(t) for k, t in tensors.items()})
182
+ return tensors.detach() if isinstance(tensors, torch.Tensor) else tensors
183
+
184
+
185
+ def nested_xla_mesh_reduce(tensors, name):
186
+ if is_torch_xla_available():
187
+ import torch_xla.core.xla_model as xm
188
+
189
+ if isinstance(tensors, (list, tuple)):
190
+ return type(tensors)(nested_xla_mesh_reduce(t, f"{name}_{i}") for i, t in enumerate(tensors))
191
+ if isinstance(tensors, Mapping):
192
+ return type(tensors)(
193
+ {k: nested_xla_mesh_reduce(t, f"{name}_{i}") for i, (k, t) in enumerate(tensors.items())}
194
+ )
195
+
196
+ tensors = atleast_1d(tensors)
197
+ return xm.mesh_reduce(name, tensors, torch.cat)
198
+ else:
199
+ raise ImportError("Torch xla must be installed to use `nested_xla_mesh_reduce`")
200
+
201
+
202
+ def distributed_concat(tensor: Any, num_total_examples: Optional[int] = None) -> Any:
203
+ try:
204
+ if isinstance(tensor, (tuple, list)):
205
+ return type(tensor)(distributed_concat(t, num_total_examples) for t in tensor)
206
+ if isinstance(tensor, Mapping):
207
+ return type(tensor)({k: distributed_concat(t, num_total_examples) for k, t in tensor.items()})
208
+ tensor = atleast_1d(tensor).contiguous()
209
+ output_tensors = [tensor.clone() for _ in range(dist.get_world_size())]
210
+ dist.all_gather(output_tensors, tensor)
211
+ concat = torch.cat(output_tensors, dim=0)
212
+
213
+ # truncate the dummy elements added by SequentialDistributedSampler
214
+ if num_total_examples is not None:
215
+ concat = concat[:num_total_examples]
216
+ return concat
217
+ except AssertionError:
218
+ raise AssertionError("Not currently using distributed training")
219
+
220
+
221
+ def distributed_broadcast_scalars(
222
+ scalars: list[Union[int, float]],
223
+ num_total_examples: Optional[int] = None,
224
+ device: Optional[torch.device] = torch.device("cuda"),
225
+ ) -> torch.Tensor:
226
+ try:
227
+ tensorized_scalar = torch.tensor(scalars, device=device)
228
+ output_tensors = [tensorized_scalar.clone() for _ in range(dist.get_world_size())]
229
+ dist.all_gather(output_tensors, tensorized_scalar)
230
+ concat = torch.cat(output_tensors, dim=0)
231
+
232
+ # truncate the dummy elements added by SequentialDistributedSampler
233
+ if num_total_examples is not None:
234
+ concat = concat[:num_total_examples]
235
+ return concat
236
+ except AssertionError:
237
+ raise AssertionError("Not currently using distributed training")
238
+
239
+
240
+ def reissue_pt_warnings(caught_warnings):
241
+ # Reissue warnings
242
+ if len(caught_warnings) > 1:
243
+ for w in caught_warnings:
244
+ if w.category is not UserWarning:
245
+ warnings.warn(w.message, w.category)
246
+
247
+
248
+ @contextmanager
249
+ def torch_distributed_zero_first(local_rank: int):
250
+ """
251
+ Decorator to make all processes in distributed training wait for each local_master to do something.
252
+
253
+ Args:
254
+ local_rank (`int`): The rank of the local process.
255
+ """
256
+ if local_rank not in [-1, 0]:
257
+ dist.barrier()
258
+ yield
259
+ if local_rank == 0:
260
+ dist.barrier()
261
+
262
+
263
+ class DistributedSamplerWithLoop(DistributedSampler):
264
+ """
265
+ Like a torch.utils.data.distributed.DistributedSampler` but loops at the end back to the beginning of the shuffled
266
+ samples to make each process have a round multiple of batch_size samples.
267
+
268
+ Args:
269
+ dataset (`torch.utils.data.Dataset`):
270
+ Dataset used for sampling.
271
+ batch_size (`int`):
272
+ The batch size used with this sampler
273
+ kwargs (`dict[str, Any]`, *optional*):
274
+ All other keyword arguments passed to `DistributedSampler`.
275
+ """
276
+
277
+ def __init__(self, dataset, batch_size, **kwargs):
278
+ super().__init__(dataset, **kwargs)
279
+ self.batch_size = batch_size
280
+
281
+ def __iter__(self):
282
+ indices = list(super().__iter__())
283
+ remainder = 0 if len(indices) % self.batch_size == 0 else self.batch_size - len(indices) % self.batch_size
284
+ # DistributedSampler already added samples from the beginning to make the number of samples a round multiple
285
+ # of the world size, so we skip those.
286
+ start_remainder = 1 if self.rank < len(self.dataset) % self.num_replicas else 0
287
+ indices += indices[start_remainder : start_remainder + remainder]
288
+ return iter(indices)
289
+
290
+
291
+ class EvalLoopContainer:
292
+ """
293
+ Container to store intermediate results of evaluation loop.
294
+
295
+ Args:
296
+ do_nested_concat (`bool`, *optional*, defaults to `True`):
297
+ If set to `True`, each iteration will recursively concatenate a new object containing tensors to
298
+ the existing stored tensors, provided that the structure of the existing object and the new one
299
+ are identical. If set to `False`, all newly added tensors will be stored in a list.
300
+ padding_index (`int`, *optional*, defaults to -100):
301
+ Value used to pad tensors of different shapes when `do_nested_concat=True`.
302
+ """
303
+
304
+ def __init__(self, do_nested_concat: bool = True, padding_index: int = -100):
305
+ self.do_nested_concat = do_nested_concat
306
+ self.padding_index = padding_index
307
+ self.tensors = None
308
+ self.arrays = None
309
+
310
+ def add(self, tensors) -> None:
311
+ """Add tensors to the stored objects. If `do_nested_concat=True`, the tensors will be concatenated recursively."""
312
+ if self.tensors is None:
313
+ self.tensors = tensors if self.do_nested_concat else [tensors]
314
+ elif self.do_nested_concat:
315
+ self.tensors = nested_concat(self.tensors, tensors, padding_index=self.padding_index)
316
+ else:
317
+ self.tensors.append(tensors)
318
+
319
+ def to_cpu_and_numpy(self) -> None:
320
+ """Move tensors in stored objects to CPU and convert them to numpy arrays."""
321
+
322
+ # Check if we have something to add, if not just return
323
+ if self.tensors is None:
324
+ return
325
+
326
+ new_arrays = nested_numpify(self.tensors)
327
+ if self.arrays is None:
328
+ self.arrays = new_arrays
329
+ elif self.do_nested_concat:
330
+ self.arrays = nested_concat(self.arrays, new_arrays, padding_index=self.padding_index)
331
+ else:
332
+ self.arrays.extend(new_arrays)
333
+
334
+ # reset device tensors after adding to cpu
335
+ self.tensors = None
336
+
337
+ def get_arrays(self):
338
+ """Returns the numpified and moved to CPU stored objects."""
339
+ self.to_cpu_and_numpy()
340
+ return self.arrays
341
+
342
+
343
+ class SequentialDistributedSampler(Sampler):
344
+ """
345
+ Distributed Sampler that subsamples indices sequentially, making it easier to collate all results at the end.
346
+
347
+ Even though we only use this sampler for eval and predict (no training), which means that the model params won't
348
+ have to be synced (i.e. will not hang for synchronization even if varied number of forward passes), we still add
349
+ extra samples to the sampler to make it evenly divisible (like in `DistributedSampler`) to make it easy to `gather`
350
+ or `reduce` resulting tensors at the end of the loop.
351
+ """
352
+
353
+ def __init__(self, dataset, num_replicas=None, rank=None, batch_size=None):
354
+ warnings.warn(
355
+ "SequentialDistributedSampler is deprecated and will be removed in v5 of Transformers.",
356
+ FutureWarning,
357
+ )
358
+ if num_replicas is None:
359
+ if not dist.is_available():
360
+ raise RuntimeError("Requires distributed package to be available")
361
+ num_replicas = dist.get_world_size()
362
+ if rank is None:
363
+ if not dist.is_available():
364
+ raise RuntimeError("Requires distributed package to be available")
365
+ rank = dist.get_rank()
366
+ self.dataset = dataset
367
+ self.num_replicas = num_replicas
368
+ self.rank = rank
369
+ num_samples = len(self.dataset)
370
+ # Add extra samples to make num_samples a multiple of batch_size if passed
371
+ if batch_size is not None:
372
+ self.num_samples = int(math.ceil(num_samples / (batch_size * num_replicas))) * batch_size
373
+ else:
374
+ self.num_samples = int(math.ceil(num_samples / num_replicas))
375
+ self.total_size = self.num_samples * self.num_replicas
376
+ self.batch_size = batch_size
377
+
378
+ def __iter__(self):
379
+ indices = list(range(len(self.dataset)))
380
+
381
+ # add extra samples to make it evenly divisible
382
+ indices += indices[: (self.total_size - len(indices))]
383
+ assert len(indices) == self.total_size, (
384
+ f"Indices length {len(indices)} and total size {self.total_size} mismatched"
385
+ )
386
+
387
+ # subsample
388
+ indices = indices[self.rank * self.num_samples : (self.rank + 1) * self.num_samples]
389
+ assert len(indices) == self.num_samples, (
390
+ f"Indices length {len(indices)} and sample number {self.num_samples} mismatched"
391
+ )
392
+
393
+ return iter(indices)
394
+
395
+ def __len__(self):
396
+ return self.num_samples
397
+
398
+
399
+ def get_tpu_sampler(dataset: torch.utils.data.Dataset, batch_size: int):
400
+ if xr.world_size() <= 1:
401
+ return RandomSampler(dataset)
402
+ return DistributedSampler(dataset, num_replicas=xr.world_size(), rank=xr.global_ordinal())
403
+
404
+
405
+ def nested_new_like(arrays, num_samples, padding_index=-100):
406
+ """Create the same nested structure as `arrays` with a first dimension always at `num_samples`."""
407
+ if isinstance(arrays, (list, tuple)):
408
+ return type(arrays)(nested_new_like(x, num_samples) for x in arrays)
409
+ return np.full_like(arrays, padding_index, shape=(num_samples, *arrays.shape[1:]))
410
+
411
+
412
+ def expand_like(arrays, new_seq_length, padding_index=-100):
413
+ """Expand the `arrays` so that the second dimension grows to `new_seq_length`. Uses `padding_index` for padding."""
414
+ result = np.full_like(arrays, padding_index, shape=(arrays.shape[0], new_seq_length) + arrays.shape[2:])
415
+ result[:, : arrays.shape[1]] = arrays
416
+ return result
417
+
418
+
419
+ def nested_truncate(tensors, limit):
420
+ "Truncate `tensors` at `limit` (even if it's a nested list/tuple/dict of tensors)."
421
+ if isinstance(tensors, (list, tuple)):
422
+ return type(tensors)(nested_truncate(t, limit) for t in tensors)
423
+ if isinstance(tensors, Mapping):
424
+ return type(tensors)({k: nested_truncate(t, limit) for k, t in tensors.items()})
425
+
426
+ return tensors[:limit]
427
+
428
+
429
+ class DistributedTensorGatherer:
430
+ """
431
+ A class responsible for properly gathering tensors (or nested list/tuple of tensors) on the CPU by chunks.
432
+
433
+ If our dataset has 16 samples with a batch size of 2 on 3 processes and we gather then transfer on CPU at every
434
+ step, our sampler will generate the following indices:
435
+
436
+ `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1]`
437
+
438
+ to get something of size a multiple of 3 (so that each process gets the same dataset length). Then process 0, 1 and
439
+ 2 will be responsible of making predictions for the following samples:
440
+
441
+ - P0: `[0, 1, 2, 3, 4, 5]`
442
+ - P1: `[6, 7, 8, 9, 10, 11]`
443
+ - P2: `[12, 13, 14, 15, 0, 1]`
444
+
445
+ The first batch treated on each process will be:
446
+
447
+ - P0: `[0, 1]`
448
+ - P1: `[6, 7]`
449
+ - P2: `[12, 13]`
450
+
451
+ So if we gather at the end of the first batch, we will get a tensor (nested list/tuple of tensor) corresponding to
452
+ the following indices:
453
+
454
+ `[0, 1, 6, 7, 12, 13]`
455
+
456
+ If we directly concatenate our results without taking any precautions, the user will then get the predictions for
457
+ the indices in this order at the end of the prediction loop:
458
+
459
+ `[0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15, 4, 5, 10, 11, 0, 1]`
460
+
461
+ For some reason, that's not going to roll their boat. This class is there to solve that problem.
462
+
463
+ Args:
464
+ world_size (`int`):
465
+ The number of processes used in the distributed training.
466
+ num_samples (`int`):
467
+ The number of samples in our dataset.
468
+ make_multiple_of (`int`, *optional*):
469
+ If passed, the class assumes the datasets passed to each process are made to be a multiple of this argument
470
+ (by adding samples).
471
+ padding_index (`int`, *optional*, defaults to -100):
472
+ The padding index to use if the arrays don't all have the same sequence length.
473
+ """
474
+
475
+ def __init__(self, world_size, num_samples, make_multiple_of=None, padding_index=-100):
476
+ warnings.warn(
477
+ "DistributedTensorGatherer is deprecated and will be removed in v5 of Transformers.",
478
+ FutureWarning,
479
+ )
480
+ self.world_size = world_size
481
+ self.num_samples = num_samples
482
+ total_size = world_size if make_multiple_of is None else world_size * make_multiple_of
483
+ self.total_samples = int(np.ceil(num_samples / total_size)) * total_size
484
+ self.process_length = self.total_samples // world_size
485
+ self._storage = None
486
+ self._offsets = None
487
+ self.padding_index = padding_index
488
+
489
+ def add_arrays(self, arrays):
490
+ """
491
+ Add `arrays` to the internal storage, Will initialize the storage to the full size at the first arrays passed
492
+ so that if we're bound to get an OOM, it happens at the beginning.
493
+ """
494
+ if arrays is None:
495
+ return
496
+ if self._storage is None:
497
+ self._storage = nested_new_like(arrays, self.total_samples, padding_index=self.padding_index)
498
+ self._offsets = list(range(0, self.total_samples, self.process_length))
499
+
500
+ slice_len, self._storage = self._nested_set_tensors(self._storage, arrays)
501
+ for i in range(self.world_size):
502
+ self._offsets[i] += slice_len
503
+
504
+ def _nested_set_tensors(self, storage, arrays):
505
+ if isinstance(arrays, (list, tuple)):
506
+ result = [self._nested_set_tensors(x, y) for x, y in zip(storage, arrays)]
507
+ return result[0][0], type(arrays)(r[1] for r in result)
508
+ assert arrays.shape[0] % self.world_size == 0, (
509
+ f"Arrays passed should all have a first dimension multiple of {self.world_size}, found {arrays.shape[0]}."
510
+ )
511
+
512
+ slice_len = arrays.shape[0] // self.world_size
513
+ for i in range(self.world_size):
514
+ if len(arrays.shape) == 1:
515
+ storage[self._offsets[i] : self._offsets[i] + slice_len] = arrays[i * slice_len : (i + 1) * slice_len]
516
+ else:
517
+ # Expand the array on the fly if needed.
518
+ if len(storage.shape) > 1 and storage.shape[1] < arrays.shape[1]:
519
+ storage = expand_like(storage, arrays.shape[1], padding_index=self.padding_index)
520
+ storage[self._offsets[i] : self._offsets[i] + slice_len, : arrays.shape[1]] = arrays[
521
+ i * slice_len : (i + 1) * slice_len
522
+ ]
523
+ return slice_len, storage
524
+
525
+ def finalize(self):
526
+ """
527
+ Return the properly gathered arrays and truncate to the number of samples (since the sampler added some extras
528
+ to get each process a dataset of the same length).
529
+ """
530
+ if self._storage is None:
531
+ return
532
+ if self._offsets[0] != self.process_length:
533
+ logger.warning("Not all data has been set. Are you sure you passed all values?")
534
+ return nested_truncate(self._storage, self.num_samples)
535
+
536
+
537
+ @dataclass
538
+ class LabelSmoother:
539
+ """
540
+ Adds label-smoothing on a pre-computed output from a Transformers model.
541
+
542
+ Args:
543
+ epsilon (`float`, *optional*, defaults to 0.1):
544
+ The label smoothing factor.
545
+ ignore_index (`int`, *optional*, defaults to -100):
546
+ The index in the labels to ignore when computing the loss.
547
+ """
548
+
549
+ epsilon: float = 0.1
550
+ ignore_index: int = -100
551
+
552
+ def __call__(self, model_output, labels, shift_labels=False):
553
+ logits = model_output["logits"] if isinstance(model_output, dict) else model_output[0]
554
+ if shift_labels:
555
+ logits = logits[..., :-1, :].contiguous()
556
+ labels = labels[..., 1:].contiguous()
557
+
558
+ log_probs = -nn.functional.log_softmax(logits, dim=-1)
559
+ if labels.dim() == log_probs.dim() - 1:
560
+ labels = labels.unsqueeze(-1)
561
+
562
+ padding_mask = labels.eq(self.ignore_index)
563
+ # In case the ignore_index is -100, the gather will fail, so we replace labels by 0. The padding_mask
564
+ # will ignore them in any case.
565
+ labels = torch.clamp(labels, min=0)
566
+ nll_loss = log_probs.gather(dim=-1, index=labels)
567
+ # works for fp16 input tensor too, by internally upcasting it to fp32
568
+ smoothed_loss = log_probs.sum(dim=-1, keepdim=True, dtype=torch.float32)
569
+
570
+ nll_loss.masked_fill_(padding_mask, 0.0)
571
+ smoothed_loss.masked_fill_(padding_mask, 0.0)
572
+
573
+ # Take the mean over the label dimensions, then divide by the number of active elements (i.e. not-padded):
574
+ num_active_elements = padding_mask.numel() - padding_mask.long().sum()
575
+ nll_loss = nll_loss.sum() / num_active_elements
576
+ smoothed_loss = smoothed_loss.sum() / (num_active_elements * log_probs.shape[-1])
577
+ return (1 - self.epsilon) * nll_loss + self.epsilon * smoothed_loss
578
+
579
+
580
+ def get_length_grouped_indices(lengths, batch_size, mega_batch_mult=None, generator=None):
581
+ """
582
+ Return a list of indices so that each slice of `batch_size` consecutive indices correspond to elements of similar
583
+ lengths. To do this, the indices are:
584
+
585
+ - randomly permuted
586
+ - grouped in mega-batches of size `mega_batch_mult * batch_size`
587
+ - sorted by length in each mega-batch
588
+
589
+ The result is the concatenation of all mega-batches, with the batch of `batch_size` containing the element of
590
+ maximum length placed first, so that an OOM happens sooner rather than later.
591
+ """
592
+ # Default for mega_batch_mult: 50 or the number to get 4 megabatches, whichever is smaller.
593
+ if mega_batch_mult is None:
594
+ mega_batch_mult = min(len(lengths) // (batch_size * 4), 50)
595
+ # Just in case, for tiny datasets
596
+ if mega_batch_mult == 0:
597
+ mega_batch_mult = 1
598
+
599
+ # We need to use torch for the random part as a distributed sampler will set the random seed for torch.
600
+ indices = torch.randperm(len(lengths), generator=generator)
601
+ megabatch_size = mega_batch_mult * batch_size
602
+ megabatches = [indices[i : i + megabatch_size].tolist() for i in range(0, len(lengths), megabatch_size)]
603
+ megabatches = [sorted(megabatch, key=lambda i: lengths[i], reverse=True) for megabatch in megabatches]
604
+
605
+ # The rest is to get the biggest batch first.
606
+ # Since each megabatch is sorted by descending length, the longest element is the first
607
+ megabatch_maximums = [lengths[megabatch[0]] for megabatch in megabatches]
608
+ max_idx = torch.argmax(torch.tensor(megabatch_maximums)).item()
609
+ # Switch to put the longest element in first position
610
+ megabatches[0][0], megabatches[max_idx][0] = megabatches[max_idx][0], megabatches[0][0]
611
+
612
+ return [i for megabatch in megabatches for i in megabatch]
613
+
614
+
615
+ class LengthGroupedSampler(Sampler):
616
+ r"""
617
+ Sampler that samples indices in a way that groups together features of the dataset of roughly the same length while
618
+ keeping a bit of randomness.
619
+ """
620
+
621
+ def __init__(
622
+ self,
623
+ batch_size: int,
624
+ dataset: Optional[Dataset] = None,
625
+ lengths: Optional[list[int]] = None,
626
+ model_input_name: Optional[str] = None,
627
+ generator=None,
628
+ ):
629
+ if dataset is None and lengths is None:
630
+ raise ValueError("One of dataset and lengths must be provided.")
631
+
632
+ self.batch_size = batch_size
633
+ if lengths is None:
634
+ model_input_name = model_input_name if model_input_name is not None else "input_ids"
635
+ if not isinstance(dataset[0], (dict, BatchEncoding)) or model_input_name not in dataset[0]:
636
+ raise ValueError(
637
+ "Can only automatically infer lengths for datasets whose items are dictionaries with an "
638
+ f"'{model_input_name}' key."
639
+ )
640
+ lengths = [len(feature[model_input_name]) for feature in dataset]
641
+ elif isinstance(lengths, torch.Tensor):
642
+ logger.info(
643
+ "If lengths is a torch.Tensor, LengthGroupedSampler will be slow. Converting lengths to list[int]..."
644
+ )
645
+ lengths = lengths.tolist()
646
+
647
+ self.lengths = lengths
648
+ self.generator = generator
649
+
650
+ def __len__(self):
651
+ return len(self.lengths)
652
+
653
+ def __iter__(self):
654
+ indices = get_length_grouped_indices(self.lengths, self.batch_size, generator=self.generator)
655
+ return iter(indices)
656
+
657
+
658
+ class DistributedLengthGroupedSampler(DistributedSampler):
659
+ r"""
660
+ Distributed Sampler that samples indices in a way that groups together features of the dataset of roughly the same
661
+ length while keeping a bit of randomness.
662
+ """
663
+
664
+ # Copied and adapted from PyTorch DistributedSampler.
665
+ def __init__(
666
+ self,
667
+ batch_size: int,
668
+ dataset: Optional[Dataset] = None,
669
+ num_replicas: Optional[int] = None,
670
+ rank: Optional[int] = None,
671
+ seed: int = 0,
672
+ drop_last: bool = False,
673
+ lengths: Optional[list[int]] = None,
674
+ model_input_name: Optional[str] = None,
675
+ ):
676
+ if dataset is None and lengths is None:
677
+ raise ValueError("One of dataset and lengths must be provided.")
678
+ if num_replicas is None:
679
+ if not dist.is_available():
680
+ raise RuntimeError("Requires distributed package to be available")
681
+ num_replicas = dist.get_world_size()
682
+ if rank is None:
683
+ if not dist.is_available():
684
+ raise RuntimeError("Requires distributed package to be available")
685
+ rank = dist.get_rank()
686
+
687
+ self.batch_size = batch_size
688
+ self.num_replicas = num_replicas
689
+ self.rank = rank
690
+ self.epoch = 0
691
+ self.drop_last = drop_last
692
+
693
+ if lengths is None:
694
+ model_input_name = model_input_name if model_input_name is not None else "input_ids"
695
+ if not isinstance(dataset[0], (dict, BatchEncoding)) or model_input_name not in dataset[0]:
696
+ raise ValueError(
697
+ "Can only automatically infer lengths for datasets whose items are dictionaries with an "
698
+ f"'{model_input_name}' key."
699
+ )
700
+ lengths = [len(feature[model_input_name]) for feature in dataset]
701
+ elif isinstance(lengths, torch.Tensor):
702
+ logger.info(
703
+ "If lengths is a torch.Tensor, DistributedLengthGroupedSampler will be slow. Converting lengths to"
704
+ " list[int]..."
705
+ )
706
+ lengths = lengths.tolist()
707
+
708
+ self.lengths = lengths
709
+
710
+ # If the dataset length is evenly divisible by # of replicas, then there
711
+ # is no need to drop any data, since the dataset will be split equally.
712
+ if self.drop_last and len(self.lengths) % self.num_replicas != 0:
713
+ # Split to nearest available length that is evenly divisible.
714
+ # This is to ensure each rank receives the same amount of data when
715
+ # using this Sampler.
716
+ self.num_samples = math.ceil((len(self.lengths) - self.num_replicas) / self.num_replicas)
717
+ else:
718
+ self.num_samples = math.ceil(len(self.lengths) / self.num_replicas)
719
+ self.total_size = self.num_samples * self.num_replicas
720
+ self.seed = seed
721
+
722
+ def __iter__(self) -> Iterator:
723
+ # Deterministically shuffle based on epoch and seed
724
+ g = torch.Generator()
725
+ g.manual_seed(self.seed + self.epoch)
726
+ indices = get_length_grouped_indices(self.lengths, self.batch_size, generator=g)
727
+
728
+ if not self.drop_last:
729
+ # add extra samples to make it evenly divisible
730
+ indices += indices[: (self.total_size - len(indices))]
731
+ else:
732
+ # remove tail of data to make it evenly divisible
733
+ indices = indices[: self.total_size]
734
+ assert len(indices) == self.total_size
735
+
736
+ # subsample
737
+ indices = indices[self.rank : self.total_size : self.num_replicas]
738
+ assert len(indices) == self.num_samples
739
+
740
+ return iter(indices)
741
+
742
+
743
+ class ShardSampler(Sampler):
744
+ """
745
+ Sampler that shards batches between several processes. Dispatches indices batch by batch: on 2 processes with batch
746
+ size 4, the first two batches are `[0, 1, 2, 3, 4, 5, 6, 7]` and `[8, 9, 10, 11, 12, 13, 14, 15]`, which shard into
747
+ `[0, 1, 2, 3]` and `[8, 9, 10, 11]` for GPU-0 and `[4, 5, 6, 7]` and `[12, 13, 14, 15]` for GPU-1.
748
+
749
+ The sampler thus yields `[0, 1, 2, 3, 8, 9, 10, 11]` on GPU-0 and `[4, 5, 6, 7, 12, 13, 14, 15]` on GPU-1.
750
+ """
751
+
752
+ def __init__(
753
+ self,
754
+ dataset: Dataset,
755
+ batch_size: int = 1,
756
+ drop_last: bool = False,
757
+ num_processes: int = 1,
758
+ process_index: int = 0,
759
+ ):
760
+ self.dataset = dataset
761
+ self.batch_size = batch_size
762
+ self.drop_last = drop_last
763
+ self.num_processes = num_processes
764
+ self.process_index = process_index
765
+
766
+ self.total_batch_size = total_batch_size = batch_size * num_processes
767
+
768
+ num_batches = len(dataset) // total_batch_size if drop_last else math.ceil(len(dataset) / total_batch_size)
769
+ self.total_num_samples = num_batches * total_batch_size
770
+
771
+ def __iter__(self):
772
+ indices = list(range(len(self.dataset)))
773
+
774
+ # Add extra samples to make it evenly divisible. While loop is there in the edge case we have a tiny dataset
775
+ # and it needs to be done several times.
776
+ while len(indices) < self.total_num_samples:
777
+ indices += indices[: (self.total_num_samples - len(indices))]
778
+
779
+ result = []
780
+ for batch_start in range(self.batch_size * self.process_index, self.total_num_samples, self.total_batch_size):
781
+ result += indices[batch_start : batch_start + self.batch_size]
782
+
783
+ return iter(result)
784
+
785
+ def __len__(self):
786
+ # Each shard only sees a fraction of total_num_samples.
787
+ return self.total_num_samples // self.num_processes
788
+
789
+
790
+ class IterableDatasetShard(IterableDataset):
791
+ """
792
+ Wraps a PyTorch `IterableDataset` to generate samples for one of the processes only. Instances of this class will
793
+ always yield a number of samples that is a round multiple of the actual batch size (which is `batch_size x
794
+ num_processes`). Depending on the value of the `drop_last` attribute, it will either stop the iteration at the
795
+ first batch that would be too small or loop with indices from the beginning.
796
+
797
+ On two processes with an iterable dataset yielding of `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]` with a batch size of
798
+ 2:
799
+
800
+ - the shard on process 0 will yield `[0, 1, 4, 5, 8, 9]` so will see batches `[0, 1]`, `[4, 5]`, `[8, 9]`
801
+ - the shard on process 1 will yield `[2, 3, 6, 7, 10, 11]` so will see batches `[2, 3]`, `[6, 7]`, `[10, 11]`
802
+
803
+ <Tip warning={true}>
804
+
805
+ If your IterableDataset implements some randomization that needs to be applied the same way on all processes
806
+ (for instance, a shuffling), you should use a `torch.Generator` in a `generator` attribute of the `dataset` to
807
+ generate your random numbers and call the [`~trainer_pt_utils.IterableDatasetShard.set_epoch`] method of this
808
+ object. It will set the seed of this `generator` to `seed + epoch` on all processes before starting the
809
+ iteration. Alternatively, you can also implement a `set_epoch()` method in your iterable dataset to deal with
810
+ this.
811
+
812
+ </Tip>
813
+
814
+ Args:
815
+ dataset (`torch.utils.data.IterableDataset`):
816
+ The batch sampler to split in several shards.
817
+ batch_size (`int`, *optional*, defaults to 1):
818
+ The size of the batches per shard.
819
+ drop_last (`bool`, *optional*, defaults to `False`):
820
+ Whether or not to drop the last incomplete batch or complete the last batches by using the samples from the
821
+ beginning.
822
+ num_processes (`int`, *optional*, defaults to 1):
823
+ The number of processes running concurrently.
824
+ process_index (`int`, *optional*, defaults to 0):
825
+ The index of the current process.
826
+ seed (`int`, *optional*, defaults to 0):
827
+ A random seed that will be used for the random number generation in
828
+ [`~trainer_pt_utils.IterableDatasetShard.set_epoch`].
829
+ """
830
+
831
+ def __init__(
832
+ self,
833
+ dataset: IterableDataset,
834
+ batch_size: int = 1,
835
+ drop_last: bool = False,
836
+ num_processes: int = 1,
837
+ process_index: int = 0,
838
+ seed: int = 0,
839
+ ):
840
+ self.dataset = dataset
841
+ self.batch_size = batch_size
842
+ self.drop_last = drop_last
843
+ self.num_processes = num_processes
844
+ self.process_index = process_index
845
+ self.seed = seed
846
+ self.epoch = 0
847
+ self.num_examples = 0
848
+
849
+ def set_epoch(self, epoch):
850
+ self.epoch = epoch
851
+ if hasattr(self.dataset, "set_epoch"):
852
+ self.dataset.set_epoch(epoch)
853
+
854
+ def __iter__(self):
855
+ self.num_examples = 0
856
+ if (
857
+ not hasattr(self.dataset, "set_epoch")
858
+ and hasattr(self.dataset, "generator")
859
+ and isinstance(self.dataset.generator, torch.Generator)
860
+ ):
861
+ self.dataset.generator.manual_seed(self.seed + self.epoch)
862
+ real_batch_size = self.batch_size * self.num_processes
863
+ process_slice = range(self.process_index * self.batch_size, (self.process_index + 1) * self.batch_size)
864
+
865
+ first_batch = None
866
+ current_batch = []
867
+ for element in self.dataset:
868
+ self.num_examples += 1
869
+ current_batch.append(element)
870
+ # Wait to have a full batch before yielding elements.
871
+ if len(current_batch) == real_batch_size:
872
+ for i in process_slice:
873
+ yield current_batch[i]
874
+ if first_batch is None:
875
+ first_batch = current_batch.copy()
876
+ current_batch = []
877
+
878
+ # Finished if drop_last is True, otherwise complete the last batch with elements from the beginning.
879
+ if not self.drop_last and len(current_batch) > 0:
880
+ if first_batch is None:
881
+ first_batch = current_batch.copy()
882
+ while len(current_batch) < real_batch_size:
883
+ current_batch += first_batch
884
+ for i in process_slice:
885
+ yield current_batch[i]
886
+
887
+ def __len__(self):
888
+ # Will raise an error if the underlying dataset is not sized.
889
+ if self.drop_last:
890
+ return (len(self.dataset) // (self.batch_size * self.num_processes)) * self.batch_size
891
+ else:
892
+ return math.ceil(len(self.dataset) / (self.batch_size * self.num_processes)) * self.batch_size
893
+
894
+
895
+ # In order to keep `trainer.py` compact and easy to understand, place any secondary PT Trainer
896
+ # helper methods here
897
+
898
+
899
+ def _get_learning_rate(self):
900
+ if self.is_deepspeed_enabled:
901
+ # with deepspeed's fp16 and dynamic loss scale enabled the optimizer/scheduler steps may
902
+ # not run for the first few dozen steps while loss scale is too large, and thus during
903
+ # that time `get_last_lr` will fail if called during that warm up stage, so work around it:
904
+ try:
905
+ last_lr = self.lr_scheduler.get_last_lr()[0]
906
+ except AssertionError as e:
907
+ if "need to call step" in str(e):
908
+ logger.warning("tried to get lr value before scheduler/optimizer started stepping, returning lr=0")
909
+ last_lr = 0
910
+ else:
911
+ raise
912
+ else:
913
+ if isinstance(self.lr_scheduler, torch.optim.lr_scheduler.ReduceLROnPlateau):
914
+ last_lr = self.optimizer.param_groups[0]["lr"]
915
+ else:
916
+ last_lr = self.lr_scheduler.get_last_lr()[0]
917
+
918
+ if torch.is_tensor(last_lr):
919
+ last_lr = last_lr.item()
920
+ return last_lr
921
+
922
+
923
+ def _secs2timedelta(secs):
924
+ """
925
+ Convert seconds to hh:mm:ss.msec, msecs rounded to 2 decimal places.
926
+ """
927
+
928
+ msec = int(abs(secs - int(secs)) * 100)
929
+ return f"{datetime.timedelta(seconds=int(secs))}.{msec:02d}"
930
+
931
+
932
+ def metrics_format(metrics: dict[str, float]) -> dict[str, float]:
933
+ """
934
+ Reformat Trainer metrics values to a human-readable format.
935
+
936
+ Args:
937
+ metrics (`dict[str, float]`):
938
+ The metrics returned from train/evaluate/predict
939
+
940
+ Returns:
941
+ metrics (`dict[str, float]`): The reformatted metrics
942
+ """
943
+
944
+ metrics_copy = metrics.copy()
945
+ for k, v in metrics_copy.items():
946
+ if "_mem_" in k:
947
+ metrics_copy[k] = f"{v >> 20}MB"
948
+ elif "_runtime" in k:
949
+ metrics_copy[k] = _secs2timedelta(v)
950
+ elif k == "total_flos":
951
+ metrics_copy[k] = f"{int(v) >> 30}GF"
952
+ elif isinstance(metrics_copy[k], float):
953
+ metrics_copy[k] = round(v, 4)
954
+
955
+ return metrics_copy
956
+
957
+
958
+ def log_metrics(self, split, metrics):
959
+ """
960
+ Log metrics in a specially formatted way.
961
+
962
+ Under distributed environment this is done only for a process with rank 0.
963
+
964
+ Args:
965
+ split (`str`):
966
+ Mode/split name: one of `train`, `eval`, `test`
967
+ metrics (`dict[str, float]`):
968
+ The metrics returned from train/evaluate/predictmetrics: metrics dict
969
+
970
+ Notes on memory reports:
971
+
972
+ In order to get memory usage report you need to install `psutil`. You can do that with `pip install psutil`.
973
+
974
+ Now when this method is run, you will see a report that will include:
975
+
976
+ ```
977
+ init_mem_cpu_alloc_delta = 1301MB
978
+ init_mem_cpu_peaked_delta = 154MB
979
+ init_mem_gpu_alloc_delta = 230MB
980
+ init_mem_gpu_peaked_delta = 0MB
981
+ train_mem_cpu_alloc_delta = 1345MB
982
+ train_mem_cpu_peaked_delta = 0MB
983
+ train_mem_gpu_alloc_delta = 693MB
984
+ train_mem_gpu_peaked_delta = 7MB
985
+ ```
986
+
987
+ **Understanding the reports:**
988
+
989
+ - the first segment, e.g., `train__`, tells you which stage the metrics are for. Reports starting with `init_`
990
+ will be added to the first stage that gets run. So that if only evaluation is run, the memory usage for the
991
+ `__init__` will be reported along with the `eval_` metrics.
992
+ - the third segment, is either `cpu` or `gpu`, tells you whether it's the general RAM or the gpu0 memory
993
+ metric.
994
+ - `*_alloc_delta` - is the difference in the used/allocated memory counter between the end and the start of the
995
+ stage - it can be negative if a function released more memory than it allocated.
996
+ - `*_peaked_delta` - is any extra memory that was consumed and then freed - relative to the current allocated
997
+ memory counter - it is never negative. When you look at the metrics of any stage you add up `alloc_delta` +
998
+ `peaked_delta` and you know how much memory was needed to complete that stage.
999
+
1000
+ The reporting happens only for process of rank 0 and gpu 0 (if there is a gpu). Typically this is enough since the
1001
+ main process does the bulk of work, but it could be not quite so if model parallel is used and then other GPUs may
1002
+ use a different amount of gpu memory. This is also not the same under DataParallel where gpu0 may require much more
1003
+ memory than the rest since it stores the gradient and optimizer states for all participating GPUs. Perhaps in the
1004
+ future these reports will evolve to measure those too.
1005
+
1006
+ The CPU RAM metric measures RSS (Resident Set Size) includes both the memory which is unique to the process and the
1007
+ memory shared with other processes. It is important to note that it does not include swapped out memory, so the
1008
+ reports could be imprecise.
1009
+
1010
+ The CPU peak memory is measured using a sampling thread. Due to python's GIL it may miss some of the peak memory if
1011
+ that thread didn't get a chance to run when the highest memory was used. Therefore this report can be less than
1012
+ reality. Using `tracemalloc` would have reported the exact peak memory, but it doesn't report memory allocations
1013
+ outside of python. So if some C++ CUDA extension allocated its own memory it won't be reported. And therefore it
1014
+ was dropped in favor of the memory sampling approach, which reads the current process memory usage.
1015
+
1016
+ The GPU allocated and peak memory reporting is done with `torch.cuda.memory_allocated()` and
1017
+ `torch.cuda.max_memory_allocated()`. This metric reports only "deltas" for pytorch-specific allocations, as
1018
+ `torch.cuda` memory management system doesn't track any memory allocated outside of pytorch. For example, the very
1019
+ first cuda call typically loads CUDA kernels, which may take from 0.5 to 2GB of GPU memory.
1020
+
1021
+ Note that this tracker doesn't account for memory allocations outside of [`Trainer`]'s `__init__`, `train`,
1022
+ `evaluate` and `predict` calls.
1023
+
1024
+ Because `evaluation` calls may happen during `train`, we can't handle nested invocations because
1025
+ `torch.cuda.max_memory_allocated` is a single counter, so if it gets reset by a nested eval call, `train`'s tracker
1026
+ will report incorrect info. If this [pytorch issue](https://github.com/pytorch/pytorch/issues/16266) gets resolved
1027
+ it will be possible to change this class to be re-entrant. Until then we will only track the outer level of
1028
+ `train`, `evaluate` and `predict` methods. Which means that if `eval` is called during `train`, it's the latter
1029
+ that will account for its memory usage and that of the former.
1030
+
1031
+ This also means that if any other tool that is used along the [`Trainer`] calls
1032
+ `torch.cuda.reset_peak_memory_stats`, the gpu peak memory stats could be invalid. And the [`Trainer`] will disrupt
1033
+ the normal behavior of any such tools that rely on calling `torch.cuda.reset_peak_memory_stats` themselves.
1034
+
1035
+ For best performance you may want to consider turning the memory profiling off for production runs.
1036
+ """
1037
+ if not self.is_world_process_zero():
1038
+ return
1039
+
1040
+ print(f"***** {split} metrics *****")
1041
+ metrics_formatted = metrics_format(metrics)
1042
+ k_width = max(len(str(x)) for x in metrics_formatted)
1043
+ v_width = max(len(str(x)) for x in metrics_formatted.values())
1044
+ for key in sorted(metrics_formatted.keys()):
1045
+ print(f" {key: <{k_width}} = {metrics_formatted[key]:>{v_width}}")
1046
+
1047
+
1048
+ def save_metrics(self, split, metrics, combined=True):
1049
+ """
1050
+ Save metrics into a json file for that split, e.g. `train_results.json`.
1051
+
1052
+ Under distributed environment this is done only for a process with rank 0.
1053
+
1054
+ Args:
1055
+ split (`str`):
1056
+ Mode/split name: one of `train`, `eval`, `test`, `all`
1057
+ metrics (`dict[str, float]`):
1058
+ The metrics returned from train/evaluate/predict
1059
+ combined (`bool`, *optional*, defaults to `True`):
1060
+ Creates combined metrics by updating `all_results.json` with metrics of this call
1061
+
1062
+ To understand the metrics please read the docstring of [`~Trainer.log_metrics`]. The only difference is that raw
1063
+ unformatted numbers are saved in the current method.
1064
+
1065
+ """
1066
+ if not self.is_world_process_zero():
1067
+ return
1068
+
1069
+ path = os.path.join(self.args.output_dir, f"{split}_results.json")
1070
+ with open(path, "w") as f:
1071
+ json.dump(metrics, f, indent=4, sort_keys=True)
1072
+
1073
+ if combined:
1074
+ path = os.path.join(self.args.output_dir, "all_results.json")
1075
+ if os.path.exists(path):
1076
+ with open(path) as f:
1077
+ all_metrics = json.load(f)
1078
+ else:
1079
+ all_metrics = {}
1080
+
1081
+ all_metrics.update(metrics)
1082
+ with open(path, "w") as f:
1083
+ json.dump(all_metrics, f, indent=4, sort_keys=True)
1084
+
1085
+
1086
+ def save_state(self):
1087
+ """
1088
+ Saves the Trainer state, since Trainer.save_model saves only the tokenizer with the model.
1089
+
1090
+ Under distributed environment this is done only for a process with rank 0.
1091
+ """
1092
+ if not self.is_world_process_zero():
1093
+ return
1094
+
1095
+ path = os.path.join(self.args.output_dir, "trainer_state.json")
1096
+ self.state.save_to_json(path)
1097
+
1098
+
1099
+ def get_model_param_count(model, trainable_only=False):
1100
+ """
1101
+ Calculate model's total param count. If trainable_only is True then count only those requiring grads.
1102
+ """
1103
+ if is_deepspeed_zero3_enabled():
1104
+
1105
+ def numel(p):
1106
+ return p.ds_numel if hasattr(p, "ds_numel") else p.numel()
1107
+
1108
+ else:
1109
+
1110
+ def numel(p):
1111
+ return p.numel()
1112
+
1113
+ return sum(numel(p) for p in model.parameters() if not trainable_only or p.requires_grad)
1114
+
1115
+
1116
+ def get_parameter_names(model, forbidden_layer_types, forbidden_layer_names=None):
1117
+ """
1118
+ Returns the names of the model parameters that are not inside a forbidden layer.
1119
+ """
1120
+ forbidden_layer_patterns = (
1121
+ [re.compile(pattern) for pattern in forbidden_layer_names] if forbidden_layer_names is not None else []
1122
+ )
1123
+ result = []
1124
+ for name, child in model.named_children():
1125
+ child_params = get_parameter_names(child, forbidden_layer_types, forbidden_layer_names)
1126
+ result += [
1127
+ f"{name}.{n}"
1128
+ for n in child_params
1129
+ if not isinstance(child, tuple(forbidden_layer_types))
1130
+ and not any(pattern.search(f"{name}.{n}".lower()) for pattern in forbidden_layer_patterns)
1131
+ ]
1132
+ # Add model specific parameters that are not in any child
1133
+ result += [
1134
+ k for k in model._parameters if not any(pattern.search(k.lower()) for pattern in forbidden_layer_patterns)
1135
+ ]
1136
+
1137
+ return result
1138
+
1139
+
1140
+ def get_module_class_from_name(module, name):
1141
+ """
1142
+ Gets a class from a module by its name.
1143
+
1144
+ Args:
1145
+ module (`torch.nn.Module`): The module to get the class from.
1146
+ name (`str`): The name of the class.
1147
+ """
1148
+ modules_children = list(module.children())
1149
+ if module.__class__.__name__ == name:
1150
+ return module.__class__
1151
+ elif len(modules_children) == 0:
1152
+ return
1153
+ else:
1154
+ for child_module in modules_children:
1155
+ module_class = get_module_class_from_name(child_module, name)
1156
+ if module_class is not None:
1157
+ return module_class
1158
+
1159
+
1160
+ def remove_dummy_checkpoint(is_main_process, output_dir, filenames):
1161
+ if is_main_process:
1162
+ for filename in filenames:
1163
+ file = os.path.join(output_dir, filename)
1164
+ if os.path.isfile(file):
1165
+ os.remove(file)
1166
+
1167
+
1168
+ if is_sagemaker_mp_enabled():
1169
+ import smdistributed.modelparallel.torch as smp
1170
+
1171
+ @smp.step()
1172
+ def smp_forward_backward(model, inputs, gradient_accumulation_steps=1):
1173
+ outputs = model(**inputs)
1174
+ loss = outputs["loss"] if isinstance(outputs, dict) else outputs[0]
1175
+ loss /= gradient_accumulation_steps
1176
+ model.backward(loss)
1177
+ return loss
1178
+
1179
+ @smp.step()
1180
+ def smp_forward_only(model, inputs):
1181
+ return model(**inputs)
1182
+
1183
+ def smp_gather(tensor):
1184
+ if isinstance(tensor, (list, tuple)):
1185
+ return type(tensor)(smp_gather(t) for t in tensor)
1186
+ elif isinstance(tensor, dict):
1187
+ return type(tensor)({k: smp_gather(v) for k, v in tensor.items()})
1188
+ elif not isinstance(tensor, torch.Tensor):
1189
+ raise TypeError(
1190
+ f"Can't gather the values of type {type(tensor)}, only of nested list/tuple/dicts of tensors."
1191
+ )
1192
+ all_tensors = smp.allgather(tensor, smp.CommGroup.DP_GROUP)
1193
+ all_tensors = [atleast_1d(t) for t in all_tensors]
1194
+ return torch.cat([t.cpu() for t in all_tensors], dim=0)
1195
+
1196
+ def smp_nested_concat(tensor):
1197
+ if isinstance(tensor, (list, tuple)):
1198
+ return type(tensor)(smp_nested_concat(t) for t in tensor)
1199
+ elif isinstance(tensor, dict):
1200
+ return type(tensor)({k: smp_nested_concat(v) for k, v in tensor.items()})
1201
+ # It doesn't seem possible to check here if `tensor` is a StepOutput because StepOutput lives in `smp.step`
1202
+ # which is also the name of the decorator so Python is confused.
1203
+ return tensor.detach().concat().cpu()
1204
+
1205
+
1206
+ @dataclass
1207
+ class AcceleratorConfig:
1208
+ """
1209
+ A subset of arguments relating to the underlying [`accelerate.Accelerator`]
1210
+ implementation utilized in the `Trainer` that can be customized.
1211
+ Mostly relating to data.
1212
+
1213
+ Parameters:
1214
+ split_batches (`bool`, *optional*, defaults to `False`):
1215
+ Whether or not the accelerator should split the batches yielded by the dataloaders across the devices. If
1216
+ `True` the actual batch size used will be the same on any kind of distributed processes, but it must be a
1217
+ round multiple of the `num_processes` you are using. If `False`, actual batch size used will be the one set
1218
+ in your script multiplied by the number of processes.
1219
+ dispatch_batches (`bool`, *optional*):
1220
+ If set to `True`, the dataloader prepared by the Accelerator is only iterated through on the main process
1221
+ and then the batches are split and broadcast to each process. Will default to `True` for `DataLoader` whose
1222
+ underlying dataset is an `IterableDataset`, `False` otherwise.
1223
+ even_batches (`bool`, *optional*, defaults to `True`):
1224
+ If set to `True`, in cases where the total batch size across all processes does not exactly divide the
1225
+ dataset, samples at the start of the dataset will be duplicated so the batch can be divided equally among
1226
+ all workers.
1227
+ use_seedable_sampler (`bool`, *optional*, defaults to `True`):
1228
+ Whether or not use a fully seedable random sampler ([`accelerate.data_loader.SeedableRandomSampler`]). Ensures
1229
+ training results are fully reproducible using a different sampling technique. While seed-to-seed results
1230
+ may differ, on average the differences are negligible when using multiple different seeds to compare. Should
1231
+ also be ran with [`~utils.set_seed`] for the best results.
1232
+ gradient_accumulation_kwargs (`dict`, *optional*):
1233
+ Additional kwargs to configure gradient accumulation, see [`accelerate.utils.GradientAccumulationPlugin`].
1234
+ Any of the following (optional) keys are acceptable:
1235
+ num_steps (`int`): Will take precedence over [`~.TrainingArguments.gradient_accumulation_steps`] if
1236
+ the latter is set to 1, otherwise an exception will be raised.
1237
+ adjust_scheduler (`bool`): Whether to adjust the scheduler steps to account for [`~.TrainingArguments.gradient_accumulation_steps`].
1238
+ The [`accelerate.utils.GradientAccumulationPlugin`] default is `True`.
1239
+ sync_each_batch (`bool`): Whether to synchronize the gradients at each data batch.
1240
+ The [`accelerate.utils.GradientAccumulationPlugin`] default is `False`.
1241
+ non_blocking (`bool`, *optional*, defaults to `False`):
1242
+ Whether to use non-blocking CUDA calls to help minimize synchronization during
1243
+ distributed training with prepared `DataLoader` inputs being moved to device.
1244
+ Best if used with `pin_memory=True` in the `TrainingArguments`.
1245
+ use_configured_state (`bool*, *optional*, defaults to `False`):
1246
+ Whether or not to use a pre-configured `AcceleratorState` or `PartialState` defined
1247
+ before calling `TrainingArguments`. If `True`, an `Accelerator` or `PartialState`
1248
+ must be initialized. May lead to issues using sweeps or hyperparameter tuning.
1249
+
1250
+ """
1251
+
1252
+ # Data related arguments
1253
+ split_batches: bool = field(
1254
+ default=False,
1255
+ metadata={
1256
+ "help": "Whether or not the accelerator should split the batches yielded by the dataloaders across the devices. If"
1257
+ " `True` the actual batch size used will be the same on any kind of distributed processes, but it must be a"
1258
+ " round multiple of the `num_processes` you are using. If `False`, actual batch size used will be the one set"
1259
+ " in your script multiplied by the number of processes."
1260
+ },
1261
+ )
1262
+ dispatch_batches: Optional[bool] = field(
1263
+ default=None,
1264
+ metadata={
1265
+ "help": "If set to `True`, the dataloader prepared by the Accelerator is only iterated through on the main process"
1266
+ " and then the batches are split and broadcast to each process. Will default to `True` for `DataLoader` whose"
1267
+ " underlying dataset is an `IterableDataslet`, `False` otherwise."
1268
+ },
1269
+ )
1270
+ even_batches: bool = field(
1271
+ default=True,
1272
+ metadata={
1273
+ "help": "If set to `True`, in cases where the total batch size across all processes does not exactly divide the"
1274
+ " dataset, samples at the start of the dataset will be duplicated so the batch can be divided equally among"
1275
+ " all workers."
1276
+ },
1277
+ )
1278
+ use_seedable_sampler: bool = field(
1279
+ default=True,
1280
+ metadata={
1281
+ "help": "Whether or not use a fully seedable random sampler ([`accelerate.data_loader.SeedableRandomSampler`])."
1282
+ "Ensures training results are fully reproducible using a different sampling technique. "
1283
+ "While seed-to-seed results may differ, on average the differences are negligible when using"
1284
+ "multiple different seeds to compare. Should also be ran with [`~utils.set_seed`] for the best results."
1285
+ },
1286
+ )
1287
+
1288
+ non_blocking: bool = field(
1289
+ default=False,
1290
+ metadata={
1291
+ "help": "Whether to use non-blocking CUDA calls to help minimize synchronization during "
1292
+ "distributed training with prepared `DataLoader` inputs being moved to device. "
1293
+ "Best if used with `pin_memory=True` in the `TrainingArguments`. Requires accelerate "
1294
+ "v0.30.0."
1295
+ },
1296
+ )
1297
+
1298
+ gradient_accumulation_kwargs: Optional[dict] = field(
1299
+ default=None,
1300
+ metadata={
1301
+ "help": "Additional kwargs to configure gradient accumulation, see [`accelerate.utils.GradientAccumulationPlugin`]. "
1302
+ "Any of the following (optional) keys are acceptable: "
1303
+ " num_steps (`int`): Will take precedence over [`~.TrainingArguments.gradient_accumulation_steps`] if "
1304
+ " the latter is set to 1, otherwise an exception will be raised. "
1305
+ " adjust_scheduler (`bool`): Whether to adjust the scheduler steps to account for [`~.TrainingArguments.gradient_accumulation_steps`]. "
1306
+ " The [`accelerate.utils.GradientAccumulationPlugin`] default is `True`. "
1307
+ " sync_each_batch (`bool`): Whether to synchronize the gradients at each data batch. "
1308
+ " The [`accelerate.utils.GradientAccumulationPlugin`] default is `False`."
1309
+ },
1310
+ )
1311
+ use_configured_state: bool = field(
1312
+ default=False,
1313
+ metadata={
1314
+ "help": "Whether or not to use a pre-configured `AcceleratorState` or `PartialState` defined before calling `TrainingArguments`."
1315
+ "If `True`, an `Accelerator` or `PartialState` must be initialized. May lead to issues using sweeps or hyperparameter tuning."
1316
+ },
1317
+ )
1318
+
1319
+ @classmethod
1320
+ def from_json_file(cls, json_file):
1321
+ # Check if exists
1322
+ open_file = io.open if os.path.exists(json_file) else open
1323
+ with open_file(json_file, "r", encoding="utf-8") as f:
1324
+ config_dict = json.load(f)
1325
+ # Check for keys and load sensible defaults
1326
+ extra_keys = sorted(key for key in config_dict if key not in cls.__dataclass_fields__)
1327
+ if len(extra_keys) > 0:
1328
+ raise ValueError(
1329
+ f"The config file at {json_file} had unknown keys ({extra_keys}), please try upgrading your `transformers`"
1330
+ " version or fix (and potentially remove these keys) from your config file."
1331
+ )
1332
+ return cls(**config_dict)
1333
+
1334
+ def to_dict(self):
1335
+ return copy.deepcopy(self.__dict__)
1336
+
1337
+ def pop(self, key, default=None):
1338
+ return self.__dict__.pop(key, default)
1339
+
1340
+
1341
+ class LayerWiseDummyOptimizer(torch.optim.Optimizer):
1342
+ """
1343
+ For Layer-wise optimizers such as GaLoRE optimizer, the optimization
1344
+ step is already done through the post gradient hooks. Therefore
1345
+ the trick is to create a dummy optimizer that can take arbitrary
1346
+ args and kwargs and return a no-op during training.
1347
+
1348
+ Initial idea from @hiyouga in LLaMA-Factory:
1349
+ https://github.com/hiyouga/LLaMA-Factory/commit/8664262cde3919e10eaecbd66e8c5d356856362e#diff-ebe08ab14496dfb9e06075f0fdd36799ef6d1535cc4dd4715b74c4e3e06fe3ba
1350
+ """
1351
+
1352
+ def __init__(self, optimizer_dict=None, **kwargs):
1353
+ dummy_tensor = torch.randn(1, 1)
1354
+ self.optimizer_dict = optimizer_dict
1355
+ super().__init__([dummy_tensor], {"lr": kwargs.get("lr", 1e-03)})
1356
+
1357
+ def zero_grad(self, set_to_none: bool = True) -> None:
1358
+ pass
1359
+
1360
+ def step(self, closure=None) -> Optional[float]:
1361
+ pass
1362
+
1363
+
1364
+ class LayerWiseDummyScheduler(LRScheduler):
1365
+ """
1366
+ For Layer-wise optimizers such as GaLoRE optimizer, the optimization and scheduling step
1367
+ are already done through the post gradient hooks. Therefore
1368
+ the trick is to create a dummy scheduler that can take arbitrary
1369
+ args and kwargs and return a no-op during training.
1370
+ """
1371
+
1372
+ def __init__(self, *args, **kwargs):
1373
+ self.default_lr = kwargs["lr"]
1374
+ optimizer = LayerWiseDummyOptimizer(**kwargs)
1375
+ last_epoch = -1
1376
+ super().__init__(optimizer, last_epoch)
1377
+
1378
+ def get_lr(self):
1379
+ # default value
1380
+ lrs = [self.default_lr]
1381
+
1382
+ # we take each lr in the parameters if they exist, assumes the optimizer to be the `LayerWiseDummyOptimizer`
1383
+ if self.optimizer is not None:
1384
+ param_wise_lrs = [
1385
+ [group["lr"] for group in optim.param_groups] for optim in self.optimizer.optimizer_dict.values()
1386
+ ]
1387
+ lrs = list(chain(*param_wise_lrs))
1388
+
1389
+ return lrs
1390
+
1391
+ def _get_closed_form_lr(self):
1392
+ return self.base_lrs
1393
+
1394
+
1395
+ def set_rng_state_for_device(device_name, device_module, checkpoint_rng_state, is_distributed):
1396
+ """Helper to set RNG state for a specific device type (CUDA, NPU, MLU, MUSA)"""
1397
+ device_state_key = device_name.lower()
1398
+ err_template = "Didn't manage to set back the RNG states of the {backend} because of the following error:\n {exception}\nThis won't yield the same results as if the training had not been interrupted."
1399
+ try:
1400
+ if is_distributed:
1401
+ device_module.random.set_rng_state_all(checkpoint_rng_state[device_state_key])
1402
+ else:
1403
+ device_module.random.set_rng_state(checkpoint_rng_state[device_state_key])
1404
+ except Exception as e:
1405
+ # Log error if setting RNG state fails
1406
+ logger.error(err_template.format(backend=device_name, exception=e))
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/trainer_seq2seq.py ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import contextlib
16
+ from copy import deepcopy
17
+ from pathlib import Path
18
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Union
19
+
20
+ import torch
21
+ from torch import nn
22
+ from torch.distributed.fsdp import FullyShardedDataParallel
23
+ from torch.utils.data import Dataset
24
+
25
+ from .generation.configuration_utils import GenerationConfig
26
+ from .integrations.deepspeed import is_deepspeed_zero3_enabled
27
+ from .integrations.fsdp import is_fsdp_managed_module
28
+ from .trainer import Trainer
29
+ from .utils import is_datasets_available, logging
30
+ from .utils.deprecation import deprecate_kwarg
31
+
32
+
33
+ if is_datasets_available():
34
+ import datasets
35
+
36
+ if TYPE_CHECKING:
37
+ from torch.utils.data import IterableDataset
38
+
39
+ from .data.data_collator import DataCollator
40
+ from .feature_extraction_utils import FeatureExtractionMixin
41
+ from .image_processing_utils import BaseImageProcessor
42
+ from .modeling_utils import PreTrainedModel
43
+ from .processing_utils import ProcessorMixin
44
+ from .tokenization_utils_base import PreTrainedTokenizerBase
45
+ from .trainer_callback import TrainerCallback
46
+ from .trainer_utils import EvalPrediction, PredictionOutput
47
+ from .training_args import TrainingArguments
48
+
49
+
50
+ logger = logging.get_logger(__name__)
51
+
52
+
53
+ class Seq2SeqTrainer(Trainer):
54
+ @deprecate_kwarg("tokenizer", new_name="processing_class", version="5.0.0", raise_if_both_names=True)
55
+ def __init__(
56
+ self,
57
+ model: Optional[Union["PreTrainedModel", nn.Module]] = None,
58
+ args: Optional["TrainingArguments"] = None,
59
+ data_collator: Optional["DataCollator"] = None,
60
+ train_dataset: Optional[Union[Dataset, "IterableDataset", "datasets.Dataset"]] = None,
61
+ eval_dataset: Optional[Union[Dataset, dict[str, Dataset]]] = None,
62
+ processing_class: Optional[
63
+ Union["PreTrainedTokenizerBase", "BaseImageProcessor", "FeatureExtractionMixin", "ProcessorMixin"]
64
+ ] = None,
65
+ model_init: Optional[Callable[[], "PreTrainedModel"]] = None,
66
+ compute_loss_func: Optional[Callable] = None,
67
+ compute_metrics: Optional[Callable[["EvalPrediction"], dict]] = None,
68
+ callbacks: Optional[list["TrainerCallback"]] = None,
69
+ optimizers: tuple[Optional[torch.optim.Optimizer], Optional[torch.optim.lr_scheduler.LambdaLR]] = (None, None),
70
+ preprocess_logits_for_metrics: Optional[Callable[[torch.Tensor, torch.Tensor], torch.Tensor]] = None,
71
+ ):
72
+ super().__init__(
73
+ model=model,
74
+ args=args,
75
+ data_collator=data_collator,
76
+ train_dataset=train_dataset,
77
+ eval_dataset=eval_dataset,
78
+ processing_class=processing_class,
79
+ model_init=model_init,
80
+ compute_loss_func=compute_loss_func,
81
+ compute_metrics=compute_metrics,
82
+ callbacks=callbacks,
83
+ optimizers=optimizers,
84
+ preprocess_logits_for_metrics=preprocess_logits_for_metrics,
85
+ )
86
+
87
+ # Override self.model.generation_config if a GenerationConfig is specified in args.
88
+ # Priority: args.generation_config > model.generation_config > default GenerationConfig.
89
+ if self.args.generation_config is not None:
90
+ gen_config = self.load_generation_config(self.args.generation_config)
91
+ self.model.generation_config = gen_config
92
+
93
+ @staticmethod
94
+ def load_generation_config(gen_config_arg: Union[str, GenerationConfig]) -> GenerationConfig:
95
+ """
96
+ Loads a `~generation.GenerationConfig` from the `Seq2SeqTrainingArguments.generation_config` arguments.
97
+
98
+ Args:
99
+ gen_config_arg (`str` or [`~generation.GenerationConfig]`):
100
+ `Seq2SeqTrainingArguments.generation_config` argument.
101
+
102
+ Returns:
103
+ A `~generation.GenerationConfig`.
104
+ """
105
+
106
+ # GenerationConfig provided, nothing to do
107
+ if isinstance(gen_config_arg, GenerationConfig):
108
+ gen_config = deepcopy(gen_config_arg)
109
+ else:
110
+ # str or Path
111
+ pretrained_model_name = Path(gen_config_arg) if isinstance(gen_config_arg, str) else gen_config_arg
112
+ config_file_name = None
113
+
114
+ # Figuring if it is path pointing to a file, pointing to a directory or else a model id or URL
115
+ # This step is required in order to determine config_file_name
116
+ if pretrained_model_name.is_file():
117
+ config_file_name = pretrained_model_name.name
118
+ pretrained_model_name = pretrained_model_name.parent
119
+ # dir path
120
+ elif pretrained_model_name.is_dir():
121
+ pass
122
+ # model id or URL
123
+ else:
124
+ pretrained_model_name = gen_config_arg
125
+
126
+ gen_config = GenerationConfig.from_pretrained(pretrained_model_name, config_file_name)
127
+
128
+ # Strict validation to fail early. `GenerationConfig.save_pretrained()`, run at the end of training, throws
129
+ # an exception if there are warnings at validation time.
130
+ try:
131
+ gen_config.validate(strict=True)
132
+ except ValueError as exc:
133
+ raise ValueError(str(exc) + "\n\nFix these issues to train your model.")
134
+
135
+ return gen_config
136
+
137
+ def evaluate(
138
+ self,
139
+ eval_dataset: Optional[Dataset] = None,
140
+ ignore_keys: Optional[list[str]] = None,
141
+ metric_key_prefix: str = "eval",
142
+ **gen_kwargs,
143
+ ) -> dict[str, float]:
144
+ """
145
+ Run evaluation and returns metrics.
146
+
147
+ The calling script will be responsible for providing a method to compute metrics, as they are task-dependent
148
+ (pass it to the init `compute_metrics` argument).
149
+
150
+ You can also subclass and override this method to inject custom behavior.
151
+
152
+ Args:
153
+ eval_dataset (`Dataset`, *optional*):
154
+ Pass a dataset if you wish to override `self.eval_dataset`. If it is an [`~datasets.Dataset`], columns
155
+ not accepted by the `model.forward()` method are automatically removed. It must implement the `__len__`
156
+ method.
157
+ ignore_keys (`list[str]`, *optional*):
158
+ A list of keys in the output of your model (if it is a dictionary) that should be ignored when
159
+ gathering predictions.
160
+ metric_key_prefix (`str`, *optional*, defaults to `"eval"`):
161
+ An optional prefix to be used as the metrics key prefix. For example the metrics "bleu" will be named
162
+ "eval_bleu" if the prefix is `"eval"` (default)
163
+ max_length (`int`, *optional*):
164
+ The maximum target length to use when predicting with the generate method.
165
+ num_beams (`int`, *optional*):
166
+ Number of beams for beam search that will be used when predicting with the generate method. 1 means no
167
+ beam search.
168
+ gen_kwargs:
169
+ Additional `generate` specific kwargs.
170
+
171
+ Returns:
172
+ A dictionary containing the evaluation loss and the potential metrics computed from the predictions. The
173
+ dictionary also contains the epoch number which comes from the training state.
174
+ """
175
+
176
+ gen_kwargs = gen_kwargs.copy()
177
+
178
+ # Use legacy argument setting if a) the option is not explicitly passed; and b) the argument is set in the
179
+ # training args
180
+ if (
181
+ gen_kwargs.get("max_length") is None
182
+ and gen_kwargs.get("max_new_tokens") is None
183
+ and self.args.generation_max_length is not None
184
+ ):
185
+ gen_kwargs["max_length"] = self.args.generation_max_length
186
+ if gen_kwargs.get("num_beams") is None and self.args.generation_num_beams is not None:
187
+ gen_kwargs["num_beams"] = self.args.generation_num_beams
188
+ # We don't want to drop samples in general
189
+ self.gather_function = self.accelerator.gather
190
+ self._gen_kwargs = gen_kwargs
191
+ return super().evaluate(eval_dataset, ignore_keys=ignore_keys, metric_key_prefix=metric_key_prefix)
192
+
193
+ def predict(
194
+ self,
195
+ test_dataset: Dataset,
196
+ ignore_keys: Optional[list[str]] = None,
197
+ metric_key_prefix: str = "test",
198
+ **gen_kwargs,
199
+ ) -> "PredictionOutput":
200
+ """
201
+ Run prediction and returns predictions and potential metrics.
202
+
203
+ Depending on the dataset and your use case, your test dataset may contain labels. In that case, this method
204
+ will also return metrics, like in `evaluate()`.
205
+
206
+ Args:
207
+ test_dataset (`Dataset`):
208
+ Dataset to run the predictions on. If it is a [`~datasets.Dataset`], columns not accepted by the
209
+ `model.forward()` method are automatically removed. Has to implement the method `__len__`
210
+ ignore_keys (`list[str]`, *optional*):
211
+ A list of keys in the output of your model (if it is a dictionary) that should be ignored when
212
+ gathering predictions.
213
+ metric_key_prefix (`str`, *optional*, defaults to `"eval"`):
214
+ An optional prefix to be used as the metrics key prefix. For example the metrics "bleu" will be named
215
+ "eval_bleu" if the prefix is `"eval"` (default)
216
+ max_length (`int`, *optional*):
217
+ The maximum target length to use when predicting with the generate method.
218
+ num_beams (`int`, *optional*):
219
+ Number of beams for beam search that will be used when predicting with the generate method. 1 means no
220
+ beam search.
221
+ gen_kwargs:
222
+ Additional `generate` specific kwargs.
223
+
224
+ <Tip>
225
+
226
+ If your predictions or labels have different sequence lengths (for instance because you're doing dynamic
227
+ padding in a token classification task) the predictions will be padded (on the right) to allow for
228
+ concatenation into one array. The padding index is -100.
229
+
230
+ </Tip>
231
+
232
+ Returns: *NamedTuple* A namedtuple with the following keys:
233
+
234
+ - predictions (`np.ndarray`): The predictions on `test_dataset`.
235
+ - label_ids (`np.ndarray`, *optional*): The labels (if the dataset contained some).
236
+ - metrics (`dict[str, float]`, *optional*): The potential dictionary of metrics (if the dataset contained
237
+ labels).
238
+ """
239
+
240
+ gen_kwargs = gen_kwargs.copy()
241
+
242
+ # Use legacy argument setting if a) the option is not explicitly passed; and b) the argument is set in the
243
+ # training args
244
+ if (
245
+ gen_kwargs.get("max_length") is None
246
+ and gen_kwargs.get("max_new_tokens") is None
247
+ and self.args.generation_max_length is not None
248
+ ):
249
+ gen_kwargs["max_length"] = self.args.generation_max_length
250
+ if gen_kwargs.get("num_beams") is None and self.args.generation_num_beams is not None:
251
+ gen_kwargs["num_beams"] = self.args.generation_num_beams
252
+ self.gather_function = self.accelerator.gather
253
+ self._gen_kwargs = gen_kwargs
254
+
255
+ return super().predict(test_dataset, ignore_keys=ignore_keys, metric_key_prefix=metric_key_prefix)
256
+
257
+ def prediction_step(
258
+ self,
259
+ model: nn.Module,
260
+ inputs: dict[str, Union[torch.Tensor, Any]],
261
+ prediction_loss_only: bool,
262
+ ignore_keys: Optional[list[str]] = None,
263
+ **gen_kwargs,
264
+ ) -> tuple[Optional[float], Optional[torch.Tensor], Optional[torch.Tensor]]:
265
+ """
266
+ Perform an evaluation step on `model` using `inputs`.
267
+
268
+ Subclass and override to inject custom behavior.
269
+
270
+ Args:
271
+ model (`nn.Module`):
272
+ The model to evaluate.
273
+ inputs (`dict[str, Union[torch.Tensor, Any]]`):
274
+ The inputs and targets of the model.
275
+
276
+ The dictionary will be unpacked before being fed to the model. Most models expect the targets under the
277
+ argument `labels`. Check your model's documentation for all accepted arguments.
278
+ prediction_loss_only (`bool`):
279
+ Whether or not to return the loss only.
280
+ gen_kwargs:
281
+ Additional `generate` specific kwargs.
282
+
283
+ Return:
284
+ tuple[Optional[float], Optional[torch.Tensor], Optional[torch.Tensor]]: A tuple with the loss, logits and
285
+ labels (each being optional).
286
+ """
287
+
288
+ if not self.args.predict_with_generate or prediction_loss_only:
289
+ return super().prediction_step(
290
+ model, inputs, prediction_loss_only=prediction_loss_only, ignore_keys=ignore_keys
291
+ )
292
+
293
+ has_labels = "labels" in inputs
294
+ inputs = self._prepare_inputs(inputs)
295
+
296
+ # Priority (handled in generate):
297
+ # non-`None` gen_kwargs > model.generation_config > default GenerationConfig()
298
+ if len(gen_kwargs) == 0 and hasattr(self, "_gen_kwargs"):
299
+ gen_kwargs = self._gen_kwargs.copy()
300
+ if "num_beams" in gen_kwargs and gen_kwargs["num_beams"] is None:
301
+ gen_kwargs.pop("num_beams")
302
+ if "max_length" in gen_kwargs and gen_kwargs["max_length"] is None:
303
+ gen_kwargs.pop("max_length")
304
+
305
+ default_synced_gpus = is_deepspeed_zero3_enabled() or is_fsdp_managed_module(self.model)
306
+ gen_kwargs["synced_gpus"] = gen_kwargs.get("synced_gpus", default_synced_gpus)
307
+
308
+ generation_inputs = inputs.copy()
309
+ # If the `decoder_input_ids` was created from `labels`, evict the former, so that the model can freely generate
310
+ # (otherwise, it would continue generating from the padded `decoder_input_ids`)
311
+ if (
312
+ "labels" in generation_inputs
313
+ and "decoder_input_ids" in generation_inputs
314
+ and generation_inputs["labels"].shape == generation_inputs["decoder_input_ids"].shape
315
+ ):
316
+ generation_inputs = {
317
+ k: v for k, v in inputs.items() if k not in ("decoder_input_ids", "decoder_attention_mask")
318
+ }
319
+
320
+ summon_full_params_context = (
321
+ FullyShardedDataParallel.summon_full_params(self.model)
322
+ if isinstance(self.model, FullyShardedDataParallel)
323
+ else contextlib.nullcontext()
324
+ )
325
+
326
+ with summon_full_params_context:
327
+ generated_tokens = self.model.generate(**generation_inputs, **gen_kwargs)
328
+
329
+ # Temporary hack to ensure the generation config is not initialized for each iteration of the evaluation loop
330
+ # TODO: remove this hack when the legacy code that initializes generation_config from a model config is
331
+ # removed in https://github.com/huggingface/transformers/blob/98d88b23f54e5a23e741833f1e973fdf600cc2c5/src/transformers/generation/utils.py#L1183
332
+ if self.model.generation_config._from_model_config:
333
+ self.model.generation_config._from_model_config = False
334
+
335
+ # Retrieves GenerationConfig from model.generation_config
336
+ gen_config = self.model.generation_config
337
+ # in case the batch is shorter than max length, the output should be padded
338
+ if generated_tokens.shape[-1] < gen_config.max_length:
339
+ generated_tokens = self._pad_tensors_to_max_len(generated_tokens, gen_config.max_length)
340
+ elif gen_config.max_new_tokens is not None and generated_tokens.shape[-1] < gen_config.max_new_tokens + 1:
341
+ generated_tokens = self._pad_tensors_to_max_len(generated_tokens, gen_config.max_new_tokens + 1)
342
+
343
+ with torch.no_grad():
344
+ if has_labels:
345
+ with self.compute_loss_context_manager():
346
+ outputs = model(**inputs)
347
+ if self.label_smoother is not None:
348
+ loss = self.label_smoother(outputs, inputs["labels"]).detach().mean()
349
+ else:
350
+ loss = (outputs["loss"] if isinstance(outputs, dict) else outputs[0]).detach().mean()
351
+ else:
352
+ loss = None
353
+
354
+ if self.args.prediction_loss_only:
355
+ return loss, None, None
356
+
357
+ if has_labels:
358
+ labels = inputs["labels"]
359
+ if labels.shape[-1] < gen_config.max_length:
360
+ labels = self._pad_tensors_to_max_len(labels, gen_config.max_length)
361
+ elif gen_config.max_new_tokens is not None and labels.shape[-1] < gen_config.max_new_tokens + 1:
362
+ labels = self._pad_tensors_to_max_len(labels, gen_config.max_new_tokens + 1)
363
+ else:
364
+ labels = None
365
+
366
+ return loss, generated_tokens, labels
367
+
368
+ def _pad_tensors_to_max_len(self, tensor, max_length):
369
+ if self.processing_class is not None and hasattr(self.processing_class, "pad_token_id"):
370
+ # If PAD token is not defined at least EOS token has to be defined
371
+ pad_token_id = (
372
+ self.processing_class.pad_token_id
373
+ if self.processing_class.pad_token_id is not None
374
+ else self.processing_class.eos_token_id
375
+ )
376
+ else:
377
+ if self.model.config.pad_token_id is not None:
378
+ pad_token_id = self.model.config.pad_token_id
379
+ else:
380
+ raise ValueError("Pad_token_id must be set in the configuration of the model, in order to pad tensors")
381
+
382
+ padded_tensor = pad_token_id * torch.ones(
383
+ (tensor.shape[0], max_length), dtype=tensor.dtype, device=tensor.device
384
+ )
385
+ padded_tensor[:, : tensor.shape[-1]] = tensor
386
+ return padded_tensor