truefoundry 0.5.0rc7__py3-none-any.whl → 0.5.1rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of truefoundry might be problematic. Click here for more details.
- truefoundry/common/utils.py +73 -1
- truefoundry/deploy/__init__.py +5 -0
- truefoundry/deploy/cli/cli.py +2 -0
- truefoundry/deploy/cli/commands/__init__.py +1 -0
- truefoundry/deploy/cli/commands/deploy_init_command.py +22 -0
- truefoundry/deploy/lib/dao/application.py +2 -1
- truefoundry/deploy/v2/lib/patched_models.py +8 -0
- truefoundry/ml/__init__.py +14 -12
- truefoundry/ml/autogen/client/__init__.py +5 -0
- truefoundry/ml/autogen/client/api/mlfoundry_artifacts_api.py +161 -0
- truefoundry/ml/autogen/client/models/__init__.py +5 -0
- truefoundry/ml/autogen/client/models/artifact_version_manifest.py +2 -2
- truefoundry/ml/autogen/client/models/export_deployment_files_request_dto.py +82 -0
- truefoundry/ml/autogen/client/models/infer_method_name.py +34 -0
- truefoundry/ml/autogen/client/models/model_server.py +34 -0
- truefoundry/ml/autogen/client/models/model_version_environment.py +1 -1
- truefoundry/ml/autogen/client/models/model_version_manifest.py +3 -3
- truefoundry/ml/autogen/client/models/sklearn_framework.py +17 -1
- truefoundry/ml/autogen/client/models/transformers_framework.py +2 -2
- truefoundry/ml/autogen/client/models/xg_boost_framework.py +6 -1
- truefoundry/ml/autogen/client_README.md +4 -0
- truefoundry/ml/autogen/entities/artifacts.py +29 -7
- truefoundry/ml/cli/commands/model_init.py +97 -0
- truefoundry/ml/cli/utils.py +34 -0
- truefoundry/ml/log_types/artifacts/model.py +63 -24
- truefoundry/ml/log_types/artifacts/utils.py +37 -1
- truefoundry/ml/mlfoundry_api.py +74 -78
- truefoundry/ml/mlfoundry_run.py +0 -30
- truefoundry/ml/model_framework.py +257 -3
- truefoundry/ml/validation_utils.py +2 -0
- {truefoundry-0.5.0rc7.dist-info → truefoundry-0.5.1rc2.dist-info}/METADATA +1 -5
- {truefoundry-0.5.0rc7.dist-info → truefoundry-0.5.1rc2.dist-info}/RECORD +34 -46
- truefoundry/deploy/function_service/__init__.py +0 -3
- truefoundry/deploy/function_service/__main__.py +0 -27
- truefoundry/deploy/function_service/app.py +0 -92
- truefoundry/deploy/function_service/build.py +0 -45
- truefoundry/deploy/function_service/remote/__init__.py +0 -6
- truefoundry/deploy/function_service/remote/context.py +0 -3
- truefoundry/deploy/function_service/remote/method.py +0 -67
- truefoundry/deploy/function_service/remote/remote.py +0 -144
- truefoundry/deploy/function_service/route.py +0 -137
- truefoundry/deploy/function_service/service.py +0 -113
- truefoundry/deploy/function_service/utils.py +0 -53
- truefoundry/langchain/__init__.py +0 -12
- truefoundry/langchain/deprecated.py +0 -302
- truefoundry/langchain/truefoundry_chat.py +0 -130
- truefoundry/langchain/truefoundry_embeddings.py +0 -171
- truefoundry/langchain/truefoundry_llm.py +0 -106
- truefoundry/langchain/utils.py +0 -44
- truefoundry/ml/log_types/artifacts/model_extras.py +0 -48
- {truefoundry-0.5.0rc7.dist-info → truefoundry-0.5.1rc2.dist-info}/WHEEL +0 -0
- {truefoundry-0.5.0rc7.dist-info → truefoundry-0.5.1rc2.dist-info}/entry_points.txt +0 -0
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
import json
|
|
3
|
-
from typing import Any, Callable, Dict, List
|
|
4
|
-
|
|
5
|
-
from truefoundry.deploy.function_service.remote import RemoteClass
|
|
6
|
-
from truefoundry.deploy.function_service.utils import (
|
|
7
|
-
create_pydantic_model_from_function_signature,
|
|
8
|
-
get_qual_name,
|
|
9
|
-
)
|
|
10
|
-
from truefoundry.logger import logger
|
|
11
|
-
from truefoundry.pydantic_v1 import BaseModel, Field, constr, validator
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def validate_we_can_create_pydantic_model_of_func_args(func: Callable):
|
|
15
|
-
qual_name = get_qual_name(func)
|
|
16
|
-
try:
|
|
17
|
-
create_pydantic_model_from_function_signature(func, get_qual_name(func))
|
|
18
|
-
except Exception as ex:
|
|
19
|
-
raise Exception(
|
|
20
|
-
f"Unable to create a route for {qual_name!r}.\n"
|
|
21
|
-
"Please ensure that in the function type signature, you have only used in-built\n"
|
|
22
|
-
"types like `int`, `float`, `str`, `bool`, `typing.Dict`, `typing.List`, typing.Optional`.\n"
|
|
23
|
-
"To temporarily resolve this error, you can remove the unsupported type signatures.\n"
|
|
24
|
-
) from ex
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def path_pre_processor(path: str, prefix: str = "") -> str:
|
|
28
|
-
path = path.strip("/")
|
|
29
|
-
|
|
30
|
-
if not path:
|
|
31
|
-
raise ValueError("path cannot be empty")
|
|
32
|
-
|
|
33
|
-
prefix = prefix.strip("/")
|
|
34
|
-
if not prefix:
|
|
35
|
-
return f"/{path}"
|
|
36
|
-
|
|
37
|
-
return f"/{prefix}/{path}"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class Route(BaseModel):
|
|
41
|
-
function_name: str
|
|
42
|
-
http_method: str
|
|
43
|
-
path: constr(regex=r"^[A-Za-z0-9\-_/]+$")
|
|
44
|
-
|
|
45
|
-
qual_name: str
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class FunctionRoute(Route):
|
|
49
|
-
module: str
|
|
50
|
-
|
|
51
|
-
@classmethod
|
|
52
|
-
def from_func(cls, func: Callable, path: str):
|
|
53
|
-
validate_we_can_create_pydantic_model_of_func_args(func)
|
|
54
|
-
return cls(
|
|
55
|
-
function_name=func.__name__,
|
|
56
|
-
http_method="POST",
|
|
57
|
-
path=path_pre_processor(path or func.__name__),
|
|
58
|
-
qual_name=get_qual_name(func),
|
|
59
|
-
module=func.__module__,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class ClassRoute(BaseModel):
|
|
64
|
-
class_name: str
|
|
65
|
-
init_kwargs: Dict[str, Any] = Field(default_factory=dict)
|
|
66
|
-
module: str
|
|
67
|
-
|
|
68
|
-
routes: List[Route] = Field(default_factory=list)
|
|
69
|
-
|
|
70
|
-
@validator("init_kwargs")
|
|
71
|
-
def init_kwargs_is_json_serializable(cls, v, values):
|
|
72
|
-
try:
|
|
73
|
-
json.dumps(v)
|
|
74
|
-
except Exception as ex:
|
|
75
|
-
class_name = values.get("class_name")
|
|
76
|
-
raise ValueError(
|
|
77
|
-
f"init_kwargs {v!r} of class {class_name!r} is not JSON serializable"
|
|
78
|
-
) from ex
|
|
79
|
-
|
|
80
|
-
return v
|
|
81
|
-
|
|
82
|
-
@classmethod
|
|
83
|
-
def from_class(cls, remote_class: RemoteClass):
|
|
84
|
-
routes = []
|
|
85
|
-
methods = inspect.getmembers(remote_class.class_, predicate=inspect.isfunction)
|
|
86
|
-
|
|
87
|
-
for method_name, method in methods:
|
|
88
|
-
if method_name.startswith("_"):
|
|
89
|
-
continue
|
|
90
|
-
validate_we_can_create_pydantic_model_of_func_args(method)
|
|
91
|
-
route = Route(
|
|
92
|
-
function_name=method_name,
|
|
93
|
-
http_method="POST",
|
|
94
|
-
path=path_pre_processor(prefix=remote_class.name, path=method_name),
|
|
95
|
-
qual_name=remote_class.get_qual_name(method),
|
|
96
|
-
)
|
|
97
|
-
routes.append(route)
|
|
98
|
-
|
|
99
|
-
return cls(
|
|
100
|
-
class_name=remote_class.class_.__name__,
|
|
101
|
-
init_kwargs=remote_class.init_kwargs,
|
|
102
|
-
routes=routes,
|
|
103
|
-
module=remote_class.class_.__module__,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
class RouteGroups(BaseModel):
|
|
108
|
-
functions: List[FunctionRoute] = Field(default_factory=list)
|
|
109
|
-
classes: Dict[str, ClassRoute] = Field(default_factory=dict)
|
|
110
|
-
|
|
111
|
-
def register_function(self, func, path):
|
|
112
|
-
function_route = FunctionRoute.from_func(func=func, path=path)
|
|
113
|
-
logger.info(
|
|
114
|
-
"Function %r from module %r will be deployed on path '%s %s'.",
|
|
115
|
-
function_route.function_name,
|
|
116
|
-
function_route.module,
|
|
117
|
-
function_route.http_method,
|
|
118
|
-
function_route.path,
|
|
119
|
-
)
|
|
120
|
-
self.functions.append(function_route)
|
|
121
|
-
|
|
122
|
-
def register_class(self, remote_class: RemoteClass):
|
|
123
|
-
if remote_class.name in self.classes:
|
|
124
|
-
raise ValueError(
|
|
125
|
-
f"name {remote_class.name!r} is already used to register a class"
|
|
126
|
-
)
|
|
127
|
-
class_route = ClassRoute.from_class(remote_class)
|
|
128
|
-
for route in class_route.routes:
|
|
129
|
-
logger.info(
|
|
130
|
-
"Method %r from `%s:%s` will be deployed on path '%s %s'.",
|
|
131
|
-
route.function_name,
|
|
132
|
-
class_route.class_name,
|
|
133
|
-
remote_class.name,
|
|
134
|
-
route.http_method,
|
|
135
|
-
route.path,
|
|
136
|
-
)
|
|
137
|
-
self.classes[remote_class.name] = class_route
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
from threading import Thread
|
|
2
|
-
from typing import Any, Callable, Dict, Optional, Union
|
|
3
|
-
|
|
4
|
-
import yaml
|
|
5
|
-
|
|
6
|
-
from truefoundry.deploy.auto_gen.models import Port, Resources
|
|
7
|
-
from truefoundry.deploy.function_service.app import (
|
|
8
|
-
build_and_run_app_in_background_thread,
|
|
9
|
-
)
|
|
10
|
-
from truefoundry.deploy.function_service.build import BuildConfig
|
|
11
|
-
from truefoundry.deploy.function_service.remote import RemoteClass
|
|
12
|
-
from truefoundry.deploy.function_service.route import RouteGroups
|
|
13
|
-
from truefoundry.deploy.v2.lib.deployable_patched_models import Service
|
|
14
|
-
from truefoundry.deploy.v2.lib.patched_models import Build, LocalSource
|
|
15
|
-
from truefoundry.logger import logger
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class FunctionService:
|
|
19
|
-
def __init__(
|
|
20
|
-
self,
|
|
21
|
-
name: str,
|
|
22
|
-
build_config: Optional[BuildConfig] = None,
|
|
23
|
-
resources: Optional[Resources] = None,
|
|
24
|
-
replicas: int = 1,
|
|
25
|
-
port: Union[int, Port] = 8000,
|
|
26
|
-
env: Optional[Dict[str, str]] = None,
|
|
27
|
-
):
|
|
28
|
-
self._name = name
|
|
29
|
-
self._build_config = build_config or BuildConfig()
|
|
30
|
-
self._resources = resources or Resources()
|
|
31
|
-
self._replicas = replicas
|
|
32
|
-
if isinstance(port, int):
|
|
33
|
-
port = Port(port=port, expose=False)
|
|
34
|
-
if not port.host:
|
|
35
|
-
logger.warning(
|
|
36
|
-
"No host is set for the port. This is not an issue if you don't "
|
|
37
|
-
"want an exposed endpoint or are just testing locally.\n"
|
|
38
|
-
"However, for actual deployment it is required to pass an "
|
|
39
|
-
"instance of `truefoundry.deploy.Port` with "
|
|
40
|
-
"`host` argument defined.\n"
|
|
41
|
-
"E.g. `FunctionService(name='...', port=Port(port=8000, host='...', path='...'), ...)`"
|
|
42
|
-
)
|
|
43
|
-
self._port = port
|
|
44
|
-
self._env = env or {}
|
|
45
|
-
|
|
46
|
-
self._route_groups: RouteGroups = RouteGroups()
|
|
47
|
-
|
|
48
|
-
@property
|
|
49
|
-
def route_groups(self) -> RouteGroups:
|
|
50
|
-
return self._route_groups
|
|
51
|
-
|
|
52
|
-
def __repr__(self):
|
|
53
|
-
return yaml.dump(
|
|
54
|
-
{
|
|
55
|
-
"name": self._name,
|
|
56
|
-
"build_config": self._build_config.dict(),
|
|
57
|
-
"resources": self._resources.dict(),
|
|
58
|
-
"routes": self._route_groups.dict(),
|
|
59
|
-
"replicas": self._replicas,
|
|
60
|
-
"port": self._port.dict(),
|
|
61
|
-
"env": self._env,
|
|
62
|
-
},
|
|
63
|
-
indent=2,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
def register_function(
|
|
67
|
-
self,
|
|
68
|
-
func: Callable,
|
|
69
|
-
*,
|
|
70
|
-
path: Optional[str] = None,
|
|
71
|
-
):
|
|
72
|
-
self._route_groups.register_function(func=func, path=path)
|
|
73
|
-
|
|
74
|
-
def register_class(
|
|
75
|
-
self,
|
|
76
|
-
class_,
|
|
77
|
-
*,
|
|
78
|
-
init_kwargs: Optional[Dict[str, Any]] = None,
|
|
79
|
-
name: Optional[str] = None,
|
|
80
|
-
):
|
|
81
|
-
# TODO: I need to rethink this `RemoteClass`.
|
|
82
|
-
# I am mixing up multiple responsibilities here.
|
|
83
|
-
# For now, I am removing the burden of using `remote` from the user when deploying
|
|
84
|
-
# an instance of a class.
|
|
85
|
-
remote_class = RemoteClass(class_, init_kwargs=init_kwargs, name=name)
|
|
86
|
-
self._route_groups.register_class(remote_class=remote_class)
|
|
87
|
-
|
|
88
|
-
def run(self) -> Thread:
|
|
89
|
-
return build_and_run_app_in_background_thread(
|
|
90
|
-
route_groups=self._route_groups, port=self._port.port
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
def get_deployment_definition(self) -> Service:
|
|
94
|
-
# Keeping this function right now so that later,
|
|
95
|
-
# the constructor of the application call this function
|
|
96
|
-
# to get the component spec, if an object of this class
|
|
97
|
-
# is directly passed as a component
|
|
98
|
-
tfy_python_build_config = self._build_config.to_tfy_python_build_config(
|
|
99
|
-
port=self._port.port, route_groups=self._route_groups
|
|
100
|
-
)
|
|
101
|
-
service = Service(
|
|
102
|
-
name=self._name,
|
|
103
|
-
image=Build(build_source=LocalSource(), build_spec=tfy_python_build_config),
|
|
104
|
-
resources=self._resources,
|
|
105
|
-
replicas=self._replicas,
|
|
106
|
-
ports=[self._port],
|
|
107
|
-
env=self._env,
|
|
108
|
-
)
|
|
109
|
-
return service
|
|
110
|
-
|
|
111
|
-
def deploy(self, workspace_fqn: str, wait: bool = True):
|
|
112
|
-
service = self.get_deployment_definition()
|
|
113
|
-
service.deploy(workspace_fqn=workspace_fqn, wait=wait)
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from truefoundry.pydantic_v1 import BaseModel
|
|
5
|
-
from truefoundry.pydantic_v1 import create_model as pydantic_create_model
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def get_qual_name(obj):
|
|
9
|
-
return f"{obj.__module__}.{obj.__qualname__}"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def create_pydantic_model_from_function_signature(func, model_name: str):
|
|
13
|
-
# https://github.com/pydantic/pydantic/issues/1391
|
|
14
|
-
(
|
|
15
|
-
args,
|
|
16
|
-
_,
|
|
17
|
-
varkw,
|
|
18
|
-
defaults,
|
|
19
|
-
kwonlyargs,
|
|
20
|
-
kwonlydefaults,
|
|
21
|
-
annotations,
|
|
22
|
-
) = inspect.getfullargspec(func)
|
|
23
|
-
defaults = defaults or []
|
|
24
|
-
args = args or []
|
|
25
|
-
if len(args) > 0 and args[0] == "self":
|
|
26
|
-
del args[0]
|
|
27
|
-
|
|
28
|
-
non_default_args = len(args) - len(defaults)
|
|
29
|
-
defaults = [
|
|
30
|
-
...,
|
|
31
|
-
] * non_default_args + list(defaults)
|
|
32
|
-
|
|
33
|
-
keyword_only_params = {
|
|
34
|
-
param: kwonlydefaults.get(param, Any) for param in kwonlyargs
|
|
35
|
-
}
|
|
36
|
-
params = {
|
|
37
|
-
param: (annotations.get(param, Any), default)
|
|
38
|
-
for param, default in zip(args, defaults)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
class Config:
|
|
42
|
-
extra = "allow"
|
|
43
|
-
|
|
44
|
-
# Allow extra params if there is a **kwargs parameter in the function signature
|
|
45
|
-
config = Config if varkw else None
|
|
46
|
-
|
|
47
|
-
return pydantic_create_model(
|
|
48
|
-
model_name,
|
|
49
|
-
**params,
|
|
50
|
-
**keyword_only_params,
|
|
51
|
-
__base__=BaseModel,
|
|
52
|
-
__config__=config,
|
|
53
|
-
)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
try:
|
|
2
|
-
import langchain as _
|
|
3
|
-
except Exception as ex:
|
|
4
|
-
raise Exception(
|
|
5
|
-
"Failed to import langchain. "
|
|
6
|
-
"Please install langchain by using `pip install langchain` command"
|
|
7
|
-
) from ex
|
|
8
|
-
from truefoundry.langchain.deprecated import TruefoundryLLM, TruefoundryPlaygroundLLM
|
|
9
|
-
from truefoundry.langchain.truefoundry_chat import TrueFoundryChat
|
|
10
|
-
from truefoundry.langchain.truefoundry_embeddings import TrueFoundryEmbeddings
|
|
11
|
-
from truefoundry.langchain.truefoundry_llm import TrueFoundryLLM
|
|
12
|
-
from truefoundry.langchain.utils import ModelParameters
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import enum
|
|
2
|
-
import warnings
|
|
3
|
-
from typing import Any, Dict, List, Mapping, Optional
|
|
4
|
-
from urllib.parse import urljoin
|
|
5
|
-
|
|
6
|
-
import requests
|
|
7
|
-
from requests.auth import HTTPBasicAuth
|
|
8
|
-
|
|
9
|
-
from truefoundry.deploy.lib.auth.servicefoundry_session import ServiceFoundrySession
|
|
10
|
-
from truefoundry.pydantic_v1 import root_validator
|
|
11
|
-
|
|
12
|
-
try:
|
|
13
|
-
from langchain.callbacks.manager import CallbackManagerForLLMRun
|
|
14
|
-
from langchain.llms.base import LLM
|
|
15
|
-
from langchain.llms.utils import enforce_stop_tokens
|
|
16
|
-
except Exception as ex:
|
|
17
|
-
raise Exception(
|
|
18
|
-
"Failed to import langchain."
|
|
19
|
-
" Please install langchain by using `pip install langchain` command"
|
|
20
|
-
) from ex
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class _ModelServerImpl(str, enum.Enum):
|
|
24
|
-
MLSERVER = "MLSERVER"
|
|
25
|
-
TGI = "TGI"
|
|
26
|
-
VLLM = "VLLM"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _get_model_server_and_validate_if_mlserver(endpoint_url, auth, model_name=None):
|
|
30
|
-
try:
|
|
31
|
-
response = requests.get(urljoin(endpoint_url, "info"), json={}, auth=auth)
|
|
32
|
-
if response.status_code == 200:
|
|
33
|
-
return _ModelServerImpl.TGI, None
|
|
34
|
-
elif response.status_code == 404:
|
|
35
|
-
# We are not using TGI, try for mlserver
|
|
36
|
-
response = requests.post(
|
|
37
|
-
urljoin(endpoint_url, "v2/repository/index"), json={}, auth=auth
|
|
38
|
-
)
|
|
39
|
-
if response.status_code == 200:
|
|
40
|
-
models = response.json()
|
|
41
|
-
if len(models) == 0:
|
|
42
|
-
raise ValueError("No model is deployed in the model server")
|
|
43
|
-
model_names = [m.get("name") for m in models]
|
|
44
|
-
if model_name and model_name not in model_names:
|
|
45
|
-
raise ValueError(
|
|
46
|
-
f"Model {model_name!r} is not available in the model server. "
|
|
47
|
-
f"Available models {model_names!r}"
|
|
48
|
-
)
|
|
49
|
-
if not model_name and len(model_names) > 1:
|
|
50
|
-
raise ValueError(
|
|
51
|
-
f"Please pass `model_name` while instantiating `TruefoundryLLM`. "
|
|
52
|
-
f"Available models are {model_names!r} "
|
|
53
|
-
)
|
|
54
|
-
if model_name:
|
|
55
|
-
return _ModelServerImpl.MLSERVER, model_name
|
|
56
|
-
return _ModelServerImpl.MLSERVER, model_names[0]
|
|
57
|
-
if response.status_code == 404:
|
|
58
|
-
return _ModelServerImpl.VLLM, None
|
|
59
|
-
response.raise_for_status()
|
|
60
|
-
except Exception as e:
|
|
61
|
-
raise Exception(f"Error raised by inference API: {e}") from e
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# TODO (chiragjn): Refactor this into separate implementations for each model server
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class TruefoundryLLM(LLM):
|
|
68
|
-
"""Wrapper around TFY model deployment.
|
|
69
|
-
To use this class, you need to have the langchain library installed.
|
|
70
|
-
Example:
|
|
71
|
-
.. code-block:: python
|
|
72
|
-
from truefoundry.langchain import TruefoundryLLM
|
|
73
|
-
endpoint_url = (
|
|
74
|
-
"https://pythia-70m-model-model-catalogue.demo2.truefoundry.tech"
|
|
75
|
-
)
|
|
76
|
-
model = TruefoundryLLM(
|
|
77
|
-
endpoint_url=endpoint_url,
|
|
78
|
-
parameters={
|
|
79
|
-
"max_new_tokens": 100,
|
|
80
|
-
"temperature": 0.7,
|
|
81
|
-
"top_k": 5,
|
|
82
|
-
"top_p": 0.9
|
|
83
|
-
}
|
|
84
|
-
)
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
endpoint_url: str
|
|
88
|
-
model_name: Optional[str] = None
|
|
89
|
-
auth: Optional[HTTPBasicAuth] = None
|
|
90
|
-
parameters: Optional[Dict[str, Any]] = None
|
|
91
|
-
model_server_impl: Optional[_ModelServerImpl] = None
|
|
92
|
-
|
|
93
|
-
@root_validator(pre=False)
|
|
94
|
-
def validate_model_server_and_name(cls, values: Dict):
|
|
95
|
-
warnings.warn(
|
|
96
|
-
message=f"{cls.__name__} is deprecated and will be removed soon. Please use `TrueFoundryLLM` or `TrueFoundryChat` to invoke models using the new TrueFoundry LLM Gateway",
|
|
97
|
-
category=DeprecationWarning,
|
|
98
|
-
stacklevel=2,
|
|
99
|
-
)
|
|
100
|
-
endpoint_url = values["endpoint_url"]
|
|
101
|
-
model_name = values.get("model_name")
|
|
102
|
-
auth = values.get("auth")
|
|
103
|
-
model_server_impl, model_name = _get_model_server_and_validate_if_mlserver(
|
|
104
|
-
endpoint_url=endpoint_url, model_name=model_name, auth=auth
|
|
105
|
-
)
|
|
106
|
-
values["model_server_impl"] = model_server_impl
|
|
107
|
-
if model_server_impl == _ModelServerImpl.MLSERVER:
|
|
108
|
-
values["model_name"] = model_name
|
|
109
|
-
return values
|
|
110
|
-
|
|
111
|
-
@property
|
|
112
|
-
def _identifying_params(self) -> Mapping[str, Any]:
|
|
113
|
-
"""Get the identifying parameters."""
|
|
114
|
-
return {
|
|
115
|
-
"endpoint_url": self.endpoint_url,
|
|
116
|
-
"model_name": self.model_name,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@property
|
|
120
|
-
def _llm_type(self) -> str:
|
|
121
|
-
"""Return type of llm."""
|
|
122
|
-
return "tfy_model_deployment"
|
|
123
|
-
|
|
124
|
-
def _call( # noqa: C901
|
|
125
|
-
self,
|
|
126
|
-
prompt: str,
|
|
127
|
-
stop: Optional[List[str]] = None,
|
|
128
|
-
run_manager: Optional[CallbackManagerForLLMRun] = None,
|
|
129
|
-
**params: Any,
|
|
130
|
-
) -> str:
|
|
131
|
-
"""Call out to the deployed model
|
|
132
|
-
Args:
|
|
133
|
-
prompt: The prompt to pass into the model.
|
|
134
|
-
stop: Optional list of stop words to use when generating.
|
|
135
|
-
Returns:
|
|
136
|
-
The string generated by the model.
|
|
137
|
-
Example:
|
|
138
|
-
.. code-block:: python
|
|
139
|
-
response = model("Tell me a joke.")
|
|
140
|
-
"""
|
|
141
|
-
_params_already_set = self.parameters or {}
|
|
142
|
-
params = {**_params_already_set, **params, "return_full_text": False}
|
|
143
|
-
|
|
144
|
-
if self.model_server_impl == _ModelServerImpl.MLSERVER:
|
|
145
|
-
generate_path = f"v2/models/{self.model_name}/infer/simple"
|
|
146
|
-
payload = {"inputs": prompt, "parameters": params}
|
|
147
|
-
elif self.model_server_impl == _ModelServerImpl.TGI:
|
|
148
|
-
generate_path = "generate"
|
|
149
|
-
payload = {"inputs": prompt, "parameters": params}
|
|
150
|
-
elif self.model_server_impl == _ModelServerImpl.VLLM:
|
|
151
|
-
generate_path = "generate"
|
|
152
|
-
payload = {**params, "prompt": prompt}
|
|
153
|
-
else:
|
|
154
|
-
raise ValueError(f"No known generate path for {self.model_server_impl}")
|
|
155
|
-
url = urljoin(self.endpoint_url, generate_path)
|
|
156
|
-
|
|
157
|
-
try:
|
|
158
|
-
response = requests.post(url, json=payload, auth=self.auth)
|
|
159
|
-
response.raise_for_status()
|
|
160
|
-
except Exception as e:
|
|
161
|
-
raise Exception(f"Error raised by inference API: {e}") from e
|
|
162
|
-
response_dict = response.json()
|
|
163
|
-
if "error" in response_dict:
|
|
164
|
-
raise ValueError(
|
|
165
|
-
f"Error raised by inference API: {response_dict['error']!r}"
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
if self.model_server_impl == _ModelServerImpl.MLSERVER:
|
|
169
|
-
inference_result = response_dict[0]
|
|
170
|
-
elif self.model_server_impl == _ModelServerImpl.TGI:
|
|
171
|
-
inference_result = response_dict
|
|
172
|
-
elif self.model_server_impl == _ModelServerImpl.VLLM:
|
|
173
|
-
inference_result = response_dict
|
|
174
|
-
else:
|
|
175
|
-
raise ValueError(
|
|
176
|
-
f"Unknown model server {self.model_server_impl}, cannot parse response"
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
if "generated_text" in inference_result:
|
|
180
|
-
text = inference_result["generated_text"]
|
|
181
|
-
elif "summarization" in inference_result:
|
|
182
|
-
text = inference_result["summary_text"]
|
|
183
|
-
elif "text" in inference_result:
|
|
184
|
-
text = inference_result["text"]
|
|
185
|
-
else:
|
|
186
|
-
raise ValueError(f"Could not parse inference response: {response_dict!r}")
|
|
187
|
-
|
|
188
|
-
if isinstance(text, list):
|
|
189
|
-
text = text[0]
|
|
190
|
-
|
|
191
|
-
if stop:
|
|
192
|
-
text = enforce_stop_tokens(text, stop)
|
|
193
|
-
|
|
194
|
-
return text
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class TruefoundryPlaygroundLLM(LLM):
|
|
198
|
-
"""Wrapper around TFY Playground.
|
|
199
|
-
To use this class, you need to have the langchain library installed.
|
|
200
|
-
Example:
|
|
201
|
-
.. code-block:: python
|
|
202
|
-
from truefoundry.langchain import TruefoundryPlaygroundLLM
|
|
203
|
-
import os
|
|
204
|
-
# Note: Login using tfy login --host <https://example-domain.com>
|
|
205
|
-
model = TruefoundryPlaygroundLLM(
|
|
206
|
-
model_name="vicuna-13b",
|
|
207
|
-
parameters={
|
|
208
|
-
"maximumLength": 100,
|
|
209
|
-
"temperature": 0.7,
|
|
210
|
-
"topP": 0.9,
|
|
211
|
-
"repetitionPenalty": 1
|
|
212
|
-
}
|
|
213
|
-
)
|
|
214
|
-
response = model.predict("Enter the prompt here")
|
|
215
|
-
"""
|
|
216
|
-
|
|
217
|
-
model_name: str
|
|
218
|
-
parameters: Optional[Dict[str, Any]] = None
|
|
219
|
-
provider: str = "truefoundry-public"
|
|
220
|
-
|
|
221
|
-
@root_validator(pre=False)
|
|
222
|
-
def validate_model_server_and_name(cls, values: Dict):
|
|
223
|
-
warnings.warn(
|
|
224
|
-
message=f"{cls.__name__} is deprecated and will be removed soon. Please use `TrueFoundryLLM` or `TrueFoundryChat` to invoke models using the new TrueFoundry LLM Gateway",
|
|
225
|
-
category=DeprecationWarning,
|
|
226
|
-
stacklevel=2,
|
|
227
|
-
)
|
|
228
|
-
return values
|
|
229
|
-
|
|
230
|
-
@property
|
|
231
|
-
def _get_model(self) -> str:
|
|
232
|
-
"""returns the model name"""
|
|
233
|
-
return self.model_name
|
|
234
|
-
|
|
235
|
-
@property
|
|
236
|
-
def _get_provider(self) -> str:
|
|
237
|
-
"""Returns the provider name"""
|
|
238
|
-
return self.provider
|
|
239
|
-
|
|
240
|
-
@property
|
|
241
|
-
def _llm_type(self) -> str:
|
|
242
|
-
"""Return type of llm."""
|
|
243
|
-
return "tfy_playground"
|
|
244
|
-
|
|
245
|
-
def _call(
|
|
246
|
-
self,
|
|
247
|
-
prompt: str,
|
|
248
|
-
stop: Optional[List[str]] = None,
|
|
249
|
-
**params: Any,
|
|
250
|
-
) -> str:
|
|
251
|
-
"""Call out to the deployed model
|
|
252
|
-
Args:
|
|
253
|
-
prompt: The prompt to pass into the model.
|
|
254
|
-
stop: Optional list of stop words to use when generating.
|
|
255
|
-
Returns:
|
|
256
|
-
The string generated by the model.
|
|
257
|
-
Example:
|
|
258
|
-
.. code-block:: python
|
|
259
|
-
response = model("I have a joke for you...")
|
|
260
|
-
"""
|
|
261
|
-
_params_already_set = self.parameters or {}
|
|
262
|
-
params = {**_params_already_set, **params}
|
|
263
|
-
if stop:
|
|
264
|
-
params["stopSequences"] = stop
|
|
265
|
-
session = ServiceFoundrySession()
|
|
266
|
-
|
|
267
|
-
if not session:
|
|
268
|
-
raise Exception(
|
|
269
|
-
"Unauthenticated: Please login using tfy login --host <https://example-domain.com>"
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
host = session.base_url
|
|
273
|
-
|
|
274
|
-
if host[-1] == "/":
|
|
275
|
-
host = host[: len(host) - 1]
|
|
276
|
-
|
|
277
|
-
url = f"{host}/llm-playground/api/inference/text"
|
|
278
|
-
headers = {"Authorization": f"Bearer {session.access_token}"}
|
|
279
|
-
|
|
280
|
-
json = {
|
|
281
|
-
"prompt": prompt,
|
|
282
|
-
"models": [
|
|
283
|
-
{
|
|
284
|
-
"name": self.model_name,
|
|
285
|
-
"provider": self.provider,
|
|
286
|
-
"tag": self.model_name,
|
|
287
|
-
"parameters": params,
|
|
288
|
-
}
|
|
289
|
-
],
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
try:
|
|
293
|
-
response = requests.post(url=url, headers=headers, json=json)
|
|
294
|
-
response.raise_for_status()
|
|
295
|
-
except Exception as ex:
|
|
296
|
-
raise Exception(f"Error inferencing the model: {ex}") from ex
|
|
297
|
-
|
|
298
|
-
data = response.json()
|
|
299
|
-
text = data[0].get("text")
|
|
300
|
-
if stop:
|
|
301
|
-
text = enforce_stop_tokens(text, stop)
|
|
302
|
-
return text
|