Skip to content

Commit ac2d18e

Browse files
committed
Tests!
1 parent 9dee2ef commit ac2d18e

File tree

6 files changed

+114
-11
lines changed

6 files changed

+114
-11
lines changed

src/lighteval/metrics/imports/data_stats_metric.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from typing import Literal
3131

3232
from lighteval.metrics.imports.data_stats_utils import Fragments
33-
from lighteval.utils.imports import raise_if_package_not_available
33+
from lighteval.utils.imports import Extras, raise_if_package_not_available, requires
3434

3535

3636
logger = logging.getLogger(__name__)
@@ -55,6 +55,7 @@ def find_ngrams(input_list, n):
5555
return zip(*[input_list[i:] for i in range(n)])
5656

5757

58+
@requires(Extras.MULTILINGUAL)
5859
class DataStatsMetric(Metric):
5960
def __init__(
6061
self,

src/lighteval/metrics/normalizations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from typing import Callable
2929

3030
from lighteval.metrics.utils.linguistic_tokenizers import get_word_tokenizer
31+
from lighteval.utils.imports import Extras, requires
3132
from lighteval.utils.language import Language
3233

3334

@@ -444,6 +445,7 @@ def remove_punc(text: str) -> str:
444445
return "".join(ch for ch in text if ch not in PUNCT)
445446

446447

448+
@requires(Extras.MULTILINGUAL)
447449
def get_multilingual_normalizer(lang: Language, lower: bool = True) -> Callable[[str], str]:
448450
"""Get a normalizer function for the specified language.
449451

src/lighteval/metrics/utils/linguistic_tokenizers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from lighteval.utils.imports import (
2121
Extras,
2222
raise_if_package_not_available,
23+
requires,
2324
)
2425
from lighteval.utils.language import Language
2526

@@ -97,11 +98,10 @@ def span_tokenize(self, text: str) -> list[tuple[int, int]]:
9798
return list(self.tokenizer.span_tokenize(text))
9899

99100

101+
@requires(Extras.MULTILINGUAL)
100102
class SpaCyTokenizer(WordTokenizer):
101103
def __init__(self, spacy_language: str, config=None):
102104
super().__init__()
103-
raise_if_package_not_available(Extras.MULTILINGUAL, language=spacy_language)
104-
105105
self.spacy_language = spacy_language
106106
self.config = config
107107
self._tokenizer = None
@@ -135,6 +135,7 @@ def span_tokenize(self, text: str) -> list[tuple[int, int]]:
135135
]
136136

137137

138+
@requires("stanza")
138139
class StanzaTokenizer(WordTokenizer):
139140
def __init__(self, stanza_language: str, **stanza_kwargs):
140141
super().__init__()

src/lighteval/tasks/extended/ifbench/instructions.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@
2525

2626
import emoji
2727
import nltk
28-
import spacy
29-
import syllapy
28+
29+
from lighteval.utils.imports import is_package_available, requires
30+
31+
32+
if is_package_available("syllapy"):
33+
import syllapy
34+
35+
if is_package_available("spacy"):
36+
import spacy
3037

3138
import lighteval.tasks.extended.ifeval.instructions_utils as instructions_util
3239

@@ -61,6 +68,7 @@
6168
RESOURCES_DOWNLOADED: bool = False
6269

6370

71+
@requires("syllapy", "spacy")
6472
class Instruction:
6573
"""An instruction template."""
6674

src/lighteval/utils/imports.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,28 +53,30 @@ def is_multilingual_package_available(language: str):
5353
def raise_if_package_not_available(package_name: str | Extras, *, language: str = None, object_name: str = None):
5454
prefix = "You" if object_name is None else f"Through the use of {object_name}, you"
5555

56-
if package_name == Extras.MULTILINGUAL and not is_multilingual_package_available(language):
56+
if package_name == Extras.MULTILINGUAL and (
57+
(language is not None) or (not is_multilingual_package_available(language))
58+
):
5759
raise ImportError(prefix + not_installed_error_message(package_name)[3:])
5860

5961
if not is_package_available(package_name):
6062
raise ImportError(prefix + not_installed_error_message(package_name)[3:])
6163

6264

6365
def not_installed_error_message(package_name: str | Extras) -> str:
64-
if package_name == Extras.MULTILINGUAL:
66+
if package_name == Extras.MULTILINGUAL.value:
6567
return "You are trying to run an evaluation requiring multilingual capabilities. Please install the required extra: `pip install lighteval[multilingual]`"
66-
elif package_name == Extras.EXTENDED:
68+
elif package_name == Extras.EXTENDED.value:
6769
return "You are trying to run an evaluation requiring additional extensions. Please install the required extra: `pip install lighteval[extended] "
6870
elif package_name == "text_generation":
69-
return "You are trying to start a text generation inference endpoint, but TGI is not present in your local environement. Please install it using pip."
71+
return "You are trying to start a text generation inference endpoint, but TGI is not present in your local environment. Please install it using pip."
7072
elif package_name in ["bitsandbytes", "auto-gptq"]:
71-
return f"You are trying to load a model quantized with `{package_name}`, which is not available in your local environement. Please install it using pip."
73+
return f"You are trying to load a model quantized with `{package_name}`, which is not available in your local environment. Please install it using pip."
7274
elif package_name == "peft":
7375
return "You are trying to use adapter weights models, for which you need `peft`, which is not available in your environment. Please install it using pip."
7476
elif package_name == "openai":
7577
return "You are trying to use an Open AI LLM as a judge, for which you need `openai`, which is not available in your environment. Please install it using pip."
7678

77-
return f"You requested the use of `{package_name}` for this evaluation, but it is not available in your current environement. Please install it using pip."
79+
return f"You requested the use of `{package_name}` for this evaluation, but it is not available in your current environment. Please install it using pip."
7880

7981

8082
class DummyObject(type):

tests/test_dependencies.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# MIT License
2+
3+
# Copyright (c) 2024 The HuggingFace Team
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
# tests/utils/pretend_missing.py
24+
import functools
25+
import importlib
26+
27+
import pytest
28+
29+
import lighteval.utils.imports as imports
30+
31+
32+
def pretend_missing(*names):
33+
"""
34+
Decorator: pretend that certain packages are missing
35+
by patching mypkg.utils.is_package_available.
36+
"""
37+
38+
def decorator(test_func):
39+
@functools.wraps(test_func)
40+
def wrapper(*args, **kwargs):
41+
from unittest.mock import patch
42+
43+
def fake(name):
44+
return False if name in names else (importlib.util.find_spec(name) is not None)
45+
46+
with patch.object(imports, "is_package_available", side_effect=fake):
47+
# If your module caches results at import time, reload here
48+
import lighteval
49+
50+
importlib.reload(lighteval)
51+
52+
return test_func(*args, **kwargs)
53+
54+
return wrapper
55+
56+
return decorator
57+
58+
59+
@pretend_missing("langdetect")
60+
def test_langdetect_required_for_ifeval():
61+
from lighteval.main_accelerate import accelerate
62+
63+
with pytest.raises(
64+
ImportError,
65+
match="Through the use of ifeval_prompt, you requested the use of `langdetect` for this evaluation, but it is not available in your current environment. Please install it using pip.",
66+
):
67+
accelerate(model_args="model_name=gpt2,batch_size=1", tasks="extended|ifeval|0", max_samples=0)
68+
69+
70+
@pretend_missing("spacy", "stanza")
71+
def test_multilingual_required_for_xnli():
72+
from lighteval.main_accelerate import accelerate
73+
74+
with pytest.raises(
75+
ImportError,
76+
match="Through the use of get_multilingual_normalizer, you are trying to run an evaluation requiring multilingual capabilities. Please install the required extra: `pip install lighteval[multilingual]`",
77+
):
78+
accelerate(model_args="model_name=gpt2,batch_size=1", tasks="lighteval|xnli_zho_mcf|0", max_samples=0)
79+
80+
81+
@pretend_missing("vllm")
82+
def test_vllm_required_for_vllm_usage():
83+
from lighteval.main_vllm import vllm
84+
85+
with pytest.raises(
86+
ImportError,
87+
match="You requested the use of `vllm` for this evaluation, but it is not available in your current environment. Please install it using pip.'",
88+
):
89+
vllm(model_args="model_name=gpt2,batch_size=1", tasks="lighteval|xnli_zho_mcf|0", max_samples=0)

0 commit comments

Comments
 (0)