llama-index
168 строк · 6.0 Кб
1from typing import Any, Optional, Sequence, Union2
3from llama_index.legacy.bridge.pydantic import Field4from llama_index.legacy.constants import DEFAULT_CONTEXT_WINDOW5from llama_index.legacy.llms.generic_utils import (6async_stream_completion_response_to_chat_response,7completion_response_to_chat_response,8stream_completion_response_to_chat_response,9)
10from llama_index.legacy.llms.openai import OpenAI, Tokenizer11from llama_index.legacy.llms.types import (12ChatMessage,13ChatResponse,14ChatResponseAsyncGen,15ChatResponseGen,16CompletionResponse,17CompletionResponseAsyncGen,18CompletionResponseGen,19LLMMetadata,20)
21
22
23class OpenAILike(OpenAI):24"""25OpenAILike is a thin wrapper around the OpenAI model that makes it compatible with
263rd party tools that provide an openai-compatible api.
27
28Currently, llama_index prevents using custom models with their OpenAI class
29because they need to be able to infer some metadata from the model name.
30
31NOTE: You still need to set the OPENAI_BASE_API and OPENAI_API_KEY environment
32variables or the api_key and api_base constructor arguments.
33OPENAI_API_KEY/api_key can normally be set to anything in this case,
34but will depend on the tool you're using.
35"""
36
37context_window: int = Field(38default=DEFAULT_CONTEXT_WINDOW,39description=LLMMetadata.__fields__["context_window"].field_info.description,40)41is_chat_model: bool = Field(42default=False,43description=LLMMetadata.__fields__["is_chat_model"].field_info.description,44)45is_function_calling_model: bool = Field(46default=False,47description=LLMMetadata.__fields__[48"is_function_calling_model"49].field_info.description,50)51tokenizer: Union[Tokenizer, str, None] = Field(52default=None,53description=(54"An instance of a tokenizer object that has an encode method, or the name"55" of a tokenizer model from Hugging Face. If left as None, then this"56" disables inference of max_tokens."57),58)59
60@property61def metadata(self) -> LLMMetadata:62return LLMMetadata(63context_window=self.context_window,64num_output=self.max_tokens or -1,65is_chat_model=self.is_chat_model,66is_function_calling_model=self.is_function_calling_model,67model_name=self.model,68)69
70@property71def _tokenizer(self) -> Optional[Tokenizer]:72if isinstance(self.tokenizer, str):73try:74from transformers import AutoTokenizer75except ImportError as exc:76raise ImportError(77"Please install transformers (pip install transformers) to use "78"huggingface tokenizers with OpenAILike."79) from exc80
81return AutoTokenizer.from_pretrained(self.tokenizer)82return self.tokenizer83
84@classmethod85def class_name(cls) -> str:86return "OpenAILike"87
88def complete(89self, prompt: str, formatted: bool = False, **kwargs: Any90) -> CompletionResponse:91"""Complete the prompt."""92if not formatted:93prompt = self.completion_to_prompt(prompt)94
95return super().complete(prompt, **kwargs)96
97def stream_complete(98self, prompt: str, formatted: bool = False, **kwargs: Any99) -> CompletionResponseGen:100"""Stream complete the prompt."""101if not formatted:102prompt = self.completion_to_prompt(prompt)103
104return super().stream_complete(prompt, **kwargs)105
106def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:107"""Chat with the model."""108if not self.metadata.is_chat_model:109prompt = self.messages_to_prompt(messages)110completion_response = self.complete(prompt, formatted=True, **kwargs)111return completion_response_to_chat_response(completion_response)112
113return super().chat(messages, **kwargs)114
115def stream_chat(116self, messages: Sequence[ChatMessage], **kwargs: Any117) -> ChatResponseGen:118if not self.metadata.is_chat_model:119prompt = self.messages_to_prompt(messages)120completion_response = self.stream_complete(prompt, formatted=True, **kwargs)121return stream_completion_response_to_chat_response(completion_response)122
123return super().stream_chat(messages, **kwargs)124
125# -- Async methods --126
127async def acomplete(128self, prompt: str, formatted: bool = False, **kwargs: Any129) -> CompletionResponse:130"""Complete the prompt."""131if not formatted:132prompt = self.completion_to_prompt(prompt)133
134return await super().acomplete(prompt, **kwargs)135
136async def astream_complete(137self, prompt: str, formatted: bool = False, **kwargs: Any138) -> CompletionResponseAsyncGen:139"""Stream complete the prompt."""140if not formatted:141prompt = self.completion_to_prompt(prompt)142
143return await super().astream_complete(prompt, **kwargs)144
145async def achat(146self, messages: Sequence[ChatMessage], **kwargs: Any147) -> ChatResponse:148"""Chat with the model."""149if not self.metadata.is_chat_model:150prompt = self.messages_to_prompt(messages)151completion_response = await self.acomplete(prompt, formatted=True, **kwargs)152return completion_response_to_chat_response(completion_response)153
154return await super().achat(messages, **kwargs)155
156async def astream_chat(157self, messages: Sequence[ChatMessage], **kwargs: Any158) -> ChatResponseAsyncGen:159if not self.metadata.is_chat_model:160prompt = self.messages_to_prompt(messages)161completion_response = await self.astream_complete(162prompt, formatted=True, **kwargs163)164return async_stream_completion_response_to_chat_response(165completion_response
166)167
168return await super().astream_chat(messages, **kwargs)169