Python SDK for Laminar AI
Project description
Laminar Python
OpenTelemetry log sender for Laminar for Python code.
Quickstart
First, install the package:
python3 -m venv .myenv
source .myenv/bin/activate # or use your favorite env management tool
pip install lmnr
Then, you can initialize Laminar in your main file and instrument your code.
import os
from openai import OpenAI
from lmnr import Laminar as L
L.initialize(
project_api_key=os.environ["LMNR_PROJECT_API_KEY"],
)
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def poem_writer(topic: str):
prompt = f"write a poem about {topic}"
# OpenAI calls are automatically instrumented
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt},
],
)
poem = response.choices[0].message.content
return poem
if __name__ == "__main__":
print(poem_writer("laminar flow"))
Note that you need to only initialize Laminar once in your application.
Project API key
Get the key from the settings page of your Laminar project (Learn more).
You can either pass it to .initialize()
or set it to .env
at the root of your package with the key LMNR_PROJECT_API_KEY
.
Instrumentation
Manual instrumentation
To instrument any function in your code, we provide a simple @observe()
decorator.
This can be useful if you want to trace a request handler or a function which combines multiple LLM calls.
import os
from openai import OpenAI
from lmnr import Laminar as L, Instruments
L.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def poem_writer(topic: str):
prompt = f"write a poem about {topic}"
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt},
]
# OpenAI calls are still automatically instrumented
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
)
poem = response.choices[0].message.content
return poem
@observe()
def generate_poems():
poem1 = poem_writer(topic="laminar flow")
L.event("is_poem_generated", True)
poem2 = poem_writer(topic="turbulence")
L.event("is_poem_generated", True)
poems = f"{poem1}\n\n---\n\n{poem2}"
return poems
Also, you can use Laminar.start_as_current_span
if you want to record a chunk of your code using with
statement.
def handle_user_request(topic: str):
with L.start_as_current_span(name="poem_writer", input=topic):
...
poem = poem_writer(topic=topic)
...
# while within the span, you can attach laminar events to it
L.event("is_poem_generated", True)
# Use set_span_output to record the output of the span
L.set_span_output(poem)
Automatic instrumentation
Laminar allows you to automatically instrument majority of the most popular LLM, Vector DB, database, requests, and other libraries.
If you want to automatically instrument a default set of libraries, then simply do NOT pass instruments
argument to .initialize()
.
See the full list of available instrumentations in the enum.
If you want to automatically instrument only specific LLM, Vector DB, or other
calls with OpenTelemetry-compatible instrumentation, then pass the appropriate instruments to .initialize()
.
For example, if you want to only instrument OpenAI and Anthropic, then do the following:
from lmnr import Laminar as L, Instruments
L.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"], instruments={Instruments.OPENAI, Instruments.ANTHROPIC})
If you want to fully disable any kind of autoinstrumentation, pass an empty set as instruments=set()
to .initialize()
.
Majority of the autoinstrumentations are provided by Traceloop's OpenLLMetry.
Sending events
You can send events in two ways:
.event(name, value)
– for a pre-defined event with one of possible values..evaluate_event(name, evaluator, data)
– for an event that is evaluated by evaluator pipeline based on the data.
Note that to run an evaluate event, you need to crate an evaluator pipeline and create a target version for it.
Read our docs to learn more about event types and how they are created and evaluated.
Example
from lmnr import Laminar as L
# ...
poem = response.choices[0].message.content
# this will register True or False value with Laminar
L.event("topic alignment", topic in poem)
# this will run the pipeline `check_wordy` with `poem` set as the value
# of `text_input` node, and write the result as an event with name
# "excessive_wordiness"
L.evaluate_event("excessive_wordiness", "check_wordy", {"text_input": poem})
Laminar pipelines as prompt chain managers
You can create Laminar pipelines in the UI and manage chains of LLM calls there.
After you are ready to use your pipeline in your code, deploy it in Laminar by selecting the target version for the pipeline.
Once your pipeline target is set, you can call it from Python in just a few lines.
Example use:
from lmnr import Laminar as L
L.initialize('<YOUR_PROJECT_API_KEY>', instruments=set())
result = l.run(
pipeline = 'my_pipeline_name',
inputs = {'input_node_name': 'some_value'},
# all environment variables
env = {'OPENAI_API_KEY': 'sk-some-key'},
)
Resulting in:
>>> result
PipelineRunResponse(
outputs={'output': {'value': [ChatMessage(role='user', content='hello')]}},
# useful to locate your trace
run_id='53b012d5-5759-48a6-a9c5-0011610e3669'
)
Running offline evaluations on your data
You can evaluate your code with your own data and send it to Laminar using the Evaluation
class.
Evaluation takes in the following parameters:
name
– the name of your evaluation. If no such evaluation exists in the project, it will be created. Otherwise, data will be pushed to the existing evaluationdata
– an array ofEvaluationDatapoint
objects, where eachEvaluationDatapoint
has two keys:target
anddata
, each containing a key-value object. Alternatively, you can pass in dictionaries, and we will instantiateEvaluationDatapoint
s with pydantic if possibleexecutor
– the logic you want to evaluate. This function must takedata
as the first argument, and produce any output. *evaluators
– evaluaton logic. List of functions that take output of executor as the first argument,target
as the second argument and produce a numeric scores. Each function can produce either a single number ordict[str, int|float]
of scores.
* If you already have the outputs of executors you want to evaluate, you can specify the executor as an identity function, that takes in data
and returns only needed value(s) from it.
Example
from openai import AsyncOpenAI
import asyncio
import os
openai_client = AsyncOpenAI(api_key=os.environ["OPENAI_API_KEY"])
async def get_capital(data):
country = data["country"]
response = await openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": f"What is the capital of {country}? Just name the "
"city and nothing else",
},
],
)
return response.choices[0].message.content.strip()
# Evaluation data
data = [
{"data": {"country": "Canada"}, "target": {"capital": "Ottawa"}},
{"data": {"country": "Germany"}, "target": {"capital": "Berlin"}},
{"data": {"country": "Tanzania"}, "target": {"capital": "Dodoma"}},
]
def evaluator_A(output, target):
return 1 if output == target["capital"] else 0
# Create an Evaluation instance
e = Evaluation(
name="py-evaluation-async",
data=data,
executor=get_capital,
evaluators=[evaluator_A],
project_api_key=os.environ["LMNR_PROJECT_API_KEY"],
)
# Run the evaluation
asyncio.run(e.run())
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file lmnr-0.4.12b2.tar.gz
.
File metadata
- Download URL: lmnr-0.4.12b2.tar.gz
- Upload date:
- Size: 49.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.7 Darwin/23.0.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2990fdf3dbc8aa72fe6e37bfa5c89f9edc80eee4d3ebe1a342386018db3d1516 |
|
MD5 | fa7c88ad3d7d1c3ec11421ee8d54e500 |
|
BLAKE2b-256 | 659dc56d1fae3a3d2d4e9e65d87f8bb810c6a8e62fce785b53b7e6ee7ea224a7 |
File details
Details for the file lmnr-0.4.12b2-py3-none-any.whl
.
File metadata
- Download URL: lmnr-0.4.12b2-py3-none-any.whl
- Upload date:
- Size: 67.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.7 Darwin/23.0.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2d3b56cb2a54611bf93da3dd3fd9916bd0403c8fd64c9762366628229b0e8bb9 |
|
MD5 | f69344341d275330c824bb592b8683f9 |
|
BLAKE2b-256 | 2da051b99dbbae17634bbce0b0b0da46cbe82605e8d3e2e2bd1e7b6faa21e118 |