lmnr 0.3.0b1__tar.gz → 0.3.1__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.
- {lmnr-0.3.0b1 → lmnr-0.3.1}/PKG-INFO +33 -14
- {lmnr-0.3.0b1 → lmnr-0.3.1}/README.md +32 -12
- {lmnr-0.3.0b1 → lmnr-0.3.1}/pyproject.toml +5 -3
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/__init__.py +1 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/client.py +5 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/LICENSE +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/collector.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/constants.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/context.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/decorators.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/interface.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/providers/__init__.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/providers/base.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/providers/fallback.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/providers/openai.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/providers/utils.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/tracing_types.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/types.py +0 -0
- {lmnr-0.3.0b1 → lmnr-0.3.1}/src/lmnr/sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: lmnr
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.1
|
4
4
|
Summary: Python SDK for Laminar AI
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: lmnr.ai
|
@@ -12,7 +12,6 @@ Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
14
14
|
Requires-Dist: backoff (>=2.2.1,<3.0.0)
|
15
|
-
Requires-Dist: black (>=24.4.2,<25.0.0)
|
16
15
|
Requires-Dist: openai (>=1.41.1,<2.0.0)
|
17
16
|
Requires-Dist: pydantic (>=2.7.4,<3.0.0)
|
18
17
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
@@ -31,6 +30,24 @@ source .myenv/bin/activate # or use your favorite env management tool
|
|
31
30
|
pip install lmnr
|
32
31
|
```
|
33
32
|
|
33
|
+
Create .env file at the root and add `LMNR_PROJECT_API_KEY` value to it.
|
34
|
+
|
35
|
+
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `LMNR_PROJECT_API_KEY`.
|
36
|
+
|
37
|
+
## Sending events
|
38
|
+
|
39
|
+
You can send events in two ways:
|
40
|
+
- `.event(name, value)` – for a pre-defined event with one of possible values.
|
41
|
+
- `.evaluate_event(name, data)` – for an event that our agent checks for and assigns a value from possible values.
|
42
|
+
|
43
|
+
There are 3 types of events:
|
44
|
+
- SCORE - this is an integer score where you specify inclusive minimum and maximum.
|
45
|
+
- CLASS - this is a classifier with one of the possible values.
|
46
|
+
- TAG - this event has no value and can be assigned to a span.
|
47
|
+
|
48
|
+
Important notes:
|
49
|
+
- If event name does not match anything pre-defined in the UI, the event won't be saved.
|
50
|
+
- If event value (when sent with `.event()`) is not in the domain, the event won't be saved.
|
34
51
|
|
35
52
|
## Decorator instrumentation example
|
36
53
|
|
@@ -65,10 +82,11 @@ def poem_writer(topic="turbulence"):
|
|
65
82
|
poem = response.choices[0].message.content
|
66
83
|
|
67
84
|
if topic in poem:
|
68
|
-
|
85
|
+
# send an event with a pre-defined name
|
86
|
+
lmnr_context.event("topic_alignment", "good")
|
69
87
|
|
70
88
|
# to trigger an automatic check for a possible event do:
|
71
|
-
lmnr_context.
|
89
|
+
lmnr_context.evaluate_event("excessive_wordiness", poem)
|
72
90
|
|
73
91
|
return poem
|
74
92
|
|
@@ -94,7 +112,7 @@ Both `TraceContext` and `SpanContext` expose the following interfaces:
|
|
94
112
|
- `end(**kwargs)` – update the current span, and terminate it
|
95
113
|
|
96
114
|
In addition, `SpanContext` allows you to:
|
97
|
-
- `event(name: str, value: str | int
|
115
|
+
- `event(name: str, value: str | int)` - emit a custom event at any point
|
98
116
|
- `evaluate_event(name: str, data: str)` - register a possible event for automatic checking by Laminar.
|
99
117
|
|
100
118
|
Example:
|
@@ -103,11 +121,11 @@ Example:
|
|
103
121
|
import os
|
104
122
|
from openai import OpenAI
|
105
123
|
|
106
|
-
from lmnr import trace, TraceContext, SpanContext
|
124
|
+
from lmnr import trace, TraceContext, SpanContext, EvaluateEvent
|
107
125
|
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
|
108
126
|
|
109
127
|
def poem_writer(t: TraceContext, topic = "turbulence"):
|
110
|
-
span: SpanContext = t.span(name="poem_writer", input=
|
128
|
+
span: SpanContext = t.span(name="poem_writer", input=topic)
|
111
129
|
|
112
130
|
prompt = f"write a poem about {topic}"
|
113
131
|
messages = [
|
@@ -126,15 +144,19 @@ def poem_writer(t: TraceContext, topic = "turbulence"):
|
|
126
144
|
)
|
127
145
|
poem = response.choices[0].message.content
|
128
146
|
if topic in poem:
|
129
|
-
llm_span.event("topic_alignment") # send an event with a pre-defined name
|
147
|
+
llm_span.event("topic_alignment", "good") # send an event with a pre-defined name
|
130
148
|
|
131
|
-
# note that you can register possible events here as well,
|
132
|
-
llm_span.
|
149
|
+
# note that you can register possible events here as well,
|
150
|
+
# not only `llm_span.evaluate_event()`
|
151
|
+
llm_span.end(
|
152
|
+
output=poem,
|
153
|
+
evaluate_events=[EvaluateEvent(name="excessive_wordines", data=poem)]
|
154
|
+
)
|
133
155
|
span.end(output=poem)
|
134
156
|
return poem
|
135
157
|
|
136
158
|
|
137
|
-
t: TraceContext = trace(user_id="
|
159
|
+
t: TraceContext = trace(user_id="user123", session_id="session123", release="release")
|
138
160
|
main(t, topic="laminar flow")
|
139
161
|
t.end(success=True)
|
140
162
|
```
|
@@ -180,7 +202,4 @@ PipelineRunResponse(
|
|
180
202
|
)
|
181
203
|
```
|
182
204
|
|
183
|
-
## PROJECT_API_KEY
|
184
|
-
|
185
|
-
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `PROJECT_API_KEY`.
|
186
205
|
|
@@ -10,6 +10,24 @@ source .myenv/bin/activate # or use your favorite env management tool
|
|
10
10
|
pip install lmnr
|
11
11
|
```
|
12
12
|
|
13
|
+
Create .env file at the root and add `LMNR_PROJECT_API_KEY` value to it.
|
14
|
+
|
15
|
+
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `LMNR_PROJECT_API_KEY`.
|
16
|
+
|
17
|
+
## Sending events
|
18
|
+
|
19
|
+
You can send events in two ways:
|
20
|
+
- `.event(name, value)` – for a pre-defined event with one of possible values.
|
21
|
+
- `.evaluate_event(name, data)` – for an event that our agent checks for and assigns a value from possible values.
|
22
|
+
|
23
|
+
There are 3 types of events:
|
24
|
+
- SCORE - this is an integer score where you specify inclusive minimum and maximum.
|
25
|
+
- CLASS - this is a classifier with one of the possible values.
|
26
|
+
- TAG - this event has no value and can be assigned to a span.
|
27
|
+
|
28
|
+
Important notes:
|
29
|
+
- If event name does not match anything pre-defined in the UI, the event won't be saved.
|
30
|
+
- If event value (when sent with `.event()`) is not in the domain, the event won't be saved.
|
13
31
|
|
14
32
|
## Decorator instrumentation example
|
15
33
|
|
@@ -44,10 +62,11 @@ def poem_writer(topic="turbulence"):
|
|
44
62
|
poem = response.choices[0].message.content
|
45
63
|
|
46
64
|
if topic in poem:
|
47
|
-
|
65
|
+
# send an event with a pre-defined name
|
66
|
+
lmnr_context.event("topic_alignment", "good")
|
48
67
|
|
49
68
|
# to trigger an automatic check for a possible event do:
|
50
|
-
lmnr_context.
|
69
|
+
lmnr_context.evaluate_event("excessive_wordiness", poem)
|
51
70
|
|
52
71
|
return poem
|
53
72
|
|
@@ -73,7 +92,7 @@ Both `TraceContext` and `SpanContext` expose the following interfaces:
|
|
73
92
|
- `end(**kwargs)` – update the current span, and terminate it
|
74
93
|
|
75
94
|
In addition, `SpanContext` allows you to:
|
76
|
-
- `event(name: str, value: str | int
|
95
|
+
- `event(name: str, value: str | int)` - emit a custom event at any point
|
77
96
|
- `evaluate_event(name: str, data: str)` - register a possible event for automatic checking by Laminar.
|
78
97
|
|
79
98
|
Example:
|
@@ -82,11 +101,11 @@ Example:
|
|
82
101
|
import os
|
83
102
|
from openai import OpenAI
|
84
103
|
|
85
|
-
from lmnr import trace, TraceContext, SpanContext
|
104
|
+
from lmnr import trace, TraceContext, SpanContext, EvaluateEvent
|
86
105
|
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
|
87
106
|
|
88
107
|
def poem_writer(t: TraceContext, topic = "turbulence"):
|
89
|
-
span: SpanContext = t.span(name="poem_writer", input=
|
108
|
+
span: SpanContext = t.span(name="poem_writer", input=topic)
|
90
109
|
|
91
110
|
prompt = f"write a poem about {topic}"
|
92
111
|
messages = [
|
@@ -105,15 +124,19 @@ def poem_writer(t: TraceContext, topic = "turbulence"):
|
|
105
124
|
)
|
106
125
|
poem = response.choices[0].message.content
|
107
126
|
if topic in poem:
|
108
|
-
llm_span.event("topic_alignment") # send an event with a pre-defined name
|
127
|
+
llm_span.event("topic_alignment", "good") # send an event with a pre-defined name
|
109
128
|
|
110
|
-
# note that you can register possible events here as well,
|
111
|
-
llm_span.
|
129
|
+
# note that you can register possible events here as well,
|
130
|
+
# not only `llm_span.evaluate_event()`
|
131
|
+
llm_span.end(
|
132
|
+
output=poem,
|
133
|
+
evaluate_events=[EvaluateEvent(name="excessive_wordines", data=poem)]
|
134
|
+
)
|
112
135
|
span.end(output=poem)
|
113
136
|
return poem
|
114
137
|
|
115
138
|
|
116
|
-
t: TraceContext = trace(user_id="
|
139
|
+
t: TraceContext = trace(user_id="user123", session_id="session123", release="release")
|
117
140
|
main(t, topic="laminar flow")
|
118
141
|
t.end(success=True)
|
119
142
|
```
|
@@ -159,6 +182,3 @@ PipelineRunResponse(
|
|
159
182
|
)
|
160
183
|
```
|
161
184
|
|
162
|
-
## PROJECT_API_KEY
|
163
|
-
|
164
|
-
Read more [here](https://docs.lmnr.ai/api-reference/introduction#authentication) on how to get `PROJECT_API_KEY`.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "lmnr"
|
3
|
-
version = "0.3.
|
3
|
+
version = "0.3.1"
|
4
4
|
description = "Python SDK for Laminar AI"
|
5
5
|
authors = [
|
6
6
|
{ name = "lmnr.ai", email = "founders@lmnr.ai" }
|
@@ -11,7 +11,7 @@ license = "Apache-2.0"
|
|
11
11
|
|
12
12
|
[tool.poetry]
|
13
13
|
name = "lmnr"
|
14
|
-
version = "0.3.
|
14
|
+
version = "0.3.1"
|
15
15
|
description = "Python SDK for Laminar AI"
|
16
16
|
authors = ["lmnr.ai"]
|
17
17
|
readme = "README.md"
|
@@ -19,7 +19,6 @@ license = "Apache-2.0"
|
|
19
19
|
|
20
20
|
[tool.poetry.dependencies]
|
21
21
|
python = "^3.9"
|
22
|
-
black = "^24.4.2"
|
23
22
|
pydantic = "^2.7.4"
|
24
23
|
requests = "^2.32.3"
|
25
24
|
python-dotenv = "^1.0.1"
|
@@ -27,6 +26,9 @@ python-dotenv = "^1.0.1"
|
|
27
26
|
openai = "^1.41.1"
|
28
27
|
backoff = "^2.2.1"
|
29
28
|
|
29
|
+
[tool.poetry.group.dev.dependencies]
|
30
|
+
black = "^24.8.0"
|
31
|
+
|
30
32
|
[build-system]
|
31
33
|
requires = ["poetry-core"]
|
32
34
|
build-backend = "poetry.core.masonry.api"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from .sdk.client import Laminar
|
2
2
|
from .sdk.decorators import observe, lmnr_context, wrap_llm_call
|
3
3
|
from .sdk.interface import trace, TraceContext, SpanContext
|
4
|
+
from .sdk.tracing_types import EvaluateEvent
|
4
5
|
from .sdk.types import ChatMessage, PipelineRunError, PipelineRunResponse, NodeInput
|
@@ -38,6 +38,11 @@ class Laminar:
|
|
38
38
|
self.project_api_key = dotenv.get_key(
|
39
39
|
dotenv_path=dotenv_path, key_to_get="LMNR_PROJECT_API_KEY"
|
40
40
|
)
|
41
|
+
if not self.project_api_key:
|
42
|
+
raise ValueError(
|
43
|
+
"Please initialize the Laminar object with your project API key or set "
|
44
|
+
"the LMNR_PROJECT_API_KEY environment variable in your environment or .env file"
|
45
|
+
)
|
41
46
|
|
42
47
|
def run(
|
43
48
|
self,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|