flytekitplugins-inference 1.13.1__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.
- flytekitplugins/inference/__init__.py +13 -0
- flytekitplugins/inference/nim/__init__.py +0 -0
- flytekitplugins/inference/nim/serve.py +180 -0
- flytekitplugins/inference/sidecar_template.py +77 -0
- flytekitplugins_inference-1.13.1-py3.12-nspkg.pth +1 -0
- flytekitplugins_inference-1.13.1.dist-info/METADATA +25 -0
- flytekitplugins_inference-1.13.1.dist-info/RECORD +11 -0
- flytekitplugins_inference-1.13.1.dist-info/WHEEL +5 -0
- flytekitplugins_inference-1.13.1.dist-info/entry_points.txt +2 -0
- flytekitplugins_inference-1.13.1.dist-info/namespace_packages.txt +1 -0
- flytekitplugins_inference-1.13.1.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from ..sidecar_template import ModelInferenceTemplate
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class NIMSecrets:
|
|
9
|
+
"""
|
|
10
|
+
:param ngc_image_secret: The name of the Kubernetes secret containing the NGC image pull credentials.
|
|
11
|
+
:param ngc_secret_key: The key name for the NGC API key.
|
|
12
|
+
:param secrets_prefix: The secrets prefix that Flyte appends to all mounted secrets.
|
|
13
|
+
:param ngc_secret_group: The group name for the NGC API key.
|
|
14
|
+
:param hf_token_group: The group name for the HuggingFace token.
|
|
15
|
+
:param hf_token_key: The key name for the HuggingFace token.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
ngc_image_secret: str # kubernetes secret
|
|
19
|
+
ngc_secret_key: str
|
|
20
|
+
secrets_prefix: str # _UNION_ or _FSEC_
|
|
21
|
+
ngc_secret_group: Optional[str] = None
|
|
22
|
+
hf_token_group: Optional[str] = None
|
|
23
|
+
hf_token_key: Optional[str] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NIM(ModelInferenceTemplate):
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
secrets: NIMSecrets,
|
|
30
|
+
image: str = "nvcr.io/nim/meta/llama3-8b-instruct:1.0.0",
|
|
31
|
+
health_endpoint: str = "v1/health/ready",
|
|
32
|
+
port: int = 8000,
|
|
33
|
+
cpu: int = 1,
|
|
34
|
+
gpu: int = 1,
|
|
35
|
+
mem: str = "20Gi",
|
|
36
|
+
shm_size: str = "16Gi",
|
|
37
|
+
env: Optional[dict[str, str]] = None,
|
|
38
|
+
hf_repo_ids: Optional[list[str]] = None,
|
|
39
|
+
lora_adapter_mem: Optional[str] = None,
|
|
40
|
+
):
|
|
41
|
+
"""
|
|
42
|
+
Initialize NIM class for managing a Kubernetes pod template.
|
|
43
|
+
|
|
44
|
+
:param image: The Docker image to be used for the model server container. Default is "nvcr.io/nim/meta/llama3-8b-instruct:1.0.0".
|
|
45
|
+
:param health_endpoint: The health endpoint for the model server container. Default is "v1/health/ready".
|
|
46
|
+
:param port: The port number for the model server container. Default is 8000.
|
|
47
|
+
:param cpu: The number of CPU cores requested for the model server container. Default is 1.
|
|
48
|
+
:param gpu: The number of GPU cores requested for the model server container. Default is 1.
|
|
49
|
+
:param mem: The amount of memory requested for the model server container. Default is "20Gi".
|
|
50
|
+
:param shm_size: The size of the shared memory volume. Default is "16Gi".
|
|
51
|
+
:param env: A dictionary of environment variables to be set in the model server container.
|
|
52
|
+
:param hf_repo_ids: A list of Hugging Face repository IDs for LoRA adapters to be downloaded.
|
|
53
|
+
:param lora_adapter_mem: The amount of memory requested for the init container that downloads LoRA adapters.
|
|
54
|
+
:param secrets: Instance of NIMSecrets for managing secrets.
|
|
55
|
+
"""
|
|
56
|
+
if secrets.ngc_image_secret is None:
|
|
57
|
+
raise ValueError("NGC image pull secret must be provided.")
|
|
58
|
+
if secrets.ngc_secret_key is None:
|
|
59
|
+
raise ValueError("NGC secret key must be provided.")
|
|
60
|
+
if secrets.secrets_prefix is None:
|
|
61
|
+
raise ValueError("Secrets prefix must be provided.")
|
|
62
|
+
|
|
63
|
+
self._shm_size = shm_size
|
|
64
|
+
self._hf_repo_ids = hf_repo_ids
|
|
65
|
+
self._lora_adapter_mem = lora_adapter_mem
|
|
66
|
+
self._secrets = secrets
|
|
67
|
+
|
|
68
|
+
super().__init__(
|
|
69
|
+
image=image,
|
|
70
|
+
health_endpoint=health_endpoint,
|
|
71
|
+
port=port,
|
|
72
|
+
cpu=cpu,
|
|
73
|
+
gpu=gpu,
|
|
74
|
+
mem=mem,
|
|
75
|
+
env=env,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self.setup_nim_pod_template()
|
|
79
|
+
|
|
80
|
+
def setup_nim_pod_template(self):
|
|
81
|
+
from kubernetes.client.models import (
|
|
82
|
+
V1Container,
|
|
83
|
+
V1EmptyDirVolumeSource,
|
|
84
|
+
V1EnvVar,
|
|
85
|
+
V1LocalObjectReference,
|
|
86
|
+
V1ResourceRequirements,
|
|
87
|
+
V1SecurityContext,
|
|
88
|
+
V1Volume,
|
|
89
|
+
V1VolumeMount,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
self.pod_template.pod_spec.volumes = [
|
|
93
|
+
V1Volume(
|
|
94
|
+
name="dshm",
|
|
95
|
+
empty_dir=V1EmptyDirVolumeSource(medium="Memory", size_limit=self._shm_size),
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
self.pod_template.pod_spec.image_pull_secrets = [V1LocalObjectReference(name=self._secrets.ngc_image_secret)]
|
|
99
|
+
|
|
100
|
+
model_server_container = self.pod_template.pod_spec.init_containers[0]
|
|
101
|
+
|
|
102
|
+
if self._secrets.ngc_secret_group:
|
|
103
|
+
ngc_api_key = f"$({self._secrets.secrets_prefix}{self._secrets.ngc_secret_group}_{self._secrets.ngc_secret_key})".upper()
|
|
104
|
+
else:
|
|
105
|
+
ngc_api_key = f"$({self._secrets.secrets_prefix}{self._secrets.ngc_secret_key})".upper()
|
|
106
|
+
|
|
107
|
+
if model_server_container.env:
|
|
108
|
+
model_server_container.env.append(V1EnvVar(name="NGC_API_KEY", value=ngc_api_key))
|
|
109
|
+
else:
|
|
110
|
+
model_server_container.env = [V1EnvVar(name="NGC_API_KEY", value=ngc_api_key)]
|
|
111
|
+
|
|
112
|
+
model_server_container.volume_mounts = [V1VolumeMount(name="dshm", mount_path="/dev/shm")]
|
|
113
|
+
model_server_container.security_context = V1SecurityContext(run_as_user=1000)
|
|
114
|
+
|
|
115
|
+
# Download HF LoRA adapters
|
|
116
|
+
if self._hf_repo_ids:
|
|
117
|
+
if not self._lora_adapter_mem:
|
|
118
|
+
raise ValueError("Memory to allocate to download LoRA adapters must be set.")
|
|
119
|
+
|
|
120
|
+
if self._secrets.hf_token_group:
|
|
121
|
+
hf_key = f"{self._secrets.hf_token_group}_{self._secrets.hf_token_key}".upper()
|
|
122
|
+
elif self._secrets.hf_token_key:
|
|
123
|
+
hf_key = self._secrets.hf_token_key.upper()
|
|
124
|
+
else:
|
|
125
|
+
hf_key = ""
|
|
126
|
+
|
|
127
|
+
local_peft_dir_env = next(
|
|
128
|
+
(env for env in model_server_container.env if env.name == "NIM_PEFT_SOURCE"),
|
|
129
|
+
None,
|
|
130
|
+
)
|
|
131
|
+
if local_peft_dir_env:
|
|
132
|
+
mount_path = local_peft_dir_env.value
|
|
133
|
+
else:
|
|
134
|
+
raise ValueError("NIM_PEFT_SOURCE environment variable must be set.")
|
|
135
|
+
|
|
136
|
+
self.pod_template.pod_spec.volumes.append(V1Volume(name="lora", empty_dir={}))
|
|
137
|
+
model_server_container.volume_mounts.append(V1VolumeMount(name="lora", mount_path=mount_path))
|
|
138
|
+
|
|
139
|
+
self.pod_template.pod_spec.init_containers.insert(
|
|
140
|
+
0,
|
|
141
|
+
V1Container(
|
|
142
|
+
name="download-loras",
|
|
143
|
+
image="python:3.12-alpine",
|
|
144
|
+
command=[
|
|
145
|
+
"sh",
|
|
146
|
+
"-c",
|
|
147
|
+
f"""
|
|
148
|
+
pip install -U "huggingface_hub[cli]"
|
|
149
|
+
|
|
150
|
+
export LOCAL_PEFT_DIRECTORY={mount_path}
|
|
151
|
+
mkdir -p $LOCAL_PEFT_DIRECTORY
|
|
152
|
+
|
|
153
|
+
TOKEN_VAR_NAME={self._secrets.secrets_prefix}{hf_key}
|
|
154
|
+
|
|
155
|
+
# Check if HF token is provided and login if so
|
|
156
|
+
if [ -n "$(printenv $TOKEN_VAR_NAME)" ]; then
|
|
157
|
+
huggingface-cli login --token "$(printenv $TOKEN_VAR_NAME)"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Download LoRAs from Huggingface Hub
|
|
161
|
+
{"".join([f'''
|
|
162
|
+
mkdir -p $LOCAL_PEFT_DIRECTORY/{repo_id.split("/")[-1]}
|
|
163
|
+
huggingface-cli download {repo_id} adapter_config.json adapter_model.safetensors --local-dir $LOCAL_PEFT_DIRECTORY/{repo_id.split("/")[-1]}
|
|
164
|
+
''' for repo_id in self._hf_repo_ids])}
|
|
165
|
+
|
|
166
|
+
chmod -R 777 $LOCAL_PEFT_DIRECTORY
|
|
167
|
+
""",
|
|
168
|
+
],
|
|
169
|
+
resources=V1ResourceRequirements(
|
|
170
|
+
requests={"cpu": 1, "memory": self._lora_adapter_mem},
|
|
171
|
+
limits={"cpu": 1, "memory": self._lora_adapter_mem},
|
|
172
|
+
),
|
|
173
|
+
volume_mounts=[
|
|
174
|
+
V1VolumeMount(
|
|
175
|
+
name="lora",
|
|
176
|
+
mount_path=mount_path,
|
|
177
|
+
)
|
|
178
|
+
],
|
|
179
|
+
),
|
|
180
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from flytekit import PodTemplate
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ModelInferenceTemplate:
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
image: Optional[str] = None,
|
|
10
|
+
health_endpoint: str = "/",
|
|
11
|
+
port: int = 8000,
|
|
12
|
+
cpu: int = 1,
|
|
13
|
+
gpu: int = 1,
|
|
14
|
+
mem: str = "1Gi",
|
|
15
|
+
env: Optional[
|
|
16
|
+
dict[str, str]
|
|
17
|
+
] = None, # https://docs.nvidia.com/nim/large-language-models/latest/configuration.html#environment-variables
|
|
18
|
+
):
|
|
19
|
+
from kubernetes.client.models import (
|
|
20
|
+
V1Container,
|
|
21
|
+
V1ContainerPort,
|
|
22
|
+
V1EnvVar,
|
|
23
|
+
V1HTTPGetAction,
|
|
24
|
+
V1PodSpec,
|
|
25
|
+
V1Probe,
|
|
26
|
+
V1ResourceRequirements,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
self._image = image
|
|
30
|
+
self._health_endpoint = health_endpoint
|
|
31
|
+
self._port = port
|
|
32
|
+
self._cpu = cpu
|
|
33
|
+
self._gpu = gpu
|
|
34
|
+
self._mem = mem
|
|
35
|
+
self._env = env
|
|
36
|
+
|
|
37
|
+
self._pod_template = PodTemplate()
|
|
38
|
+
|
|
39
|
+
if env and not isinstance(env, dict):
|
|
40
|
+
raise ValueError("env must be a dict.")
|
|
41
|
+
|
|
42
|
+
self._pod_template.pod_spec = V1PodSpec(
|
|
43
|
+
containers=[],
|
|
44
|
+
init_containers=[
|
|
45
|
+
V1Container(
|
|
46
|
+
name="model-server",
|
|
47
|
+
image=self._image,
|
|
48
|
+
ports=[V1ContainerPort(container_port=self._port)],
|
|
49
|
+
resources=V1ResourceRequirements(
|
|
50
|
+
requests={
|
|
51
|
+
"cpu": self._cpu,
|
|
52
|
+
"nvidia.com/gpu": self._gpu,
|
|
53
|
+
"memory": self._mem,
|
|
54
|
+
},
|
|
55
|
+
limits={
|
|
56
|
+
"cpu": self._cpu,
|
|
57
|
+
"nvidia.com/gpu": self._gpu,
|
|
58
|
+
"memory": self._mem,
|
|
59
|
+
},
|
|
60
|
+
),
|
|
61
|
+
restart_policy="Always", # treat this container as a sidecar
|
|
62
|
+
env=([V1EnvVar(name=k, value=v) for k, v in self._env.items()] if self._env else None),
|
|
63
|
+
startup_probe=V1Probe(
|
|
64
|
+
http_get=V1HTTPGetAction(path=self._health_endpoint, port=self._port),
|
|
65
|
+
failure_threshold=100, # The model server initialization can take some time, so the failure threshold is increased to accommodate this delay.
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
],
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def pod_template(self):
|
|
73
|
+
return self._pod_template
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def base_url(self):
|
|
77
|
+
return f"http://localhost:{self._port}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('flytekitplugins',));importlib = __import__('importlib.util');__import__('importlib.machinery');m = sys.modules.setdefault('flytekitplugins', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('flytekitplugins', [os.path.dirname(p)])));m = m or sys.modules.setdefault('flytekitplugins', types.ModuleType('flytekitplugins'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: flytekitplugins-inference
|
|
3
|
+
Version: 1.13.1
|
|
4
|
+
Summary: This package enables seamless use of model inference sidecar services within Flyte
|
|
5
|
+
Author: flyteorg
|
|
6
|
+
Author-email: admin@flyte.org
|
|
7
|
+
License: apache2
|
|
8
|
+
Classifier: Intended Audience :: Science/Research
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Topic :: Software Development
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Requires-Dist: flytekit <2.0.0,>=1.13.0
|
|
23
|
+
Requires-Dist: kubernetes
|
|
24
|
+
Requires-Dist: openai
|
|
25
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
flytekitplugins_inference-1.13.1-py3.12-nspkg.pth,sha256=ya_zoT0ZM023a2lpUsRaqXsgDEknLucLLOWbbtFBPw4,512
|
|
2
|
+
flytekitplugins/inference/__init__.py,sha256=bbbo-H0lXf_TvEgPQnZAZ_w15W1jL-DAc-tWQqvYWzs,200
|
|
3
|
+
flytekitplugins/inference/sidecar_template.py,sha256=iYwSR63n6unLiLsZ8NhsLY0UMOZtKGcR5tTwyTUnsJ4,2572
|
|
4
|
+
flytekitplugins/inference/nim/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
flytekitplugins/inference/nim/serve.py,sha256=U11fTR7UkpF9c2KpHQ7MPeH9mz-fTIrLY3jt1zz2L-4,7488
|
|
6
|
+
flytekitplugins_inference-1.13.1.dist-info/METADATA,sha256=F53e1MqcpDC6lfPVOkWU753k3oRQ-leWJUXfTI8gAuI,1033
|
|
7
|
+
flytekitplugins_inference-1.13.1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
8
|
+
flytekitplugins_inference-1.13.1.dist-info/entry_points.txt,sha256=EQ6EAiE9IMGdtV3detqwGCowPbDj0pV8I3c1jSO9vbs,57
|
|
9
|
+
flytekitplugins_inference-1.13.1.dist-info/namespace_packages.txt,sha256=b2gTzXFHuV5afchaJ28HueRhYzj-8x5Ytr8n2twnAik,16
|
|
10
|
+
flytekitplugins_inference-1.13.1.dist-info/top_level.txt,sha256=b2gTzXFHuV5afchaJ28HueRhYzj-8x5Ytr8n2twnAik,16
|
|
11
|
+
flytekitplugins_inference-1.13.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
flytekitplugins
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
flytekitplugins
|