Feature Extraction
Transformers
Safetensors
PyTorch
Russian
accentik
russian
accentuation
word-stress
custom-code
custom_code
Instructions to use TeraSpace/accentik with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use TeraSpace/accentik with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="TeraSpace/accentik", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("TeraSpace/accentik", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Release Accentik experimental context v2
Browse filesFP32 safetensors, self-contained PyTorch/Transformers inference code, matched tokenizer, documented evaluation tradeoff and public-project attribution license.
- LICENSE +95 -0
- LICENSE-APACHE-2.0 +202 -0
- LICENSE-OPENRAIL +209 -0
- NOTICE +25 -0
- README.md +173 -0
- accentik_features.py +44 -0
- accentik_inference.py +117 -0
- accentik_text.py +79 -0
- config.json +134 -0
- configuration_accentik.py +20 -0
- evaluation.json +111 -0
- inference.py +33 -0
- model.safetensors +3 -0
- modeling_accentik.py +106 -0
- release_manifest.json +76 -0
- requirements.txt +4 -0
- tokenizer.json +0 -0
- tokenizer_config.json +17 -0
LICENSE
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Accentik License
|
| 2 |
+
Open RAIL-M with Public Project Attribution, version 1.0
|
| 3 |
+
|
| 4 |
+
Copyright 2026 TeraSpace, for the Accentik contributions.
|
| 5 |
+
|
| 6 |
+
1. Scope and permission
|
| 7 |
+
|
| 8 |
+
This license covers the Accentik model weights (the "Model") and the original
|
| 9 |
+
Accentik inference source code distributed in this repository (the "Code").
|
| 10 |
+
Independently licensed upstream material retains its own license as described
|
| 11 |
+
in section 4. "Derivatives of the Model" has the meaning given in the
|
| 12 |
+
accompanying BigScience Open RAIL-M License.
|
| 13 |
+
|
| 14 |
+
The BigScience Open RAIL-M License dated August 18, 2022, reproduced in full in
|
| 15 |
+
LICENSE-OPENRAIL, is incorporated into this license for the Model and its
|
| 16 |
+
derivatives. Its conditions, including use-based restrictions, redistribution
|
| 17 |
+
requirements and notice requirements, apply alongside the additional public
|
| 18 |
+
project attribution condition below. TeraSpace adopts those terms for its Model
|
| 19 |
+
contributions; this does not relicense independently licensed upstream material.
|
| 20 |
+
|
| 21 |
+
Subject to the applicable terms, permission is granted without any license fee
|
| 22 |
+
or royalty payable to TeraSpace to use, copy, modify, fine-tune, convert, distill,
|
| 23 |
+
host and redistribute the Model and its derivatives, including commercially.
|
| 24 |
+
Permission is also granted without any license fee or royalty to use, copy,
|
| 25 |
+
modify, merge, publish, distribute, sublicense and sell copies of the original
|
| 26 |
+
Code, subject to sections 2, 3 and 5 of this license. Donations are voluntary
|
| 27 |
+
and are not a condition of any permission granted here.
|
| 28 |
+
|
| 29 |
+
2. Additional public project attribution condition
|
| 30 |
+
|
| 31 |
+
If you incorporate Accentik, its original Code, or a modified, fine-tuned,
|
| 32 |
+
quantized, converted or distilled version of the Model into a public project,
|
| 33 |
+
you must clearly acknowledge Accentik by TeraSpace in the project's publicly
|
| 34 |
+
accessible description. Include a link to
|
| 35 |
+
https://huggingface.co/TeraSpace/accentik wherever hyperlinks are supported.
|
| 36 |
+
|
| 37 |
+
A public project includes a public source-code repository, publicly released
|
| 38 |
+
application, publicly offered product or service, public research project, or
|
| 39 |
+
publicly distributed derivative model. This condition applies to commercial
|
| 40 |
+
and noncommercial projects alike, whether the Model or Code runs locally,
|
| 41 |
+
is embedded in an application, or operates on a backend providing functionality.
|
| 42 |
+
|
| 43 |
+
An acceptable acknowledgement for the unmodified Model or Code is:
|
| 44 |
+
"Russian word stress powered by Accentik by TeraSpace."
|
| 45 |
+
|
| 46 |
+
An acceptable acknowledgement for a derivative is:
|
| 47 |
+
"Russian word stress based on Accentik by TeraSpace."
|
| 48 |
+
|
| 49 |
+
Place the acknowledgement in a reasonably visible and readable public README,
|
| 50 |
+
documentation, product page, app-store listing or comparable project description.
|
| 51 |
+
A credit present only in source-code comments or a bundled license file does
|
| 52 |
+
not by itself satisfy this additional condition. Equivalent wording is allowed
|
| 53 |
+
if it identifies Accentik and TeraSpace and includes the link where supported.
|
| 54 |
+
|
| 55 |
+
Private internal use without a public project does not require a public
|
| 56 |
+
announcement. This condition does not require disclosure of an application's
|
| 57 |
+
source code. Distributing individual annotated texts alone does not trigger
|
| 58 |
+
this additional attribution condition, and credit need not accompany every
|
| 59 |
+
generated annotation. Public products or services that provide annotations
|
| 60 |
+
using the Model or Code remain covered. Applicable Open RAIL-M output provisions
|
| 61 |
+
continue to apply to the Model.
|
| 62 |
+
|
| 63 |
+
3. Redistribution
|
| 64 |
+
|
| 65 |
+
Redistributors of the Model, Code or their derivatives must include this LICENSE,
|
| 66 |
+
LICENSE-OPENRAIL, LICENSE-APACHE-2.0 and NOTICE, preserve applicable copyright and
|
| 67 |
+
attribution notices, and preserve the public project attribution condition for
|
| 68 |
+
the Accentik contributions in terms supplied to downstream recipients.
|
| 69 |
+
Applicable Open RAIL-M redistribution terms apply to the Model and its
|
| 70 |
+
derivatives. Applicable Apache 2.0 terms apply to upstream RuModernBERT material.
|
| 71 |
+
|
| 72 |
+
4. Independently licensed components
|
| 73 |
+
|
| 74 |
+
The Model includes material derived from deepvk/RuModernBERT-small:
|
| 75 |
+
https://huggingface.co/deepvk/RuModernBERT-small
|
| 76 |
+
|
| 77 |
+
The upstream weights and tokenizer remain subject to the Apache License 2.0,
|
| 78 |
+
reproduced in LICENSE-APACHE-2.0. Nothing in this license removes permissions
|
| 79 |
+
granted directly under that upstream license or changes licenses of third-party
|
| 80 |
+
libraries and datasets. Only TeraSpace's contributions are offered under the
|
| 81 |
+
additional terms of this license. See NOTICE for provenance and acknowledgements.
|
| 82 |
+
|
| 83 |
+
5. No endorsement; warranty and liability
|
| 84 |
+
|
| 85 |
+
Attribution does not imply endorsement by TeraSpace or upstream contributors.
|
| 86 |
+
No trademark permission is granted beyond identification necessary for credit.
|
| 87 |
+
The warranty disclaimers and limitations of liability in LICENSE-OPENRAIL apply
|
| 88 |
+
to the Model and TeraSpace's Model contributions.
|
| 89 |
+
|
| 90 |
+
THE ORIGINAL CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 91 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
| 92 |
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
| 93 |
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
| 94 |
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 95 |
+
WITH THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
LICENSE-APACHE-2.0
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright [yyyy] [name of copyright owner]
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
LICENSE-OPENRAIL
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BigScience Open RAIL-M License
|
| 2 |
+
dated August 18, 2022
|
| 3 |
+
|
| 4 |
+
Section I: PREAMBLE
|
| 5 |
+
|
| 6 |
+
This Open RAIL-M License was created by BigScience, a collaborative open innovation project aimed at
|
| 7 |
+
the responsible development and use of large multilingual datasets and Large Language Models
|
| 8 |
+
(“LLMs”). While a similar license was originally designed for the BLOOM model, we decided to adapt it
|
| 9 |
+
and create this license in order to propose a general open and responsible license applicable to other
|
| 10 |
+
machine learning based AI models (e.g. multimodal generative models).
|
| 11 |
+
In short, this license strives for both the open and responsible downstream use of the accompanying
|
| 12 |
+
model. When it comes to the open character, we took inspiration from open source permissive licenses
|
| 13 |
+
regarding the grant of IP rights. Referring to the downstream responsible use, we added use-based
|
| 14 |
+
restrictions not permitting the use of the Model in very specific scenarios, in order for the licensor to be
|
| 15 |
+
able to enforce the license in case potential misuses of the Model may occur. Even though downstream
|
| 16 |
+
derivative versions of the model could be released under different licensing terms, the latter will always
|
| 17 |
+
have to include - at minimum - the same use-based restrictions as the ones in the original license (this
|
| 18 |
+
license).
|
| 19 |
+
The development and use of artificial intelligence (“AI”), does not come without concerns. The world has
|
| 20 |
+
witnessed how AI techniques may, in some instances, become risky for the public in general. These risks
|
| 21 |
+
come in many forms, from racial discrimination to the misuse of sensitive information.
|
| 22 |
+
BigScience believes in the intersection between open and responsible AI development; thus, this License
|
| 23 |
+
aims to strike a balance between both in order to enable responsible open-science in the field of AI.
|
| 24 |
+
This License governs the use of the model (and its derivatives) and is informed by the model card
|
| 25 |
+
associated with the model.
|
| 26 |
+
|
| 27 |
+
NOW THEREFORE, You and Licensor agree as follows:
|
| 28 |
+
|
| 29 |
+
1. Definitions
|
| 30 |
+
(a) "License" means the terms and conditions for use, reproduction, and Distribution as defined in
|
| 31 |
+
this document.
|
| 32 |
+
(b) “Data” means a collection of information and/or content extracted from the dataset used with the
|
| 33 |
+
Model, including to train, pretrain, or otherwise evaluate the Model. The Data is not licensed under
|
| 34 |
+
this License.
|
| 35 |
+
(c)“Output” means the results of operating a Model as embodied in informational content resulting
|
| 36 |
+
therefrom.
|
| 37 |
+
(d)“Model” means any accompanying machine-learning based assemblies (including checkpoints),
|
| 38 |
+
consisting of learnt weights, parameters (including optimizer states), corresponding to the model
|
| 39 |
+
architecture as embodied in the Complementary Material, that have been trained or tuned, in whole or
|
| 40 |
+
in part on the Data, using the Complementary Material.
|
| 41 |
+
(e) “Derivatives of the Model” means all modifications to the Model, works based on the Model, or any
|
| 42 |
+
other model which is created or initialized by transfer of patterns of the weights, parameters,
|
| 43 |
+
activations or output of the Model, to the other model, in order to cause the other model to perform
|
| 44 |
+
similarly to the Model, including - but not limited to - distillation methods entailing the use of
|
| 45 |
+
intermediate data representations or methods based on the generation of synthetic data by the Model
|
| 46 |
+
for training the other model.
|
| 47 |
+
(f)“Complementary Material” means the accompanying source code and scripts used to define,
|
| 48 |
+
run, load, benchmark or evaluate the Model, and used to prepare data for training or evaluation, if
|
| 49 |
+
any. This includes any accompanying documentation, tutorials, examples, etc, if any.
|
| 50 |
+
(g) “Distribution” means any transmission, reproduction, publication or other sharing of the Model or
|
| 51 |
+
Derivatives of the Model to a third party, including providing the Model as a hosted service made
|
| 52 |
+
available by electronic or other remote means - e.g. API-based or web access.
|
| 53 |
+
(h) “Licensor” means the copyright owner or entity authorized by the copyright owner that is
|
| 54 |
+
granting the License, including the persons or entities that may have rights in the Model and/or
|
| 55 |
+
distributing the Model.
|
| 56 |
+
(i) "You" (or "Your") means an individual or Legal Entity exercising permissions granted by this
|
| 57 |
+
License and/or making use of the Model for whichever purpose and in any field of use, including
|
| 58 |
+
usage of the Model in an end-use application - e.g. chatbot, translator, image generator.
|
| 59 |
+
(j) “Third Parties” means individuals or legal entities that are not under common control with
|
| 60 |
+
Licensor or You.
|
| 61 |
+
(k) "Contribution" means any work of authorship, including the original version of the Model and
|
| 62 |
+
any modifications or additions to that Model or Derivatives of the Model thereof, that is
|
| 63 |
+
intentionally submitted to Licensor for inclusion in the Model by the copyright owner or by an
|
| 64 |
+
individual or Legal Entity authorized to submit on behalf of the copyright owner. For the
|
| 65 |
+
purposes of this definition,
|
| 66 |
+
“submitted” means any form of electronic, verbal, or written
|
| 67 |
+
communication sent to the Licensor or its representatives, including but not limited to
|
| 68 |
+
communication on electronic mailing lists, source code control systems, and issue tracking
|
| 69 |
+
systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and
|
| 70 |
+
improving the Model, but excluding communication that is conspicuously marked or otherwise
|
| 71 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 72 |
+
(l) "Contributor" means Licensor and any individual or Legal Entity on behalf of whom a
|
| 73 |
+
Contribution has been received by Licensor and subsequently incorporated within the Model.
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
Section II: INTELLECTUAL PROPERTY RIGHTS
|
| 77 |
+
|
| 78 |
+
Both copyright and patent grants apply to the Model, Derivatives of the Model and Complementary
|
| 79 |
+
Material. The Model and Derivatives of the Model are subject to additional terms as described in Section III.
|
| 80 |
+
|
| 81 |
+
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor
|
| 82 |
+
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare, publicly display, publicly perform, sublicense, and distribute the
|
| 83 |
+
Complementary Material, the Model, and Derivatives of the Model.
|
| 84 |
+
|
| 85 |
+
3. Grant of Patent License. Subject to the terms and conditions of this License and where and as
|
| 86 |
+
applicable, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
| 87 |
+
royalty-free, irrevocable (except as stated in this paragraph) patent license to make, have made, use, offer
|
| 88 |
+
to sell, sell, import, and otherwise transfer the Model and the Complementary Material, where such
|
| 89 |
+
license applies only to those patent claims licensable by such Contributor that are necessarily infringed by
|
| 90 |
+
their Contribution(s) alone or by combination of their Contribution(s) with the Model to which such
|
| 91 |
+
Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim
|
| 92 |
+
or counterclaim in a lawsuit) alleging that the Model and/or Complementary Material or a Contribution
|
| 93 |
+
incorporated within the Model and/or Complementary Material constitutes direct or contributory patent
|
| 94 |
+
infringement, then any patent licenses granted to You under this License for the Model and/or Work shall
|
| 95 |
+
terminate as of the date such litigation is asserted or filed.
|
| 96 |
+
Section III: CONDITIONS OF USAGE, DISTRIBUTION AND REDISTRIBUTION
|
| 97 |
+
|
| 98 |
+
4. Distribution and Redistribution. You may host for Third Party remote access purposes (e.g.
|
| 99 |
+
software-as-a-service), reproduce and distribute copies of the Model or Derivatives of the Model thereof
|
| 100 |
+
in any medium, with or without modifications, provided that You meet the following conditions:
|
| 101 |
+
|
| 102 |
+
a. Use-based restrictions as referenced in paragraph 5 MUST be included as an enforceable provision
|
| 103 |
+
by You in any type of legal agreement (e.g. a license) governing the use and/or distribution of the
|
| 104 |
+
Model or Derivatives of the Model, and You shall give notice to subsequent users You Distribute to,
|
| 105 |
+
that the Model or Derivatives of the Model are subject to paragraph 5. This provision does not apply
|
| 106 |
+
to the use of Complementary Material.
|
| 107 |
+
|
| 108 |
+
b. You must give any Third Party recipients of the Model or Derivatives of the Model a copy of this
|
| 109 |
+
License;
|
| 110 |
+
|
| 111 |
+
c. You must cause any modified files to carry prominent notices stating that You changed the files;
|
| 112 |
+
|
| 113 |
+
d. You must retain all copyright, patent, trademark, and attribution notices excluding those notices
|
| 114 |
+
that do not pertain to any part of the Model, Derivatives of the Model.
|
| 115 |
+
You may add Your own copyright statement to Your modifications and may provide additional or
|
| 116 |
+
different license terms and conditions - respecting paragraph 4.a.
|
| 117 |
+
- for use, reproduction, or Distribution
|
| 118 |
+
of Your modifications, or for any such Derivatives of the Model as a whole, provided Your use,
|
| 119 |
+
reproduction, and Distribution of the Model otherwise complies with the conditions stated in this License.
|
| 120 |
+
|
| 121 |
+
5. Use-based restrictions. The restrictions set forth in Attachment A are considered Use-based restrictions.
|
| 122 |
+
Therefore You cannot use the Model and the Derivatives of the Model for the specified restricted uses. You
|
| 123 |
+
may use the Model subject to this License, including only for lawful purposes and in accordance with the
|
| 124 |
+
License. Use may include creating any content with, finetuning, updating, running, training, evaluating and/or
|
| 125 |
+
reparametrizing the Model. You shall require all of Your users who use the Model or a Derivative of the Model
|
| 126 |
+
to comply with the terms of this paragraph (paragraph 5).
|
| 127 |
+
|
| 128 |
+
6. The Output You Generate. Except as set forth herein, Licensor claims no rights in the Output You
|
| 129 |
+
generate using the Model. You are accountable for the Output you generate and its subsequent uses. No
|
| 130 |
+
use of the output can contravene any provision as stated in the License.
|
| 131 |
+
|
| 132 |
+
Section IV: OTHER PROVISIONS
|
| 133 |
+
|
| 134 |
+
7. Updates and Runtime Restrictions. To the maximum extent permitted by law, Licensor reserves the
|
| 135 |
+
right to restrict (remotely or otherwise) usage of the Model in violation of this License, update the Model
|
| 136 |
+
through electronic means, or modify the Output of the Model based on updates. You shall undertake
|
| 137 |
+
reasonable efforts to use the latest version of the Model.
|
| 138 |
+
|
| 139 |
+
8. Trademarks and related. Nothing in this License permits You to make use of Licensors’ trademarks,
|
| 140 |
+
trade names, logos or to otherwise suggest endorsement or misrepresent the relationship between the
|
| 141 |
+
parties; and any rights not expressly granted herein are reserved by the Licensors.
|
| 142 |
+
|
| 143 |
+
9. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides
|
| 144 |
+
the Model and the Complementary Material (and each Contributor provides its Contributions) on an "AS
|
| 145 |
+
IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
| 146 |
+
including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
|
| 147 |
+
MERCHANTABILITY , or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for
|
| 148 |
+
determining the appropriateness of using or redistributing the Model, Derivatives of the Model, and the
|
| 149 |
+
Complementary Material and assume any risks associated with Your exercise of permissions under this
|
| 150 |
+
License.
|
| 151 |
+
|
| 152 |
+
10. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence),
|
| 153 |
+
contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or
|
| 154 |
+
agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect,
|
| 155 |
+
special, incidental, or consequential damages of any character arising as a result of this License or out of
|
| 156 |
+
the use or inability to use the Model and the Complementary Material (including but not limited to
|
| 157 |
+
damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other
|
| 158 |
+
commercial damages or losses), even if such Contributor has been advised of the possibility of such
|
| 159 |
+
damages.
|
| 160 |
+
|
| 161 |
+
11. Accepting Warranty or Additional Liability. While redistributing the Model, Derivatives of the
|
| 162 |
+
Model and the Complementary Material thereof, You may choose to offer, and charge a fee for, acceptance
|
| 163 |
+
of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License.
|
| 164 |
+
However, in accepting such obligations, You may act only on Your own behalf and on Your sole
|
| 165 |
+
responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and
|
| 166 |
+
hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor
|
| 167 |
+
by reason of your accepting any such warranty or additional liability.
|
| 168 |
+
|
| 169 |
+
12. If any provision of this License is held to be invalid, illegal or unenforceable, the remaining
|
| 170 |
+
provisions shall be unaffected thereby and remain valid as if such provision had not been set forth herein.
|
| 171 |
+
|
| 172 |
+
END OF TERMS AND CONDITIONS
|
| 173 |
+
|
| 174 |
+
Attachment A
|
| 175 |
+
|
| 176 |
+
Use Restrictions
|
| 177 |
+
|
| 178 |
+
You agree not to use the Model or Derivatives of the Model:
|
| 179 |
+
(a) In any way that violates any applicable national, federal, state, local or international law
|
| 180 |
+
or regulation;
|
| 181 |
+
(b) For the purpose of exploiting, harming or attempting to exploit or harm minors in any
|
| 182 |
+
way;
|
| 183 |
+
(c) To generate or disseminate verifiably false information and/or content with the purpose of
|
| 184 |
+
harming others;
|
| 185 |
+
(d) To generate or disseminate personal identifiable information that can be used to harm an
|
| 186 |
+
individual;
|
| 187 |
+
(e) To generate or disseminate information and/or content (e.g. images, code, posts, articles),
|
| 188 |
+
and place the information and/or content in any context (e.g. bot generating tweets)
|
| 189 |
+
without expressly and intelligibly disclaiming that the information and/or content is
|
| 190 |
+
machine generated;
|
| 191 |
+
(f) To defame, disparage or otherwise harass others;
|
| 192 |
+
(g) To impersonate or attempt to impersonate (e.g. deepfakes) others without their consent;
|
| 193 |
+
(h) For fully automated decision making that adversely impacts an individual’s legal rights or
|
| 194 |
+
otherwise creates or modifies a binding, enforceable obligation;
|
| 195 |
+
(i) For any use intended to or which has the effect of discriminating against or harming
|
| 196 |
+
individuals or groups based on online or offline social behavior or known or predicted
|
| 197 |
+
personal or personality characteristics;
|
| 198 |
+
(j) To exploit any of the vulnerabilities of a specific group of persons based on their age,
|
| 199 |
+
social, physical or mental characteristics, in order to materially distort the behavior of a
|
| 200 |
+
person pertaining to that group in a manner that causes or is likely to cause that person or
|
| 201 |
+
another person physical or psychological harm;
|
| 202 |
+
(k) For any use intended to or which has the effect of discriminating against individuals or
|
| 203 |
+
groups based on legally protected characteristics or categories;
|
| 204 |
+
(l) To provide medical advice and medical results interpretation;
|
| 205 |
+
(m) To generate or disseminate information for the purpose to be used for administration of
|
| 206 |
+
justice, law enforcement, immigration or asylum processes, such as predicting an
|
| 207 |
+
individual will commit fraud/crime commitment (e.g. by text profiling, drawing causal
|
| 208 |
+
relationships between assertions made in documents, indiscriminate and
|
| 209 |
+
arbitrarily-targeted use).
|
NOTICE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Accentik — experimental context v2
|
| 2 |
+
Copyright 2026 TeraSpace, for Accentik contributions.
|
| 3 |
+
https://huggingface.co/TeraSpace/accentik
|
| 4 |
+
|
| 5 |
+
The encoder and bundled tokenizer derive from deepvk/RuModernBERT-small,
|
| 6 |
+
revision cdfe49388e1f5261c69e4b1c8c41fa9e60b9ebef (patched-tokenizer branch).
|
| 7 |
+
https://huggingface.co/deepvk/RuModernBERT-small
|
| 8 |
+
These upstream materials retain the Apache License 2.0; see LICENSE-APACHE-2.0.
|
| 9 |
+
RuModernBERT builds on ModernBERT: https://arxiv.org/abs/2412.13663
|
| 10 |
+
|
| 11 |
+
Accentik's word-stress and local-context heads, inference helpers, and model
|
| 12 |
+
refinement are TeraSpace contributions under LICENSE. This repository does not
|
| 13 |
+
claim ownership of independently licensed upstream material or dependencies.
|
| 14 |
+
|
| 15 |
+
Training acknowledgements (training datasets are not redistributed):
|
| 16 |
+
- iv-stoliar/RussianHomographDataset, source repository GPL-3.0.
|
| 17 |
+
https://github.com/iv-stoliar/RussianHomographDataset
|
| 18 |
+
- TeraTTS/stress_dataset_sft_proza, stress_dataset_sft_poetry, open_accent,
|
| 19 |
+
dataset metadata MIT.
|
| 20 |
+
- RUAccent (Den4ikAI), pseudo-label teacher and evaluation comparison.
|
| 21 |
+
No RUAccent dictionary, morphological assets or code are required at inference.
|
| 22 |
+
- MashaPo/russtress, external evaluation reference.
|
| 23 |
+
|
| 24 |
+
See README.md and evaluation.json for methodology, source revisions and limits.
|
| 25 |
+
Third-party names identify sources and do not imply endorsement.
|
README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: accentik-openrail-m-public-attribution
|
| 4 |
+
license_link: https://huggingface.co/TeraSpace/accentik/blob/main/LICENSE
|
| 5 |
+
library_name: transformers
|
| 6 |
+
language:
|
| 7 |
+
- ru
|
| 8 |
+
base_model: deepvk/RuModernBERT-small
|
| 9 |
+
tags:
|
| 10 |
+
- russian
|
| 11 |
+
- accentuation
|
| 12 |
+
- word-stress
|
| 13 |
+
- custom-code
|
| 14 |
+
- pytorch
|
| 15 |
+
- safetensors
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
## 💜 Support Accentik
|
| 19 |
+
|
| 20 |
+
If Accentik is useful to you, consider supporting its development. Thank you for your support!
|
| 21 |
+
|
| 22 |
+
| Currency | Donation address |
|
| 23 |
+
| :--- | :--- |
|
| 24 |
+
| **ETH** | `0x19766c207F82303c3998976d852DB82e8Dcc5d77` |
|
| 25 |
+
| **GRAM (TON)** | `UQDYx1blVO8H31APnRUXVg2uTXV--wXX8HdTyKxnOKQciPQj` |
|
| 26 |
+
| **SOL** | `DvBjAqaj4AYWi3JBMcW4FmXsaU4Nu6yjxrox4XJZ6o6Z` |
|
| 27 |
+
| **Tether USDt (TRON / TRC20)** | `TZ6QeYZSr2h22rzGqQZQZTMzWYVPdUej1y` |
|
| 28 |
+
| **BTC** | `bc1q2l0xdlylqpweu4sm3y53f95g0nazcm8yu42gkq` |
|
| 29 |
+
|
| 30 |
+
---
|
| 31 |
+
|
| 32 |
+
# Accentik — experimental context v2
|
| 33 |
+
|
| 34 |
+
Accentik adds Russian word-stress marks to text. It inserts `+` before the stressed vowel in Russian words with more than one vowel, using the surrounding text to resolve ambiguous words.
|
| 35 |
+
|
| 36 |
+
```text
|
| 37 |
+
Input: на двери в замок висел замок.
|
| 38 |
+
Output: на двер+и в з+амок вис+ел зам+ок.
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
This is the **experimental context v2** checkpoint. Contextual homograph accuracy improved substantially over the initial Accentik model, while general RusStress accuracy decreased slightly. See the measurements below before choosing it for your project.
|
| 42 |
+
|
| 43 |
+
The model has **34.85 million parameters**, a single encoder pass, and parallel vowel classification. It uses [deepvk/RuModernBERT-small](https://huggingface.co/deepvk/RuModernBERT-small) with a learned word-stress head and local-context residual head. Inference uses PyTorch and Transformers, without a dictionary, morphological analyzer, RUAccent installation, or autoregressive decoding.
|
| 44 |
+
|
| 45 |
+
## Installation
|
| 46 |
+
|
| 47 |
+
```bash
|
| 48 |
+
pip install "torch>=2.6" "transformers>=5.15.1,<6" "safetensors>=0.4.3" "numpy>=1.24"
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
Tested with Python 3.10, PyTorch 2.9.0 and Transformers 5.15.1. CPU and CUDA are supported. The encoder uses PyTorch SDPA; installing `flash-attn` is unnecessary.
|
| 52 |
+
|
| 53 |
+
## Load with Transformers
|
| 54 |
+
|
| 55 |
+
The repository includes the inference code, matched tokenizer, config and one FP32 `model.safetensors` file, approximately 140 MB. The first call loads the bundled tokenizer from the same repository revision as the weights.
|
| 56 |
+
|
| 57 |
+
```python
|
| 58 |
+
import torch
|
| 59 |
+
from transformers import AutoModel
|
| 60 |
+
|
| 61 |
+
torch.set_num_threads(2) # Optional: avoids excessive CPU thread overhead.
|
| 62 |
+
|
| 63 |
+
model = AutoModel.from_pretrained(
|
| 64 |
+
"TeraSpace/accentik",
|
| 65 |
+
trust_remote_code=True,
|
| 66 |
+
).eval()
|
| 67 |
+
|
| 68 |
+
text = "на двери в замок висел замок."
|
| 69 |
+
print(model.accentuate(text))
|
| 70 |
+
# на двер+и в з+амок вис+ел зам+ок.
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
For CUDA, move the model before inference:
|
| 74 |
+
|
| 75 |
+
```python
|
| 76 |
+
model = model.to("cuda")
|
| 77 |
+
print(model.accentuate("Он уже закончил работу."))
|
| 78 |
+
# Он +уже зак+ончил раб+оту.
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
The text API uses BF16 autocast on CUDA and FP32 on CPU. Keep the model weights in FP32 when using these examples. For a reproducible deployment, pass an explicit Hub commit hash as `revision=` when loading the model. Its automatically loaded tokenizer follows that revision.
|
| 82 |
+
|
| 83 |
+
## Batch inference and manual stress
|
| 84 |
+
|
| 85 |
+
```python
|
| 86 |
+
texts = [
|
| 87 |
+
"Для платья купили атлас.",
|
| 88 |
+
"В старом з+амке тихо.\nМолоко́ на столе. English. 2+2=4.",
|
| 89 |
+
]
|
| 90 |
+
for result in model.accentuate_batch(texts):
|
| 91 |
+
print(result)
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
Existing manual `+` marks before Russian vowels and combining acute marks after vowels override model decisions. The original markers remain in the output. Capitalization, punctuation, spaces, line breaks, mathematical plus signs, English text and the original `е`/`ё` spelling are preserved. New stress marks are added only to Russian words with at least two vowels.
|
| 95 |
+
|
| 96 |
+
For decisions and confidence scores:
|
| 97 |
+
|
| 98 |
+
```python
|
| 99 |
+
result = model.annotate("Он уже закончил работу.")
|
| 100 |
+
print(result["text"])
|
| 101 |
+
for word in result["words"]:
|
| 102 |
+
print(word["word"], word["position"], word["confidence"], word["supplied"])
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
`start`, `end` and `position` are character offsets in the input after removing stress markers; `end` is exclusive. Confidence is an uncalibrated softmax score, not an estimated correctness probability. Manually supplied stress has `confidence=None` and `supplied=True`.
|
| 106 |
+
|
| 107 |
+
You can supply the tokenizer explicitly with `tokenizer=AutoTokenizer.from_pretrained("TeraSpace/accentik", trust_remote_code=True)` to any text method. Use the same revision as the model.
|
| 108 |
+
|
| 109 |
+
## Long texts and offline use
|
| 110 |
+
|
| 111 |
+
Text is processed in whole-word windows of at most **512 tokens**. Longer inputs split at whitespace, retain all source characters and use token-budget batching. Context across window boundaries is limited. A single unbroken token sequence that cannot fit the window raises an error instead of silently truncating it.
|
| 112 |
+
|
| 113 |
+
Download a complete snapshot once, then load it locally:
|
| 114 |
+
|
| 115 |
+
```python
|
| 116 |
+
from huggingface_hub import snapshot_download
|
| 117 |
+
from transformers import AutoModel
|
| 118 |
+
|
| 119 |
+
folder = snapshot_download("TeraSpace/accentik")
|
| 120 |
+
model = AutoModel.from_pretrained(
|
| 121 |
+
folder, trust_remote_code=True, local_files_only=True,
|
| 122 |
+
).eval()
|
| 123 |
+
print(model.accentuate("Для платья купили атлас."))
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
The repository also contains a command-line script:
|
| 127 |
+
|
| 128 |
+
```bash
|
| 129 |
+
python inference.py --text "на двери в замок висел замок."
|
| 130 |
+
python inference.py --input input.txt --output accented.txt --device cuda
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
## Evaluation
|
| 134 |
+
|
| 135 |
+
Word-stress target accuracy, measured using the same evaluation procedures for both Accentik checkpoints:
|
| 136 |
+
|
| 137 |
+
| Evaluation | Targets | Initial Accentik | Experimental context v2 |
|
| 138 |
+
| :--- | ---: | ---: | ---: |
|
| 139 |
+
| Held-out manually annotated Russian homograph contexts | 7,673 | 85.13% | **97.51%** |
|
| 140 |
+
| General RusStress multi-vowel targets | 11,089 | **94.75%** | 94.10% |
|
| 141 |
+
| Supplied dialogue-label agreement | 50,564 | **99.02%** | 98.72% |
|
| 142 |
+
|
| 143 |
+
On the same general RusStress targets, the native RUAccent comparison achieved **95.15%**. This release does not claim better overall accuracy than RUAccent. The dialogue result measures agreement with supplied labels rather than an independent human annotation benchmark.
|
| 144 |
+
|
| 145 |
+
The new checkpoint resolves 9/10 words in a small set of reported contextual diagnostics, compared with 4/10 for the initial model. Those examples were repeatedly inspected during development; they are not a representative independent benchmark. One remaining failure is `На двери замка висел замок.`, where the castle form can still receive the wrong stress.
|
| 146 |
+
|
| 147 |
+
Checkpoint selection used validation data. Fixed evaluations were subsequently reused during development. Exact external benchmark contexts were excluded from refinement data, but overlap with the original teacher-labelled pretraining corpus is unknown. The general accuracy regression failed the internal promotion gate; this checkpoint is published explicitly as an experimental alternative. Machine-readable counts are in [evaluation.json](evaluation.json).
|
| 148 |
+
|
| 149 |
+
## Training sources
|
| 150 |
+
|
| 151 |
+
The initial model learned from existing RUAccent-labelled Russian speech transcripts. Refinement added manually annotated homograph contexts, the supplied datasets below, and a small amount of authored contextual training material. Unmarked words were treated as unknown labels; absent stress was not trained as a negative. Known corrupt labels and ambiguous teacher replay targets were filtered or masked.
|
| 152 |
+
|
| 153 |
+
- [iv-stoliar/RussianHomographDataset](https://github.com/iv-stoliar/RussianHomographDataset): manually annotated homograph contexts; the source repository provides GPL-3.0.
|
| 154 |
+
- [TeraTTS/stress_dataset_sft_proza](https://huggingface.co/datasets/TeraTTS/stress_dataset_sft_proza), [TeraTTS/stress_dataset_sft_poetry](https://huggingface.co/datasets/TeraTTS/stress_dataset_sft_poetry) and [TeraTTS/open_accent](https://huggingface.co/datasets/TeraTTS/open_accent): dataset metadata specifies MIT. Positive-labelled examples were used; negative-labelled examples were excluded.
|
| 155 |
+
- [RUAccent](https://github.com/Den4ikAI/ruaccent): original pseudo-label teacher and evaluation comparison; not an inference dependency.
|
| 156 |
+
|
| 157 |
+
Training datasets are not redistributed in this repository. Dataset metadata and source revisions are recorded in `evaluation.json`.
|
| 158 |
+
|
| 159 |
+
## Limitations
|
| 160 |
+
|
| 161 |
+
Russian lexical stress can depend on meaning that the available context does not resolve. Names, rare forms and ambiguous words can still be wrong, including at high confidence. Manual stress remains useful for known exceptions. The model does not restore `ё`, normalize spelling, predict pauses, label emphasis or generate speech.
|
| 162 |
+
|
| 163 |
+
## License and attribution
|
| 164 |
+
|
| 165 |
+
Accentik is available without a license fee or royalty for personal and commercial use, subject to [LICENSE](LICENSE) and [LICENSE-OPENRAIL](LICENSE-OPENRAIL). Donations are optional.
|
| 166 |
+
|
| 167 |
+
**Public projects using Accentik must give visible credit**, whether commercial or noncommercial. Put the credit in the project's public README, documentation, product page or comparable public description, with a link where supported:
|
| 168 |
+
|
| 169 |
+
> Russian word stress powered by [Accentik by TeraSpace](https://huggingface.co/TeraSpace/accentik).
|
| 170 |
+
|
| 171 |
+
For a derivative model, use “based on Accentik by TeraSpace.” Private internal use does not require a public announcement. You do not need to credit each individual annotated text. Redistributing the model or code requires retaining the license and notices. These terms do not require publishing your application's source code.
|
| 172 |
+
|
| 173 |
+
The upstream RuModernBERT material retains its Apache 2.0 license; see [NOTICE](NOTICE) and [LICENSE-APACHE-2.0](LICENSE-APACHE-2.0). The repository uses a custom attribution license and is not licensed as MIT or Apache 2.0 as a whole.
|
accentik_features.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Construct the exact parallel vowel-ranking features used in training."""
|
| 2 |
+
import numpy as np
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
WORD = np.dtype([('first', '<u2'), ('last', '<u2'), ('offset', '<u8'), ('n', '<u2'),
|
| 6 |
+
('label', '<i2'), ('start', '<u4'), ('end', '<u4')])
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
CANDIDATE = np.dtype([('first', '<u2'), ('last', '<u2'), ('position', '<u4'),
|
| 10 |
+
('letter', 'u1'), ('relative_start', '<f4'), ('relative_end', '<f4')])
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def collate(examples, pad=50283):
|
| 14 |
+
"""examples are (tokens, structured words, structured candidates)."""
|
| 15 |
+
width = max(len(t) for t, w, c in examples)
|
| 16 |
+
width = (width+7)//8*8
|
| 17 |
+
nw = sum(len(w) for t, w, c in examples)
|
| 18 |
+
nv = max([int(w['n'].max()) for t, w, c in examples if len(w)] or [2])
|
| 19 |
+
tokens = np.full((len(examples), width), pad, dtype=np.int64)
|
| 20 |
+
attention = np.zeros_like(tokens)
|
| 21 |
+
wf = np.zeros(nw, dtype=np.int64); wl = np.zeros_like(wf)
|
| 22 |
+
cf = np.zeros((nw, nv), dtype=np.int64); cl = np.zeros_like(cf)
|
| 23 |
+
letters = np.zeros_like(cf); rank = np.zeros_like(cf); count = np.zeros_like(cf)
|
| 24 |
+
scalars = np.zeros((nw, nv, 4), dtype=np.float32)
|
| 25 |
+
valid = np.zeros((nw, nv), dtype=np.bool_)
|
| 26 |
+
target = np.full(nw, -100, dtype=np.int64)
|
| 27 |
+
row = 0
|
| 28 |
+
for bi, (t, words, candidates) in enumerate(examples):
|
| 29 |
+
tokens[bi, :len(t)] = t; attention[bi, :len(t)] = 1
|
| 30 |
+
for w in words:
|
| 31 |
+
n, off = int(w['n']), int(w['offset'])
|
| 32 |
+
c = candidates[off:off+n]
|
| 33 |
+
wf[row], wl[row] = bi*width+int(w['first']), bi*width+int(w['last'])
|
| 34 |
+
cf[row, :n], cl[row, :n] = bi*width+c['first'], bi*width+c['last']
|
| 35 |
+
letters[row, :n] = c['letter']; rank[row, :n] = np.minimum(np.arange(n), 63)
|
| 36 |
+
count[row, :n] = min(n, 63)
|
| 37 |
+
scalars[row, :n, 0], scalars[row, :n, 1] = c['relative_start'], c['relative_end']
|
| 38 |
+
scalars[row, :n, 2] = np.arange(n)/max(n-1, 1)
|
| 39 |
+
scalars[row, :n, 3] = 1/max(int(w['end'])-int(w['start']), 1)
|
| 40 |
+
valid[row, :n] = True; target[row] = int(w['label']); row += 1
|
| 41 |
+
x = {k: torch.from_numpy(v) for k, v in dict(tokens=tokens, attention=attention,
|
| 42 |
+
word_first=wf, word_last=wl, candidate_first=cf, candidate_last=cl,
|
| 43 |
+
letters=letters, rank=rank, count=count, scalars=scalars, valid=valid).items()}
|
| 44 |
+
return x, torch.from_numpy(target)
|
accentik_inference.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""High-level source-preserving text API for Accentik."""
|
| 2 |
+
import numpy as np
|
| 3 |
+
import torch
|
| 4 |
+
from transformers import AutoTokenizer
|
| 5 |
+
from .accentik_text import WORD as RUSSIAN_WORD, VOWELS, parse, encode, context_parts
|
| 6 |
+
from .accentik_features import WORD, CANDIDATE, collate
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class AccentikInferenceMixin:
|
| 10 |
+
def _get_tokenizer(self, tokenizer=None):
|
| 11 |
+
if tokenizer is not None:
|
| 12 |
+
if not tokenizer.is_fast:
|
| 13 |
+
raise ValueError("Accentik requires its bundled fast tokenizer")
|
| 14 |
+
return tokenizer
|
| 15 |
+
if getattr(self, "_accentik_tokenizer", None) is None:
|
| 16 |
+
source = getattr(self, "_accentik_source", None) or self.config._name_or_path
|
| 17 |
+
if not source:
|
| 18 |
+
raise ValueError("Supply tokenizer= when constructing the model directly")
|
| 19 |
+
self._accentik_tokenizer = AutoTokenizer.from_pretrained(
|
| 20 |
+
source, config=self.config, **getattr(self, "_accentik_tokenizer_options", {}))
|
| 21 |
+
return self._accentik_tokenizer
|
| 22 |
+
|
| 23 |
+
@torch.inference_mode()
|
| 24 |
+
def annotate_many(self, texts, tokenizer=None):
|
| 25 |
+
if isinstance(texts, str):
|
| 26 |
+
raise TypeError('Pass a list of strings or use annotate(text)')
|
| 27 |
+
texts = list(texts)
|
| 28 |
+
if any(not isinstance(t, str) for t in texts):
|
| 29 |
+
raise TypeError('Every input must be a string')
|
| 30 |
+
if not texts:
|
| 31 |
+
return []
|
| 32 |
+
tokenizer = self._get_tokenizer(tokenizer)
|
| 33 |
+
parsed = [parse(t) for t in texts]
|
| 34 |
+
selections = [[] for _ in texts]
|
| 35 |
+
pending = []
|
| 36 |
+
for ri, (plain, supplied) in enumerate(parsed):
|
| 37 |
+
if not any(sum(c.lower() in VOWELS for c in w.group()) > 1
|
| 38 |
+
for w in RUSSIAN_WORD.finditer(plain)):
|
| 39 |
+
continue
|
| 40 |
+
for a, b in context_parts(plain, tokenizer, self.config.context_window):
|
| 41 |
+
t, w, c = encode(plain[a:b], {}, tokenizer)
|
| 42 |
+
if not w:
|
| 43 |
+
continue
|
| 44 |
+
pending.append((ri, a, (t, np.asarray(w, dtype=WORD), np.asarray(c, dtype=CANDIDATE))))
|
| 45 |
+
position = 0
|
| 46 |
+
while position < len(pending):
|
| 47 |
+
end, width = position, 0
|
| 48 |
+
while end < len(pending):
|
| 49 |
+
n = len(pending[end][2][0]); proposed = max(width, (n+7)//8*8)
|
| 50 |
+
if end > position and (proposed*(end-position+1) > self.config.batch_token_budget or end-position >= 128):
|
| 51 |
+
break
|
| 52 |
+
width = proposed; end += 1
|
| 53 |
+
chunk = pending[position:end]
|
| 54 |
+
x, _ = collate([r[2] for r in chunk], tokenizer.pad_token_id)
|
| 55 |
+
x = {k: v.to(self.device) for k, v in x.items()}
|
| 56 |
+
if self.device.type == 'cuda':
|
| 57 |
+
with torch.autocast('cuda', dtype=torch.bfloat16):
|
| 58 |
+
logits = self(**x).logits
|
| 59 |
+
else:
|
| 60 |
+
logits = self(**x).logits
|
| 61 |
+
probs = logits.softmax(-1); choice = probs.argmax(-1).cpu().numpy()
|
| 62 |
+
confidence = probs.max(-1).values.cpu().numpy()
|
| 63 |
+
wi = 0
|
| 64 |
+
for ri, a, (t, words, candidates) in chunk:
|
| 65 |
+
for w in words:
|
| 66 |
+
off, n = int(w['offset']), int(w['n'])
|
| 67 |
+
pos = a+int(candidates[off+int(choice[wi])]['position'])
|
| 68 |
+
selections[ri].append(dict(start=a+int(w['start']), end=a+int(w['end']),
|
| 69 |
+
position=pos, vowel_ordinal=int(choice[wi]), confidence=float(confidence[wi])))
|
| 70 |
+
wi += 1
|
| 71 |
+
position = end
|
| 72 |
+
results = []
|
| 73 |
+
for raw, (plain, supplied), words in zip(texts, parsed, selections):
|
| 74 |
+
source_map = []
|
| 75 |
+
for i, c in enumerate(raw):
|
| 76 |
+
if c == '+' and i+1 < len(raw) and raw[i+1].lower() in VOWELS:
|
| 77 |
+
continue
|
| 78 |
+
if c == '\u0301' and source_map and raw[source_map[-1]].lower() in VOWELS:
|
| 79 |
+
continue
|
| 80 |
+
source_map.append(i)
|
| 81 |
+
assert ''.join(raw[i] for i in source_map) == plain
|
| 82 |
+
new = set()
|
| 83 |
+
for w in words:
|
| 84 |
+
manual = sorted(p for p in supplied if w['start'] <= p < w['end'])
|
| 85 |
+
w['word'] = plain[w['start']:w['end']]
|
| 86 |
+
w['supplied'] = bool(manual)
|
| 87 |
+
if manual:
|
| 88 |
+
w['position'] = manual[0]; w['confidence'] = None
|
| 89 |
+
w['vowel_ordinal'] = sum(
|
| 90 |
+
c.lower() in VOWELS for c in plain[w['start']:manual[0]])
|
| 91 |
+
else:
|
| 92 |
+
new.add(source_map[w['position']])
|
| 93 |
+
output = ''.join(('+' if i in new else '')+c for i, c in enumerate(raw))
|
| 94 |
+
# Undo only newly inserted characters, preserving supplied acute/+,
|
| 95 |
+
# math signs, е/ё, case, whitespace and every source character.
|
| 96 |
+
recovered = list(output)
|
| 97 |
+
for extra, p in reversed(list(enumerate(sorted(new)))):
|
| 98 |
+
del recovered[p+extra]
|
| 99 |
+
assert ''.join(recovered) == raw
|
| 100 |
+
results.append(dict(input=raw, text=output, words=words))
|
| 101 |
+
return results
|
| 102 |
+
|
| 103 |
+
def annotate(self, text, tokenizer=None):
|
| 104 |
+
"""Return annotated text and vowel decisions; offsets refer to unmarked input.
|
| 105 |
+
|
| 106 |
+
Existing +/combining-acute stress overrides the model. Confidence is an
|
| 107 |
+
uncalibrated softmax score, or None for a supplied manual stress mark.
|
| 108 |
+
"""
|
| 109 |
+
return self.annotate_many([text], tokenizer=tokenizer)[0]
|
| 110 |
+
|
| 111 |
+
def accentuate(self, text, tokenizer=None):
|
| 112 |
+
"""Insert + before stressed vowels, retaining every source character."""
|
| 113 |
+
return self.annotate(text, tokenizer=tokenizer)["text"]
|
| 114 |
+
|
| 115 |
+
def accentuate_batch(self, texts, tokenizer=None):
|
| 116 |
+
"""Annotate a list of texts using token-budget batching."""
|
| 117 |
+
return [r["text"] for r in self.annotate_many(texts, tokenizer=tokenizer)]
|
accentik_text.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Source-preserving stress parsing and whole-word context windows."""
|
| 2 |
+
import re
|
| 3 |
+
|
| 4 |
+
VOWELS = 'аеёиоуыэюя'
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
WORD = re.compile('[А-Яа-яЁё]+')
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def parse(text):
|
| 11 |
+
plain, marks = [], set()
|
| 12 |
+
for i, c in enumerate(text):
|
| 13 |
+
if c == '+' and i+1 < len(text) and text[i+1].lower() in VOWELS:
|
| 14 |
+
marks.add(len(plain))
|
| 15 |
+
elif c == '\u0301' and plain and plain[-1].lower() in VOWELS:
|
| 16 |
+
marks.add(len(plain)-1)
|
| 17 |
+
else:
|
| 18 |
+
plain.append(c)
|
| 19 |
+
return ''.join(plain), marks
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def encode(text, target, tokenizer, encoded=None):
|
| 23 |
+
"""Keep the complete original string and map each vowel to all BPE pieces."""
|
| 24 |
+
if encoded is None:
|
| 25 |
+
encoded = tokenizer(text, add_special_tokens=True, return_offsets_mapping=True,
|
| 26 |
+
return_attention_mask=False, truncation=False)
|
| 27 |
+
offsets = encoded['offset_mapping']
|
| 28 |
+
# Fast tokenizer byte pieces can share a character span: use both ends.
|
| 29 |
+
covering = {}
|
| 30 |
+
for token, (a, b) in enumerate(offsets):
|
| 31 |
+
for p in range(a, b):
|
| 32 |
+
if p in covering:
|
| 33 |
+
covering[p][1] = token
|
| 34 |
+
else:
|
| 35 |
+
covering[p] = [token, token]
|
| 36 |
+
words, candidates = [], []
|
| 37 |
+
for wi, w in enumerate(WORD.finditer(text)):
|
| 38 |
+
vowels = [p for p in range(w.start(), w.end()) if text[p].lower() in VOWELS]
|
| 39 |
+
if len(vowels) <= 1:
|
| 40 |
+
continue
|
| 41 |
+
if any(p not in covering for p in range(w.start(), w.end())):
|
| 42 |
+
raise ValueError('Tokenizer omitted characters inside a Russian word')
|
| 43 |
+
first, last = covering[w.start()][0], covering[w.end()-1][1]
|
| 44 |
+
off = len(candidates)
|
| 45 |
+
for vi, pos in enumerate(vowels):
|
| 46 |
+
a, b = covering[pos]
|
| 47 |
+
candidates.append((a, b, pos, VOWELS.index(text[pos].lower()),
|
| 48 |
+
(pos-w.start())/len(w.group()), (w.end()-pos-1)/len(w.group())))
|
| 49 |
+
label = int(target.get(wi, -100))
|
| 50 |
+
if label != -100 and not 0 <= label < len(vowels):
|
| 51 |
+
raise ValueError('Label outside candidate vowels')
|
| 52 |
+
words.append((first, last, off, len(vowels), label, w.start(), w.end()))
|
| 53 |
+
return encoded['input_ids'], words, candidates
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def context_parts(text, tokenizer, limit=512):
|
| 57 |
+
"""Split only on whitespace, never truncate or cut a Russian word."""
|
| 58 |
+
if len(tokenizer.encode(text, add_special_tokens=True, verbose=False)) <= limit:
|
| 59 |
+
return [(0, len(text))]
|
| 60 |
+
spans = [(m.start(), m.end()) for m in re.finditer(r'\S+', text)]
|
| 61 |
+
parts = []
|
| 62 |
+
start_word = 0
|
| 63 |
+
while start_word < len(spans):
|
| 64 |
+
lo, hi = start_word+1, len(spans)
|
| 65 |
+
best = None
|
| 66 |
+
while lo <= hi:
|
| 67 |
+
mid = (lo+hi)//2
|
| 68 |
+
a = 0 if start_word == 0 else spans[start_word][0]
|
| 69 |
+
b = len(text) if mid == len(spans) else spans[mid][0]
|
| 70 |
+
if len(tokenizer.encode(text[a:b], add_special_tokens=True, verbose=False)) <= limit:
|
| 71 |
+
best = (a, b, mid); lo = mid+1
|
| 72 |
+
else:
|
| 73 |
+
hi = mid-1
|
| 74 |
+
if best is None:
|
| 75 |
+
raise ValueError('One unbroken word exceeds the encoder context')
|
| 76 |
+
a, b, start_word = best
|
| 77 |
+
parts.append((a, b))
|
| 78 |
+
assert ''.join(text[a:b] for a, b in parts) == text
|
| 79 |
+
return parts
|
config.json
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"AccentikModel"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "configuration_accentik.AccentikConfig",
|
| 7 |
+
"AutoModel": "modeling_accentik.AccentikModel"
|
| 8 |
+
},
|
| 9 |
+
"batch_token_budget": 8192,
|
| 10 |
+
"context_window": 512,
|
| 11 |
+
"dtype": "float32",
|
| 12 |
+
"encoder_config": {
|
| 13 |
+
"accentor_local_head": true,
|
| 14 |
+
"activation_function": "gelu",
|
| 15 |
+
"allow_embedding_resizing": true,
|
| 16 |
+
"architectures": [
|
| 17 |
+
"ModernBertForMaskedLM"
|
| 18 |
+
],
|
| 19 |
+
"attention_bias": false,
|
| 20 |
+
"attention_dropout": 0.0,
|
| 21 |
+
"attention_layer": "rope",
|
| 22 |
+
"attention_probs_dropout_prob": 0.0,
|
| 23 |
+
"attn_out_bias": false,
|
| 24 |
+
"attn_out_dropout_prob": 0.1,
|
| 25 |
+
"attn_qkv_bias": false,
|
| 26 |
+
"bert_layer": "prenorm",
|
| 27 |
+
"bos_token_id": 50281,
|
| 28 |
+
"chunk_size_feed_forward": 0,
|
| 29 |
+
"classifier_activation": "gelu",
|
| 30 |
+
"classifier_bias": false,
|
| 31 |
+
"classifier_dropout": 0.0,
|
| 32 |
+
"classifier_pooling": "cls",
|
| 33 |
+
"cls_token_id": 50281,
|
| 34 |
+
"compile_model": true,
|
| 35 |
+
"decoder_bias": true,
|
| 36 |
+
"deterministic_flash_attn": false,
|
| 37 |
+
"dtype": "float32",
|
| 38 |
+
"embed_dropout_prob": 0.0,
|
| 39 |
+
"embed_norm": true,
|
| 40 |
+
"embedding_dropout": 0.0,
|
| 41 |
+
"embedding_layer": "sans_pos",
|
| 42 |
+
"eos_token_id": 50282,
|
| 43 |
+
"final_norm": true,
|
| 44 |
+
"global_attn_every_n_layers": 3,
|
| 45 |
+
"head_pred_act": "gelu",
|
| 46 |
+
"hidden_act": "gelu",
|
| 47 |
+
"hidden_activation": "gelu",
|
| 48 |
+
"hidden_size": 384,
|
| 49 |
+
"id2label": {
|
| 50 |
+
"0": "LABEL_0",
|
| 51 |
+
"1": "LABEL_1"
|
| 52 |
+
},
|
| 53 |
+
"init_method": "full_megatron",
|
| 54 |
+
"initializer_cutoff_factor": 2.0,
|
| 55 |
+
"initializer_range": 0.02,
|
| 56 |
+
"intermediate_size": 576,
|
| 57 |
+
"is_encoder_decoder": false,
|
| 58 |
+
"label2id": {
|
| 59 |
+
"LABEL_0": 0,
|
| 60 |
+
"LABEL_1": 1
|
| 61 |
+
},
|
| 62 |
+
"layer_types": [
|
| 63 |
+
"full_attention",
|
| 64 |
+
"sliding_attention",
|
| 65 |
+
"sliding_attention",
|
| 66 |
+
"full_attention",
|
| 67 |
+
"sliding_attention",
|
| 68 |
+
"sliding_attention",
|
| 69 |
+
"full_attention",
|
| 70 |
+
"sliding_attention",
|
| 71 |
+
"sliding_attention",
|
| 72 |
+
"full_attention",
|
| 73 |
+
"sliding_attention",
|
| 74 |
+
"sliding_attention"
|
| 75 |
+
],
|
| 76 |
+
"local_attention": 256,
|
| 77 |
+
"local_attn_rotary_emb_base": 10000.0,
|
| 78 |
+
"loss_function": "fa_cross_entropy",
|
| 79 |
+
"loss_kwargs": {
|
| 80 |
+
"reduction": "mean"
|
| 81 |
+
},
|
| 82 |
+
"masked_prediction": true,
|
| 83 |
+
"max_position_embeddings": 8192,
|
| 84 |
+
"mlp_bias": false,
|
| 85 |
+
"mlp_dropout": 0.0,
|
| 86 |
+
"mlp_dropout_prob": 0.0,
|
| 87 |
+
"mlp_in_bias": false,
|
| 88 |
+
"mlp_layer": "glu",
|
| 89 |
+
"mlp_out_bias": false,
|
| 90 |
+
"model_type": "modernbert",
|
| 91 |
+
"norm_bias": false,
|
| 92 |
+
"norm_eps": 1e-05,
|
| 93 |
+
"norm_kwargs": {
|
| 94 |
+
"bias": false,
|
| 95 |
+
"eps": 1e-05
|
| 96 |
+
},
|
| 97 |
+
"normalization": "layernorm",
|
| 98 |
+
"num_attention_heads": 6,
|
| 99 |
+
"num_hidden_layers": 12,
|
| 100 |
+
"output_attentions": false,
|
| 101 |
+
"output_hidden_states": false,
|
| 102 |
+
"pad_token_id": 50283,
|
| 103 |
+
"padding": "unpadded",
|
| 104 |
+
"problem_type": null,
|
| 105 |
+
"repad_logits_with_grad": false,
|
| 106 |
+
"return_dict": true,
|
| 107 |
+
"rope_parameters": {
|
| 108 |
+
"full_attention": {
|
| 109 |
+
"rope_theta": 160000.0,
|
| 110 |
+
"rope_type": "default"
|
| 111 |
+
},
|
| 112 |
+
"sliding_attention": {
|
| 113 |
+
"rope_theta": 10000.0,
|
| 114 |
+
"rope_type": "default"
|
| 115 |
+
}
|
| 116 |
+
},
|
| 117 |
+
"rotary_emb_base": 160000.0,
|
| 118 |
+
"rotary_emb_dim": null,
|
| 119 |
+
"rotary_emb_interleaved": false,
|
| 120 |
+
"rotary_emb_scale_base": null,
|
| 121 |
+
"sep_token_id": 50282,
|
| 122 |
+
"skip_first_prenorm": true,
|
| 123 |
+
"sparse_pred_ignore_index": -100,
|
| 124 |
+
"sparse_prediction": false,
|
| 125 |
+
"tie_word_embeddings": true,
|
| 126 |
+
"transformers_version": "5.15.1",
|
| 127 |
+
"unpad_embeddings": true,
|
| 128 |
+
"vocab_size": 50368
|
| 129 |
+
},
|
| 130 |
+
"model_type": "accentik",
|
| 131 |
+
"release": "experimental-context-v2",
|
| 132 |
+
"tie_word_embeddings": false,
|
| 133 |
+
"transformers_version": "5.15.1"
|
| 134 |
+
}
|
configuration_accentik.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Configuration for Accentik's parallel Russian vowel-ranking model."""
|
| 2 |
+
from copy import deepcopy
|
| 3 |
+
|
| 4 |
+
from transformers import PreTrainedConfig
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class AccentikConfig(PreTrainedConfig):
|
| 8 |
+
model_type = "accentik"
|
| 9 |
+
|
| 10 |
+
def __init__(self, encoder_config=None, context_window=512,
|
| 11 |
+
batch_token_budget=8192, release="experimental-context-v2", **kwargs):
|
| 12 |
+
super().__init__(**kwargs)
|
| 13 |
+
self.encoder_config = deepcopy(encoder_config or {})
|
| 14 |
+
self.context_window = int(context_window)
|
| 15 |
+
self.batch_token_budget = int(batch_token_budget)
|
| 16 |
+
self.release = release
|
| 17 |
+
if self.context_window < 8 or self.context_window % 8:
|
| 18 |
+
raise ValueError("context_window must be a positive multiple of eight")
|
| 19 |
+
if self.batch_token_budget < self.context_window:
|
| 20 |
+
raise ValueError("batch_token_budget must fit one complete context window")
|
evaluation.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"release": "experimental-context-v2",
|
| 3 |
+
"status": "experimental, explicitly approved for public release",
|
| 4 |
+
"parameters": 34851578,
|
| 5 |
+
"weights_sha256": "8e0be4ecb637a35c4f152e2cb887bca8e95ab1f1b17daa4f62a1706331f7aa3e",
|
| 6 |
+
"source_checkpoint_sha256": "d406729a83a1cd65e17431a5ec642f32d26df089238f694d0fbf2d8ae34052da",
|
| 7 |
+
"selection_step": 200,
|
| 8 |
+
"manual_homograph_contexts": {
|
| 9 |
+
"original": {
|
| 10 |
+
"correct": 6532,
|
| 11 |
+
"total": 7673,
|
| 12 |
+
"accuracy": 0.8512967548546853,
|
| 13 |
+
"macro_accuracy": 0.8031411032280502
|
| 14 |
+
},
|
| 15 |
+
"experimental_context_v2": {
|
| 16 |
+
"correct": 7482,
|
| 17 |
+
"total": 7673,
|
| 18 |
+
"accuracy": 0.975107519874886,
|
| 19 |
+
"macro_accuracy": 0.9637305667643875
|
| 20 |
+
}
|
| 21 |
+
},
|
| 22 |
+
"general_russtress": {
|
| 23 |
+
"targets": 11089,
|
| 24 |
+
"original_correct": 10507,
|
| 25 |
+
"original_accuracy": 0.9475155559563532,
|
| 26 |
+
"experimental_correct": 10435,
|
| 27 |
+
"experimental_accuracy": 0.9410226350437371,
|
| 28 |
+
"native_ruaccent_correct": 10551,
|
| 29 |
+
"native_ruaccent_accuracy": 0.9514834520696186,
|
| 30 |
+
"reference": {
|
| 31 |
+
"repository": "MashaPo/russtress",
|
| 32 |
+
"revision": "8c46eac0750b1cd6eabcd5c380091d36d9aec7c4",
|
| 33 |
+
"path": "data/data_ru.csv",
|
| 34 |
+
"url": "https://raw.githubusercontent.com/MashaPo/russtress/8c46eac0750b1cd6eabcd5c380091d36d9aec7c4/data/data_ru.csv",
|
| 35 |
+
"sha256": "4e5002a50c375db6805ada2a8b4178997b4b481affc261dce4189ce5a93b8129"
|
| 36 |
+
},
|
| 37 |
+
"single_vowel_targets_excluded": 35
|
| 38 |
+
},
|
| 39 |
+
"supplied_dialogue_agreement": {
|
| 40 |
+
"original": {
|
| 41 |
+
"correct": 50069,
|
| 42 |
+
"words": 50564,
|
| 43 |
+
"accuracy": 0.9902104263903172,
|
| 44 |
+
"cross_entropy": 0.06666617238458393,
|
| 45 |
+
"mean_confidence": 0.99781406469883
|
| 46 |
+
},
|
| 47 |
+
"experimental": {
|
| 48 |
+
"correct": 49915,
|
| 49 |
+
"words": 50564,
|
| 50 |
+
"accuracy": 0.9871647812673048,
|
| 51 |
+
"cross_entropy": 0.057279157993131664,
|
| 52 |
+
"mean_confidence": 0.9928592729866481
|
| 53 |
+
},
|
| 54 |
+
"independent_human_benchmark": false
|
| 55 |
+
},
|
| 56 |
+
"targeted_diagnostics": {
|
| 57 |
+
"original_correct": 4,
|
| 58 |
+
"experimental_correct": 9,
|
| 59 |
+
"targets": 10,
|
| 60 |
+
"representative_benchmark": false,
|
| 61 |
+
"repeatedly_inspected_during_development": true
|
| 62 |
+
},
|
| 63 |
+
"internal_promotion_gate": {
|
| 64 |
+
"passed": false,
|
| 65 |
+
"gates": {
|
| 66 |
+
"manual_context_macro_improved": true,
|
| 67 |
+
"manual_context_micro_improved": true,
|
| 68 |
+
"external_no_material_regression": false,
|
| 69 |
+
"dialogue_no_material_regression": true,
|
| 70 |
+
"reported_lowercase_castle_lock_fixed": true,
|
| 71 |
+
"contextual_regressions_improved": true,
|
| 72 |
+
"cpu_reported_case_fixed": true,
|
| 73 |
+
"cpu_source_preserved": true,
|
| 74 |
+
"source_preserved": true
|
| 75 |
+
},
|
| 76 |
+
"note": "General accuracy regressed; released as an experimental alternative by explicit author approval."
|
| 77 |
+
},
|
| 78 |
+
"base_model": {
|
| 79 |
+
"model": "deepvk/RuModernBERT-small",
|
| 80 |
+
"revision": "cdfe49388e1f5261c69e4b1c8c41fa9e60b9ebef",
|
| 81 |
+
"branch": "patched-tokenizer"
|
| 82 |
+
},
|
| 83 |
+
"manual_training_context_source": {
|
| 84 |
+
"repository": "https://github.com/iv-stoliar/RussianHomographDataset",
|
| 85 |
+
"revision": "d8f65f2004a6ae0bbc0dc9bd70801a63d6a00ff3",
|
| 86 |
+
"license": "GPL-3.0"
|
| 87 |
+
},
|
| 88 |
+
"additional_training_sources": [
|
| 89 |
+
{
|
| 90 |
+
"repository": "TeraTTS/open_accent",
|
| 91 |
+
"revision": "19842ee44cd6f2d098ca7e6eeb36848e6e261410",
|
| 92 |
+
"license": "mit"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"repository": "TeraTTS/stress_dataset_sft_poetry",
|
| 96 |
+
"revision": "ab82b64cb446366894e273ff0abf5177d33479d6",
|
| 97 |
+
"license": "mit"
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"repository": "TeraTTS/stress_dataset_sft_proza",
|
| 101 |
+
"revision": "c1277f16ec3f70f11d711163bb5b622a17a8bd77",
|
| 102 |
+
"license": "mit"
|
| 103 |
+
}
|
| 104 |
+
],
|
| 105 |
+
"methodology_limits": [
|
| 106 |
+
"Validation selected checkpoint; fixed tests were reused during development.",
|
| 107 |
+
"Exact benchmark contexts excluded from refinement; overlap with original pseudo-label corpus unknown.",
|
| 108 |
+
"Teacher pretraining overlap with external references unknown.",
|
| 109 |
+
"No training texts redistributed in this model repository."
|
| 110 |
+
]
|
| 111 |
+
}
|
inference.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run Accentik from Hugging Face or a downloaded model folder."""
|
| 2 |
+
import argparse
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from transformers import AutoModel
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def main():
|
| 10 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 11 |
+
parser.add_argument("--model", default="TeraSpace/accentik")
|
| 12 |
+
parser.add_argument("--revision", help="Optional pinned Hub commit")
|
| 13 |
+
parser.add_argument("--device", default="cpu")
|
| 14 |
+
parser.add_argument("--threads", type=int, default=2)
|
| 15 |
+
inputs = parser.add_mutually_exclusive_group(required=True)
|
| 16 |
+
inputs.add_argument("--text")
|
| 17 |
+
inputs.add_argument("--input", type=Path)
|
| 18 |
+
parser.add_argument("--output", type=Path)
|
| 19 |
+
args = parser.parse_args()
|
| 20 |
+
torch.set_num_threads(args.threads)
|
| 21 |
+
model = AutoModel.from_pretrained(
|
| 22 |
+
args.model, revision=args.revision, trust_remote_code=True,
|
| 23 |
+
).to(args.device).eval()
|
| 24 |
+
text = args.text if args.text is not None else args.input.read_text(encoding="utf-8")
|
| 25 |
+
result = model.accentuate(text)
|
| 26 |
+
if args.output:
|
| 27 |
+
args.output.write_text(result, encoding="utf-8")
|
| 28 |
+
else:
|
| 29 |
+
print(result)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
if __name__ == "__main__":
|
| 33 |
+
main()
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8e0be4ecb637a35c4f152e2cb887bca8e95ab1f1b17daa4f62a1706331f7aa3e
|
| 3 |
+
size 139414960
|
modeling_accentik.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""PyTorch/Transformers implementation of Accentik experimental context v2."""
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
from typing import Optional
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from torch import nn
|
| 7 |
+
from transformers import AutoConfig, AutoModel, PreTrainedModel
|
| 8 |
+
from transformers.utils import ModelOutput
|
| 9 |
+
|
| 10 |
+
from .configuration_accentik import AccentikConfig
|
| 11 |
+
from .accentik_inference import AccentikInferenceMixin
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@dataclass
|
| 15 |
+
class AccentikOutput(ModelOutput):
|
| 16 |
+
"""One row per multi-vowel Russian word, one column per candidate vowel."""
|
| 17 |
+
loss: Optional[torch.Tensor] = None
|
| 18 |
+
logits: Optional[torch.Tensor] = None
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class AccentikModel(AccentikInferenceMixin, PreTrainedModel):
|
| 22 |
+
config_class = AccentikConfig
|
| 23 |
+
base_model_prefix = "encoder"
|
| 24 |
+
main_input_name = "tokens"
|
| 25 |
+
_supports_sdpa = True
|
| 26 |
+
|
| 27 |
+
def __init__(self, config):
|
| 28 |
+
super().__init__(config)
|
| 29 |
+
cfg = dict(config.encoder_config)
|
| 30 |
+
kind = cfg.pop("model_type")
|
| 31 |
+
cfg.pop("accentor_local_head", None)
|
| 32 |
+
cfg["reference_compile"] = False
|
| 33 |
+
self.encoder = AutoModel.from_config(
|
| 34 |
+
AutoConfig.for_model(kind, **cfg), attn_implementation="sdpa"
|
| 35 |
+
)
|
| 36 |
+
h = self.encoder.config.hidden_size
|
| 37 |
+
self.letter = nn.Embedding(10, 12)
|
| 38 |
+
self.rank = nn.Embedding(64, 12)
|
| 39 |
+
self.count = nn.Embedding(64, 12)
|
| 40 |
+
self.head = nn.Sequential(
|
| 41 |
+
nn.Linear(h * 2 + 40, 192), nn.GELU(), nn.Dropout(0.1), nn.Linear(192, 1)
|
| 42 |
+
)
|
| 43 |
+
self.local_head = nn.Sequential(
|
| 44 |
+
nn.Linear(h * 4 + 40, 192), nn.GELU(), nn.Dropout(0.1), nn.Linear(192, 1)
|
| 45 |
+
)
|
| 46 |
+
self.post_init()
|
| 47 |
+
|
| 48 |
+
@classmethod
|
| 49 |
+
def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
|
| 50 |
+
loaded = super().from_pretrained(pretrained_model_name_or_path, *args, **kwargs)
|
| 51 |
+
model = loaded[0] if isinstance(loaded, tuple) else loaded
|
| 52 |
+
model._accentik_source = str(pretrained_model_name_or_path)
|
| 53 |
+
# Keep the tokenizer pinned to the same Hub snapshot as the weights.
|
| 54 |
+
options = {key: kwargs[key] for key in
|
| 55 |
+
("cache_dir", "local_files_only", "token", "subfolder", "force_download")
|
| 56 |
+
if key in kwargs}
|
| 57 |
+
revision = getattr(model.config, "_commit_hash", None) or kwargs.get("revision")
|
| 58 |
+
if revision is not None:
|
| 59 |
+
options["revision"] = revision
|
| 60 |
+
model._accentik_tokenizer_options = options
|
| 61 |
+
return loaded
|
| 62 |
+
|
| 63 |
+
def forward(self, tokens, attention, word_first, word_last, candidate_first,
|
| 64 |
+
candidate_last, letters, rank, count, scalars, valid,
|
| 65 |
+
labels=None, return_dict=True):
|
| 66 |
+
"""Score candidate vowels; use accentuate()/annotate() for ordinary text.
|
| 67 |
+
|
| 68 |
+
Feature indices are flattened across the padded token batch. The supplied
|
| 69 |
+
inference helpers construct these features without truncating words.
|
| 70 |
+
"""
|
| 71 |
+
hidden = self.encoder(input_ids=tokens, attention_mask=attention).last_hidden_state
|
| 72 |
+
flat = hidden.reshape(-1, hidden.shape[-1])
|
| 73 |
+
width = tokens.shape[1]
|
| 74 |
+
word = (flat[word_first] + flat[word_last]) * 0.5
|
| 75 |
+
vowel = (flat[candidate_first] + flat[candidate_last]) * 0.5
|
| 76 |
+
features = torch.cat((
|
| 77 |
+
vowel, word[:, None, :].expand_as(vowel), self.letter(letters),
|
| 78 |
+
self.rank(rank), self.count(count), scalars.to(vowel.dtype)
|
| 79 |
+
), dim=-1)
|
| 80 |
+
begin = (word_first // width) * width
|
| 81 |
+
end = begin + width - 1
|
| 82 |
+
mask = attention.reshape(-1)
|
| 83 |
+
neighbors = []
|
| 84 |
+
for anchor, direction in [(word_first, -1), (word_last, 1)]:
|
| 85 |
+
offsets = torch.tensor([1, 2, 3], device=tokens.device)
|
| 86 |
+
indices = (anchor[:, None] + direction * offsets).maximum(
|
| 87 |
+
begin[:, None]).minimum(end[:, None])
|
| 88 |
+
weights = mask[indices].to(flat.dtype)
|
| 89 |
+
neighbors.append((flat[indices] * weights[:, :, None]).sum(1) /
|
| 90 |
+
weights.sum(1).clamp_min(1)[:, None])
|
| 91 |
+
local = torch.cat((
|
| 92 |
+
features, neighbors[0][:, None, :].expand_as(vowel),
|
| 93 |
+
neighbors[1][:, None, :].expand_as(vowel)
|
| 94 |
+
), dim=-1)
|
| 95 |
+
logits = (self.head(features).squeeze(-1).float() +
|
| 96 |
+
self.local_head(local).squeeze(-1).float())
|
| 97 |
+
logits = logits.masked_fill(~valid, -1e9)
|
| 98 |
+
loss = None
|
| 99 |
+
if labels is not None:
|
| 100 |
+
if (labels != -100).any():
|
| 101 |
+
loss = nn.functional.cross_entropy(logits, labels, ignore_index=-100)
|
| 102 |
+
else:
|
| 103 |
+
loss = logits.sum() * 0.0
|
| 104 |
+
if not return_dict:
|
| 105 |
+
return (loss, logits) if loss is not None else (logits,)
|
| 106 |
+
return AccentikOutput(loss=loss, logits=logits)
|
release_manifest.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"release": "experimental-context-v2",
|
| 3 |
+
"parameters": 34851578,
|
| 4 |
+
"tensor_precision": "float32",
|
| 5 |
+
"source_checkpoint_sha256": "d406729a83a1cd65e17431a5ec642f32d26df089238f694d0fbf2d8ae34052da",
|
| 6 |
+
"files": {
|
| 7 |
+
"LICENSE": {
|
| 8 |
+
"sha256": "60cdc5a7bdc8928a0580d8101c83830278aaa12cdd466251e97f1a1ef392381c",
|
| 9 |
+
"bytes": 5238
|
| 10 |
+
},
|
| 11 |
+
"LICENSE-APACHE-2.0": {
|
| 12 |
+
"sha256": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30",
|
| 13 |
+
"bytes": 11358
|
| 14 |
+
},
|
| 15 |
+
"LICENSE-OPENRAIL": {
|
| 16 |
+
"sha256": "0d944a9110fed9a9602d60e0423a272903e7bd21ab060490774efc77c2275e9f",
|
| 17 |
+
"bytes": 15007
|
| 18 |
+
},
|
| 19 |
+
"NOTICE": {
|
| 20 |
+
"sha256": "a4dc2e8cdd693187272ecc287ff7fd5517accfa0a64955b0b3df3956066a0457",
|
| 21 |
+
"bytes": 1358
|
| 22 |
+
},
|
| 23 |
+
"README.md": {
|
| 24 |
+
"sha256": "50aa45874a444c27eb46890ca3594adbbee275c981c19d5afe21b1305929c1e1",
|
| 25 |
+
"bytes": 9864
|
| 26 |
+
},
|
| 27 |
+
"accentik_features.py": {
|
| 28 |
+
"sha256": "225818fd735d8d9cee68353ee929c35653b4e8a7bf8c48d4d4d180ad6434ebce",
|
| 29 |
+
"bytes": 2334
|
| 30 |
+
},
|
| 31 |
+
"accentik_inference.py": {
|
| 32 |
+
"sha256": "d27420f296a5fe01f9002bb92fb811fe670c6c179727e3a34977f3e81edcb553",
|
| 33 |
+
"bytes": 5826
|
| 34 |
+
},
|
| 35 |
+
"accentik_text.py": {
|
| 36 |
+
"sha256": "cdbe0263cee84f590c1b6cc37939c169297a36b3af844b1fc0cd7d8c217d7686",
|
| 37 |
+
"bytes": 3246
|
| 38 |
+
},
|
| 39 |
+
"config.json": {
|
| 40 |
+
"sha256": "0e6caa1dfd026b7673887eabb9c30081366f883e819a297266797452b09f88de",
|
| 41 |
+
"bytes": 3582
|
| 42 |
+
},
|
| 43 |
+
"configuration_accentik.py": {
|
| 44 |
+
"sha256": "6e171612c15849379a49418cc78aee3a901178e89de2af1008f05558acdc9d2d",
|
| 45 |
+
"bytes": 893
|
| 46 |
+
},
|
| 47 |
+
"evaluation.json": {
|
| 48 |
+
"sha256": "63c52751ce883f484b45ae7302bf5fb9dac6ff531cadc0edc29770f65fef0268",
|
| 49 |
+
"bytes": 3879
|
| 50 |
+
},
|
| 51 |
+
"inference.py": {
|
| 52 |
+
"sha256": "6a2544fc70272489ffb3567b019deb7df9d8b2f44befb52c85bc0a0e4c916b96",
|
| 53 |
+
"bytes": 1149
|
| 54 |
+
},
|
| 55 |
+
"model.safetensors": {
|
| 56 |
+
"sha256": "8e0be4ecb637a35c4f152e2cb887bca8e95ab1f1b17daa4f62a1706331f7aa3e",
|
| 57 |
+
"bytes": 139414960
|
| 58 |
+
},
|
| 59 |
+
"modeling_accentik.py": {
|
| 60 |
+
"sha256": "54d4b79235b4e715c9540a2e2154d21a9d1f3f42ec1de9c47002f69da775ae86",
|
| 61 |
+
"bytes": 4702
|
| 62 |
+
},
|
| 63 |
+
"requirements.txt": {
|
| 64 |
+
"sha256": "bb0103c01f47cb453da2a1b51b9ef4976e22cf2d7640681c2bafa6868f4aa09b",
|
| 65 |
+
"bytes": 66
|
| 66 |
+
},
|
| 67 |
+
"tokenizer.json": {
|
| 68 |
+
"sha256": "a648622822a938fca174540ec4bf7753541cb4130aaf52b120b186d33fae6ee6",
|
| 69 |
+
"bytes": 4752657
|
| 70 |
+
},
|
| 71 |
+
"tokenizer_config.json": {
|
| 72 |
+
"sha256": "8ffb7a7dfa44bde33ceaf6824a840042fed4e408921e8208f0233a5d43c3a53b",
|
| 73 |
+
"bytes": 377
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
}
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch>=2.6
|
| 2 |
+
transformers>=5.15.1,<6
|
| 3 |
+
safetensors>=0.4.3
|
| 4 |
+
numpy>=1.24
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"backend": "tokenizers",
|
| 3 |
+
"clean_up_tokenization_spaces": true,
|
| 4 |
+
"cls_token": "[CLS]",
|
| 5 |
+
"is_local": true,
|
| 6 |
+
"local_files_only": true,
|
| 7 |
+
"mask_token": "[MASK]",
|
| 8 |
+
"model_input_names": [
|
| 9 |
+
"input_ids",
|
| 10 |
+
"attention_mask"
|
| 11 |
+
],
|
| 12 |
+
"model_max_length": 512,
|
| 13 |
+
"pad_token": "[PAD]",
|
| 14 |
+
"sep_token": "[SEP]",
|
| 15 |
+
"tokenizer_class": "TokenizersBackend",
|
| 16 |
+
"unk_token": "[UNK]"
|
| 17 |
+
}
|