LangSmith는 LLM 애플리케이션을 구축하기 위한 인기 오픈소스 프레임워크인 LangChain(Python 및 JavaScript)과 원활하게 통합됩니다.

설치

아래 코드 예시에서 사용하는 OpenAI 통합과 함께, Python 및 JS용 core 라이브러리와 OpenAI 통합을 설치하세요. 사용 가능한 전체 패키지 목록은 LangChain 문서를 참고하세요.
pip install langchain_openai langchain_core

빠른 시작

1. 환경 구성하기

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# This example uses OpenAI, but you can use any LLM provider of choice
export OPENAI_API_KEY=<your-openai-api-key>
# For LangSmith API keys linked to multiple workspaces, set the LANGSMITH_WORKSPACE_ID environment variable to specify which workspace to use.
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>
LangChain.js를 LangSmith와 함께 서버리스 환경이 아닌 곳에서 사용하는 경우, 지연 시간을 줄이기 위해 아래 설정을 명시적으로 지정하는 것을 권장합니다:export LANGCHAIN_CALLBACKS_BACKGROUND=true서버리스 환경에서는 함수가 종료되기 전에 트레이싱이 완료될 수 있도록 반대로 설정하는 것을 권장합니다:export LANGCHAIN_CALLBACKS_BACKGROUND=false

2. 트레이스 기록하기

LangSmith에 트레이스를 기록하기 위해 추가 코드가 필요하지 않습니다. 평소처럼 LangChain 코드를 실행하면 됩니다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
    ("user", "Question: {question}\nContext: {context}")
])

model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()
chain = prompt | model | output_parser

question = "Can you summarize this morning's meetings?"
context = "During this morning's meeting, we solved all world conflict."

chain.invoke({"question": question, "context": context})

3. 트레이스 확인하기

기본적으로 트레이스는 default라는 이름의 프로젝트에 기록됩니다. 위 코드로 기록된 트레이스 예시는 공개되어 있으며 여기에서 확인할 수 있습니다.

선택적으로 트레이스하기

이전 섹션에서는 환경 변수 하나만 설정하여 애플리케이션 내 모든 LangChain runnable 호출을 트레이스하는 방법을 소개했습니다. 이는 시작하기에 편리하지만, 특정 호출이나 애플리케이션의 일부만 트레이스하고 싶을 수도 있습니다. Python에서는 두 가지 방법이 있습니다: callback으로 LangChainTracer 인스턴스를 직접 전달하거나, tracing_context 컨텍스트 매니저를 사용하는 방법입니다. JS/TS에서는 LangChainTracer 인스턴스를 callback으로 전달할 수 있습니다.
# You can opt-in to specific invocations..
import langsmith as ls

with ls.tracing_context(enabled=True):
    chain.invoke({"question": "Am I using a callback?", "context": "I'm using a callback"})

# This will NOT be traced (assuming LANGSMITH_TRACING is not set)
chain.invoke({"question": "Am I being traced?", "context": "I'm not being traced"})

# This would not be traced, even if LANGSMITH_TRACING=true
with ls.tracing_context(enabled=False):
    chain.invoke({"question": "Am I being traced?", "context": "I'm not being traced"})

특정 프로젝트에 기록하기

정적으로

트레이싱 개념 가이드에서 언급한 것처럼, LangSmith는 트레이스를 그룹화하기 위해 Project 개념을 사용합니다. 지정하지 않으면 tracer 프로젝트가 default로 설정됩니다. 전체 애플리케이션 실행에 대해 커스텀 프로젝트 이름을 지정하려면 LANGSMITH_PROJECT 환경 변수를 설정하세요. 이는 애플리케이션 실행 전에 해야 합니다.
export LANGSMITH_PROJECT=my-project
LANGSMITH_PROJECT 플래그는 JS SDK 버전 >= 0.2.16에서만 지원되며, 이전 버전을 사용하는 경우 LANGCHAIN_PROJECT를 사용하세요.

동적으로

이 방법은 이전 섹션을 기반으로 하며, 특정 LangChainTracer 인스턴스나 Python의 tracing_context 컨텍스트 매니저의 파라미터로 프로젝트 이름을 지정할 수 있습니다.
# You can set the project name using the project_name parameter.
import langsmith as ls

with ls.tracing_context(project_name="My Project", enabled=True):
    chain.invoke({"question": "Am I using a context manager?", "context": "I'm using a context manager"})

트레이스에 메타데이터 및 태그 추가하기

RunnableConfig에 메타데이터와 태그를 지정하여 트레이스를 주석 처리할 수 있습니다. 이는 트레이스에 실행 환경이나 실행한 사용자를 비롯한 추가 정보를 연결하는 데 유용합니다. 메타데이터 및 태그로 트레이스와 실행을 쿼리하는 방법은 이 가이드를 참고하세요.
메타데이터나 태그를 runnable에(RunnableConfig 또는 런타임 invocation params로) 지정하면, 해당 runnable의 모든 자식 runnable에도 상속됩니다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful AI."),
    ("user", "{input}")
])

# The tag "model-tag" and metadata {"model-key": "model-value"} will be attached to the ChatOpenAI run only
chat_model = ChatOpenAI().with_config({"tags": ["model-tag"], "metadata": {"model-key": "model-value"}})
output_parser = StrOutputParser()

# Tags and metadata can be configured with RunnableConfig
chain = (prompt | chat_model | output_parser).with_config({"tags": ["config-tag"], "metadata": {"config-key": "config-value"}})

# Tags and metadata can also be passed at runtime
chain.invoke({"input": "What is the meaning of life?"}, {"tags": ["invoke-tag"], "metadata": {"invoke-key": "invoke-value"}})

실행(run) 이름 커스터마이즈하기

LangChain 코드를 호출하거나 스트리밍할 때 Config에 실행 이름을 지정하여 커스터마이즈할 수 있습니다. 이 이름은 LangSmith에서 실행을 식별하고, 필터링 및 그룹화에 사용할 수 있습니다. 또한 LangSmith UI에서 실행의 제목으로 사용됩니다. run_nameRunnableConfig 객체 생성 시 지정하거나 JS/TS에서는 호출 파라미터로 전달하면 됩니다.
# When tracing within LangChain, run names default to the class name of the traced object (e.g., 'ChatOpenAI').
configured_chain = chain.with_config({"run_name": "MyCustomChain"})
configured_chain.invoke({"input": "What is the meaning of life?"})

# You can also configure the run name at invocation time, like below
chain.invoke({"input": "What is the meaning of life?"}, {"run_name": "MyCustomChain"})
run_name 파라미터는 호출하는 runnable(예: 체인, 함수)의 이름만 변경합니다. LLM 객체(ChatOpenAI(gpt-4o-mini) 등)를 호출할 때 자동 생성되는 중첩 실행의 이름은 변경되지 않습니다.LLM 실행에 더 의미 있는 이름을 부여하려면 다음 중 하나를 사용할 수 있습니다:
  • 모델을 다른 runnable로 감싸고 해당 단계에 run_name을 지정합니다.
  • 트레이싱 데코레이터 또는 헬퍼(예: Python의 @traceable, JS/TS의 langsmithtraceable)를 사용하여 모델 호출 주위에 커스텀 실행을 생성합니다.

실행(run) ID 커스터마이즈하기

LangChain 코드를 호출하거나 스트리밍할 때 Config에 실행 ID를 지정하여 커스터마이즈할 수 있습니다. 이 ID는 LangSmith에서 실행을 고유하게 식별하며, 특정 실행을 쿼리하는 데 사용할 수 있습니다. 여러 시스템 간 실행을 연결하거나 커스텀 추적 로직을 구현할 때 유용합니다. run_idRunnableConfig 객체 생성 시 지정하거나 호출 파라미터로 전달하면 됩니다.
이 기능은 현재 LLM 객체에는 직접 지원되지 않습니다.
import uuid

my_uuid = uuid.uuid4()

# You can configure the run ID at invocation time:
chain.invoke({"input": "What is the meaning of life?"}, {"run_id": my_uuid})
트레이스의 루트(즉, 최상위 실행)에서 이 작업을 수행하면 해당 실행 ID가 trace_id로 사용됩니다.

LangChain 호출의 실행(span) ID 접근하기

LangChain 객체를 호출할 때, 호출의 실행 ID를 수동으로 지정할 수 있습니다. 이 실행 ID는 LangSmith에서 실행을 쿼리하는 데 사용할 수 있습니다. JS/TS에서는 RunCollectorCallbackHandler 인스턴스를 사용하여 실행 ID에 접근할 수 있습니다.
import uuid

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
    ("user", "Question: {question}\n\nContext: {context}")
])
model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()

chain = prompt | model | output_parser

question = "Can you summarize this morning's meetings?"
context = "During this morning's meeting, we solved all world conflict."
my_uuid = uuid.uuid4()
result = chain.invoke({"question": question, "context": context}, {"run_id": my_uuid})
print(my_uuid)

종료 전에 모든 트레이스 제출 보장하기

LangChain Python에서는 LangSmith의 트레이싱이 백그라운드 스레드에서 수행되어, 프로덕션 애플리케이션의 흐름을 방해하지 않습니다. 이로 인해 프로세스가 종료되기 전에 모든 트레이스가 LangSmith에 성공적으로 전송되지 않을 수 있습니다. 특히 서버리스 환경에서는 체인이나 에이전트가 완료되면 VM이 즉시 종료될 수 있습니다. 콜백을 동기적으로 만들려면 LANGCHAIN_CALLBACKS_BACKGROUND 환경 변수를 "false"로 설정하세요. 두 언어 모두에서, LangChain은 애플리케이션 종료 전에 트레이스가 제출될 때까지 대기하는 메서드를 제공합니다. 아래는 예시입니다:
from langchain_openai import ChatOpenAI
from langchain_core.tracers.langchain import wait_for_all_tracers

llm = ChatOpenAI()

try:
  llm.invoke("Hello, World!")
finally:
  wait_for_all_tracers()

환경 변수 없이 트레이스하기

다른 가이드에서 언급한 환경 변수들은 트레이싱 활성화, api 엔드포인트, api 키, 트레이싱 프로젝트를 설정할 수 있습니다:
  • LANGSMITH_TRACING
  • LANGSMITH_API_KEY
  • LANGSMITH_ENDPOINT
  • LANGSMITH_PROJECT
하지만 일부 환경에서는 환경 변수를 설정할 수 없습니다. 이런 경우에는 프로그래밍 방식으로 트레이싱 설정을 할 수 있습니다. 이 방법은 이전 섹션을 기반으로 합니다.
import langsmith as ls

# You can create a client instance with an api key and api url
client = ls.Client(
    api_key="YOUR_API_KEY",  # This can be retrieved from a secrets manager
    api_url="https://api.smith.langchain.com",  # Update appropriately for self-hosted installations or the EU region
)

# You can pass the client and project_name to the tracing_context
with ls.tracing_context(client=client, project_name="test-no-env", enabled=True):
    chain.invoke({"question": "Am I using a callback?", "context": "I'm using a callback"})

LangChain(Python)으로 분산 트레이싱

LangSmith는 LangChain Python과 함께 분산 트레이싱을 지원합니다. 이를 통해 서로 다른 서비스와 애플리케이션 간 실행(span)을 연결할 수 있습니다. 원리는 분산 트레이싱 가이드의 LangSmith SDK와 유사합니다.
import langsmith
from langchain_core.runnables import chain
from langsmith.run_helpers import get_current_run_tree

# -- This code should be in a separate file or service --
@chain
def child_chain(inputs):
    return inputs["test"] + 1

def child_wrapper(x, headers):
    with langsmith.tracing_context(parent=headers):
        child_chain.invoke({"test": x})

# -- This code should be in a separate file or service --
@chain
def parent_chain(inputs):
    rt = get_current_run_tree()
    headers = rt.to_headers()
    # ... make a request to another service with the headers
    # The headers should be passed to the other service, eventually to the child_wrapper function

parent_chain.invoke({"test": 1})

LangChain(Python)과 LangSmith SDK 간 상호운용성

애플리케이션의 일부에서 LangChain을, 다른 부분에서 LangSmith SDK(이 가이드 참고)를 사용하는 경우에도 전체 애플리케이션을 원활하게 트레이스할 수 있습니다. LangChain 객체는 traceable 함수 내에서 호출될 때 트레이스되며, 해당 traceable 함수의 자식 실행(run)으로 연결됩니다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langsmith import traceable

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
    ("user", "Question: {question}\nContext: {context}")
])

model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()
chain = prompt | model | output_parser

# The above chain will be traced as a child run of the traceable function
@traceable(
    tags=["openai", "chat"],
    metadata={"foo": "bar"}
)
def invoke_runnnable(question, context):
    result = chain.invoke({"question": question, "context": context})
    return "The response is: " + result

invoke_runnnable("Can you summarize this morning's meetings?", "During this morning's meeting, we solved all world conflict.")
이렇게 하면 다음과 같은 트레이스 트리가 생성됩니다:

LangChain.JS와 LangSmith SDK 간 상호운용성

traceable 내 LangChain 객체 트레이싱(JS 전용)

[email protected]부터, LangChain 객체는 @traceable 함수 내에서 사용할 때 자동으로 트레이스되며, traceable 함수의 클라이언트, 태그, 메타데이터, 프로젝트 이름을 상속받습니다. 0.2.x 이전 버전의 LangChain에서는, @traceable에서 생성된 tracing context로 만든 LangChainTracer 인스턴스를 수동으로 전달해야 합니다.
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { getLangchainCallbacks } from "langsmith/langchain";

const prompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    "You are a helpful assistant. Please respond to the user's request only based on the given context.",
  ],
  ["user", "Question: {question}\nContext: {context}"],
]);

const model = new ChatOpenAI({ modelName: "gpt-4o-mini" });
const outputParser = new StringOutputParser();
const chain = prompt.pipe(model).pipe(outputParser);

const main = traceable(
  async (input: { question: string; context: string }) => {
    const callbacks = await getLangchainCallbacks();
    const response = await chain.invoke(input, { callbacks });
    return response;
  },
  { name: "main" }
);

traceable / RunTree API를 통한 LangChain 자식 실행 트레이싱(JS 전용)

traceable과 LangChain의 상호운용성 개선을 위해 작업 중입니다. LangChain과 traceable을 함께 사용할 때 다음과 같은 제한 사항이 있습니다:
  1. RunnableLambda 컨텍스트의 getCurrentRunTree()로 얻은 RunTree를 변경해도 아무런 효과가 없습니다(no-op).
  2. RunnableLambda에서 얻은 RunTree를 탐색하는 것은 권장하지 않습니다. 모든 RunTree 노드를 포함하지 않을 수 있습니다.
  3. 서로 다른 자식 실행(run)은 동일한 execution_orderchild_execution_order 값을 가질 수 있습니다. 극단적인 경우, 일부 실행이 start_time에 따라 다른 순서로 나타날 수 있습니다.
일부 사용 사례에서는 RunnableSequence의 일부로 traceable 함수를 실행하거나 LangChain 실행의 자식 실행을 RunTree API를 통해 명령형으로 트레이스하고 싶을 수 있습니다. LangSmith 0.1.39 및 @langchain/core 0.2.18부터 RunnableLambda 내에서 traceable로 감싼 함수를 직접 호출할 수 있습니다.
import { traceable } from "langsmith/traceable";
import { RunnableLambda } from "@langchain/core/runnables";
import { RunnableConfig } from "@langchain/core/runnables";

const tracedChild = traceable((input: string) => `Child Run: ${input}`, {
  name: "Child Run",
});

const parrot = new RunnableLambda({
  func: async (input: { text: string }, config?: RunnableConfig) => {
    return await tracedChild(input.text);
  },
});
트레이스 트리 또는 LangChain의 RunnableConfigRunTree.fromRunnableConfig로 동등한 RunTree 객체로 변환하거나, RunnableConfigtraceable로 감싼 함수의 첫 번째 인자로 전달할 수 있습니다.
import { traceable } from "langsmith/traceable";
import { RunnableLambda } from "@langchain/core/runnables";
import { RunnableConfig } from "@langchain/core/runnables";

const tracedChild = traceable((input: string) => `Child Run: ${input}`, {
  name: "Child Run",
});

const parrot = new RunnableLambda({
  func: async (input: { text: string }, config?: RunnableConfig) => {
    // Pass the config to existing traceable function
    await tracedChild(config, input.text);
    return input.text;
  },
});
영상 튜토리얼을 원하신다면, LangSmith 소개 과정의 Alternative Ways to Trace 영상을 참고하세요.
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I