lmnr 0.1.3__py3-none-any.whl → 0.2.1__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.
- lmnr/__init__.py +5 -3
- lmnr/cli/__init__.py +0 -0
- lmnr/cli/cli.py +3 -3
- lmnr/cli/parser/nodes/types.py +1 -0
- lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/{{cookiecutter.pipeline_dir_name}}.py +3 -3
- lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/types.py +1 -16
- lmnr/sdk/endpoint.py +3 -3
- lmnr/types.py +10 -51
- {lmnr-0.1.3.dist-info → lmnr-0.2.1.dist-info}/LICENSE +4 -1
- {lmnr-0.1.3.dist-info → lmnr-0.2.1.dist-info}/METADATA +1 -1
- {lmnr-0.1.3.dist-info → lmnr-0.2.1.dist-info}/RECORD +13 -12
- {lmnr-0.1.3.dist-info → lmnr-0.2.1.dist-info}/WHEEL +0 -0
- {lmnr-0.1.3.dist-info → lmnr-0.2.1.dist-info}/entry_points.txt +0 -0
lmnr/__init__.py
CHANGED
lmnr/cli/__init__.py
ADDED
File without changes
|
lmnr/cli/cli.py
CHANGED
@@ -56,7 +56,7 @@ def pull(pipeline_name, pipeline_version_name, project_api_key, loglevel):
|
|
56
56
|
"pipelineVersionName": pipeline_version_name,
|
57
57
|
}
|
58
58
|
res = requests.get(
|
59
|
-
"https://api.lmnr.ai/
|
59
|
+
"https://api.lmnr.ai/v2/pipeline-version-by-name",
|
60
60
|
headers=headers,
|
61
61
|
params=params,
|
62
62
|
)
|
@@ -73,7 +73,7 @@ def pull(pipeline_name, pipeline_version_name, project_api_key, loglevel):
|
|
73
73
|
|
74
74
|
pipeline_version = res.json()
|
75
75
|
|
76
|
-
class_name = to_pascal(pipeline_name.replace(" ", "_"))
|
76
|
+
class_name = to_pascal(pipeline_name.replace(" ", "_").replace("-", "_"))
|
77
77
|
|
78
78
|
context = {
|
79
79
|
"pipeline_name": pipeline_name,
|
@@ -91,7 +91,7 @@ def pull(pipeline_name, pipeline_version_name, project_api_key, loglevel):
|
|
91
91
|
output_dir=".",
|
92
92
|
config_file=None,
|
93
93
|
extra_context=context,
|
94
|
-
directory="cli",
|
94
|
+
directory="cli/",
|
95
95
|
no_input=True,
|
96
96
|
overwrite_if_exists=True,
|
97
97
|
)
|
lmnr/cli/parser/nodes/types.py
CHANGED
@@ -5,6 +5,7 @@ from lmnr.cli.parser.nodes import Handle, HandleType, NodeFunctions
|
|
5
5
|
from lmnr.cli.parser.utils import map_handles
|
6
6
|
from lmnr.types import NodeInput, ChatMessage
|
7
7
|
|
8
|
+
|
8
9
|
def node_input_from_json(json_val: Any) -> NodeInput:
|
9
10
|
if isinstance(json_val, str):
|
10
11
|
return json_val
|
@@ -3,7 +3,7 @@ from dataclasses import dataclass
|
|
3
3
|
import logging
|
4
4
|
from typing import Optional, Union
|
5
5
|
|
6
|
-
from
|
6
|
+
from lmnr.types import ChatMessage
|
7
7
|
from lmnr_engine.engine import Engine
|
8
8
|
{% set function_names = cookiecutter._tasks.values() | selectattr('node_type', '!=', 'Input') | map(attribute='function_name') | join(', ') %}
|
9
9
|
from .nodes.functions import {{ function_names }}
|
@@ -19,7 +19,7 @@ class PipelineRunnerError(Exception):
|
|
19
19
|
|
20
20
|
@dataclass
|
21
21
|
class PipelineRunOutput:
|
22
|
-
value: Union[str,
|
22
|
+
value: Union[str, list[ChatMessage]]
|
23
23
|
|
24
24
|
|
25
25
|
# This class is not imported in other files and can be renamed to desired name
|
@@ -55,7 +55,7 @@ class {{ cookiecutter.class_name }}:
|
|
55
55
|
run_inputs[inp_name] = inp
|
56
56
|
else:
|
57
57
|
assert isinstance(inp, list), f"Invalid input type: {type(inp)}"
|
58
|
-
run_inputs[inp_name] = [ChatMessage.
|
58
|
+
run_inputs[inp_name] = [ChatMessage.model_validate(msg) for msg in inp]
|
59
59
|
|
60
60
|
tasks = []
|
61
61
|
{% for task in cookiecutter._tasks.values() %}
|
@@ -2,22 +2,7 @@ from dataclasses import dataclass
|
|
2
2
|
from typing import Union
|
3
3
|
import uuid
|
4
4
|
import datetime
|
5
|
-
|
6
|
-
|
7
|
-
@dataclass
|
8
|
-
class ChatMessage:
|
9
|
-
role: str
|
10
|
-
content: str
|
11
|
-
|
12
|
-
@classmethod
|
13
|
-
def from_dict(cls, data: dict) -> "ChatMessage":
|
14
|
-
return cls(
|
15
|
-
role=data["role"],
|
16
|
-
content=data["content"],
|
17
|
-
)
|
18
|
-
|
19
|
-
|
20
|
-
NodeInput = Union[str, list[ChatMessage]] # TODO: Add conditioned value
|
5
|
+
from lmnr.types import NodeInput, ChatMessage
|
21
6
|
|
22
7
|
|
23
8
|
@dataclass
|
lmnr/sdk/endpoint.py
CHANGED
@@ -2,7 +2,7 @@ import json
|
|
2
2
|
from pydantic.alias_generators import to_snake
|
3
3
|
import pydantic
|
4
4
|
import requests
|
5
|
-
from
|
5
|
+
from lmnr.types import (
|
6
6
|
EndpointRunError, EndpointRunResponse, NodeInput, EndpointRunRequest,
|
7
7
|
ToolCall, SDKError
|
8
8
|
)
|
@@ -21,7 +21,7 @@ class Laminar:
|
|
21
21
|
"""
|
22
22
|
self.project_api_key = project_api_key
|
23
23
|
self.url = 'https://api.lmnr.ai/v2/endpoint/run'
|
24
|
-
self.ws_url = '
|
24
|
+
self.ws_url = 'wss://api.lmnr.ai/v2/endpoint/ws'
|
25
25
|
|
26
26
|
def run (
|
27
27
|
self,
|
@@ -120,7 +120,7 @@ class Laminar:
|
|
120
120
|
raise ValueError(f'Invalid request: {e}')
|
121
121
|
|
122
122
|
with connect(
|
123
|
-
|
123
|
+
self.ws_url,
|
124
124
|
additional_headers={
|
125
125
|
'Authorization': f'Bearer {self.project_api_key}'
|
126
126
|
}
|
lmnr/types.py
CHANGED
@@ -1,21 +1,12 @@
|
|
1
|
+
|
1
2
|
import requests
|
2
3
|
import pydantic
|
3
|
-
from typing import
|
4
|
+
from typing import Union, Optional
|
4
5
|
|
5
6
|
class ChatMessage(pydantic.BaseModel):
|
6
|
-
"""Chat message object
|
7
|
-
|
8
|
-
Attributes:
|
9
|
-
role (str):
|
10
|
-
Role of the message sender.
|
11
|
-
Can be 'user', 'assistant', or 'system'.
|
12
|
-
content (str): Message content
|
13
|
-
"""
|
14
7
|
role: str
|
15
8
|
content: str
|
16
9
|
|
17
|
-
"""NodeInput is a common type for values shared
|
18
|
-
between nodes in Laminar pipelines."""
|
19
10
|
NodeInput = Union[str, list[ChatMessage]] # TypeAlias
|
20
11
|
|
21
12
|
class EndpointRunRequest(pydantic.BaseModel):
|
@@ -25,30 +16,9 @@ class EndpointRunRequest(pydantic.BaseModel):
|
|
25
16
|
metadata: dict[str, str] = pydantic.Field(default_factory=dict)
|
26
17
|
|
27
18
|
class EndpointRunResponse(pydantic.BaseModel):
|
28
|
-
"""Response object from endpoint run
|
29
|
-
|
30
|
-
Attributes:
|
31
|
-
outputs (dict[str, dict[str, NodeInput]]):
|
32
|
-
Dictionary of output names and their values.
|
33
|
-
Each value is a dictionary with the following keys:
|
34
|
-
- 'value': Output value
|
35
|
-
run_id (str): Stringified UUID of the run. Useful to find traces.
|
36
|
-
"""
|
37
19
|
outputs: dict[str, dict[str, NodeInput]]
|
38
20
|
run_id: str
|
39
21
|
|
40
|
-
def get_output(self, output_name: str) -> Optional[NodeInput]:
|
41
|
-
"""utility to extract the output value by node name
|
42
|
-
|
43
|
-
Args:
|
44
|
-
output_name (str): must match the output node name
|
45
|
-
|
46
|
-
Returns:
|
47
|
-
Optional[NodeInput]: value of the output node if found
|
48
|
-
"""
|
49
|
-
output = self.outputs.get(output_name)
|
50
|
-
return output.get('value') if output else None
|
51
|
-
|
52
22
|
class EndpointRunError(Exception):
|
53
23
|
error_code: str
|
54
24
|
error_message: str
|
@@ -64,30 +34,19 @@ class EndpointRunError(Exception):
|
|
64
34
|
|
65
35
|
def __str__(self) -> str:
|
66
36
|
try:
|
67
|
-
return str({
|
68
|
-
'error_code': self.error_code,
|
69
|
-
'error_message': self.error_message
|
70
|
-
})
|
37
|
+
return str({'error_code': self.error_code, 'error_message': self.error_message})
|
71
38
|
except:
|
72
39
|
return super().__str__()
|
73
|
-
|
40
|
+
|
74
41
|
class SDKError(Exception):
|
75
|
-
|
76
|
-
|
77
|
-
def __init__(self, error_message: str):
|
78
|
-
self.error_message = error_message
|
79
|
-
super().__init__(self.error_message)
|
80
|
-
|
81
|
-
def __str__(self) -> str:
|
82
|
-
return super().__str__()
|
42
|
+
def __init__(self, error_mesasge: str):
|
43
|
+
super().__init__(error_mesasge)
|
83
44
|
|
84
|
-
class
|
45
|
+
class ToolCallRequest(pydantic.BaseModel):
|
85
46
|
name: str
|
86
47
|
arguments: str
|
87
48
|
|
88
49
|
class ToolCall(pydantic.BaseModel):
|
89
|
-
id: str
|
90
|
-
type: str
|
91
|
-
function:
|
92
|
-
|
93
|
-
ToolResponse = NodeInput # TypeAlias
|
50
|
+
id: Optional[str]
|
51
|
+
type: Optional[str]
|
52
|
+
function: ToolCallRequest
|
@@ -1,3 +1,5 @@
|
|
1
|
+
|
2
|
+
|
1
3
|
Apache License
|
2
4
|
Version 2.0, January 2004
|
3
5
|
http://www.apache.org/licenses/
|
@@ -51,7 +53,8 @@ You may add Your own copyright statement to Your modifications and may provide a
|
|
51
53
|
|
52
54
|
END OF TERMS AND CONDITIONS
|
53
55
|
|
54
|
-
|
56
|
+
|
57
|
+
APPENDIX: How to apply the Apache License to your work
|
55
58
|
|
56
59
|
Include a copy of the Apache License, typically in a file called LICENSE, in your work, and consider also including a NOTICE file that references the License.
|
57
60
|
|
@@ -1,10 +1,11 @@
|
|
1
|
-
lmnr/__init__.py,sha256=
|
1
|
+
lmnr/__init__.py,sha256=fUbQpFuP1eK1dymP72SH5tFn-zggGVJkqIPU8X9Iq6w,134
|
2
|
+
lmnr/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
3
|
lmnr/cli/__main__.py,sha256=8hDtWlaFZK24KhfNq_ZKgtXqYHsDQDetukOCMlsbW0Q,59
|
3
|
-
lmnr/cli/cli.py,sha256=
|
4
|
+
lmnr/cli/cli.py,sha256=pzr5LUILi7TcaJIkC-CzmT7RG7-HWApQmUpgK9bc7mI,2847
|
4
5
|
lmnr/cli/cookiecutter.json,sha256=PeiMMzCPzDhsapqYoAceYGPI5lOUNimvFzh5KeQv5QE,359
|
5
6
|
lmnr/cli/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
7
|
lmnr/cli/parser/nodes/__init__.py,sha256=BNbbfn0WwbFDA6TNhLOaT_Ji69rCL5voUibqMD7Knng,1163
|
7
|
-
lmnr/cli/parser/nodes/types.py,sha256=
|
8
|
+
lmnr/cli/parser/nodes/types.py,sha256=fqw_0-szpcZ8G3bADjgG97gCng2DRIkL72nLV11gTP4,5081
|
8
9
|
lmnr/cli/parser/parser.py,sha256=UtuupKj2Dh-47HVcYU4PI2s4Erh1gTjKiuGCcc-nkbM,2163
|
9
10
|
lmnr/cli/parser/utils.py,sha256=wVaqHVOR9VXl8Og9nkVyCVgHIcgbtYGkDOEGPtmjZ8g,715
|
10
11
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -15,12 +16,12 @@ lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/engine/state.py,sha256=wTx7jAv
|
|
15
16
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/engine/task.py,sha256=ware5VIrZvluHH3mpH6h7G0YDk5L0buSQ7s09za4Fro,1200
|
16
17
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/__init__.py,sha256=bsfbNUBYtKv37qzc_GLhSAzBam2lnowP_dlr8pubhcg,80
|
17
18
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/nodes/functions.py,sha256=2fLTN6PbhlSPEcrHBSSJESmg__UNMk4Ivs5mz0LqnG8,5169
|
18
|
-
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/{{cookiecutter.pipeline_dir_name}}.py,sha256=
|
19
|
-
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/types.py,sha256=
|
20
|
-
lmnr/sdk/endpoint.py,sha256=
|
21
|
-
lmnr/types.py,sha256=
|
22
|
-
lmnr-0.1.
|
23
|
-
lmnr-0.1.
|
24
|
-
lmnr-0.1.
|
25
|
-
lmnr-0.1.
|
26
|
-
lmnr-0.1.
|
19
|
+
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/{{cookiecutter.pipeline_dir_name}}.py,sha256=WG-ZMofPpGXCx5jdWVry3_XBzcKjqn8ZycFSiWEOBPg,2858
|
20
|
+
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/types.py,sha256=iWuflMV7TiaBPs6-B-BlrovvWpZgHGGHK0v8rSqER7A,997
|
21
|
+
lmnr/sdk/endpoint.py,sha256=tT6-w-mwbh4BAwnj5G0pCVE_Sz8EUzZmpBtacm_T2pE,6359
|
22
|
+
lmnr/types.py,sha256=SECA2thlH3pO1F6UvvpyffnwHSdjho4RE2hPYJQH-jE,1444
|
23
|
+
lmnr-0.2.1.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
|
24
|
+
lmnr-0.2.1.dist-info/METADATA,sha256=aTT3pJgKV_4wxQ6kyjhhk7GuI1xBNTbK-MFviSn3iGo,2258
|
25
|
+
lmnr-0.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
26
|
+
lmnr-0.2.1.dist-info/entry_points.txt,sha256=Qg7ZRax4k-rcQsZ26XRYQ8YFSBiyY2PNxYfq4a6PYXI,41
|
27
|
+
lmnr-0.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|