Skip to main content

Client library to connect to the LangSmith Observability and Evaluation Platform.

Project description

LangSmith Client SDK

Release Notes Python Downloads

This package contains the Python client for interacting with the LangSmith platform.

To install:

pip install -U langsmith
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=ls_...

Then trace:

import openai
from langsmith.wrappers import wrap_openai
from langsmith import traceable

# Auto-trace LLM calls in-context
client = wrap_openai(openai.Client())

@traceable # Auto-trace this function
def pipeline(user_input: str):
    result = client.chat.completions.create(
        messages=[{"role": "user", "content": user_input}],
        model="gpt-3.5-turbo"
    )
    return result.choices[0].message.content

pipeline("Hello, world!")

See the resulting nested trace 🌐 here.

LangSmith helps you and your team develop and evaluate language models and intelligent agents. It is compatible with any LLM application.

Cookbook: For tutorials on how to get more value out of LangSmith, check out the Langsmith Cookbook repo.

A typical workflow looks like:

  1. Set up an account with LangSmith.
  2. Log traces while debugging and prototyping.
  3. Run benchmark evaluations and continuously improve with the collected data.

We'll walk through these steps in more detail below.

Sandbox AWS Auth Proxy

When sandbox code needs to call AWS services, use the sandbox AWS auth proxy. The proxy keeps the real AWS credentials outside the sandbox and signs supported AWS HTTPS requests with SigV4, so code in the sandbox can use AWS SDKs normally without storing long-lived AWS keys in files, environment variables, shell history, or logs.

Store AWS credentials as LangSmith workspace secrets using names that make sense for your workspace. Then create the sandbox with an AWS auth proxy config:

from langsmith.sandbox import (
    SandboxClient,
    aws_auth,
    proxy_config,
    workspace_secret,
)

client = SandboxClient()
auth_config = proxy_config(
    rules=[
        aws_auth(
            access_key_id=workspace_secret("SANDBOX_AWS_ACCESS_KEY_ID"),
            secret_access_key=workspace_secret("SANDBOX_AWS_SECRET_ACCESS_KEY"),
        )
    ],
)

with client.sandbox(
    name="aws-sandbox",
    proxy_config=auth_config,
) as sandbox:
    result = sandbox.run("python your_aws_script.py")
    print(result.stdout)

Use opaque_secret("...") instead of workspace_secret(...) when your application needs to pass short-lived write-only AWS credentials at sandbox creation time. Plaintext AWS credential values are not accepted directly; wrap them as opaque_secret(...) values.

Sandbox GCP Auth Proxy

When sandbox code needs to call Google APIs, use the sandbox GCP auth proxy. The proxy keeps the service account JSON outside the sandbox and injects OAuth bearer tokens for Google API hosts matched automatically by the sandbox proxy.

Store the service account JSON as a LangSmith workspace secret. Then create the sandbox with a GCP auth proxy config:

from langsmith.sandbox import (
    SandboxClient,
    gcp_auth,
    proxy_config,
    workspace_secret,
)

client = SandboxClient()
auth_config = proxy_config(
    rules=[
        gcp_auth(
            service_account_json=workspace_secret(
                "SANDBOX_GCP_SERVICE_ACCOUNT_JSON"
            ),
            scopes=["https://www.googleapis.com/auth/devstorage.read_write"],
        )
    ],
)

with client.sandbox(
    name="gcp-sandbox",
    proxy_config=auth_config,
) as sandbox:
    result = sandbox.run("python your_gcp_script.py")
    print(result.stdout)

Use opaque_secret("...") for short-lived write-only service account JSON. Plaintext service account JSON is not accepted directly.

Sandbox Mounts

When you create a LangSmith sandbox that needs filesystem access to external data such as object storage buckets or public Git repositories, pass a mount_config on sandbox creation. Mount specs contain only the mount target. Provider credentials stay in explicit auth config, and the SDK expands mount_config into the backend mounts and proxy_config fields. If you also pass proxy_config, its rules are merged with the mount-generated proxy auth rules. Provider auth for the same provider must appear in only one place.

S3 mounts require an enabled AWS auth proxy rule:

from langsmith.sandbox import (
    aws_auth,
    mount_config,
    s3_mount,
    workspace_secret,
)

mount_cfg = mount_config(
    auth=[
        aws_auth(
            access_key_id=workspace_secret("SANDBOX_AWS_ACCESS_KEY_ID"),
            secret_access_key=workspace_secret("SANDBOX_AWS_SECRET_ACCESS_KEY"),
        )
    ],
    mounts=[
        s3_mount(
            id="customer_data",
            mount_path="/mnt/mounts/customer-data",
            bucket="example-bucket",
            prefix="datasets/customer-data",
            region="us-east-1",
            endpoint_url="https://s3.amazonaws.com",
            path_style=False,
            read_only=False,
        )
    ],
)

with client.sandbox(
    name="s3-mount-sandbox",
    mount_config=mount_cfg,
) as sandbox:
    result = sandbox.run("ls /mnt/mounts/customer-data")
    print(result.stdout)

GCS mounts require an enabled GCP auth proxy rule with a compatible storage OAuth scope. Read/write mounts require devstorage.read_write or cloud-platform; read-only mounts can also use devstorage.read_only.

from langsmith.sandbox import (
    gcp_auth,
    gcs_mount,
    mount_config,
    workspace_secret,
)

mount_cfg = mount_config(
    auth=[
        gcp_auth(
            service_account_json=workspace_secret(
                "SANDBOX_GCP_SERVICE_ACCOUNT_JSON"
            ),
            scopes=["https://www.googleapis.com/auth/devstorage.read_write"],
        )
    ],
    mounts=[
        gcs_mount(
            id="customer_data",
            mount_path="/mnt/mounts/customer-data",
            bucket="example-bucket",
            prefix="datasets/customer-data",
        )
    ],
)

with client.sandbox(
    name="gcs-mount-sandbox",
    mount_config=mount_cfg,
) as sandbox:
    result = sandbox.run("ls /mnt/mounts/customer-data")
    print(result.stdout)

Public Git mounts do not require AWS or GCP auth:

from langsmith.sandbox import git_mount, mount_config

mount_cfg = mount_config(
    mounts=[
        git_mount(
            id="repo",
            mount_path="/mnt/repo",
            remote_url="https://github.com/langchain-ai/langsmith-sdk.git",
            ref={"type": "branch", "name": "main"},
            refresh_interval_seconds=60,
        )
    ],
)

with client.sandbox(
    name="git-mount-sandbox",
    mount_config=mount_cfg,
) as sandbox:
    result = sandbox.run("ls /mnt/repo")
    print(result.stdout)

Private Git repositories can use low-level proxy_config rules when the remote requires proxy-managed auth. There is not yet a high-level private Git auth helper.

1. Connect to LangSmith

Sign up for LangSmith using your GitHub, Discord accounts, or an email address and password. If you sign up with an email, make sure to verify your email address before logging in.

Then, create a unique API key on the Settings Page, which is found in the menu at the top right corner of the page.

[!NOTE] Save the API Key in a secure location. It will not be shown again.

2. Log Traces

You can log traces natively using the LangSmith SDK or within your LangChain application.

Logging Traces with LangChain

LangSmith seamlessly integrates with the Python LangChain library to record traces from your LLM applications.

  1. Copy the environment variables from the Settings Page and add them to your application.

Tracing can be activated by setting the following environment variables or by manually specifying the LangChainTracer.

import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_ENDPOINT"] = "https://api.smith.langchain.com"
# os.environ["LANGSMITH_ENDPOINT"] = "https://eu.api.smith.langchain.com" # If signed up in the EU region
os.environ["LANGSMITH_API_KEY"] = "<YOUR-LANGSMITH-API-KEY>"
# os.environ["LANGSMITH_PROJECT"] = "My Project Name" # Optional: "default" is used if not set
# os.environ["LANGSMITH_WORKSPACE_ID"] = "<YOUR-WORKSPACE-ID>" # Required for org-scoped API keys

Tip: Projects are groups of traces. All runs are logged to a project. If not specified, the project is set to default.

  1. Run an Agent, Chain, or Language Model in LangChain

If the environment variables are correctly set, your application will automatically connect to the LangSmith platform.

from langchain_core.runnables import chain

@chain
def add_val(x: dict) -> dict:
    return {"val": x["val"] + 1}

add_val({"val": 1})

Logging Traces Outside LangChain

You can still use the LangSmith development platform without depending on any LangChain code.

  1. Copy the environment variables from the Settings Page and add them to your application.
import os
os.environ["LANGSMITH_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGSMITH_API_KEY"] = "<YOUR-LANGSMITH-API-KEY>"
# os.environ["LANGSMITH_PROJECT"] = "My Project Name" # Optional: "default" is used if not set
  1. Log traces

The easiest way to log traces using the SDK is via the @traceable decorator. Below is an example.

from datetime import datetime
from typing import List, Optional, Tuple

import openai
from langsmith import traceable
from langsmith.wrappers import wrap_openai

client = wrap_openai(openai.Client())

@traceable
def argument_generator(query: str, additional_description: str = "") -> str:
    return client.chat.completions.create(
        [
            {"role": "system", "content": "You are a debater making an argument on a topic."
             f"{additional_description}"
             f" The current time is {datetime.now()}"},
            {"role": "user", "content": f"The discussion topic is {query}"}
        ]
    ).choices[0].message.content



@traceable
def argument_chain(query: str, additional_description: str = "") -> str:
    argument = argument_generator(query, additional_description)
    # ... Do other processing or call other functions...
    return argument

argument_chain("Why is blue better than orange?")

Alternatively, you can manually log events using the Client directly or using a RunTree, which is what the traceable decorator is meant to manage for you!

A RunTree tracks your application. Each RunTree object is required to have a name and run_type. These and other important attributes are as follows:

  • name: str - used to identify the component's purpose
  • run_type: str - Currently one of "llm", "chain" or "tool"; more options will be added in the future
  • inputs: dict - the inputs to the component
  • outputs: Optional[dict] - the (optional) returned values from the component
  • error: Optional[str] - Any error messages that may have arisen during the call
from langsmith.run_trees import RunTree

parent_run = RunTree(
    name="My Chat Bot",
    run_type="chain",
    inputs={"text": "Summarize this morning's meetings."},
    # project_name= "Defaults to the LANGSMITH_PROJECT env var"
)
parent_run.post()
# .. My Chat Bot calls an LLM
child_llm_run = parent_run.create_child(
    name="My Proprietary LLM",
    run_type="llm",
    inputs={
        "prompts": [
            "You are an AI Assistant. The time is XYZ."
            " Summarize this morning's meetings."
        ]
    },
)
child_llm_run.post()
child_llm_run.end(
    outputs={
        "generations": [
            "I should use the transcript_loader tool"
            " to fetch meeting_transcripts from XYZ"
        ]
    }
)
child_llm_run.patch()
# ..  My Chat Bot takes the LLM output and calls
# a tool / function for fetching transcripts ..
child_tool_run = parent_run.create_child(
    name="transcript_loader",
    run_type="tool",
    inputs={"date": "XYZ", "content_type": "meeting_transcripts"},
)
child_tool_run.post()
# The tool returns meeting notes to the chat bot
child_tool_run.end(outputs={"meetings": ["Meeting1 notes.."]})
child_tool_run.patch()

child_chain_run = parent_run.create_child(
    name="Unreliable Component",
    run_type="tool",
    inputs={"input": "Summarize these notes..."},
)
child_chain_run.post()

try:
    # .... the component does work
    raise ValueError("Something went wrong")
    child_chain_run.end(outputs={"output": "foo"}
    child_chain_run.patch()
except Exception as e:
    child_chain_run.end(error=f"I errored again {e}")
    child_chain_run.patch()
    pass
# .. The chat agent recovers

parent_run.end(outputs={"output": ["The meeting notes are as follows:..."]})
res = parent_run.patch()
res.result()

Create a Dataset from Existing Runs

Once your runs are stored in LangSmith, you can convert them into a dataset. For this example, we will do so using the Client, but you can also do this using the web interface, as explained in the LangSmith docs.

from langsmith import Client

client = Client()
dataset_name = "Example Dataset"
# We will only use examples from the top level AgentExecutor run here,
# and exclude runs that errored.
runs = client.list_runs(
    project_name="my_project",
    execution_order=1,
    error=False,
)

dataset = client.create_dataset(dataset_name, description="An example dataset")
for run in runs:
    client.create_example(
        inputs=run.inputs,
        outputs=run.outputs,
        dataset_id=dataset.id,
    )

Evaluating Runs

Check out the LangSmith Testing & Evaluation dos for up-to-date workflows.

For generating automated feedback on individual runs, you can run evaluations directly using the LangSmith client.

from typing import Optional
from langsmith.evaluation import StringEvaluator


def jaccard_chars(output: str, answer: str) -> float:
    """Naive Jaccard similarity between two strings."""
    prediction_chars = set(output.strip().lower())
    answer_chars = set(answer.strip().lower())
    intersection = prediction_chars.intersection(answer_chars)
    union = prediction_chars.union(answer_chars)
    return len(intersection) / len(union)


def grader(run_input: str, run_output: str, answer: Optional[str]) -> dict:
    """Compute the score and/or label for this run."""
    if answer is None:
        value = "AMBIGUOUS"
        score = 0.5
    else:
        score = jaccard_chars(run_output, answer)
        value = "CORRECT" if score > 0.9 else "INCORRECT"
    return dict(score=score, value=value)

evaluator = StringEvaluator(evaluation_name="Jaccard", grading_function=grader)

runs = client.list_runs(
    project_name="my_project",
    execution_order=1,
    error=False,
)
for run in runs:
    client.evaluate_run(run, evaluator)

Integrations

LangSmith easily integrates with your favorite LLM framework.

OpenAI SDK

We provide a convenient wrapper for the OpenAI SDK.

In order to use, you first need to set your LangSmith API key.

export LANGSMITH_API_KEY=<your-api-key>

Next, you will need to install the LangSmith SDK:

pip install -U langsmith

After that, you can wrap the OpenAI client:

from openai import OpenAI
from langsmith import wrappers

client = wrappers.wrap_openai(OpenAI())

Now, you can use the OpenAI client as you normally would, but now everything is logged to LangSmith!

client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Say this is a test"}],
)

Oftentimes, you use the OpenAI client inside of other functions. You can get nested traces by using this wrapped client and decorating those functions with @traceable. See this documentation for more documentation how to use this decorator

from langsmith import traceable

@traceable(name="Call OpenAI")
def my_function(text: str):
    return client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": f"Say {text}"}],
    )

my_function("hello world")

Instructor

We provide a convenient integration with Instructor, largely by virtue of it essentially just using the OpenAI SDK.

In order to use, you first need to set your LangSmith API key.

export LANGSMITH_API_KEY=<your-api-key>

Next, you will need to install the LangSmith SDK:

pip install -U langsmith

After that, you can wrap the OpenAI client:

from openai import OpenAI
from langsmith import wrappers

client = wrappers.wrap_openai(OpenAI())

After this, you can patch the OpenAI client using instructor:

import instructor

client = instructor.patch(OpenAI())

Now, you can use instructor as you normally would, but now everything is logged to LangSmith!

from pydantic import BaseModel


class UserDetail(BaseModel):
    name: str
    age: int


user = client.chat.completions.create(
    model="gpt-3.5-turbo",
    response_model=UserDetail,
    messages=[
        {"role": "user", "content": "Extract Jason is 25 years old"},
    ]
)

Oftentimes, you use instructor inside of other functions. You can get nested traces by using this wrapped client and decorating those functions with @traceable. See this documentation for more documentation how to use this decorator

@traceable()
def my_function(text: str) -> UserDetail:
    return client.chat.completions.create(
        model="gpt-3.5-turbo",
        response_model=UserDetail,
        messages=[
            {"role": "user", "content": f"Extract {text}"},
        ]
    )


my_function("Jason is 25 years old")

Pytest Plugin

The LangSmith pytest plugin lets Python developers define their datasets and evaluations as pytest test cases. See online docs for more information.

This plugin is installed as part of the LangSmith SDK, and is enabled by default. See also official pytest docs: How to install and use plugins

Additional Documentation

To learn more about the LangSmith platform, check out the docs.

License

The LangSmith SDK is licensed under the MIT License.

The copyright information for certain dependencies' are reproduced in their corresponding COPYRIGHT.txt files in this repo, including the following:

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

langsmith-0.8.17.tar.gz (4.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langsmith-0.8.17-py3-none-any.whl (507.8 kB view details)

Uploaded Python 3

File details

Details for the file langsmith-0.8.17.tar.gz.

File metadata

  • Download URL: langsmith-0.8.17.tar.gz
  • Upload date:
  • Size: 4.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for langsmith-0.8.17.tar.gz
Algorithm Hash digest
SHA256 dfedd6a2558cf8e420fdf8b9ee735537f02d97c329197c9499a5c7ecbe0f18fb
MD5 95399f42ac84a104f77b81985f9af87c
BLAKE2b-256 adaa30295e5b27b86a607aaa21390cb1e10c84203916fdcf953ba0ff94a1dfaa

See more details on using hashes here.

Provenance

The following attestation bundles were made for langsmith-0.8.17.tar.gz:

Publisher: release.yml on langchain-ai/langsmith-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langsmith-0.8.17-py3-none-any.whl.

File metadata

  • Download URL: langsmith-0.8.17-py3-none-any.whl
  • Upload date:
  • Size: 507.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for langsmith-0.8.17-py3-none-any.whl
Algorithm Hash digest
SHA256 62796120a46781a8c717b3d2e846e94343334b57bd504cc10b61a5d2e4739c5a
MD5 7474b35b2420954f9936ec3c72bab7d5
BLAKE2b-256 09043dddd1e331e000f942b174a7bf3382422dc2a8414ef8786efb2e9f9f5d6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for langsmith-0.8.17-py3-none-any.whl:

Publisher: release.yml on langchain-ai/langsmith-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page