Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
self_hosted_hugging_face.py212 linesDownload Raw Back to llms
1import importlib.util2import logging3from typing import Any, Callable, List, Mapping, Optional4 5from langchain_core.callbacks import CallbackManagerForLLMRun6from pydantic import ConfigDict7 8from langchain_community.llms.self_hosted import SelfHostedPipeline9from langchain_community.llms.utils import enforce_stop_tokens10 11DEFAULT_MODEL_ID = "gpt2"12DEFAULT_TASK = "text-generation"13VALID_TASKS = ("text2text-generation", "text-generation", "summarization")14 15logger = logging.getLogger(__name__)16 17 18def _generate_text(19    pipeline: Any,20    prompt: str,21    *args: Any,22    stop: Optional[List[str]] = None,23    **kwargs: Any,24) -> str:25    """Inference function to send to the remote hardware.26 27    Accepts a Hugging Face pipeline (or more likely,28    a key pointing to such a pipeline on the cluster's object store)29    and returns generated text.30    """31    response = pipeline(prompt, *args, **kwargs)32    if pipeline.task == "text-generation":33        # Text generation return includes the starter text.34        text = response[0]["generated_text"][len(prompt) :]35    elif pipeline.task == "text2text-generation":36        text = response[0]["generated_text"]37    elif pipeline.task == "summarization":38        text = response[0]["summary_text"]39    else:40        raise ValueError(41            f"Got invalid task {pipeline.task}, "42            f"currently only {VALID_TASKS} are supported"43        )44    if stop is not None:45        text = enforce_stop_tokens(text, stop)46    return text47 48 49def _load_transformer(50    model_id: str = DEFAULT_MODEL_ID,51    task: str = DEFAULT_TASK,52    device: int = 0,53    model_kwargs: Optional[dict] = None,54) -> Any:55    """Inference function to send to the remote hardware.56 57    Accepts a huggingface model_id and returns a pipeline for the task.58    """59    from transformers import AutoModelForCausalLM, AutoModelForSeq2SeqLM, AutoTokenizer60    from transformers import pipeline as hf_pipeline61 62    _model_kwargs = model_kwargs or {}63    tokenizer = AutoTokenizer.from_pretrained(model_id, **_model_kwargs)64 65    try:66        if task == "text-generation":67            model = AutoModelForCausalLM.from_pretrained(model_id, **_model_kwargs)68        elif task in ("text2text-generation", "summarization"):69            model = AutoModelForSeq2SeqLM.from_pretrained(model_id, **_model_kwargs)70        else:71            raise ValueError(72                f"Got invalid task {task}, currently only {VALID_TASKS} are supported"73            )74    except ImportError as e:75        raise ImportError(76            f"Could not load the {task} model due to missing dependencies."77        ) from e78 79    if importlib.util.find_spec("torch") is not None:80        import torch81 82        cuda_device_count = torch.cuda.device_count()83        if device < -1 or (device >= cuda_device_count):84            raise ValueError(85                f"Got device=={device}, "86                f"device is required to be within [-1, {cuda_device_count})"87            )88        if device < 0 and cuda_device_count > 0:89            logger.warning(90                "Device has %d GPUs available. "91                "Provide device={deviceId} to `from_model_id` to use available"92                "GPUs for execution. deviceId is -1 for CPU and "93                "can be a positive integer associated with CUDA device id.",94                cuda_device_count,95            )96 97    pipeline = hf_pipeline(98        task=task,99        model=model,100        tokenizer=tokenizer,101        device=device,102        model_kwargs=_model_kwargs,103    )104    if pipeline.task not in VALID_TASKS:105        raise ValueError(106            f"Got invalid task {pipeline.task}, "107            f"currently only {VALID_TASKS} are supported"108        )109    return pipeline110 111 112class SelfHostedHuggingFaceLLM(SelfHostedPipeline):113    """HuggingFace Pipeline API to run on self-hosted remote hardware.114 115    Supported hardware includes auto-launched instances on AWS, GCP, Azure,116    and Lambda, as well as servers specified117    by IP address and SSH credentials (such as on-prem, or another cloud118    like Paperspace, Coreweave, etc.).119 120    To use, you should have the ``runhouse`` python package installed.121 122    Only supports `text-generation`, `text2text-generation` and `summarization` for now.123 124    Example using from_model_id:125        .. code-block:: python126 127            from langchain_community.llms import SelfHostedHuggingFaceLLM128            import runhouse as rh129            gpu = rh.cluster(name="rh-a10x", instance_type="A100:1")130            hf = SelfHostedHuggingFaceLLM(131                model_id="google/flan-t5-large", task="text2text-generation",132                hardware=gpu133            )134    Example passing fn that generates a pipeline (bc the pipeline is not serializable):135        .. code-block:: python136 137            from langchain_community.llms import SelfHostedHuggingFaceLLM138            from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline139            import runhouse as rh140 141            def get_pipeline():142                model_id = "gpt2"143                tokenizer = AutoTokenizer.from_pretrained(model_id)144                model = AutoModelForCausalLM.from_pretrained(model_id)145                pipe = pipeline(146                    "text-generation", model=model, tokenizer=tokenizer147                )148                return pipe149            hf = SelfHostedHuggingFaceLLM(150                model_load_fn=get_pipeline, model_id="gpt2", hardware=gpu)151    """152 153    model_id: str = DEFAULT_MODEL_ID154    """Hugging Face model_id to load the model."""155    task: str = DEFAULT_TASK156    """Hugging Face task ("text-generation", "text2text-generation" or157    "summarization")."""158    device: int = 0159    """Device to use for inference. -1 for CPU, 0 for GPU, 1 for second GPU, etc."""160    model_kwargs: Optional[dict] = None161    """Keyword arguments to pass to the model."""162    hardware: Any = None163    """Remote hardware to send the inference function to."""164    model_reqs: List[str] = ["./", "transformers", "torch"]165    """Requirements to install on hardware to inference the model."""166    model_load_fn: Callable = _load_transformer167    """Function to load the model remotely on the server."""168    inference_fn: Callable = _generate_text  #: :meta private:169    """Inference function to send to the remote hardware."""170 171    model_config = ConfigDict(172        extra="forbid",173    )174 175    def __init__(self, **kwargs: Any):176        """Construct the pipeline remotely using an auxiliary function.177 178        The load function needs to be importable to be imported179        and run on the server, i.e. in a module and not a REPL or closure.180        Then, initialize the remote inference function.181        """182        load_fn_kwargs = {183            "model_id": kwargs.get("model_id", DEFAULT_MODEL_ID),184            "task": kwargs.get("task", DEFAULT_TASK),185            "device": kwargs.get("device", 0),186            "model_kwargs": kwargs.get("model_kwargs", None),187        }188        super().__init__(load_fn_kwargs=load_fn_kwargs, **kwargs)189 190    @property191    def _identifying_params(self) -> Mapping[str, Any]:192        """Get the identifying parameters."""193        return {194            **{"model_id": self.model_id},195            **{"model_kwargs": self.model_kwargs},196        }197 198    @property199    def _llm_type(self) -> str:200        return "selfhosted_huggingface_pipeline"201 202    def _call(203        self,204        prompt: str,205        stop: Optional[List[str]] = None,206        run_manager: Optional[CallbackManagerForLLMRun] = None,207        **kwargs: Any,208    ) -> str:209        return self.client(210            pipeline=self.pipeline_ref, prompt=prompt, stop=stop, **kwargs211        )212 
codekingpro/portable-devtools · Team Ai