kiln-ai 0.5.3__tar.gz → 0.5.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kiln-ai might be problematic. Click here for more details.
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/.gitignore +1 -0
- kiln_ai-0.5.5/LICENSE.txt +13 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/PKG-INFO +43 -6
- kiln_ai-0.5.5/README.md +58 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/langchain_adapters.py +29 -13
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/ml_model_list.py +241 -39
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_ml_model_list.py +26 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_prompt_adaptors.py +18 -2
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_structured_output.py +23 -16
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/pyproject.toml +4 -2
- kiln_ai-0.5.3/LICENSE.txt +0 -4
- kiln_ai-0.5.3/POET +0 -29
- kiln_ai-0.5.3/README.md +0 -23
- kiln_ai-0.5.3/kiln_ai.egg-info/PKG-INFO +0 -45
- kiln_ai-0.5.3/kiln_ai.egg-info/SOURCES.txt +0 -38
- kiln_ai-0.5.3/kiln_ai.egg-info/dependency_links.txt +0 -1
- kiln_ai-0.5.3/kiln_ai.egg-info/requires.txt +0 -11
- kiln_ai-0.5.3/kiln_ai.egg-info/top_level.txt +0 -1
- kiln_ai-0.5.3/poetry.lock +0 -101
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/.python-version +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/index.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/base_adapter.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/langchain_adapters.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/ml_model_list.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/prompt_builders.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/repair/repair_task.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters/repair.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/adapters.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/datamodel/basemodel.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/datamodel/json_schema.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/datamodel.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/utils/config.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/utils/formatting.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai/utils.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/kiln_ai.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/core_library_docs/search.js +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/index.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/base_adapter.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/langchain_adapters.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/ml_model_list.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/prompt_builders.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/repair/repair_task.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters/repair.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/adapters.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/datamodel/basemodel.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/datamodel/json_schema.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/datamodel.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/utils/config.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/utils/formatting.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai/utils.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/kiln_ai.html +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/docs/kiln_core_docs/search.js +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/__init__.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/__init__.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/base_adapter.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/prompt_builders.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/repair/__init__.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/repair/repair_task.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/repair/test_repair_task.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_langchain_adapter.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_prompt_builders.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/adapters/test_saving_adapter_results.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/__init__.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/basemodel.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/json_schema.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_basemodel.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_datasource.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_example_models.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_json_schema.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_models.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_nested_save.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/datamodel/test_output_rating.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/utils/__init__.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/utils/config.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/utils/formatting.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/kiln_ai/utils/test_config.py +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/setup.cfg +0 -0
- {kiln_ai-0.5.3 → kiln_ai-0.5.5}/uv.lock +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
This license applies only to the software in the libs/core directory.
|
|
4
|
+
|
|
5
|
+
=======================================================
|
|
6
|
+
|
|
7
|
+
Copyright 2024 - Chesterfield Laboratories Inc.
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: kiln-ai
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.5
|
|
4
4
|
Summary: Kiln AI
|
|
5
5
|
Project-URL: Homepage, https://getkiln.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/Kiln-AI/kiln
|
|
@@ -9,9 +9,11 @@ Project-URL: Issues, https://github.com/Kiln-AI/kiln/issues
|
|
|
9
9
|
Author-email: "Steve Cosman, Chesterfield Laboratories Inc" <scosman@users.noreply.github.com>
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
17
|
Requires-Python: >=3.10
|
|
16
18
|
Requires-Dist: coverage>=7.6.4
|
|
17
19
|
Requires-Dist: jsonschema>=4.23.0
|
|
@@ -29,6 +31,12 @@ Description-Content-Type: text/markdown
|
|
|
29
31
|
|
|
30
32
|
# kiln_ai
|
|
31
33
|
|
|
34
|
+
<p align="center">
|
|
35
|
+
<picture>
|
|
36
|
+
<img width="205" alt="Kiln AI Logo" src="https://github.com/user-attachments/assets/5fbcbdf7-1feb-45c9-bd73-99a46dd0a47f">
|
|
37
|
+
</picture>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
32
40
|
[](https://pypi.org/project/kiln-ai)
|
|
33
41
|
[](https://pypi.org/project/kiln-ai)
|
|
34
42
|
[](https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html)
|
|
@@ -41,12 +49,41 @@ Description-Content-Type: text/markdown
|
|
|
41
49
|
pip install kiln_ai
|
|
42
50
|
```
|
|
43
51
|
|
|
44
|
-
## About
|
|
52
|
+
## About
|
|
53
|
+
|
|
54
|
+
This package is the Kiln AI core library. There is also a separate desktop application and server package. Learn more about Kiln AI at [getkiln.ai](https://getkiln.ai)
|
|
55
|
+
|
|
56
|
+
- Github: [github.com/Kiln-AI/kiln](https://github.com/Kiln-AI/kiln)
|
|
57
|
+
- Core Library Docs: [https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html](https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html)
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
45
60
|
|
|
46
|
-
|
|
61
|
+
```python
|
|
62
|
+
from kiln_ai.datamodel import Project
|
|
47
63
|
|
|
48
|
-
|
|
64
|
+
print("Reading Kiln project")
|
|
65
|
+
project = Project.load_from_file("path/to/project.kiln")
|
|
66
|
+
print("Project: ", project.name, " - ", project.description)
|
|
49
67
|
|
|
50
|
-
|
|
68
|
+
task = project.tasks()[0]
|
|
69
|
+
print("Task: ", task.name, " - ", task.description)
|
|
70
|
+
print("Total dataset size:", len(task.runs()))
|
|
51
71
|
|
|
52
|
-
|
|
72
|
+
# ... app specific code using the typed kiln datamodel
|
|
73
|
+
|
|
74
|
+
# Alternatively, load data into pandas or a similar tool:
|
|
75
|
+
import glob
|
|
76
|
+
import json
|
|
77
|
+
import pandas as pd
|
|
78
|
+
from pathlib import Path
|
|
79
|
+
|
|
80
|
+
dataitem_glob = str(task.path.parent) + "/runs/*/task_run.kiln"
|
|
81
|
+
|
|
82
|
+
dfs = []
|
|
83
|
+
for file in glob.glob(dataitem_glob):
|
|
84
|
+
js = json.loads(Path(file).read_text())
|
|
85
|
+
df = pd.json_normalize(js)
|
|
86
|
+
dfs.append(df)
|
|
87
|
+
final_df = pd.concat(dfs, ignore_index=True)
|
|
88
|
+
print(final_df)
|
|
89
|
+
```
|
kiln_ai-0.5.5/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# kiln_ai
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<picture>
|
|
5
|
+
<img width="205" alt="Kiln AI Logo" src="https://github.com/user-attachments/assets/5fbcbdf7-1feb-45c9-bd73-99a46dd0a47f">
|
|
6
|
+
</picture>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
[](https://pypi.org/project/kiln-ai)
|
|
10
|
+
[](https://pypi.org/project/kiln-ai)
|
|
11
|
+
[](https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```console
|
|
18
|
+
pip install kiln_ai
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## About
|
|
22
|
+
|
|
23
|
+
This package is the Kiln AI core library. There is also a separate desktop application and server package. Learn more about Kiln AI at [getkiln.ai](https://getkiln.ai)
|
|
24
|
+
|
|
25
|
+
- Github: [github.com/Kiln-AI/kiln](https://github.com/Kiln-AI/kiln)
|
|
26
|
+
- Core Library Docs: [https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html](https://kiln-ai.github.io/Kiln/kiln_core_docs/index.html)
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from kiln_ai.datamodel import Project
|
|
32
|
+
|
|
33
|
+
print("Reading Kiln project")
|
|
34
|
+
project = Project.load_from_file("path/to/project.kiln")
|
|
35
|
+
print("Project: ", project.name, " - ", project.description)
|
|
36
|
+
|
|
37
|
+
task = project.tasks()[0]
|
|
38
|
+
print("Task: ", task.name, " - ", task.description)
|
|
39
|
+
print("Total dataset size:", len(task.runs()))
|
|
40
|
+
|
|
41
|
+
# ... app specific code using the typed kiln datamodel
|
|
42
|
+
|
|
43
|
+
# Alternatively, load data into pandas or a similar tool:
|
|
44
|
+
import glob
|
|
45
|
+
import json
|
|
46
|
+
import pandas as pd
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
|
|
49
|
+
dataitem_glob = str(task.path.parent) + "/runs/*/task_run.kiln"
|
|
50
|
+
|
|
51
|
+
dfs = []
|
|
52
|
+
for file in glob.glob(dataitem_glob):
|
|
53
|
+
js = json.loads(Path(file).read_text())
|
|
54
|
+
df = pd.json_normalize(js)
|
|
55
|
+
dfs.append(df)
|
|
56
|
+
final_df = pd.concat(dfs, ignore_index=True)
|
|
57
|
+
print(final_df)
|
|
58
|
+
```
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
from typing import Dict
|
|
2
2
|
|
|
3
|
+
from langchain_core.language_models import LanguageModelInput
|
|
3
4
|
from langchain_core.language_models.chat_models import BaseChatModel
|
|
4
5
|
from langchain_core.messages import HumanMessage, SystemMessage
|
|
5
6
|
from langchain_core.messages.base import BaseMessage
|
|
7
|
+
from langchain_core.runnables import Runnable
|
|
8
|
+
from pydantic import BaseModel
|
|
6
9
|
|
|
7
10
|
import kiln_ai.datamodel as datamodel
|
|
8
11
|
|
|
9
12
|
from .base_adapter import AdapterInfo, BaseAdapter, BasePromptBuilder
|
|
10
13
|
from .ml_model_list import langchain_model_from
|
|
11
14
|
|
|
15
|
+
LangChainModelType = BaseChatModel | Runnable[LanguageModelInput, Dict | BaseModel]
|
|
16
|
+
|
|
12
17
|
|
|
13
18
|
class LangChainPromptAdapter(BaseAdapter):
|
|
19
|
+
_model: LangChainModelType | None = None
|
|
20
|
+
|
|
14
21
|
def __init__(
|
|
15
22
|
self,
|
|
16
23
|
kiln_task: datamodel.Task,
|
|
@@ -21,7 +28,7 @@ class LangChainPromptAdapter(BaseAdapter):
|
|
|
21
28
|
):
|
|
22
29
|
super().__init__(kiln_task, prompt_builder=prompt_builder)
|
|
23
30
|
if custom_model is not None:
|
|
24
|
-
self.
|
|
31
|
+
self._model = custom_model
|
|
25
32
|
|
|
26
33
|
# Attempt to infer model provider and name from custom model
|
|
27
34
|
self.model_provider = "custom.langchain:" + custom_model.__class__.__name__
|
|
@@ -37,19 +44,32 @@ class LangChainPromptAdapter(BaseAdapter):
|
|
|
37
44
|
):
|
|
38
45
|
self.model_name = "custom.langchain:" + getattr(custom_model, "model")
|
|
39
46
|
elif model_name is not None:
|
|
40
|
-
self.model = langchain_model_from(model_name, provider)
|
|
41
47
|
self.model_name = model_name
|
|
42
48
|
self.model_provider = provider or "custom.langchain.default_provider"
|
|
43
49
|
else:
|
|
44
50
|
raise ValueError(
|
|
45
51
|
"model_name and provider must be provided if custom_model is not provided"
|
|
46
52
|
)
|
|
53
|
+
|
|
54
|
+
def adapter_specific_instructions(self) -> str | None:
|
|
55
|
+
# TODO: would be better to explicitly use bind_tools:tool_choice="task_response" here
|
|
47
56
|
if self.has_structured_output():
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
return "Always respond with a tool call. Never respond with a human readable message."
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
async def model(self) -> LangChainModelType:
|
|
61
|
+
# cached model
|
|
62
|
+
if self._model:
|
|
63
|
+
return self._model
|
|
64
|
+
|
|
65
|
+
self._model = await langchain_model_from(self.model_name, self.model_provider)
|
|
66
|
+
|
|
67
|
+
if self.has_structured_output():
|
|
68
|
+
if not hasattr(self._model, "with_structured_output") or not callable(
|
|
69
|
+
getattr(self._model, "with_structured_output")
|
|
50
70
|
):
|
|
51
71
|
raise ValueError(
|
|
52
|
-
f"model {self.
|
|
72
|
+
f"model {self._model} does not support structured output, cannot use output_json_schema"
|
|
53
73
|
)
|
|
54
74
|
# Langchain expects title/description to be at top level, on top of json schema
|
|
55
75
|
output_schema = self.kiln_task.output_schema()
|
|
@@ -59,15 +79,10 @@ class LangChainPromptAdapter(BaseAdapter):
|
|
|
59
79
|
)
|
|
60
80
|
output_schema["title"] = "task_response"
|
|
61
81
|
output_schema["description"] = "A response from the task"
|
|
62
|
-
self.
|
|
82
|
+
self._model = self._model.with_structured_output(
|
|
63
83
|
output_schema, include_raw=True
|
|
64
84
|
)
|
|
65
|
-
|
|
66
|
-
def adapter_specific_instructions(self) -> str | None:
|
|
67
|
-
# TODO: would be better to explicitly use bind_tools:tool_choice="task_response" here
|
|
68
|
-
if self.has_structured_output():
|
|
69
|
-
return "Always respond with a tool call. Never respond with a human readable message."
|
|
70
|
-
return None
|
|
85
|
+
return self._model
|
|
71
86
|
|
|
72
87
|
async def _run(self, input: Dict | str) -> Dict | str:
|
|
73
88
|
prompt = self.build_prompt()
|
|
@@ -76,7 +91,8 @@ class LangChainPromptAdapter(BaseAdapter):
|
|
|
76
91
|
SystemMessage(content=prompt),
|
|
77
92
|
HumanMessage(content=user_msg),
|
|
78
93
|
]
|
|
79
|
-
|
|
94
|
+
model = await self.model()
|
|
95
|
+
response = model.invoke(messages)
|
|
80
96
|
|
|
81
97
|
if self.has_structured_output():
|
|
82
98
|
if (
|
|
@@ -2,9 +2,10 @@ import os
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from os import getenv
|
|
5
|
-
from typing import Dict, List, NoReturn
|
|
5
|
+
from typing import Any, Dict, List, NoReturn
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
|
+
import requests
|
|
8
9
|
from langchain_aws import ChatBedrockConverse
|
|
9
10
|
from langchain_core.language_models.chat_models import BaseChatModel
|
|
10
11
|
from langchain_groq import ChatGroq
|
|
@@ -43,6 +44,8 @@ class ModelFamily(str, Enum):
|
|
|
43
44
|
phi = "phi"
|
|
44
45
|
mistral = "mistral"
|
|
45
46
|
gemma = "gemma"
|
|
47
|
+
gemini = "gemini"
|
|
48
|
+
claude = "claude"
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
# Where models have instruct and raw versions, instruct is default and raw is specified
|
|
@@ -55,6 +58,9 @@ class ModelName(str, Enum):
|
|
|
55
58
|
llama_3_1_8b = "llama_3_1_8b"
|
|
56
59
|
llama_3_1_70b = "llama_3_1_70b"
|
|
57
60
|
llama_3_1_405b = "llama_3_1_405b"
|
|
61
|
+
llama_3_2_3b = "llama_3_2_3b"
|
|
62
|
+
llama_3_2_11b = "llama_3_2_11b"
|
|
63
|
+
llama_3_2_90b = "llama_3_2_90b"
|
|
58
64
|
gpt_4o_mini = "gpt_4o_mini"
|
|
59
65
|
gpt_4o = "gpt_4o"
|
|
60
66
|
phi_3_5 = "phi_3_5"
|
|
@@ -63,6 +69,12 @@ class ModelName(str, Enum):
|
|
|
63
69
|
gemma_2_2b = "gemma_2_2b"
|
|
64
70
|
gemma_2_9b = "gemma_2_9b"
|
|
65
71
|
gemma_2_27b = "gemma_2_27b"
|
|
72
|
+
claude_3_5_haiku = "claude_3_5_haiku"
|
|
73
|
+
claude_3_5_sonnet = "claude_3_5_sonnet"
|
|
74
|
+
gemini_1_5_flash = "gemini_1_5_flash"
|
|
75
|
+
gemini_1_5_flash_8b = "gemini_1_5_flash_8b"
|
|
76
|
+
gemini_1_5_pro = "gemini_1_5_pro"
|
|
77
|
+
nemotron_70b = "nemotron_70b"
|
|
66
78
|
|
|
67
79
|
|
|
68
80
|
class KilnModelProvider(BaseModel):
|
|
@@ -132,6 +144,79 @@ built_in_models: List[KilnModel] = [
|
|
|
132
144
|
),
|
|
133
145
|
],
|
|
134
146
|
),
|
|
147
|
+
# Claude 3.5 Haiku
|
|
148
|
+
KilnModel(
|
|
149
|
+
family=ModelFamily.claude,
|
|
150
|
+
name=ModelName.claude_3_5_haiku,
|
|
151
|
+
friendly_name="Claude 3.5 Haiku",
|
|
152
|
+
providers=[
|
|
153
|
+
KilnModelProvider(
|
|
154
|
+
name=ModelProviderName.openrouter,
|
|
155
|
+
provider_options={"model": "anthropic/claude-3-5-haiku"},
|
|
156
|
+
),
|
|
157
|
+
],
|
|
158
|
+
),
|
|
159
|
+
# Claude 3.5 Sonnet
|
|
160
|
+
KilnModel(
|
|
161
|
+
family=ModelFamily.claude,
|
|
162
|
+
name=ModelName.claude_3_5_sonnet,
|
|
163
|
+
friendly_name="Claude 3.5 Sonnet",
|
|
164
|
+
providers=[
|
|
165
|
+
KilnModelProvider(
|
|
166
|
+
name=ModelProviderName.openrouter,
|
|
167
|
+
provider_options={"model": "anthropic/claude-3.5-sonnet"},
|
|
168
|
+
),
|
|
169
|
+
],
|
|
170
|
+
),
|
|
171
|
+
# Gemini 1.5 Pro
|
|
172
|
+
KilnModel(
|
|
173
|
+
family=ModelFamily.gemini,
|
|
174
|
+
name=ModelName.gemini_1_5_pro,
|
|
175
|
+
friendly_name="Gemini 1.5 Pro",
|
|
176
|
+
providers=[
|
|
177
|
+
KilnModelProvider(
|
|
178
|
+
name=ModelProviderName.openrouter,
|
|
179
|
+
provider_options={"model": "google/gemini-pro-1.5"},
|
|
180
|
+
),
|
|
181
|
+
],
|
|
182
|
+
),
|
|
183
|
+
# Gemini 1.5 Flash
|
|
184
|
+
KilnModel(
|
|
185
|
+
family=ModelFamily.gemini,
|
|
186
|
+
name=ModelName.gemini_1_5_flash,
|
|
187
|
+
friendly_name="Gemini 1.5 Flash",
|
|
188
|
+
providers=[
|
|
189
|
+
KilnModelProvider(
|
|
190
|
+
name=ModelProviderName.openrouter,
|
|
191
|
+
provider_options={"model": "google/gemini-flash-1.5"},
|
|
192
|
+
),
|
|
193
|
+
],
|
|
194
|
+
),
|
|
195
|
+
# Gemini 1.5 Flash 8B
|
|
196
|
+
KilnModel(
|
|
197
|
+
family=ModelFamily.gemini,
|
|
198
|
+
name=ModelName.gemini_1_5_flash_8b,
|
|
199
|
+
friendly_name="Gemini 1.5 Flash 8B",
|
|
200
|
+
providers=[
|
|
201
|
+
KilnModelProvider(
|
|
202
|
+
name=ModelProviderName.openrouter,
|
|
203
|
+
provider_options={"model": "google/gemini-flash-1.5-8b"},
|
|
204
|
+
),
|
|
205
|
+
],
|
|
206
|
+
),
|
|
207
|
+
# Nemotron 70B
|
|
208
|
+
KilnModel(
|
|
209
|
+
family=ModelFamily.llama,
|
|
210
|
+
name=ModelName.nemotron_70b,
|
|
211
|
+
friendly_name="Nemotron 70B",
|
|
212
|
+
providers=[
|
|
213
|
+
KilnModelProvider(
|
|
214
|
+
name=ModelProviderName.openrouter,
|
|
215
|
+
supports_structured_output=False,
|
|
216
|
+
provider_options={"model": "nvidia/llama-3.1-nemotron-70b-instruct"},
|
|
217
|
+
),
|
|
218
|
+
],
|
|
219
|
+
),
|
|
135
220
|
# Llama 3.1-8b
|
|
136
221
|
KilnModel(
|
|
137
222
|
family=ModelFamily.llama,
|
|
@@ -144,6 +229,7 @@ built_in_models: List[KilnModel] = [
|
|
|
144
229
|
),
|
|
145
230
|
KilnModelProvider(
|
|
146
231
|
name=ModelProviderName.amazon_bedrock,
|
|
232
|
+
supports_structured_output=False,
|
|
147
233
|
provider_options={
|
|
148
234
|
"model": "meta.llama3-1-8b-instruct-v1:0",
|
|
149
235
|
"region_name": "us-west-2", # Llama 3.1 only in west-2
|
|
@@ -151,10 +237,14 @@ built_in_models: List[KilnModel] = [
|
|
|
151
237
|
),
|
|
152
238
|
KilnModelProvider(
|
|
153
239
|
name=ModelProviderName.ollama,
|
|
154
|
-
provider_options={
|
|
240
|
+
provider_options={
|
|
241
|
+
"model": "llama3.1:8b",
|
|
242
|
+
"model_aliases": ["llama3.1"], # 8b is default
|
|
243
|
+
},
|
|
155
244
|
),
|
|
156
245
|
KilnModelProvider(
|
|
157
246
|
name=ModelProviderName.openrouter,
|
|
247
|
+
supports_structured_output=False,
|
|
158
248
|
provider_options={"model": "meta-llama/llama-3.1-8b-instruct"},
|
|
159
249
|
),
|
|
160
250
|
],
|
|
@@ -171,7 +261,6 @@ built_in_models: List[KilnModel] = [
|
|
|
171
261
|
),
|
|
172
262
|
KilnModelProvider(
|
|
173
263
|
name=ModelProviderName.amazon_bedrock,
|
|
174
|
-
# TODO: this should work but a bug in the bedrock response schema
|
|
175
264
|
supports_structured_output=False,
|
|
176
265
|
provider_options={
|
|
177
266
|
"model": "meta.llama3-1-70b-instruct-v1:0",
|
|
@@ -182,11 +271,10 @@ built_in_models: List[KilnModel] = [
|
|
|
182
271
|
name=ModelProviderName.openrouter,
|
|
183
272
|
provider_options={"model": "meta-llama/llama-3.1-70b-instruct"},
|
|
184
273
|
),
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
# ),
|
|
274
|
+
KilnModelProvider(
|
|
275
|
+
name=ModelProviderName.ollama,
|
|
276
|
+
provider_options={"model": "llama3.1:70b"},
|
|
277
|
+
),
|
|
190
278
|
],
|
|
191
279
|
),
|
|
192
280
|
# Llama 3.1 405b
|
|
@@ -195,11 +283,6 @@ built_in_models: List[KilnModel] = [
|
|
|
195
283
|
name=ModelName.llama_3_1_405b,
|
|
196
284
|
friendly_name="Llama 3.1 405B",
|
|
197
285
|
providers=[
|
|
198
|
-
# TODO: bring back when groq does: https://console.groq.com/docs/models
|
|
199
|
-
# KilnModelProvider(
|
|
200
|
-
# name=ModelProviderName.groq,
|
|
201
|
-
# provider_options={"model": "llama-3.1-405b-instruct-v1:0"},
|
|
202
|
-
# ),
|
|
203
286
|
KilnModelProvider(
|
|
204
287
|
name=ModelProviderName.amazon_bedrock,
|
|
205
288
|
provider_options={
|
|
@@ -207,11 +290,10 @@ built_in_models: List[KilnModel] = [
|
|
|
207
290
|
"region_name": "us-west-2", # Llama 3.1 only in west-2
|
|
208
291
|
},
|
|
209
292
|
),
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
# ),
|
|
293
|
+
KilnModelProvider(
|
|
294
|
+
name=ModelProviderName.ollama,
|
|
295
|
+
provider_options={"model": "llama3.1:405b"},
|
|
296
|
+
),
|
|
215
297
|
KilnModelProvider(
|
|
216
298
|
name=ModelProviderName.openrouter,
|
|
217
299
|
provider_options={"model": "meta-llama/llama-3.1-405b-instruct"},
|
|
@@ -247,11 +329,49 @@ built_in_models: List[KilnModel] = [
|
|
|
247
329
|
name=ModelProviderName.openrouter,
|
|
248
330
|
provider_options={"model": "mistralai/mistral-large"},
|
|
249
331
|
),
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
332
|
+
KilnModelProvider(
|
|
333
|
+
name=ModelProviderName.ollama,
|
|
334
|
+
provider_options={"model": "mistral-large"},
|
|
335
|
+
),
|
|
336
|
+
],
|
|
337
|
+
),
|
|
338
|
+
# Llama 3.2 3B
|
|
339
|
+
KilnModel(
|
|
340
|
+
family=ModelFamily.llama,
|
|
341
|
+
name=ModelName.llama_3_2_3b,
|
|
342
|
+
friendly_name="Llama 3.2 3B",
|
|
343
|
+
providers=[
|
|
344
|
+
KilnModelProvider(
|
|
345
|
+
name=ModelProviderName.openrouter,
|
|
346
|
+
supports_structured_output=False,
|
|
347
|
+
provider_options={"model": "meta-llama/llama-3.2-3b-instruct"},
|
|
348
|
+
),
|
|
349
|
+
],
|
|
350
|
+
),
|
|
351
|
+
# Llama 3.2 11B
|
|
352
|
+
KilnModel(
|
|
353
|
+
family=ModelFamily.llama,
|
|
354
|
+
name=ModelName.llama_3_2_11b,
|
|
355
|
+
friendly_name="Llama 3.2 11B",
|
|
356
|
+
providers=[
|
|
357
|
+
KilnModelProvider(
|
|
358
|
+
name=ModelProviderName.openrouter,
|
|
359
|
+
supports_structured_output=False,
|
|
360
|
+
provider_options={"model": "meta-llama/llama-3.2-11b-vision-instruct"},
|
|
361
|
+
),
|
|
362
|
+
],
|
|
363
|
+
),
|
|
364
|
+
# Llama 3.2 90B
|
|
365
|
+
KilnModel(
|
|
366
|
+
family=ModelFamily.llama,
|
|
367
|
+
name=ModelName.llama_3_2_90b,
|
|
368
|
+
friendly_name="Llama 3.2 90B",
|
|
369
|
+
providers=[
|
|
370
|
+
KilnModelProvider(
|
|
371
|
+
name=ModelProviderName.openrouter,
|
|
372
|
+
supports_structured_output=False,
|
|
373
|
+
provider_options={"model": "meta-llama/llama-3.2-90b-vision-instruct"},
|
|
374
|
+
),
|
|
255
375
|
],
|
|
256
376
|
),
|
|
257
377
|
# Phi 3.5
|
|
@@ -263,6 +383,7 @@ built_in_models: List[KilnModel] = [
|
|
|
263
383
|
providers=[
|
|
264
384
|
KilnModelProvider(
|
|
265
385
|
name=ModelProviderName.ollama,
|
|
386
|
+
supports_structured_output=False,
|
|
266
387
|
provider_options={"model": "phi3.5"},
|
|
267
388
|
),
|
|
268
389
|
KilnModelProvider(
|
|
@@ -280,6 +401,7 @@ built_in_models: List[KilnModel] = [
|
|
|
280
401
|
providers=[
|
|
281
402
|
KilnModelProvider(
|
|
282
403
|
name=ModelProviderName.ollama,
|
|
404
|
+
supports_structured_output=False,
|
|
283
405
|
provider_options={
|
|
284
406
|
"model": "gemma2:2b",
|
|
285
407
|
},
|
|
@@ -293,13 +415,12 @@ built_in_models: List[KilnModel] = [
|
|
|
293
415
|
friendly_name="Gemma 2 9B",
|
|
294
416
|
supports_structured_output=False,
|
|
295
417
|
providers=[
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# ),
|
|
418
|
+
KilnModelProvider(
|
|
419
|
+
name=ModelProviderName.ollama,
|
|
420
|
+
provider_options={
|
|
421
|
+
"model": "gemma2:9b",
|
|
422
|
+
},
|
|
423
|
+
),
|
|
303
424
|
KilnModelProvider(
|
|
304
425
|
name=ModelProviderName.openrouter,
|
|
305
426
|
provider_options={"model": "google/gemma-2-9b-it"},
|
|
@@ -313,13 +434,12 @@ built_in_models: List[KilnModel] = [
|
|
|
313
434
|
friendly_name="Gemma 2 27B",
|
|
314
435
|
supports_structured_output=False,
|
|
315
436
|
providers=[
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
# ),
|
|
437
|
+
KilnModelProvider(
|
|
438
|
+
name=ModelProviderName.ollama,
|
|
439
|
+
provider_options={
|
|
440
|
+
"model": "gemma2:27b",
|
|
441
|
+
},
|
|
442
|
+
),
|
|
323
443
|
KilnModelProvider(
|
|
324
444
|
name=ModelProviderName.openrouter,
|
|
325
445
|
provider_options={"model": "google/gemma-2-27b-it"},
|
|
@@ -417,7 +537,9 @@ def check_provider_warnings(provider_name: ModelProviderName):
|
|
|
417
537
|
raise ValueError(warning_check.message)
|
|
418
538
|
|
|
419
539
|
|
|
420
|
-
def langchain_model_from(
|
|
540
|
+
async def langchain_model_from(
|
|
541
|
+
name: str, provider_name: str | None = None
|
|
542
|
+
) -> BaseChatModel:
|
|
421
543
|
"""
|
|
422
544
|
Creates a LangChain chat model instance for the specified model and provider.
|
|
423
545
|
|
|
@@ -476,7 +598,23 @@ def langchain_model_from(name: str, provider_name: str | None = None) -> BaseCha
|
|
|
476
598
|
**provider.provider_options,
|
|
477
599
|
)
|
|
478
600
|
elif provider.name == ModelProviderName.ollama:
|
|
479
|
-
|
|
601
|
+
# Ollama model naming is pretty flexible. We try a few versions of the model name
|
|
602
|
+
potential_model_names = []
|
|
603
|
+
if "model" in provider.provider_options:
|
|
604
|
+
potential_model_names.append(provider.provider_options["model"])
|
|
605
|
+
if "model_aliases" in provider.provider_options:
|
|
606
|
+
potential_model_names.extend(provider.provider_options["model_aliases"])
|
|
607
|
+
|
|
608
|
+
# Get the list of models Ollama supports
|
|
609
|
+
ollama_connection = await get_ollama_connection()
|
|
610
|
+
if ollama_connection is None:
|
|
611
|
+
raise ValueError("Failed to connect to Ollama. Ensure Ollama is running.")
|
|
612
|
+
|
|
613
|
+
for model_name in potential_model_names:
|
|
614
|
+
if ollama_model_supported(ollama_connection, model_name):
|
|
615
|
+
return ChatOllama(model=model_name, base_url=ollama_base_url())
|
|
616
|
+
|
|
617
|
+
raise ValueError(f"Model {name} not installed on Ollama")
|
|
480
618
|
elif provider.name == ModelProviderName.openrouter:
|
|
481
619
|
api_key = Config.shared().open_router_api_key
|
|
482
620
|
base_url = getenv("OPENROUTER_BASE_URL") or "https://openrouter.ai/api/v1"
|
|
@@ -519,3 +657,67 @@ async def ollama_online() -> bool:
|
|
|
519
657
|
except httpx.RequestError:
|
|
520
658
|
return False
|
|
521
659
|
return True
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
class OllamaConnection(BaseModel):
|
|
663
|
+
message: str
|
|
664
|
+
models: List[str]
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
# Parse the Ollama /api/tags response
|
|
668
|
+
def parse_ollama_tags(tags: Any) -> OllamaConnection | None:
|
|
669
|
+
# Build a list of models we support for Ollama from the built-in model list
|
|
670
|
+
supported_ollama_models = [
|
|
671
|
+
provider.provider_options["model"]
|
|
672
|
+
for model in built_in_models
|
|
673
|
+
for provider in model.providers
|
|
674
|
+
if provider.name == ModelProviderName.ollama
|
|
675
|
+
]
|
|
676
|
+
# Append model_aliases to supported_ollama_models
|
|
677
|
+
supported_ollama_models.extend(
|
|
678
|
+
[
|
|
679
|
+
alias
|
|
680
|
+
for model in built_in_models
|
|
681
|
+
for provider in model.providers
|
|
682
|
+
for alias in provider.provider_options.get("model_aliases", [])
|
|
683
|
+
]
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
if "models" in tags:
|
|
687
|
+
models = tags["models"]
|
|
688
|
+
if isinstance(models, list):
|
|
689
|
+
model_names = [model["model"] for model in models]
|
|
690
|
+
print(f"model_names: {model_names}")
|
|
691
|
+
available_supported_models = [
|
|
692
|
+
model
|
|
693
|
+
for model in model_names
|
|
694
|
+
if model in supported_ollama_models
|
|
695
|
+
or model in [f"{m}:latest" for m in supported_ollama_models]
|
|
696
|
+
]
|
|
697
|
+
if available_supported_models:
|
|
698
|
+
return OllamaConnection(
|
|
699
|
+
message="Ollama connected",
|
|
700
|
+
models=available_supported_models,
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
return OllamaConnection(
|
|
704
|
+
message="Ollama is running, but no supported models are installed. Install one or more supported model, like 'ollama pull phi3.5'.",
|
|
705
|
+
models=[],
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
async def get_ollama_connection() -> OllamaConnection | None:
|
|
710
|
+
"""
|
|
711
|
+
Gets the connection status for Ollama.
|
|
712
|
+
"""
|
|
713
|
+
try:
|
|
714
|
+
tags = requests.get(ollama_base_url() + "/api/tags", timeout=5).json()
|
|
715
|
+
|
|
716
|
+
except Exception:
|
|
717
|
+
return None
|
|
718
|
+
|
|
719
|
+
return parse_ollama_tags(tags)
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
def ollama_model_supported(conn: OllamaConnection, model_name: str) -> bool:
|
|
723
|
+
return model_name in conn.models or f"{model_name}:latest" in conn.models
|