kiln-ai 0.11.1__py3-none-any.whl → 0.13.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 (80) hide show
  1. kiln_ai/adapters/__init__.py +4 -0
  2. kiln_ai/adapters/adapter_registry.py +163 -39
  3. kiln_ai/adapters/data_gen/data_gen_task.py +18 -0
  4. kiln_ai/adapters/eval/__init__.py +28 -0
  5. kiln_ai/adapters/eval/base_eval.py +164 -0
  6. kiln_ai/adapters/eval/eval_runner.py +270 -0
  7. kiln_ai/adapters/eval/g_eval.py +368 -0
  8. kiln_ai/adapters/eval/registry.py +16 -0
  9. kiln_ai/adapters/eval/test_base_eval.py +325 -0
  10. kiln_ai/adapters/eval/test_eval_runner.py +641 -0
  11. kiln_ai/adapters/eval/test_g_eval.py +498 -0
  12. kiln_ai/adapters/eval/test_g_eval_data.py +4 -0
  13. kiln_ai/adapters/fine_tune/base_finetune.py +16 -2
  14. kiln_ai/adapters/fine_tune/finetune_registry.py +2 -0
  15. kiln_ai/adapters/fine_tune/test_dataset_formatter.py +4 -1
  16. kiln_ai/adapters/fine_tune/test_fireworks_tinetune.py +1 -1
  17. kiln_ai/adapters/fine_tune/test_openai_finetune.py +1 -1
  18. kiln_ai/adapters/fine_tune/test_together_finetune.py +531 -0
  19. kiln_ai/adapters/fine_tune/together_finetune.py +325 -0
  20. kiln_ai/adapters/ml_model_list.py +758 -163
  21. kiln_ai/adapters/model_adapters/__init__.py +2 -4
  22. kiln_ai/adapters/model_adapters/base_adapter.py +61 -43
  23. kiln_ai/adapters/model_adapters/litellm_adapter.py +391 -0
  24. kiln_ai/adapters/model_adapters/litellm_config.py +13 -0
  25. kiln_ai/adapters/model_adapters/test_base_adapter.py +22 -13
  26. kiln_ai/adapters/model_adapters/test_litellm_adapter.py +407 -0
  27. kiln_ai/adapters/model_adapters/test_saving_adapter_results.py +41 -19
  28. kiln_ai/adapters/model_adapters/test_structured_output.py +59 -35
  29. kiln_ai/adapters/ollama_tools.py +3 -3
  30. kiln_ai/adapters/parsers/r1_parser.py +19 -14
  31. kiln_ai/adapters/parsers/test_r1_parser.py +17 -5
  32. kiln_ai/adapters/prompt_builders.py +80 -42
  33. kiln_ai/adapters/provider_tools.py +50 -58
  34. kiln_ai/adapters/repair/repair_task.py +9 -21
  35. kiln_ai/adapters/repair/test_repair_task.py +6 -6
  36. kiln_ai/adapters/run_output.py +3 -0
  37. kiln_ai/adapters/test_adapter_registry.py +26 -29
  38. kiln_ai/adapters/test_generate_docs.py +4 -4
  39. kiln_ai/adapters/test_ollama_tools.py +0 -1
  40. kiln_ai/adapters/test_prompt_adaptors.py +47 -33
  41. kiln_ai/adapters/test_prompt_builders.py +91 -31
  42. kiln_ai/adapters/test_provider_tools.py +26 -81
  43. kiln_ai/datamodel/__init__.py +50 -952
  44. kiln_ai/datamodel/basemodel.py +2 -0
  45. kiln_ai/datamodel/datamodel_enums.py +60 -0
  46. kiln_ai/datamodel/dataset_filters.py +114 -0
  47. kiln_ai/datamodel/dataset_split.py +170 -0
  48. kiln_ai/datamodel/eval.py +298 -0
  49. kiln_ai/datamodel/finetune.py +105 -0
  50. kiln_ai/datamodel/json_schema.py +7 -1
  51. kiln_ai/datamodel/project.py +23 -0
  52. kiln_ai/datamodel/prompt.py +37 -0
  53. kiln_ai/datamodel/prompt_id.py +83 -0
  54. kiln_ai/datamodel/strict_mode.py +24 -0
  55. kiln_ai/datamodel/task.py +181 -0
  56. kiln_ai/datamodel/task_output.py +328 -0
  57. kiln_ai/datamodel/task_run.py +164 -0
  58. kiln_ai/datamodel/test_basemodel.py +19 -11
  59. kiln_ai/datamodel/test_dataset_filters.py +71 -0
  60. kiln_ai/datamodel/test_dataset_split.py +32 -8
  61. kiln_ai/datamodel/test_datasource.py +22 -2
  62. kiln_ai/datamodel/test_eval_model.py +635 -0
  63. kiln_ai/datamodel/test_example_models.py +9 -13
  64. kiln_ai/datamodel/test_json_schema.py +23 -0
  65. kiln_ai/datamodel/test_models.py +2 -2
  66. kiln_ai/datamodel/test_prompt_id.py +129 -0
  67. kiln_ai/datamodel/test_task.py +159 -0
  68. kiln_ai/utils/config.py +43 -1
  69. kiln_ai/utils/dataset_import.py +232 -0
  70. kiln_ai/utils/test_dataset_import.py +596 -0
  71. {kiln_ai-0.11.1.dist-info → kiln_ai-0.13.0.dist-info}/METADATA +86 -6
  72. kiln_ai-0.13.0.dist-info/RECORD +103 -0
  73. kiln_ai/adapters/model_adapters/langchain_adapters.py +0 -302
  74. kiln_ai/adapters/model_adapters/openai_compatible_config.py +0 -11
  75. kiln_ai/adapters/model_adapters/openai_model_adapter.py +0 -246
  76. kiln_ai/adapters/model_adapters/test_langchain_adapter.py +0 -350
  77. kiln_ai/adapters/model_adapters/test_openai_model_adapter.py +0 -225
  78. kiln_ai-0.11.1.dist-info/RECORD +0 -76
  79. {kiln_ai-0.11.1.dist-info → kiln_ai-0.13.0.dist-info}/WHEEL +0 -0
  80. {kiln_ai-0.11.1.dist-info → kiln_ai-0.13.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiln-ai
3
- Version: 0.11.1
3
+ Version: 0.13.0
4
4
  Summary: Kiln AI
5
5
  Project-URL: Homepage, https://getkiln.ai
6
6
  Project-URL: Repository, https://github.com/Kiln-AI/kiln
@@ -13,20 +13,20 @@ Classifier: License :: OSI Approved :: MIT License
13
13
  Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
16
17
  Requires-Python: >=3.10
18
+ Requires-Dist: boto3>=1.37.10
17
19
  Requires-Dist: coverage>=7.6.4
20
+ Requires-Dist: google-cloud-aiplatform>=1.84.0
18
21
  Requires-Dist: jsonschema>=4.23.0
19
- Requires-Dist: langchain-aws>=0.2.4
20
- Requires-Dist: langchain-fireworks>=0.2.5
21
- Requires-Dist: langchain-groq>=0.2.0
22
- Requires-Dist: langchain-ollama>=0.2.2
23
- Requires-Dist: langchain>=0.3.5
22
+ Requires-Dist: litellm>=1.63.5
24
23
  Requires-Dist: openai>=1.53.0
25
24
  Requires-Dist: pdoc>=15.0.0
26
25
  Requires-Dist: pydantic>=2.9.2
27
26
  Requires-Dist: pytest-benchmark>=5.1.0
28
27
  Requires-Dist: pytest-cov>=6.0.0
29
28
  Requires-Dist: pyyaml>=6.0.2
29
+ Requires-Dist: together>=1.4.6
30
30
  Requires-Dist: typing-extensions>=4.12.2
31
31
  Description-Content-Type: text/markdown
32
32
 
@@ -71,6 +71,8 @@ The library has a [comprehensive set of docs](https://kiln-ai.github.io/Kiln/kil
71
71
  - [Load an Existing Dataset into a Kiln Task Dataset](#load-an-existing-dataset-into-a-kiln-task-dataset)
72
72
  - [Using your Kiln Dataset in a Notebook or Project](#using-your-kiln-dataset-in-a-notebook-or-project)
73
73
  - [Using Kiln Dataset in Pandas](#using-kiln-dataset-in-pandas)
74
+ - [Building and Running a Kiln Task from Code](#building-and-running-a-kiln-task-from-code)
75
+ - [Adding Custom Model or AI Provider from Code](#adding-custom-model-or-ai-provider-from-code)
74
76
  - [Full API Reference](#full-api-reference)
75
77
 
76
78
  ## Installation
@@ -232,6 +234,84 @@ final_df = pd.concat(dfs, ignore_index=True)
232
234
  print(final_df)
233
235
  ```
234
236
 
237
+ ### Building and Running a Kiln Task from Code
238
+
239
+ ```python
240
+ # Step 1: Create or Load a Task -- choose one of the following 1.A or 1.B
241
+
242
+ # Step 1.A: Optionally load an existing task from disk
243
+ # task = datamodel.Task.load_from_file("path/to/task.kiln")
244
+
245
+ # Step 1.B: Create a new task in code, without saving to disk.
246
+ task = datamodel.Task(
247
+ name="test task",
248
+ instruction="Tell a joke, given a subject.",
249
+ )
250
+ # replace with a valid JSON schema https://json-schema.org for your task (json string, not a python dict).
251
+ # Or delete this line to use plaintext output
252
+ task.output_json_schema = json_joke_schema
253
+
254
+ # Step 2: Create an Adapter to run the task, with a specific model and provider
255
+ adapter = adapter_for_task(task, model_name="llama_3_1_8b", provider="groq")
256
+
257
+ # Step 3: Invoke the Adapter to run the task
258
+ task_input = "cows"
259
+ response = await adapter.invoke(task_input)
260
+ print(f"Output: {response.output.output}")
261
+
262
+ # Step 4 (optional): Load the task from disk and print the results.
263
+ # This will only work if the task was loaded from disk, or you called task.save_to_file() before invoking the adapter (ephemeral tasks don't save their result to disk)
264
+ task = datamodel.Task.load_from_file(tmp_path / "test_task.kiln")
265
+ for run in task.runs():
266
+ print(f"Run: {run.id}")
267
+ print(f"Input: {run.input}")
268
+ print(f"Output: {run.output}")
269
+
270
+ ```
271
+
272
+ ### Adding Custom Model or AI Provider from Code
273
+
274
+ You can add additional AI models and providers to Kiln.
275
+
276
+ See our docs for more information, including how to add these from the UI:
277
+
278
+ - [Custom Models From Existing Providers](https://docs.getkiln.ai/docs/models-and-ai-providers#custom-models-from-existing-providers)
279
+ - [Custom OpenAI Compatible Servers](https://docs.getkiln.ai/docs/models-and-ai-providers#custom-openai-compatible-servers)
280
+
281
+ You can also add these from code. The kiln_ai.utils.Config class helps you manage the Kiln config file (stored at `~/.kiln_settings/config.yaml`):
282
+
283
+ ```python
284
+ # Addding an OpenAI compatible provider
285
+ name = "CustomOllama"
286
+ base_url = "http://localhost:1234/api/v1"
287
+ api_key = "12345"
288
+ providers = Config.shared().openai_compatible_providers or []
289
+ existing_provider = next((p for p in providers if p["name"] == name), None)
290
+ if existing_provider:
291
+ # skip since this already exists
292
+ return
293
+ providers.append(
294
+ {
295
+ "name": name,
296
+ "base_url": base_url,
297
+ "api_key": api_key,
298
+ }
299
+ )
300
+ Config.shared().openai_compatible_providers = providers
301
+ ```
302
+
303
+ ```python
304
+ # Add a custom model ID to an existing provider.
305
+ new_model = "openai::gpt-3.5-turbo"
306
+ custom_model_ids = Config.shared().custom_models
307
+ existing_model = next((m for m in custom_model_ids if m == new_model), None)
308
+ if existing_model:
309
+ # skip since this already exists
310
+ return
311
+ custom_model_ids.append(new_model)
312
+ Config.shared().custom_models = custom_model_ids
313
+ ```
314
+
235
315
  ## Full API Reference
236
316
 
237
317
  The library can do a lot more than the examples we've shown here.
@@ -0,0 +1,103 @@
1
+ kiln_ai/__init__.py,sha256=Sc4z8LRVFMwJUoc_DPVUriSXTZ6PO9MaJ80PhRbKyB8,34
2
+ kiln_ai/adapters/__init__.py,sha256=XjGmWagEyOEVwVIAxjN5rYNsQWIEACT5DB7MMTxdPss,1005
3
+ kiln_ai/adapters/adapter_registry.py,sha256=rOIL8xMm_REVO92iDphj_cBwhDOZVyS5ST-nHk4_6pA,8955
4
+ kiln_ai/adapters/ml_model_list.py,sha256=u1nFkJm_UD1IZjBBoynmWnhx_aPkuvSuHVI69Thma3w,58939
5
+ kiln_ai/adapters/ollama_tools.py,sha256=uObtLWfqKb9RXHN-TGGw2Y1FQlEMe0u8FgszI0zQn6U,3550
6
+ kiln_ai/adapters/prompt_builders.py,sha256=LYHTIaisQMBFtWDRIGo1QJgOsmQ-NBpQ8fI4eImHxaQ,15269
7
+ kiln_ai/adapters/provider_tools.py,sha256=pVLziYwHQxOZODil3iyn-BnW8CyCYnFsSdjerliWqvs,14671
8
+ kiln_ai/adapters/run_output.py,sha256=RAi2Qp6dmqJVNm3CxbNTdAuhitHfH5NiUGbf6ygUP-k,257
9
+ kiln_ai/adapters/test_adapter_registry.py,sha256=eDLHqv9mwgdde221pa47bTV87vCXwkUyjqsas-iFUrY,6123
10
+ kiln_ai/adapters/test_generate_docs.py,sha256=M-uKcgF3hQmlEFOJ0o7DyL-9RgitGzkfROV-Dxtooec,2770
11
+ kiln_ai/adapters/test_ollama_tools.py,sha256=xAUzL0IVmmXadVehJu1WjqbhpKEYGAgGt3pWx7hrubc,2514
12
+ kiln_ai/adapters/test_prompt_adaptors.py,sha256=J1ZGZ8GG7SxP3_J3Zw0e6XmZY4NyPmUGX3IPgjh2LD8,7767
13
+ kiln_ai/adapters/test_prompt_builders.py,sha256=5Xvfr-oQg_LLrle6UqfpRHWcPUYa8ywG3aL1rM7q1Jw,22054
14
+ kiln_ai/adapters/test_provider_tools.py,sha256=T2t99i4LnH4xilmyV4przff3MnTdDvAnTmaiYhFPShE,26621
15
+ kiln_ai/adapters/data_gen/__init__.py,sha256=QTZWaf7kq5BorhPvexJfwDEKmjRmIbhwW9ei8LW2SIs,276
16
+ kiln_ai/adapters/data_gen/data_gen_prompts.py,sha256=kudjHnAz7L3q0k_NLyTlaIV7M0uRFrxXNcfcnjOE2uc,5810
17
+ kiln_ai/adapters/data_gen/data_gen_task.py,sha256=0PuYCcj09BtpgNj23mKj_L45mKZBdV5VreUeZ-Tj_xM,6642
18
+ kiln_ai/adapters/data_gen/test_data_gen_task.py,sha256=cRKUKMvC0uVompbmPTKwbnQ_N3c0cQDm4J_9H4Y5U18,10129
19
+ kiln_ai/adapters/eval/__init__.py,sha256=0ptbK0ZxWuraxGn_WMgmE1tcaq0k5t-g-52kVohvWCg,693
20
+ kiln_ai/adapters/eval/base_eval.py,sha256=jVXMiVBC07ZnLEuZVAjUAYewsnuV99put39n_GZcG1M,7261
21
+ kiln_ai/adapters/eval/eval_runner.py,sha256=h3DvRFM5J5LDJqaLzNJ-q9i5LRycv2J9Ev5nw1mUDUQ,10806
22
+ kiln_ai/adapters/eval/g_eval.py,sha256=muJuolDz3SSJNcruqkMmgo8P3sX5Pzm6XD7vtfiVeX4,14298
23
+ kiln_ai/adapters/eval/registry.py,sha256=gZ_s0VgEx79Fswkgi1tS4yOl7lzpkvUBJZ62RldhM_w,626
24
+ kiln_ai/adapters/eval/test_base_eval.py,sha256=_1CiOUOiBt1R_gGYMcRblrPkHf-H4uIlvfcHj5-Wh7o,10724
25
+ kiln_ai/adapters/eval/test_eval_runner.py,sha256=82WPE_frNRTSQ2lylqT0inkqcDgM72nWt8GEuoDkJ7w,18568
26
+ kiln_ai/adapters/eval/test_g_eval.py,sha256=XSZ12BEqhzYLOfCg1VFZwu2DkbI9h4kVCqOFgzp9gX8,16163
27
+ kiln_ai/adapters/eval/test_g_eval_data.py,sha256=8caiZfLWnXVX8alrBPrH7L7gqqSS9vO7u6PzcHurQcA,27769
28
+ kiln_ai/adapters/fine_tune/__init__.py,sha256=DxdTR60chwgck1aEoVYWyfWi6Ed2ZkdJj0lar-SEAj4,257
29
+ kiln_ai/adapters/fine_tune/base_finetune.py,sha256=MxSnBiapWfZQw5UmkYAtC0QXj2zDeF9Ows0k0g3p1IA,6455
30
+ kiln_ai/adapters/fine_tune/dataset_formatter.py,sha256=qRhSSkMhTWn13OMb6LKPVwAU7uY4bB49GDiVSuhDkNg,14449
31
+ kiln_ai/adapters/fine_tune/finetune_registry.py,sha256=CvcEVxtKwjgCMA-oYH9Tpjn1DVWmMzgHpXJOZ0YQA8k,610
32
+ kiln_ai/adapters/fine_tune/fireworks_finetune.py,sha256=6IfTDn_8tg6PR0OFudRx6V7Wjvf4P7t0fm_xyRwII68,13978
33
+ kiln_ai/adapters/fine_tune/openai_finetune.py,sha256=Dz9E_0BWfrIkvv8ArZe-RKPwbIKPZ3v8rfbc3JELyTY,8571
34
+ kiln_ai/adapters/fine_tune/test_base_finetune.py,sha256=0zWxFYrDGVuoQNQmi9vVUEkBc4mstfHnsUjQmiJA-sE,10864
35
+ kiln_ai/adapters/fine_tune/test_dataset_formatter.py,sha256=T3jbFZooLVBaGCE0LUVxwPxzM3l8IY41zUj3jPk-Zi8,24027
36
+ kiln_ai/adapters/fine_tune/test_fireworks_tinetune.py,sha256=e88z5-KtU9Y7frXqCVy6r6iE6S-tInn5oMOqmSnbR2I,18144
37
+ kiln_ai/adapters/fine_tune/test_openai_finetune.py,sha256=H63Xk2PNHbt5Ev5IQpdR9JZ4uz-Huo2gfuC4mHHqe0w,20011
38
+ kiln_ai/adapters/fine_tune/test_together_finetune.py,sha256=YHtOHi2bsZcUDVHY62DTRKF3ZQry3Dv-qeW8povyR1o,17991
39
+ kiln_ai/adapters/fine_tune/together_finetune.py,sha256=kp-60ClwUimtjhRDsvPErS5whLDsBHGZhw8ITQ9JWCM,13868
40
+ kiln_ai/adapters/model_adapters/__init__.py,sha256=m5GRtOHwVVvp_XDOss8c1X3NFf1wQQlC2eBgI4tXQhM,212
41
+ kiln_ai/adapters/model_adapters/base_adapter.py,sha256=ifPJMg0nEKamfOSmBIsnp_MRFfBs47FLeQrLbav34yA,9872
42
+ kiln_ai/adapters/model_adapters/litellm_adapter.py,sha256=c4J_tIpM96KWS2qzoPaQmBj7X7mHyRMShdkmEh7_EHM,16129
43
+ kiln_ai/adapters/model_adapters/litellm_config.py,sha256=7-tIh5cuVu23Uy2Sd6q7UCT_4VgevBsAzVhQMj6Svgw,425
44
+ kiln_ai/adapters/model_adapters/test_base_adapter.py,sha256=uQyKrHLN3Jha6R-6SWkEME6brQecVFdPTSXogo-xpt0,6556
45
+ kiln_ai/adapters/model_adapters/test_litellm_adapter.py,sha256=QpnzuReNeBzvvRYnNj_5c8l1PS7NyrDDUQx_o21IIH4,13731
46
+ kiln_ai/adapters/model_adapters/test_saving_adapter_results.py,sha256=1XFQQxdSIbqSoQEdxHOYJcY0cMb59qpTDPOmL9bW4B8,7870
47
+ kiln_ai/adapters/model_adapters/test_structured_output.py,sha256=lHZSuPyvr--WCCEIik5OFqfvufmooPBbbUlSMUVvqmE,12516
48
+ kiln_ai/adapters/parsers/__init__.py,sha256=TGJS_8JhjUwg5Bnq4cDmwt5eIRo4vowmcL2A72L1Hzk,202
49
+ kiln_ai/adapters/parsers/base_parser.py,sha256=DaoZVEOOuFTMZd5ZTpl_as6-xc9NPWGP2fAmP12J58M,389
50
+ kiln_ai/adapters/parsers/json_parser.py,sha256=IszrBrhIFrrVr76UZsuejkBdqpZG27mU72264HVgVzE,1274
51
+ kiln_ai/adapters/parsers/parser_registry.py,sha256=G9bAZrnWrR0a82JAQHsSqA2o7-CjrZUBANZljY_6ZxE,623
52
+ kiln_ai/adapters/parsers/r1_parser.py,sha256=XHc_dKxiQjj8wG1w__rTmJVqa4fIg5L1g-igbv5Rl_g,2965
53
+ kiln_ai/adapters/parsers/test_json_parser.py,sha256=9kdWe_vRC5wjP8A1Ym6Zu6enDIz4ARCNiRpcZr7_3ak,1971
54
+ kiln_ai/adapters/parsers/test_parser_registry.py,sha256=S4MdX7cnhCbmeKq8tZwMwRdGWr-019Z-fw5zey9Wm08,1043
55
+ kiln_ai/adapters/parsers/test_r1_parser.py,sha256=VvCT_qCAfIbutFsxnpEzyZg-m5XLg7hI-Sorh2PplYw,4898
56
+ kiln_ai/adapters/repair/__init__.py,sha256=dOO9MEpEhjiwzDVFg3MNfA2bKMPlax9iekDatpTkX8E,217
57
+ kiln_ai/adapters/repair/repair_task.py,sha256=iW0bHWQq6Tir6ULTATWFS0zpwNji8Tbwhm2lZu52RsM,3342
58
+ kiln_ai/adapters/repair/test_repair_task.py,sha256=2jO0_aDPzbmZHC0skZBcKp3t9K4gISko3iSGCFHhQRs,7945
59
+ kiln_ai/datamodel/__init__.py,sha256=GbRfDrdSq9d_-HxzmFIicTmLO3qz-O3XGvSwDPh3XCk,1957
60
+ kiln_ai/datamodel/basemodel.py,sha256=Qsr3Kxq5B5rfPZxQFrfOMTGwInnfYy5srd8nK0nwOs0,22204
61
+ kiln_ai/datamodel/datamodel_enums.py,sha256=HUnGI_ZGQqyOicqEFFutZRWSANlQRQwfBu3XhVQFQSc,2270
62
+ kiln_ai/datamodel/dataset_filters.py,sha256=hWKxGJ-mSl4y0igyNcpmRoRYCiGrf0_uN4MMU9Fe_ng,3180
63
+ kiln_ai/datamodel/dataset_split.py,sha256=q4l4SlUvjLV547bzk7Z-fbmj_o26GDcYOZ2rA5RPh3c,5612
64
+ kiln_ai/datamodel/eval.py,sha256=kio2LqQ87MsP75DJTiIVdVfopTZXH4xjGN9g11V1mUU,13826
65
+ kiln_ai/datamodel/finetune.py,sha256=TYoNVRAfbjqvrY-1YmHwG6xSoDljiJWuuVcTbvQAJL4,4569
66
+ kiln_ai/datamodel/json_schema.py,sha256=qIlR8btXhN-8Yj5GhwebzPLUHPw2sJC3uM1axV2xV7w,3032
67
+ kiln_ai/datamodel/model_cache.py,sha256=9X4aAigbkFdytckgw8InCMh86uBna0ME_1HJSeMPEn0,4495
68
+ kiln_ai/datamodel/project.py,sha256=uVH2_3TDFtsG_tpts81A-zbd9uPDFxAwMCKZt_km3IE,727
69
+ kiln_ai/datamodel/prompt.py,sha256=70JPYHfgyX18cHW_DXoMzIOA28Jbaz6gyabElmpycyc,1161
70
+ kiln_ai/datamodel/prompt_id.py,sha256=eU2TV0RZapn-BgnZ4sOSNOOVEQ3aPaLzW4YSYCd3OBo,2531
71
+ kiln_ai/datamodel/registry.py,sha256=XwGFXJFKZtOpR1Z9ven6SftggfADdZRm8TFxCEVtfUQ,957
72
+ kiln_ai/datamodel/strict_mode.py,sha256=sm4Xka8mnJHCShtbh6MMU5dDQv-cLj8lHgHkmFKpsl0,849
73
+ kiln_ai/datamodel/task.py,sha256=r-_zgrQCIiIkN8gvBISdU449Z9oKp7E1XL0lkik_rVI,7036
74
+ kiln_ai/datamodel/task_output.py,sha256=uIYR8EyWv8Bbl60gPRuTIUSvfGGzP9Ltc5P280HyTpY,12931
75
+ kiln_ai/datamodel/task_run.py,sha256=yquE0jyr_9WzcvrMsEmZfXUnn8zZDEZIXZhVcVBMrT8,7038
76
+ kiln_ai/datamodel/test_basemodel.py,sha256=sJ8wXGef2WxzbrbMTYgrOwmkd5J6sHkly-cQBO2IZh4,18126
77
+ kiln_ai/datamodel/test_dataset_filters.py,sha256=v88QPkIsq4diUmoUF3-qj5KAW2rLRp0KDAm_pexbFy4,1894
78
+ kiln_ai/datamodel/test_dataset_split.py,sha256=5CHO1Lq4xQBB72tV2SPER7OZODJNvj15qxi_cYBV2Rs,11157
79
+ kiln_ai/datamodel/test_datasource.py,sha256=H4Kc-Im9eM7WnADWZXdoiOIrOl05RtkyuhTCKiRimyU,3905
80
+ kiln_ai/datamodel/test_eval_model.py,sha256=J7MqwWBgPpeXGqh3IacVUUHdZFJSZ2MgTsUNu-hNOJw,19528
81
+ kiln_ai/datamodel/test_example_models.py,sha256=fpqh0u7zFhWHcRHgtxCjX8RD2oKHYOP_mJJymaUhEZU,20944
82
+ kiln_ai/datamodel/test_json_schema.py,sha256=UgKwAFcdrJTq2byh7Yf-HoSAtiHiGAsNZxfkIvoMxIg,3915
83
+ kiln_ai/datamodel/test_model_cache.py,sha256=Fy-ucYNzS5JEG-8SFY4nVHA8iRbXXxai20f8_oGl97o,8184
84
+ kiln_ai/datamodel/test_model_perf.py,sha256=NdD7L8XraGkunaEKGPsfYwdcbIgdjhFanOO3G6hU158,3235
85
+ kiln_ai/datamodel/test_models.py,sha256=hmV7sTbOamWJCwOY96w-g4PQRv4Uai-XaHtg0QKH-ak,19295
86
+ kiln_ai/datamodel/test_nested_save.py,sha256=xciCddqvPyKyoyjC5Lx_3Kh1t4LJv1xYRAPazR3SRcs,5588
87
+ kiln_ai/datamodel/test_output_rating.py,sha256=zvPIp2shAgCs2RQBgwYoL09fRA3krHvgAqUa91RlWR0,15125
88
+ kiln_ai/datamodel/test_prompt_id.py,sha256=ihyXVPQi0dSLGnBM7rTXRnVaiWXhh7HJmSy4nZZKmso,4225
89
+ kiln_ai/datamodel/test_registry.py,sha256=PhS4anLi5Bf_023obuTlO5DALhtPB8WIc_bX12Yg6Po,2705
90
+ kiln_ai/datamodel/test_task.py,sha256=FYyoEqJXQIy8rcBsLTdki4-1z9COnZQk1-aoS3ZoNuU,5307
91
+ kiln_ai/utils/__init__.py,sha256=PTD0MwBCKAMIOGsTAwsFaJOusTJJoRFTfOGqRvCaU-E,142
92
+ kiln_ai/utils/config.py,sha256=IKPk9dMecDbqoBkfj52GT9xeity_y_sGP-vdm9CcKe4,8201
93
+ kiln_ai/utils/dataset_import.py,sha256=HvTCdK9OO8WE3Runn8_Vsks5KpCTckGIzAA7JKe-cWI,6956
94
+ kiln_ai/utils/exhaustive_error.py,sha256=TkkRixIAR3CPEKHeAJzyv0mtxp6BxUBKMvobA3vzQug,262
95
+ kiln_ai/utils/formatting.py,sha256=VtB9oag0lOGv17dwT7OPX_3HzBfaU9GsLH-iLete0yM,97
96
+ kiln_ai/utils/name_generator.py,sha256=v26TgpCwQbhQFcZvzgjZvURinjrOyyFhxpsI6NQrHKc,1914
97
+ kiln_ai/utils/test_config.py,sha256=Jw3nMFeIgZUsZDRJJY2HpB-2EkR2NoZ-rDe_o9oA7ws,9174
98
+ kiln_ai/utils/test_dataset_import.py,sha256=ZZOt7zqtaEIlMMx0VNXyRegDvnVqbWY2bcz-iMY_Oag,17427
99
+ kiln_ai/utils/test_name_geneator.py,sha256=9-hSTBshyakqlPbFnNcggwLrL7lcPTitauBYHg9jFWI,1513
100
+ kiln_ai-0.13.0.dist-info/METADATA,sha256=csSjOcBVu_PrMLFU16V54GmCmibcfCoeCWV0fWydbEA,12238
101
+ kiln_ai-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
102
+ kiln_ai-0.13.0.dist-info/licenses/LICENSE.txt,sha256=_NA5pnTYgRRr4qH6lE3X-TuZJ8iRcMUi5ASoGr-lEx8,1209
103
+ kiln_ai-0.13.0.dist-info/RECORD,,
@@ -1,302 +0,0 @@
1
- import os
2
- from typing import Any, Dict
3
-
4
- from langchain_aws import ChatBedrockConverse
5
- from langchain_core.language_models import LanguageModelInput
6
- from langchain_core.language_models.chat_models import BaseChatModel
7
- from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
8
- from langchain_core.messages.base import BaseMessage
9
- from langchain_core.runnables import Runnable
10
- from langchain_fireworks import ChatFireworks
11
- from langchain_groq import ChatGroq
12
- from langchain_ollama import ChatOllama
13
- from pydantic import BaseModel
14
-
15
- import kiln_ai.datamodel as datamodel
16
- from kiln_ai.adapters.ml_model_list import (
17
- KilnModelProvider,
18
- ModelProviderName,
19
- StructuredOutputMode,
20
- )
21
- from kiln_ai.adapters.model_adapters.base_adapter import (
22
- COT_FINAL_ANSWER_PROMPT,
23
- AdapterInfo,
24
- BaseAdapter,
25
- BasePromptBuilder,
26
- RunOutput,
27
- )
28
- from kiln_ai.adapters.ollama_tools import (
29
- get_ollama_connection,
30
- ollama_base_url,
31
- ollama_model_installed,
32
- )
33
- from kiln_ai.utils.config import Config
34
- from kiln_ai.utils.exhaustive_error import raise_exhaustive_enum_error
35
-
36
- LangChainModelType = BaseChatModel | Runnable[LanguageModelInput, Dict | BaseModel]
37
-
38
-
39
- class LangchainAdapter(BaseAdapter):
40
- _model: LangChainModelType | None = None
41
-
42
- def __init__(
43
- self,
44
- kiln_task: datamodel.Task,
45
- custom_model: BaseChatModel | None = None,
46
- model_name: str | None = None,
47
- provider: str | None = None,
48
- prompt_builder: BasePromptBuilder | None = None,
49
- tags: list[str] | None = None,
50
- ):
51
- if custom_model is not None:
52
- self._model = custom_model
53
-
54
- # Attempt to infer model provider and name from custom model
55
- if provider is None:
56
- provider = "custom.langchain:" + custom_model.__class__.__name__
57
-
58
- if model_name is None:
59
- model_name = "custom.langchain:unknown_model"
60
- if hasattr(custom_model, "model_name") and isinstance(
61
- getattr(custom_model, "model_name"), str
62
- ):
63
- model_name = "custom.langchain:" + getattr(
64
- custom_model, "model_name"
65
- )
66
- if hasattr(custom_model, "model") and isinstance(
67
- getattr(custom_model, "model"), str
68
- ):
69
- model_name = "custom.langchain:" + getattr(custom_model, "model")
70
- elif model_name is not None:
71
- # default provider name if not provided
72
- provider = provider or "custom.langchain.default_provider"
73
- else:
74
- raise ValueError(
75
- "model_name and provider must be provided if custom_model is not provided"
76
- )
77
-
78
- if model_name is None:
79
- raise ValueError("model_name must be provided")
80
-
81
- super().__init__(
82
- kiln_task,
83
- model_name=model_name,
84
- model_provider_name=provider,
85
- prompt_builder=prompt_builder,
86
- tags=tags,
87
- )
88
-
89
- async def model(self) -> LangChainModelType:
90
- # cached model
91
- if self._model:
92
- return self._model
93
-
94
- self._model = await self.langchain_model_from()
95
-
96
- # Decide if we want to use Langchain's structured output:
97
- # 1. Only for structured tasks
98
- # 2. Only if the provider's mode isn't json_instructions (only mode that doesn't use an API option for structured output capabilities)
99
- provider = self.model_provider()
100
- use_lc_structured_output = (
101
- self.has_structured_output()
102
- and provider.structured_output_mode
103
- != StructuredOutputMode.json_instructions
104
- )
105
-
106
- if use_lc_structured_output:
107
- if not hasattr(self._model, "with_structured_output") or not callable(
108
- getattr(self._model, "with_structured_output")
109
- ):
110
- raise ValueError(
111
- f"model {self._model} does not support structured output, cannot use output_json_schema"
112
- )
113
- # Langchain expects title/description to be at top level, on top of json schema
114
- output_schema = self.kiln_task.output_schema()
115
- if output_schema is None:
116
- raise ValueError(
117
- f"output_json_schema is not valid json: {self.kiln_task.output_json_schema}"
118
- )
119
- output_schema["title"] = "task_response"
120
- output_schema["description"] = "A response from the task"
121
- with_structured_output_options = self.get_structured_output_options(
122
- self.model_name, self.model_provider_name
123
- )
124
- self._model = self._model.with_structured_output(
125
- output_schema,
126
- include_raw=True,
127
- **with_structured_output_options,
128
- )
129
- return self._model
130
-
131
- async def _run(self, input: Dict | str) -> RunOutput:
132
- provider = self.model_provider()
133
- model = await self.model()
134
- chain = model
135
- intermediate_outputs = {}
136
-
137
- prompt = self.build_prompt()
138
- user_msg = self.prompt_builder.build_user_message(input)
139
- messages = [
140
- SystemMessage(content=prompt),
141
- HumanMessage(content=user_msg),
142
- ]
143
-
144
- run_strategy, cot_prompt = self.run_strategy()
145
-
146
- if run_strategy == "cot_as_message":
147
- if not cot_prompt:
148
- raise ValueError("cot_prompt is required for cot_as_message strategy")
149
- messages.append(SystemMessage(content=cot_prompt))
150
- elif run_strategy == "cot_two_call":
151
- if not cot_prompt:
152
- raise ValueError("cot_prompt is required for cot_two_call strategy")
153
- messages.append(
154
- SystemMessage(content=cot_prompt),
155
- )
156
-
157
- # Base model (without structured output) used for COT message
158
- base_model = await self.langchain_model_from()
159
-
160
- cot_messages = [*messages]
161
- cot_response = await base_model.ainvoke(cot_messages)
162
- intermediate_outputs["chain_of_thought"] = cot_response.content
163
- messages.append(AIMessage(content=cot_response.content))
164
- messages.append(HumanMessage(content=COT_FINAL_ANSWER_PROMPT))
165
-
166
- response = await chain.ainvoke(messages)
167
-
168
- # Langchain may have already parsed the response into structured output, so use that if available.
169
- # However, a plain string may still be fixed at the parsing layer, so not being structured isn't a critical failure (yet)
170
- if (
171
- self.has_structured_output()
172
- and isinstance(response, dict)
173
- and "parsed" in response
174
- and isinstance(response["parsed"], dict)
175
- ):
176
- structured_response = response["parsed"]
177
- return RunOutput(
178
- output=self._munge_response(structured_response),
179
- intermediate_outputs=intermediate_outputs,
180
- )
181
-
182
- if not isinstance(response, BaseMessage):
183
- raise RuntimeError(f"response is not a BaseMessage: {response}")
184
-
185
- text_content = response.content
186
- if not isinstance(text_content, str):
187
- raise RuntimeError(f"response is not a string: {text_content}")
188
-
189
- return RunOutput(
190
- output=text_content,
191
- intermediate_outputs=intermediate_outputs,
192
- )
193
-
194
- def adapter_info(self) -> AdapterInfo:
195
- return AdapterInfo(
196
- model_name=self.model_name,
197
- model_provider=self.model_provider_name,
198
- adapter_name="kiln_langchain_adapter",
199
- prompt_builder_name=self.prompt_builder.__class__.prompt_builder_name(),
200
- prompt_id=self.prompt_builder.prompt_id(),
201
- )
202
-
203
- def _munge_response(self, response: Dict) -> Dict:
204
- # Mistral Large tool calling format is a bit different. Convert to standard format.
205
- if (
206
- "name" in response
207
- and response["name"] == "task_response"
208
- and "arguments" in response
209
- ):
210
- return response["arguments"]
211
- return response
212
-
213
- def get_structured_output_options(
214
- self, model_name: str, model_provider_name: str
215
- ) -> Dict[str, Any]:
216
- provider = self.model_provider()
217
- if not provider:
218
- return {}
219
-
220
- options = {}
221
- # We may need to add some provider specific logic here if providers use different names for the same mode, but everyone is copying openai for now
222
- match provider.structured_output_mode:
223
- case StructuredOutputMode.function_calling:
224
- options["method"] = "function_calling"
225
- case StructuredOutputMode.json_mode:
226
- options["method"] = "json_mode"
227
- case StructuredOutputMode.json_instruction_and_object:
228
- # We also pass instructions
229
- options["method"] = "json_mode"
230
- case StructuredOutputMode.json_schema:
231
- options["method"] = "json_schema"
232
- case StructuredOutputMode.json_instructions:
233
- # JSON done via instructions in prompt, not via API
234
- pass
235
- case StructuredOutputMode.default:
236
- if provider.name == ModelProviderName.ollama:
237
- # Ollama has great json_schema support, so use that: https://ollama.com/blog/structured-outputs
238
- options["method"] = "json_schema"
239
- else:
240
- # Let langchain decide the default
241
- pass
242
- case _:
243
- raise_exhaustive_enum_error(provider.structured_output_mode)
244
-
245
- return options
246
-
247
- async def langchain_model_from(self) -> BaseChatModel:
248
- provider = self.model_provider()
249
- return await langchain_model_from_provider(provider, self.model_name)
250
-
251
-
252
- async def langchain_model_from_provider(
253
- provider: KilnModelProvider, model_name: str
254
- ) -> BaseChatModel:
255
- if provider.name == ModelProviderName.openai:
256
- # We use the OpenAICompatibleAdapter for OpenAI
257
- raise ValueError("OpenAI is not supported in Langchain adapter")
258
- elif provider.name == ModelProviderName.openai_compatible:
259
- # We use the OpenAICompatibleAdapter for OpenAI compatible
260
- raise ValueError("OpenAI compatible is not supported in Langchain adapter")
261
- elif provider.name == ModelProviderName.groq:
262
- api_key = Config.shared().groq_api_key
263
- if api_key is None:
264
- raise ValueError(
265
- "Attempted to use Groq without an API key set. "
266
- "Get your API key from https://console.groq.com/keys"
267
- )
268
- return ChatGroq(**provider.provider_options, groq_api_key=api_key) # type: ignore[arg-type]
269
- elif provider.name == ModelProviderName.amazon_bedrock:
270
- api_key = Config.shared().bedrock_access_key
271
- secret_key = Config.shared().bedrock_secret_key
272
- # langchain doesn't allow passing these, so ugly hack to set env vars
273
- os.environ["AWS_ACCESS_KEY_ID"] = api_key
274
- os.environ["AWS_SECRET_ACCESS_KEY"] = secret_key
275
- return ChatBedrockConverse(
276
- **provider.provider_options,
277
- )
278
- elif provider.name == ModelProviderName.fireworks_ai:
279
- api_key = Config.shared().fireworks_api_key
280
- return ChatFireworks(**provider.provider_options, api_key=api_key)
281
- elif provider.name == ModelProviderName.ollama:
282
- # Ollama model naming is pretty flexible. We try a few versions of the model name
283
- potential_model_names = []
284
- if "model" in provider.provider_options:
285
- potential_model_names.append(provider.provider_options["model"])
286
- if "model_aliases" in provider.provider_options:
287
- potential_model_names.extend(provider.provider_options["model_aliases"])
288
-
289
- # Get the list of models Ollama supports
290
- ollama_connection = await get_ollama_connection()
291
- if ollama_connection is None:
292
- raise ValueError("Failed to connect to Ollama. Ensure Ollama is running.")
293
-
294
- for model_name in potential_model_names:
295
- if ollama_model_installed(ollama_connection, model_name):
296
- return ChatOllama(model=model_name, base_url=ollama_base_url())
297
-
298
- raise ValueError(f"Model {model_name} not installed on Ollama")
299
- elif provider.name == ModelProviderName.openrouter:
300
- raise ValueError("OpenRouter is not supported in Langchain adapter")
301
- else:
302
- raise ValueError(f"Invalid model or provider: {model_name} - {provider.name}")
@@ -1,11 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
-
4
- @dataclass
5
- class OpenAICompatibleConfig:
6
- api_key: str
7
- model_name: str
8
- provider_name: str
9
- base_url: str | None = None # Defaults to OpenAI
10
- default_headers: dict[str, str] | None = None
11
- openrouter_style_reasoning: bool = False