Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
anyscale.py320 linesDownload Raw Back to llms
1"""Wrapper around Anyscale Endpoint"""2 3from typing import (4    Any,5    Dict,6    List,7    Mapping,8    Optional,9    Set,10)11 12from langchain_core.callbacks import (13    AsyncCallbackManagerForLLMRun,14    CallbackManagerForLLMRun,15)16from langchain_core.outputs import Generation, GenerationChunk, LLMResult17from langchain_core.utils import convert_to_secret_str, get_from_dict_or_env, pre_init18from pydantic import Field, SecretStr19 20from langchain_community.llms.openai import (21    BaseOpenAI,22    acompletion_with_retry,23    completion_with_retry,24)25from langchain_community.utils.openai import is_openai_v126 27DEFAULT_BASE_URL = "https://api.endpoints.anyscale.com/v1"28DEFAULT_MODEL = "mistralai/Mixtral-8x7B-Instruct-v0.1"29 30 31def update_token_usage(32    keys: Set[str], response: Dict[str, Any], token_usage: Dict[str, Any]33) -> None:34    """Update token usage."""35    _keys_to_use = keys.intersection(response["usage"])36    for _key in _keys_to_use:37        if _key not in token_usage:38            token_usage[_key] = response["usage"][_key]39        else:40            token_usage[_key] += response["usage"][_key]41 42 43def create_llm_result(44    choices: Any, prompts: List[str], token_usage: Dict[str, int], model_name: str45) -> LLMResult:46    """Create the LLMResult from the choices and prompts."""47    generations = []48    for i, _ in enumerate(prompts):49        choice = choices[i]50        generations.append(51            [52                Generation(53                    text=choice["message"]["content"],54                    generation_info=dict(55                        finish_reason=choice.get("finish_reason"),56                        logprobs=choice.get("logprobs"),57                    ),58                )59            ]60        )61    llm_output = {"token_usage": token_usage, "model_name": model_name}62    return LLMResult(generations=generations, llm_output=llm_output)63 64 65class Anyscale(BaseOpenAI):66    """Anyscale large language models.67 68    To use, you should have the environment variable ``ANYSCALE_API_KEY``set with your69    Anyscale Endpoint, or pass it as a named parameter to the constructor.70    To use with Anyscale Private Endpoint, please also set ``ANYSCALE_BASE_URL``.71 72    Example:73        .. code-block:: python74            from langchain_classic.llms import Anyscale75            anyscalellm = Anyscale(anyscale_api_key="ANYSCALE_API_KEY")76            # To leverage Ray for parallel processing77            @ray.remote(num_cpus=1)78            def send_query(llm, text):79                resp = llm.invoke(text)80                return resp81            futures = [send_query.remote(anyscalellm, text) for text in texts]82            results = ray.get(futures)83    """84 85    """Key word arguments to pass to the model."""86    anyscale_api_base: str = Field(default=DEFAULT_BASE_URL)87    anyscale_api_key: SecretStr = Field(default=SecretStr(""))88    model_name: str = Field(default=DEFAULT_MODEL)89 90    prefix_messages: List = Field(default_factory=list)91 92    @classmethod93    def is_lc_serializable(cls) -> bool:94        return False95 96    @pre_init97    def validate_environment(cls, values: Dict) -> Dict:98        """Validate that api key and python package exists in environment."""99        values["anyscale_api_base"] = get_from_dict_or_env(100            values,101            "anyscale_api_base",102            "ANYSCALE_API_BASE",103            default=DEFAULT_BASE_URL,104        )105        values["anyscale_api_key"] = convert_to_secret_str(106            get_from_dict_or_env(values, "anyscale_api_key", "ANYSCALE_API_KEY")107        )108        values["model_name"] = get_from_dict_or_env(109            values,110            "model_name",111            "MODEL_NAME",112            default=DEFAULT_MODEL,113        )114 115        try:116            import openai117 118            if is_openai_v1():119                client_params = {120                    "api_key": values["anyscale_api_key"].get_secret_value(),121                    "base_url": values["anyscale_api_base"],122                    # To do: future support123                    # "organization": values["openai_organization"],124                    # "timeout": values["request_timeout"],125                    # "max_retries": values["max_retries"],126                    # "default_headers": values["default_headers"],127                    # "default_query": values["default_query"],128                    # "http_client": values["http_client"],129                }130                if not values.get("client"):131                    values["client"] = openai.OpenAI(**client_params).completions132                if not values.get("async_client"):133                    values["async_client"] = openai.AsyncOpenAI(134                        **client_params135                    ).completions136            else:137                values["openai_api_base"] = values["anyscale_api_base"]138                values["openai_api_key"] = values["anyscale_api_key"].get_secret_value()139                values["client"] = openai.Completion140        except ImportError:141            raise ImportError(142                "Could not import openai python package. "143                "Please install it with `pip install openai`."144            )145        if values["streaming"] and values["n"] > 1:146            raise ValueError("Cannot stream results when n > 1.")147        if values["streaming"] and values["best_of"] > 1:148            raise ValueError("Cannot stream results when best_of > 1.")149 150        return values151 152    @property153    def _identifying_params(self) -> Mapping[str, Any]:154        """Get the identifying parameters."""155        return {156            **{"model_name": self.model_name},157            **super()._identifying_params,158        }159 160    @property161    def _invocation_params(self) -> Dict[str, Any]:162        """Get the parameters used to invoke the model."""163        openai_creds: Dict[str, Any] = {164            "model": self.model_name,165        }166        if not is_openai_v1():167            openai_creds.update(168                {169                    "api_key": self.anyscale_api_key.get_secret_value(),170                    "api_base": self.anyscale_api_base,171                }172            )173        return {**openai_creds, **super()._invocation_params}174 175    @property176    def _llm_type(self) -> str:177        """Return type of llm."""178        return "Anyscale LLM"179 180    def _generate(181        self,182        prompts: List[str],183        stop: Optional[List[str]] = None,184        run_manager: Optional[CallbackManagerForLLMRun] = None,185        **kwargs: Any,186    ) -> LLMResult:187        """Call out to OpenAI's endpoint with k unique prompts.188 189        Args:190            prompts: The prompts to pass into the model.191            stop: Optional list of stop words to use when generating.192 193        Returns:194            The full LLM output.195 196        Example:197            .. code-block:: python198 199                response = openai.generate(["Tell me a joke."])200        """201        # TODO: write a unit test for this202        params = self._invocation_params203        params = {**params, **kwargs}204        sub_prompts = self.get_sub_prompts(params, prompts, stop)205        choices = []206        token_usage: Dict[str, int] = {}207        # Get the token usage from the response.208        # Includes prompt, completion, and total tokens used.209        _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}210        system_fingerprint: Optional[str] = None211        for _prompts in sub_prompts:212            if self.streaming:213                if len(_prompts) > 1:214                    raise ValueError("Cannot stream results with multiple prompts.")215 216                generation: Optional[GenerationChunk] = None217                for chunk in self._stream(_prompts[0], stop, run_manager, **kwargs):218                    if generation is None:219                        generation = chunk220                    else:221                        generation += chunk222                assert generation is not None223                choices.append(224                    {225                        "text": generation.text,226                        "finish_reason": generation.generation_info.get("finish_reason")227                        if generation.generation_info228                        else None,229                        "logprobs": generation.generation_info.get("logprobs")230                        if generation.generation_info231                        else None,232                    }233                )234            else:235                response = completion_with_retry(236                    ## THis is the ONLY change from BaseOpenAI()._generate()237                    self,238                    prompt=_prompts[0],239                    run_manager=run_manager,240                    **params,241                )242                if not isinstance(response, dict):243                    # V1 client returns the response in an PyDantic object instead of244                    # dict. For the transition period, we deep convert it to dict.245                    response = response.dict()246 247                choices.extend(response["choices"])248                update_token_usage(_keys, response, token_usage)249                if not system_fingerprint:250                    system_fingerprint = response.get("system_fingerprint")251        return self.create_llm_result(252            choices,253            prompts,254            params,255            token_usage,256            system_fingerprint=system_fingerprint,257        )258 259    async def _agenerate(260        self,261        prompts: List[str],262        stop: Optional[List[str]] = None,263        run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,264        **kwargs: Any,265    ) -> LLMResult:266        """Call out to OpenAI's endpoint async with k unique prompts."""267        params = self._invocation_params268        params = {**params, **kwargs}269        sub_prompts = self.get_sub_prompts(params, prompts, stop)270        choices = []271        token_usage: Dict[str, int] = {}272        # Get the token usage from the response.273        # Includes prompt, completion, and total tokens used.274        _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}275        system_fingerprint: Optional[str] = None276        for _prompts in sub_prompts:277            if self.streaming:278                if len(_prompts) > 1:279                    raise ValueError("Cannot stream results with multiple prompts.")280 281                generation: Optional[GenerationChunk] = None282                async for chunk in self._astream(283                    _prompts[0], stop, run_manager, **kwargs284                ):285                    if generation is None:286                        generation = chunk287                    else:288                        generation += chunk289                assert generation is not None290                choices.append(291                    {292                        "text": generation.text,293                        "finish_reason": generation.generation_info.get("finish_reason")294                        if generation.generation_info295                        else None,296                        "logprobs": generation.generation_info.get("logprobs")297                        if generation.generation_info298                        else None,299                    }300                )301            else:302                response = await acompletion_with_retry(303                    ## THis is the ONLY change from BaseOpenAI()._agenerate()304                    self,305                    prompt=_prompts[0],306                    run_manager=run_manager,307                    **params,308                )309                if not isinstance(response, dict):310                    response = response.dict()311                choices.extend(response["choices"])312                update_token_usage(_keys, response, token_usage)313        return self.create_llm_result(314            choices,315            prompts,316            params,317            token_usage,318            system_fingerprint=system_fingerprint,319        )320 
codekingpro/portable-devtools · Team Ai