이 제품은 선택한 Datadog 사이트에서 지원되지 않습니다. ().

개요

Agent Observability SDK는 자동 계측과 수동 계측 API를 모두 제공하여 LLM 애플리케이션에 대한 관측 가능성과 인사이트를 제공합니다.

설정

요구 사항

  • 최신 ddtrace 패키지가 설치되어 있어야 합니다(Python 3.7 이상 필요).
    pip install ddtrace
    
  • 최신 dd-trace 패키지가 설치되어 있어야 합니다(Node.js 16 이상 필요).
    npm install dd-trace
    
  • 최신 dd-trace-java JAR 파일을 다운로드해야 합니다. Agent Observability SDK는 dd-trace-java v1.51.0 이상에서 지원됩니다(Java 8 이상 필요).

ddtrace-run 명령을 사용하여 애플리케이션을 실행하고 필수 환경 변수를 지정하여 Agent Observability를 활성화합니다.

참고: ddtrace-run은 모든 Agent Observability 통합을 자동으로 활성화합니다.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> DD_LLMOBS_ENABLED=1 \
DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME> ddtrace-run <YOUR_APP_STARTUP_COMMAND>

명령줄 설정용 환경 변수

DD_SITE
필수 - string
LLM 데이터를 제출할 목적지 Datadog 사이트입니다. 사이트는 입니다.
DD_LLMOBS_ENABLED
필수 - integer 또는 string
Agent Observability로 데이터 전송을 활성화하는 토글입니다. 1 또는 true로 설정해야 합니다.
DD_LLMOBS_ML_APP
선택 사항 - string
모든 트레이스와 스팬이 그룹화되는 LLM 애플리케이션, 서비스 또는 프로젝트의 이름입니다. 이를 통해 서로 다른 애플리케이션 또는 실험을 구분할 수 있습니다. 허용 문자 및 기타 제약 사항은 애플리케이션 명명 지침을 참조하세요. 특정 루트 스팬에 대해 이 값을 재정의하려면 여러 애플리케이션 추적을 참조하세요. 지정하지 않으면 DD_SERVICE 값 또는 업스트림 서비스에서 전파된 DD_LLMOBS_ML_APP 값이 기본값으로 사용됩니다.
참고: ddtrace==3.14.0 이전 버전에서 이 필드는 필수 필드입니다.
DD_LLMOBS_AGENTLESS_ENABLED
선택 사항 - integer 또는 string - 기본값: false
Datadog Agent를 사용하지 않는 경우에만 필요하며, 이 경우 1 또는 true로 설정해야 합니다.
DD_LLMOBS_SAMPLE_RATE
선택 사항 - float - 기본값: 1.0
Agent Observability가 보존하는 트레이스의 비율입니다. 트레이스 샘플링을 참조하세요.
DD_API_KEY
선택 사항 - string
Datadog API 키입니다. Datadog Agent를 사용하지 않는 경우에만 필요합니다.
DD_MCP_CAPTURE_INTENT
선택 사항 - integer 또는 string - 기본값: false
1 또는 true로 설정된 경우 호출 모델이 해당 도구를 호출한 이유를 설명하도록 요청하는 모든 MCP 서버 도구에 인수를 추가합니다. 의도는 도구 스팬에 기록됩니다.

NODE_OPTIONS="--import dd-trace/initialize.mjs"를 사용하여 애플리케이션을 실행하고 필수 환경 변수를 지정하여 Agent Observability를 활성화합니다.

참고: : dd-trace/initialize.mjs는 모든 APM 통합을 자동으로 활성화합니다.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> DD_LLMOBS_ENABLED=1 \
DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME> NODE_OPTIONS="--import dd-trace/initialize.mjs" node <YOUR_APP_ENTRYPOINT>

명령줄 설정용 환경 변수

DD_SITE
필수 - string
LLM 데이터를 제출할 Datadog 사이트입니다. 사이트는 입니다.
DD_LLMOBS_ENABLED
필수 - integer 또는 string
Agent Observability로 데이터 전송을 활성화하는 토글입니다. 1 또는 true로 설정해야 합니다.
DD_LLMOBS_ML_APP
선택 사항 - string
모든 트레이스와 스팬이 그룹화되는 LLM 애플리케이션, 서비스 또는 프로젝트의 이름입니다. 이를 통해 서로 다른 애플리케이션 또는 실험을 구분할 수 있습니다. 허용 문자 및 기타 제약 사항은 애플리케이션 명명 지침을 참조하세요. 특정 루트 스팬에 대해 이 값을 재정의하려면 여러 애플리케이션 추적을 참조하세요. 지정하지 않으면 DD_SERVICE 값 또는 업스트림 서비스에서 전파된 DD_LLMOBS_ML_APP 값이 기본값으로 사용됩니다.
참고: dd-trace@5.66.0 이전 버전에서 이 필드는 필수 필드입니다.
DD_LLMOBS_AGENTLESS_ENABLED
선택 사항 - integer 또는 string - 기본값: false
Datadog Agent를 사용하지 않는 경우에만 필요하며, 이 경우 1 또는 true로 설정해야 합니다.
DD_LLMOBS_SAMPLE_RATE
선택 사항 - float - 기본값: 1.0
Agent Observability가 보존하는 트레이스의 비율입니다. 트레이스 샘플링을 참조하세요.
DD_API_KEY
선택 사항 - string
Datadog API 키입니다. Datadog Agent를 사용하지 않는 경우에만 필요합니다.

dd-trace-java를 사용하여 애플리케이션을 실행하고 필수 파라미터를 환경 변수 또는 시스템 속성으로 지정하여 Agent Observability를 활성화합니다.

DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> \
java -javaagent:path/to/your/dd-trace-java-jar/dd-java-agent-SNAPSHOT.jar \
-Ddd.service=my-app -Ddd.llmobs.enabled=true -Ddd.llmobs.ml.app=my-ml-app -jar path/to/your/app.jar

환경 변수 및 시스템 속성

다음 파라미터는 환경 변수(예: DD_LLMOBS_ENABLED) 또는 Java 시스템 속성(예: dd.llmobs_enabled)으로 제공할 수 있습니다.

DD_SITE 또는 dd.site
필수 - string
LLM 데이터를 제출할 목적지 Datadog 사이트입니다. 사이트는 입니다.
DD_LLMOBS_ENABLED 또는 dd.llmobs.enabled
필수 - integer 또는 string
Agent Observability로 데이터 전송을 활성화하는 토글입니다. 1 또는 true로 설정해야 합니다.
DD_LLMOBS_ML_APP 또는 dd.llmobs.ml.app
선택 사항 - string
모든 트레이스와 스팬이 그룹화되는 LLM 애플리케이션, 서비스 또는 프로젝트의 이름입니다. 이를 통해 서로 다른 애플리케이션 또는 실험을 구분할 수 있습니다. 허용 문자 및 기타 제약 사항은 애플리케이션 명명 지침을 참조하세요. 특정 루트 스팬에 대해 이 값을 재정의하려면 여러 애플리케이션 추적을 참조하세요. 지정하지 않으면 DD_SERVICE 값 또는 업스트림 서비스에서 전파된 DD_LLMOBS_ML_APP 값이 기본값으로 사용됩니다.
참고: dd-trace-java 1.54.0 버전 이전에서 이 필드는 필수 필드입니다.
DD_LLMOBS_AGENTLESS_ENABLED 또는 dd.llmobs.agentless.enabled
선택 사항 - integer 또는 string - 기본값: false
Datadog Agent를 사용하지 않는 경우에만 필요하며, 이 경우 1 또는 true로 설정해야 합니다.
DD_API_KEY 또는 dd.api.key
선택 사항 - string
Datadog API 키입니다. Datadog Agent를 사용하지 않는 경우에만 필요합니다.

명령줄 설정 대신 프로그래밍 방식으로도 Agent Observability를 활성화할 수 있습니다.

LLMObs.enable() 함수를 사용하여 Agent Observability를 활성화합니다.

이 설정 메서드는 ddtrace-run 명령과 함께 사용하지 마세요.
from ddtrace.llmobs import LLMObs
LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  api_key="<YOUR_DATADOG_API_KEY>",
  site="<YOUR_DATADOG_SITE>",
  agentless_enabled=True,
)
파라미터
ml_app
선택 사항 - string
모든 트레이스와 스팬이 그룹화되는 LLM 애플리케이션, 서비스 또는 프로젝트의 이름입니다. 이를 통해 서로 다른 애플리케이션 또는 실험을 구분할 수 있습니다. 허용 문자 및 기타 제약 사항은 애플리케이션 명명 지침을 참조하세요. 주어진 트레이스에 대해 이 값을 재정의하려면 여러 애플리케이션 추적하기를 참조하세요. 지정하지 않으면 DD_LLMOBS_ML_APP 값이 기본값으로 사용됩니다.
integrations_enabled - 기본값: true
선택 사항 - boolean
Datadog에서 지원하는 LLM 통합에 대해 LLM 호출을 자동으로 추적하도록 활성화하는 플래그입니다. 지정하지 않으면 지원되는 모든 LLM 통합이 기본적으로 활성화됩니다. LLM 통합을 사용하지 않으려면 이 값을 false로 설정하세요.
agentless_enabled
선택 사항 - boolean - 기본값: false
Datadog Agent를 사용하지 않는 경우에만 필요하며, 이 경우 True로 설정해야 합니다. 이 구성은 ddtrace 라이브러리가 Datadog Agent가 필요한 데이터를 전송하지 않도록 구성합니다. 지정하지 않으면 DD_LLMOBS_AGENTLESS_ENABLED 값이 기본값으로 사용됩니다.
site
선택 사항 - string
LLM 데이터를 제출할 Datadog 사이트입니다. 사이트는 입니다. 지정하지 않으면 DD_SITE 값이 기본값으로 사용됩니다.
api_key
선택 사항 - string
Datadog API 키입니다. Datadog Agent를 사용하지 않는 경우에만 필요합니다. 지정하지 않으면 DD_API_KEY 값이 기본값으로 사용됩니다.
env
선택 사항 - string
애플리케이션이 실행되는 환경 이름입니다(예: : prod, pre-prod, staging). 지정하지 않으면 DD_ENV 값이 기본값으로 사용됩니다.
service
선택 사항 - string
애플리케이션에 사용되는 서비스의 이름입니다. 지정하지 않으면 DD_SERVICE 값이 기본값으로 사용됩니다.
sample_rate
선택 사항 - float
Agent Observability가 보존하는 트레이스의 비율입니다. ddtrace 4.12.0 이상이 필요합니다. 설정되면 DD_LLMOBS_SAMPLE_RATE보다 우선합니다. 트레이스 샘플링을 참조하세요.
capture_intent
선택 사항 - boolean - 기본값: false
True로 설정된 경우 호출 모델이 해당 도구를 호출한 이유를 설명하도록 요청하는 모든 MCP 서버 도구에 인수를 추가합니다. 의도는 도구 스팬에 기록됩니다. 지정하지 않으면 DD_MCP_CAPTURE_INTENT 값이 기본값으로 사용됩니다.
이 설정 메서드는 dd-trace/initialize.mjs 명령과 함께 사용하지 마세요.

init() 함수를 사용하여 Agent Observability를 활성화합니다.

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>",
    agentlessEnabled: true,
  },
  site: "<YOUR_DATADOG_SITE>",
  env: "<YOUR_ENV>",
});

const llmobs = tracer.llmobs;

llmobs 구성 옵션

mlApp
선택 사항 - string
모든 트레이스와 스팬이 그룹화되는 LLM 애플리케이션, 서비스 또는 프로젝트의 이름입니다. 이를 통해 서로 다른 애플리케이션 또는 실험을 구분할 수 있습니다. 허용 문자 및 기타 제약 사항은 애플리케이션 명명 지침을 참조하세요. 주어진 트레이스에 대해 이 값을 재정의하려면 여러 애플리케이션 추적하기를 참조하세요. 지정하지 않으면 DD_LLMOBS_ML_APP 값이 기본값으로 사용됩니다.
agentlessEnabled
선택 사항 - boolean - 기본값: false
Datadog Agent를 사용하지 않는 경우에만 필요하며, 이 경우 true로 설정해야 합니다. 이 구성은 dd-trace 라이브러리가 Datadog Agent가 필요한 데이터를 전송하지 않도록 구성합니다. 지정하지 않으면 DD_LLMOBS_AGENTLESS_ENABLED 값이 기본값으로 사용됩니다.
sampleRate
선택 사항 - number
Agent Observability가 보존하는 트레이스의 비율입니다. dd-trace 5.110.0 이상이 필요합니다. 설정되면 DD_LLMOBS_SAMPLE_RATE보다 우선합니다. 트레이스 샘플링을 참조하세요.

일반 트레이서 구성 옵션:

site
선택 사항 - string
LLM 데이터를 제출할 Datadog 사이트입니다. 사이트는 입니다. 지정하지 않으면 DD_SITE 값이 기본값으로 사용됩니다.
env
선택 사항 - string
애플리케이션이 실행되는 환경 이름입니다(예: : prod, pre-prod, staging). 지정하지 않으면 DD_ENV 값이 기본값으로 사용됩니다.
service
선택 사항 - string
애플리케이션에 사용되는 서비스의 이름입니다. 지정하지 않으면 DD_SERVICE 값이 기본값으로 사용됩니다.
환경 변수

다음 값을 환경 변수로 설정하세요. 프로그래밍 방식으로는 구성할 수 없습니다.

DD_API_KEY
선택 사항 - string
Datadog API 키입니다. Datadog Agent를 사용하지 않는 경우에만 필요합니다.

AWS Lambda의 경우, AWS Lambda에서 LLM 애플리케이션을 추적하기를 참조하십시오.

SDK를 설치하고 애플리케이션을 실행하면 자동 계측을 통해 Agent Observability에 일부 데이터가 표시되는 것을 확인할 수 있습니다. 아직 지원되지 않는 라이브러리에서 생성된 사용자 지정 프레임워크나 작업을 수집하려면 수동 계측을 사용할 수 있습니다.

트레이스 샘플링

트레이스 샘플링은 Python SDK(ddtrace 4.12.0 이상) 및 Node.js SDK(dd-trace 5.110.0 이상)에서 사용할 수 있습니다. Java SDK는 트레이스 샘플링을 지원하지 않습니다.

트레이스 샘플링은 Agent Observability가 보존하는 트레이스의 비율을 설정합니다. Agent Observability 청구는 전송하는 스팬의 볼륨을 기준으로 하므로, 샘플링 비율을 설정하는 것은 Agent Observability 비용을 제어하는 한 가지 방법입니다. SDK는 루트 스팬에 대해 샘플링 결정을 내리고, 분산 트레이싱을 통해 다운스트림 서비스에서 생성된 스팬을 포함하여 해당 루트 스팬의 모든 하위 스팬에 이를 적용합니다.

샘플링은 Agent Observability 메트릭(여기에는 토큰 및 비용 메트릭과 기타 운영 메트릭이 포함됨)에 영향을 주지 않습니다. 샘플링되지 않은 스팬은 Datadog이 트레이스를 수집한 후 드롭되므로, 해당 메트릭은 지정된 샘플 비율과 관계없이 애플리케이션의 계측된 트래픽 100%를 기준으로 유지됩니다. 추적 샘플링은 수집 후에 적용되는 자동화 규칙APM 추적 샘플링과 같은 인앱 제어와도 독립적입니다.

다음 두 가지 메커니즘 중 하나를 통해 샘플 비율을 구성할 수 있습니다.

  • 환경 변수(DD_LLMOBS_SAMPLE_RATE): 명령줄 설정인코드 설정 모두에 적용됩니다.
  • 인코드 파라미터(Python의 경우 sample_rate, Node.js의 경우 sampleRate): 인코드 설정으로 SDK를 활성화할 때 Python에서는 LLMObs.enable()에 전달되며, Node.js에서는 llmobs 아래에서 전달됩니다. 설정된 경우 DD_LLMOBS_SAMPLE_RATE보다 우선합니다.

샘플 비율은 0.0(트레이스 보존 안 함)에서 1.0(모든 트레이스 보존) 사이의 부동 소수점 값입니다. 기본값은 1.0입니다. 범위를 벗어난 값은 무시됩니다.

다음과 같이 환경 변수로 샘플 비율을 설정하세요.

DD_LLMOBS_SAMPLE_RATE=0.5 ddtrace-run <YOUR_APP_STARTUP_COMMAND>

또는 sample_rateLLMObs.enable()에 전달하면 환경 변수보다 우선 적용됩니다.

from ddtrace.llmobs import LLMObs

LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  sample_rate=0.5,
)

다음과 같이 환경 변수로 샘플 비율을 설정하세요.

DD_LLMOBS_SAMPLE_RATE=0.5 NODE_OPTIONS="--import dd-trace/initialize.mjs" <YOUR_APP_STARTUP_COMMAND>

또는 llmobs 아래에서 sampleRateinit()에 전달하면 환경 변수보다 우선합니다.

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>",
    sampleRate: 0.5,
  },
});

const llmobs = tracer.llmobs;

수동 계측

LLM 작업을 캡처하기 위해 함수 데코레이터를 사용하여 워크플로를 손쉽게 계측할 수 있습니다.

from ddtrace.llmobs.decorators import workflow

@workflow
def handle_user_request():
    ...

또는 세밀한 작업을 캡처하기 위해 컨텍스트 관리자 기반 접근 방식을 사용할 수도 있습니다.

from ddtrace.llmobs import LLMObs

with LLMObs.llm(model="gpt-4o"):
    call_llm()
    LLMObs.annotate(
        metrics={
            "input_tokens": ...,
            "output_tokens": ...,
        },
    )

사용 가능한 스팬 종류의 목록은 스팬 종류 설명서를 참조하세요. 함수 내부 작업을 보다 세밀하게 추적하려면 인라인 메서드를 사용한 스팬 추적하기를 참조하세요.

스팬을 추적하려면 추적하려는 함수에 대해 함수 래퍼로 llmobs.wrap(options, function)을 사용하세요. 사용 가능한 스팬 종류의 목록은 스팬 종류 설명서를 참조하세요. 함수 내부 작업을 보다 세밀하게 추적하려면 인라인 메서드를 사용한 스팬 추적하기를 참조하세요.

스팬 종류

스팬 종류는 필수이며, llmobs 추적 함수(trace, wrap, decorate)에 전달되는 options 객체에서 지정합니다. 지원되는 스팬 종류의 목록은 스팬 종류 설명서를 참조하세요.

참고: 유효하지 않은 스팬 종류의 스팬은 Agent Observability에 제출되지 않습니다.

함수 인수/출력/이름 자동 캡처

llmobs.wrap(TypeScript의 경우 llmobs.decorate 포함)은 추적 중인 함수의 입력값, 출력값 및 함수 이름을 자동으로 캡처하려고 시도합니다. 스팬에 수동으로 주석을 달아야 하는 경우 스팬 강화하기를 참조하세요. 입력과 출력에 주석을 달면 자동 수집된 값을 재정의하게 됩니다. 또한 함수 이름을 재정의하려면 llmobs.wrap 함수의 options 객체에 name 속성을 전달하면 됩니다.

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow', name: 'differentFunctionName' }, processMessage)

래핑된 함수의 스팬 종료 조건

llmobs.wraptracer.wrap의 기본 동작을 확장합니다. 함수가 호출될 때 생성된 기본 스팬은 다음 조건에서 종료됩니다.

  • 함수가 Promise를 반환하면 Promise가 해결되거나 거부될 때 스팬이 종료됩니다.
  • 함수의 마지막 파라미터가 콜백인 경우 해당 콜백이 호출될 때 스팬이 종료됩니다.
  • 함수가 콜백을 받지 않고 Promise도 반환하지 않으면 함수 실행이 끝날 때 스팬이 종료됩니다.

다음 예시는 마지막 인수가 콜백인 두 번째 조건을 보여줍니다.

예시

const express = require('express')
const app = express()

function myAgentMiddleware (req, res, next) {
  const err = ... // user application logic
  // the span for this function is finished when `next` is called
  next(err)
}
myAgentMiddleware = llmobs.wrap({ kind: 'agent' }, myAgentMiddleware)

app.use(myAgentMiddleware)

애플리케이션에서 콜백 함수를 사용하지 않는 경우, 대신 인라인 추적 블록을 사용하는 것이 좋습니다. 자세한 내용은 인라인 메서드를 사용한 스팬 추적하기를 참조하세요.

const express = require('express')
const app = express()

function myAgentMiddleware (req, res) {
  // the `next` callback is not being used here
  return llmobs.trace({ kind: 'agent', name: 'myAgentMiddleware' }, () => {
    return res.status(200).send('Hello World!')
  })
}

app.use(myAgentMiddleware)

스팬 시작하기

스팬은 시작하려는 스팬의 종류에 따라 여러 메서드로 시작할 수 있습니다. 지원되는 스팬 종류의 목록은 스팬 종류 설명서를 참조하세요.

모든 스팬은 LLMObsSpan의 객체 인스턴스로 시작됩니다. 각 스팬에는 스팬과 상호작용하고 데이터를 기록할 수 있는 메서드가 제공됩니다.

스팬 종료하기

트레이스를 Datadog 앱에서 제출하고 표시하려면 스팬을 종료해야 합니다.

스팬을 종료하려면 스팬 객체 인스턴스에서 finish()를 호출하세요. 가능한 경우, 예외가 발생하더라도 스팬이 제출되도록 try/finally 블록으로 래핑하는 것이 좋습니다.

예시

    try {
        LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("my-workflow-span-name", "ml-app-override", "session-141");
        // user logic
        // interact with started span
    } finally {
      workflowSpan.finish();
    }

LLM 호출

Datadog의 LLM 통합에서 지원하는 LLM 제공업체 또는 프레임워크를 사용하는 경우, 이러한 작업을 추적하기 위해 LLM 스팬을 수동으로 시작할 필요가 없습니다.
LLM 스팬을 수동으로 계측하는 경우에는 토큰 수(예: input_tokens, output_tokenstotal_tokens)를 직접 기록해야 하며, 이를 위해 스팬에 주석을 달아야 합니다. 자세한 내용은 스팬 강화하기를 참조하세요.

LLM 호출을 추적하려면 ddtrace.llmobs.decorators.llm() 함수 데코레이터를 사용하세요.

model_name
필수 - string
호출된 LLM의 이름입니다.
name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
model_provider
선택 사항 - string - 기본값: "custom"
모델 제공자의 이름입니다.
참고: 미국 달러 기준 예상 비용을 표시하려면 model_provider 값을 openai, azure_openai, anthropic 중 하나로 설정하세요.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call(prompt):
    completion = ... # user application logic to invoke LLM
    LLMObs.annotate(
        input_data=[{"role": "user", "content": prompt}],
        output_data=[{"role": "assistant", "content": completion}],
        metrics={"input_tokens": 4, "output_tokens": 6, "total_tokens": 10},
    )
    return completion

LLM 호출을 추적하려면 스팬 종류를 llm으로 지정하고 필요에 따라 options 객체에 다음 인수를 지정하세요.

modelName
선택 사항 - string - 기본값: "custom"
호출된 LLM의 이름입니다.
name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
modelProvider
선택 사항 - string - 기본값: "custom"
모델 제공자의 이름입니다.
참고: 미국 달러 기준 예상 비용을 표시하려면 modelProvider 값을 openai, azure_openai, anthropic 중 하나로 설정하세요.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function llmCall (prompt) {
  const completion = ... // user application logic to invoke LLM
  llmobs.annotate({
    inputData: [{ role: "user", content: prompt }],
    outputData: [{ role: "assistant", content: completion }],
    metrics: { input_tokens: 4, output_tokens: 6, total_tokens: 10 }
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

LLM 호출을 추적하려면 아래 나열된 인수와 함께 다음 메서드를 가져와 호출하세요.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startLLMSpan(spanName, modelName, modelProvider, mlApp, sessionID);
spanName
선택 사항 - String
작업의 이름입니다. 지정하지 않으면 spanName은 스팬 종류를 기본값으로 사용합니다.
modelName
선택 사항 - String - 기본값: "custom"
호출된 LLM의 이름입니다.
modelProvider
선택 사항 - String - 기본값: "custom"
모델 제공자의 이름입니다.
참고: 미국 달러 기준 예상 비용을 표시하려면 modelProvider 값을 openai, azure_openai, anthropic 중 하나로 설정하세요.
mlApp
선택 사항 - String
해당 작업이 속한 ML 애플리케이션의 이름입니다. null이 아닌 값을 제공하면 애플리케이션 시작 시 지정된 ML 애플리케이션 이름을 재정의합니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.
sessionId
선택 사항 - String
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeModel() {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String inference = ... // user application logic to invoke LLM
    llmSpan.annotateIO(...); // record the input and output
    llmSpan.setMetrics(Map.of(
      "input_tokens", 617,
      "output_tokens", 338,
      "total_tokens", 955
    ));
    llmSpan.finish();
    return inference;
  }
}

워크플로

워크플로 스팬을 추적하려면 ddtrace.llmobs.decorators.workflow() 함수 데코레이터를 사용하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import workflow

@workflow
def process_message():
    ... # user application logic
    return

워크플로 스팬을 추적하려면 스팬 종류를 workflow로 지정하고 필요에 따라 options 객체에 인수를 지정하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow' }, processMessage)

워크플로 스팬을 추적하려면 아래 나열된 인수와 함께 다음 메서드를 가져와 호출하세요.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startWorkflowSpan(spanName, mlApp, sessionID);
spanName
선택 사항 - String
작업의 이름입니다. 지정하지 않으면 spanName은 스팬 종류를 기본값으로 사용합니다.
mlApp
선택 사항 - String
해당 작업이 속한 ML 애플리케이션의 이름입니다. null이 아닌 값을 제공하면 애플리케이션 시작 시 지정된 ML 애플리케이션 이름을 재정의합니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.
sessionId
선택 사항 - String
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String executeWorkflow() {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("my-workflow-span-name", null, "session-141");
    String workflowResult = workflowFn(); // user application logic
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
    return workflowResult;
  }
}

에이전트

에이전트 실행을 추적하려면 ddtrace.llmobs.decorators.agent() 함수 데코레이터를 사용하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import agent

@agent
def react_agent():
    ... # user application logic
    return

에이전트 실행을 추적하려면 스팬 종류를 agent로 지정하고 필요에 따라 options 객체에 인수를 지정하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function reactAgent () {
  ... // user application logic
  return
}
reactAgent = llmobs.wrap({ kind: 'agent' }, reactAgent)

에이전트 실행을 추적하려면 아래 나열된 인수와 함께 다음 메서드를 가져와 호출하세요.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startAgentSpan(spanName, mlApp, sessionID);
spanName
선택 사항 - String
작업의 이름입니다. 지정하지 않으면 spanName은 추적된 함수의 이름을 기본값으로 사용합니다.
mlApp
선택 사항 - String
해당 작업이 속한 ML 애플리케이션의 이름입니다. null이 아닌 값을 제공하면 애플리케이션 시작 시 지정된 ML 애플리케이션 이름을 재정의합니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.
sessionId
선택 사항 - String
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.

도구 호출

도구 호출을 추적하려면 ddtrace.llmobs.decorators.tool() 함수 데코레이터를 사용하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import tool

@tool
def call_weather_api():
    ... # user application logic
    return

도구 호출을 추적하려면 스팬 종류를 tool로 지정하고 필요에 따라 options 객체에 인수를 지정하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function callWeatherApi () {
  ... // user application logic
  return
}
callWeatherApi = llmobs.wrap({ kind: 'tool' }, callWeatherApi)

도구 호출을 추적하려면 아래 나열된 인수와 함께 다음 메서드를 가져와 호출하세요.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startToolSpan(spanName, mlApp, sessionID);
spanName
선택 사항 - String
작업의 이름입니다. 지정하지 않으면 spanName은 추적된 함수의 이름을 기본값으로 사용합니다.
mlApp
선택 사항 - String
해당 작업이 속한 ML 애플리케이션의 이름입니다. null이 아닌 값을 제공하면 애플리케이션 시작 시 지정된 ML 애플리케이션 이름을 재정의합니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.
sessionId
선택 사항 - String
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.

작업

작업 스팬을 추적하려면 LLMObs.task() 함수 데코레이터를 사용하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import task

@task
def sanitize_input():
    ... # user application logic
    return

작업 스팬을 추적하려면 스팬 종류를 task로 지정하고 필요에 따라 options 객체에 인수를 지정하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function sanitizeInput () {
  ... // user application logic
  return
}
sanitizeInput = llmobs.wrap({ kind: 'task' }, sanitizeInput)

작업 스팬을 추적하려면 아래 나열된 인수와 함께 다음 메서드를 가져와 호출하세요.

import datadog.trace.api.llmobs.LLMObs;
LLMObs.startTaskSpan(spanName, mlApp, sessionID);
spanName
선택 사항 - String
작업의 이름입니다. 지정하지 않으면 spanName은 추적된 함수의 이름을 기본값으로 사용합니다.
mlApp
선택 사항 - String
해당 작업이 속한 ML 애플리케이션의 이름입니다. null이 아닌 값을 제공하면 애플리케이션 시작 시 지정된 ML 애플리케이션 이름을 재정의합니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.
sessionId
선택 사항 - String
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.

임베딩

임베딩 작업을 추적하려면 LLMObs.embedding() 함수 데코레이터를 사용하세요.

참고: 임베딩 스팬의 입력에 주석을 달려면 그 외의 스팬 유형과 다른 형식을 사용해야 합니다. 임베딩 입력을 지정하는 방법에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

model_name
필수 - string
호출된 LLM의 이름입니다.
name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름으로 설정됩니다.
model_provider
선택 사항 - string - 기본값: "custom"
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import embedding

@embedding(model_name="text-embedding-3", model_provider="openai")
def perform_embedding():
    ... # user application logic
    return

임베딩 작업을 추적하려면 스팬 종류를 embedding으로 지정하고 필요에 따라 options 객체에 인수를 지정하세요.

참고: 임베딩 스팬의 입력에 주석을 달려면 그 외의 스팬 유형과 다른 형식을 사용해야 합니다. 임베딩 입력을 지정하는 방법에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

modelName
선택 사항 - string - 기본값: "custom"
호출된 LLM의 이름입니다.
name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름으로 설정됩니다.
modelProvider
선택 사항 - string - 기본값: "custom"
모델 제공자의 이름입니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

function performEmbedding () {
  ... // user application logic
  return
}
performEmbedding = llmobs.wrap({ kind: 'embedding', modelName: 'text-embedding-3', modelProvider: 'openai' }, performEmbedding)

검색

검색 스팬을 추적하려면 ddtrace.llmobs.decorators.retrieval() 함수 데코레이터를 사용하세요.

참고: 검색 스팬의 출력에 주석을 달려면 그 외의 스팬 유형과 다른 형식을 사용해야 합니다. 검색 출력을 지정하는 방법에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
session_id
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
ml_app
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

from ddtrace.llmobs.decorators import retrieval

@retrieval
def get_relevant_docs(question):
    context_documents = ... # user application logic
    LLMObs.annotate(
        input_data=question,
        output_data = [
            {"id": doc.id, "score": doc.score, "text": doc.text, "name": doc.name} for doc in context_documents
        ]
    )
    return

검색 스팬을 추적하려면 스팬 종류를 retrieval로 지정하고 필요에 따라 options 객체에 다음 인수를 지정하세요.

참고: 검색 스팬의 출력에 주석을 달려면 그 외의 스팬 유형과 다른 형식을 사용해야 합니다. 검색 출력을 지정하는 방법에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

name
선택 사항 - string
작업의 이름입니다. 지정하지 않으면 name은 추적된 함수의 이름을 기본값으로 사용합니다.
sessionId
선택 사항 - string
기본 사용자 세션의 ID입니다. 자세한 내용은 사용자 세션 추적하기를 참조하세요.
mlApp
선택 사항 - string
해당 작업이 속한 ML 애플리케이션의 이름입니다. 자세한 내용은 여러 애플리케이션 추적하기를 참조하세요.

예시

다음에는 스팬에 주석을 다는 예시도 포함되어 있습니다. 자세한 내용은 스팬 강화하기를 참조하세요.

function getRelevantDocs (question) {
  const contextDocuments = ... // user application logic
  llmobs.annotate({
    inputData: question,
    outputData: contextDocuments.map(doc => ({
      id: doc.id,
      score: doc.score,
      text: doc.text,
      name: doc.name
    }))
  })
  return
}
getRelevantDocs = llmobs.wrap({ kind: 'retrieval' }, getRelevantDocs)

스팬 중첩하기

현재 스팬이 종료되기 전에 새로운 스팬을 시작하면 두 스팬 간에 자동으로 상위-하위 관계가 추적됩니다. 상위 스팬은 더 큰 작업을 나타내며, 하위 스팬은 그 안의 더 작은 중첩된 하위 작업을 나타냅니다.

from ddtrace.llmobs.decorators import task, workflow

@workflow
def extract_data(document):
    preprocess_document(document)
    ... # performs data extraction on the document
    return

@task
def preprocess_document(document):
    ... # preprocesses a document for data extraction
    return
function preprocessDocument (document) {
  ... // preprocesses a document for data extraction
  return
}
preprocessDocument = llmobs.wrap({ kind: 'task' }, preprocessDocument)

function extractData (document) {
  preprocessDocument(document)
  ... // performs data extraction on the document
  return
}
extractData = llmobs.wrap({ kind: 'workflow' }, extractData)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;

public class MyJavaClass {
  public void preprocessDocument(String document) {
  LLMObsSpan taskSpan = LLMObs.startTaskSpan("preprocessDocument", null, "session-141");
   ...   // preprocess document for data extraction
   taskSpan.annotateIO(...); // record the input and output
   taskSpan.finish();
  }

  public String extractData(String document) {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("extractData", null, "session-141");
    preprocessDocument(document);
    ... // perform data extraction on the document
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
  }
}

스팬 강화하기

여기에서 metrics 여기서 파라미터는 개별 스팬에 부여된 숫자 값을 의미하며, Datadog 플랫폼 메트릭을 의미하지 않습니다. 인지되는 특정 키(예: input_tokens, output_tokenstotal_tokens)의 경우 Datadog은 이러한 스팬 속성을 사용해 해당 플랫폼 메트릭(예: ml_obs.span.llm.input.tokens)을 생성하며, 생성된 메트릭은 대시보드와 모니터에서 사용할 수 있습니다.

SDK는 입력, 출력 및 메타데이터로 스팬을 강화하기 위해 LLMObs.annotate() 메서드를 제공합니다.

LLMObs.annotate() 메서드는 다음 인수를 허용합니다.

span
선택 사항 - Span - 기본값: 현재 활성 스팬
주석을 달 스팬입니다. span이 제공되지 않으면(함수 데코레이터를 사용하는 경우 등) SDK는 현재 활성 스팬에 주석을 답니다.
input_data
선택 사항 - JSON 직렬화 가능 유형 또는 딕셔너리 목록
JSON 직렬화 가능 유형(LLM 이외의 스팬용) 또는 딕셔너리 목록(형식: {"content": \"...\", \"role\": \"...\", \"tool_calls\": ..., \"tool_results\": ..., \"audio_parts\": ..., \"image_parts\": ...}) 중 하나. 여기서 "tool_calls"는 도구 호출 딕셔너리의 선택적 목록으로 필수 키는 "name", "arguments", 선택적 키는 "tool_id", "type"이며, "tool_results"는 함수 호출 시 사용할 도구 결과 딕셔너리의 선택적 목록으로 필수 키는 "result", 선택적 키는 "name", "tool_id", "type"입니다. "audio_parts""image_parts"는 멀티모달 스팬을 위한 미디어 딕셔너리의 선택적 목록으로 각각 필수 "mime_type""content"(인라인으로 전달되는 base64 인코딩 미디어) 또는 "attachment_key" 중 정확히 하나를 포함합니다. 참고: 임베딩 스팬은 예외적으로 문자열 또는 딕셔너리(또는 딕셔너리 목록, 형식: {"text": "..."})를 사용해야 합니다.
output_data
선택 사항 - JSON 직렬화 가능 유형 또는 딕셔너리 목록
JSON 직렬화 가능 유형(LLM 이외의 스팬용) 또는 딕셔너리 목록(형식: {"content": "...", "role": "...", "tool_calls": ..., "audio_parts": ..., "image_parts": ...}) 중 하나. 여기서 "tool_calls"는 함수 호출 시 사용할 도구 호출 딕셔너리의 선택적 목록으로 필수 키는 "name", "arguments", 선택적 키는 "tool_id", "type"입니다. "audio_parts""image_parts"는 멀티모달 스팬을 위한 미디어 딕셔너리의 선택적 목록으로 각각 필수 "mime_type""content"(인라인으로 전달되는 base64 인코딩 미디어) 또는 "attachment_key" 중 정확히 하나를 포함합니다. 참고: 검색 스팬은 예외적으로 문자열 또는 딕셔너리(또는 딕셔너리 목록, 형식: {"text": "...", "name": "...", "score": float, "id": "..."})를 사용해야 합니다.
tool_definitions
선택 사항 - 딕셔너리 목록
함수 호출 시 사용할 도구 정의 딕셔너리 목록입니다. 각 도구 정의에는 필수 "name": "..." 키와 선택적 "description": "...", "schema": {...} 키가 있어야 합니다.
metadata
선택 사항 - dictionary
스팬이 설명하는 입력 또는 출력 작업과 관련된 메타데이터 정보(model_temperature, max_tokens, top_k 등)를 사용자가 추가할 수 있는 JSON 직렬화 가능 키-값 쌍의 딕셔너리입니다.
metrics
선택 사항 - dictionary
스팬이 설명하는 작업과 관련된 메트릭(input_tokens, output_tokens, total_tokens, time_to_first_token 등)을 사용자가 추가할 수 있는 JSON 직렬화 가능 키와 숫자 값의 딕셔너리입니다. time_to_first_token의 단위는 초이며, 기본적으로 생성되는 duration 메트릭과 동일합니다.
tags
선택 사항 - dictionary
사용자가 스팬에 태그로 추가할 수 있는 JSON 직렬화 가능 키-값 쌍의 딕셔너리입니다. 예시 키: session, env, system, version. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
cost_tags
선택 사항 - 문자열 목록
생성된 LLM 비용 및 토큰 메트릭에 사용자 지정 태그로 전파할 태그 키 목록(tags로 이미 설정되었거나 이전에 동일한 스팬에 주석이 달린 태그)입니다. 기존 태그 키를 참조하지 않는 항목은 건너뜁니다. 자세한 내용은 비용 모니터링을 참조하세요.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import embedding, llm, retrieval, workflow

@llm(model_name="model_name", model_provider="model_provider")
def llm_call(prompt):
    resp = ... # llm call here
    LLMObs.annotate(
        span=None,
        input_data=[{"role": "user", "content": "Hello world!"}],
        output_data=[{"role": "assistant", "content": "How can I help?"}],
        metadata={"temperature": 0, "max_tokens": 200},
        metrics={"input_tokens": 4, "output_tokens": 6, "total_tokens": 10},
        tags={"host": "host_name"},
    )
    return resp

@workflow
def extract_data(document):
    resp = llm_call(document)
    LLMObs.annotate(
        input_data=document,
        output_data=resp,
        tags={"host": "host_name"},
    )
    return resp

@embedding(model_name="text-embedding-3", model_provider="openai")
def perform_embedding():
    ... # user application logic
    LLMObs.annotate(
        span=None,
        input_data={"text": "Hello world!"},
        output_data=[0.0023064255, -0.009327292, ...],
        metrics={"input_tokens": 4},
        tags={"host": "host_name"},
    )
    return

@retrieval(name="get_relevant_docs")
def similarity_search():
    ... # user application logic
    LLMObs.annotate(
        span=None,
        input_data="Hello world!",
        output_data=[{"text": "Hello world is ...", "name": "Hello, World! program", "id": "document_id", "score": 0.9893}],
        tags={"host": "host_name"},
    )
    return

@llm(model_name="gpt-realtime", model_provider="openai")
def voice_turn(user_audio_bytes):
    import base64
    resp = ... # multimodal (audio) llm call here
    LLMObs.annotate(
        span=None,
        input_data=[
            {
                "role": "user",
                "content": "Hey, how are you?",  # transcript of the input audio
                "audio_parts": [
                    {"mime_type": "audio/wav", "content": base64.b64encode(user_audio_bytes).decode("utf-8")}
                ],
            }
        ],
        output_data=[
            {
                "role": "assistant",
                "content": "Hey! I'm doing great, thanks for asking. How about you?",
                "audio_parts": [
                    {"mime_type": "audio/wav", "content": base64.b64encode(resp.audio_bytes).decode("utf-8")}
                ],
            }
        ],
    )
    return resp

@llm(model_name="gpt-4o", model_provider="openai")
def describe_image(image_bytes):
    import base64
    resp = ... # multimodal (vision) llm call here
    LLMObs.annotate(
        span=None,
        input_data=[
            {
                "role": "user",
                "content": "What is in this image?",
                "image_parts": [
                    {"mime_type": "image/png", "content": base64.b64encode(image_bytes).decode("utf-8")}
                ],
            }
        ],
        output_data=[{"role": "assistant", "content": "The image shows a golden retriever puppy."}],
    )
    return resp

audio_parts 또는 image_parts로 주석이 달린 메시지는 트레이스 보기에서 인라인 오디오 플레이어 및 이미지로 렌더링됩니다.

Agent Observability 트레이스 보기의 LLM 스팬입니다. USER의 입력 메시지는 'Hey, how are you?'라는 전사본이 포함된 인라인 오디오 플레이어를 보여주고, ASSISTANT의 출력 메시지는 'Click to play audio' 제어 기능과 'Hey! I'm doing great, thanks for asking. How about you?'라는 전사본을 표시합니다.
Agent Observability 트레이스 보기의 LLM 스팬입니다. USER 입력 메시지는 'What is in this image?'라는 프롬프트와 함께 검은 강아지 사진이 인라인으로 포함되어 있으며, ASSISTANT 출력 메시지는 이를 나무 표면 위의 검은 래브라도 리트리버 강아지로 설명합니다.

SDK는 입력, 출력 및 메타데이터로 스팬에 주석을 달기 위해 llmobs.annotate() 메서드를 제공합니다.

LLMObs.annotate() 메서드는 다음 인수를 허용합니다.

span
선택 사항 - Span - 기본값: 현재 활성 스팬
주석을 달 스팬입니다. span이 제공되지 않으면(함수 래퍼를 사용할 때와 같이) SDK는 현재 활성 스팬에 주석을 답니다.
annotationOptions
필수 - object
스팬에 주석을 달기 위한 다양한 유형의 데이터 객체입니다.

annotationOptions 객체에는 다음 항목이 포함될 수 있습니다.

inputData
선택 사항 - JSON 직렬화 가능 유형 또는 객체 목록
JSON 직렬화 가능 유형(LLM 이외의 스팬용) 또는 딕셔너리 목록(형식: {role: \"...\", content: \"...\", audioParts: [...], imageParts: [...]}, LLM 스팬용)입니다. audioPartsimageParts는 멀티모달 스팬을 위한 미디어 객체의 선택적 목록으로 각각 필수 mimeTypecontent(인라인으로 전달되는 base64 인코딩 미디어), attachmentKey 중 정확히 하나를 포함합니다. 참고: 임베딩 스팬은 예외적으로 문자열 또는 객체(또는 객체 목록, 형식: {text: "..."})를 사용해야 합니다.
outputData
선택 사항 - JSON 직렬화 가능 유형 또는 객체 목록
JSON 직렬화 가능 유형(LLM 이외의 스팬용) 또는 객체 목록(형식: {role: "...", content: "...", audioParts: [...], imageParts: [...]}, LLM 스팬용)입니다. audioPartsimageParts는 멀티모달 스팬을 위한 미디어 객체의 선택적 목록으로 각각 필수 mimeTypecontent(인라인으로 전달되는 base64 인코딩 미디어), attachmentKey 중 정확히 하나를 포함합니다. 참고: 검색 스팬은 예외적으로 문자열 또는 객체(또는 객체 목록, 형식: {text: "...", name: "...", score: number, id: "..."})를 사용해야 합니다.
metadata
선택 사항 - 객체
스팬이 설명하는 입력 또는 출력 작업과 관련된 메타데이터 정보(model_temperature, max_tokens, top_k 등)를 사용자가 추가할 수 있는 JSON 직렬화 가능 키-값 쌍 객체입니다.
metrics
선택 사항 - 객체
스팬이 설명하는 작업과 관련된 메트릭(input_tokens, output_tokens, total_tokens 등)을 사용자가 추가할 수 있는 JSON 직렬화 가능 키와 숫자 값의 객체입니다.
tags
선택 사항 - 객체
스팬의 컨텍스트와 관련된 태그(session, environment, system, versioning 등)를 사용자가 추가할 수 있는 JSON 직렬화 가능 키-값 쌍 객체입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
costTags
선택 사항 - 문자열 배열
생성된 LLM 비용 및 토큰 메트릭에 사용자 지정 태그로 전파할 태그 키 목록(tags로 이미 설정되었거나 이전에 동일한 스팬에 주석이 달린 태그)입니다. 기존 태그 키를 참조하지 않는 항목은 건너뜁니다. 자세한 내용은 비용 모니터링을 참조하세요.

예시

function llmCall (prompt) {
  const completion = ... // user application logic to invoke LLM
  llmobs.annotate({
    inputData: [{ role: "user", content: "Hello world!" }],
    outputData: [{ role: "assistant", content: "How can I help?" }],
    metadata: { temperature: 0, max_tokens: 200 },
    metrics: { input_tokens: 4, output_tokens: 6, total_tokens: 10 },
    tags: { host: "host_name" }
  })
  return completion
}
llmCall = llmobs.wrap({ kind:'llm', modelName: 'modelName', modelProvider: 'modelProvider' }, llmCall)

function extractData (document) {
  const resp = llmCall(document)
  llmobs.annotate({
    inputData: document,
    outputData: resp,
    tags: { host: "host_name" }
  })
  return resp
}
extractData = llmobs.wrap({ kind: 'workflow' }, extractData)

function performEmbedding () {
  ... // user application logic
  llmobs.annotate(
    undefined, { // this can be set to undefined or left out entirely
      inputData: { text: "Hello world!" },
      outputData: [0.0023064255, -0.009327292, ...],
      metrics: { input_tokens: 4 },
      tags: { host: "host_name" }
    }
  )
}
performEmbedding = llmobs.wrap({ kind: 'embedding', modelName: 'text-embedding-3', modelProvider: 'openai' }, performEmbedding)

function similaritySearch () {
  ... // user application logic
  llmobs.annotate(undefined, {
    inputData: "Hello world!",
    outputData: [{ text: "Hello world is ...", name: "Hello, World! program", id: "document_id", score: 0.9893 }],
    tags: { host: "host_name" }
  })
  return
}
similaritySearch = llmobs.wrap({ kind: 'retrieval', name: 'getRelevantDocs' }, similaritySearch)

function voiceTurn (userAudioBytes) {
  const resp = ... // multimodal (audio) llm call here
  llmobs.annotate({
    inputData: [
      {
        role: "user",
        content: "Hey, how are you?", // transcript of the input audio
        audioParts: [{ mimeType: "audio/wav", content: userAudioBytes.toString("base64") }]
      }
    ],
    outputData: [
      {
        role: "assistant",
        content: "Hey! I'm doing great, thanks for asking. How about you?",
        audioParts: [{ mimeType: "audio/wav", content: resp.audioBuffer.toString("base64") }]
      }
    ]
  })
  return resp
}
voiceTurn = llmobs.wrap({ kind: 'llm', modelName: 'gpt-audio', modelProvider: 'openai' }, voiceTurn)

function describeImage (imageBytes) {
  const resp = ... // multimodal (vision) llm call here
  llmobs.annotate({
    inputData: [
      {
        role: "user",
        content: "What is in this image?",
        imageParts: [{ mimeType: "image/png", content: imageBytes.toString("base64") }]
      }
    ],
    outputData: [{ role: "assistant", content: "The image shows a golden retriever puppy." }]
  })
  return resp
}
describeImage = llmobs.wrap({ kind: 'llm', modelName: 'gpt-4o', modelProvider: 'openai' }, describeImage)

audioParts 또는 imageParts로 주석이 달린 메시지는 트레이스 보기에서 인라인 오디오 플레이어 및 이미지로 렌더링됩니다.

Agent Observability 트레이스 보기의 LLM 스팬입니다. USER의 입력 메시지는 'Hey, how are you?'라는 전사본이 포함된 인라인 오디오 플레이어를 보여주고, ASSISTANT의 출력 메시지는 'Click to play audio' 제어 기능과 'Hey! I'm doing great, thanks for asking. How about you?'라는 전사본을 표시합니다.
Agent Observability 트레이스 보기의 LLM 스팬입니다. USER 입력 메시지는 'What is in this image?'라는 프롬프트와 함께 검은 강아지 사진이 인라인으로 포함되어 있으며, ASSISTANT 출력 메시지는 이를 나무 표면 위의 검은 래브라도 리트리버 강아지로 설명합니다.

OpenAI 오디오 채팅 완료의 경우, audioPartsDatadog의 LLM 통합을 통해 자동으로 캡처되므로 수동 주석이 필요하지 않습니다. audioParts와 달리 imageParts는 현재 자동으로 캡처되지 않으므로 수동으로 주석을 달아야 합니다. 향후 릴리스에서 자동 캡처가 지원될 예정입니다.

SDK는 입력, 출력, 메트릭 및 메타데이터를 사용해 스팬에 주석을 다는 여러 메서드를 제공합니다.

입력 및 출력에 주석 달기

LLMObsSpan 인터페이스의 annotateIO() 멤버 메서드를 사용하여 LLMObsSpan에 구조화된 입력 데이터와 출력 데이터를 추가할 수 있습니다. 여기에는 선택적 인수와 LLM 메시지 객체가 포함됩니다.

인수

인수가 null이거나 비어 있으면 아무 일도 발생하지 않습니다. 예를 들어 inputData가 비어 있지 않은 문자열이고 outputData가 null인 경우에는 inputData만 기록됩니다.

inputData
선택 사항 - String 또는 List<LLMObs.LLMMessage>
LLM 이외의 스팬의 경우 문자열, LLM 스팬의 경우 LLMObs.LLMMessage 목록입니다.
outputData
선택 사항 - String 또는 List<LLMObs.LLMMessage>
LLM 이외의 스팬의 경우 문자열, LLM 스팬의 경우 LLMObs.LLMMessage 목록입니다.

LLM 메시지

LLM 스팬은 LLMObs.LLMMessage 객체를 사용하여 LLM 메시지로 주석을 달아야 합니다.

LLMObs.LLMMessage 객체는 LLMObs.LLMMessage.from()을 호출하여 생성할 수 있으며, 다음 인수를 사용합니다.

role
필수 - String
메시지 작성자의 역할을 설명하는 문자열입니다.
content
필수 - String
메시지의 내용을 포함하는 문자열입니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String systemMessage = "You are a helpful assistant";
    Response chatResponse = ... // user application logic to invoke LLM
    llmSpan.annotateIO(
      Arrays.asList(
        LLMObs.LLMMessage.from("user", userInput),
        LLMObs.LLMMessage.from("system", systemMessage)
      ),
      Arrays.asList(
        LLMObs.LLMMessage.from(chatResponse.role, chatResponse.content)
      )
    );
    llmSpan.finish();
    return chatResponse;
  }
}

메트릭 추가

메트릭 일괄 추가

LLMObsSpan 인터페이스의 setMetrics() 멤버 메서드는 여러 메트릭을 한 번에 추가하기 위해 다음 인수를 허용합니다.

인수
metrics
필수 - Map<String, Number>
스팬이 설명하는 작업과 관련된 메트릭(예: input_tokens, output_tokens, total_tokens)을 기록하기 위해 사용자가 추가할 수 있는 JSON 직렬화 가능 키와 숫자 값의 맵입니다.

단일 메트릭 추가

LLMObsSpan 인터페이스의 setMetric() 멤버 메서드는 단일 메트릭을 추가하기 위해 다음 인수를 허용합니다.

인수
key
필수 - CharSequence
메트릭의 이름입니다.
value
필수 - int, long 또는 double
메트릭의 값입니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = ... // user application logic to invoke LLM
    llmSpan.setMetrics(Map.of(
      "input_tokens", 617,
      "output_tokens", 338,
      "time_per_output_token", 0.1773
    ));
    llmSpan.setMetric("total_tokens", 955);
    llmSpan.setMetric("time_to_first_token", 0.23);
    llmSpan.finish();
    return chatResponse;
  }
}

태그 추가

태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.

태그 일괄 추가

LLMObsSpan 인터페이스의 setTags() 멤버 메서드는 여러 태그를 한 번에 추가하기 위해 다음 인수를 허용합니다.

인수
tags
필수 - Map<String, Object>
스팬의 컨텍스트를 설명하기 위해 사용자가 추가할 수 있는 JSON 직렬화 가능 키-값 쌍의 맵입니다(예: session, environment, system, version).

단일 태그 추가

LLMObsSpan 인터페이스의 setTag() 멤버 메서드는 단일 태그를 추가하기 위해 다음 인수를 허용합니다.

인수
key
필수 - String
태그의 키입니다.
value
필수 - int, long, double, boolean, 또는 String
태그의 값입니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = ... // user application logic to invoke LLM
    llmSpan.setTags(Map.of(
      "chat_source", "web",
      "users_in_chat", 3
    ));
    llmSpan.setTag("is_premium_user", true);
    llmSpan.finish();
    return chatResponse;
  }
}

오류에 주석 달기

LLMObsSpan 인터페이스의 addThrowable() 멤버 메서드는 스택 트레이스가 포함된 Throwable을 첨부하기 위해 다음 인수를 허용합니다.

인수
throwable
필수 - Throwable
발생한 Throwable/예외입니다.

오류 메시지 추가하기

LLMObsSpan 인터페이스의 setErrorMessage() 멤버 메서드는 오류 문자열을 첨부하기 위해 다음 인수를 허용합니다.

인수
errorMessage
필수 - String
오류 메시지입니다.

오류 플래그 설정하기

LLMObsSpan 인터페이스의 setError() 멤버 메서드는 작업에 오류가 발생했음을 표시하기 위해 다음 인수를 허용합니다.

인수
error
필수 - boolean
스팬에 오류가 발생한 경우 true입니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = "N/A";
    try {
      chatResponse = ... // user application logic to invoke LLM
    } catch (Exception e) {
      llmSpan.addThrowable(e);
      throw new RuntimeException(e);
    } finally {
      llmSpan.finish();
    }
    return chatResponse;
  }
}

메타데이터에 주석 달기

LLMObsSpan 인터페이스의 setMetadata() 멤버 메서드는 다음 인수를 허용합니다.

metadata
필수 - Map<String, Object>
스팬이 설명하는 입력 또는 출력 작업과 관련된 메타데이터를 포함하는 JSON 직렬화 가능 키-값 쌍의 맵입니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    llmSpan.setMetadata(
      Map.of(
        "temperature", 0.5,
        "is_premium_member", true,
        "class", "e1"
      )
    );
    String chatResponse = ... // user application logic to invoke LLM
    return chatResponse;
  }
}

자동 계측된 스팬에 주석 달기

SDK의 LLMObs.annotation_context() 메서드는 주석 컨텍스트가 활성화된 동안 시작되는 모든 자동 계측된 스팬을 수정하는 데 사용할 수 있는 컨텍스트 관리자를 반환합니다.

LLMObs.annotation_context() 메서드는 다음 인수를 허용합니다.

name
선택 사항 - str
주석 컨텍스트 내에서 시작된 자동 계측된 모든 스팬의 이름을 재정의하는 이름입니다.
prompt
선택 사항 - dictionary
LLM 호출에 사용된 프롬프트를 나타내는 딕셔너리입니다. 전체 스키마 및 지원되는 키의 경우 프롬프트 객체 설명서를 참조하세요. Prompt 객체를 ddtrace.llmobs.utils에서 가져와 prompt 인수로 전달할 수도 있습니다. 참고: 이 인수는 LLM 스팬에만 적용됩니다.
tags
선택 사항 - dictionary
사용자가 스팬에 태그로 추가할 수 있는 JSON 직렬화 가능 키-값 쌍의 딕셔너리입니다. 예시 키: session, env, system, version. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
cost_tags
선택 사항 - 문자열 목록
생성된 LLM 비용 및 토큰 메트릭에 사용자 지정 태그로 전파할 태그 키 목록입니다. 각 항목은 스팬 시작 시 tags에 존재하는 키를 참조해야 합니다(동일한 컨텍스트 또는 상위 컨텍스트에 제공됨). LLMObs.annotate()로 나중에 추가된 태그 키는 보존되지 않습니다. 자세한 내용은 비용 모니터링을 참조하세요.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import workflow

@workflow
def rag_workflow(user_question):
    context_str = retrieve_documents(user_question).join(" ")

    with LLMObs.annotation_context(
        prompt = Prompt(
            id="chatbot_prompt",
            version="1.0.0",
            template="Please answer the question using the provided context: {{question}}\n\nContext:\n{{context}}",
            variables={
                "question": user_question,
                "context": context_str,
            }
        ),
        tags = {
            "retrieval_strategy": "semantic_similarity"
        },
        name = "augmented_generation"
    ):
        completion = openai_client.chat.completions.create(...)
    return completion.choices[0].message.content

SDK의 llmobs.annotationContext()는 콜백 함수 범위 내에서 시작된 모든 자동 계측된 스팬을 수정하는 데 사용할 수 있는 콜백 함수를 허용합니다.

llmobs.annotationContext() 메서드는 첫 번째 인수로 다음 옵션을 허용합니다.

name
선택 사항 - str
주석 컨텍스트 내에서 시작된 자동 계측된 모든 스팬의 이름을 재정의하는 이름입니다.
tags
선택 사항 - object
사용자가 스팬에 태그로 추가할 수 있는 JSON 직렬화 가능 키-값 쌍의 객체입니다. 예시 키: session, env, system, version. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
costTags
선택 사항 - 문자열 배열
생성된 LLM 비용 및 토큰 메트릭에 사용자 지정 태그로 전파할 태그 키 목록입니다. 각 항목은 스팬 시작 시 tags에 존재하는 키를 참조해야 합니다(동일한 컨텍스트 또는 상위 컨텍스트에 제공됨). llmobs.annotate()로 나중에 추가된 태그 키는 보존되지 않습니다. 자세한 내용은 비용 모니터링을 참조하세요.

예시

const { llmobs } = require('dd-trace');

function ragWorkflow(userQuestion) {
    const contextStr = retrieveDocuments(userQuestion).join(" ");

    const completion = await llmobs.annotationContext({
      tags: {
        retrieval_strategy: "semantic_similarity"
      },
      name: "augmented_generation"
    }, async () => {
      const completion = await openai_client.chat.completions.create(...);
      return completion.choices[0].message.content;
    });
}

프롬프트 추적

LLM 스팬에 구조화된 프롬프트 메타데이터를 첨부하여 결과를 재현하고, 변경 사항을 감사하며, 버전 간 프롬프트 성능을 비교할 수 있습니다. 템플릿을 사용할 때 Agent Observability는 템플릿 콘텐츠 변경에 따라 버전 추적 기능도 제공합니다.

LLM 호출 전에 프롬프트 메타데이터를 첨부하려면 LLMObs.annotation_context(prompt=...)를 사용합니다. 스팬 주석에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

인수

prompt
필수 - dictionary
아래의 프롬프트 스키마를 따르는 타입 지정 딕셔너리입니다.

지원되는 키:

  • id (str): 이 프롬프트의 논리적 식별자입니다. ml_app마다 고유해야 합니다. 기본값은 {ml_app}-unnamed_prompt입니다.
  • version (str): 프롬프트의 버전 태그입니다(예: “1.0.0”). 자세한 내용은 버전 추적을 참조하세요.
  • variables (Dict[str, str]): 템플릿 자리표시자를 채우는 데 사용되는 변수입니다.
  • template (str): 자리표시자가 포함된 템플릿 문자열입니다(예: "Translate {{text}} to {{lang}}").
  • chat_template (List[Message]): 다중 메시지 템플릿 형식입니다. { "role": "<role>", "content": "<template string with placeholders>" } 객체 목록을 제공합니다.
  • tags (Dict[str, str]): 프롬프트 실행에 첨부할 태그입니다.
  • rag_context_variables (List[str]): 실제/컨텍스트 콘텐츠를 포함하는 변수 키입니다. 환각 탐지에 사용됩니다.
  • rag_query_variables (List[str]): 사용자 쿼리를 포함하는 변수 키입니다. 환각 탐지에 사용됩니다.

예: 단일 템플릿 프롬프트

from ddtrace.llmobs import LLMObs

def answer_question(text):
    # Attach prompt metadata to the upcoming LLM span using LLMObs.annotation_context()
    with LLMObs.annotation_context(prompt={
        "id": "translation-template",
        "version": "1.0.0",
        "chat_template": [{"role": "user", "content": "Translate to {{lang}}: {{text}}"}],
        "variables": {"lang": "fr", "text": text},
        "tags": {"team": "nlp"}
    }):
        # Example provider call (replace with your client)
        completion = openai_client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": f"Translate to fr: {text}"}]
        )
    return completion

예: LangChain 프롬프트 템플릿

LangChain의 프롬프트 템플릿 기능을 자동 계측과 함께 사용하는 경우, 템플릿을 의미 있는 이름의 변수에 할당하세요. 자동 계측은 이러한 변수 이름을 사용하여 프롬프트를 식별합니다.

# "translation_template" will be used to identify the template in Datadog
translation_template = PromptTemplate.from_template("Translate {text} to {language}")
chain = translation_template | llm

LLM 호출 전에 프롬프트 메타데이터를 첨부하려면 llmobs.annotationContext({ prompt: ... }, () => { ... })를 사용합니다. 스팬 주석에 대한 자세한 내용은 스팬 강화하기를 참조하세요.

인수

prompt
필수 - object
아래의 프롬프트 스키마를 따르는 객체입니다.

지원되는 속성:

  • id (string): 이 프롬프트의 논리적 식별자입니다. ml_app마다 고유해야 합니다. 기본값은 {ml_app}-unnamed_prompt입니다.
  • version (string): 프롬프트의 버전 태그입니다(예: “1.0.0”). 자세한 내용은 버전 추적을 참조하세요.
  • variables (Record<string, string>): 템플릿 자리표시자를 채우는 데 사용되는 변수입니다.
  • template (string | List[Message]): 자리표시자를 포함하는 템플릿 문자열 또는 메시지 목록입니다(예: "Translate {{text}} to {{lang}}"). Alternatively, a list of { "role": "<role>", "content": "<template string with placeholders>" } 형식의 객체 목록입니다.
  • tags (Record<string, string>): 프롬프트 실행에 첨부할 태그입니다.
  • contextVariables (string[]): 실제/컨텍스트 콘텐츠를 포함하는 변수 키입니다. 환각 탐지에 사용됩니다.
  • queryVariables (string[]): 사용자 쿼리를 포함하는 변수 키입니다. 환각 탐지에 사용됩니다.

예: 단일 템플릿 프롬프트

const { llmobs } = require('dd-trace');

function answerQuestion(text) {
    // Attach prompt metadata to the upcoming LLM span using LLMObs.annotation_context()
    return llmobs.annotationContext({
      prompt: {
        id: "translation-template",
        version: "1.0.0",
        chat_template: [{"role": "user", "content": "Translate to {{lang}}: {{text}}"}],
        variables: {"lang": "fr", "text": text},
        tags: {"team": "nlp"}
      }
    }, () => {
      // Example provider call (replace with your client)
      return openaiClient.chat.completions.create({
          model: "gpt-4o",
          messages: [{"role": "user", "content": f"Translate to fr: {text}"}]
        });
    });
}

참고

  • 프롬프트 주석 기능은 LLM 스팬에서만 사용할 수 있습니다.
  • 올바른 LLM 스팬에 적용되도록 공급자 호출 직전에 주석을 추가하세요.
  • 애플리케이션 내에서 서로 다른 프롬프트를 구분하기 위해 고유한 프롬프트 id를 사용하세요.
  • 템플릿을 정적으로 유지하려면 자리표시자 구문(예: {{variable_name}})를 사용하고 variables 섹션에서 동적 콘텐츠를 정의하세요.
  • 블록 내에서 여러 자동 계측 LLM 호출을 위해 주석 컨텍스트를 사용하여 호출 간에 동일한 프롬프트 메타데이터를 적용하세요. 자동 계측된 스팬 주석 달기를 참조하세요.

버전 추적

Agent Observability는 명시적인 버전이 지정되지 않은 경우 프롬프트에 대해 자동 버전 관리를 제공합니다. 프롬프트 메타데이터에 template 또는 chat_template을 제공하고 version 태그를 지정하지 않으면 시스템은 템플릿 콘텐츠의 해시를 계산하여 자동으로 버전을 생성합니다. version 태그를 지정하면 Agent Observability는 자동 생성 버전 대신 사용자가 지정한 버전 레이블을 사용합니다.

버전 관리 시스템은 다음과 같이 작동합니다.

  • 자동 버전 관리: version 태그가 지정되지 않으면 Agent Observability는 template 또는 chat_template 콘텐츠의 해시를 계산하여 숫자 버전 식별자를 자동 생성합니다.
  • 수동 버전 관리: version 태그를 지정하면 Agent Observability는 사용자가 지정한 버전 레이블을 그대로 사용합니다.
  • 버전 기록: 자동 생성 버전과 수동 지정 버전 모두 버전 기록에 유지되어 시간 경과에 따른 프롬프트 변화를 추적할 수 있습니다.

이렇게 하면 템플릿 내용 변경에 따른 자동 버전 관리에 의존할 수도 있고, 직접 버전 라벨을 지정하여 버전 관리를 완전히 제어할 수도 있는 유연성을 제공합니다.

MCP 인텐트 캡처

MCP 도구가 호출된 이유를 파악하려면 MCP 서버에서 인텐트 캡처를 활성화하세요. 활성화되면 SDK는 호출 모델에 도구를 호출한 이유를 설명하도록 요청하는 인수를 모든 MCP 서버 도구에 추가합니다. 인텐트는 도구 스팬에 기록되므로 도구 정의 및 설명을 개선하는 데 도움이 됩니다.

다음의 DD_MCP_CAPTURE_INTENT 환경 변수로 MCP 인텐트 캡처를 활성화하세요.

DD_MCP_CAPTURE_INTENT=1 DD_SITE=<YOUR_DATADOG_SITE> DD_API_KEY=<YOUR_API_KEY> DD_LLMOBS_ENABLED=1 \
DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME> ddtrace-run <YOUR_APP_STARTUP_COMMAND>

또는 capture_intentLLMObs.enable() 파라미터를 사용하여 프로그래밍 방식으로 활성화하세요.

from ddtrace.llmobs import LLMObs
LLMObs.enable(
  ml_app="<YOUR_ML_APP_NAME>",
  capture_intent=True,
)

비용 모니터링

LLM/임베딩 스팬에 토큰 메트릭(자동 비용 추적용) 또는 비용 메트릭(수동 비용 추적용)을 연결합니다. 토큰 메트릭은 Datadog이 제공업체 가격을 기반으로 비용을 계산할 수 있게 해주며, 비용 메트릭을 통해 맞춤형 모델이나 지원되지 않는 모델을 사용할 때 직접 가격 정보를 제공할 수 있습니다. 자세한 내용은 비용을 참조하세요.

자동 계측을 사용하는 경우, 토큰 및 비용 메트릭은 스팬에 자동으로 표시됩니다. 수동으로 계측하는 경우, 아래 지침을 따릅니다.

이 문맥에서 "토큰 메트릭" 및 "비용 메트릭"은 metrics 파라미터( LLMObs.annotate() 메서드의 파라미터)를 통해 스팬에 첨부하는 숫자형 키-값 쌍을 의미합니다. 이는 Datadog 플랫폼 Agent Observability 메트릭과는 별개입니다. 인지되는 키(예: input_tokens, output_tokens, input_costoutput_cost)의 경우 Datadog은 이러한 스팬 속성을 사용해 해당 플랫폼 메트릭(예: ml_obs.span.llm.input.cost)을 생성하며, 생성된 메트릭은 대시보드와 모니터에서 사용할 수 있습니다.

사용 사례: 일반 모델 제공업체 사용하기

Datadog은 OpenAI, Azure OpenAI, Anthropic, Google Gemini 등 일반 모델 제공업체를 지원합니다. 이러한 제공업체를 사용할 때는 LLM 요청에 모델 이름, 모델 제공업체 및 토큰 사용량에만 주석을 달면 됩니다. Datadog은 제공업체 가격을 기반으로 예상 비용을 자동 계산합니다.

각 토큰이 무엇을 나타내는지와 Datadog에서 이를 계산하는 방법에 대한 자세한 내용은 토큰 수 계산 방법을 참조하세요.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="gpt-5.1", model_provider="openai")
def llm_call(prompt):
    resp = ... # llm call here
    # Annotate token metrics
    LLMObs.annotate(
        metrics={
          "input_tokens": 50,
          "output_tokens": 120,
          "total_tokens": 170,
          "non_cached_input_tokens": 13,  # optional
          "cache_read_input_tokens": 22,  # optional
          "cache_write_input_tokens": 15, # optional
        },
    )
    return resp
function llmCall (prompt) {
  const resp = ... // llm call here
  llmobs.annotate({
    metrics: {
      input_tokens: 50,
      output_tokens: 120,
      total_tokens: 170,
      non_cached_input_tokens: 13,  // optional
      cache_read_input_tokens: 22,  // optional
      cache_write_input_tokens: 15  // optional
    }
  })
  return resp
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'gpt-5.1', modelProvider: 'openai' }, llmCall)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;
import java.util.Map;

public class MyJavaClass {
  public String llmCall(String prompt) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("llm-call", "gpt-5.1", "openai", null, null);
    String resp = ... // llm call here
    llmSpan.setMetrics(Map.of(
      "input_tokens", 50,
      "output_tokens", 120,
      "total_tokens", 170,
      "non_cached_input_tokens", 13,  // optional
      "cache_read_input_tokens", 22,  // optional
      "cache_write_input_tokens", 15  // optional
    ));
    llmSpan.finish();
    return resp;
  }
}

사용 사례: 사용자 지정 모델 사용하기

사용자 지정 또는 지원되지 않는 모델의 경우, 비용 데이터를 달러 단위로 스팬에 수동으로 주석을 달아야 합니다.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="custom_model", model_provider="model_provider")
def llm_call(prompt):
    resp = ... # llm call here
    # Annotate cost metrics
    LLMObs.annotate(
        metrics={
          "input_cost": 3,
          "output_cost": 7,
          "total_cost": 10,
          "non_cached_input_cost": 1,    # optional
          "cache_read_input_cost": 0.6,  # optional
          "cache_write_input_cost": 1.4, # optional
        },
    )
    return resp
function llmCall (prompt) {
  const resp = ... // llm call here
  llmobs.annotate({
    metrics: {
      input_cost: 3,
      output_cost: 7,
      total_cost: 10,
      non_cached_input_cost: 1,    // optional
      cache_read_input_cost: 0.6,  // optional
      cache_write_input_cost: 1.4  // optional
    }
  })
  return resp
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'custom_model', modelProvider: 'model_provider' }, llmCall)
import datadog.trace.api.llmobs.LLMObs;
import datadog.trace.api.llmobs.LLMObsSpan;
import java.util.Map;

public class MyJavaClass {
  public String llmCall(String prompt) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("llm-call", "custom_model", "model_provider", null, null);
    String resp = ... // llm call here
    llmSpan.setMetrics(Map.of(
      "input_cost", 3,
      "output_cost", 7,
      "total_cost", 10,
      "non_cached_input_cost", 1,    // optional
      "cache_read_input_cost", 0.6,  // optional
      "cache_write_input_cost", 1.4  // optional
    ));
    llmSpan.finish();
    return resp;
  }
}

비용 및 토큰 메트릭에 사용자 지정 태그 추가하기

기본적으로 LLM 비용 및 토큰 메트릭에는 model_name, model_provider, ml_app과 같은 고정된 OOTB 태그 세트가 포함됩니다. 팀, 고객 또는 기능과 같이 애플리케이션에 특정한 속성별로 LLM 지출을 분류하려면 스팬의 기존 태그 키의 하위 집합을 해당 메트릭에 사용자 지정 태그로 전파하도록 표시하세요. 사용자 지정 대시보드 및 모니터와 같은 예시 사용 사례는 비용 및 토큰 메트릭의 사용자 지정 태그를 참조하세요.

각 항목은 문자열이어야 하며, 주석이 적용되는 시점에 스팬의 tags 파라미터를 통해 이미 제공된 키를 참조해야 합니다. 단일 스팬에 주석을 달 때 키는 동일한 주석 호출 내의 tags를 통해 제공되거나 동일한 스팬에 대한 이전 주석에서 제공될 수 있습니다. 주석 컨텍스트를 사용할 때는 스팬 시작 시 tags에 존재하는 키만 유효하며, 개별 스팬 주석을 통해 나중에 추가된 키는 보존되지 않습니다. 기존 태그 키를 참조하지 않는 항목은 건너뜁니다.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="gpt-5.1", model_provider="openai")
def llm_call(prompt):
    resp = ... # llm call here
    LLMObs.annotate(
        metrics={"input_tokens": 50, "output_tokens": 120, "total_tokens": 170},
        tags={"team": "nlp", "customer_tier": "enterprise", "host": "host_name"},
        cost_tags=["team", "customer_tier"],
    )
    return resp
function llmCall (prompt) {
  const resp = ... // llm call here
  llmobs.annotate({
    metrics: { input_tokens: 50, output_tokens: 120, total_tokens: 170 },
    tags: { team: 'nlp', customer_tier: 'enterprise', host: 'host_name' },
    costTags: ['team', 'customer_tier']
  })
  return resp
}
llmCall = llmobs.wrap({ kind: 'llm', modelName: 'gpt-5.1', modelProvider: 'openai' }, llmCall)

이 방식을 통해 주석 컨텍스트를 거쳐 태그를 전파하여 컨텍스트 내에서 시작된 모든 자동 계측 스팬에 적용할 수도 있습니다.

with LLMObs.annotation_context(
    tags={"team": "nlp", "customer_tier": "enterprise"},
    cost_tags=["team", "customer_tier"],
):
    resp = ... # llm call here
llmobs.annotationContext({
  tags: { team: 'nlp', customer_tier: 'enterprise' },
  costTags: ['team', 'customer_tier']
}, () => {
  const resp = ... // llm call here
})

평가

Agent Observability SDK는 평가를 Datadog에 내보내고 제출할 수 있는 메서드를 제공합니다.

풍부한 결과 메타데이터를 갖춘 재사용 가능한 클래스 기반 평가기(BaseEvaluator, BaseSummaryEvaluator)를 풍부한 결과 메타데이터와 함께 사용하려면 Evaluation Developer Guide를 참조하십시오.

평가는 단일 스팬에 연결해야 합니다. 대상 스팬은 다음 두 가지 방법 중 하나로 식별할 수 있습니다.

  • 태그 기반 연결 - 고유 키-값 태그 쌍을 단일 스팬에 설정하여 평가를 연결합니다. 태그 키-값 쌍이 여러 스팬과 일치하거나 일치하는 스팬이 없는 경우 평가 연결에 실패합니다.
  • 직접 스팬 참조 - 스팬의 고유 트레이스 ID와 스팬 ID 조합을 사용하여 평가를 연결합니다.

스팬 내보내기

LLMObs.export_span()을 사용하여 스팬에서 스팬 컨텍스트를 추출할 수 있습니다. 이 메서드는 평가를 해당 스팬과 연결할 때 유용합니다.

인수

LLMObs.export_span() 메서드는 다음 인수를 허용합니다.

span
선택 사항 - Span
스팬 컨텍스트(스팬 ID와 트레이스 ID)를 추출할 스팬입니다. 지정하지 않으면(함수 데코레이터를 사용할 때와 같이) SDK는 현재 활성 스팬을 내보냅니다.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call():
    completion = ... # user application logic to invoke LLM
    span_context = LLMObs.export_span(span=None)
    return completion

llmobs.exportSpan()을 사용하여 스팬에서 스팬 컨텍스트를 추출할 수 있습니다. 이 방법을 사용하여 평가를 해당 스팬과 연결해야 합니다.

인수

llmobs.exportSpan() 메서드는 다음 인수를 허용합니다.

span
선택 사항 - Span
스팬 컨텍스트(스팬 ID와 트레이스 ID)를 추출할 스팬입니다. 제공하지 않으면(함수 래퍼를 사용할 때와 같이) SDK는 현재 활성 스팬을 내보냅니다.

예시

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

평가 제출하기

LLMObs.submit_evaluation()을 사용하여 주어진 스팬과 연결된 사용자 지정 평가를 제출할 수 있습니다.

LLMObs.submit_evaluation_for 는 더 이상 사용되지 않으며 ddtrace의 다음 주요 버전(4.0)에서 제거될 예정입니다. 마이그레이션하려면 LLMObs.submit_evaluation_for 호출의 이름을 LLMObs.submit_evaluation.

참고: 사용자 지정 평가는 사용자가 구현하고 호스팅하는 평가자입니다. Datadog이 내장 평가기를 사용해 자동으로 계산하는 기본 제공 평가와는 다릅니다. 애플리케이션용 기본 제공 평가를 구성하려면 Datadog의 Agent Observability > Settings > Evaluations 페이지를 사용하세요.

LLMObs.submit_evaluation() 메서드는 다음 인수를 허용합니다.

label
필수 - string
평가의 이름입니다.
metric_type
필수 - string
평가의 유형입니다. categorical, score, boolean 또는 json이어야 합니다.
value
필수 - string, numeric type 또는 dict
평가의 값입니다. 문자열(metric_type==categorical), 정수/부동 소수점(metric_type==score), 불리언(metric_type==boolean) 또는 딕셔너리(metric_type==json)여야 합니다.
span
선택 사항 - dictionary
이 평가와 연결된 스팬을 고유하게 식별하는 딕셔너리입니다. span_id(string) 및 trace_id(string)을 포함해야 합니다. 이 딕셔너리는 LLMObs.export_span()을 사용해 생성할 수 있습니다.
span_with_tag_value
선택 사항 - dictionary
이 평가와 연결된 스팬을 고유하게 식별하는 딕셔너리입니다. tag_key(string) 및 tag_value(string)을 포함해야 합니다.

참고: span 또는 span_with_tag_value 중 정확히 하나만 필요합니다. 두 개를 모두 제공하거나 둘 다 제공하지 않으면 ValueError가 발생합니다.

ml_app
필수 - string
ML 애플리케이션의 이름입니다.
timestamp_ms
선택 사항 - integer
평가 메트릭 결과가 생성된 밀리초 단위의 유닉스 타임스탬프입니다. 제공하지 않으면 현재 시간이 기본값으로 사용됩니다.
tags
선택 사항 - dictionary
사용자가 평가와 관련하여 태그로 추가할 수 있는 문자열 키-값 쌍의 딕셔너리입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
assessment
선택 사항 - string
평가 결과에 대한 판단입니다. 허용되는 값은 passfail입니다.
reasoning
선택 사항 - string
평가 결과에 대한 설명 텍스트입니다.
metadata
선택 사항 - dictionary
평가 결과와 관련된 구조화된 임의 메타데이터를 포함하는 딕셔너리입니다.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call():
    completion = ... # user application logic to invoke LLM

    # joining an evaluation to a span via a tag key-value pair
    msg_id = get_msg_id()
    LLMObs.annotate(
        tags = {'msg_id': msg_id}
    )

    LLMObs.submit_evaluation(
        span_with_tag_value = {
            "tag_key": "msg_id",
            "tag_value": msg_id
        },
        ml_app = "chatbot",
        label="harmfulness",
        metric_type="score",
        value=10,
        tags={"evaluation_provider": "ragas"},
        assessment="fail",
        reasoning="Malicious intent was detected in the user instructions.",
        metadata={"details": ["jailbreak", "SQL injection"]}
    )

    # joining an evaluation to a span via span ID and trace ID
    span_context = LLMObs.export_span(span=None)
    LLMObs.submit_evaluation(
        span_context = span_context,
        ml_app = "chatbot",
        label="harmfulness",
        metric_type="score",
        value=10,
        tags={"evaluation_provider": "ragas"},
        assessment="fail",
        reasoning="Malicious intent was detected in the user instructions.",
        metadata={"details": ["jailbreak", "SQL injection"]}
    )
    return completion

llmobs.submitEvaluation()을 사용하여 주어진 스팬과 연결된 사용자 지정 평가를 제출할 수 있습니다.

llmobs.submitEvaluation() 메서드는 다음 인수를 허용합니다.

span_context
필수 - dictionary
평가를 연결할 스팬 컨텍스트입니다. 이는 LLMObs.export_span()의 출력이어야 합니다.
evaluationOptions
필수 - object
평가 데이터의 객체입니다.

evaluationOptions 객체에는 다음 항목이 포함될 수 있습니다.

label
필수 - string
평가의 이름입니다.
metricType
필수 - string
평가의 유형입니다. “categorical”, “score”, “boolean”, “json” 중 하나여야 합니다.
value
필수 - string 또는 numeric type
평가의 값입니다. 문자열(범주형 평가 metric_type), 숫자(점수 평가 metric_type), 불리언(불리언 평가 metric_type) 또는 JSON 객체(JSON 평가 metric_type)여야 합니다.
tags
선택 사항 - dictionary
사용자가 평가와 관련하여 태그로 추가할 수 있는 문자열 키-값 쌍의 딕셔너리입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
assessment
선택 사항 - string
평가 결과에 대한 판단입니다. 허용되는 값은 passfail입니다.
reasoning
선택 사항 - string
평가 결과에 대한 설명 텍스트입니다.
metadata
선택 사항 - dictionary
평가 결과와 관련된 구조화된 임의 메타데이터를 포함하는 JSON 객체입니다.

예시

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()
  llmobs.submitEvaluation(spanContext, {
    label: "harmfulness",
    metricType: "score",
    value: 10,
    tags: { evaluationProvider: "ragas" }
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

주어진 스팬과 관련된 사용자 지정 평가를 제출하려면 LLMObs.SubmitEvaluation()을 사용하세요.

LLMObs.SubmitEvaluation() 메서드는 다음 인수를 허용합니다.

llmObsSpan
필수 - LLMObsSpan
평가를 연결할 스팬 컨텍스트입니다.
label
필수 - String
평가의 이름입니다.
categoricalValue 또는 scoreValue
필수 - String 또는 double
평가의 값입니다. string(범주형 평가의 경우) 또는 double(점수 평가의 경우)이어야 합니다.
tags
선택 사항 - Map<String, Object>
평가에 태그를 지정하는 데 사용하는 문자열 키-값 쌍 딕셔너리입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = "N/A";
    try {
      chatResponse = ... // user application logic to invoke LLM
    } catch (Exception e) {
      llmSpan.addThrowable(e);
      throw new RuntimeException(e);
    } finally {
      llmSpan.finish();

      // submit evaluations
      LLMObs.SubmitEvaluation(llmSpan, "toxicity", "toxic", Map.of("language", "english"));
      LLMObs.SubmitEvaluation(llmSpan, "f1-similarity", 0.02, Map.of("provider", "f1-calculator"));
    }
    return chatResponse;
  }
}

최종 사용자 피드백 제출하기

최종 사용자 피드백은 만족 또는 불만족 아이콘 평가, 사용자가 에이전트의 변경 사항을 수락했는지 여부, 자유 텍스트 코멘트와 같이 LLM 애플리케이션 사용자의 입력을 캡처합니다. 평가와 달리 피드백은 제출자의 신원을 포함하며 스팬, 트레이스, 세션 또는 고객 정의 엔터티를 대상으로 할 수 있습니다. 자세한 내용은 최종 사용자 피드백을 참조하세요.

LLMObs.submit_feedback()을 사용하여 스팬, 트레이스, 세션 또는 고객 정의 엔터티와 연결된 최종 사용자 피드백을 제출하세요.

LLMObs.submit_feedback() 메서드는 다음 인수를 허용합니다.

label
필수 - string
피드백 메트릭의 이름입니다. .을 포함해서는 안 됩니다.
metric_type
필수 - string
피드백의 유형입니다. categorical, score, boolean, json 또는 text이어야 합니다.
value
필수 - string, numeric type, boolean 또는 dict
피드백의 값입니다. 문자열(metric_type==categorical 또는 metric_type==text), 정수 또는 부동 소수점(metric_type==score), 불리언(metric_type==boolean) 또는 딕셔너리(metric_type==json)여야 합니다.
submitter
필수 - dictionary
피드백을 제출한 사람을 식별하는 딕셔너리입니다. 비어 있지 않은 id(string)를 포함해야 하며, user와 같은 선택적 type(string)을 포함할 수 있습니다.
span
선택 사항 - dictionary
이 피드백과 연결된 스팬을 식별하는 딕셔너리입니다. 이 딕셔너리는 LLMObs.export_span()을 사용해 생성할 수 있습니다.
span_id
선택 사항 - string
이 피드백과 연결된 스팬의 ID입니다.
trace_id
선택 사항 - string
이 피드백과 연결된 트레이스의 ID입니다.
session_id
선택 사항 - string
이 피드백과 연결된 세션의 ID입니다.
feedback_join_key
선택 사항 - string
인시던트 ID나 티켓 ID와 같이 이 피드백과 연결된 고객 정의 키입니다. 피드백을 스팬에 연결하려면 먼저 동일한 값을 가진 feedback_join_key 태그로 스팬에 주석을 달아야 합니다. 스팬 강화하기를 참조하세요.

참고: span, span_id, trace_id, session_id, feedback_join_key 중 정확히 하나만 필요합니다. 하나보다 많은 항목을 제공하거나 하나도 제공하지 않으면 ValueError가 발생합니다.

ml_app
선택 사항 - string
ML 애플리케이션의 이름입니다. 제공되지 않으면 SDK에 대해 구성된 ML 애플리케이션이 기본값으로 사용됩니다.
timestamp_ms
선택 사항 - integer
피드백이 생성된 시점의 밀리초 단위 Unix 타임스탬프입니다. 제공하지 않으면 현재 시간이 기본값으로 사용됩니다.
tags
선택 사항 - dictionary
사용자가 피드백과 관련하여 태그로 추가할 수 있는 문자열 키-값 쌍의 딕셔너리입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
assessment
선택 사항 - string
이 피드백에 대한 평가입니다. 허용되는 값은 passfail입니다.
reasoning
선택 사항 - string
피드백에 대한 텍스트 설명입니다.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import llm

@llm(model_name="claude", name="invoke_llm", model_provider="anthropic")
def llm_call():
    completion = ... # user application logic to invoke LLM
    span_context = LLMObs.export_span(span=None)

    # submitting feedback for a trace
    LLMObs.submit_feedback(
        label="thumbs",
        metric_type="categorical",
        value="down",
        submitter={"id": "user-123", "type": "user"},
        trace_id=span_context["trace_id"],
        assessment="fail",
    )

    # connecting the span to a customer-defined entity
    LLMObs.annotate(tags={"feedback_join_key": "incident-123"})

    # submitting feedback for that entity
    LLMObs.submit_feedback(
        label="user_comment",
        metric_type="text",
        value="The investigation missed the customer impact.",
        submitter={"id": "user-123", "type": "user"},
        feedback_join_key="incident-123",
    )
    return completion

llmobs.submitFeedback()을 사용하여 스팬, 트레이스, 세션 또는 고객 정의 엔터티와 연결된 최종 사용자 피드백을 제출하세요.

llmobs.submitFeedback() 메서드는 다음 속성을 가진 옵션 객체를 허용합니다.

label
필수 - string
피드백 메트릭의 이름입니다. .을 포함해서는 안 됩니다.
metricType
필수 - string
피드백의 유형입니다. categorical, score, boolean, json, text 중 하나여야 합니다.
value
필수 - string, number, boolean, 또는 object
피드백의 값입니다. 문자열(categoricaltext 메트릭 유형의 경우), 숫자(score의 경우), 불리언(boolean의 경우) 또는 JSON 객체(json의 경우)여야 합니다.
submitter
필수 - object
피드백을 제출한 사람을 식별하는 객체입니다. 비어 있지 않은 id(string)를 포함해야 하며, user와 같은 선택적 type(string)을 포함할 수 있습니다.
span
선택 사항 - object
피드백을 첨부할 스팬의 스팬 컨텍스트입니다. 이는 llmobs.exportSpan()의 출력이어야 합니다.
spanId
선택 사항 - string
피드백을 첨부할 스팬의 ID입니다.
traceId
선택 사항 - string
피드백을 첨부할 트레이스의 ID입니다.
sessionId
선택 사항 - string
피드백을 연결할 세션의 ID입니다.
feedbackJoinKey
선택 사항 - string
인시던트 ID나 티켓 ID와 같이 피드백을 연결할 고객 정의 키입니다. 피드백을 스팬에 연결하려면 스팬에 동일한 키를 설정하세요.

참고: span, spanId, traceId, sessionId, feedbackJoinKey 중 정확히 하나만 필요합니다. 하나보다 많은 항목을 제공하거나 하나도 제공하지 않으면 오류가 발생합니다.

mlApp
선택 사항 - string
ML 애플리케이션의 이름입니다. 제공되지 않으면 SDK에 대해 구성된 ML 애플리케이션이 기본값으로 사용됩니다.
timestampMs
선택 사항 - number
피드백이 생성된 시점의 밀리초 단위 Unix 타임스탬프입니다. 제공하지 않으면 현재 시간이 기본값으로 사용됩니다.
tags
선택 사항 - object
사용자가 피드백과 관련하여 태그로 추가할 수 있는 문자열 키-값 쌍의 객체입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
assessment
선택 사항 - string
이 피드백에 대한 평가입니다. 허용되는 값은 passfail입니다.
reasoning
선택 사항 - string
피드백에 대한 텍스트 설명입니다.

예시

function llmCall () {
  const completion = ... // user application logic to invoke LLM
  const spanContext = llmobs.exportSpan()

  // submitting feedback for a trace
  llmobs.submitFeedback({
    label: 'thumbs',
    metricType: 'boolean',
    value: true,
    submitter: { id: 'user-123', type: 'user' },
    traceId: spanContext.traceId,
    assessment: 'pass'
  })

  // connecting the span to a customer-defined entity
  llmobs.annotate({
    tags: { feedback_join_key: 'incident-123' }
  })

  // submitting feedback for that entity
  llmobs.submitFeedback({
    label: 'user_comment',
    metricType: 'text',
    value: 'This answer was helpful.',
    submitter: { id: 'user-123', type: 'user' },
    feedbackJoinKey: 'incident-123'
  })
  return completion
}
llmCall = llmobs.wrap({ kind: 'llm', name: 'invokeLLM', modelName: 'claude', modelProvider: 'anthropic' }, llmCall)

LLMObs.submitFeedback()을 사용하여 스팬, 트레이스, 세션 또는 고객 정의 엔터티와 연결된 최종 사용자 피드백을 제출하세요. LLMObs.Feedback.builder()를 사용하여 피드백을 구축하세요.

빌더는 다음 메서드를 허용합니다.

label(String label)
필수
피드백 메트릭의 이름입니다. .을 포함해서는 안 됩니다.
categoricalValue(String), scoreValue(double), booleanValue(boolean), jsonValue(Map<String, Object>) 또는 textValue(String)
필수
피드백의 값입니다. 이 메서드 중 정확히 하나를 설정하세요. 이 메서드는 메트릭 유형도 결정합니다.
submitter(String id, String type) 또는 submitter(Submitter submitter)
필수
피드백을 제출한 사람을 식별합니다. id는 비어 있지 않은 문자열이어야 합니다. typeuser와 같은 선택적 한정자입니다.
span(LLMObsSpan span), spanId(String), traceId(String), sessionId(String) 또는 feedbackJoinKey(String)
필수
피드백을 연결할 엔터티입니다. 이 메서드 중 정확히 하나를 설정하세요. 인시던트 ID나 티켓 ID와 같은 고객 정의 엔터티에는 feedbackJoinKey를 사용하고, 피드백을 스팬에 연결하려면 스팬에 동일한 키를 설정하세요.
mlApp(String mlApp)
선택 사항
ML 애플리케이션의 이름입니다. 제공되지 않으면 트레이서에 대해 구성된 ML 애플리케이션이 기본값으로 사용됩니다.
timestampMs(long timestampMs)
선택 사항
피드백이 생성된 시점의 밀리초 단위 Unix 타임스탬프입니다. 제공하지 않으면 현재 시간이 기본값으로 사용됩니다.
tags(Map<String, Object> tags) 또는 tag(String key, Object value)
선택 사항
피드백에 태그를 지정하는 데 사용되는 키-값 쌍입니다. 태그에 대한 자세한 내용은 태그 시작하기를 참조하세요.
assessment(Assessment assessment)
선택 사항
이 피드백에 대한 평가입니다. 허용되는 값은 LLMObs.Feedback.Assessment.PASSLLMObs.Feedback.Assessment.FAIL입니다.
reasoning(String reasoning)
선택 사항
피드백에 대한 텍스트 설명입니다.

참고: LLMObs.submitFeedback()은 피드백을 검증하며, Agent Observability가 활성화되어 있고 대상, 값 또는 제출자가 누락되는 등 피드백이 유효하지 않은 경우 IllegalArgumentException을 발생시킵니다. Agent Observability가 비활성화되어 있거나 Agent가 연결되지 않은 경우, 해당 호출은 아무 작업도 수행하지 않습니다.

예시

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String invokeChat(String userInput) {
    LLMObsSpan llmSpan = LLMObs.startLLMSpan("my-llm-span-name", "my-llm-model", "my-company", "maybe-ml-app-override", "session-141");
    String chatResponse = "N/A";
    try {
      chatResponse = ... // user application logic to invoke LLM
    } catch (Exception e) {
      llmSpan.addThrowable(e);
      throw new RuntimeException(e);
    } finally {
      // connecting the span to a customer-defined entity
      llmSpan.setTag("feedback_join_key", "incident-123");
      llmSpan.finish();

      // submitting feedback for a trace
      LLMObs.submitFeedback(
          LLMObs.Feedback.builder()
              .traceId(llmSpan.getTraceId().toString())
              .label("thumbs")
              .booleanValue(true)
              .submitter("user-123", "end_user")
              .assessment(LLMObs.Feedback.Assessment.PASS)
              .reasoning("answered the question")
              .build());

      // submitting feedback for that entity
      LLMObs.submitFeedback(
          LLMObs.Feedback.builder()
              .feedbackJoinKey("incident-123")
              .label("user_comment")
              .textValue("The answer missed the customer impact.")
              .submitter("user-123", "end_user")
              .assessment(LLMObs.Feedback.Assessment.FAIL)
              .build());
    }
    return chatResponse;
  }
}

스팬 처리

스팬의 입력 및 출력 데이터를 수정하려면 프로세서 함수를 구성할 수 있습니다. 프로세서 함수는 스팬 태그에 접근할 수 있어 조건부 입력/출력 수정이 가능합니다. 프로세서 함수는 수정된 스팬을 반환하여 전송하거나 None/null을 반환하여 스팬이 완전히 전송되지 않도록 할 수도 있습니다. 이는 민감한 데이터를 포함하거나 특정 기준을 충족하는 스팬을 필터링할 때 유용합니다.

예시

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan

def redact_processor(span: LLMObsSpan) -> LLMObsSpan:
    if span.get_tag("no_output") == "true":
        for message in span.output:
            message["content"] = ""
    return span


# If using LLMObs.enable()
LLMObs.enable(
  ...
  span_processor=redact_processor,
)
# else when using `ddtrace-run`
LLMObs.register_processor(redact_processor)

with LLMObs.llm("invoke_llm_with_no_output"):
    LLMObs.annotate(tags={"no_output": "true"})

예시: 자동 계측을 통한 조건부 수정

자동 계측을 사용할 때는 스팬이 항상 컨텍스트상 접근 가능한 상태가 아닙니다. 자동 계측된 스팬의 입력과 출력을 조건부로 수정하려면 annotation_context()를 스팬 프로세서와 함께 사용할 수 있습니다.

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan

def redact_processor(span: LLMObsSpan) -> LLMObsSpan:
    if span.get_tag("no_input") == "true":
        for message in span.input:
            message["content"] = ""
    return span

LLMObs.register_processor(redact_processor)


def call_openai():
    with LLMObs.annotation_context(tags={"no_input": "true"}):
        # make call to openai
        ...

예시: 스팬이 전송되지 않도록 방지하기

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs import LLMObsSpan
from typing import Optional

def filter_processor(span: LLMObsSpan) -> Optional[LLMObsSpan]:
    # Skip spans that are marked as internal or contain sensitive data
    if span.get_tag("internal") == "true" or span.get_tag("sensitive") == "true":
        return None  # This span will not be emitted

    # Process and return the span normally
    return span

LLMObs.register_processor(filter_processor)

# This span will be filtered out and not sent to Datadog
with LLMObs.workflow("internal_workflow"):
    LLMObs.annotate(tags={"internal": "true"})
    # ... workflow logic

예시

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>"
  }
})

const llmobs = tracer.llmobs

function redactProcessor(span) {
  if (span.getTag("no_output") === "true") {
    for (const message of span.output) {
      message.content = ""
    }
  }
  return span
}

llmobs.registerProcessor(redactProcessor)

예시: 자동 계측을 통한 조건부 수정

자동 계측을 사용할 때는 스팬이 항상 컨텍스트상 접근 가능한 상태가 아닙니다. 자동 계측된 스팬의 입력과 출력을 조건부로 수정하려면 llmobs.annotationContext()를 스팬 프로세서와 함께 사용할 수 있습니다.

const { llmobs } = require('dd-trace');

function redactProcessor(span) {
  if (span.getTag("no_input") == "true") {
    for (const message of span.input) {
      message.content = "";
    }
  }

  return span;
}

llmobs.registerProcessor(redactProcessor);

async function callOpenai() {
  await llmobs.annotationContext({ tags: { no_input: "true" } }, async () => {
    // make call to openai
  });
}

예시: 스팬이 전송되지 않도록 방지하기

const tracer = require('dd-trace').init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>"
  }
})

const llmobs = tracer.llmobs

function filterProcessor(span) {
  // Skip spans that are marked as internal or contain sensitive data
  if (span.getTag("internal") === "true" || span.getTag("sensitive") === "true") {
    return null  // This span will not be emitted
  }

  // Process and return the span normally
  return span
}

llmobs.registerProcessor(filterProcessor)

// This span will be filtered out and not sent to Datadog
function internalWorkflow() {
  return llmobs.trace({ kind: 'workflow', name: 'internalWorkflow' }, (span) => {
    llmobs.annotate({ tags: { internal: "true" } })
    // ... workflow logic
  })
}

사용자 세션 추적하기

세션 추적을 통해 여러 상호작용을 특정 사용자와 연결할 수 있습니다.

새로운 트레이스 또는 새로운 프로세스의 스팬을 위한 루트 스팬을 시작할 때, 기본 사용자 세션의 문자열 ID와 함께 session_id 인수를 지정해야 하며, 이는 스팬의 태그로 제출됩니다. 필요에 따라 user_handle, user_name, 및 user_id 태그를 지정할 수도 있습니다.

from ddtrace.llmobs.decorators import workflow

@workflow(session_id="<SESSION_ID>")
def process_user_message():
    LLMObs.annotate(
        ...
        tags = {"user_handle": "poodle@dog.com", "user_id": "1234", "user_name": "poodle"}
    )
    return

세션 추적 태그

태그설명
session_id단일 사용자 세션을 나타내는 ID입니다(예: 채팅 세션).
user_handle채팅 세션 사용자의 핸들입니다.
user_name채팅 세션 사용자의 이름입니다.
user_id채팅 세션 사용자의 ID입니다.

새로운 트레이스 또는 새로운 프로세스의 스팬을 위한 루트 스팬을 시작할 때, 기본 사용자 세션의 문자열 ID와 함께 sessionId 인수를 지정해야 합니다.

function processMessage() {
    ... # user application logic
    return
}
processMessage = llmobs.wrap({ kind: 'workflow', sessionId: "<SESSION_ID>" }, processMessage)

새로운 트레이스 또는 새로운 프로세스의 스팬을 위한 루트 스팬을 시작할 때, 기본 사용자 세션의 문자열 ID와 함께 sessionId 인수를 지정해야 합니다.

import datadog.trace.api.llmobs.LLMObs;

public class MyJavaClass {
  public String processChat(int userID) {
    LLMObsSpan workflowSpan = LLMObs.startWorkflowSpan("incoming-chat", null, "session-" + System.currentTimeMillis() + "-" + userID);
    String chatResponse = answerChat(); // user application logic
    workflowSpan.annotateIO(...); // record the input and output
    workflowSpan.finish();
    return chatResponse;
  }
}

분산 추적

SDK는 분산 서비스 또는 호스트 간의 추적을 지원합니다. 분산 추적은 웹 요청을 통해 스팬 정보를 전파하여 작동합니다.

ddtrace 라이브러리는 인기 있는 웹 프레임워크HTTP 라이브러리에 대한 분산 추적을 지원하는 몇 가지 기본 통합을 제공합니다. 애플리케이션이 이러한 지원 라이브러리를 사용하여 요청을 하는 경우, 다음을 실행하여 분산 추적을 활성화할 수 있습니다.

from ddtrace import patch
patch(<INTEGRATION_NAME>=True)

애플리케이션이 이러한 지원 라이브러리를 사용하지 않는 경우, HTTP 헤더를 통해 스팬 정보를 주고받아 분산 추적을 수동으로 활성화할 수 있습니다. SDK는 요청 헤더에 추적 컨텍스트를 주입하고 활성화하기 위한 도우미 메서드 LLMObs.inject_distributed_headers()LLMObs.activate_distributed_headers()를 제공합니다.

분산 헤더 주입하기

LLMObs.inject_distributed_headers() 메서드는 스팬을 받아 해당 컨텍스트를 HTTP 헤더에 주입합니다. 이 메서드는 다음 인수를 허용합니다.

request_headers
필수 - dictionary
추적 컨텍스트 속성으로 확장할 HTTP 헤더입니다.
span
선택 사항 - Span - 기본값: The current active span.
제공된 요청 헤더에 컨텍스트를 주입할 스팬입니다. 함수 데코레이터가 적용된 스팬을 포함하며, 현재 활성 스팬이 기본값으로 사용됩니다.

분산 헤더 활성화하기

LLMObs.activate_distributed_headers() 메서드는 HTTP 헤더를 받아 추적 컨텍스트 속성을 추출하고 이를 새로운 서비스에서 활성화합니다.

참고: 다운스트림 서비스에서 스팬을 시작하기 전에 LLMObs.activate_distributed_headers()를 호출해야 합니다. 이전에 시작된 스팬(함수 데코레이터 스팬 포함)은 분산 트레이스에 포함되지 않습니다.

이 메서드는 다음 인수를 허용합니다.

request_headers
필수 - dictionary
추적 컨텍스트 속성을 추출할 HTTP 헤더입니다.

예시

client.py

from ddtrace.llmobs import LLMObs
from ddtrace.llmobs.decorators import workflow

@workflow
def client_send_request():
    request_headers = {}
    request_headers = LLMObs.inject_distributed_headers(request_headers)
    send_request("<method>", request_headers)  # arbitrary HTTP call

server.py

from ddtrace.llmobs import LLMObs

def server_process_request(request):
    LLMObs.activate_distributed_headers(request.headers)
    with LLMObs.task(name="process_request") as span:
        pass  # arbitrary server work

dd-trace 라이브러리는 인기 있는 웹 프레임워크에 대한 분산 추적을 지원하는 기본 통합을 제공합니다. 트레이서를 사용하면 이러한 통합 기능이 자동으로 활성화되지만, 필요에 따라 다음을 사용하여 비활성화할 수도 있습니다.

const tracer = require('dd-trace').init({
  llmobs: { ... },
})
tracer.use('http', false) // disable the http integration

고급 추적

인라인 메서드를 사용한 스팬 추적하기

각 스팬 종류마다 ddtrace.llmobs.LLMObs 클래스는 주어진 코드 블록에서 수반되는 작업을 자동으로 추적할 수 있는 해당 인라인 메서드를 제공합니다. 이 메서드는 함수 데코레이터와 동일한 인수 서명을 가지며, name 인수가 제공되지 않은 경우 스팬 종류(llm, workflow 등)로 기본값이 설정됩니다. 이 메서드는 컨텍스트 관리자로 사용할 수 있으며, 코드 블록 실행이 완료되면 스팬이 자동으로 종료됩니다.

예시

from ddtrace.llmobs import LLMObs

def process_message():
    with LLMObs.workflow(name="process_message", session_id="<SESSION_ID>", ml_app="<ML_APP>") as workflow_span:
        ... # user application logic
    return

컨텍스트 간 스팬 유지하기

다른 컨텍스트나 범위에서 스팬을 수동으로 시작하고 중지하려면 다음 단계를 따르세요.

  1. 스팬을 수동으로 시작합니다. 동일한 메서드(예: 워크플로 스팬의 경우 LLMObs.workflow)를 사용하되, 컨텍스트 관리자가 아닌 일반 함수 호출 방식으로 실행합니다.
  2. 스팬 객체를 다른 함수의 인수로 전달합니다.
  3. span.finish() 메서드를 사용하여 스팬을 수동으로 중지합니다. 참고: 스팬은 수동으로 종료해야 하며, 그렇지 않으면 제출되지 않습니다.

예시

from ddtrace.llmobs import LLMObs

def process_message():
    workflow_span = LLMObs.workflow(name="process_message")
    ... # user application logic
    separate_task(workflow_span)
    return

def separate_task(workflow_span):
    ... # user application logic
    workflow_span.finish()
    return

서버리스 환경에서 강제 플러시

LLMObs.flush()는 모든 버퍼링된 Agent Observability 데이터를 Datadog 백엔드로 전송하는 블로킹 함수입니다. 이는 서버리스 환경에서 모든 Agent Observability 트레이스가 제출될 때까지 애플리케이션 종료를 방지하는 데 유용할 수 있습니다.

여러 애플리케이션 추적하기

SDK는 동일한 서비스의 여러 LLM 애플리케이션 추적을 지원합니다.

환경 변수 DD_LLMOBS_ML_APP를 LLM 애플리케이션의 이름으로 구성할 수 있으며, 기본적으로 모든 생성된 스팬이 이 이름으로 그룹화됩니다.

이 구성을 재정의하고 주어진 루트 스팬에 대해 다른 LLM 애플리케이션 이름을 사용하려면, 새로운 트레이스의 루트 스팬을 시작하거나 새로운 프로세스의 스팬을 시작할 때 기본 LLM 애플리케이션의 문자열 이름과 함께 ml_app 인수를 전달하세요.

from ddtrace.llmobs.decorators import workflow

@workflow(name="process_message", ml_app="<NON_DEFAULT_ML_APP_NAME>")
def process_message():
    ... # user application logic
    return

인라인 메서드를 사용한 스팬 추적하기

llmobs SDK는 주어진 코드 블록에서 수반되는 작업을 자동으로 추적하기 위한 해당 인라인 메서드를 제공합니다. 이 메서드는 함수 래퍼 버전과 동일한 인수 서명을 가지며, 익명 콜백에서 이름을 유추할 수 없기 때문에 name 인수가 반드시 필요합니다. 이 메서드는 다음 조건에서 스팬을 종료합니다.

  • 함수가 Promise를 반환하면 Promise가 해결되거나 거부될 때 스팬이 종료됩니다.
  • 함수의 마지막 파라미터가 콜백인 경우 해당 콜백이 호출될 때 스팬이 종료됩니다.
  • 함수가 콜백을 받지 않고 Promise도 반환하지 않으면 함수 실행이 끝날 때 스팬이 종료됩니다.

콜백 없는 예시

function processMessage () {
  return llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, workflowSpan => {
    ... // user application logic
    return
  })
}

콜백 있는 예시

function processMessage () {
  return llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, (workflowSpan, cb) => {
    ... // user application logic
    let maybeError = ...
    cb(maybeError) // the span will finish here, and tag the error if it is not null or undefined
    return
  })
}

이 함수의 반환 유형은 추적된 함수의 반환 유형과 일치합니다.

function processMessage () {
  const result = llmobs.trace({ kind: 'workflow', name: 'processMessage', sessionId: '<SESSION_ID>', mlApp: '<ML_APP>' }, workflowSpan => {
    ... // user application logic
    return 'hello world'
  })

  console.log(result) // 'hello world'
  return result
}

TypeScript의 함수 데코레이터

Node.js Agent Observability SDK는 TypeScript 애플리케이션을 위한 함수 데코레이터 역할을 하는 llmobs.decorate 함수를 제공합니다. 이 함수의 추적 동작은 llmobs.wrap과 동일합니다.

예시

// index.ts
import tracer from 'dd-trace';
tracer.init({
  llmobs: {
    mlApp: "<YOUR_ML_APP_NAME>",
  },
});

const { llmobs } = tracer;

class MyAgent {
  @llmobs.decorate({ kind: 'agent' })
  async runChain () {
    ... // user application logic
    return
  }
}

서버리스 환경에서 강제 플러시

llmobs.flush()는 모든 버퍼링된 Agent Observability 데이터를 Datadog 백엔드로 전송하는 블로킹 함수입니다. 이는 서버리스 환경에서 모든 Agent Observability 트레이스가 제출될 때까지 애플리케이션 종료를 방지하는 데 유용할 수 있습니다.

여러 애플리케이션 추적하기

SDK는 동일한 서비스의 여러 LLM 애플리케이션 추적을 지원합니다.

환경 변수 DD_LLMOBS_ML_APP를 LLM 애플리케이션의 이름으로 구성할 수 있으며, 기본적으로 모든 생성된 스팬이 이 이름으로 그룹화됩니다.

이 구성을 재정의하고 주어진 루트 스팬에 대해 다른 LLM 애플리케이션 이름을 사용하려면, 새로운 트레이스의 루트 스팬을 시작하거나 새로운 프로세스의 스팬을 시작할 때 기본 LLM 애플리케이션의 문자열 이름과 함께 mlApp 인수를 전달하세요.

function processMessage () {
  ... // user application logic
  return
}
processMessage = llmobs.wrap({ kind: 'workflow', name: 'processMessage', mlApp: '<NON_DEFAULT_ML_APP_NAME>' }, processMessage)

애플리케이션 이름 지정 가이드라인

애플리케이션 이름(DD_LLMOBS_ML_APP의 값)은 다음 가이드라인을 따라야 합니다.

  • 소문자 유니코드 문자열이어야 함
  • 최대 193자까지 가능
  • 연속 밑줄이나 끝부분 밑줄을 포함할 수 없음
  • 다음 문자를 포함할 수 있음
    • 영숫자
    • 밑줄
    • 하이픈
    • 콜론
    • 슬래시

추가 자료