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_name을 RunnableConfig 객체 생성 시 지정하거나 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의 langsmith의 traceable)를 사용하여 모델 호출 주위에 커스텀 실행을 생성합니다.
실행(run) ID 커스터마이즈하기
LangChain 코드를 호출하거나 스트리밍할 때 Config에 실행 ID를 지정하여 커스터마이즈할 수 있습니다. 이 ID는 LangSmith에서 실행을 고유하게 식별하며, 특정 실행을 쿼리하는 데 사용할 수 있습니다. 여러 시스템 간 실행을 연결하거나 커스텀 추적 로직을 구현할 때 유용합니다. run_id를 RunnableConfig 객체 생성 시 지정하거나 호출 파라미터로 전달하면 됩니다.
이 기능은 현재 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을 함께 사용할 때 다음과 같은 제한 사항이 있습니다:
- RunnableLambda 컨텍스트의
getCurrentRunTree()로 얻은 RunTree를 변경해도 아무런 효과가 없습니다(no-op).
- RunnableLambda에서 얻은 RunTree를 탐색하는 것은 권장하지 않습니다. 모든 RunTree 노드를 포함하지 않을 수 있습니다.
- 서로 다른 자식 실행(run)은 동일한
execution_order 및 child_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의 RunnableConfig를 RunTree.fromRunnableConfig로 동등한 RunTree 객체로 변환하거나, RunnableConfig를 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) => {
// Pass the config to existing traceable function
await tracedChild(config, input.text);
return input.text;
},
});
영상 튜토리얼을 원하신다면, LangSmith 소개 과정의 Alternative Ways to Trace 영상을 참고하세요.