g2ps-torch 0.1.0__py3-none-any.whl
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.
- g2ps_torch/__init__.py +1 -0
- g2ps_torch/_resolve.py +35 -0
- g2ps_torch/models/nano/meta.pkl +0 -0
- g2ps_torch/models/nano/nano.pt +0 -0
- g2ps_torch/models/small/meta.pkl +0 -0
- g2ps_torch/models/tiny/meta.pkl +0 -0
- g2ps_torch/modules.py +192 -0
- g2ps_torch/runtime.py +107 -0
- g2ps_torch-0.1.0.dist-info/METADATA +6 -0
- g2ps_torch-0.1.0.dist-info/RECORD +12 -0
- g2ps_torch-0.1.0.dist-info/WHEEL +5 -0
- g2ps_torch-0.1.0.dist-info/top_level.txt +1 -0
g2ps_torch/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .runtime import G2pS
|
g2ps_torch/_resolve.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Tier auto-resolution: packaged weights first, then on-demand download."""
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import urllib.request
|
|
5
|
+
|
|
6
|
+
MODELS_DIR = os.path.join(os.path.dirname(__file__), 'models')
|
|
7
|
+
CACHE_DIR = os.environ.get('G2PS_CACHE', os.path.join(os.path.expanduser('~'), '.cache', 'g2ps'))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resolve_model_dir(model_dir, arch_keys, weights_name, urls):
|
|
11
|
+
"""model_dir may be a path, or a tier name ('nano'/'tiny'/'small')."""
|
|
12
|
+
if os.path.isdir(model_dir) and os.path.exists(os.path.join(model_dir, weights_name)):
|
|
13
|
+
return model_dir
|
|
14
|
+
tier = model_dir if model_dir in arch_keys else os.path.basename(os.path.normpath(model_dir))
|
|
15
|
+
if tier not in arch_keys:
|
|
16
|
+
raise ValueError(f"model_dir must be a path or one of {list(arch_keys)}, got {model_dir!r}")
|
|
17
|
+
pkg = os.path.join(MODELS_DIR, tier)
|
|
18
|
+
if os.path.exists(os.path.join(pkg, weights_name)):
|
|
19
|
+
return pkg
|
|
20
|
+
dst = os.path.join(CACHE_DIR, tier)
|
|
21
|
+
os.makedirs(dst, exist_ok=True)
|
|
22
|
+
if not os.path.exists(os.path.join(dst, 'meta.pkl')):
|
|
23
|
+
shutil.copy(os.path.join(pkg, 'meta.pkl'), os.path.join(dst, 'meta.pkl'))
|
|
24
|
+
wp = os.path.join(dst, weights_name)
|
|
25
|
+
if not os.path.exists(wp):
|
|
26
|
+
err = []
|
|
27
|
+
for url in urls:
|
|
28
|
+
try:
|
|
29
|
+
print(f'g2pS: downloading {url.rsplit("/", 1)[-1]} ({tier}) ...')
|
|
30
|
+
urllib.request.urlretrieve(url, wp)
|
|
31
|
+
return dst
|
|
32
|
+
except Exception as e: # noqa: BLE001
|
|
33
|
+
err.append(str(e)[:80])
|
|
34
|
+
raise RuntimeError('could not download weights from any mirror:\n' + '\n'.join(err))
|
|
35
|
+
return dst
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
g2ps_torch/modules.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Student model: modern small char-level encoder.
|
|
2
|
+
|
|
3
|
+
6 x 384 bidirectional transformer with RoPE / RMSNorm / SwiGLU (2024-style recipe),
|
|
4
|
+
candidate-masked readout at every labeled polyphone position.
|
|
5
|
+
"""
|
|
6
|
+
import math
|
|
7
|
+
|
|
8
|
+
import torch
|
|
9
|
+
import torch.nn as nn
|
|
10
|
+
import torch.nn.functional as F
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RMSNorm(nn.Module):
|
|
14
|
+
def __init__(self, d, eps=1e-6):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self.w = nn.Parameter(torch.ones(d))
|
|
17
|
+
self.eps = eps
|
|
18
|
+
|
|
19
|
+
def forward(self, x):
|
|
20
|
+
ms = x.float().pow(2).mean(-1, keepdim=True) # fp32 accumulation (fp16-safe)
|
|
21
|
+
return (self.w * (x.float() * torch.rsqrt(ms + self.eps))).to(x.dtype)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def rope_table(max_len, dim, base=10000.0, device='cpu', dtype=torch.float32):
|
|
25
|
+
inv = 1.0 / (base ** (torch.arange(0, dim, 2, device=device, dtype=torch.float64) / dim))
|
|
26
|
+
t = torch.arange(max_len, device=device, dtype=torch.float64)
|
|
27
|
+
angles = torch.outer(t, inv)
|
|
28
|
+
return torch.stack([torch.cos(angles), torch.sin(angles)], dim=-1).to(dtype) # (T, D/2, 2)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def apply_rope(x, rope):
|
|
32
|
+
"""x: (B, T, H, Dh); rope: (T, Dh/2, 2)"""
|
|
33
|
+
T = x.shape[1]
|
|
34
|
+
r = rope[:T].to(x.dtype) # (T, Dh/2, 2)
|
|
35
|
+
x1, x2 = x[..., 0::2], x[..., 1::2]
|
|
36
|
+
cos = r[..., 0].unsqueeze(0).unsqueeze(2) # (1, T, 1, Dh/2)
|
|
37
|
+
sin = r[..., 1].unsqueeze(0).unsqueeze(2)
|
|
38
|
+
o1 = x1 * cos - x2 * sin
|
|
39
|
+
o2 = x1 * sin + x2 * cos
|
|
40
|
+
return torch.stack((o1, o2), dim=-1).flatten(-2)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Attention(nn.Module):
|
|
44
|
+
def __init__(self, d, n_heads):
|
|
45
|
+
super().__init__()
|
|
46
|
+
self.n_heads = n_heads
|
|
47
|
+
self.dh = d // n_heads
|
|
48
|
+
self.qkv = nn.Linear(d, 3 * d, bias=False)
|
|
49
|
+
self.o = nn.Linear(d, d, bias=False)
|
|
50
|
+
|
|
51
|
+
def forward(self, x, mask, rope):
|
|
52
|
+
B, T, D = x.shape
|
|
53
|
+
q, k, v = self.qkv(x).split(D, dim=2)
|
|
54
|
+
q = q.view(B, T, self.n_heads, self.dh).transpose(1, 2)
|
|
55
|
+
k = k.view(B, T, self.n_heads, self.dh).transpose(1, 2)
|
|
56
|
+
v = v.view(B, T, self.n_heads, self.dh).transpose(1, 2)
|
|
57
|
+
q, k = apply_rope(q, rope), apply_rope(k, rope)
|
|
58
|
+
# mask: (B, T) bool True=valid -> (B,1,1,T) additive
|
|
59
|
+
att_mask = ((~mask).unsqueeze(1).unsqueeze(2) * -1e4).to(q.dtype) # (B,1,1,T)
|
|
60
|
+
y = F.scaled_dot_product_attention(q, k, v, attn_mask=att_mask)
|
|
61
|
+
y = y.transpose(1, 2).contiguous().view(B, T, D)
|
|
62
|
+
return self.o(y)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ConvStem(nn.Module):
|
|
66
|
+
"""depthwise conv k=3 with dilations 1/2/3 -> fused local n-gram features. ~3.5K params."""
|
|
67
|
+
def __init__(self, d):
|
|
68
|
+
super().__init__()
|
|
69
|
+
self.convs = nn.ModuleList([nn.Conv1d(d, d, 3, padding=dl, dilation=dl, groups=d) for dl in (1, 2, 3)])
|
|
70
|
+
self.norm = RMSNorm(d)
|
|
71
|
+
|
|
72
|
+
def forward(self, x):
|
|
73
|
+
# x: (B, T, D); padding-aware: zero pad chars already are 0-emb? mask conv beyond seq via padding zeros
|
|
74
|
+
h = x.transpose(1, 2) # (B, D, T)
|
|
75
|
+
hs = [c(h) for c in self.convs]
|
|
76
|
+
out = x + sum(hs).transpose(1, 2)
|
|
77
|
+
return self.norm(out)
|
|
78
|
+
|
|
79
|
+
class SwiGLU(nn.Module):
|
|
80
|
+
def __init__(self, d, hidden):
|
|
81
|
+
super().__init__()
|
|
82
|
+
self.w1 = nn.Linear(d, hidden, bias=False)
|
|
83
|
+
self.w2 = nn.Linear(d, hidden, bias=False)
|
|
84
|
+
self.w3 = nn.Linear(hidden, d, bias=False)
|
|
85
|
+
|
|
86
|
+
def forward(self, x):
|
|
87
|
+
return self.w3(F.silu(self.w1(x)) * self.w2(x))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Block(nn.Module):
|
|
91
|
+
def __init__(self, d, n_heads, ffn_hidden):
|
|
92
|
+
super().__init__()
|
|
93
|
+
self.n1 = RMSNorm(d)
|
|
94
|
+
self.attn = Attention(d, n_heads)
|
|
95
|
+
self.n2 = RMSNorm(d)
|
|
96
|
+
self.ffn = SwiGLU(d, ffn_hidden)
|
|
97
|
+
|
|
98
|
+
def forward(self, x, mask, rope):
|
|
99
|
+
x = x + self.attn(self.n1(x), mask, rope)
|
|
100
|
+
x = x + self.ffn(self.n2(x))
|
|
101
|
+
return x
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class StudentG2P(nn.Module):
|
|
105
|
+
def __init__(self, vocab_size, n_labels, n_poly_chars, d=384, n_layers=6,
|
|
106
|
+
n_heads=6, ffn_hidden=1024, max_len=128, dropout=0.1, use_conv_stem=True,
|
|
107
|
+
emb_dim=None, bias_rank=0, n_passes=1):
|
|
108
|
+
self.n_passes = n_passes
|
|
109
|
+
super().__init__()
|
|
110
|
+
rope = rope_table(max_len, d // n_heads)
|
|
111
|
+
self.register_buffer('rope', rope, persistent=False)
|
|
112
|
+
emb_dim = emb_dim or d
|
|
113
|
+
self.emb = nn.Embedding(vocab_size, emb_dim, padding_idx=0)
|
|
114
|
+
self.emb_proj = nn.Linear(emb_dim, d, bias=False) if emb_dim != d else nn.Identity()
|
|
115
|
+
self.stem = ConvStem(d) if use_conv_stem else nn.Identity()
|
|
116
|
+
self.drop = nn.Dropout(dropout)
|
|
117
|
+
self.blocks = nn.ModuleList([Block(d, n_heads, ffn_hidden)
|
|
118
|
+
for _ in range(n_layers)])
|
|
119
|
+
self.n_final = RMSNorm(d)
|
|
120
|
+
self.readout = nn.Linear(d, n_labels, bias=False)
|
|
121
|
+
# tone-factored auxiliary heads (set via set_tone_heads)
|
|
122
|
+
self.n_syl = 0
|
|
123
|
+
# per (poly char, label) bias; low-rank option for tiny models
|
|
124
|
+
if bias_rank > 0:
|
|
125
|
+
self.char_bias = nn.Sequential(
|
|
126
|
+
nn.Embedding(n_poly_chars, bias_rank),
|
|
127
|
+
nn.Linear(bias_rank, n_labels, bias=False),
|
|
128
|
+
)
|
|
129
|
+
else:
|
|
130
|
+
self.char_bias = nn.Embedding(n_poly_chars, n_labels)
|
|
131
|
+
nn.init.zeros_(self.char_bias[-1].weight if bias_rank > 0 else self.char_bias.weight)
|
|
132
|
+
self.pos_head = nn.Linear(d, 11)
|
|
133
|
+
self.apply(self._init)
|
|
134
|
+
|
|
135
|
+
def _init(self, m):
|
|
136
|
+
if isinstance(m, nn.Linear):
|
|
137
|
+
nn.init.normal_(m.weight, std=0.02)
|
|
138
|
+
if m.bias is not None:
|
|
139
|
+
nn.init.zeros_(m.bias)
|
|
140
|
+
|
|
141
|
+
def set_tone_heads(self, n_syl, n_tone=6):
|
|
142
|
+
import torch.nn as nn
|
|
143
|
+
self.n_syl = n_syl
|
|
144
|
+
dev = self.readout.weight.device
|
|
145
|
+
self.syl_head = nn.Linear(self.readout.in_features, n_syl).to(dev)
|
|
146
|
+
self.tone_head = nn.Linear(self.readout.in_features, n_tone).to(dev)
|
|
147
|
+
|
|
148
|
+
def init_bias_prior(self, counts):
|
|
149
|
+
"""counts: list (aligned with poly chars) of dict label_id -> count"""
|
|
150
|
+
import numpy as np
|
|
151
|
+
if isinstance(self.char_bias, nn.Sequential):
|
|
152
|
+
n = self.char_bias[0].weight.shape[0]
|
|
153
|
+
L = self.char_bias[-1].weight.shape[0]
|
|
154
|
+
else:
|
|
155
|
+
n = self.char_bias.weight.shape[0]
|
|
156
|
+
L = self.char_bias.weight.shape[1]
|
|
157
|
+
M = np.zeros((n, L), dtype=np.float32)
|
|
158
|
+
for i, d in enumerate(counts):
|
|
159
|
+
tot = sum(d.values()) + 1e-9
|
|
160
|
+
for j, c in d.items():
|
|
161
|
+
M[i, j] = math.log((c + 1.0) / (tot + len(d)))
|
|
162
|
+
if isinstance(self.char_bias, nn.Sequential):
|
|
163
|
+
U, S, Vh = np.linalg.svd(M, full_matrices=False)
|
|
164
|
+
r = self.char_bias[0].weight.shape[1]
|
|
165
|
+
emb = U[:, :r] * np.sqrt(S[:r])
|
|
166
|
+
lin = (np.sqrt(S[:r])[:, None] * Vh[:r]).T
|
|
167
|
+
with torch.no_grad():
|
|
168
|
+
self.char_bias[0].weight.copy_(torch.from_numpy(emb))
|
|
169
|
+
self.char_bias[-1].weight.copy_(torch.from_numpy(lin))
|
|
170
|
+
else:
|
|
171
|
+
with torch.no_grad():
|
|
172
|
+
self.char_bias.weight.copy_(torch.from_numpy(M))
|
|
173
|
+
|
|
174
|
+
def forward_with_ids(self, char_ids, poly_ids, positions, pos_mask, cand_mask):
|
|
175
|
+
pad = char_ids.ne(0)
|
|
176
|
+
x = self.emb_proj(self.emb(char_ids))
|
|
177
|
+
x = self.drop(x)
|
|
178
|
+
x = self.stem(x)
|
|
179
|
+
for blk in self.blocks:
|
|
180
|
+
x = blk(x, pad, self.rope)
|
|
181
|
+
h = self.n_final(x)
|
|
182
|
+
B, T, D = h.shape
|
|
183
|
+
P = positions.shape[1]
|
|
184
|
+
idx = positions.clamp(min=0).unsqueeze(-1).expand(B, P, D)
|
|
185
|
+
ph = torch.gather(h, 1, idx)
|
|
186
|
+
poly_ids_s = poly_ids.clamp(min=0)
|
|
187
|
+
logits = self.readout(ph) + self.char_bias(poly_ids_s)
|
|
188
|
+
masked = logits.masked_fill(~cand_mask, -1e4)
|
|
189
|
+
logp = F.log_softmax(masked.float(), dim=-1)
|
|
190
|
+
pos_logits = self.pos_head(ph)
|
|
191
|
+
extra = (self.syl_head(ph), self.tone_head(ph)) if self.n_syl else None
|
|
192
|
+
return logp, pos_logits, ph, masked, extra
|
g2ps_torch/runtime.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""g2pS PyTorch runtime — same API as the numpy runtime, with GPU (CUDA) support.
|
|
2
|
+
|
|
3
|
+
Deps: torch, numpy.
|
|
4
|
+
GPU: moves model+inputs to CUDA automatically when available. Set fp16=True for
|
|
5
|
+
half-precision inference (recommended on tensor-core GPUs).
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
import pickle
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import torch
|
|
12
|
+
|
|
13
|
+
from ._resolve import resolve_model_dir
|
|
14
|
+
|
|
15
|
+
from .modules import StudentG2P
|
|
16
|
+
|
|
17
|
+
MAX_LEN = 128
|
|
18
|
+
|
|
19
|
+
ARCH = {
|
|
20
|
+
'small': dict(d=384, n_layers=6, n_heads=6, ffn_hidden=1024, emb_dim=None, bias_rank=0),
|
|
21
|
+
'tiny': dict(d=256, n_layers=5, n_heads=4, ffn_hidden=640, emb_dim=128, bias_rank=64),
|
|
22
|
+
'nano': dict(d=96, n_layers=6, n_heads=4, ffn_hidden=256, emb_dim=48, bias_rank=16, n_passes=2),
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class G2pS:
|
|
27
|
+
_URLS = ['https://github.com/baicai-1145/g2pS-torch/raw/main/models/{t}/{t}.pt',
|
|
28
|
+
'https://huggingface.co/baicai1145/g2pS/resolve/main/torch_weights/{t}/{t}.pt']
|
|
29
|
+
|
|
30
|
+
def __init__(self, model_dir, tier=None, device=None, fp16=None):
|
|
31
|
+
tier = tier or (model_dir if model_dir in ARCH else None) or os.path.basename(os.path.normpath(model_dir))
|
|
32
|
+
model_dir = resolve_model_dir(model_dir, ARCH, f'{tier}.pt',
|
|
33
|
+
[u.format(t=tier) for u in self._URLS])
|
|
34
|
+
self.tier = tier
|
|
35
|
+
self.device = device or ('cuda' if torch.cuda.is_available() else 'cpu')
|
|
36
|
+
self.fp16 = (fp16 if fp16 is not None else self.device == 'cuda') and self.device == 'cuda'
|
|
37
|
+
|
|
38
|
+
meta = pickle.load(open(os.path.join(model_dir, 'meta.pkl'), 'rb'))
|
|
39
|
+
self.vocab = meta['vocab']
|
|
40
|
+
self.labels = meta['labels']
|
|
41
|
+
self.poly_id = {c: i for i, c in enumerate(meta['poly_chars'])}
|
|
42
|
+
self.char_cands = meta['char_cands']
|
|
43
|
+
self.n_labels = len(self.labels)
|
|
44
|
+
|
|
45
|
+
kw = dict(ARCH[tier])
|
|
46
|
+
n_passes = kw.pop('n_passes', 1)
|
|
47
|
+
self.model = StudentG2P(len(self.vocab), len(self.labels), len(meta['poly_chars']),
|
|
48
|
+
max_len=MAX_LEN, use_conv_stem=True, n_passes=n_passes, **kw)
|
|
49
|
+
sd = torch.load(os.path.join(model_dir, tier + '.pt'), map_location='cpu')
|
|
50
|
+
sd = {k[10:] if k.startswith('_orig_mod.') else k: v for k, v in sd.items()}
|
|
51
|
+
sd = {k: v for k, v in sd.items() if not k.startswith(('syl_head', 'tone_head'))}
|
|
52
|
+
self.model.load_state_dict(sd)
|
|
53
|
+
self.model.to(self.device)
|
|
54
|
+
if self.fp16:
|
|
55
|
+
self.model.half()
|
|
56
|
+
self.model.eval()
|
|
57
|
+
self.dtype = torch.float16 if self.fp16 else torch.float32
|
|
58
|
+
|
|
59
|
+
def _prepare(self, text):
|
|
60
|
+
text = text.lower()
|
|
61
|
+
positions = [i for i, c in enumerate(text) if c in self.poly_id]
|
|
62
|
+
if not positions:
|
|
63
|
+
return None
|
|
64
|
+
if len(text) > MAX_LEN:
|
|
65
|
+
first = positions[0]
|
|
66
|
+
start = max(0, min(first - MAX_LEN // 2, len(text) - MAX_LEN))
|
|
67
|
+
text = text[start:start + MAX_LEN]
|
|
68
|
+
positions = [p - start for p in positions if start <= p < start + MAX_LEN]
|
|
69
|
+
if not positions:
|
|
70
|
+
return None
|
|
71
|
+
char_ids = np.array([[self.vocab.get(c, 1) for c in text]], dtype=np.int64)
|
|
72
|
+
P = len(positions)
|
|
73
|
+
poly_ids = np.array([[self.poly_id[text[p]] for p in positions]], dtype=np.int64)
|
|
74
|
+
pos_arr = np.array([positions], dtype=np.int64)
|
|
75
|
+
cand = np.zeros((1, P, self.n_labels), dtype=bool)
|
|
76
|
+
for k, p in enumerate(positions):
|
|
77
|
+
cand[0, k, list(self.char_cands[text[p]])] = True
|
|
78
|
+
return text, positions, char_ids, poly_ids, pos_arr, cand
|
|
79
|
+
|
|
80
|
+
def predict(self, text):
|
|
81
|
+
prep = self._prepare(text)
|
|
82
|
+
if prep is None:
|
|
83
|
+
return {}, text
|
|
84
|
+
text, positions, char_ids, poly_ids, pos_arr, cand = prep
|
|
85
|
+
dev = self.device
|
|
86
|
+
with torch.no_grad():
|
|
87
|
+
logp, _, _, _, _ = self.model.forward_with_ids(
|
|
88
|
+
torch.as_tensor(char_ids, device=dev),
|
|
89
|
+
torch.as_tensor(poly_ids, device=dev),
|
|
90
|
+
torch.as_tensor(pos_arr, device=dev),
|
|
91
|
+
torch.ones(1, len(positions), dtype=torch.bool, device=dev),
|
|
92
|
+
torch.as_tensor(cand, device=dev))
|
|
93
|
+
pred = logp.argmax(-1)[0].cpu().numpy()
|
|
94
|
+
return {p: self.labels[int(pred[k])] for k, p in enumerate(positions)}, text
|
|
95
|
+
|
|
96
|
+
def convert(self, text):
|
|
97
|
+
res, t = self.predict(text)
|
|
98
|
+
return t, [(c, res.get(i)) for i, c in enumerate(t)]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
if __name__ == '__main__':
|
|
102
|
+
import sys
|
|
103
|
+
g = G2pS(sys.argv[1] if len(sys.argv) > 1 else 'models/nano')
|
|
104
|
+
print('device:', g.device, '| fp16:', g.fp16)
|
|
105
|
+
for s in ['他在银行工作,行踪不定。', '能把小孩哄睡是个技术活。']:
|
|
106
|
+
_, pairs = g.convert(s)
|
|
107
|
+
print(s, '->', [(c, p) for c, p in pairs if p])
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
g2ps_torch/__init__.py,sha256=ab4S7abmoWlWylOKA8ajspt8ir8tcUlGb1aiWt8lLKg,26
|
|
2
|
+
g2ps_torch/_resolve.py,sha256=_UtLV6jlFUsrsbPFs14tACY6HL6XJYsxo7erAYDEc3k,1595
|
|
3
|
+
g2ps_torch/modules.py,sha256=2TvSJF2fPqdQOtsNyONceiQ7ODleBam-RPUuPSgb9JM,7724
|
|
4
|
+
g2ps_torch/runtime.py,sha256=ooy-1weo2GVJKZ4DbiaspVi0l5Va3W7UwOmyezOUbGw,4660
|
|
5
|
+
g2ps_torch/models/nano/meta.pkl,sha256=oxziLhr2oZ_1aL1-5sGaT2VALiuCwOWdurRck3JDZ4U,77622
|
|
6
|
+
g2ps_torch/models/nano/nano.pt,sha256=5TlMLwDFY67JWC2LkXvBEHh46rBO4kwsxYK5q2fq4IE,4304251
|
|
7
|
+
g2ps_torch/models/small/meta.pkl,sha256=krEDH4PE5clMaGpNXLePhhoBQD_DuDsUvsdvuN1qlko,123832
|
|
8
|
+
g2ps_torch/models/tiny/meta.pkl,sha256=oxziLhr2oZ_1aL1-5sGaT2VALiuCwOWdurRck3JDZ4U,77622
|
|
9
|
+
g2ps_torch-0.1.0.dist-info/METADATA,sha256=kuAHN6Wf7p_GKKR3X94r4kzY6_5nsP4HeNThu7HvdRc,141
|
|
10
|
+
g2ps_torch-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
11
|
+
g2ps_torch-0.1.0.dist-info/top_level.txt,sha256=HZRCxz0yNEiD4E8LzWTFkFzqZqTEcAEAGtoIaVzwpts,11
|
|
12
|
+
g2ps_torch-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
g2ps_torch
|