kiln-ai 0.14.0__py3-none-any.whl → 0.15.0__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 kiln-ai might be problematic. Click here for more details.
- kiln_ai/adapters/eval/base_eval.py +7 -2
- kiln_ai/adapters/fine_tune/base_finetune.py +6 -3
- kiln_ai/adapters/fine_tune/dataset_formatter.py +4 -4
- kiln_ai/adapters/fine_tune/finetune_registry.py +2 -0
- kiln_ai/adapters/fine_tune/fireworks_finetune.py +2 -1
- kiln_ai/adapters/fine_tune/test_base_finetune.py +7 -0
- kiln_ai/adapters/fine_tune/test_dataset_formatter.py +3 -3
- kiln_ai/adapters/fine_tune/test_fireworks_tinetune.py +1 -1
- kiln_ai/adapters/fine_tune/test_vertex_finetune.py +586 -0
- kiln_ai/adapters/fine_tune/vertex_finetune.py +217 -0
- kiln_ai/adapters/ml_model_list.py +318 -37
- kiln_ai/adapters/model_adapters/base_adapter.py +15 -10
- kiln_ai/adapters/model_adapters/litellm_adapter.py +10 -5
- kiln_ai/adapters/provider_tools.py +7 -0
- kiln_ai/adapters/test_provider_tools.py +16 -0
- kiln_ai/datamodel/json_schema.py +24 -7
- kiln_ai/datamodel/task_output.py +9 -5
- kiln_ai/datamodel/task_run.py +29 -5
- kiln_ai/datamodel/test_example_models.py +104 -3
- kiln_ai/datamodel/test_json_schema.py +22 -3
- kiln_ai/datamodel/test_model_perf.py +3 -2
- {kiln_ai-0.14.0.dist-info → kiln_ai-0.15.0.dist-info}/METADATA +3 -2
- {kiln_ai-0.14.0.dist-info → kiln_ai-0.15.0.dist-info}/RECORD +25 -24
- kiln_ai/adapters/test_generate_docs.py +0 -69
- {kiln_ai-0.14.0.dist-info → kiln_ai-0.15.0.dist-info}/WHEEL +0 -0
- {kiln_ai-0.14.0.dist-info → kiln_ai-0.15.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import vertexai
|
|
5
|
+
from google.cloud import storage
|
|
6
|
+
from google.cloud.aiplatform_v1beta1 import types as gca_types
|
|
7
|
+
from vertexai.tuning import sft
|
|
8
|
+
|
|
9
|
+
from kiln_ai.adapters.fine_tune.base_finetune import (
|
|
10
|
+
BaseFinetuneAdapter,
|
|
11
|
+
FineTuneParameter,
|
|
12
|
+
FineTuneStatus,
|
|
13
|
+
FineTuneStatusType,
|
|
14
|
+
)
|
|
15
|
+
from kiln_ai.adapters.fine_tune.dataset_formatter import DatasetFormat, DatasetFormatter
|
|
16
|
+
from kiln_ai.datamodel import DatasetSplit, StructuredOutputMode, Task
|
|
17
|
+
from kiln_ai.utils.config import Config
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class VertexFinetune(BaseFinetuneAdapter):
|
|
23
|
+
"""
|
|
24
|
+
A fine-tuning adapter for Vertex AI.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
async def status(self) -> FineTuneStatus:
|
|
28
|
+
"""
|
|
29
|
+
Get the status of the fine-tune.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# Update the datamodel with the latest status if it has changed
|
|
33
|
+
status = await self._status()
|
|
34
|
+
if status.status != self.datamodel.latest_status:
|
|
35
|
+
self.datamodel.latest_status = status.status
|
|
36
|
+
if self.datamodel.path:
|
|
37
|
+
self.datamodel.save_to_file()
|
|
38
|
+
return status
|
|
39
|
+
|
|
40
|
+
async def _status(self) -> FineTuneStatus:
|
|
41
|
+
if not self.datamodel or not self.datamodel.provider_id:
|
|
42
|
+
return FineTuneStatus(
|
|
43
|
+
status=FineTuneStatusType.pending,
|
|
44
|
+
message="This fine-tune has not been started or has not been assigned a provider ID.",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
response = sft.SupervisedTuningJob(self.datamodel.provider_id)
|
|
48
|
+
# If the fine-tuned model ID has been updated, update the datamodel
|
|
49
|
+
try:
|
|
50
|
+
if self.datamodel.fine_tune_model_id != response.tuned_model_endpoint_name:
|
|
51
|
+
self.datamodel.fine_tune_model_id = response.tuned_model_endpoint_name
|
|
52
|
+
if self.datamodel.path:
|
|
53
|
+
self.datamodel.save_to_file()
|
|
54
|
+
except Exception as e:
|
|
55
|
+
# Don't let this error crash the status call
|
|
56
|
+
logger.warning(f"Error updating fine-tune model ID: {e}")
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
error = response.error
|
|
60
|
+
if error and error.code != 0:
|
|
61
|
+
return FineTuneStatus(
|
|
62
|
+
status=FineTuneStatusType.failed,
|
|
63
|
+
message=f"Fine Tune Job Error: {error.message} [{error.code}]",
|
|
64
|
+
)
|
|
65
|
+
state = response.state
|
|
66
|
+
if state in [
|
|
67
|
+
gca_types.JobState.JOB_STATE_FAILED,
|
|
68
|
+
gca_types.JobState.JOB_STATE_EXPIRED,
|
|
69
|
+
]:
|
|
70
|
+
return FineTuneStatus(
|
|
71
|
+
status=FineTuneStatusType.failed,
|
|
72
|
+
message="Fine Tune Job Failed",
|
|
73
|
+
)
|
|
74
|
+
if state in [
|
|
75
|
+
gca_types.JobState.JOB_STATE_CANCELLED,
|
|
76
|
+
gca_types.JobState.JOB_STATE_CANCELLING,
|
|
77
|
+
]:
|
|
78
|
+
return FineTuneStatus(
|
|
79
|
+
status=FineTuneStatusType.failed, message="Fine Tune Job Cancelled"
|
|
80
|
+
)
|
|
81
|
+
if state in [
|
|
82
|
+
gca_types.JobState.JOB_STATE_PENDING,
|
|
83
|
+
gca_types.JobState.JOB_STATE_QUEUED,
|
|
84
|
+
]:
|
|
85
|
+
return FineTuneStatus(
|
|
86
|
+
status=FineTuneStatusType.pending, message="Fine Tune Job Pending"
|
|
87
|
+
)
|
|
88
|
+
if state in [
|
|
89
|
+
gca_types.JobState.JOB_STATE_RUNNING,
|
|
90
|
+
]:
|
|
91
|
+
return FineTuneStatus(
|
|
92
|
+
status=FineTuneStatusType.running,
|
|
93
|
+
message="Fine Tune Job Running",
|
|
94
|
+
)
|
|
95
|
+
if state in [
|
|
96
|
+
gca_types.JobState.JOB_STATE_SUCCEEDED,
|
|
97
|
+
gca_types.JobState.JOB_STATE_PARTIALLY_SUCCEEDED,
|
|
98
|
+
]:
|
|
99
|
+
return FineTuneStatus(
|
|
100
|
+
status=FineTuneStatusType.completed, message="Fine Tune Job Completed"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if state not in [
|
|
104
|
+
gca_types.JobState.JOB_STATE_UPDATING,
|
|
105
|
+
gca_types.JobState.JOB_STATE_UNSPECIFIED,
|
|
106
|
+
gca_types.JobState.JOB_STATE_PAUSED,
|
|
107
|
+
]:
|
|
108
|
+
# While the above states map to "unknown", they are expected unknowns. Log if some new state appears we aren't expecting
|
|
109
|
+
logger.warning(f"Unknown Vertex AI Fine Tune Status: [{state}]")
|
|
110
|
+
|
|
111
|
+
return FineTuneStatus(
|
|
112
|
+
status=FineTuneStatusType.unknown, message=f"Unknown state: [{state}]"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
async def _start(self, dataset: DatasetSplit) -> None:
|
|
116
|
+
task = self.datamodel.parent_task()
|
|
117
|
+
if not task:
|
|
118
|
+
raise ValueError("Task is required to start a fine-tune")
|
|
119
|
+
|
|
120
|
+
# Use chat format for unstructured output, and JSON for formatted output
|
|
121
|
+
format = DatasetFormat.VERTEX_GEMINI
|
|
122
|
+
if task.output_json_schema:
|
|
123
|
+
self.datamodel.structured_output_mode = StructuredOutputMode.json_mode
|
|
124
|
+
train_file_id = await self.generate_and_upload_jsonl(
|
|
125
|
+
dataset, self.datamodel.train_split_name, task, format
|
|
126
|
+
)
|
|
127
|
+
validation_file_id = None
|
|
128
|
+
if self.datamodel.validation_split_name:
|
|
129
|
+
validation_file_id = await self.generate_and_upload_jsonl(
|
|
130
|
+
dataset, self.datamodel.validation_split_name, task, format
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
hyperparameters = self.datamodel.parameters
|
|
134
|
+
|
|
135
|
+
project, location = self.get_vertex_provider_location()
|
|
136
|
+
vertexai.init(project=project, location=location)
|
|
137
|
+
|
|
138
|
+
sft_tuning_job = sft.train(
|
|
139
|
+
source_model=self.datamodel.base_model_id,
|
|
140
|
+
train_dataset=train_file_id,
|
|
141
|
+
validation_dataset=validation_file_id,
|
|
142
|
+
tuned_model_display_name=f"kiln_finetune_{self.datamodel.id}",
|
|
143
|
+
# It is recommended to use auto-selection and leave them unset
|
|
144
|
+
epochs=hyperparameters.get("epochs", None), # type: ignore
|
|
145
|
+
adapter_size=hyperparameters.get("adapter_size", None), # type: ignore
|
|
146
|
+
learning_rate_multiplier=hyperparameters.get(
|
|
147
|
+
"learning_rate_multiplier", None
|
|
148
|
+
), # type: ignore
|
|
149
|
+
labels={
|
|
150
|
+
"source": "kiln",
|
|
151
|
+
"kiln_finetune_id": str(self.datamodel.id),
|
|
152
|
+
"kiln_task_id": str(task.id),
|
|
153
|
+
},
|
|
154
|
+
)
|
|
155
|
+
self.datamodel.provider_id = sft_tuning_job.resource_name
|
|
156
|
+
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
async def generate_and_upload_jsonl(
|
|
160
|
+
self, dataset: DatasetSplit, split_name: str, task: Task, format: DatasetFormat
|
|
161
|
+
) -> str:
|
|
162
|
+
formatter = DatasetFormatter(
|
|
163
|
+
dataset, self.datamodel.system_message, self.datamodel.thinking_instructions
|
|
164
|
+
)
|
|
165
|
+
path = formatter.dump_to_file(split_name, format, self.datamodel.data_strategy)
|
|
166
|
+
|
|
167
|
+
project, location = self.get_vertex_provider_location()
|
|
168
|
+
storage_client = storage.Client(project=project)
|
|
169
|
+
|
|
170
|
+
bucket_name = "kiln-ai-data"
|
|
171
|
+
|
|
172
|
+
# Check if bucket exists and create it if it doesn't
|
|
173
|
+
if not storage_client.lookup_bucket(bucket_name):
|
|
174
|
+
bucket = storage_client.create_bucket(bucket_name, location=location)
|
|
175
|
+
else:
|
|
176
|
+
bucket = storage_client.bucket(bucket_name)
|
|
177
|
+
|
|
178
|
+
# Create a blob and upload
|
|
179
|
+
epoch_timestamp = int(time.time())
|
|
180
|
+
blob_name = f"{epoch_timestamp}/{path.name}"
|
|
181
|
+
blob = bucket.blob(blob_name)
|
|
182
|
+
blob.upload_from_filename(path)
|
|
183
|
+
|
|
184
|
+
return f"gs://{bucket.name}/{blob.name}"
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def available_parameters(cls) -> list[FineTuneParameter]:
|
|
188
|
+
return [
|
|
189
|
+
FineTuneParameter(
|
|
190
|
+
name="learning_rate_multiplier",
|
|
191
|
+
type="float",
|
|
192
|
+
description="Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. Defaults to 1.0 (don't scale vertex's learning rate).",
|
|
193
|
+
optional=True,
|
|
194
|
+
),
|
|
195
|
+
FineTuneParameter(
|
|
196
|
+
name="epochs",
|
|
197
|
+
type="int",
|
|
198
|
+
description="The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. Defaults to 'auto'",
|
|
199
|
+
optional=True,
|
|
200
|
+
),
|
|
201
|
+
FineTuneParameter(
|
|
202
|
+
name="adapter_size",
|
|
203
|
+
type="int",
|
|
204
|
+
description="The size of the adapter to use for the fine-tune. One of 1, 4, 8, or 16. By default Vertex will auto-select a size.",
|
|
205
|
+
optional=True,
|
|
206
|
+
),
|
|
207
|
+
]
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def get_vertex_provider_location(cls) -> tuple[str, str]:
|
|
211
|
+
project = Config.shared().vertex_project_id
|
|
212
|
+
location = Config.shared().vertex_location
|
|
213
|
+
if not project or not location:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
"Google Vertex project and location must be set in Kiln settings to fine tune."
|
|
216
|
+
)
|
|
217
|
+
return project, location
|
|
@@ -70,9 +70,18 @@ class ModelName(str, Enum):
|
|
|
70
70
|
llama_3_3_70b = "llama_3_3_70b"
|
|
71
71
|
gpt_4o_mini = "gpt_4o_mini"
|
|
72
72
|
gpt_4o = "gpt_4o"
|
|
73
|
+
gpt_4_1 = "gpt_4_1"
|
|
74
|
+
gpt_4_1_mini = "gpt_4_1_mini"
|
|
75
|
+
gpt_4_1_nano = "gpt_4_1_nano"
|
|
76
|
+
gpt_o3_low = "gpt_o3_low"
|
|
77
|
+
gpt_o3_medium = "gpt_o3_medium"
|
|
78
|
+
gpt_o3_high = "gpt_o3_high"
|
|
73
79
|
gpt_o1_low = "gpt_o1_low"
|
|
74
80
|
gpt_o1_medium = "gpt_o1_medium"
|
|
75
81
|
gpt_o1_high = "gpt_o1_high"
|
|
82
|
+
gpt_o4_mini_low = "gpt_o4_mini_low"
|
|
83
|
+
gpt_o4_mini_medium = "gpt_o4_mini_medium"
|
|
84
|
+
gpt_o4_mini_high = "gpt_o4_mini_high"
|
|
76
85
|
gpt_o3_mini_low = "gpt_o3_mini_low"
|
|
77
86
|
gpt_o3_mini_medium = "gpt_o3_mini_medium"
|
|
78
87
|
gpt_o3_mini_high = "gpt_o3_mini_high"
|
|
@@ -97,6 +106,9 @@ class ModelName(str, Enum):
|
|
|
97
106
|
gemini_1_5_flash_8b = "gemini_1_5_flash_8b"
|
|
98
107
|
gemini_1_5_pro = "gemini_1_5_pro"
|
|
99
108
|
gemini_2_0_flash = "gemini_2_0_flash"
|
|
109
|
+
gemini_2_0_flash_lite = "gemini_2_0_flash_lite"
|
|
110
|
+
gemini_2_5_pro = "gemini_2_5_pro"
|
|
111
|
+
gemini_2_5_flash = "gemini_2_5_flash"
|
|
100
112
|
nemotron_70b = "nemotron_70b"
|
|
101
113
|
mixtral_8x7b = "mixtral_8x7b"
|
|
102
114
|
qwen_2p5_7b = "qwen_2p5_7b"
|
|
@@ -181,29 +193,77 @@ class KilnModel(BaseModel):
|
|
|
181
193
|
|
|
182
194
|
|
|
183
195
|
built_in_models: List[KilnModel] = [
|
|
184
|
-
# GPT
|
|
196
|
+
# GPT 4.1
|
|
185
197
|
KilnModel(
|
|
186
198
|
family=ModelFamily.gpt,
|
|
187
|
-
name=ModelName.
|
|
188
|
-
friendly_name="GPT
|
|
199
|
+
name=ModelName.gpt_4_1,
|
|
200
|
+
friendly_name="GPT 4.1",
|
|
189
201
|
providers=[
|
|
190
202
|
KilnModelProvider(
|
|
191
203
|
name=ModelProviderName.openai,
|
|
192
|
-
model_id="gpt-
|
|
193
|
-
provider_finetune_id="gpt-
|
|
204
|
+
model_id="gpt-4.1",
|
|
205
|
+
provider_finetune_id="gpt-4.1-2025-04-14",
|
|
194
206
|
structured_output_mode=StructuredOutputMode.json_schema,
|
|
195
207
|
supports_logprobs=True,
|
|
196
208
|
),
|
|
197
209
|
KilnModelProvider(
|
|
198
210
|
name=ModelProviderName.openrouter,
|
|
199
|
-
model_id="openai/gpt-
|
|
211
|
+
model_id="openai/gpt-4.1",
|
|
200
212
|
structured_output_mode=StructuredOutputMode.json_schema,
|
|
201
213
|
supports_logprobs=True,
|
|
202
|
-
logprobs_openrouter_options=True,
|
|
203
214
|
),
|
|
204
215
|
KilnModelProvider(
|
|
205
216
|
name=ModelProviderName.azure_openai,
|
|
206
|
-
model_id="gpt-
|
|
217
|
+
model_id="gpt-4.1",
|
|
218
|
+
),
|
|
219
|
+
],
|
|
220
|
+
),
|
|
221
|
+
# GPT 4.1 Mini
|
|
222
|
+
KilnModel(
|
|
223
|
+
family=ModelFamily.gpt,
|
|
224
|
+
name=ModelName.gpt_4_1_mini,
|
|
225
|
+
friendly_name="GPT 4.1 Mini",
|
|
226
|
+
providers=[
|
|
227
|
+
KilnModelProvider(
|
|
228
|
+
name=ModelProviderName.openai,
|
|
229
|
+
model_id="gpt-4.1-mini",
|
|
230
|
+
provider_finetune_id="gpt-4.1-mini-2025-04-14",
|
|
231
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
232
|
+
supports_logprobs=True,
|
|
233
|
+
),
|
|
234
|
+
KilnModelProvider(
|
|
235
|
+
name=ModelProviderName.openrouter,
|
|
236
|
+
model_id="openai/gpt-4.1-mini",
|
|
237
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
238
|
+
supports_logprobs=True,
|
|
239
|
+
),
|
|
240
|
+
KilnModelProvider(
|
|
241
|
+
name=ModelProviderName.azure_openai,
|
|
242
|
+
model_id="gpt-4.1-mini",
|
|
243
|
+
),
|
|
244
|
+
],
|
|
245
|
+
),
|
|
246
|
+
# GPT 4.1 Nano
|
|
247
|
+
KilnModel(
|
|
248
|
+
family=ModelFamily.gpt,
|
|
249
|
+
name=ModelName.gpt_4_1_nano,
|
|
250
|
+
friendly_name="GPT 4.1 Nano",
|
|
251
|
+
providers=[
|
|
252
|
+
KilnModelProvider(
|
|
253
|
+
name=ModelProviderName.openai,
|
|
254
|
+
model_id="gpt-4.1-nano",
|
|
255
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
256
|
+
supports_logprobs=True,
|
|
257
|
+
),
|
|
258
|
+
KilnModelProvider(
|
|
259
|
+
name=ModelProviderName.openrouter,
|
|
260
|
+
model_id="openai/gpt-4.1-nano",
|
|
261
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
262
|
+
supports_logprobs=True,
|
|
263
|
+
),
|
|
264
|
+
KilnModelProvider(
|
|
265
|
+
name=ModelProviderName.azure_openai,
|
|
266
|
+
model_id="gpt-4.1-nano",
|
|
207
267
|
),
|
|
208
268
|
],
|
|
209
269
|
),
|
|
@@ -233,6 +293,102 @@ built_in_models: List[KilnModel] = [
|
|
|
233
293
|
),
|
|
234
294
|
],
|
|
235
295
|
),
|
|
296
|
+
# GPT 4o Mini
|
|
297
|
+
KilnModel(
|
|
298
|
+
family=ModelFamily.gpt,
|
|
299
|
+
name=ModelName.gpt_4o_mini,
|
|
300
|
+
friendly_name="GPT 4o Mini",
|
|
301
|
+
providers=[
|
|
302
|
+
KilnModelProvider(
|
|
303
|
+
name=ModelProviderName.openai,
|
|
304
|
+
model_id="gpt-4o-mini",
|
|
305
|
+
provider_finetune_id="gpt-4o-mini-2024-07-18",
|
|
306
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
307
|
+
supports_logprobs=True,
|
|
308
|
+
),
|
|
309
|
+
KilnModelProvider(
|
|
310
|
+
name=ModelProviderName.openrouter,
|
|
311
|
+
model_id="openai/gpt-4o-mini",
|
|
312
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
313
|
+
supports_logprobs=True,
|
|
314
|
+
logprobs_openrouter_options=True,
|
|
315
|
+
),
|
|
316
|
+
KilnModelProvider(
|
|
317
|
+
name=ModelProviderName.azure_openai,
|
|
318
|
+
model_id="gpt-4o-mini",
|
|
319
|
+
),
|
|
320
|
+
],
|
|
321
|
+
),
|
|
322
|
+
# GPT o4 Mini Low
|
|
323
|
+
KilnModel(
|
|
324
|
+
family=ModelFamily.gpt,
|
|
325
|
+
name=ModelName.gpt_o4_mini_low,
|
|
326
|
+
friendly_name="GPT o4 Mini - Low",
|
|
327
|
+
providers=[
|
|
328
|
+
KilnModelProvider(
|
|
329
|
+
name=ModelProviderName.openai,
|
|
330
|
+
model_id="o4-mini",
|
|
331
|
+
thinking_level="low",
|
|
332
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
333
|
+
),
|
|
334
|
+
KilnModelProvider(
|
|
335
|
+
name=ModelProviderName.azure_openai,
|
|
336
|
+
model_id="o4-mini",
|
|
337
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
338
|
+
thinking_level="low",
|
|
339
|
+
),
|
|
340
|
+
],
|
|
341
|
+
),
|
|
342
|
+
# GPT o4 Mini Medium
|
|
343
|
+
KilnModel(
|
|
344
|
+
family=ModelFamily.gpt,
|
|
345
|
+
name=ModelName.gpt_o4_mini_medium,
|
|
346
|
+
friendly_name="GPT o4 Mini - Medium",
|
|
347
|
+
providers=[
|
|
348
|
+
KilnModelProvider(
|
|
349
|
+
name=ModelProviderName.openai,
|
|
350
|
+
model_id="o4-mini",
|
|
351
|
+
thinking_level="medium",
|
|
352
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
353
|
+
),
|
|
354
|
+
KilnModelProvider(
|
|
355
|
+
name=ModelProviderName.azure_openai,
|
|
356
|
+
model_id="o4-mini",
|
|
357
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
358
|
+
thinking_level="medium",
|
|
359
|
+
),
|
|
360
|
+
KilnModelProvider(
|
|
361
|
+
name=ModelProviderName.openrouter,
|
|
362
|
+
model_id="openai/o4-mini",
|
|
363
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
364
|
+
),
|
|
365
|
+
],
|
|
366
|
+
),
|
|
367
|
+
# GPT o4 Mini High
|
|
368
|
+
KilnModel(
|
|
369
|
+
family=ModelFamily.gpt,
|
|
370
|
+
name=ModelName.gpt_o4_mini_high,
|
|
371
|
+
friendly_name="GPT o4 Mini - High",
|
|
372
|
+
providers=[
|
|
373
|
+
KilnModelProvider(
|
|
374
|
+
name=ModelProviderName.openai,
|
|
375
|
+
model_id="o4-mini",
|
|
376
|
+
thinking_level="high",
|
|
377
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
378
|
+
),
|
|
379
|
+
KilnModelProvider(
|
|
380
|
+
name=ModelProviderName.azure_openai,
|
|
381
|
+
model_id="o4-mini",
|
|
382
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
383
|
+
thinking_level="high",
|
|
384
|
+
),
|
|
385
|
+
KilnModelProvider(
|
|
386
|
+
name=ModelProviderName.openrouter,
|
|
387
|
+
model_id="openai/o4-mini-high",
|
|
388
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
389
|
+
),
|
|
390
|
+
],
|
|
391
|
+
),
|
|
236
392
|
# GPT o3 Mini Low
|
|
237
393
|
KilnModel(
|
|
238
394
|
family=ModelFamily.gpt,
|
|
@@ -293,6 +449,66 @@ built_in_models: List[KilnModel] = [
|
|
|
293
449
|
),
|
|
294
450
|
],
|
|
295
451
|
),
|
|
452
|
+
# GPT o3 Low
|
|
453
|
+
KilnModel(
|
|
454
|
+
family=ModelFamily.gpt,
|
|
455
|
+
name=ModelName.gpt_o3_low,
|
|
456
|
+
friendly_name="GPT o3 - Low",
|
|
457
|
+
providers=[
|
|
458
|
+
KilnModelProvider(
|
|
459
|
+
name=ModelProviderName.openai,
|
|
460
|
+
model_id="o3",
|
|
461
|
+
thinking_level="low",
|
|
462
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
463
|
+
),
|
|
464
|
+
KilnModelProvider(
|
|
465
|
+
name=ModelProviderName.azure_openai,
|
|
466
|
+
model_id="o3",
|
|
467
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
468
|
+
thinking_level="low",
|
|
469
|
+
),
|
|
470
|
+
],
|
|
471
|
+
),
|
|
472
|
+
# GPT o3 Medium
|
|
473
|
+
KilnModel(
|
|
474
|
+
family=ModelFamily.gpt,
|
|
475
|
+
name=ModelName.gpt_o3_medium,
|
|
476
|
+
friendly_name="GPT o3 - Medium",
|
|
477
|
+
providers=[
|
|
478
|
+
KilnModelProvider(
|
|
479
|
+
name=ModelProviderName.openai,
|
|
480
|
+
model_id="o3",
|
|
481
|
+
thinking_level="medium",
|
|
482
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
483
|
+
),
|
|
484
|
+
KilnModelProvider(
|
|
485
|
+
name=ModelProviderName.azure_openai,
|
|
486
|
+
model_id="o3",
|
|
487
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
488
|
+
thinking_level="medium",
|
|
489
|
+
),
|
|
490
|
+
],
|
|
491
|
+
),
|
|
492
|
+
# GPT o3 High
|
|
493
|
+
KilnModel(
|
|
494
|
+
family=ModelFamily.gpt,
|
|
495
|
+
name=ModelName.gpt_o3_high,
|
|
496
|
+
friendly_name="GPT o3 - High",
|
|
497
|
+
providers=[
|
|
498
|
+
KilnModelProvider(
|
|
499
|
+
name=ModelProviderName.openai,
|
|
500
|
+
model_id="o3",
|
|
501
|
+
thinking_level="high",
|
|
502
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
503
|
+
),
|
|
504
|
+
KilnModelProvider(
|
|
505
|
+
name=ModelProviderName.azure_openai,
|
|
506
|
+
model_id="o3",
|
|
507
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
508
|
+
thinking_level="high",
|
|
509
|
+
),
|
|
510
|
+
],
|
|
511
|
+
),
|
|
296
512
|
# GPT o1 Low
|
|
297
513
|
KilnModel(
|
|
298
514
|
family=ModelFamily.gpt,
|
|
@@ -440,6 +656,100 @@ built_in_models: List[KilnModel] = [
|
|
|
440
656
|
),
|
|
441
657
|
],
|
|
442
658
|
),
|
|
659
|
+
# Gemini 2.5 Pro
|
|
660
|
+
KilnModel(
|
|
661
|
+
family=ModelFamily.gemini,
|
|
662
|
+
name=ModelName.gemini_2_5_pro,
|
|
663
|
+
friendly_name="Gemini 2.5 Pro",
|
|
664
|
+
providers=[
|
|
665
|
+
KilnModelProvider(
|
|
666
|
+
name=ModelProviderName.openrouter,
|
|
667
|
+
model_id="google/gemini-2.5-pro-preview-03-25",
|
|
668
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
669
|
+
),
|
|
670
|
+
KilnModelProvider(
|
|
671
|
+
name=ModelProviderName.gemini_api,
|
|
672
|
+
model_id="gemini-2.5-pro-preview-03-25",
|
|
673
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
674
|
+
),
|
|
675
|
+
KilnModelProvider(
|
|
676
|
+
name=ModelProviderName.vertex,
|
|
677
|
+
model_id="gemini-2.5-pro-preview-03-25",
|
|
678
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
679
|
+
),
|
|
680
|
+
],
|
|
681
|
+
),
|
|
682
|
+
# Gemini 2.5 Flash
|
|
683
|
+
KilnModel(
|
|
684
|
+
family=ModelFamily.gemini,
|
|
685
|
+
name=ModelName.gemini_2_5_flash,
|
|
686
|
+
friendly_name="Gemini 2.5 Flash",
|
|
687
|
+
providers=[
|
|
688
|
+
KilnModelProvider(
|
|
689
|
+
name=ModelProviderName.openrouter,
|
|
690
|
+
model_id="google/gemini-2.5-flash-preview",
|
|
691
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
692
|
+
),
|
|
693
|
+
KilnModelProvider(
|
|
694
|
+
name=ModelProviderName.gemini_api,
|
|
695
|
+
model_id="gemini-2.5-flash-preview-04-17",
|
|
696
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
697
|
+
),
|
|
698
|
+
KilnModelProvider(
|
|
699
|
+
name=ModelProviderName.vertex,
|
|
700
|
+
model_id="gemini-2.5-flash-preview-04-17",
|
|
701
|
+
structured_output_mode=StructuredOutputMode.json_schema,
|
|
702
|
+
),
|
|
703
|
+
],
|
|
704
|
+
),
|
|
705
|
+
# Gemini 2.0 Flash
|
|
706
|
+
KilnModel(
|
|
707
|
+
family=ModelFamily.gemini,
|
|
708
|
+
name=ModelName.gemini_2_0_flash,
|
|
709
|
+
friendly_name="Gemini 2.0 Flash",
|
|
710
|
+
providers=[
|
|
711
|
+
KilnModelProvider(
|
|
712
|
+
name=ModelProviderName.openrouter,
|
|
713
|
+
model_id="google/gemini-2.0-flash-001",
|
|
714
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
715
|
+
),
|
|
716
|
+
KilnModelProvider(
|
|
717
|
+
name=ModelProviderName.gemini_api,
|
|
718
|
+
model_id="gemini-2.0-flash",
|
|
719
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
720
|
+
),
|
|
721
|
+
KilnModelProvider(
|
|
722
|
+
name=ModelProviderName.vertex,
|
|
723
|
+
model_id="gemini-2.0-flash",
|
|
724
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
725
|
+
provider_finetune_id="gemini-2.0-flash-001",
|
|
726
|
+
),
|
|
727
|
+
],
|
|
728
|
+
),
|
|
729
|
+
# Gemini 2.0 Flash Lite
|
|
730
|
+
KilnModel(
|
|
731
|
+
family=ModelFamily.gemini,
|
|
732
|
+
name=ModelName.gemini_2_0_flash_lite,
|
|
733
|
+
friendly_name="Gemini 2.0 Flash Lite",
|
|
734
|
+
providers=[
|
|
735
|
+
KilnModelProvider(
|
|
736
|
+
name=ModelProviderName.openrouter,
|
|
737
|
+
model_id="google/gemini-2.0-flash-lite-001",
|
|
738
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
739
|
+
),
|
|
740
|
+
KilnModelProvider(
|
|
741
|
+
name=ModelProviderName.gemini_api,
|
|
742
|
+
model_id="gemini-2.0-flash-lite",
|
|
743
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
744
|
+
),
|
|
745
|
+
KilnModelProvider(
|
|
746
|
+
name=ModelProviderName.vertex,
|
|
747
|
+
model_id="gemini-2.0-flash-lite",
|
|
748
|
+
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
749
|
+
provider_finetune_id="gemini-2.0-flash-lite-001",
|
|
750
|
+
),
|
|
751
|
+
],
|
|
752
|
+
),
|
|
443
753
|
# Gemini 1.5 Pro
|
|
444
754
|
KilnModel(
|
|
445
755
|
family=ModelFamily.gemini,
|
|
@@ -506,29 +816,6 @@ built_in_models: List[KilnModel] = [
|
|
|
506
816
|
),
|
|
507
817
|
],
|
|
508
818
|
),
|
|
509
|
-
# Gemini 2.0 Flash
|
|
510
|
-
KilnModel(
|
|
511
|
-
family=ModelFamily.gemini,
|
|
512
|
-
name=ModelName.gemini_2_0_flash,
|
|
513
|
-
friendly_name="Gemini 2.0 Flash",
|
|
514
|
-
providers=[
|
|
515
|
-
KilnModelProvider(
|
|
516
|
-
name=ModelProviderName.openrouter,
|
|
517
|
-
model_id="google/gemini-2.0-flash-001",
|
|
518
|
-
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
519
|
-
),
|
|
520
|
-
KilnModelProvider(
|
|
521
|
-
name=ModelProviderName.gemini_api,
|
|
522
|
-
model_id="gemini-2.0-flash",
|
|
523
|
-
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
524
|
-
),
|
|
525
|
-
KilnModelProvider(
|
|
526
|
-
name=ModelProviderName.vertex,
|
|
527
|
-
model_id="gemini-2.0-flash",
|
|
528
|
-
structured_output_mode=StructuredOutputMode.json_instruction_and_object,
|
|
529
|
-
),
|
|
530
|
-
],
|
|
531
|
-
),
|
|
532
819
|
# Nemotron 70B
|
|
533
820
|
KilnModel(
|
|
534
821
|
family=ModelFamily.llama,
|
|
@@ -760,12 +1047,6 @@ built_in_models: List[KilnModel] = [
|
|
|
760
1047
|
supports_data_gen=False,
|
|
761
1048
|
model_id="llama3.2",
|
|
762
1049
|
),
|
|
763
|
-
KilnModelProvider(
|
|
764
|
-
name=ModelProviderName.fireworks_ai,
|
|
765
|
-
supports_structured_output=False,
|
|
766
|
-
supports_data_gen=False,
|
|
767
|
-
model_id="accounts/fireworks/models/llama-v3p2-3b-instruct",
|
|
768
|
-
),
|
|
769
1050
|
KilnModelProvider(
|
|
770
1051
|
name=ModelProviderName.huggingface,
|
|
771
1052
|
model_id="meta-llama/Llama-3.2-3B-Instruct",
|
|
@@ -3,20 +3,16 @@ from abc import ABCMeta, abstractmethod
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Dict, Literal, Tuple
|
|
5
5
|
|
|
6
|
+
import jsonschema
|
|
7
|
+
|
|
6
8
|
from kiln_ai.adapters.ml_model_list import KilnModelProvider, StructuredOutputMode
|
|
7
9
|
from kiln_ai.adapters.parsers.json_parser import parse_json_string
|
|
8
10
|
from kiln_ai.adapters.parsers.parser_registry import model_parser_from_id
|
|
9
11
|
from kiln_ai.adapters.prompt_builders import prompt_builder_from_id
|
|
10
12
|
from kiln_ai.adapters.provider_tools import kiln_model_provider_from
|
|
11
13
|
from kiln_ai.adapters.run_output import RunOutput
|
|
12
|
-
from kiln_ai.datamodel import
|
|
13
|
-
|
|
14
|
-
DataSourceType,
|
|
15
|
-
Task,
|
|
16
|
-
TaskOutput,
|
|
17
|
-
TaskRun,
|
|
18
|
-
)
|
|
19
|
-
from kiln_ai.datamodel.json_schema import validate_schema
|
|
14
|
+
from kiln_ai.datamodel import DataSource, DataSourceType, Task, TaskOutput, TaskRun
|
|
15
|
+
from kiln_ai.datamodel.json_schema import validate_schema_with_value_error
|
|
20
16
|
from kiln_ai.datamodel.task import RunConfig
|
|
21
17
|
from kiln_ai.utils.config import Config
|
|
22
18
|
|
|
@@ -103,7 +99,12 @@ class BaseAdapter(metaclass=ABCMeta):
|
|
|
103
99
|
if self.input_schema is not None:
|
|
104
100
|
if not isinstance(input, dict):
|
|
105
101
|
raise ValueError(f"structured input is not a dict: {input}")
|
|
106
|
-
|
|
102
|
+
|
|
103
|
+
validate_schema_with_value_error(
|
|
104
|
+
input,
|
|
105
|
+
self.input_schema,
|
|
106
|
+
"This task requires a specific input schema. While the model produced JSON, that JSON didn't meet the schema. Search 'Troubleshooting Structured Data Issues' in our docs for more information.",
|
|
107
|
+
)
|
|
107
108
|
|
|
108
109
|
# Run
|
|
109
110
|
run_output = await self._run(input)
|
|
@@ -125,7 +126,11 @@ class BaseAdapter(metaclass=ABCMeta):
|
|
|
125
126
|
raise RuntimeError(
|
|
126
127
|
f"structured response is not a dict: {parsed_output.output}"
|
|
127
128
|
)
|
|
128
|
-
|
|
129
|
+
validate_schema_with_value_error(
|
|
130
|
+
parsed_output.output,
|
|
131
|
+
self.output_schema,
|
|
132
|
+
"This task requires a specific output schema. While the model produced JSON, that JSON didn't meet the schema. Search 'Troubleshooting Structured Data Issues' in our docs for more information.",
|
|
133
|
+
)
|
|
129
134
|
else:
|
|
130
135
|
if not isinstance(parsed_output.output, str):
|
|
131
136
|
raise RuntimeError(
|