diff --git a/optimum/intel/utils/import_utils.py b/optimum/intel/utils/import_utils.py index b982d1c746..b7ebdc3652 100644 --- a/optimum/intel/utils/import_utils.py +++ b/optimum/intel/utils/import_utils.py @@ -183,6 +183,15 @@ _sentence_transformers_available = False +_langchain_hf_available = importlib.util.find_spec("langchain_huggingface") is not None +_langchain_hf_version = "N/A" +if _langchain_hf_available: + try: + _langchain_hf_version = importlib.metadata.version("langchain_huggingface") + except importlib.metadata.PackageNotFoundError: + _langchain_hf_available = False + + def is_transformers_available(): return _transformers_available diff --git a/setup.py b/setup.py index ab9226dcc2..663528ef9c 100644 --- a/setup.py +++ b/setup.py @@ -58,6 +58,7 @@ "peft", "datasets[audio]>=1.4.0", "tbb", + "langchain-huggingface", ] QUALITY_REQUIRE = ["black~=23.1", "ruff==0.4.4"] diff --git a/tests/ipex/test_modeling.py b/tests/ipex/test_modeling.py index 419e1bb42a..7bff39147e 100644 --- a/tests/ipex/test_modeling.py +++ b/tests/ipex/test_modeling.py @@ -21,6 +21,7 @@ import numpy as np import requests import torch +from typing import Generator from parameterized import parameterized from PIL import Image from transformers import ( @@ -34,6 +35,7 @@ pipeline, set_seed, ) +from packaging import version from optimum.intel import ( IPEXModel, IPEXModelForAudioClassification, @@ -47,7 +49,12 @@ IPEXSentenceTransformer, ) from optimum.utils.testing_utils import grid_parameters, require_sentence_transformers -from optimum.intel.utils.import_utils import is_sentence_transformers_available, is_torch_version +from optimum.intel.utils.import_utils import ( + is_sentence_transformers_available, + is_torch_version, + _langchain_hf_available, + _langchain_hf_version, +) if is_sentence_transformers_available(): from sentence_transformers import SentenceTransformer @@ -707,3 +714,54 @@ def test_sentence_transformers_save_and_infer(self, model_arch): model = IPEXSentenceTransformer(tmpdirname, model_kwargs={"subfolder": "ipex"}) sentences = ["This is an example sentence", "Each sentence is converted"] model.encode(sentences) + + @parameterized.expand(SUPPORTED_ARCHITECTURES) + @require_sentence_transformers + @unittest.skipIf( + not _langchain_hf_available or version.parse(_langchain_hf_version) <= version.parse("0.1.2"), + reason="Unsupported langchain version", + ) + def test_langchain(self, model_arch): + from langchain_huggingface import HuggingFaceEmbeddings + + model_id = MODEL_NAMES[model_arch] + model_kwargs = {"device": "cpu", "backend": "ipex"} + + embedding = HuggingFaceEmbeddings( + model_name=model_id, + model_kwargs=model_kwargs, + ) + output = embedding.embed_query("foo bar") + self.assertTrue(len(output) > 0) + + +class IPEXLangchainTest(unittest.TestCase): + SUPPORTED_ARCHITECTURES = ("gpt2",) + + @parameterized.expand(SUPPORTED_ARCHITECTURES) + @unittest.skipIf( + not _langchain_hf_available or version.parse(_langchain_hf_version) <= version.parse("0.1.2"), + reason="Unsupported langchain version", + ) + def test_huggingface_pipeline_streaming(self, model_arch): + from langchain_huggingface import HuggingFacePipeline + + model_id = MODEL_NAMES[model_arch] + + hf_pipe = HuggingFacePipeline.from_model_id( + model_id=model_id, + task="text-generation", + pipeline_kwargs={"max_new_tokens": 10}, + backend="ipex", + ) + + generator = hf_pipe.stream("Q: How do you say 'hello' in German? A:'", stop=["."]) + + self.assertIsInstance(generator, Generator) + + stream_results_string = "" + for chunk in generator: + self.assertIsInstance(chunk, str) + stream_results_string = chunk + + self.assertTrue(len(stream_results_string.strip()) > 1) diff --git a/tests/openvino/test_modeling.py b/tests/openvino/test_modeling.py index 9da0069706..57d4b64764 100644 --- a/tests/openvino/test_modeling.py +++ b/tests/openvino/test_modeling.py @@ -20,7 +20,7 @@ import time import unittest from pathlib import Path -from typing import Dict +from typing import Dict, Generator import numpy as np import open_clip @@ -107,7 +107,11 @@ _print_compiled_model_properties, ) from optimum.intel.pipelines import pipeline as optimum_pipeline -from optimum.intel.utils.import_utils import is_openvino_version, is_transformers_version +from optimum.intel.utils.import_utils import ( + _langchain_hf_available, + is_openvino_version, + is_transformers_version, +) from optimum.intel.utils.modeling_utils import _find_files_matching_pattern from optimum.utils import ( DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER, @@ -2796,3 +2800,50 @@ def test_sentence_transformers_save_and_infer(self, model_arch): sentences = ["This is an example sentence", "Each sentence is converted"] model.encode(sentences) gc.collect() + + @parameterized.expand(SUPPORTED_ARCHITECTURES) + @unittest.skipIf(not _langchain_hf_available, reason="langchain not installed") + def test_langchain(self, model_arch): + from langchain_huggingface import HuggingFaceEmbeddings + + model_id = MODEL_NAMES[model_arch] + model_kwargs = {"device": "cpu", "backend": "openvino"} + + embedding = HuggingFaceEmbeddings( + model_name=model_id, + model_kwargs=model_kwargs, + ) + output = embedding.embed_query("foo bar") + self.assertTrue(len(output) > 0) + + +class OVLangchainTest(unittest.TestCase): + SUPPORTED_ARCHITECTURES = ("gpt2",) + + @parameterized.expand(SUPPORTED_ARCHITECTURES) + @unittest.skipIf(not _langchain_hf_available, reason="langchain not installed") + def test_huggingface_pipeline_streaming(self, model_arch): + from langchain_huggingface import HuggingFacePipeline + + model_id = MODEL_NAMES[model_arch] + + hf_pipe = HuggingFacePipeline.from_model_id( + model_id=model_id, + task="text-generation", + pipeline_kwargs={"max_new_tokens": 10}, + backend="openvino", + ) + + generator = hf_pipe.stream("Q: How do you say 'hello' in German? A:'", stop=["."]) + + self.assertIsInstance(generator, Generator) + + stream_results_string = "" + for chunk in generator: + self.assertIsInstance(chunk, str) + stream_results_string = chunk + + self.assertTrue(len(stream_results_string.strip()) > 1) + + del hf_pipe + gc.collect()