kiln-ai 0.13.2__tar.gz → 0.14.0__tar.gz
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 kiln-ai might be problematic. Click here for more details.
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/PKG-INFO +1 -1
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/base_finetune.py +0 -20
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/fireworks_finetune.py +161 -14
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/test_base_finetune.py +0 -9
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/test_fireworks_tinetune.py +494 -8
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/ml_model_list.py +1 -6
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/pyproject.toml +1 -1
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/.gitignore +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/.python-version +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/LICENSE.txt +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/README.md +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/index.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/data_gen/data_gen_task.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/data_gen.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/eval/base_eval.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/eval/eval_runner.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/eval/g_eval.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/eval/registry.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/eval.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/fine_tune/base_finetune.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/fine_tune/dataset_formatter.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/fine_tune/finetune_registry.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/fine_tune/openai_finetune.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/fine_tune.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/ml_model_list.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/model_adapters/base_adapter.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/model_adapters/litellm_adapter.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/model_adapters.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/prompt_builders.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/repair/repair_task.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters/repair.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/adapters.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/datamodel/dataset_split.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/datamodel/eval.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/datamodel/strict_mode.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/datamodel.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/utils/config.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/utils/formatting.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai/utils.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/kiln_ai.html +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/docs/kiln_core_docs/search.js +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/adapter_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/data_gen/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/data_gen/data_gen_prompts.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/data_gen/data_gen_task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/data_gen/test_data_gen_task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/base_eval.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/eval_runner.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/g_eval.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/test_base_eval.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/test_eval_runner.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/test_g_eval.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/eval/test_g_eval_data.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/dataset_formatter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/finetune_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/openai_finetune.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/test_dataset_formatter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/test_openai_finetune.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/test_together_finetune.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/fine_tune/together_finetune.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/base_adapter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/litellm_adapter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/litellm_config.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/test_base_adapter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/test_litellm_adapter.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/test_saving_adapter_results.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/model_adapters/test_structured_output.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/ollama_tools.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/base_parser.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/json_parser.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/parser_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/r1_parser.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/test_json_parser.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/test_parser_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/parsers/test_r1_parser.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/prompt_builders.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/provider_tools.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/repair/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/repair/repair_task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/repair/test_repair_task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/run_output.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_adapter_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_generate_docs.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_ollama_tools.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_prompt_adaptors.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_prompt_builders.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/adapters/test_provider_tools.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/basemodel.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/datamodel_enums.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/dataset_filters.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/dataset_split.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/eval.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/finetune.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/json_schema.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/model_cache.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/project.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/prompt.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/prompt_id.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/strict_mode.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/task_output.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/task_run.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_basemodel.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_dataset_filters.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_dataset_split.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_datasource.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_eval_model.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_example_models.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_json_schema.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_model_cache.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_model_perf.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_models.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_nested_save.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_output_rating.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_prompt_id.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_registry.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/datamodel/test_task.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/__init__.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/config.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/dataset_import.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/exhaustive_error.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/formatting.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/name_generator.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/test_config.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/test_dataset_import.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/kiln_ai/utils/test_name_geneator.py +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/setup.cfg +0 -0
- {kiln_ai-0.13.2 → kiln_ai-0.14.0}/uv.lock +0 -0
|
@@ -72,8 +72,6 @@ class BaseFinetuneAdapter(ABC):
|
|
|
72
72
|
Create and start a fine-tune.
|
|
73
73
|
"""
|
|
74
74
|
|
|
75
|
-
cls.check_valid_provider_model(provider_id, provider_base_model_id)
|
|
76
|
-
|
|
77
75
|
if not dataset.id:
|
|
78
76
|
raise ValueError("Dataset must have an id")
|
|
79
77
|
|
|
@@ -184,21 +182,3 @@ class BaseFinetuneAdapter(ABC):
|
|
|
184
182
|
for parameter_key in parameters:
|
|
185
183
|
if parameter_key not in allowed_parameters:
|
|
186
184
|
raise ValueError(f"Parameter {parameter_key} is not available")
|
|
187
|
-
|
|
188
|
-
@classmethod
|
|
189
|
-
def check_valid_provider_model(
|
|
190
|
-
cls, provider_id: str, provider_base_model_id: str
|
|
191
|
-
) -> None:
|
|
192
|
-
"""
|
|
193
|
-
Check if the provider and base model are valid.
|
|
194
|
-
"""
|
|
195
|
-
for model in built_in_models:
|
|
196
|
-
for provider in model.providers:
|
|
197
|
-
if (
|
|
198
|
-
provider.name == provider_id
|
|
199
|
-
and provider.provider_finetune_id == provider_base_model_id
|
|
200
|
-
):
|
|
201
|
-
return
|
|
202
|
-
raise ValueError(
|
|
203
|
-
f"Provider {provider_id} with base model {provider_base_model_id} is not available"
|
|
204
|
-
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
|
+
from typing import List, Tuple
|
|
2
3
|
from uuid import uuid4
|
|
3
4
|
|
|
4
5
|
import httpx
|
|
@@ -13,6 +14,14 @@ from kiln_ai.adapters.fine_tune.dataset_formatter import DatasetFormat, DatasetF
|
|
|
13
14
|
from kiln_ai.datamodel import DatasetSplit, StructuredOutputMode, Task
|
|
14
15
|
from kiln_ai.utils.config import Config
|
|
15
16
|
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
# https://docs.fireworks.ai/fine-tuning/fine-tuning-models#supported-base-models-loras-on-serverless
|
|
20
|
+
serverless_models = [
|
|
21
|
+
"accounts/fireworks/models/llama-v3p1-8b-instruct",
|
|
22
|
+
"accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
23
|
+
]
|
|
24
|
+
|
|
16
25
|
|
|
17
26
|
class FireworksFinetune(BaseFinetuneAdapter):
|
|
18
27
|
"""
|
|
@@ -283,32 +292,54 @@ class FireworksFinetune(BaseFinetuneAdapter):
|
|
|
283
292
|
return {k: v for k, v in payload.items() if v is not None}
|
|
284
293
|
|
|
285
294
|
async def _deploy(self) -> bool:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
# https://docs.fireworks.ai/models/deploying#deploying-to-serverless
|
|
291
|
-
# This endpoint will return 400 if already deployed with code 9, so we consider that a success.
|
|
295
|
+
if self.datamodel.base_model_id in serverless_models:
|
|
296
|
+
return await self._deploy_serverless()
|
|
297
|
+
else:
|
|
298
|
+
return await self._check_or_deploy_server()
|
|
292
299
|
|
|
300
|
+
def api_key_and_account_id(self) -> Tuple[str, str]:
|
|
293
301
|
api_key = Config.shared().fireworks_api_key
|
|
294
302
|
account_id = Config.shared().fireworks_account_id
|
|
295
303
|
if not api_key or not account_id:
|
|
296
304
|
raise ValueError("Fireworks API key or account ID not set")
|
|
305
|
+
return api_key, account_id
|
|
297
306
|
|
|
307
|
+
def deployment_display_name(self) -> str:
|
|
308
|
+
# Limit the display name to 60 characters
|
|
309
|
+
display_name = f"Kiln AI fine-tuned model [ID:{self.datamodel.id}][name:{self.datamodel.name}]"[
|
|
310
|
+
:60
|
|
311
|
+
]
|
|
312
|
+
return display_name
|
|
313
|
+
|
|
314
|
+
async def model_id_checking_status(self) -> str | None:
|
|
298
315
|
# Model ID != fine tune ID on Fireworks. Model is the result of the tune job. Call status to get it.
|
|
299
316
|
status, model_id = await self._status()
|
|
300
317
|
if status.status != FineTuneStatusType.completed:
|
|
301
|
-
return
|
|
318
|
+
return None
|
|
302
319
|
if not model_id or not isinstance(model_id, str):
|
|
303
|
-
return
|
|
320
|
+
return None
|
|
321
|
+
return model_id
|
|
322
|
+
|
|
323
|
+
async def _deploy_serverless(self) -> bool:
|
|
324
|
+
# Now we "deploy" the model using PEFT serverless.
|
|
325
|
+
# A bit complicated: most fireworks deploys are server based.
|
|
326
|
+
# However, a Lora can be serverless (PEFT).
|
|
327
|
+
# By calling the deploy endpoint WITHOUT first creating a deployment ID, it will only deploy if it can be done serverless.
|
|
328
|
+
# https://docs.fireworks.ai/models/deploying#deploying-to-serverless
|
|
329
|
+
# This endpoint will return 400 if already deployed with code 9, so we consider that a success.
|
|
330
|
+
|
|
331
|
+
api_key, account_id = self.api_key_and_account_id()
|
|
304
332
|
|
|
305
333
|
url = f"https://api.fireworks.ai/v1/accounts/{account_id}/deployedModels"
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
334
|
+
model_id = await self.model_id_checking_status()
|
|
335
|
+
if not model_id:
|
|
336
|
+
logger.error(
|
|
337
|
+
"Model ID not found - can't deploy model to Fireworks serverless"
|
|
338
|
+
)
|
|
339
|
+
return False
|
|
340
|
+
|
|
310
341
|
payload = {
|
|
311
|
-
"displayName":
|
|
342
|
+
"displayName": self.deployment_display_name(),
|
|
312
343
|
"model": model_id,
|
|
313
344
|
}
|
|
314
345
|
headers = {
|
|
@@ -327,4 +358,120 @@ class FireworksFinetune(BaseFinetuneAdapter):
|
|
|
327
358
|
self.datamodel.save_to_file()
|
|
328
359
|
return True
|
|
329
360
|
|
|
361
|
+
logger.error(
|
|
362
|
+
f"Failed to deploy model to Fireworks serverless: [{response.status_code}] {response.text}"
|
|
363
|
+
)
|
|
330
364
|
return False
|
|
365
|
+
|
|
366
|
+
async def _check_or_deploy_server(self) -> bool:
|
|
367
|
+
"""
|
|
368
|
+
Check if the model is already deployed. If not, deploy it to a dedicated server.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
# Check if the model is already deployed
|
|
372
|
+
# If it's fine_tune_model_id is set, it might be deployed. However, Fireworks deletes them over time so we need to check.
|
|
373
|
+
if self.datamodel.fine_tune_model_id:
|
|
374
|
+
deployments = await self._fetch_all_deployments()
|
|
375
|
+
for deployment in deployments:
|
|
376
|
+
if deployment[
|
|
377
|
+
"baseModel"
|
|
378
|
+
] == self.datamodel.fine_tune_model_id and deployment["state"] in [
|
|
379
|
+
"READY",
|
|
380
|
+
"CREATING",
|
|
381
|
+
]:
|
|
382
|
+
return True
|
|
383
|
+
|
|
384
|
+
# If the model is not deployed, deploy it
|
|
385
|
+
return await self._deploy_server()
|
|
386
|
+
|
|
387
|
+
async def _deploy_server(self) -> bool:
|
|
388
|
+
# For models that are not serverless, we just need to deploy the model to a server.
|
|
389
|
+
# We use a scale-to-zero on-demand deployment. If you stop using it, it
|
|
390
|
+
# will scale to zero and charges will stop.
|
|
391
|
+
model_id = await self.model_id_checking_status()
|
|
392
|
+
if not model_id:
|
|
393
|
+
logger.error("Model ID not found - can't deploy model to Fireworks server")
|
|
394
|
+
return False
|
|
395
|
+
|
|
396
|
+
api_key, account_id = self.api_key_and_account_id()
|
|
397
|
+
url = f"https://api.fireworks.ai/v1/accounts/{account_id}/deployments"
|
|
398
|
+
|
|
399
|
+
payload = {
|
|
400
|
+
"displayName": self.deployment_display_name(),
|
|
401
|
+
"description": "Deployed by Kiln AI",
|
|
402
|
+
# Allow scale to zero
|
|
403
|
+
"minReplicaCount": 0,
|
|
404
|
+
"autoscalingPolicy": {
|
|
405
|
+
"scaleUpWindow": "30s",
|
|
406
|
+
"scaleDownWindow": "300s",
|
|
407
|
+
# Scale to zero after 5 minutes of inactivity - this is the minimum allowed
|
|
408
|
+
"scaleToZeroWindow": "300s",
|
|
409
|
+
},
|
|
410
|
+
"baseModel": model_id,
|
|
411
|
+
}
|
|
412
|
+
headers = {
|
|
413
|
+
"Authorization": f"Bearer {api_key}",
|
|
414
|
+
"Content-Type": "application/json",
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async with httpx.AsyncClient() as client:
|
|
418
|
+
response = await client.post(url, json=payload, headers=headers)
|
|
419
|
+
|
|
420
|
+
if response.status_code == 200:
|
|
421
|
+
basemodel = response.json().get("baseModel")
|
|
422
|
+
if basemodel is not None and isinstance(basemodel, str):
|
|
423
|
+
self.datamodel.fine_tune_model_id = basemodel
|
|
424
|
+
if self.datamodel.path:
|
|
425
|
+
self.datamodel.save_to_file()
|
|
426
|
+
return True
|
|
427
|
+
|
|
428
|
+
logger.error(
|
|
429
|
+
f"Failed to deploy model to Fireworks server: [{response.status_code}] {response.text}"
|
|
430
|
+
)
|
|
431
|
+
return False
|
|
432
|
+
|
|
433
|
+
async def _fetch_all_deployments(self) -> List[dict]:
|
|
434
|
+
"""
|
|
435
|
+
Fetch all deployments for an account.
|
|
436
|
+
"""
|
|
437
|
+
api_key, account_id = self.api_key_and_account_id()
|
|
438
|
+
|
|
439
|
+
url = f"https://api.fireworks.ai/v1/accounts/{account_id}/deployments"
|
|
440
|
+
|
|
441
|
+
params = {
|
|
442
|
+
# Note: filter param does not work for baseModel, which would have been ideal, and ideally would have been documented. Instead we'll fetch all and filter.
|
|
443
|
+
# Max page size
|
|
444
|
+
"pageSize": 200,
|
|
445
|
+
}
|
|
446
|
+
headers = {
|
|
447
|
+
"Authorization": f"Bearer {api_key}",
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
deployments = []
|
|
451
|
+
|
|
452
|
+
# Paginate through all deployments
|
|
453
|
+
async with httpx.AsyncClient() as client:
|
|
454
|
+
while True:
|
|
455
|
+
response = await client.get(url, params=params, headers=headers)
|
|
456
|
+
json = response.json()
|
|
457
|
+
if "deployments" not in json or not isinstance(
|
|
458
|
+
json["deployments"], list
|
|
459
|
+
):
|
|
460
|
+
raise ValueError(
|
|
461
|
+
f"Invalid response from Fireworks. Expected list of deployments in 'deployments' key: [{response.status_code}] {response.text}"
|
|
462
|
+
)
|
|
463
|
+
deployments.extend(json["deployments"])
|
|
464
|
+
next_page_token = json.get("nextPageToken")
|
|
465
|
+
if (
|
|
466
|
+
next_page_token
|
|
467
|
+
and isinstance(next_page_token, str)
|
|
468
|
+
and len(next_page_token) > 0
|
|
469
|
+
):
|
|
470
|
+
params = {
|
|
471
|
+
"pageSize": 200,
|
|
472
|
+
"pageToken": next_page_token,
|
|
473
|
+
}
|
|
474
|
+
else:
|
|
475
|
+
break
|
|
476
|
+
|
|
477
|
+
return deployments
|
|
@@ -261,15 +261,6 @@ async def test_create_and_start_no_parent_task_path():
|
|
|
261
261
|
)
|
|
262
262
|
|
|
263
263
|
|
|
264
|
-
def test_check_valid_provider_model():
|
|
265
|
-
MockFinetune.check_valid_provider_model("openai", "gpt-4o-mini-2024-07-18")
|
|
266
|
-
|
|
267
|
-
with pytest.raises(
|
|
268
|
-
ValueError, match="Provider openai with base model gpt-99 is not available"
|
|
269
|
-
):
|
|
270
|
-
MockFinetune.check_valid_provider_model("openai", "gpt-99")
|
|
271
|
-
|
|
272
|
-
|
|
273
264
|
async def test_create_and_start_invalid_train_split(mock_dataset):
|
|
274
265
|
# Test with an invalid train split name
|
|
275
266
|
mock_dataset.split_contents = {"valid_train": [], "valid_test": []}
|