lmnr 0.4.4__tar.gz → 0.4.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.
- {lmnr-0.4.4 → lmnr-0.4.5}/PKG-INFO +39 -1
- {lmnr-0.4.4 → lmnr-0.4.5}/README.md +38 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/pyproject.toml +2 -2
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/laminar.py +20 -19
- {lmnr-0.4.4 → lmnr-0.4.5}/LICENSE +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/__init__.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/decorators.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/evaluations.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/log.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/types.py +0 -0
- {lmnr-0.4.4 → lmnr-0.4.5}/src/lmnr/sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: lmnr
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.5
|
4
4
|
Summary: Python SDK for Laminar AI
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: lmnr.ai
|
@@ -89,6 +89,44 @@ def poem_writer(topic="turbulence"):
|
|
89
89
|
print(poem_writer(topic="laminar flow"))
|
90
90
|
```
|
91
91
|
|
92
|
+
### Manual instrumentation
|
93
|
+
|
94
|
+
Our manual instrumentation is a very thin wrapper around OpenTelemetry's
|
95
|
+
`trace.start_span`. Our wrapper sets the span into the active context.
|
96
|
+
You don't have to explicitly pass the spans around, it is enough to
|
97
|
+
just call `L.start_span`, and OpenTelemetry will handle the context management
|
98
|
+
|
99
|
+
```python
|
100
|
+
from lmnr import observe, Laminar as L
|
101
|
+
L.initialize(project_api_key="<LMNR_PROJECT_API_KEY>")
|
102
|
+
|
103
|
+
def poem_writer(topic="turbulence"):
|
104
|
+
|
105
|
+
span = L.start_span("poem_writer", topic) # start a span
|
106
|
+
|
107
|
+
prompt = f"write a poem about {topic}"
|
108
|
+
|
109
|
+
# OpenAI calls are still automatically instrumented with OpenLLMetry
|
110
|
+
response = client.chat.completions.create(
|
111
|
+
model="gpt-4o",
|
112
|
+
messages=[
|
113
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
114
|
+
{"role": "user", "content": prompt},
|
115
|
+
],
|
116
|
+
)
|
117
|
+
poem = response.choices[0].message.content
|
118
|
+
# while within the span, you can attach laminar events to it
|
119
|
+
L.event("event_name", "event_value")
|
120
|
+
|
121
|
+
L.set_span_output(span, poem) # set an output
|
122
|
+
|
123
|
+
# IMPORTANT: don't forget to end all the spans (usually in `finally` blocks)
|
124
|
+
# Otherwise, the trace may not be sent/displayed correctly
|
125
|
+
span.end()
|
126
|
+
|
127
|
+
return poem
|
128
|
+
```
|
129
|
+
|
92
130
|
|
93
131
|
## Sending events
|
94
132
|
|
@@ -68,6 +68,44 @@ def poem_writer(topic="turbulence"):
|
|
68
68
|
print(poem_writer(topic="laminar flow"))
|
69
69
|
```
|
70
70
|
|
71
|
+
### Manual instrumentation
|
72
|
+
|
73
|
+
Our manual instrumentation is a very thin wrapper around OpenTelemetry's
|
74
|
+
`trace.start_span`. Our wrapper sets the span into the active context.
|
75
|
+
You don't have to explicitly pass the spans around, it is enough to
|
76
|
+
just call `L.start_span`, and OpenTelemetry will handle the context management
|
77
|
+
|
78
|
+
```python
|
79
|
+
from lmnr import observe, Laminar as L
|
80
|
+
L.initialize(project_api_key="<LMNR_PROJECT_API_KEY>")
|
81
|
+
|
82
|
+
def poem_writer(topic="turbulence"):
|
83
|
+
|
84
|
+
span = L.start_span("poem_writer", topic) # start a span
|
85
|
+
|
86
|
+
prompt = f"write a poem about {topic}"
|
87
|
+
|
88
|
+
# OpenAI calls are still automatically instrumented with OpenLLMetry
|
89
|
+
response = client.chat.completions.create(
|
90
|
+
model="gpt-4o",
|
91
|
+
messages=[
|
92
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
93
|
+
{"role": "user", "content": prompt},
|
94
|
+
],
|
95
|
+
)
|
96
|
+
poem = response.choices[0].message.content
|
97
|
+
# while within the span, you can attach laminar events to it
|
98
|
+
L.event("event_name", "event_value")
|
99
|
+
|
100
|
+
L.set_span_output(span, poem) # set an output
|
101
|
+
|
102
|
+
# IMPORTANT: don't forget to end all the spans (usually in `finally` blocks)
|
103
|
+
# Otherwise, the trace may not be sent/displayed correctly
|
104
|
+
span.end()
|
105
|
+
|
106
|
+
return poem
|
107
|
+
```
|
108
|
+
|
71
109
|
|
72
110
|
## Sending events
|
73
111
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "lmnr"
|
3
|
-
version = "0.4.
|
3
|
+
version = "0.4.5"
|
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.4.
|
14
|
+
version = "0.4.5"
|
15
15
|
description = "Python SDK for Laminar AI"
|
16
16
|
authors = ["lmnr.ai"]
|
17
17
|
readme = "README.md"
|
@@ -11,7 +11,7 @@ from traceloop.sdk import Traceloop
|
|
11
11
|
from traceloop.sdk.tracing import get_tracer
|
12
12
|
|
13
13
|
from pydantic.alias_generators import to_snake
|
14
|
-
from typing import Any, Optional,
|
14
|
+
from typing import Any, Optional, Union
|
15
15
|
|
16
16
|
import copy
|
17
17
|
import datetime
|
@@ -289,7 +289,7 @@ class Laminar:
|
|
289
289
|
cls,
|
290
290
|
name: str,
|
291
291
|
input: Any = None,
|
292
|
-
) ->
|
292
|
+
) -> Span:
|
293
293
|
"""Start a new span with the given name. Useful for manual
|
294
294
|
instrumentation.
|
295
295
|
|
@@ -304,33 +304,34 @@ class Laminar:
|
|
304
304
|
that must be passed to `end_span` to end the span.
|
305
305
|
|
306
306
|
"""
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
307
|
+
tracer = get_tracer().__enter__()
|
308
|
+
span = tracer.start_span(name)
|
309
|
+
# apparently, detaching from this context is not mandatory.
|
310
|
+
# According to traceloop, and the github issue in opentelemetry,
|
311
|
+
# the context is collected by the garbage collector.
|
312
|
+
# https://github.com/open-telemetry/opentelemetry-python/issues/2606#issuecomment-2106320379
|
313
|
+
context.attach(set_span_in_context(span))
|
314
|
+
|
315
|
+
if input is not None:
|
316
|
+
span.set_attribute(
|
317
|
+
SpanAttributes.TRACELOOP_ENTITY_INPUT, json.dumps({"input": input})
|
318
|
+
)
|
319
|
+
|
320
|
+
return span
|
317
321
|
|
318
322
|
@classmethod
|
319
|
-
def
|
320
|
-
"""
|
323
|
+
def set_span_output(cls, span: Span, output: Any = None):
|
324
|
+
"""Set the output of the span. Useful for manual instrumentation.
|
321
325
|
|
322
326
|
Args:
|
323
|
-
span (Span): span
|
324
|
-
token (object): context token returned by `start_span`
|
327
|
+
span (Span): the span to set the output for
|
325
328
|
output (Any, optional): output of the span. Will be sent as an
|
326
329
|
attribute, so must be json serializable. Defaults to None.
|
327
330
|
"""
|
328
331
|
if output is not None:
|
329
332
|
span.set_attribute(
|
330
|
-
SpanAttributes.TRACELOOP_ENTITY_OUTPUT, json.dumps({
|
333
|
+
SpanAttributes.TRACELOOP_ENTITY_OUTPUT, json.dumps({output})
|
331
334
|
)
|
332
|
-
span.end()
|
333
|
-
context.detach(token)
|
334
335
|
|
335
336
|
@classmethod
|
336
337
|
def set_session(
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|