Skip to main content

Laminar Python

Python SDK for Laminar.

Laminar is an open-source platform for engineering LLM products. Trace, evaluate, annotate, and analyze LLM data. Bring LLM applications to production with confidence.

Check our open-source repo and don't forget to star it ⭐

PyPI - Version PyPI - Downloads PyPI - Python Version

Quickstart

First, install the package, specifying the extras you want to use.

uv add lmnr

To install all possible instrumentations, use the following command:

uv add lmnr --all-extras

Initialize Laminar in your code:

from lmnr import Laminar

Laminar.initialize(project_api_key="<PROJECT_API_KEY>")

You can also skip passing the project_api_key, in which case it will be looked in the environment (or local .env file) by the key LMNR_PROJECT_API_KEY.

Note that you need to only initialize Laminar once in your application. You should try to do that as early as possible in your application, e.g. at server startup.

Set-up for self-hosting

If you self-host a Laminar instance, the default connection settings to it are http://localhost:8000 for HTTP and http://localhost:8001 for gRPC. Initialize the SDK accordingly:

from lmnr import Laminar

Laminar.initialize(
    project_api_key="<PROJECT_API_KEY>",
    base_url="http://localhost",
    http_port=8000,
    grpc_port=8001,
)

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

Laminar.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")
    poem2 = poem_writer(topic="turbulence")
    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 Laminar.start_as_current_span(name="poem_writer", input=topic):
        poem = poem_writer(topic=topic)
        # Use set_span_output to record the output of the span
        Laminar.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, Instruments

Laminar.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().

Autoinstrumentations are provided by Traceloop's OpenLLMetry.

Evaluations

Quickstart

Install the package:

pip install lmnr

Create a file named my_first_eval.py with the following code:

from lmnr import evaluate


def write_poem(data):
    return f"This is a good poem about {data['topic']}"


def contains_poem(output, target):
    return 1 if output in target["poem"] else 0


# Evaluation data
data = [
    {"data": {"topic": "flowers"}, "target": {"poem": "This is a good poem about flowers"}},
    {"data": {"topic": "cars"}, "target": {"poem": "I like cars"}},
]

evaluate(
    data=data,
    executor=write_poem,
    evaluators={"containsPoem": contains_poem},
    group_id="my_first_feature",
)

Run the following commands:

export LMNR_PROJECT_API_KEY=<YOUR_PROJECT_API_KEY>  # get from Laminar project settings
lmnr eval my_first_eval.py  # run in the virtual environment where lmnr is installed

Visit the URL printed in the console to see the results.

Overview

Bring rigor to the development of your LLM applications with evaluations.

You can run evaluations locally by providing executor (part of the logic used in your application) and evaluators (numeric scoring functions) to evaluate function.

evaluate takes in the following parameters:

  • data – an array of EvaluationDatapoint objects, where each EvaluationDatapoint has two keys: target and data, each containing a key-value object. Alternatively, you can pass in dictionaries, and we will instantiate EvaluationDatapoints with pydantic if possible
  • executor – the logic you want to evaluate. This function must take data as the first argument, and produce any output. It can be both a function or an async function.
  • evaluators – Dictionary which maps evaluator names to evaluators. 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 or dict[str, int|float] of scores. Each evaluator can be both a function or an async function.
  • name – optional name for the evaluation. Automatically generated if not provided.
  • group_id – optional group name for the evaluation. Evaluations within the same group can be compared visually side-by-side

* 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.

Read the docs to learn more about evaluations.

Client for HTTP operations

Various interactions with Laminar API are available in LaminarClient and its asynchronous version AsyncLaminarClient.

Metadata

Release files for lmnr 0.8.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lmnr 0.8.6
File Size Uploaded Provenance Actions
lmnr-0.8.6.tar.gz 475.7 kB With provenance Details for lmnr-0.8.6.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for lmnr 0.8.6
File Interpreter ABI Platform Actions
lmnr-0.8.6-py3-none-any.whl Python 3 none any Details for lmnr-0.8.6-py3-none-any.whl

Total release size: 1.1 MB

Release files / lmnr-0.8.6.tar.gz

Download URL lmnr-0.8.6.tar.gz
Size 475.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ffb70c53a9eb3545d66ee8e682f1b950f9b4b056ea82b3e44feabd257090e1dd
BLAKE2b-256 checksum
How to use checksums
14aa16976cda7cccf60aac596f206bb233bfa314e09caee2b55e877afd9fddaf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Release files / lmnr-0.8.6-py3-none-any.whl

Download URL lmnr-0.8.6-py3-none-any.whl
Size 586.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1b0bcae62bad099c079b2e1dbbe16cb77e2912ed6bf894334aea3ca147a0007a
BLAKE2b-256 checksum
How to use checksums
da52104659c2b3489bde5595109f9f2c14ca1955e3d485601cb0bd8ced5dc644
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Security for lmnr 0.8.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for lmnr-0.8.6.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.8.6 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page