커스텀 계측

커스텀 계측 (Custom instrumentation)

코드에 계측을 직접 추가하면 애플리케이션이 어떤 함수를 트레이싱하는지, 어떤 입력/출력이 기록되는지, 트레이스 계층이 어떻게 구성되는지 정밀하게 제어할 수 있어요. 세 가지 핵심 계측 접근 방식이 있습니다.

출처: 문서

본문

코드에 계측을 직접 추가하면 애플리케이션이 어떤 함수를 트레이싱하는지, 어떤 입력과 출력이 기록되는지, 트레이스 계층이 어떻게 구성되는지 정밀하게 제어할 수 있습니다. 세 가지 핵심 계측 접근 방식:

이 페이지는 또한 다음을 다룹니다:

LangChain(Python 또는 JS/TS)은 LangChain 특화 지침을 참고하세요.

플러그: 내장 LangSmith 통합이 있는 LLM 제공자 또는 에이전트 프레임워크를 사용한다면 통합 개요를 참고하세요.

사전 준비 사항

트레이싱 전에 다음 환경 변수를 설정하세요:

  • LANGSMITH_TRACING=true: 트레이싱 활성화. 코드를 변경하지 않고 트레이싱을 켜고 끄려면 이를 설정하세요.

    참고: LANGSMITH_TRACING@traceable 데코레이터와 trace 컨텍스트 매니저를 제어합니다. 환경 변수를 변경하지 않고 @traceable에 대해 런타임에 이를 재정의하려면 tracing_context(enabled=True/False)(Python) 사용하거나 traceabletracingEnabled를 직접 전달(JS/TS)하세요. RunTree 객체는 이러한 제어의 영향을 받지 않습니다. 게시되면 항상 LangSmith로 데이터를 보냅니다.

  • LANGSMITH_API_KEY: LangSmith API 키.

  • 기본적으로 LangSmith는 default라는 프로젝트에 트레이스를 기록합니다. 다른 프로젝트에 기록하려면 LANGSMITH_PROJECT를 설정하세요. 자세한 내용은 특정 프로젝트에 트레이스 기록을 참고하세요.

@traceable / traceable 사용

@traceable(Python), traceable(TypeScript), traceable(Kotlin) 또는 Tracing.traceFunction(Java)을 어떤 함수에 적용해 추적된 런으로 만듭니다. LangSmith는 중첩 호출 간 컨텍스트 전파를 자동으로 처리합니다.

다음 예시는 간단한 파이프라인을 트레이싱합니다: run_pipelineformat_prompt를 호출해 메시지를 만들고, invoke_llm으로 모델을 호출하고, parse_output으로 결과를 추출합니다.

각 함수는 개별적으로 추적되며, (역시 추적되는) run_pipeline 안에서 호출되므로 LangSmith는 이를 자식 런으로 자동 중첩합니다. invoke_llmrun_type="llm"을 사용해 LLM 호출로 표시, LangSmith가 토큰 수와 지연 시간을 올바르게 렌더링할 수 있게 합니다:

from langsmith import traceable
from openai import Client

openai = Client()

@traceable
def format_prompt(subject):
  return [
      {
          "role": "system",
          "content": "You are a helpful assistant.",
      },
      {
          "role": "user",
          "content": f"What's a good name for a store that sells {subject}?"
      }
  ]

@traceable(run_type="llm")
def invoke_llm(messages):
  return openai.chat.completions.create(
      messages=messages, model="gpt-5.4-mini", temperature=0
  )

@traceable
def parse_output(response):
  return response.choices[0].message.content

@traceable
def run_pipeline():
  messages = format_prompt("colorful socks")
  response = invoke_llm(messages)
  return parse_output(response)

run_pipeline()
import { traceable } from "langsmith/traceable";
import OpenAI from "openai";

const openai = new OpenAI();

const formatPrompt = traceable((subject: string) => {
  return [
    {
      role: "system" as const,
      content: "You are a helpful assistant.",
    },
    {
      role: "user" as const,
      content: `What's a good name for a store that sells ${subject}?`,
    },
  ];
},{ name: "formatPrompt" });

const invokeLLM = traceable(
  async ({ messages }: { messages: { role: string; content: string }[] }) => {
      return openai.chat.completions.create({
          model: "gpt-5.4-mini",
          messages: messages,
          temperature: 0,
      });
  },
  { run_type: "llm", name: "invokeLLM" }
);

const parseOutput = traceable(
  (response: any) => {
      return response.choices[0].message.content;
  },
  { name: "parseOutput" }
);

const runPipeline = traceable(
  async () => {
      const messages = await formatPrompt("colorful socks");
      const response = await invokeLLM({ messages });
      return parseOutput(response);
  },
  { name: "runPipeline" }
);

await runPipeline();
import com.langchain.smith.tracing.RunType;
import com.langchain.smith.tracing.TraceConfig;
import com.langchain.smith.tracing.Tracing;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import com.openai.models.chat.completions.ChatCompletionMessageParam;
import com.openai.models.chat.completions.ChatCompletionSystemMessageParam;
import com.openai.models.chat.completions.ChatCompletionUserMessageParam;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class TraceablePipeline {
  public static void main(String[] args) {
    new TraceablePipelineRunner().run();
  }

  private static final class TraceablePipelineRunner {
    private final OpenAIClient openai = OpenAIOkHttpClient.fromEnv();

    private final Function<String, List<ChatCompletionMessageParam>> formatPrompt =
        Tracing.traceFunction(
            subject ->
                Arrays.asList(
                    ChatCompletionMessageParam.ofSystem(
                        ChatCompletionSystemMessageParam.builder()
                            .content("You are a helpful assistant.")
                            .build()),
                    ChatCompletionMessageParam.ofUser(
                        ChatCompletionUserMessageParam.builder()
                            .content("What's a good name for a store that sells " + subject + "?")
                            .build())),
            TraceConfig.builder().name("format_prompt").build());

    private final Function<List<ChatCompletionMessageParam>, ChatCompletion> invokeLlm =
        Tracing.traceFunction(
            messages ->
                openai.chat()
                    .completions()
                    .create(
                        ChatCompletionCreateParams.builder()
                            .model(ChatModel.GPT_5_5)
                            .messages(messages)
                            .build()),
            TraceConfig.builder().name("invoke_llm").runType(RunType.LLM).build());

    private final Function<ChatCompletion, String> parseOutput =
        Tracing.traceFunction(
            response -> response.choices().get(0).message().content().orElse(""),
            TraceConfig.builder().name("parse_output").build());

    private final Function<String, String> runPipeline =
        Tracing.traceFunction(
            subject -> parseOutput.apply(invokeLlm.apply(formatPrompt.apply(subject))),
            TraceConfig.builder().name("run_pipeline").build());

    void run() {
      runPipeline.apply("colorful socks");
    }
  }
}

View example trace — 이 예시에 대한 공개 LangSmith 런을 엽니다.

import com.langchain.smith.tracing.RunType
import com.langchain.smith.tracing.TraceConfig
import com.langchain.smith.tracing.traceable
import com.openai.client.okhttp.OpenAIOkHttpClient
import com.openai.models.ChatModel
import com.openai.models.chat.completions.ChatCompletion
import com.openai.models.chat.completions.ChatCompletionCreateParams
import com.openai.models.chat.completions.ChatCompletionMessageParam
import com.openai.models.chat.completions.ChatCompletionSystemMessageParam
import com.openai.models.chat.completions.ChatCompletionUserMessageParam
import kotlin.jvm.optionals.getOrNull

val openai = OpenAIOkHttpClient.fromEnv()

val formatPrompt =
    traceable(
        { subject: String ->
            listOf(
                ChatCompletionMessageParam.ofSystem(
                    ChatCompletionSystemMessageParam.builder()
                        .content("You are a helpful assistant.")
                        .build(),
                ),
                ChatCompletionMessageParam.ofUser(
                    ChatCompletionUserMessageParam.builder()
                        .content("What's a good name for a store that sells $subject?")
                        .build(),
                ),
            )
        },
        TraceConfig.builder().name("format_prompt").build(),
    )

val invokeLlm =
    traceable(
        { messages: List<ChatCompletionMessageParam> ->
            openai.chat().completions().create(
                ChatCompletionCreateParams.builder()
                    .model(ChatModel.GPT_5_5)
                    .messages(messages)
                    .build(),
            )
        },
        TraceConfig.builder().name("invoke_llm").runType(RunType.LLM).build(),
    )

val parseOutput =
    traceable(
        { response: ChatCompletion ->
            response.choices()[0].message().content().getOrNull().orEmpty()
        },
        TraceConfig.builder().name("parse_output").build(),
    )

val runPipeline =
    traceable(
        { subject: String -> parseOutput(invokeLlm(formatPrompt(subject))) },
        TraceConfig.builder().name("run_pipeline").build(),
    )

println(runPipeline("colorful socks"))

View example trace — 이 예시에 대한 공개 LangSmith 런을 엽니다.

UI에서 format_prompt, invoke_llm, parse_output가 중첩 자식 런으로 있는 run_pipeline 트레이스를 확인할 수 있습니다.

참고: traceable로 동기 함수를 감쌀 때(예: 위 예시의 formatPrompt) 호출할 때 await 키워드를 사용해 트레이스가 올바르게 기록되도록 하세요.

trace 컨텍스트 매니저 사용 (Python 전용)

Python에서는 trace 컨텍스트 매니저를 사용해 트레이스를 LangSmith로 기록할 수 있습니다. 다음과 같은 상황에서 유용합니다:

  1. 특정 코드 블록에 대한 트레이스를 기록하고 싶을 때.
  2. 트레이스의 입력, 출력 및 기타 속성을 제어하고 싶을 때.
  3. 데코레이터나 래퍼를 사용하는 것이 불가능할 때.
  4. 위 중 어느 하나 또는 전부.

컨텍스트 매니저는 traceable 데코레이터와 wrap_openai 래퍼와 원활하게 통합되므로, 같은 애플리케이션에서 함께 사용할 수 있습니다.

다음 예시는 세 가지를 모두 함께 사용하는 것을 보여줍니다. wrap_openai는 OpenAI 클라이언트를 감싸 그 호출이 자동으로 추적되게 합니다. my_toolrun_type="tool"과 커스텀 name으로 @traceable을 사용해 트레이스에 올바르게 나타나게 합니다. chat_pipeline 자체는 데코레이트되지 않습니다. 대신 ls.trace가 호출을 감싸, 프로젝트 이름과 입력을 명시적으로 전달하고 rt.end()로 출력을 수동으로 설정할 수 있게 합니다:

import openai
import langsmith as ls
from langsmith.wrappers import wrap_openai

client = wrap_openai(openai.Client())

@ls.traceable(run_type="tool", name="Retrieve Context")
def my_tool(question: str) -> str:
    return "During this morning's meeting, we solved all world conflict."

def chat_pipeline(question: str):
    context = my_tool(question)
    messages = [
        { "role": "system", "content": "You are a helpful assistant. Please respond to the user's request only based on the given context." },
        { "role": "user", "content": f"Question: {question}\nContext: {context}"}
    ]
    chat_completion = client.chat.completions.create(
        model="gpt-5.4-mini", messages=messages
    )
    return chat_completion.choices[0].message.content

app_inputs = {"input": "Can you summarize this morning's meetings?"}

with ls.trace("Chat Pipeline", "chain", project_name="my_test", inputs=app_inputs) as rt:
    output = chat_pipeline("Can you summarize this morning's meetings?")
    rt.end(outputs={"output": output})

RunTree API 사용

트레이스를 LangSmith로 기록하는 더 명시적인 또 다른 방법은 RunTree API입니다. 이 API를 사용하면 트레이싱을 더 깊이 제어할 수 있습니다. 런과 자식 런을 수동으로 만들어 트레이스를 조립할 수 있습니다. 여전히 LANGSMITH_API_KEY를 설정해야 하지만, 이 방법에는 LANGSMITH_TRACING이 필요하지 않습니다.

이 방법은 대부분의 사용 사례에 권장되지 않습니다. 트레이스 컨텍스트를 수동으로 관리하는 것은 컨텍스트 전파를 자동으로 처리하는 @traceable에 비해 오류가 발생하기 쉽습니다.

import openai
from langsmith.run_trees import RunTree

# This can be a user input to your app
question = "Can you summarize this morning's meetings?"

# Create a top-level run
pipeline = RunTree(
  name="Chat Pipeline",
  run_type="chain",
  inputs={"question": question}
)
pipeline.post()

# This can be retrieved in a retrieval step
context = "During this morning's meeting, we solved all world conflict."
messages = [
  { "role": "system", "content": "You are a helpful assistant. Please respond to the user's request only based on the given context." },
  { "role": "user", "content": f"Question: {question}\nContext: {context}"}
]

# Create a child run
child_llm_run = pipeline.create_child(
  name="OpenAI Call",
  run_type="llm",
  inputs={"messages": messages},
)
child_llm_run.post()

# Generate a completion
client = openai.Client()
chat_completion = client.chat.completions.create(
  model="gpt-5.4-mini", messages=messages
)

# End the runs and log them
child_llm_run.end(outputs=chat_completion)
child_llm_run.patch()
pipeline.end(outputs={"answer": chat_completion.choices[0].message.content})
pipeline.patch()
import OpenAI from "openai";
import { RunTree } from "langsmith";

// This can be a user input to your app
const question = "Can you summarize this morning's meetings?";

const pipeline = new RunTree({
  name: "Chat Pipeline",
  run_type: "chain",
  inputs: { question }
});
await pipeline.postRun();

// This can be retrieved in a retrieval step
const context = "During this morning's meeting, we solved all world conflict.";
const messages = [
  { role: "system", content: "You are a helpful assistant. Please respond to the user's request only based on the given context." },
  { role: "user", content: `Question: ${question}Context: ${context}` }
];

// Create a child run
const childRun = await pipeline.createChild({
  name: "OpenAI Call",
  run_type: "llm",
  inputs: { messages },
});
await childRun.postRun();

// Generate a completion
const client = new OpenAI();
const chatCompletion = await client.chat.completions.create({
  model: "gpt-5.4-mini",
  messages: messages,
});

// End the runs and log them
childRun.end(chatCompletion);
await childRun.patchRun();
pipeline.end({ outputs: { answer: chatCompletion.choices[0].message.content } });
await pipeline.patchRun();
import com.langchain.smith.client.LangsmithClient;
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient;
import com.langchain.smith.tracing.RunTree;
import com.langchain.smith.tracing.RunType;
import com.langchain.smith.tracing.TraceConfig;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import com.openai.models.chat.completions.ChatCompletionMessageParam;
import com.openai.models.chat.completions.ChatCompletionSystemMessageParam;
import com.openai.models.chat.completions.ChatCompletionUserMessageParam;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class RunTreeExample {
    public static void main(String[] args) throws InterruptedException {
        LangsmithClient langsmith = LangsmithOkHttpClient.fromEnv();
        OpenAIClient openai = OpenAIOkHttpClient.fromEnv();
        ExecutorService executor = Executors.newSingleThreadExecutor();

        try {
            String question = "Can you summarize this morning's meetings?";
            String runId = "01990f3e-7f97-74c5-a9b6-8d3f7e8e2f11";

            RunTree pipeline = RunTree.builder()
                .id(runId)
                .name("Chat Pipeline")
                .runType(RunType.CHAIN)
                .inputs(Collections.singletonMap("question", question))
                .client(langsmith)
                .executor(executor)
                .build();
            pipeline.postRun();

            String context = "During this morning's meeting, we solved all world conflict.";
            List<ChatCompletionMessageParam> messages = Arrays.asList(
                ChatCompletionMessageParam.ofSystem(
                    ChatCompletionSystemMessageParam.builder()
                        .content(
                            "You are a helpful assistant. Please respond to the user's " +
                                "request only based on the given context.")
                        .build()),
                ChatCompletionMessageParam.ofUser(
                    ChatCompletionUserMessageParam.builder()
                        .content("Question: " + question + "\nContext: " + context)
                        .build()));

            RunTree childRun = pipeline.createChild(
                TraceConfig.builder().name("OpenAI Call").runType(RunType.LLM).build());
            childRun.setInputs(Collections.singletonMap("messages", messages));
            childRun.postRun();

            ChatCompletion chatCompletion = openai.chat().completions().create(
                ChatCompletionCreateParams.builder()
                    .model(ChatModel.GPT_5_5)
                    .messages(messages)
                    .build());

            String answer = chatCompletion.choices().get(0).message().content().orElse("");
            System.out.println(answer);

            childRun.setOutputs(Collections.singletonMap("response", chatCompletion.toString()));
            childRun.setEndTime(Instant.now().toString());
            childRun.patchRun();

            pipeline.setOutputs(Collections.singletonMap(
                "answer", answer));
            pipeline.setEndTime(Instant.now().toString());
            pipeline.patchRun();
        } finally {
            executor.shutdown();
            if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                throw new IllegalStateException(
                    "Timed out waiting for LangSmith traces to submit");
            }
        }
    }
}
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.tracing.RunTree
import com.langchain.smith.tracing.RunType
import com.langchain.smith.tracing.TraceConfig
import com.openai.client.okhttp.OpenAIOkHttpClient
import com.openai.models.ChatModel
import com.openai.models.chat.completions.ChatCompletionCreateParams
import com.openai.models.chat.completions.ChatCompletionMessageParam
import com.openai.models.chat.completions.ChatCompletionSystemMessageParam
import com.openai.models.chat.completions.ChatCompletionUserMessageParam
import java.time.Instant
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

val langsmith = LangsmithOkHttpClient.fromEnv()
val openai = OpenAIOkHttpClient.fromEnv()
val executor = Executors.newSingleThreadExecutor()

try {
    val question = "Can you summarize this morning's meetings?"
    val runId = "01990f3e-7f97-74c5-a9b6-8d3f7e8e2f11"

    val pipeline =
        RunTree.builder()
            .id(runId)
            .name("Chat Pipeline")
            .runType(RunType.CHAIN)
            .inputs(mapOf("question" to question))
            .client(langsmith)
            .executor(executor)
            .build()
    println("[run-tree-example] Posting parent run to LangSmith…")
    pipeline.postRun()

    val context = "During this morning's meeting, we solved all world conflict."
    val messages =
        listOf(
            ChatCompletionMessageParam.ofSystem(
                ChatCompletionSystemMessageParam.builder()
                    .content(
                        "You are a helpful assistant. Please respond to the user's " +
                            "request only based on the given context.",
                    )
                    .build(),
            ),
            ChatCompletionMessageParam.ofUser(
                ChatCompletionUserMessageParam.builder()
                    .content("Question: $question\nContext: $context")
                    .build(),
            ),
        )

    val childRun =
        pipeline.createChild(
            TraceConfig.builder().name("OpenAI Call").runType(RunType.LLM).build(),
        )
    childRun.inputs = mapOf("messages" to messages)
    println("[run-tree-example] Posting child run to LangSmith…")
    childRun.postRun()

    val chatCompletion =
        openai.chat().completions().create(
            ChatCompletionCreateParams.builder()
                .model(ChatModel.GPT_5_5)
                .messages(messages)
                .build(),
        )

    val answer = chatCompletion.choices()[0].message().content().orElse("")
    println("[run-tree-example] Answer:")
    println(answer)

    childRun.outputs = mapOf("response" to chatCompletion.toString())
    childRun.endTime = Instant.now().toString()
    childRun.patchRun()

    pipeline.outputs =
        mapOf(
            "answer" to answer,
        )
    pipeline.endTime = Instant.now().toString()
    pipeline.patchRun()
} finally {
    executor.shutdown()
    check(executor.awaitTermination(10, TimeUnit.SECONDS)) {
        "Timed out waiting for LangSmith traces to submit"
    }
}

Java와 Kotlin 예시는 커스텀 루트 런 ID와 전용 실행기를 사용합니다. 실행기를 종료하고 종료를 기다리면 프로세스가 끝나기 전에 백그라운드 런 제출이 완료됩니다.

예시 사용법

이전 섹션에서 설명한 유틸리티를 확장해 어떤 코드든 트레이싱할 수 있습니다. 다음 코드는 몇 가지 예시 확장을 보여줍니다.

클래스의 공개 메서드 트레이싱:

from typing import Any, Callable, Type, TypeVar

T = TypeVar("T")

def traceable_cls(cls: Type[T]) -> Type[T]:
    """Instrument all public methods in a class."""
    def wrap_method(name: str, method: Any) -> Any:
        if callable(method) and not name.startswith("__"):
            return traceable(name=f"{cls.__name__}.{name}")(method)
        return method

    # Handle __dict__ case
    for name in dir(cls):
        if not name.startswith("_"):
            try:
                method = getattr(cls, name)
                setattr(cls, name, wrap_method(name, method))
            except AttributeError:
                # Skip attributes that can't be set (e.g., some descriptors)
                pass

    # Handle __slots__ case
    if hasattr(cls, "__slots__"):
        for slot in cls.__slots__:  # type: ignore[attr-defined]
            if not slot.startswith("__"):
                try:
                    method = getattr(cls, slot)
                    setattr(cls, slot, wrap_method(slot, method))
                except AttributeError:
                    # Skip slots that don't have a value yet
                    pass

    return cls

@traceable_cls
class MyClass:
    def __init__(self, some_val: int):
        self.some_val = some_val

    def combine(self, other_val: int):
        return self.some_val + other_val

# See trace: https://smith.langchain.com/public/882f9ecf-5057-426a-ae98-0edf84fdcaf9/r
MyClass(13).combine(29)

커스텀 런 ID 지정

기본적으로 LangSmith는 각 런에 무작위 ID를 할당합니다. 런 ID를 미리 알아야 할 때(예: 런 직후 피드백을 연결하기 위해), LangSmith 런을 외부 시스템의 ID와 상관시키거나, 결정적 ID로 런을 멱등성(idempotent) 있게 만들 때 이를 재정의할 수 있습니다.

참고: 커스텀 런 ID에는 UUID v7을 사용하세요. UUIDv7은 타임스탬프를 내장해 트레이스 내 런의 올바른 시간 정렬을 보존합니다. LangSmith SDK는 uuid7 헬퍼(Python v0.4.43+, JS v0.3.80+)를 내보냅니다:

  • Python: from langsmith import uuid7
  • JS/TS: import { uuid7 } from 'langsmith'

어떤 UUID v7 문자열이든 허용됩니다 — SDK 헬퍼를 사용하거나 시스템이 이미 UUID v7 식별자를 사용한다면 자체 것을 사용할 수 있습니다.

다음 중 하나를 사용하세요:

  • @traceable:@traceable 함수를 호출할 때 langsmith_extra 안의 run_id를 전달(Python), 또는 traceable에 전달되는 구성 객체의 id를 전달(TypeScript):

    from langsmith import traceable, uuid7
    
    @traceable
    def my_pipeline(question: str) -> str:
        return "answer"
    
    run_id = uuid7()
    my_pipeline("What is the capital of France?", langsmith_extra={"run_id": run_id})
    
    # run_id can now be used to attach feedback, query the run, etc.
    
    import { traceable } from "langsmith/traceable";
    import { uuid7 } from "langsmith";
    
    const runId = uuid7();
    
    const myPipeline = traceable(
    async (question: string) => {
        return "answer";
    },
    { name: "my-pipeline", id: runId }
    );
    
    await myPipeline("What is the capital of France?");
    
    // runId can now be used to attach feedback, query the run, etc.
    
  • trace 컨텍스트 매니저 (Python 전용): trace 컨텍스트 매니저 생성자에 run_id를 직접 전달:

    from langsmith import trace, uuid7
    
    run_id = uuid7()
    
    with trace("my-pipeline", run_id=run_id) as run:
        result = "answer"
        run.end(outputs={"result": result})
    
    # run_id can now be used to attach feedback, query the run, etc.
    

종료 전에 모든 트레이스가 제출되도록 보장

LangSmith는 프로덕션 애플리케이션을 방해하지 않도록 백그라운드 스레드에서 트레이싱을 수행합니다. 즉 프로세스가 모든 트레이스가 LangSmith에 성공적으로 게시되기 전에 끝날 수 있습니다. 다음 옵션을 참고하세요:

  • LangChain을 사용한다면 LangChain 트레이싱 가이드를 참고하세요.

  • LangSmith SDK를 독립형으로 사용한다면 종료 전에 flush 메서드를 사용할 수 있습니다:

    from langsmith import Client
    
    client = Client()
    
    @traceable(client=client)
    async def my_traced_func():
    # Your code here...
    pass
    
    try:
    await my_traced_func()
    finally:
    await client.flush()
    
    import { Client } from "langsmith";
    
    const langsmithClient = new Client({});
    
    const myTracedFunc = traceable(async () => {
    // Your code here...
    },{ client: langsmithClient });
    
    try {
    await myTracedFunc();
    } finally {
    await langsmithClient.flush();
    }
    

관련 문서

더 알아보기