kiln-ai 0.20.1__py3-none-any.whl → 0.21.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.

Files changed (117) hide show
  1. kiln_ai/adapters/__init__.py +6 -0
  2. kiln_ai/adapters/adapter_registry.py +43 -226
  3. kiln_ai/adapters/chunkers/__init__.py +13 -0
  4. kiln_ai/adapters/chunkers/base_chunker.py +42 -0
  5. kiln_ai/adapters/chunkers/chunker_registry.py +16 -0
  6. kiln_ai/adapters/chunkers/fixed_window_chunker.py +39 -0
  7. kiln_ai/adapters/chunkers/helpers.py +23 -0
  8. kiln_ai/adapters/chunkers/test_base_chunker.py +63 -0
  9. kiln_ai/adapters/chunkers/test_chunker_registry.py +28 -0
  10. kiln_ai/adapters/chunkers/test_fixed_window_chunker.py +346 -0
  11. kiln_ai/adapters/chunkers/test_helpers.py +75 -0
  12. kiln_ai/adapters/data_gen/test_data_gen_task.py +9 -3
  13. kiln_ai/adapters/embedding/__init__.py +0 -0
  14. kiln_ai/adapters/embedding/base_embedding_adapter.py +44 -0
  15. kiln_ai/adapters/embedding/embedding_registry.py +32 -0
  16. kiln_ai/adapters/embedding/litellm_embedding_adapter.py +199 -0
  17. kiln_ai/adapters/embedding/test_base_embedding_adapter.py +283 -0
  18. kiln_ai/adapters/embedding/test_embedding_registry.py +166 -0
  19. kiln_ai/adapters/embedding/test_litellm_embedding_adapter.py +1149 -0
  20. kiln_ai/adapters/eval/eval_runner.py +6 -2
  21. kiln_ai/adapters/eval/test_base_eval.py +1 -3
  22. kiln_ai/adapters/eval/test_g_eval.py +1 -1
  23. kiln_ai/adapters/extractors/__init__.py +18 -0
  24. kiln_ai/adapters/extractors/base_extractor.py +72 -0
  25. kiln_ai/adapters/extractors/encoding.py +20 -0
  26. kiln_ai/adapters/extractors/extractor_registry.py +44 -0
  27. kiln_ai/adapters/extractors/extractor_runner.py +112 -0
  28. kiln_ai/adapters/extractors/litellm_extractor.py +386 -0
  29. kiln_ai/adapters/extractors/test_base_extractor.py +244 -0
  30. kiln_ai/adapters/extractors/test_encoding.py +54 -0
  31. kiln_ai/adapters/extractors/test_extractor_registry.py +181 -0
  32. kiln_ai/adapters/extractors/test_extractor_runner.py +181 -0
  33. kiln_ai/adapters/extractors/test_litellm_extractor.py +1192 -0
  34. kiln_ai/adapters/fine_tune/test_dataset_formatter.py +2 -2
  35. kiln_ai/adapters/fine_tune/test_fireworks_tinetune.py +2 -6
  36. kiln_ai/adapters/fine_tune/test_together_finetune.py +2 -6
  37. kiln_ai/adapters/ml_embedding_model_list.py +192 -0
  38. kiln_ai/adapters/ml_model_list.py +382 -4
  39. kiln_ai/adapters/model_adapters/litellm_adapter.py +7 -69
  40. kiln_ai/adapters/model_adapters/test_litellm_adapter.py +1 -1
  41. kiln_ai/adapters/model_adapters/test_structured_output.py +3 -1
  42. kiln_ai/adapters/ollama_tools.py +69 -12
  43. kiln_ai/adapters/provider_tools.py +190 -46
  44. kiln_ai/adapters/rag/deduplication.py +49 -0
  45. kiln_ai/adapters/rag/progress.py +252 -0
  46. kiln_ai/adapters/rag/rag_runners.py +844 -0
  47. kiln_ai/adapters/rag/test_deduplication.py +195 -0
  48. kiln_ai/adapters/rag/test_progress.py +785 -0
  49. kiln_ai/adapters/rag/test_rag_runners.py +2376 -0
  50. kiln_ai/adapters/remote_config.py +80 -8
  51. kiln_ai/adapters/test_adapter_registry.py +579 -86
  52. kiln_ai/adapters/test_ml_embedding_model_list.py +429 -0
  53. kiln_ai/adapters/test_ml_model_list.py +212 -0
  54. kiln_ai/adapters/test_ollama_tools.py +340 -1
  55. kiln_ai/adapters/test_prompt_builders.py +1 -1
  56. kiln_ai/adapters/test_provider_tools.py +199 -8
  57. kiln_ai/adapters/test_remote_config.py +551 -56
  58. kiln_ai/adapters/vector_store/__init__.py +1 -0
  59. kiln_ai/adapters/vector_store/base_vector_store_adapter.py +83 -0
  60. kiln_ai/adapters/vector_store/lancedb_adapter.py +389 -0
  61. kiln_ai/adapters/vector_store/test_base_vector_store.py +160 -0
  62. kiln_ai/adapters/vector_store/test_lancedb_adapter.py +1841 -0
  63. kiln_ai/adapters/vector_store/test_vector_store_registry.py +199 -0
  64. kiln_ai/adapters/vector_store/vector_store_registry.py +33 -0
  65. kiln_ai/datamodel/__init__.py +16 -13
  66. kiln_ai/datamodel/basemodel.py +170 -1
  67. kiln_ai/datamodel/chunk.py +158 -0
  68. kiln_ai/datamodel/datamodel_enums.py +27 -0
  69. kiln_ai/datamodel/embedding.py +64 -0
  70. kiln_ai/datamodel/extraction.py +303 -0
  71. kiln_ai/datamodel/project.py +33 -1
  72. kiln_ai/datamodel/rag.py +79 -0
  73. kiln_ai/datamodel/test_attachment.py +649 -0
  74. kiln_ai/datamodel/test_basemodel.py +1 -1
  75. kiln_ai/datamodel/test_chunk_models.py +317 -0
  76. kiln_ai/datamodel/test_dataset_split.py +1 -1
  77. kiln_ai/datamodel/test_embedding_models.py +448 -0
  78. kiln_ai/datamodel/test_eval_model.py +6 -6
  79. kiln_ai/datamodel/test_extraction_chunk.py +206 -0
  80. kiln_ai/datamodel/test_extraction_model.py +470 -0
  81. kiln_ai/datamodel/test_rag.py +641 -0
  82. kiln_ai/datamodel/test_tool_id.py +81 -0
  83. kiln_ai/datamodel/test_vector_store.py +320 -0
  84. kiln_ai/datamodel/tool_id.py +22 -0
  85. kiln_ai/datamodel/vector_store.py +141 -0
  86. kiln_ai/tools/mcp_session_manager.py +4 -1
  87. kiln_ai/tools/rag_tools.py +157 -0
  88. kiln_ai/tools/test_mcp_session_manager.py +1 -1
  89. kiln_ai/tools/test_rag_tools.py +848 -0
  90. kiln_ai/tools/test_tool_registry.py +91 -2
  91. kiln_ai/tools/tool_registry.py +21 -0
  92. kiln_ai/utils/__init__.py +3 -0
  93. kiln_ai/utils/async_job_runner.py +62 -17
  94. kiln_ai/utils/config.py +2 -2
  95. kiln_ai/utils/env.py +15 -0
  96. kiln_ai/utils/filesystem.py +14 -0
  97. kiln_ai/utils/filesystem_cache.py +60 -0
  98. kiln_ai/utils/litellm.py +94 -0
  99. kiln_ai/utils/lock.py +100 -0
  100. kiln_ai/utils/mime_type.py +38 -0
  101. kiln_ai/utils/pdf_utils.py +38 -0
  102. kiln_ai/utils/test_async_job_runner.py +151 -35
  103. kiln_ai/utils/test_env.py +142 -0
  104. kiln_ai/utils/test_filesystem_cache.py +316 -0
  105. kiln_ai/utils/test_litellm.py +206 -0
  106. kiln_ai/utils/test_lock.py +185 -0
  107. kiln_ai/utils/test_mime_type.py +66 -0
  108. kiln_ai/utils/test_pdf_utils.py +73 -0
  109. kiln_ai/utils/test_uuid.py +111 -0
  110. kiln_ai/utils/test_validation.py +524 -0
  111. kiln_ai/utils/uuid.py +9 -0
  112. kiln_ai/utils/validation.py +90 -0
  113. {kiln_ai-0.20.1.dist-info → kiln_ai-0.21.0.dist-info}/METADATA +7 -1
  114. kiln_ai-0.21.0.dist-info/RECORD +211 -0
  115. kiln_ai-0.20.1.dist-info/RECORD +0 -138
  116. {kiln_ai-0.20.1.dist-info → kiln_ai-0.21.0.dist-info}/WHEEL +0 -0
  117. {kiln_ai-0.20.1.dist-info → kiln_ai-0.21.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -5,6 +5,7 @@ from pydantic import BaseModel
5
5
 
6
6
  from kiln_ai.datamodel.datamodel_enums import (
7
7
  ChatStrategy,
8
+ KilnMimeType,
8
9
  ModelProviderName,
9
10
  StructuredOutputMode,
10
11
  )
@@ -39,6 +40,8 @@ class ModelFamily(str, Enum):
39
40
  ernie = "ernie"
40
41
  minimax = "minimax"
41
42
  pangu = "pangu"
43
+ bytedance = "bytedance"
44
+ stepfun = "stepfun"
42
45
 
43
46
 
44
47
  # Where models have instruct and raw versions, instruct is default and raw is specified
@@ -136,6 +139,9 @@ class ModelName(str, Enum):
136
139
  grok_3 = "grok_3"
137
140
  grok_3_mini = "grok_3_mini"
138
141
  grok_4 = "grok_4"
142
+ qwen_3_next_80b_a3b = "qwen_3_next_80b_a3b"
143
+ qwen_3_next_80b_a3b_thinking = "qwen_3_next_80b_a3b_thinking"
144
+ qwen_3_max = "qwen_3_max"
139
145
  qwen_3_0p6b = "qwen_3_0p6b"
140
146
  qwen_3_0p6b_no_thinking = "qwen_3_0p6b_no_thinking"
141
147
  qwen_3_1p7b = "qwen_3_1p7b"
@@ -158,6 +164,7 @@ class ModelName(str, Enum):
158
164
  qwen_3_235b_a22b_no_thinking = "qwen_3_235b_a22b_no_thinking"
159
165
  qwen_long_l1_32b = "qwen_long_l1_32b"
160
166
  kimi_k2 = "kimi_k2"
167
+ kimi_k2_0905 = "kimi_k2_0905"
161
168
  kimi_dev_72b = "kimi_dev_72b"
162
169
  glm_4_5 = "glm_4_5"
163
170
  glm_4_5_air = "glm_4_5_air"
@@ -169,6 +176,8 @@ class ModelName(str, Enum):
169
176
  hunyuan_a13b_no_thinking = "hunyuan_a13b_no_thinking"
170
177
  minimax_m1_80k = "minimax_m1_80k"
171
178
  pangu_pro_moe_72b_a16b = "pangu_pro_moe_72b_a16b"
179
+ bytedance_seed_oss_36b = "bytedance_seed_oss_36b"
180
+ stepfun_step3 = "stepfun_step3"
172
181
 
173
182
 
174
183
  class ModelParserID(str, Enum):
@@ -202,6 +211,10 @@ class KilnModelProvider(BaseModel):
202
211
  parser: A parser to use for the model, if applicable
203
212
  reasoning_capable: Whether the model is designed to output thinking in a structured format (eg <think></think>). If so we don't use COT across 2 calls, and ask for thinking and final response in the same call.
204
213
  tuned_chat_strategy: Used when a model is finetuned with a specific chat strategy, and it's best to use it at call time.
214
+ supports_doc_extraction: Whether the provider is meant to support document extraction
215
+ suggested_for_doc_extraction: Whether the model is suggested for document extraction
216
+ multimodal_capable: Whether the model supports multimodal inputs (e.g. images, audio, video, PDFs, etc.)
217
+ multimodal_mime_types: The mime types that the model supports for multimodal inputs (e.g. image/jpeg, video/mp4, application/pdf, etc.)
205
218
  """
206
219
 
207
220
  name: ModelProviderName
@@ -221,6 +234,10 @@ class KilnModelProvider(BaseModel):
221
234
  uncensored: bool = False
222
235
  suggested_for_uncensored_data_gen: bool = False
223
236
  tuned_chat_strategy: ChatStrategy | None = None
237
+ supports_doc_extraction: bool = False
238
+ suggested_for_doc_extraction: bool = False
239
+ multimodal_capable: bool = False
240
+ multimodal_mime_types: List[str] | None = None
224
241
 
225
242
  # We need a more generalized way to handle custom provider parameters.
226
243
  # Making them quite declarative here for now, isolating provider specific logic
@@ -275,6 +292,15 @@ built_in_models: List[KilnModel] = [
275
292
  structured_output_mode=StructuredOutputMode.json_schema,
276
293
  suggested_for_data_gen=True,
277
294
  suggested_for_evals=True,
295
+ supports_doc_extraction=True,
296
+ multimodal_capable=True,
297
+ multimodal_mime_types=[
298
+ # documents
299
+ KilnMimeType.PDF,
300
+ # images
301
+ KilnMimeType.JPG,
302
+ KilnMimeType.PNG,
303
+ ],
278
304
  ),
279
305
  KilnModelProvider(
280
306
  name=ModelProviderName.openrouter,
@@ -297,6 +323,15 @@ built_in_models: List[KilnModel] = [
297
323
  structured_output_mode=StructuredOutputMode.json_schema,
298
324
  suggested_for_evals=True,
299
325
  suggested_for_data_gen=True,
326
+ supports_doc_extraction=True,
327
+ multimodal_capable=True,
328
+ multimodal_mime_types=[
329
+ # documents
330
+ KilnMimeType.PDF,
331
+ # images
332
+ KilnMimeType.JPG,
333
+ KilnMimeType.PNG,
334
+ ],
300
335
  ),
301
336
  KilnModelProvider(
302
337
  name=ModelProviderName.openrouter,
@@ -317,6 +352,15 @@ built_in_models: List[KilnModel] = [
317
352
  name=ModelProviderName.openai,
318
353
  model_id="gpt-5-nano",
319
354
  structured_output_mode=StructuredOutputMode.json_schema,
355
+ supports_doc_extraction=True,
356
+ multimodal_capable=True,
357
+ multimodal_mime_types=[
358
+ # documents
359
+ KilnMimeType.PDF,
360
+ # images
361
+ KilnMimeType.JPG,
362
+ KilnMimeType.PNG,
363
+ ],
320
364
  ),
321
365
  KilnModelProvider(
322
366
  name=ModelProviderName.openrouter,
@@ -354,6 +398,15 @@ built_in_models: List[KilnModel] = [
354
398
  supports_logprobs=True,
355
399
  suggested_for_evals=True,
356
400
  suggested_for_data_gen=True,
401
+ supports_doc_extraction=True,
402
+ multimodal_capable=True,
403
+ multimodal_mime_types=[
404
+ # documents
405
+ KilnMimeType.PDF,
406
+ # images
407
+ KilnMimeType.JPG,
408
+ KilnMimeType.PNG,
409
+ ],
357
410
  ),
358
411
  KilnModelProvider(
359
412
  name=ModelProviderName.openrouter,
@@ -362,12 +415,30 @@ built_in_models: List[KilnModel] = [
362
415
  supports_logprobs=True,
363
416
  suggested_for_evals=True,
364
417
  suggested_for_data_gen=True,
418
+ supports_doc_extraction=True,
419
+ multimodal_capable=True,
420
+ multimodal_mime_types=[
421
+ # documents
422
+ KilnMimeType.PDF,
423
+ # images
424
+ KilnMimeType.JPG,
425
+ KilnMimeType.PNG,
426
+ ],
365
427
  ),
366
428
  KilnModelProvider(
367
429
  name=ModelProviderName.azure_openai,
368
430
  model_id="gpt-4.1",
369
431
  suggested_for_evals=True,
370
432
  suggested_for_data_gen=True,
433
+ supports_doc_extraction=True,
434
+ multimodal_capable=True,
435
+ multimodal_mime_types=[
436
+ # documents
437
+ KilnMimeType.PDF,
438
+ # images
439
+ KilnMimeType.JPG,
440
+ KilnMimeType.PNG,
441
+ ],
371
442
  ),
372
443
  ],
373
444
  ),
@@ -933,6 +1004,20 @@ built_in_models: List[KilnModel] = [
933
1004
  suggested_for_data_gen=True,
934
1005
  suggested_for_evals=True,
935
1006
  reasoning_capable=True,
1007
+ supports_doc_extraction=True,
1008
+ suggested_for_doc_extraction=True,
1009
+ multimodal_capable=True,
1010
+ multimodal_mime_types=[
1011
+ # documents
1012
+ KilnMimeType.PDF,
1013
+ KilnMimeType.CSV,
1014
+ KilnMimeType.TXT,
1015
+ KilnMimeType.HTML,
1016
+ KilnMimeType.MD,
1017
+ # images
1018
+ KilnMimeType.JPG,
1019
+ KilnMimeType.PNG,
1020
+ ],
936
1021
  gemini_reasoning_enabled=True,
937
1022
  thinking_level="medium",
938
1023
  ),
@@ -942,6 +1027,27 @@ built_in_models: List[KilnModel] = [
942
1027
  structured_output_mode=StructuredOutputMode.json_schema,
943
1028
  suggested_for_data_gen=True,
944
1029
  suggested_for_evals=True,
1030
+ supports_doc_extraction=True,
1031
+ suggested_for_doc_extraction=True,
1032
+ multimodal_capable=True,
1033
+ multimodal_mime_types=[
1034
+ # documents
1035
+ KilnMimeType.PDF,
1036
+ KilnMimeType.CSV,
1037
+ KilnMimeType.TXT,
1038
+ KilnMimeType.HTML,
1039
+ KilnMimeType.MD,
1040
+ # images
1041
+ KilnMimeType.JPG,
1042
+ KilnMimeType.PNG,
1043
+ # audio
1044
+ KilnMimeType.MP3,
1045
+ KilnMimeType.WAV,
1046
+ KilnMimeType.OGG,
1047
+ # video
1048
+ KilnMimeType.MP4,
1049
+ KilnMimeType.MOV,
1050
+ ],
945
1051
  reasoning_capable=True,
946
1052
  gemini_reasoning_enabled=True,
947
1053
  thinking_level="medium",
@@ -969,6 +1075,20 @@ built_in_models: List[KilnModel] = [
969
1075
  model_id="google/gemini-2.5-flash",
970
1076
  structured_output_mode=StructuredOutputMode.json_schema,
971
1077
  reasoning_capable=True,
1078
+ supports_doc_extraction=True,
1079
+ suggested_for_doc_extraction=True,
1080
+ multimodal_capable=True,
1081
+ multimodal_mime_types=[
1082
+ # documents
1083
+ KilnMimeType.PDF,
1084
+ KilnMimeType.CSV,
1085
+ KilnMimeType.TXT,
1086
+ KilnMimeType.HTML,
1087
+ KilnMimeType.MD,
1088
+ # images
1089
+ KilnMimeType.JPG,
1090
+ KilnMimeType.PNG,
1091
+ ],
972
1092
  gemini_reasoning_enabled=True,
973
1093
  ),
974
1094
  KilnModelProvider(
@@ -977,6 +1097,27 @@ built_in_models: List[KilnModel] = [
977
1097
  structured_output_mode=StructuredOutputMode.json_schema,
978
1098
  reasoning_capable=True,
979
1099
  thinking_level="medium",
1100
+ supports_doc_extraction=True,
1101
+ suggested_for_doc_extraction=True,
1102
+ multimodal_capable=True,
1103
+ multimodal_mime_types=[
1104
+ # documents
1105
+ KilnMimeType.PDF,
1106
+ KilnMimeType.CSV,
1107
+ KilnMimeType.TXT,
1108
+ KilnMimeType.HTML,
1109
+ KilnMimeType.MD,
1110
+ # images
1111
+ KilnMimeType.JPG,
1112
+ KilnMimeType.PNG,
1113
+ # audio
1114
+ KilnMimeType.MP3,
1115
+ KilnMimeType.WAV,
1116
+ KilnMimeType.OGG,
1117
+ # video
1118
+ KilnMimeType.MP4,
1119
+ KilnMimeType.MOV,
1120
+ ],
980
1121
  ),
981
1122
  KilnModelProvider(
982
1123
  name=ModelProviderName.vertex,
@@ -996,11 +1137,44 @@ built_in_models: List[KilnModel] = [
996
1137
  KilnModelProvider(
997
1138
  name=ModelProviderName.openrouter,
998
1139
  model_id="google/gemini-2.0-flash-001",
1140
+ supports_doc_extraction=True,
1141
+ multimodal_capable=True,
1142
+ multimodal_mime_types=[
1143
+ # documents
1144
+ KilnMimeType.PDF,
1145
+ KilnMimeType.CSV,
1146
+ KilnMimeType.TXT,
1147
+ KilnMimeType.HTML,
1148
+ KilnMimeType.MD,
1149
+ # images
1150
+ KilnMimeType.JPG,
1151
+ KilnMimeType.PNG,
1152
+ ],
999
1153
  structured_output_mode=StructuredOutputMode.json_schema,
1000
1154
  ),
1001
1155
  KilnModelProvider(
1002
1156
  name=ModelProviderName.gemini_api,
1003
1157
  model_id="gemini-2.0-flash",
1158
+ supports_doc_extraction=True,
1159
+ multimodal_capable=True,
1160
+ multimodal_mime_types=[
1161
+ # documents
1162
+ KilnMimeType.PDF,
1163
+ KilnMimeType.CSV,
1164
+ KilnMimeType.TXT,
1165
+ KilnMimeType.HTML,
1166
+ KilnMimeType.MD,
1167
+ # images
1168
+ KilnMimeType.JPG,
1169
+ KilnMimeType.PNG,
1170
+ # audio
1171
+ KilnMimeType.MP3,
1172
+ KilnMimeType.WAV,
1173
+ KilnMimeType.OGG,
1174
+ # video
1175
+ KilnMimeType.MP4,
1176
+ KilnMimeType.MOV,
1177
+ ],
1004
1178
  structured_output_mode=StructuredOutputMode.json_schema,
1005
1179
  ),
1006
1180
  KilnModelProvider(
@@ -1020,11 +1194,44 @@ built_in_models: List[KilnModel] = [
1020
1194
  KilnModelProvider(
1021
1195
  name=ModelProviderName.openrouter,
1022
1196
  model_id="google/gemini-2.0-flash-lite-001",
1197
+ supports_doc_extraction=True,
1198
+ multimodal_capable=True,
1199
+ multimodal_mime_types=[
1200
+ # documents
1201
+ KilnMimeType.PDF,
1202
+ KilnMimeType.CSV,
1203
+ KilnMimeType.TXT,
1204
+ KilnMimeType.HTML,
1205
+ KilnMimeType.MD,
1206
+ # images
1207
+ KilnMimeType.JPG,
1208
+ KilnMimeType.PNG,
1209
+ ],
1023
1210
  structured_output_mode=StructuredOutputMode.json_schema,
1024
1211
  ),
1025
1212
  KilnModelProvider(
1026
1213
  name=ModelProviderName.gemini_api,
1027
1214
  model_id="gemini-2.0-flash-lite",
1215
+ supports_doc_extraction=True,
1216
+ multimodal_capable=True,
1217
+ multimodal_mime_types=[
1218
+ # documents
1219
+ KilnMimeType.PDF,
1220
+ KilnMimeType.CSV,
1221
+ KilnMimeType.TXT,
1222
+ KilnMimeType.HTML,
1223
+ KilnMimeType.MD,
1224
+ # images
1225
+ KilnMimeType.JPG,
1226
+ KilnMimeType.PNG,
1227
+ # audio
1228
+ KilnMimeType.MP3,
1229
+ KilnMimeType.WAV,
1230
+ KilnMimeType.OGG,
1231
+ # video
1232
+ KilnMimeType.MP4,
1233
+ KilnMimeType.MOV,
1234
+ ],
1028
1235
  structured_output_mode=StructuredOutputMode.json_schema,
1029
1236
  ),
1030
1237
  KilnModelProvider(
@@ -2107,7 +2314,7 @@ built_in_models: List[KilnModel] = [
2107
2314
  KilnModelProvider(
2108
2315
  name=ModelProviderName.openrouter,
2109
2316
  model_id="deepseek/deepseek-chat-v3.1",
2110
- structured_output_mode=StructuredOutputMode.json_instruction_and_object,
2317
+ structured_output_mode=StructuredOutputMode.json_schema,
2111
2318
  supports_data_gen=True,
2112
2319
  ),
2113
2320
  KilnModelProvider(
@@ -2116,6 +2323,12 @@ built_in_models: List[KilnModel] = [
2116
2323
  structured_output_mode=StructuredOutputMode.json_instruction_and_object,
2117
2324
  supports_data_gen=True,
2118
2325
  ),
2326
+ KilnModelProvider(
2327
+ name=ModelProviderName.siliconflow_cn,
2328
+ model_id="Pro/deepseek-ai/DeepSeek-V3.1",
2329
+ structured_output_mode=StructuredOutputMode.json_schema,
2330
+ supports_data_gen=True,
2331
+ ),
2119
2332
  ],
2120
2333
  ),
2121
2334
  # DeepSeek 3
@@ -2521,6 +2734,53 @@ built_in_models: List[KilnModel] = [
2521
2734
  ),
2522
2735
  ],
2523
2736
  ),
2737
+ # Qwen 3 Next 80B A3B
2738
+ KilnModel(
2739
+ family=ModelFamily.qwen,
2740
+ name=ModelName.qwen_3_next_80b_a3b,
2741
+ friendly_name="Qwen 3 Next 80B A3B (Instruct)",
2742
+ providers=[
2743
+ KilnModelProvider(
2744
+ name=ModelProviderName.openrouter,
2745
+ model_id="qwen/qwen3-next-80b-a3b-instruct",
2746
+ structured_output_mode=StructuredOutputMode.json_instruction_and_object,
2747
+ supports_data_gen=True,
2748
+ supports_function_calling=True,
2749
+ ),
2750
+ ],
2751
+ ),
2752
+ # Qwen 3 Next 80B A3B (Thinking)
2753
+ KilnModel(
2754
+ family=ModelFamily.qwen,
2755
+ name=ModelName.qwen_3_next_80b_a3b_thinking,
2756
+ friendly_name="Qwen 3 Next 80B A3B (Thinking)",
2757
+ providers=[
2758
+ KilnModelProvider(
2759
+ name=ModelProviderName.openrouter,
2760
+ model_id="qwen/qwen3-next-80b-a3b-thinking",
2761
+ structured_output_mode=StructuredOutputMode.json_instructions,
2762
+ supports_data_gen=True,
2763
+ supports_function_calling=True,
2764
+ reasoning_capable=True,
2765
+ require_openrouter_reasoning=True,
2766
+ ),
2767
+ ],
2768
+ ),
2769
+ # Qwen 3 Max
2770
+ KilnModel(
2771
+ family=ModelFamily.qwen,
2772
+ name=ModelName.qwen_3_max,
2773
+ friendly_name="Qwen 3 Max",
2774
+ providers=[
2775
+ KilnModelProvider(
2776
+ name=ModelProviderName.openrouter,
2777
+ model_id="qwen/qwen3-max",
2778
+ structured_output_mode=StructuredOutputMode.json_instruction_and_object,
2779
+ supports_data_gen=True,
2780
+ supports_function_calling=True,
2781
+ ),
2782
+ ],
2783
+ ),
2524
2784
  # Qwen 3 0.6B
2525
2785
  KilnModel(
2526
2786
  family=ModelFamily.qwen,
@@ -3222,6 +3482,13 @@ built_in_models: List[KilnModel] = [
3222
3482
  structured_output_mode=StructuredOutputMode.json_instructions,
3223
3483
  reasoning_capable=True,
3224
3484
  ),
3485
+ KilnModelProvider(
3486
+ name=ModelProviderName.siliconflow_cn,
3487
+ model_id="zai-org/GLM-4.5",
3488
+ structured_output_mode=StructuredOutputMode.json_instructions,
3489
+ reasoning_capable=True,
3490
+ reasoning_optional_for_structured_output=True,
3491
+ ),
3225
3492
  ],
3226
3493
  ),
3227
3494
  # GLM 4.5 AIR
@@ -3249,6 +3516,13 @@ built_in_models: List[KilnModel] = [
3249
3516
  reasoning_capable=True,
3250
3517
  parser=ModelParserID.r1_thinking,
3251
3518
  ),
3519
+ KilnModelProvider(
3520
+ name=ModelProviderName.siliconflow_cn,
3521
+ model_id="zai-org/GLM-4.5-Air",
3522
+ structured_output_mode=StructuredOutputMode.json_instructions,
3523
+ reasoning_capable=True,
3524
+ reasoning_optional_for_structured_output=True,
3525
+ ),
3252
3526
  ],
3253
3527
  ),
3254
3528
  # Kimi K2 Instruct
@@ -3260,8 +3534,9 @@ built_in_models: List[KilnModel] = [
3260
3534
  KilnModelProvider(
3261
3535
  name=ModelProviderName.fireworks_ai,
3262
3536
  model_id="accounts/fireworks/models/kimi-k2-instruct",
3263
- structured_output_mode=StructuredOutputMode.json_instruction_and_object,
3264
- # Ignoring json mode for now, so not suggested for evals
3537
+ structured_output_mode=StructuredOutputMode.json_schema,
3538
+ supports_data_gen=True,
3539
+ suggested_for_evals=True,
3265
3540
  ),
3266
3541
  KilnModelProvider(
3267
3542
  name=ModelProviderName.openrouter,
@@ -3281,7 +3556,7 @@ built_in_models: List[KilnModel] = [
3281
3556
  name=ModelProviderName.groq,
3282
3557
  model_id="moonshotai/kimi-k2-instruct",
3283
3558
  supports_data_gen=True,
3284
- structured_output_mode=StructuredOutputMode.function_calling,
3559
+ structured_output_mode=StructuredOutputMode.json_schema,
3285
3560
  suggested_for_evals=True,
3286
3561
  ),
3287
3562
  KilnModelProvider(
@@ -3293,6 +3568,51 @@ built_in_models: List[KilnModel] = [
3293
3568
  ),
3294
3569
  ],
3295
3570
  ),
3571
+ # Kimi K2 Instruct 0905
3572
+ KilnModel(
3573
+ family=ModelFamily.kimi,
3574
+ name=ModelName.kimi_k2_0905,
3575
+ friendly_name="Kimi K2 0905",
3576
+ providers=[
3577
+ KilnModelProvider(
3578
+ name=ModelProviderName.openrouter,
3579
+ model_id="moonshotai/kimi-k2-0905",
3580
+ structured_output_mode=StructuredOutputMode.json_schema,
3581
+ supports_data_gen=True,
3582
+ suggested_for_evals=True,
3583
+ ),
3584
+ KilnModelProvider(
3585
+ name=ModelProviderName.fireworks_ai,
3586
+ model_id="accounts/fireworks/models/kimi-k2-instruct-0905",
3587
+ structured_output_mode=StructuredOutputMode.json_schema,
3588
+ supports_data_gen=True,
3589
+ suggested_for_evals=True,
3590
+ ),
3591
+ KilnModelProvider(
3592
+ name=ModelProviderName.together_ai,
3593
+ model_id="moonshotai/Kimi-K2-Instruct-0905",
3594
+ structured_output_mode=StructuredOutputMode.json_instruction_and_object,
3595
+ supports_data_gen=True,
3596
+ suggested_for_evals=True,
3597
+ # this model on this provider currently fails the tool call test, but might work in the future
3598
+ supports_function_calling=False,
3599
+ ),
3600
+ KilnModelProvider(
3601
+ name=ModelProviderName.groq,
3602
+ model_id="moonshotai/kimi-k2-instruct-0905",
3603
+ structured_output_mode=StructuredOutputMode.json_schema,
3604
+ supports_data_gen=True,
3605
+ suggested_for_evals=True,
3606
+ ),
3607
+ KilnModelProvider(
3608
+ name=ModelProviderName.siliconflow_cn,
3609
+ model_id="Pro/moonshotai/Kimi-K2-Instruct-0905",
3610
+ structured_output_mode=StructuredOutputMode.json_schema,
3611
+ supports_data_gen=True,
3612
+ suggested_for_evals=True,
3613
+ ),
3614
+ ],
3615
+ ),
3296
3616
  KilnModel(
3297
3617
  family=ModelFamily.kimi,
3298
3618
  name=ModelName.kimi_dev_72b,
@@ -3442,6 +3762,53 @@ built_in_models: List[KilnModel] = [
3442
3762
  ),
3443
3763
  ],
3444
3764
  ),
3765
+ # Bytedance
3766
+ KilnModel(
3767
+ family=ModelFamily.bytedance,
3768
+ name=ModelName.bytedance_seed_oss_36b,
3769
+ friendly_name="ByteDance Seed OSS 36B",
3770
+ providers=[
3771
+ KilnModelProvider(
3772
+ name=ModelProviderName.openrouter,
3773
+ model_id="bytedance/seed-oss-36b-instruct",
3774
+ structured_output_mode=StructuredOutputMode.json_schema,
3775
+ reasoning_capable=True,
3776
+ supports_data_gen=True,
3777
+ supports_function_calling=False,
3778
+ ),
3779
+ KilnModelProvider(
3780
+ name=ModelProviderName.siliconflow_cn,
3781
+ model_id="ByteDance-Seed/Seed-OSS-36B-Instruct",
3782
+ structured_output_mode=StructuredOutputMode.json_schema,
3783
+ reasoning_capable=True,
3784
+ supports_data_gen=True,
3785
+ supports_function_calling=False,
3786
+ reasoning_optional_for_structured_output=True,
3787
+ ),
3788
+ ],
3789
+ ),
3790
+ # StepFun
3791
+ KilnModel(
3792
+ family=ModelFamily.stepfun,
3793
+ name=ModelName.stepfun_step3,
3794
+ friendly_name="StepFun Step3",
3795
+ providers=[
3796
+ KilnModelProvider(
3797
+ name=ModelProviderName.openrouter,
3798
+ model_id="stepfun-ai/step3",
3799
+ structured_output_mode=StructuredOutputMode.json_instructions,
3800
+ reasoning_capable=True,
3801
+ supports_function_calling=False,
3802
+ ),
3803
+ KilnModelProvider(
3804
+ name=ModelProviderName.siliconflow_cn,
3805
+ model_id="stepfun-ai/step3",
3806
+ structured_output_mode=StructuredOutputMode.json_instructions,
3807
+ reasoning_capable=True,
3808
+ supports_function_calling=False,
3809
+ ),
3810
+ ],
3811
+ ),
3445
3812
  ]
3446
3813
 
3447
3814
 
@@ -3452,6 +3819,17 @@ def get_model_by_name(name: ModelName) -> KilnModel:
3452
3819
  raise ValueError(f"Model {name} not found in the list of built-in models")
3453
3820
 
3454
3821
 
3822
+ def built_in_models_from_provider(
3823
+ provider_name: ModelProviderName, model_name: str
3824
+ ) -> KilnModelProvider | None:
3825
+ for model in built_in_models:
3826
+ if model.name == model_name:
3827
+ for p in model.providers:
3828
+ if p.name == provider_name:
3829
+ return p
3830
+ return None
3831
+
3832
+
3455
3833
  def default_structured_output_mode_for_model_provider(
3456
3834
  model_name: str,
3457
3835
  provider: ModelProviderName,
@@ -11,13 +11,9 @@ from litellm.types.utils import (
11
11
  Choices,
12
12
  ModelResponse,
13
13
  )
14
- from litellm.types.utils import (
15
- Message as LiteLLMMessage,
16
- )
14
+ from litellm.types.utils import Message as LiteLLMMessage
17
15
  from litellm.types.utils import Usage as LiteLlmUsage
18
- from openai.types.chat import (
19
- ChatCompletionToolMessageParam,
20
- )
16
+ from openai.types.chat import ChatCompletionToolMessageParam
21
17
  from openai.types.chat.chat_completion_message_tool_call_param import (
22
18
  ChatCompletionMessageToolCallParam,
23
19
  )
@@ -38,6 +34,7 @@ from kiln_ai.adapters.model_adapters.litellm_config import LiteLlmConfig
38
34
  from kiln_ai.datamodel.json_schema import validate_schema_with_value_error
39
35
  from kiln_ai.tools.base_tool import KilnToolInterface
40
36
  from kiln_ai.utils.exhaustive_error import raise_exhaustive_enum_error
37
+ from kiln_ai.utils.litellm import get_litellm_provider_info
41
38
  from kiln_ai.utils.open_ai_types import (
42
39
  ChatCompletionAssistantMessageParamWrapper,
43
40
  ChatCompletionMessageParam,
@@ -447,75 +444,16 @@ class LiteLlmAdapter(BaseAdapter):
447
444
  def litellm_model_id(self) -> str:
448
445
  # The model ID is an interesting combination of format and url endpoint.
449
446
  # It specifics the provider URL/host, but this is overridden if you manually set an api url
450
-
451
447
  if self._litellm_model_id:
452
448
  return self._litellm_model_id
453
449
 
454
- provider = self.model_provider()
455
- if not provider.model_id:
456
- raise ValueError("Model ID is required for OpenAI compatible models")
457
-
458
- litellm_provider_name: str | None = None
459
- is_custom = False
460
- match provider.name:
461
- case ModelProviderName.openrouter:
462
- litellm_provider_name = "openrouter"
463
- case ModelProviderName.openai:
464
- litellm_provider_name = "openai"
465
- case ModelProviderName.groq:
466
- litellm_provider_name = "groq"
467
- case ModelProviderName.anthropic:
468
- litellm_provider_name = "anthropic"
469
- case ModelProviderName.ollama:
470
- # We don't let litellm use the Ollama API and muck with our requests. We use Ollama's OpenAI compatible API.
471
- # This is because we're setting detailed features like response_format=json_schema and want lower level control.
472
- is_custom = True
473
- case ModelProviderName.docker_model_runner:
474
- # Docker Model Runner uses OpenAI-compatible API, similar to Ollama
475
- # We want direct control over the requests for features like response_format=json_schema
476
- is_custom = True
477
- case ModelProviderName.gemini_api:
478
- litellm_provider_name = "gemini"
479
- case ModelProviderName.fireworks_ai:
480
- litellm_provider_name = "fireworks_ai"
481
- case ModelProviderName.amazon_bedrock:
482
- litellm_provider_name = "bedrock"
483
- case ModelProviderName.azure_openai:
484
- litellm_provider_name = "azure"
485
- case ModelProviderName.huggingface:
486
- litellm_provider_name = "huggingface"
487
- case ModelProviderName.vertex:
488
- litellm_provider_name = "vertex_ai"
489
- case ModelProviderName.together_ai:
490
- litellm_provider_name = "together_ai"
491
- case ModelProviderName.cerebras:
492
- litellm_provider_name = "cerebras"
493
- case ModelProviderName.siliconflow_cn:
494
- is_custom = True
495
- case ModelProviderName.openai_compatible:
496
- is_custom = True
497
- case ModelProviderName.kiln_custom_registry:
498
- is_custom = True
499
- case ModelProviderName.kiln_fine_tune:
500
- is_custom = True
501
- case _:
502
- raise_exhaustive_enum_error(provider.name)
503
-
504
- if is_custom:
505
- if self._api_base is None:
506
- raise ValueError(
507
- "Explicit Base URL is required for OpenAI compatible APIs (custom models, ollama, fine tunes, and custom registry models)"
508
- )
509
- # Use openai as it's only used for format, not url
510
- litellm_provider_name = "openai"
511
-
512
- # Sholdn't be possible but keep type checker happy
513
- if litellm_provider_name is None:
450
+ litellm_provider_info = get_litellm_provider_info(self.model_provider())
451
+ if litellm_provider_info.is_custom and self._api_base is None:
514
452
  raise ValueError(
515
- f"Provider name could not lookup valid litellm provider ID {provider.model_id}"
453
+ "Explicit Base URL is required for OpenAI compatible APIs (custom models, ollama, fine tunes, and custom registry models)"
516
454
  )
517
455
 
518
- self._litellm_model_id = litellm_provider_name + "/" + provider.model_id
456
+ self._litellm_model_id = litellm_provider_info.litellm_model_id
519
457
  return self._litellm_model_id
520
458
 
521
459
  async def build_completion_kwargs(