Skip to content

Commit 8c0f684

Browse files
authored
Merge pull request #1257 from PyThaiNLP/copilot/refactor-delayed-imports
Delay external dependency imports to class initialization
2 parents b9cbff4 + 9c7b341 commit 8c0f684

9 files changed

Lines changed: 72 additions & 51 deletions

File tree

pythainlp/augment/lm/fasttext.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66
import itertools
77

8-
from gensim.models.fasttext import FastText as FastText_gensim
9-
from gensim.models.keyedvectors import KeyedVectors
10-
118
from pythainlp.tokenize import word_tokenize
129

1310

@@ -20,6 +17,9 @@ class FastTextAug:
2017
def __init__(self, model_path: str):
2118
""":param str model_path: path of model file
2219
"""
20+
from gensim.models.fasttext import FastText as FastText_gensim
21+
from gensim.models.keyedvectors import KeyedVectors
22+
2323
if model_path.endswith(".bin"):
2424
self.model = FastText_gensim.load_facebook_vectors(model_path)
2525
elif model_path.endswith(".vec"):

pythainlp/augment/lm/wangchanberta.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
# SPDX-License-Identifier: Apache-2.0
44
from __future__ import annotations
55

6-
from transformers import (
7-
CamembertTokenizer,
8-
pipeline,
9-
)
10-
116
model_name = "airesearch/wangchanberta-base-att-spm-uncased"
127

138

149
class Thai2transformersAug:
1510
def __init__(self):
11+
from transformers import (
12+
CamembertTokenizer,
13+
pipeline,
14+
)
15+
1616
self.model_name = "airesearch/wangchanberta-base-att-spm-uncased"
1717
self.target_tokenizer = CamembertTokenizer
1818
self.tokenizer = CamembertTokenizer.from_pretrained(

pythainlp/coref/_fastcoref.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@
33
# SPDX-License-Identifier: Apache-2.0
44
from __future__ import annotations
55

6-
import spacy
7-
86

97
class FastCoref:
108
def __init__(
119
self,
1210
model_name,
13-
nlp=spacy.blank("th"),
11+
nlp=None,
1412
device: str = "cpu",
1513
type: str = "FCoref",
1614
) -> None:
1715
if type == "FCoref":
1816
from fastcoref import FCoref as _model
1917
else:
2018
from fastcoref import LingMessCoref as _model
19+
20+
if nlp is None:
21+
import spacy
22+
23+
nlp = spacy.blank("th")
24+
2125
self.model_name = model_name
2226
self.nlp = nlp
2327
self.model = _model(self.model_name, device=device, nlp=self.nlp)

pythainlp/coref/han_coref.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
# SPDX-License-Identifier: Apache-2.0
44
from __future__ import annotations
55

6-
import spacy
7-
86
from pythainlp.coref._fastcoref import FastCoref
97

108

119
class HanCoref(FastCoref):
12-
def __init__(self, device: str = "cpu", nlp=spacy.blank("th")) -> None:
10+
def __init__(self, device: str = "cpu", nlp=None) -> None:
1311
super().__init__(
1412
model_name="pythainlp/han-coref-v1.0", device=device, nlp=nlp
1513
)

pythainlp/parse/transformers_ud.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,22 @@
1212
from __future__ import annotations
1313

1414
import os
15-
from typing import List, Union
16-
17-
import numpy
18-
import torch
19-
import ufal.chu_liu_edmonds
20-
from transformers import (
21-
AutoConfig,
22-
AutoModelForQuestionAnswering,
23-
AutoModelForTokenClassification,
24-
AutoTokenizer,
25-
TokenClassificationPipeline,
26-
)
27-
from transformers.utils import cached_file
15+
from typing import Union
2816

2917

3018
class Parse:
3119
def __init__(
3220
self, model: str = "KoichiYasuoka/deberta-base-thai-ud-head"
3321
) -> None:
22+
from transformers import (
23+
AutoConfig,
24+
AutoModelForQuestionAnswering,
25+
AutoModelForTokenClassification,
26+
AutoTokenizer,
27+
TokenClassificationPipeline,
28+
)
29+
from transformers.utils import cached_file
30+
3431
if model is None:
3532
model = "KoichiYasuoka/deberta-base-thai-ud-head"
3633
self.tokenizer = AutoTokenizer.from_pretrained(model)
@@ -57,7 +54,11 @@ def __init__(
5754
model=t, tokenizer=self.tokenizer
5855
)
5956

60-
def __call__(self, text: str, tag: str = "str") -> Union[List[List[str]], str]:
57+
def __call__(self, text: str, tag: str = "str") -> Union[list[list[str]], str]:
58+
import numpy
59+
import torch
60+
import ufal.chu_liu_edmonds
61+
6162
w = [
6263
(t["start"], t["end"], t["entity_group"])
6364
for t in self.deprel(text)

pythainlp/summarize/keybert.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,21 @@
1414

1515
from collections import Counter
1616
from collections.abc import Iterable
17-
from typing import Optional, Union
18-
19-
import numpy as np
20-
from transformers import pipeline
17+
from typing import TYPE_CHECKING, Optional, Union
2118

2219
from pythainlp.corpus import thai_stopwords
2320
from pythainlp.tokenize import word_tokenize
2421

22+
if TYPE_CHECKING:
23+
import numpy as np
24+
2525

2626
class KeyBERT:
2727
def __init__(
2828
self, model_name: str = "airesearch/wangchanberta-base-att-spm-uncased"
2929
):
30+
from transformers import pipeline
31+
3032
self.ft_pipeline = pipeline(
3133
"feature-extraction",
3234
tokenizer=model_name,
@@ -136,8 +138,9 @@ def extract_keywords(
136138
return [kw for kw, _ in keywords]
137139

138140
def embed(self, docs: Union[str, list[str]]) -> np.ndarray:
139-
"""Create an embedding of each input in `docs` by averaging vectors from the last hidden layer.
140-
"""
141+
"""Create an embedding of each input in `docs` by averaging vectors from the last hidden layer."""
142+
import numpy as np
143+
141144
embs = self.ft_pipeline(docs)
142145
if isinstance(docs, str) or len(docs) == 1:
143146
# embed doc. return shape = [1, hidden_size]
@@ -206,6 +209,8 @@ def _rank_keywords(
206209
keywords: list[str],
207210
max_keywords: int,
208211
) -> list[tuple[str, float]]:
212+
import numpy as np
213+
209214
def l2_norm(v: np.ndarray) -> np.ndarray:
210215
vec_size = v.shape[1]
211216
result = np.divide(

pythainlp/summarize/mt5.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
from __future__ import annotations
88

9-
from transformers import MT5ForConditionalGeneration, T5Tokenizer
10-
119
from pythainlp.summarize import CPE_KMUTT_THAI_SENTENCE_SUM
1210

1311

@@ -38,6 +36,8 @@ def __init__(
3836
:param str pretrained_mt5_model_name: Name of pretrained model.
3937
If empty (default), uses google/mt5-{model_size}.
4038
"""
39+
from transformers import MT5ForConditionalGeneration, T5Tokenizer
40+
4141
model_name = ""
4242
if not pretrained_mt5_model_name:
4343
if model_size not in ["small", "base", "large", "xl", "xxl"]:

pythainlp/wangchanberta/core.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,24 @@
77
import warnings
88
from typing import Union
99

10-
from transformers import (
11-
CamembertTokenizer,
12-
pipeline,
13-
)
14-
1510
from pythainlp.tokenize import word_tokenize
1611

1712
_model_name = "wangchanberta-base-att-spm-uncased"
18-
_tokenizer = CamembertTokenizer.from_pretrained(
19-
f"airesearch/{_model_name}", revision="main"
20-
)
21-
if _model_name == "wangchanberta-base-att-spm-uncased":
22-
_tokenizer.additional_special_tokens = ["<s>NOTUSED", "</s>NOTUSED", "<_>"]
13+
_tokenizer = None
14+
15+
16+
def _get_tokenizer():
17+
"""Get the tokenizer, initializing it if necessary."""
18+
global _tokenizer
19+
if _tokenizer is None:
20+
from transformers import CamembertTokenizer
21+
22+
_tokenizer = CamembertTokenizer.from_pretrained(
23+
f"airesearch/{_model_name}", revision="main"
24+
)
25+
if _model_name == "wangchanberta-base-att-spm-uncased":
26+
_tokenizer.additional_special_tokens = ["<s>NOTUSED", "</s>NOTUSED", "<_>"]
27+
return _tokenizer
2328

2429

2530
class ThaiNameTagger:
@@ -33,11 +38,13 @@ def __init__(self, dataset_name: str = "thainer", grouped_entities: bool = True)
3338
* *thainer* - ThaiNER dataset
3439
:param bool grouped_entities: grouped entities
3540
"""
41+
from transformers import pipeline
42+
3643
self.dataset_name = dataset_name
3744
self.grouped_entities = grouped_entities
3845
self.classify_tokens = pipeline(
3946
task="ner",
40-
tokenizer=_tokenizer,
47+
tokenizer=_get_tokenizer(),
4148
model=f"airesearch/{_model_name}",
4249
revision=f"finetuned@{self.dataset_name}-ner",
4350
ignore_labels=[],
@@ -226,4 +233,4 @@ def segment(text: str) -> list[str]:
226233
if not text or not isinstance(text, str):
227234
return []
228235

229-
return _tokenizer.tokenize(text)
236+
return _get_tokenizer().tokenize(text)

pythainlp/word_vector/core.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
# SPDX-License-Identifier: Apache-2.0
44
from __future__ import annotations
55

6-
from gensim.models import KeyedVectors
7-
from gensim.models.keyedvectors import Word2VecKeyedVectors
8-
from numpy import ndarray, zeros
6+
from typing import TYPE_CHECKING
97

108
from pythainlp.corpus import get_corpus_path
119
from pythainlp.tokenize import thai2fit_tokenizer, word_tokenize
1210

11+
if TYPE_CHECKING:
12+
from gensim.models.keyedvectors import Word2VecKeyedVectors
13+
from numpy import ndarray
14+
1315
WV_DIM = 300 # word vector dimension
1416

1517
_MODEL_NAME = "thai2fit_wv"
@@ -48,6 +50,8 @@ def load_wordvector(self, model_name: str) -> None:
4850
4951
:param str model_name: model name
5052
"""
53+
from gensim.models import KeyedVectors
54+
5155
self.model_name = model_name
5256
self.model = KeyedVectors.load_word2vec_format(
5357
get_corpus_path(self.model_name),
@@ -290,6 +294,8 @@ def sentence_vectorizer(self, text: str, use_mean: bool = True) -> ndarray:
290294
0.40506999, 1.58591403, 0.63869202, -0.702155 , 1.62977601,
291295
4.52269109, -0.70760502, 0.50952601, -0.914392 , 0.70673105]])
292296
"""
297+
from numpy import zeros
298+
293299
vec = zeros((1, self.WV_DIM))
294300

295301
words = self.tokenize(text)

0 commit comments

Comments
 (0)