Add comprehensive detailed design documents
This commit is contained in:
659
src-python/docs/details/transliteration_transliterator.md
Normal file
659
src-python/docs/details/transliteration_transliterator.md
Normal file
@@ -0,0 +1,659 @@
|
||||
# transliteration_transliterator.py - 総合音写・転写システム
|
||||
|
||||
## 概要
|
||||
|
||||
SudachiPyを利用した日本語のローマ字転写システムのメインクラスです。形態素解析、漢字・送り仮名の分離、文脈依存ルールの適用、ヘボン式変換を統合し、高精度な日本語ローマ字化を提供します。
|
||||
|
||||
## 主要機能
|
||||
|
||||
### 統合転写システム
|
||||
- SudachiPyによる高精度形態素解析
|
||||
- 漢字・送り仮名の自動分離処理
|
||||
- 文脈依存読み変更ルールの適用
|
||||
|
||||
### 多層変換処理
|
||||
- カタカナ読み取得・分配
|
||||
- ひらがな自動変換
|
||||
- ヘボン式ローマ字生成
|
||||
|
||||
### 並行処理対応
|
||||
- スレッドセーフなトークナイザー利用
|
||||
- ロック機構による安全な並行実行
|
||||
- 高負荷環境での安定動作
|
||||
|
||||
## クラス構造
|
||||
|
||||
### Transliterator クラス
|
||||
```python
|
||||
class Transliterator:
|
||||
def __init__(self) -> None:
|
||||
self.tokenizer_obj: tokenizer.Tokenizer
|
||||
self.mode: tokenizer.Tokenizer.SplitMode
|
||||
self._tokenizer_lock: threading.Lock
|
||||
```
|
||||
|
||||
日本語転写処理の中核クラス
|
||||
|
||||
#### 属性
|
||||
- **tokenizer_obj**: SudachiPyトークナイザーインスタンス
|
||||
- **mode**: 分割モード(SplitMode.C = 最長一致)
|
||||
- **_tokenizer_lock**: 並行アクセス制御用ミューテックス
|
||||
|
||||
## 主要メソッド
|
||||
|
||||
### analyze
|
||||
|
||||
```python
|
||||
def analyze(self, text: str, use_macron: bool = False) -> List[Dict[str, Any]]
|
||||
```
|
||||
|
||||
テキストを解析して転写情報を生成
|
||||
|
||||
#### パラメータ
|
||||
- **text**: 解析対象の日本語テキスト
|
||||
- **use_macron**: マクロン使用フラグ(長音表記方式)
|
||||
|
||||
#### 戻り値
|
||||
- **List[Dict[str, Any]]**: トークン転写情報のリスト
|
||||
|
||||
#### 出力辞書構造
|
||||
```python
|
||||
{
|
||||
"orig": str, # 元の文字・文字列
|
||||
"kana": str, # カタカナ読み
|
||||
"hira": str, # ひらがな読み
|
||||
"hepburn": str # ヘボン式ローマ字
|
||||
}
|
||||
```
|
||||
|
||||
### split_kanji_okurigana (静的メソッド)
|
||||
|
||||
```python
|
||||
@staticmethod
|
||||
def split_kanji_okurigana(surface: str, reading_kana: str, use_macron: bool = True) -> List[Dict[str, str]]
|
||||
```
|
||||
|
||||
単語の表層形と読みを漢字・送り仮名ブロックに分割
|
||||
|
||||
#### パラメータ
|
||||
- **surface**: 表層形(漢字+ひらがな混在可能)
|
||||
- **reading_kana**: 全体のカタカナ読み
|
||||
- **use_macron**: ヘボン式変換でのマクロン使用
|
||||
|
||||
#### 戻り値
|
||||
- **List[Dict[str, str]]**: 分割された部分の転写情報
|
||||
|
||||
## 補助メソッド
|
||||
|
||||
### is_kanji (静的メソッド)
|
||||
|
||||
```python
|
||||
@staticmethod
|
||||
def is_kanji(ch: str) -> bool
|
||||
```
|
||||
|
||||
文字が漢字かどうかを判定
|
||||
|
||||
#### パラメータ
|
||||
- **ch**: 判定対象文字
|
||||
|
||||
#### 戻り値
|
||||
- **bool**: 漢字判定結果
|
||||
|
||||
### kata_to_hira (静的メソッド)
|
||||
|
||||
```python
|
||||
@staticmethod
|
||||
def kata_to_hira(text: str) -> str
|
||||
```
|
||||
|
||||
カタカナをひらがなに変換
|
||||
|
||||
#### パラメータ
|
||||
- **text**: 変換対象のカタカナテキスト
|
||||
|
||||
#### 戻り値
|
||||
- **str**: ひらがな変換結果
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 基本的な転写処理
|
||||
|
||||
```python
|
||||
from models.transliteration.transliteration_transliterator import Transliterator
|
||||
|
||||
# 転写システムの初期化
|
||||
transliterator = Transliterator()
|
||||
|
||||
# 基本的な文章の転写
|
||||
text = "向こうへ行く"
|
||||
results = transliterator.analyze(text)
|
||||
|
||||
for token in results:
|
||||
print(f"{token['orig']} -> {token['kana']} -> {token['hira']} -> {token['hepburn']}")
|
||||
|
||||
# 期待される出力例:
|
||||
# 向こう -> ムコウ -> むこう -> mukou
|
||||
# へ -> ヘ -> へ -> he
|
||||
# 行く -> イク -> いく -> iku
|
||||
```
|
||||
|
||||
### マクロン使用の長音処理
|
||||
|
||||
```python
|
||||
# マクロンを使用した長音表記
|
||||
text = "東京に行く"
|
||||
results_macron = transliterator.analyze(text, use_macron=True)
|
||||
results_normal = transliterator.analyze(text, use_macron=False)
|
||||
|
||||
print("=== マクロンあり ===")
|
||||
for token in results_macron:
|
||||
print(f"{token['orig']} -> {token['hepburn']}")
|
||||
|
||||
print("=== マクロンなし ===")
|
||||
for token in results_normal:
|
||||
print(f"{token['orig']} -> {token['hepburn']}")
|
||||
|
||||
# 期待される出力:
|
||||
# === マクロンあり ===
|
||||
# 東京 -> tōkyō
|
||||
# に -> ni
|
||||
# 行く -> iku
|
||||
|
||||
# === マクロンなし ===
|
||||
# 東京 -> toukyou
|
||||
# に -> ni
|
||||
# 行く -> iku
|
||||
```
|
||||
|
||||
### 複雑な文章の処理
|
||||
|
||||
```python
|
||||
# 漢字・ひらがな・カタカナ・英語混在文の処理
|
||||
complex_text = "パーティーで美しい花を見る"
|
||||
results = transliterator.analyze(complex_text, use_macron=True)
|
||||
|
||||
for token in results:
|
||||
print(f"原文: '{token['orig']}'")
|
||||
print(f" カナ: {token['kana']}")
|
||||
print(f" ひら: {token['hira']}")
|
||||
print(f" ローマ: {token['hepburn']}")
|
||||
print()
|
||||
|
||||
# 期待される出力:
|
||||
# 原文: 'パーティー'
|
||||
# カナ: パーティー
|
||||
# ひら: ぱーてぃー
|
||||
# ローマ: pātī
|
||||
#
|
||||
# 原文: 'で'
|
||||
# カナ: デ
|
||||
# ひら: で
|
||||
# ローマ: de
|
||||
#
|
||||
# 原文: '美しい'
|
||||
# カナ: ウツクシイ
|
||||
# ひら: うつくしい
|
||||
# ローマ: utsukushii
|
||||
```
|
||||
|
||||
### 文脈依存ルールの効果確認
|
||||
|
||||
```python
|
||||
# 文脈に依存する読み変更の例(「何」の読み分け)
|
||||
test_cases = [
|
||||
"何が好き?", # 何 -> ナニ (後続が「ガ」)
|
||||
"何度も挑戦", # 何 -> ナン (後続が「ド」)
|
||||
"何色ありますか?" # 何 -> ナニ (後続が「イ」)
|
||||
]
|
||||
|
||||
for text in test_cases:
|
||||
results = transliterator.analyze(text)
|
||||
|
||||
print(f"入力: {text}")
|
||||
|
||||
# 「何」トークンを探して読みを確認
|
||||
for token in results:
|
||||
if token['orig'] == '何':
|
||||
print(f"「何」の読み: {token['kana']} -> {token['hepburn']}")
|
||||
break
|
||||
print()
|
||||
|
||||
# 期待される出力:
|
||||
# 入力: 何が好き?
|
||||
# 「何」の読み: ナニ -> nani
|
||||
#
|
||||
# 入力: 何度も挑戦
|
||||
# 「何」の読み: ナン -> nan
|
||||
#
|
||||
# 入力: 何色ありますか?
|
||||
# 「何」の読み: ナニ -> nani
|
||||
```
|
||||
|
||||
### 特殊文字・記号の処理
|
||||
|
||||
```python
|
||||
# 記号・英数字混在テキストの処理
|
||||
mixed_text = "ID:12345、URL:https://example.com"
|
||||
results = transliterator.analyze(mixed_text)
|
||||
|
||||
for token in results:
|
||||
print(f"'{token['orig']}' -> '{token['hepburn']}'")
|
||||
|
||||
# 期待される出力:
|
||||
# 'ID' -> 'ID' # 英字はそのまま
|
||||
# ':' -> ':' # 記号はそのまま
|
||||
# '12345' -> '12345' # 数字はそのまま
|
||||
# '、' -> '、' # 区切り記号はそのまま
|
||||
# 'URL' -> 'URL' # 英字はそのまま
|
||||
```
|
||||
|
||||
## 内部処理フロー
|
||||
|
||||
### 解析処理パイプライン
|
||||
|
||||
```python
|
||||
def analyze_pipeline_explained(self, text):
|
||||
"""転写処理パイプラインの詳細説明"""
|
||||
|
||||
# 1. SudachiPy形態素解析
|
||||
with self._tokenizer_lock:
|
||||
tokens = self.tokenizer_obj.tokenize(text, self.mode)
|
||||
|
||||
results = []
|
||||
|
||||
# 2. 各トークンの処理
|
||||
for token in tokens:
|
||||
surface = token.surface() # 表層形
|
||||
reading = token.reading_form() # 読み(カタカナ)
|
||||
pos = token.part_of_speech() # 品詞情報
|
||||
|
||||
# 3. 記号・空白の特別処理
|
||||
if pos and pos[0] in ["記号", "補助記号", "空白"]:
|
||||
reading = surface # 記号は表層形をそのまま使用
|
||||
|
||||
# 4. 表層形と読みが同じ場合(ひらがな・記号等)
|
||||
if surface == reading:
|
||||
results.append({
|
||||
"orig": surface,
|
||||
"kana": reading,
|
||||
"hira": surface, # そのまま
|
||||
"hepburn": surface # そのまま
|
||||
})
|
||||
continue
|
||||
|
||||
# 5. 単一文字の処理
|
||||
if len(surface) == 1:
|
||||
results.append({
|
||||
"orig": surface,
|
||||
"kana": reading,
|
||||
"hira": self.kata_to_hira(reading),
|
||||
"hepburn": katakana_to_hepburn(reading, use_macron)
|
||||
})
|
||||
else:
|
||||
# 6. 複数文字の漢字・送り仮名分離
|
||||
parts = self.split_kanji_okurigana(surface, reading, use_macron)
|
||||
results.extend(parts)
|
||||
|
||||
# 7. 文脈依存ルールの適用
|
||||
try:
|
||||
results = apply_context_rules(results, use_macron) or results
|
||||
except Exception:
|
||||
pass # ルール適用失敗時は元の結果を使用
|
||||
|
||||
# 8. ルール適用後の再計算
|
||||
for entry in results:
|
||||
kana = entry.get("kana", "")
|
||||
if kana:
|
||||
entry["hira"] = self.kata_to_hira(kana)
|
||||
entry["hepburn"] = katakana_to_hepburn(kana, use_macron)
|
||||
|
||||
return results
|
||||
```
|
||||
|
||||
### 漢字・送り仮名分離アルゴリズム
|
||||
|
||||
```python
|
||||
def split_algorithm_explained(surface, reading_kana):
|
||||
"""分離アルゴリズムの詳細説明"""
|
||||
|
||||
# 1. 表層形のブロック分割
|
||||
blocks = []
|
||||
current_block = ""
|
||||
prev_is_kanji = None
|
||||
|
||||
for char in surface:
|
||||
is_kanji = Transliterator.is_kanji(char)
|
||||
|
||||
if prev_is_kanji is None or is_kanji == prev_is_kanji:
|
||||
# 同じタイプの文字は同じブロックに
|
||||
current_block += char
|
||||
else:
|
||||
# タイプが変わったら新しいブロック
|
||||
blocks.append((prev_is_kanji, current_block))
|
||||
current_block = char
|
||||
|
||||
prev_is_kanji = is_kanji
|
||||
|
||||
if current_block:
|
||||
blocks.append((prev_is_kanji, current_block))
|
||||
|
||||
# 例: "向こう" -> [(True, "向"), (False, "こう")]
|
||||
# "行く" -> [(True, "行"), (False, "く")]
|
||||
|
||||
# 2. 読みの分配
|
||||
kana_len = len(reading_kana)
|
||||
|
||||
# 初期割当: 各ブロックの文字数に比例
|
||||
allocations = [len(block_text) for _, block_text in blocks]
|
||||
allocated_total = sum(allocations)
|
||||
remaining = kana_len - allocated_total
|
||||
|
||||
# 3. 余った読みの分配(漢字ブロック優先)
|
||||
if remaining > 0:
|
||||
# まず漢字ブロックに分配
|
||||
for i, (is_kanji, _) in enumerate(blocks):
|
||||
if remaining <= 0:
|
||||
break
|
||||
if is_kanji:
|
||||
allocations[i] += 1
|
||||
remaining -= 1
|
||||
|
||||
# まだ余りがある場合は左から順に分配
|
||||
i = 0
|
||||
while remaining > 0 and len(blocks) > 0:
|
||||
allocations[i] += 1
|
||||
remaining -= 1
|
||||
i = (i + 1) % len(blocks)
|
||||
|
||||
# 4. 読みが不足している場合は右から削減
|
||||
if remaining < 0:
|
||||
need_to_remove = -remaining
|
||||
i = len(blocks) - 1
|
||||
|
||||
while need_to_remove > 0 and i >= 0:
|
||||
can_remove = max(0, allocations[i] - 1)
|
||||
remove_amount = min(can_remove, need_to_remove)
|
||||
allocations[i] -= remove_amount
|
||||
need_to_remove -= remove_amount
|
||||
i -= 1
|
||||
|
||||
# 5. 最終的な読み分配
|
||||
pos = 0
|
||||
result = []
|
||||
|
||||
for (is_kanji, block_text), allocation in zip(blocks, allocations):
|
||||
block_reading = reading_kana[pos:pos + allocation]
|
||||
pos += allocation
|
||||
|
||||
result.append({
|
||||
"orig": block_text,
|
||||
"kana": block_reading,
|
||||
"hira": Transliterator.kata_to_hira(block_reading),
|
||||
"hepburn": katakana_to_hepburn(block_reading, use_macron)
|
||||
})
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
## 並行処理・スレッドセーフティ
|
||||
|
||||
### ロック機構
|
||||
|
||||
```python
|
||||
class ThreadSafeUsage:
|
||||
"""スレッドセーフな使用例"""
|
||||
|
||||
def __init__(self):
|
||||
self.transliterator = Transliterator()
|
||||
|
||||
def process_texts_concurrently(self, texts):
|
||||
"""複数テキストの並行処理"""
|
||||
import concurrent.futures
|
||||
|
||||
def process_single(text):
|
||||
return self.transliterator.analyze(text)
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
|
||||
# 内部のロック機構により安全に並行実行
|
||||
futures = [executor.submit(process_single, text) for text in texts]
|
||||
results = [f.result() for f in futures]
|
||||
|
||||
return results
|
||||
|
||||
# 使用例
|
||||
processor = ThreadSafeUsage()
|
||||
texts = ["東京に行く", "大阪で食事", "名古屋を観光", "福岡に宿泊"]
|
||||
results = processor.process_texts_concurrently(texts)
|
||||
|
||||
for i, result in enumerate(results):
|
||||
print(f"テキスト{i+1}: {texts[i]}")
|
||||
for token in result:
|
||||
print(f" {token['orig']} -> {token['hepburn']}")
|
||||
```
|
||||
|
||||
### パフォーマンス考慮事項
|
||||
|
||||
```python
|
||||
# 大量テキスト処理のベストプラクティス
|
||||
def efficient_batch_processing(texts, batch_size=100):
|
||||
"""効率的なバッチ処理"""
|
||||
|
||||
transliterator = Transliterator()
|
||||
results = []
|
||||
|
||||
for i in range(0, len(texts), batch_size):
|
||||
batch = texts[i:i + batch_size]
|
||||
|
||||
batch_results = []
|
||||
for text in batch:
|
||||
# 各テキストを個別に処理(ロック制御あり)
|
||||
result = transliterator.analyze(text)
|
||||
batch_results.append(result)
|
||||
|
||||
results.extend(batch_results)
|
||||
|
||||
# バッチ間で少し休憩(メモリ管理)
|
||||
if len(results) % 1000 == 0:
|
||||
print(f"処理済み: {len(results)} テキスト")
|
||||
|
||||
return results
|
||||
```
|
||||
|
||||
## エラーハンドリング
|
||||
|
||||
### 例外処理
|
||||
|
||||
```python
|
||||
def safe_analyze(text):
|
||||
"""安全な解析処理"""
|
||||
|
||||
transliterator = Transliterator()
|
||||
|
||||
try:
|
||||
results = transliterator.analyze(text)
|
||||
return results, None
|
||||
|
||||
except RuntimeError as e:
|
||||
if "Already borrowed" in str(e):
|
||||
# SudachiPyの並行アクセスエラー
|
||||
print("並行アクセスエラーが発生しました。リトライします。")
|
||||
return None, "RETRY_NEEDED"
|
||||
else:
|
||||
print(f"実行時エラー: {e}")
|
||||
return None, "RUNTIME_ERROR"
|
||||
|
||||
except Exception as e:
|
||||
print(f"予期しないエラー: {e}")
|
||||
return None, "UNKNOWN_ERROR"
|
||||
|
||||
# 使用例(リトライ機構付き)
|
||||
def analyze_with_retry(text, max_retries=3):
|
||||
"""リトライ機構付き解析"""
|
||||
|
||||
for attempt in range(max_retries):
|
||||
results, error = safe_analyze(text)
|
||||
|
||||
if results is not None:
|
||||
return results
|
||||
|
||||
if error == "RETRY_NEEDED":
|
||||
print(f"リトライ {attempt + 1}/{max_retries}")
|
||||
import time
|
||||
time.sleep(0.1 * (attempt + 1)) # 指数バックオフ
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
# 全てのリトライが失敗した場合のフォールバック
|
||||
print("解析に失敗しました。フォールバック処理を実行します。")
|
||||
return [{"orig": text, "kana": text, "hira": text, "hepburn": text}]
|
||||
```
|
||||
|
||||
## 設定・カスタマイズ
|
||||
|
||||
### SudachiPy設定
|
||||
|
||||
```python
|
||||
# カスタムSudachiPy設定での初期化
|
||||
class CustomTransliterator(Transliterator):
|
||||
def __init__(self, dict_type="full", split_mode="C"):
|
||||
"""カスタム設定での初期化"""
|
||||
|
||||
# 辞書タイプの選択
|
||||
dict_types = {
|
||||
"small": dictionary.Dictionary.create(dict_type="small"),
|
||||
"core": dictionary.Dictionary.create(dict_type="core"),
|
||||
"full": dictionary.Dictionary.create(dict_type="full")
|
||||
}
|
||||
|
||||
self.tokenizer_obj = dict_types.get(dict_type, dict_types["full"])
|
||||
|
||||
# 分割モードの選択
|
||||
split_modes = {
|
||||
"A": tokenizer.Tokenizer.SplitMode.A, # 短い単位
|
||||
"B": tokenizer.Tokenizer.SplitMode.B, # 中間単位
|
||||
"C": tokenizer.Tokenizer.SplitMode.C # 長い単位(デフォルト)
|
||||
}
|
||||
|
||||
self.mode = split_modes.get(split_mode, split_modes["C"])
|
||||
self._tokenizer_lock = threading.Lock()
|
||||
|
||||
# 使用例
|
||||
# 短い単位での分割を使用
|
||||
small_unit_transliterator = CustomTransliterator(dict_type="core", split_mode="A")
|
||||
|
||||
text = "取り敢えず検索してみる"
|
||||
results = small_unit_transliterator.analyze(text)
|
||||
|
||||
for token in results:
|
||||
print(f"{token['orig']} -> {token['hepburn']}")
|
||||
```
|
||||
|
||||
## テスト・デバッグ
|
||||
|
||||
### 包括的テストセット
|
||||
|
||||
```python
|
||||
def run_comprehensive_tests():
|
||||
"""包括的な機能テスト"""
|
||||
|
||||
transliterator = Transliterator()
|
||||
|
||||
test_cases = [
|
||||
# 基本的な文章
|
||||
("向こうへ行く", "向こう", "ムコウ"),
|
||||
("美しい花", "美しい", "ウツクシイ"),
|
||||
|
||||
# 文脈依存
|
||||
("何度も", "何", "ナン"),
|
||||
("何が", "何", "ナニ"),
|
||||
|
||||
# 外来語
|
||||
("パーティー", "パーティー", "パーティー"),
|
||||
("コンピューター", "コンピューター", "コンピューター"),
|
||||
|
||||
# 漢字・送り仮名
|
||||
("取り敢えず", "取り", "トリ"),
|
||||
("見知らぬ", "見知ら", "ミシラ"),
|
||||
|
||||
# 記号・英数字
|
||||
("ID:12345", "ID", "ID"),
|
||||
("SessionIDを取得", "SessionID", "SessionID")
|
||||
]
|
||||
|
||||
for text, target_orig, expected_kana in test_cases:
|
||||
results = transliterator.analyze(text)
|
||||
|
||||
# 対象トークンを検索
|
||||
target_token = None
|
||||
for token in results:
|
||||
if token['orig'] == target_orig:
|
||||
target_token = token
|
||||
break
|
||||
|
||||
if target_token:
|
||||
actual_kana = target_token['kana']
|
||||
status = "✓" if actual_kana == expected_kana else "✗"
|
||||
print(f"{status} {text}: {target_orig} -> {actual_kana} (期待値: {expected_kana})")
|
||||
else:
|
||||
print(f"✗ {text}: トークン '{target_orig}' が見つかりません")
|
||||
|
||||
run_comprehensive_tests()
|
||||
```
|
||||
|
||||
## 依存関係
|
||||
|
||||
### 必須依存関係
|
||||
- `sudachipy`: 形態素解析エンジン
|
||||
- `threading`: 並行制御
|
||||
- `typing`: 型ヒント
|
||||
|
||||
### 内部モジュール依存
|
||||
- `transliteration_kana_to_hepburn`: ヘボン式変換
|
||||
- `transliteration_context_rules`: 文脈依存ルール
|
||||
|
||||
### システム要件
|
||||
- Python 3.7以上
|
||||
- SudachiPy辞書ファイル(自動ダウンロード)
|
||||
- 十分なメモリ(辞書読み込み用)
|
||||
|
||||
## 注意事項・制限
|
||||
|
||||
### 処理精度の制限
|
||||
- 形態素解析結果に依存
|
||||
- 未知語・固有名詞は読み推定
|
||||
- 文脈によっては不正確な分割
|
||||
|
||||
### パフォーマンス制限
|
||||
- 初回実行時の辞書読み込み時間
|
||||
- 大量テキスト処理時のメモリ使用量
|
||||
- 並行アクセス時のロック待機
|
||||
|
||||
### 出力形式の制限
|
||||
```python
|
||||
# 現在サポートしていない機能
|
||||
unsupported_features = [
|
||||
"アクセント記号(音調)",
|
||||
"方言・古語の特殊読み",
|
||||
"人名・地名の特殊読み",
|
||||
"外国語の音写(中国語・韓国語等)",
|
||||
"カスタム読み辞書",
|
||||
"品詞情報の出力"
|
||||
]
|
||||
```
|
||||
|
||||
## 関連モジュール
|
||||
|
||||
- `transliteration_kana_to_hepburn.py`: ヘボン式変換処理
|
||||
- `transliteration_context_rules.py`: 文脈依存ルール適用
|
||||
- `config.py`: システム設定管理
|
||||
- `utils.py`: ユーティリティ関数
|
||||
|
||||
## 将来の改善点
|
||||
|
||||
- カスタム読み辞書対応
|
||||
- より高精度な文脈解析
|
||||
- 他言語音写システムとの統合
|
||||
- リアルタイム処理最適化
|
||||
- 分散処理対応
|
||||
Reference in New Issue
Block a user