kabosu 0.6.11.3-aarch64-linux → 0.7.0.1-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +44 -5
- data/lib/kabosu/3.1/kabosu.so +0 -0
- data/lib/kabosu/3.2/kabosu.so +0 -0
- data/lib/kabosu/3.3/kabosu.so +0 -0
- data/lib/kabosu/3.4/kabosu.so +0 -0
- data/lib/kabosu/4.0/kabosu.so +0 -0
- data/lib/kabosu/dict_manager.rb +59 -26
- data/lib/kabosu/resources/char.def +1 -1
- data/lib/kabosu/tasks.rake +15 -1
- data/lib/kabosu/version.rb +1 -1
- data/lib/kabosu.rb +60 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba6c61184a10e59d12f7618f0769f27766422c11644ec5c47af51f7eb1775890
|
|
4
|
+
data.tar.gz: 1442e054d02e0bbfaad77d0447f32f33b00d8dec19aafd4c9f60062b0b1e11d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc59f91c5486eebb6382f68df24459d6dc34aa52c02e53197d6538c5e19830c9865a6c859535d2e95d8f082ea5beb928e0106ed6c5b7afd3a7a66220cbc847c1
|
|
7
|
+
data.tar.gz: f187ffa82f345736a0a160b4146ed6c9b6b7f4c69bfa98a03a76d80075c6670554a76063cffb3ba724d38bd3b237fdf8871a8c540eee81aa70b7168d2dfdfc46
|
data/README.md
CHANGED
|
@@ -43,10 +43,12 @@ morpheme.dictionary_id # => 0 - source dictionary id
|
|
|
43
43
|
morpheme.word_id # => 544373 - internal word id
|
|
44
44
|
morpheme.synonym_group_ids # => [] - synonym group ids
|
|
45
45
|
morpheme.dictionary_form_word_id # => -1 - dictionary-form word id
|
|
46
|
-
morpheme.head_word_length # =>
|
|
46
|
+
morpheme.head_word_length # => 9 - bytes of the normalized index form
|
|
47
47
|
morpheme.a_unit_split # => [123, 456] - split-A word ids
|
|
48
48
|
morpheme.b_unit_split # => [] - split-B word ids
|
|
49
49
|
morpheme.word_structure # => [123, 456] - word-structure ids
|
|
50
|
+
morpheme.c_unit_split # => [] - split-C word ids (V1 dictionaries)
|
|
51
|
+
morpheme.user_data # => "" - free text from a user dictionary's user_data column
|
|
50
52
|
morpheme.total_cost # => 5765 - morphological analysis cost
|
|
51
53
|
morpheme.begin # => 0 - start byte offset
|
|
52
54
|
morpheme.end # => 9 - end byte offset
|
|
@@ -75,22 +77,34 @@ Then install and download a [Sudachi dictionary](https://github.com/WorksApplica
|
|
|
75
77
|
|
|
76
78
|
```sh
|
|
77
79
|
bundle install
|
|
78
|
-
bundle exec rake kabosu:install
|
|
80
|
+
bundle exec rake kabosu:install:small # or :core, :full
|
|
79
81
|
```
|
|
80
82
|
|
|
81
83
|
Dictionary editions (from smallest to largest): `small`, `core`, `full`. See the [SudachiDict documentation](https://github.com/WorksApplications/SudachiDict?tab=readme-ov-file#dictionary-types) for details on the differences between editions.
|
|
82
84
|
|
|
85
|
+
kabosu 0.7 (sudachi.rs 0.7) reads only the V1 dictionary format: SudachiDict `20261015` or later.
|
|
86
|
+
|
|
87
|
+
## Upgrading from 0.6
|
|
88
|
+
|
|
89
|
+
sudachi.rs 0.7 changed the binary dictionary format, so a 0.6 setup needs three things:
|
|
90
|
+
|
|
91
|
+
1. **Reinstall the system dictionary.** Dictionaries installed by kabosu 0.6 are V0 and cannot be loaded. Run `rake kabosu:install` (or `install_if_missing`, which ignores V0 files), then drop the old ones with `rake kabosu:remove VERSION=...`. `rake kabosu:list` marks them.
|
|
92
|
+
2. **Rebuild user dictionaries** against that exact system dictionary: `rake kabosu:build_user_dict CSV=names.csv OUTPUT=names.dic` (or `Kabosu.build_user_dict`). A user dictionary now records which system dictionary it was built with, and loading it with a different one raises `Kabosu::DictionaryError`. The CSV uses the V1 column layout (see [Sudachi's user dictionary guide](https://github.com/WorksApplications/Sudachi/blob/develop/docs/user_dict.md)).
|
|
93
|
+
3. **Expect small tokenization differences.** sudachi.rs 0.7 aligned its lattice search, character-category handling and katakana OOV joining with Java Sudachi, so some inputs segment differently even with the same dictionary. Custom `char.def` files must replace `NOOOVBOW2` with `NOOOVBOW NOOOVEOW`.
|
|
94
|
+
|
|
95
|
+
Other visible changes: `Dictionary#lookup` normalizes the query first (`カボス` finds カボス), joined numerals and katakana carry an OOV `word_id` instead of `4294967295`, and a custom config that names no `char.def`/`unk.def` falls back to the files built into sudachi.rs.
|
|
96
|
+
|
|
83
97
|
## Dictionary management
|
|
84
98
|
|
|
85
99
|
Rake tasks for managing Sudachi dictionaries:
|
|
86
100
|
|
|
87
101
|
```sh
|
|
88
|
-
rake kabosu:install
|
|
102
|
+
rake kabosu:install:small # Install a dictionary (VERSION=YYYYMMDD for a specific version)
|
|
89
103
|
rake kabosu:install_if_missing # Same, but a no-op when a dictionary is already installed
|
|
90
104
|
rake kabosu:list # List installed dictionaries
|
|
91
105
|
rake kabosu:versions # Show available versions from GitHub
|
|
92
106
|
rake kabosu:path # Show path to best available dictionary
|
|
93
|
-
rake kabosu:remove
|
|
107
|
+
rake kabosu:remove:small # Remove a dictionary (VERSION=YYYYMMDD for a specific version)
|
|
94
108
|
```
|
|
95
109
|
|
|
96
110
|
Dictionaries are stored in `~/.kabosu/dict/` by default. Set `KABOSU_DICT_DIR` to customize — useful for pointing at a Docker volume so the dictionary persists across deployments.
|
|
@@ -134,7 +148,7 @@ list = tokenizer.tokenize("国会議事堂前駅")
|
|
|
134
148
|
list.surfaces
|
|
135
149
|
list.first.part_of_speech
|
|
136
150
|
|
|
137
|
-
# Dictionary prefix lookup
|
|
151
|
+
# Dictionary prefix lookup (the query is normalized first, like tokenization)
|
|
138
152
|
dict.lookup("東京都").surfaces
|
|
139
153
|
|
|
140
154
|
# Morpheme split
|
|
@@ -146,6 +160,31 @@ Kabosu.split_sentences("東京都に住んでいる。大阪も好きだ。", ra
|
|
|
146
160
|
Kabosu.split_sentences("長い文...", limit: 12, with_checker: true)
|
|
147
161
|
```
|
|
148
162
|
|
|
163
|
+
### Dictionary entries and forms (sudachi.rs 0.7)
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
m = tokenizer.tokenize("住んでいた").first # 住ん
|
|
167
|
+
m.dictionary_form_morpheme # the 住む entry itself: POS, reading, ids…
|
|
168
|
+
tokenizer.tokenize("附属").first.normalized_form_morpheme.surface # => "付属"
|
|
169
|
+
# A word that is its own form (and any OOV word) returns itself.
|
|
170
|
+
|
|
171
|
+
# Every entry in the loaded dictionaries, lazily (millions for `full`)
|
|
172
|
+
dict.entries.lazy.select(&:user?).first(10)
|
|
173
|
+
|
|
174
|
+
# Exact matches by scanning every entry, including ones not indexed for
|
|
175
|
+
# lookup. Slow on large dictionaries; prefer #lookup.
|
|
176
|
+
dict.lookup_all_entries("カボス").surfaces # => ["カボス"]
|
|
177
|
+
|
|
178
|
+
# Hand-made out-of-vocabulary morpheme; forms default to the surface
|
|
179
|
+
dict.oov_morpheme(m.part_of_speech_id, "ズィーガン", reading: "ジーガン")
|
|
180
|
+
|
|
181
|
+
# What tokenization actually sees after the input-text plugins
|
|
182
|
+
dict.normalize("カボス ABC コンピュータ〜〜") # => "カボス abc コンピューター"
|
|
183
|
+
|
|
184
|
+
# Compile a user dictionary against the installed system dictionary
|
|
185
|
+
Kabosu.build_user_dict("names.csv", output: "names.dic")
|
|
186
|
+
```
|
|
187
|
+
|
|
149
188
|
## Benchmarks
|
|
150
189
|
|
|
151
190
|
Kabosu ships with a benchmark suite that measures tokenization throughput and compares the Ruby bindings against raw [sudachi.rs](https://github.com/WorksApplications/sudachi.rs).
|
data/lib/kabosu/3.1/kabosu.so
CHANGED
|
Binary file
|
data/lib/kabosu/3.2/kabosu.so
CHANGED
|
Binary file
|
data/lib/kabosu/3.3/kabosu.so
CHANGED
|
Binary file
|
data/lib/kabosu/3.4/kabosu.so
CHANGED
|
Binary file
|
data/lib/kabosu/4.0/kabosu.so
CHANGED
|
Binary file
|
data/lib/kabosu/dict_manager.rb
CHANGED
|
@@ -10,9 +10,16 @@ module Kabosu
|
|
|
10
10
|
EDITION_PRIORITY = %w[full core small].freeze
|
|
11
11
|
GITHUB_REPO = "WorksApplications/SudachiDict".freeze
|
|
12
12
|
GITHUB_API = "https://api.github.com".freeze
|
|
13
|
+
# sudachi.rs 0.7 reads only V1 dictionaries, which open with this magic.
|
|
14
|
+
# Older (V0) files stay listed so they can be removed, but are never picked.
|
|
15
|
+
V1_MAGIC = "SudachiBinaryDic".b.freeze
|
|
16
|
+
# The first SudachiDict GitHub release carrying V1 assets. v20260723.1 is
|
|
17
|
+
# V1 too, but was published to PyPI only and has no assets to download.
|
|
18
|
+
MIN_VERSION = "20261015".freeze
|
|
13
19
|
|
|
14
20
|
class DictNotFound < StandardError; end
|
|
15
21
|
class DownloadError < StandardError; end
|
|
22
|
+
class UnsupportedVersion < StandardError; end
|
|
16
23
|
|
|
17
24
|
# Default storage directory. Honors KABOSU_DICT_DIR so consumers can point
|
|
18
25
|
# the gem at a Docker volume / shared mount without subclassing or threading
|
|
@@ -37,13 +44,19 @@ module Kabosu
|
|
|
37
44
|
def install(edition = "core", version: nil)
|
|
38
45
|
edition = validate_edition(edition)
|
|
39
46
|
version ||= latest_version
|
|
47
|
+
validate_version(version)
|
|
40
48
|
|
|
41
49
|
dest_dir = File.join(@dir, "sudachi-dictionary-#{version}")
|
|
42
50
|
dic_path = File.join(dest_dir, "system_#{edition}.dic")
|
|
43
51
|
|
|
44
52
|
if File.exist?(dic_path)
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if v1?(dic_path)
|
|
54
|
+
warn "Already installed: #{dic_path}"
|
|
55
|
+
return dic_path
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
warn "Replacing pre-V1 dictionary: #{dic_path}"
|
|
59
|
+
FileUtils.rm_f(dic_path)
|
|
47
60
|
end
|
|
48
61
|
|
|
49
62
|
FileUtils.mkdir_p(@dir)
|
|
@@ -58,23 +71,26 @@ module Kabosu
|
|
|
58
71
|
raise DownloadError, "No downloadable assets for #{version}/#{edition}" if sources.empty?
|
|
59
72
|
|
|
60
73
|
sources.each do |source|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
warn " falling back: #{e.message}"
|
|
73
|
-
end
|
|
74
|
+
download(source.fetch(:url), source.fetch(:archive_path))
|
|
75
|
+
extract(source.fetch(:archive_path), dest_dir, edition: edition)
|
|
76
|
+
FileUtils.rm_f(source.fetch(:archive_path))
|
|
77
|
+
break
|
|
78
|
+
rescue DownloadError => e
|
|
79
|
+
FileUtils.rm_f(source.fetch(:archive_path))
|
|
80
|
+
# Try the next candidate (e.g. wheel if the zip 404s). If this was
|
|
81
|
+
# the last one, surface the original error.
|
|
82
|
+
raise if sources.last.equal?(source)
|
|
83
|
+
|
|
84
|
+
warn " falling back: #{e.message}"
|
|
74
85
|
end
|
|
75
86
|
|
|
76
87
|
raise DownloadError, "Expected #{dic_path} after extraction, but file not found" unless File.exist?(dic_path)
|
|
77
88
|
|
|
89
|
+
unless v1?(dic_path)
|
|
90
|
+
FileUtils.rm_f(dic_path)
|
|
91
|
+
raise UnsupportedVersion, "#{version}/#{edition} is not a V1 dictionary, which sudachi.rs 0.7+ requires"
|
|
92
|
+
end
|
|
93
|
+
|
|
78
94
|
warn "Installed: #{dic_path}"
|
|
79
95
|
dic_path
|
|
80
96
|
end
|
|
@@ -89,7 +105,7 @@ module Kabosu
|
|
|
89
105
|
#
|
|
90
106
|
def install_if_missing(edition = "core", version: nil)
|
|
91
107
|
edition = validate_edition(edition)
|
|
92
|
-
matching =
|
|
108
|
+
matching = readable.find do |d|
|
|
93
109
|
d[:edition] == edition && (version.nil? || d[:version] == version)
|
|
94
110
|
end
|
|
95
111
|
return matching[:path] if matching
|
|
@@ -123,8 +139,13 @@ module Kabosu
|
|
|
123
139
|
# Find the best available dictionary path.
|
|
124
140
|
# Prefers: latest version, then full > core > small.
|
|
125
141
|
def find(edition: nil)
|
|
126
|
-
candidates =
|
|
127
|
-
|
|
142
|
+
candidates = readable
|
|
143
|
+
if candidates.empty?
|
|
144
|
+
raise DictNotFound, "No dictionaries installed. Run: rake kabosu:install" if installed.empty?
|
|
145
|
+
|
|
146
|
+
raise DictNotFound, "Only pre-V1 dictionaries are installed, which sudachi.rs 0.7+ cannot read. " \
|
|
147
|
+
"Run: rake kabosu:install (and rake kabosu:remove VERSION=... for the old ones)"
|
|
148
|
+
end
|
|
128
149
|
|
|
129
150
|
if edition
|
|
130
151
|
edition = validate_edition(edition)
|
|
@@ -146,6 +167,14 @@ module Kabosu
|
|
|
146
167
|
best.is_a?(Hash) ? best[:path] : latest_version_dicts.first[:path]
|
|
147
168
|
end
|
|
148
169
|
|
|
170
|
+
def readable
|
|
171
|
+
installed.select { |d| v1?(d[:path]) }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def v1?(path)
|
|
175
|
+
File.binread(path, V1_MAGIC.bytesize) == V1_MAGIC
|
|
176
|
+
end
|
|
177
|
+
|
|
149
178
|
# ── Remove ──
|
|
150
179
|
|
|
151
180
|
# Remove a specific dictionary edition, or an entire version.
|
|
@@ -191,6 +220,15 @@ module Kabosu
|
|
|
191
220
|
|
|
192
221
|
private
|
|
193
222
|
|
|
223
|
+
def validate_version(version)
|
|
224
|
+
return if Gem::Version.new(version) >= Gem::Version.new(MIN_VERSION)
|
|
225
|
+
|
|
226
|
+
raise UnsupportedVersion, "SudachiDict #{version} predates the V1 format sudachi.rs 0.7+ reads; " \
|
|
227
|
+
"use #{MIN_VERSION} or later"
|
|
228
|
+
rescue ArgumentError
|
|
229
|
+
raise UnsupportedVersion, "Malformed SudachiDict version: #{version.inspect}"
|
|
230
|
+
end
|
|
231
|
+
|
|
194
232
|
def validate_edition(edition)
|
|
195
233
|
edition = edition.to_s.downcase
|
|
196
234
|
unless EDITIONS.include?(edition)
|
|
@@ -214,7 +252,8 @@ module Kabosu
|
|
|
214
252
|
def pick_release_sources(version, edition)
|
|
215
253
|
candidates = []
|
|
216
254
|
zip = release_asset_url(version, edition)
|
|
217
|
-
candidates << { url: zip, archive_path: File.join(@dir, "sudachi-dictionary-#{version}-#{edition}.zip"),
|
|
255
|
+
candidates << { url: zip, archive_path: File.join(@dir, "sudachi-dictionary-#{version}-#{edition}.zip"),
|
|
256
|
+
format: :zip }
|
|
218
257
|
|
|
219
258
|
begin
|
|
220
259
|
release = fetch_release(version)
|
|
@@ -337,14 +376,8 @@ module Kabosu
|
|
|
337
376
|
|
|
338
377
|
next if entry.directory?
|
|
339
378
|
|
|
340
|
-
target = File.join(dest_dir, target_name)
|
|
341
|
-
# Guard against zip-slip — refuse entries that escape dest_dir.
|
|
342
|
-
unless File.expand_path(target).start_with?(File.expand_path(dest_dir) + File::SEPARATOR)
|
|
343
|
-
raise DownloadError, "Refusing to extract entry outside dest_dir: #{entry.name}"
|
|
344
|
-
end
|
|
345
|
-
|
|
346
379
|
FileUtils.mkdir_p(dest_dir)
|
|
347
|
-
entry.extract(
|
|
380
|
+
entry.extract(target_name, destination_directory: dest_dir) { true }
|
|
348
381
|
end
|
|
349
382
|
end
|
|
350
383
|
rescue Zip::Error => e
|
|
@@ -174,6 +174,6 @@ CYRILLIC 1 1 0
|
|
|
174
174
|
0x1F3FB..0x1F3FE ALL NOOOVBOW # emoji skin tone modifiers https://codepoints.net/U+1F3FF
|
|
175
175
|
|
|
176
176
|
# Combination marks
|
|
177
|
-
0x200C..0x200D ALL
|
|
177
|
+
0x200C..0x200D ALL NOOOVBOW NOOOVEOW # Zero Width Non-Joiner/Joiner
|
|
178
178
|
|
|
179
179
|
# END OF TABLE
|
data/lib/kabosu/tasks.rake
CHANGED
|
@@ -56,6 +56,19 @@ namespace :kabosu do
|
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
# ── User dictionaries ──
|
|
60
|
+
|
|
61
|
+
desc "Build a user dictionary: CSV=a.csv[,b.csv] OUTPUT=user.dic [SYSTEM_DICT=path] " \
|
|
62
|
+
"(defaults to the best installed dictionary)"
|
|
63
|
+
task :build_user_dict do
|
|
64
|
+
require "kabosu"
|
|
65
|
+
csv = ENV.fetch("CSV") { abort "CSV=path/to/lexicon.csv is required" }.split(",")
|
|
66
|
+
output = ENV.fetch("OUTPUT") { abort "OUTPUT=path/to/user.dic is required" }
|
|
67
|
+
system_dict = ENV.fetch("SYSTEM_DICT") { Kabosu::Dictionary.path }
|
|
68
|
+
Kabosu.build_user_dict(csv, output: output, system_dict: system_dict)
|
|
69
|
+
puts "Built #{output} against #{system_dict}"
|
|
70
|
+
end
|
|
71
|
+
|
|
59
72
|
# ── Info ──
|
|
60
73
|
|
|
61
74
|
desc "List installed Sudachi dictionaries"
|
|
@@ -70,7 +83,8 @@ namespace :kabosu do
|
|
|
70
83
|
puts
|
|
71
84
|
dicts.each do |d|
|
|
72
85
|
size_mb = (File.size(d[:path]).to_f / 1024 / 1024).round(1)
|
|
73
|
-
|
|
86
|
+
unreadable = manager.v1?(d[:path]) ? "" : " [pre-V1, unreadable by this kabosu]"
|
|
87
|
+
puts " #{d[:version]} / #{d[:edition].ljust(5)} (#{size_mb} MB)#{unreadable}"
|
|
74
88
|
puts " #{d[:path]}"
|
|
75
89
|
end
|
|
76
90
|
end
|
data/lib/kabosu/version.rb
CHANGED
data/lib/kabosu.rb
CHANGED
|
@@ -105,6 +105,14 @@ module Kabosu
|
|
|
105
105
|
|
|
106
106
|
def map_dictionary_init_error(error, config:, system_dict:)
|
|
107
107
|
message = error.message
|
|
108
|
+
if message.include?("V0 version")
|
|
109
|
+
return DictionaryError.new(
|
|
110
|
+
"#{message}: a system or user dictionary is in the pre-V1 format, which sudachi.rs 0.7+ cannot read. " \
|
|
111
|
+
"Install SudachiDict #{DictManager::MIN_VERSION} or later (rake kabosu:install) " \
|
|
112
|
+
"and rebuild user dictionaries against it."
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
108
116
|
if (config && system_dict.nil?) || message.match?(/config|setting\.json|json/i)
|
|
109
117
|
ConfigError.new(message)
|
|
110
118
|
else
|
|
@@ -148,6 +156,41 @@ module Kabosu
|
|
|
148
156
|
rescue RuntimeError => e
|
|
149
157
|
raise LookupError.new(e.message), cause: e
|
|
150
158
|
end
|
|
159
|
+
|
|
160
|
+
# Every public dictionary entry as a standalone Morpheme (offsets cover its
|
|
161
|
+
# own headword). Lazy: a `full` dictionary holds millions of entries, so
|
|
162
|
+
# chain with `.lazy`, `.first(n)` or `.each` rather than `.to_a`.
|
|
163
|
+
#
|
|
164
|
+
# dict.entries.lazy.select { _1.user? }.first(10)
|
|
165
|
+
def entries(&block)
|
|
166
|
+
return enum_for(:entries) unless block
|
|
167
|
+
|
|
168
|
+
_each_entry(&block)
|
|
169
|
+
self
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Like #lookup, but exact matches only and found by scanning every entry,
|
|
173
|
+
# so it also finds entries that are not indexed for lookup. Slow.
|
|
174
|
+
def lookup_all_entries(surface)
|
|
175
|
+
raise ArgumentError, "surface must be a String" unless surface.is_a?(String)
|
|
176
|
+
|
|
177
|
+
MorphemeList.new(_lookup_all_entries(surface))
|
|
178
|
+
rescue RuntimeError => e
|
|
179
|
+
raise LookupError.new(e.message), cause: e
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Builds an out-of-vocabulary Morpheme by hand. The forms default to the
|
|
183
|
+
# surface. pos_id comes from Morpheme#part_of_speech_id.
|
|
184
|
+
#
|
|
185
|
+
# dict.oov_morpheme(pos_id, "ズィーガンボルト", reading: "ズィーガンボルト")
|
|
186
|
+
def oov_morpheme(pos_id, surface, reading: nil, normalized_form: nil, dictionary_form: nil)
|
|
187
|
+
raise ArgumentError, "pos_id must be an Integer" unless pos_id.is_a?(Integer)
|
|
188
|
+
raise ArgumentError, "surface must be a String" unless surface.is_a?(String)
|
|
189
|
+
|
|
190
|
+
_oov_morpheme(pos_id, surface, reading, normalized_form, dictionary_form)
|
|
191
|
+
rescue RangeError, RuntimeError => e
|
|
192
|
+
raise ArgumentError, "invalid part-of-speech id #{pos_id}: #{e.message}"
|
|
193
|
+
end
|
|
151
194
|
end
|
|
152
195
|
|
|
153
196
|
# ── Tokenizer: wrap output in MorphemeList ──
|
|
@@ -179,6 +222,23 @@ module Kabosu
|
|
|
179
222
|
end
|
|
180
223
|
end
|
|
181
224
|
|
|
225
|
+
# Compiles user-dictionary CSV(s) into a binary user dictionary. The result
|
|
226
|
+
# loads only next to the system dictionary it was built against, so rebuild
|
|
227
|
+
# whenever that changes (including the move to sudachi.rs 0.7).
|
|
228
|
+
#
|
|
229
|
+
# Kabosu.build_user_dict("names.csv", output: "names.dic")
|
|
230
|
+
# Kabosu::Dictionary.new(system_dict: Kabosu::Dictionary.path, user_dicts: ["names.dic"])
|
|
231
|
+
def self.build_user_dict(inputs, output:, system_dict: Dictionary.path, description: nil)
|
|
232
|
+
inputs = Array(inputs)
|
|
233
|
+
raise ArgumentError, "inputs must be String paths" unless inputs.all?(String)
|
|
234
|
+
raise ArgumentError, "output must be a String" unless output.is_a?(String)
|
|
235
|
+
|
|
236
|
+
_build_user_dict(inputs, system_dict, output, description)
|
|
237
|
+
output
|
|
238
|
+
rescue RuntimeError => e
|
|
239
|
+
raise DictionaryError.new(e.message), cause: e
|
|
240
|
+
end
|
|
241
|
+
|
|
182
242
|
def self.split_sentences(text, limit: nil, with_checker: false, ranges: false, dictionary: nil)
|
|
183
243
|
raise ArgumentError, "text must be a String" unless text.is_a?(String)
|
|
184
244
|
raise ArgumentError, "limit must be an Integer or nil" unless limit.nil? || limit.is_a?(Integer)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kabosu
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0.1
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- davafons
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubyzip
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '3.4'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '3.4'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: benchmark
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|