lmnr 0.2.3__py3-none-any.whl → 0.2.4__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/sdk/remote_debugger.py +4 -3
- lmnr/types.py +6 -1
- lmnr-0.2.4.dist-info/METADATA +186 -0
- {lmnr-0.2.3.dist-info → lmnr-0.2.4.dist-info}/RECORD +7 -7
- lmnr-0.2.3.dist-info/METADATA +0 -78
- {lmnr-0.2.3.dist-info → lmnr-0.2.4.dist-info}/LICENSE +0 -0
- {lmnr-0.2.3.dist-info → lmnr-0.2.4.dist-info}/WHEEL +0 -0
- {lmnr-0.2.3.dist-info → lmnr-0.2.4.dist-info}/entry_points.txt +0 -0
lmnr/sdk/remote_debugger.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Callable, Optional
|
2
2
|
from websockets.sync.client import connect
|
3
|
-
from lmnr.types import NodeInput, RegisterDebuggerRequest, SDKError, ToolCall
|
3
|
+
from lmnr.types import DeregisterDebuggerRequest, NodeInput, RegisterDebuggerRequest, SDKError, ToolCall
|
4
4
|
import uuid
|
5
5
|
import json
|
6
6
|
from threading import Thread
|
@@ -32,7 +32,7 @@ class RemoteDebugger:
|
|
32
32
|
return self.session
|
33
33
|
|
34
34
|
def _run(self):
|
35
|
-
request = RegisterDebuggerRequest(
|
35
|
+
request = RegisterDebuggerRequest(debuggerSessionId=self.session)
|
36
36
|
with connect(
|
37
37
|
self.url,
|
38
38
|
additional_headers={
|
@@ -71,6 +71,7 @@ class RemoteDebugger:
|
|
71
71
|
pass
|
72
72
|
response = tool(**arguments)
|
73
73
|
websocket.send(json.dumps(response))
|
74
|
+
websocket.send(DeregisterDebuggerRequest(debuggerSessionId=self.session, deregister=True).model_dump_json())
|
74
75
|
|
75
76
|
def _generate_session_id(self) -> str:
|
76
77
|
return uuid.uuid4().urn[9:]
|
@@ -80,7 +81,7 @@ class RemoteDebugger:
|
|
80
81
|
f"""
|
81
82
|
========================================
|
82
83
|
Debugger Session ID:
|
83
|
-
{self.
|
84
|
+
{self.session}
|
84
85
|
========================================
|
85
86
|
"""
|
86
87
|
|
lmnr/types.py
CHANGED
@@ -51,5 +51,10 @@ class ToolCall(pydantic.BaseModel):
|
|
51
51
|
type: Optional[str]
|
52
52
|
function: ToolCallRequest
|
53
53
|
|
54
|
+
# TODO: allow snake_case and manually convert to camelCase
|
54
55
|
class RegisterDebuggerRequest(pydantic.BaseModel):
|
55
|
-
|
56
|
+
debuggerSessionId: str
|
57
|
+
|
58
|
+
class DeregisterDebuggerRequest(pydantic.BaseModel):
|
59
|
+
debuggerSessionId: str
|
60
|
+
deregister: bool
|
@@ -0,0 +1,186 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: lmnr
|
3
|
+
Version: 0.2.4
|
4
|
+
Summary: Python SDK for Laminar AI
|
5
|
+
License: Apache-2.0
|
6
|
+
Author: lmnr.ai
|
7
|
+
Requires-Python: >=3.9,<4.0
|
8
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
14
|
+
Requires-Dist: black (>=24.4.2,<25.0.0)
|
15
|
+
Requires-Dist: click (>=8.1.7,<9.0.0)
|
16
|
+
Requires-Dist: cookiecutter (>=2.6.0,<3.0.0)
|
17
|
+
Requires-Dist: pydantic (>=2.7.4,<3.0.0)
|
18
|
+
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
19
|
+
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
20
|
+
Requires-Dist: urllib3 (==1.26.6)
|
21
|
+
Requires-Dist: websockets (>=12.0,<13.0)
|
22
|
+
Description-Content-Type: text/markdown
|
23
|
+
|
24
|
+
# Python SDK for Laminar AI
|
25
|
+
|
26
|
+
## Quickstart
|
27
|
+
```sh
|
28
|
+
python3 -m venv .myenv
|
29
|
+
source .myenv/bin/activate # or use your favorite env management tool
|
30
|
+
|
31
|
+
pip install lmnr
|
32
|
+
```
|
33
|
+
|
34
|
+
## Features
|
35
|
+
|
36
|
+
- Make Laminar endpoint calls from your Python code
|
37
|
+
- Make Laminar endpoint calls that can run your own functions as tools
|
38
|
+
- CLI to generate code from pipelines you build on Laminar
|
39
|
+
- `LaminarRemoteDebugger` to execute your own functions while you test your flows in workshop
|
40
|
+
|
41
|
+
## Making Laminar endpoint calls
|
42
|
+
|
43
|
+
After you are ready to use your pipeline in your code, deploy it in Laminar following the [docs](https://docs.lmnr.ai/pipeline/run-save-deploy#deploying-a-pipeline-version).
|
44
|
+
|
45
|
+
Once your pipeline is deployed, you can call it from Python in just a few lines.
|
46
|
+
|
47
|
+
Example use:
|
48
|
+
|
49
|
+
```python
|
50
|
+
from lmnr import Laminar
|
51
|
+
|
52
|
+
l = Laminar('<YOUR_PROJECT_API_KEY>')
|
53
|
+
result = l.run(
|
54
|
+
endpoint = 'my_endpoint_name',
|
55
|
+
inputs = {'input_node_name': 'some_value'},
|
56
|
+
# all environment variables
|
57
|
+
env = {'OPENAI_API_KEY': 'sk-some-key'},
|
58
|
+
# any metadata to attach to this run's trace
|
59
|
+
metadata = {'session_id': 'your_custom_session_id'}
|
60
|
+
)
|
61
|
+
```
|
62
|
+
|
63
|
+
Resulting in:
|
64
|
+
|
65
|
+
```python
|
66
|
+
>>> result
|
67
|
+
EndpointRunResponse(
|
68
|
+
outputs={'output': {'value': [ChatMessage(role='user', content='hello')]}},
|
69
|
+
# useful to locate your trace
|
70
|
+
run_id='53b012d5-5759-48a6-a9c5-0011610e3669'
|
71
|
+
)
|
72
|
+
```
|
73
|
+
|
74
|
+
## Making calls to pipelines that run your own logic
|
75
|
+
|
76
|
+
If your pipeline contains tool call nodes, they will be able to call your local code.
|
77
|
+
The only difference is that you need to pass references
|
78
|
+
to the functions you want to call right into our SDK.
|
79
|
+
|
80
|
+
Example use:
|
81
|
+
|
82
|
+
```python
|
83
|
+
from lmnr import Laminar, NodeInput
|
84
|
+
|
85
|
+
# adding **kwargs is safer, in case an LLM produces more arguments than needed
|
86
|
+
def my_tool(arg1: string, arg2: string, **kwargs) -> NodeInput {
|
87
|
+
return f'{arg1}&{arg2}'
|
88
|
+
}
|
89
|
+
|
90
|
+
l = Laminar('<YOUR_PROJECT_API_KEY>')
|
91
|
+
result = l.run(
|
92
|
+
endpoint = 'my_endpoint_name',
|
93
|
+
inputs = {'input_node_name': 'some_value'},
|
94
|
+
# all environment variables
|
95
|
+
env = {'OPENAI_API_KEY': '<YOUR_MODEL_PROVIDER_KEY>'},
|
96
|
+
# any metadata to attach to this run's trace
|
97
|
+
metadata = {'session_id': 'your_custom_session_id'},
|
98
|
+
# specify as many tools as needed.
|
99
|
+
# Each tool name must match tool node name in the pipeline
|
100
|
+
tools=[my_tool]
|
101
|
+
)
|
102
|
+
```
|
103
|
+
|
104
|
+
## LaminarRemoteDebugger
|
105
|
+
|
106
|
+
If your pipeline contains tool call nodes, they will be able to call your local code.
|
107
|
+
If you want to test them from the Laminar workshop in your browser, you can attach to your
|
108
|
+
locally running debugger.
|
109
|
+
|
110
|
+
### Step by step instructions to use `LaminarRemoteDebugger`:
|
111
|
+
|
112
|
+
#### 1. Create your pipeline with tool call nodes
|
113
|
+
|
114
|
+
Add tool calls to your pipeline; node names must match the functions you want to call.
|
115
|
+
|
116
|
+
#### 2. Start LaminarRemoteDebugger in your code
|
117
|
+
|
118
|
+
Example:
|
119
|
+
|
120
|
+
```python
|
121
|
+
from lmnr import LaminarRemoteDebugger, NodeInput
|
122
|
+
|
123
|
+
# adding **kwargs is safer, in case an LLM produces more arguments than needed
|
124
|
+
def my_tool(arg1: string, arg2: string, **kwargs) -> NodeInput {
|
125
|
+
return f'{arg1}&{arg2}'
|
126
|
+
}
|
127
|
+
|
128
|
+
debugger = LaminarRemoteDebugger('<YOUR_PROJECT_API_KEY>', [my_tool])
|
129
|
+
session_id = debugger.start() # the session id will also be printed to console
|
130
|
+
```
|
131
|
+
|
132
|
+
This will establish a connection with Laminar API and allow for the pipeline execution
|
133
|
+
to call your local functions.
|
134
|
+
|
135
|
+
#### 3. Link lmnr.ai workshop to your debugger
|
136
|
+
|
137
|
+
Set up `DEBUGGER_SESSION_ID` environment variable in your pipeline.
|
138
|
+
|
139
|
+
#### 4. Run and experiment
|
140
|
+
|
141
|
+
You can run as many sessions as you need, experimenting with your flows.
|
142
|
+
|
143
|
+
#### 5. Stop the debugger
|
144
|
+
|
145
|
+
In order to stop the session, do
|
146
|
+
|
147
|
+
```python
|
148
|
+
debugger.stop()
|
149
|
+
```
|
150
|
+
|
151
|
+
## CLI for code generation
|
152
|
+
|
153
|
+
### Basic usage
|
154
|
+
|
155
|
+
```
|
156
|
+
lmnr pull <pipeline_name> <pipeline_version_name> --project-api-key <PROJECT_API_KEY>
|
157
|
+
```
|
158
|
+
|
159
|
+
Note that `lmnr` CLI command will only be available from within the virtual environment
|
160
|
+
where you have installed the package.
|
161
|
+
|
162
|
+
To import your pipeline
|
163
|
+
```python
|
164
|
+
# submodule with the name of your pipeline will be generated in lmnr_engine.pipelines
|
165
|
+
from lmnr_engine.pipelines.my_custom_pipeline import MyCustomPipeline
|
166
|
+
|
167
|
+
|
168
|
+
pipeline = MyCustomPipeline()
|
169
|
+
res = pipeline.run(
|
170
|
+
inputs={
|
171
|
+
"instruction": "Write me a short linkedin post about a dev tool for LLM developers"
|
172
|
+
},
|
173
|
+
env={
|
174
|
+
"OPENAI_API_KEY": <OPENAI_API_KEY>,
|
175
|
+
}
|
176
|
+
)
|
177
|
+
print(f"RESULT:\n{res}")
|
178
|
+
```
|
179
|
+
|
180
|
+
### Current functionality
|
181
|
+
- Supports graph generation for graphs with Input, Output, and LLM nodes only
|
182
|
+
- For LLM nodes, it only supports OpenAI and Anthropic models and doesn't support structured output
|
183
|
+
|
184
|
+
## PROJECT_API_KEY
|
185
|
+
|
186
|
+
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `PROJECT_API_KEY`.
|
@@ -19,10 +19,10 @@ lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipel
|
|
19
19
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/pipelines/{{cookiecutter.pipeline_dir_name}}/{{cookiecutter.pipeline_dir_name}}.py,sha256=WG-ZMofPpGXCx5jdWVry3_XBzcKjqn8ZycFSiWEOBPg,2858
|
20
20
|
lmnr/cli/{{cookiecutter.lmnr_pipelines_dir_name}}/types.py,sha256=iWuflMV7TiaBPs6-B-BlrovvWpZgHGGHK0v8rSqER7A,997
|
21
21
|
lmnr/sdk/endpoint.py,sha256=tT6-w-mwbh4BAwnj5G0pCVE_Sz8EUzZmpBtacm_T2pE,6359
|
22
|
-
lmnr/sdk/remote_debugger.py,sha256=
|
23
|
-
lmnr/types.py,sha256=
|
24
|
-
lmnr-0.2.
|
25
|
-
lmnr-0.2.
|
26
|
-
lmnr-0.2.
|
27
|
-
lmnr-0.2.
|
28
|
-
lmnr-0.2.
|
22
|
+
lmnr/sdk/remote_debugger.py,sha256=lAL7t0DXADLMTLsh6AN3rqVYf_A-aeG_mMbyU-G2wTk,3299
|
23
|
+
lmnr/types.py,sha256=Pi6R5qMmN4fiwZR0TzP4rxfSP6rFv4iouZ_OKnJsmhA,1685
|
24
|
+
lmnr-0.2.4.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
|
25
|
+
lmnr-0.2.4.dist-info/METADATA,sha256=BUDTL9WKd18EieHeb47or0gwjGd1dkSz0nJsvx6AFiw,5494
|
26
|
+
lmnr-0.2.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
27
|
+
lmnr-0.2.4.dist-info/entry_points.txt,sha256=Qg7ZRax4k-rcQsZ26XRYQ8YFSBiyY2PNxYfq4a6PYXI,41
|
28
|
+
lmnr-0.2.4.dist-info/RECORD,,
|
lmnr-0.2.3.dist-info/METADATA
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: lmnr
|
3
|
-
Version: 0.2.3
|
4
|
-
Summary: Python SDK for Laminar AI
|
5
|
-
License: Apache-2.0
|
6
|
-
Author: lmnr.ai
|
7
|
-
Requires-Python: >=3.9,<4.0
|
8
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: Programming Language :: Python :: 3.9
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
14
|
-
Requires-Dist: black (>=24.4.2,<25.0.0)
|
15
|
-
Requires-Dist: click (>=8.1.7,<9.0.0)
|
16
|
-
Requires-Dist: cookiecutter (>=2.6.0,<3.0.0)
|
17
|
-
Requires-Dist: pydantic (>=2.7.4,<3.0.0)
|
18
|
-
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
19
|
-
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
20
|
-
Requires-Dist: urllib3 (==1.26.6)
|
21
|
-
Requires-Dist: websockets (>=12.0,<13.0)
|
22
|
-
Description-Content-Type: text/markdown
|
23
|
-
|
24
|
-
# Python SDK for Laminar AI
|
25
|
-
|
26
|
-
Example use:
|
27
|
-
|
28
|
-
```python
|
29
|
-
from lmnr import Laminar
|
30
|
-
|
31
|
-
l = Laminar('<YOUR_PROJECT_API_KEY>')
|
32
|
-
result = l.run(
|
33
|
-
endpoint = 'my_endpoint_name',
|
34
|
-
inputs = {'input_node_name': 'some_value'},
|
35
|
-
env = {'OPENAI_API_KEY': 'sk-some-key'},
|
36
|
-
metadata = {'session_id': 'your_custom_session_id'}
|
37
|
-
)
|
38
|
-
```
|
39
|
-
|
40
|
-
Resulting in:
|
41
|
-
|
42
|
-
```python
|
43
|
-
>>> result
|
44
|
-
EndpointRunResponse(outputs={'output': {'value': [ChatMessage(role='user', content='hello')]}}, run_id='53b012d5-5759-48a6-a9c5-0011610e3669')
|
45
|
-
```
|
46
|
-
|
47
|
-
## CLI for code generation
|
48
|
-
|
49
|
-
### Basic usage
|
50
|
-
|
51
|
-
```
|
52
|
-
lmnr pull <pipeline_name> <pipeline_version_name> --project-api-key <PROJECT_API_KEY>
|
53
|
-
```
|
54
|
-
|
55
|
-
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `PROJECT_API_KEY`.
|
56
|
-
|
57
|
-
To import your pipeline
|
58
|
-
```python
|
59
|
-
# submodule with the name of your pipeline will be generated in lmnr_engine.pipelines
|
60
|
-
from lmnr_engine.pipelines.my_custom_pipeline import MyCustomPipeline
|
61
|
-
|
62
|
-
|
63
|
-
pipeline = MyCustomPipeline()
|
64
|
-
res = pipeline.run(
|
65
|
-
inputs={
|
66
|
-
"instruction": "Write me a short linked post about dev tool for LLM developers which they'll love"
|
67
|
-
},
|
68
|
-
env={
|
69
|
-
"OPENAI_API_KEY": <OPENAI_API_KEY>,
|
70
|
-
}
|
71
|
-
)
|
72
|
-
print(f"RESULT:\n{res}")
|
73
|
-
```
|
74
|
-
|
75
|
-
### Current functionality
|
76
|
-
- Supports graph generation for graphs with Input, Output, and LLM nodes only
|
77
|
-
- For LLM nodes, it only supports OpenAI and Anthropic models and doesn't support structured output
|
78
|
-
|
File without changes
|
File without changes
|
File without changes
|