TrueFoundry

TrueFoundry

Python과 TypeScript에서 TrueFoundry 호출을 트레이싱하고 평가해볼게요. TrueFoundry는 중앙화된 인증·라우팅·거버넌스로 모델에 접근할 수 있게 하는 AI 게이트웨이예요. Confident AI는 OpenTelemetry 네이티브 트레이싱 SDK인 confident-trace를 통해 TrueFoundry 호출을 트레이싱하고 평가해요.

출처: 문서

본문

개요

TrueFoundry는 중앙화된 인증, 라우팅, 거버넌스로 모델에 접근하기 위한 AI 게이트웨이예요. Confident AI는 Python과 TypeScript용 OpenTelemetry 네이티브 트레이싱 SDK인 confident-trace를 통해 TrueFoundry 호출을 트레이싱하고 평가해요.

이 통합은 지원되는 호출에서 다음 데이터를 캡처해요:

  • LLM 스팬(span) — 모델 이름, 타이밍, 상태, 토큰 사용량
  • 메시지 — 모델이 반환한 인풋/아웃풋 메시지와 툴 콜 데이터
  • 스트리밍 아웃풋 — 애플리케이션이 소비하는 대로의 응답 콘텐츠

TrueFoundry는 모든 애플리케이션에 트레이싱 코드를 추가하지 않고도 게이트웨이 측 OTLP 내보내기로 Confident AI 지원을 제공해요. AI Gateway → Controls → Settings → OTEL Config에서 traces 내보내기를 활성화하고, HTTP와 JSON을 선택하고, https://otel.confident-ai.com/v1/traces로 설정하세요. Content-Type: application/json과 x-confident-api-key: <your-...y>를 추가하세요. EU는 https://eu.otel.confident-ai.com/v1/traces를, self-hosted Confident 배포는 자체 traces 엔드포인트를 사용하세요. 요청/응답 캡처는 Exclude Request Data로 제어돼요. 이들은 게이트웨이 트레이스이며, 아래 SDK 설정은 애플리케이션의 호출을 캡처해요.

런타임 요구 사항 설정
Python Python 3.10+, openai >=1.109 <4; 실행 중인 TrueFoundry 게이트웨이 모델 호출 전에 init() 호출
TypeScript Node.js 22+, openai >=7.10.0 <8; 실행 중인 TrueFoundry 게이트웨이 init() 호출 및 register preload로 시작

자동 계측 (Auto-Instrument)

의존성 설치

예시에서 사용하는 클라이언트와 함께 confident-trace를 설치해요:

Python

pip install confident-trace

TypeScript

tsx는 TypeScript 소스를 직접 실행할 때만 필요해요.

npm install confident-trace
npm install -D tsx
yarn add confident-trace
yarn add -D tsx

API 키 설정

Confident AI에서 프로젝트 API 키를 받고 모델 클라이언트의 자격 증명을 설정해요:

export CONFIDENT_API_KEY="<your-confident-project-key>"
export TRUEFOUNDRY_API_KEY="<your-gateway-key>"
export TRUEFOUNDRY_BASE_URL="<your-full-gateway-base-url>"

EU 프로젝트는 CONFIDENT_OTEL_ENDPOINT="https://eu.otel.confident-ai.com/v1/traces"를 설정하세요. self-hosted 배포는 전체 OTLP/HTTP traces URL을 사용해요. US 프로젝트는 기본적으로 https://otel.confident-ai.com/v1/traces를 사용해요. 이 설정들은 트레이스 내보내기를 제어하며, 모델 요청은 게이트웨이 base URL이 제어해요.

TrueFoundry 계측

init()을 한 번 호출하고 클라이언트가 사용하는 정확한 게이트웨이 base URL을 등록해요. 요청은 평소의 SDK 형태를 유지해요. 예시 모델을 TrueFoundry 게이트웨이에 구성된 모델 이름으로 바꾸세요.

Python

import os
from confident_trace import init, shutdown
from openai import OpenAI

base_url = os.environ["TRUEFOUNDRY_BASE_URL"]
init(truefoundry_proxy_urls=[base_url])
client = OpenAI(base_url=base_url, api_key=os.environ["TRUEFOUNDRY_API_KEY"])

try:
    response = client.chat.completions.create(
        model="openai-main/gpt-4o-mini",
        messages=[
            {"role": "user", "content": "Explain OpenTelemetry in one sentence."}
        ],
    )
    print(response.choices[0].message.content)
finally:
    shutdown()

TypeScript

import OpenAI from "openai";
import { init } from "confident-trace";

const baseURL = process.env.TRUEFOUNDRY_BASE_URL!;
const runtime = init({ truefoundryProxyUrls: [baseURL] });
const client = new OpenAI({ baseURL, apiKey: proces...KEY! });

try {
  const response = await client.chat.completions.create({
    model: "openai-main/gpt-4o-mini",
    messages: [{ role: "user", content: "Explain OpenTelemetry in one sentence." }],
  });
  console.log(response);
} finally {
  await runtime.shutdown();
}

장기 실행 서버에서는 시작 시 init()을 한 번, 정상 종료 중에는 활성 요청이 끝난 뒤 shutdown()을 한 번 호출하세요 — 요청마다 호출하지 마세요. flush와 shutdown을 참고하세요.

TrueFoundry 실행

Python

python main.py

TypeScript

confident-trace/register preload로 진입점을 시작해 Node가 SDK를 로드할 때 훅할 수 있게 해요. 자동 트레이싱에는 preload와 init() 둘 다 필요해요.

# Running TypeScript source directly
node --import tsx --import confident-trace/register src/index.ts

# Running compiled JavaScript
node --import confident-trace/register dist/index.js

완료 ✅. Confident AI 프로젝트에서 Observatory를 열어 트레이스와 모델-콜 스팬을 확인하세요.

Anthropic 호환 클라이언트

이 통합은 Anthropic Messages create와 stream도 지원해요. Python용 anthropic>=0.69,<2 또는 TypeScript용 @anthropic-ai/sdk>=0.124.0 <0.125를 confident-trace와 함께 설치하세요. 이 스니펫들은 퀵스타트의 클라이언트 설정을 대체하며, 시작·종료 수명 주기는 동일하게 유지해요.

export TRUEFOUNDRY_BASE_URL="<your-full-gateway-base-url>"

Python

import os
from anthropic import Anthropic
from confident_trace import init

base_url = os.environ["TRUEFOUNDRY_BASE_URL"]
api_key = os.environ["TRUEFOUNDRY_API_KEY"]
init(truefoundry_proxy_urls=[base_url])
client = Anthropic(
    base_url=base_url,
    api_key=api_key,
    default_headers={"Authorization": f"Bearer {api_key}"},
)

TypeScript

import Anthropic from "@anthropic-ai/sdk";
import { init } from "confident-trace";

const baseURL = process.env.TRUEFOUNDRY_BASE_URL!;
const apiKey = process.env.TRUEFOUNDRY_API_KEY!;
const runtime = init({ truefoundryProxyUrls: [baseURL] });
const client = new Anthropic({
  baseURL,
  apiKey,
  defaultHeaders: { Authorization: *** ${apiKey}` },
});

client.messages.create를 model, max_tokens, messages와 함께 호출하거나 client.messages.stream을 사용해요. 이 엔드포인트에 구성된 모델을 사용하세요. 두 SDK를 모두 쓰면 같은 init() 호출에 두 클라이언트 base URL을 모두 나열해요. 매칭은 정확한 base URL을 기준으로 하며 자동 localhost 탐지는 없어요.

수동 TypeScript 설정의 경우 해당 confident-trace 하위 경로에서 instrumentOpenAI나 instrumentAnthropic을 사용하고 { truefoundryProxyUrls: [baseURL] }을 전달해요. init()으로 내보내기를 초기화하고, 수동 어댑터는 preload가 필요 없어요.

캡처되는 것

지원되는 각 애플리케이션 호출은 모델-콜 스팬을 만들어요. 활성 스팬 아래에 중첩되며, 부모가 없으면 새 트레이스를 시작해요.

  • 지원 API — OpenAI Chat Completions와 Responses create, 그리고 Anthropic Messages create와 stream(Python sync/async 호출 포함). Google GenAI/Bedrock 게이트웨이 탐지, 임베딩, 백그라운드 추론 폴링 수명 주기는 이 통합 범위 밖이에요.
  • 모델과 사용량 — 요청된 모델 또는 별칭, 가능하면 반환된 모델, 응답 ID, 완료 이유(finish reasons), 게이트웨이가 제공한 토큰 수
  • 메시지와 툴 — 정규화된 인풋/아웃풋 메시지와 툴-콜 데이터; 툴 실행은 별개 작업이며 이 게이트웨이 통합이 트레이싱하지 않아요
  • 게이트웨이 정체성 — 스팬은 OpenAI 또는 Anthropic 통합 라벨을 유지하고 게이트웨이/프로바이더 정체성을 truefoundry로 기록해요

메시지는 캡처 옵트아웃, 리드액션, 구성된 크기 제한을 포함한 콘텐츠 정책을 따르며, 바이너리 멀티모달 페이로드는 생략돼요.

애플리케이션 스팬은 코드가 만드는 호출을 설명해요. 게이트웨이 내부의 모든 재시도, 폴백, 라우팅 결정을 드러내진 않아요. 게이트웨이 내보내기는 자체 스팬 속성과 콘텐츠 설정을 가져요. 두 경로를 모두 활성화하면 클라이언트와 게이트웨이 스팬이 모두 보일 수 있는데, 하나의 분산 트레이스로 합치려면 모델 이름 매칭이 아니라 컨텍스트 전파(context propagation)가 필요해요.

스트리밍

스트리밍은 같은 설정을 사용해요. 각 예시는 초기화와 종료를 포함해요:

Python

import os
from confident_trace import init, shutdown
from openai import OpenAI

base_url = os.environ["TRUEFOUNDRY_BASE_URL"]
init(truefoundry_proxy_urls=[base_url])
client = OpenAI(base_url=base_url, api_key=os.environ["TRUEFOUNDRY_API_KEY"])

try:
    stream = client.chat.completions.create(
        model="openai-main/gpt-4o-mini",
        messages=[{"role": "user", "content": "Tell me a short story."}],
        stream=True,
    )
    try:
        for chunk in stream:
            print(chunk)
    finally:
        stream.close()
finally:
    shutdown()

TypeScript

import OpenAI from "openai";
import { init } from "confident-trace";

const baseURL = process.env.TRUEFOUNDRY_BASE_URL!;
const runtime = init({ truefoundryProxyUrls: [baseURL] });
const client = new OpenAI({ baseURL, apiKey: proces...KEY! });

try {
  const stream = await client.chat.completions.create({
    model: "openai-main/gpt-4o-mini",
    messages: [{ role: "user", content: "Tell me a short story." }],
    stream: true,
  });
  for await (const chunk of stream) {
    console.log(chunk);
  }
} finally {
  await runtime.shutdown();
}

Python 비동기 코드의 경우 AsyncOpenAI 또는 AsyncAnthropic을 사용하고 해당 메서드를 await하며, 스트림은 async for로 소비해요.

shutdown() 전에 스트림을 소비하거나 닫으세요. TypeScript는 스트림을 소비하거나 클라이언트 SDK의 취소 컨트롤을 사용해요. 스트림을 버리면 스팬이 불완전하게 남을 수 있어요. flush와 shutdown을 참고하세요.

트레이스 스팬 속성 설정 (Set Trace Span Properties)

트레이스 컨텍스트를 사용해 호출이 시작되기 전에 아는 속성을 추가해요. 추가 스팬은 만들지 않아요. 각 예시는 호출 전에 트레이싱을 초기화하고 클라이언트를 만들어요.

Python

import os
from confident_trace import init, shutdown, trace_context
from openai import OpenAI

base_url = os.environ["TRUEFOUNDRY_BASE_URL"]
init(truefoundry_proxy_urls=[base_url])
client = OpenAI(base_url=base_url, api_key=os.environ["TRUEFOUNDRY_API_KEY"])

try:
    with trace_context(
        tags=["support"],
        metadata={"gateway": "truefoundry"},
        user_id="user-42",
        customer_id="customer-7",
    ):
        response = client.chat.completions.create(
            model="openai-main/gpt-4o-mini",
            messages=[
                {"role": "user", "content": "Explain OpenTelemetry in one sentence."}
            ],
        )
finally:
    shutdown()

TypeScript

import OpenAI from "openai";
import { init, traceContext } from "confident-trace";

const baseURL = process.env.TRUEFOUNDRY_BASE_URL!;
const runtime = init({ truefoundryProxyUrls: [baseURL] });
const client = new OpenAI({ baseURL, apiKey: proces...KEY! });

try {
  const response = await traceContext(
    {
      tags: ["support"],
      metadata: { gateway: "truefoundry" },
      userId: "user-42",
      customerId: "customer-7",
    },
    () =>
      client.chat.completions.create({
        model: "openai-main/gpt-4o-mini",
        messages: [{ role: "user", content: "Explain OpenTelemetry in one sentence." }],
      }),
  );
} finally {
  await runtime.shutdown();
}

각 ID 옆에 선택적 표시 이름을 설정하려면 users와 customers를, 모든 지원 속성은 trace context를 참고하세요.

멀티턴 계측 (Instrumenting Multi-Turn)

단일 모델 호출을 트레이싱하는 데 turn()이 필요하지 않아요. 대화 경계를 정의하려 할 때, 예를 들어 두 호출을 하나의 턴으로 묶으려 할 때 사용해요. 이후 턴에 같은 thread ID를 재사용해 하나의 대화로 묶어요.

각 예시는 초기화와 종료를 포함해요. 퀵스타트와 같은 환경 변수를 사용해요.

Python

import os
from confident_trace import init, shutdown, turn
from openai import OpenAI

base_url = os.environ["TRUEFOUNDRY_BASE_URL"]
init(truefoundry_proxy_urls=[base_url])
client = OpenAI(base_url=base_url, api_key=os.environ["TRUEFOUNDRY_API_KEY"])

try:
    with turn("support-turn", thread_id="chat-42"):
        context = client.chat.completions.create(
            model="openai-main/gpt-4o-mini",
            messages=[
                {
                    "role": "user",
                    "content": "List two useful facts about OpenTelemetry.",
                }
            ],
        )
        answer = client.chat.completions.create(
            model="openai-main/gpt-4o-mini",
            messages=[
                {
                    "role": "user",
                    "content": f"Summarize these facts: {context.choices[0].message.content}",
                }
            ],
        )
finally:
    shutdown()

TypeScript

import OpenAI from "openai";
import { init, turn } from "confident-trace";

const baseURL = process.env.TRUEFOUNDRY_BASE_URL!;
const runtime = init({ truefoundryProxyUrls: [baseURL] });
const client = new OpenAI({ baseURL, apiKey: proces...KEY! });

try {
  const answer = await turn({ name: "support-turn", threadId: "chat-42" }, async () => {
    const context = await client.chat.completions.create({
      model: "openai-main/gpt-4o-mini",
      messages: [
        { role: "user", content: "List two useful facts about OpenTelemetry." },
      ],
    });
    return client.chat.completions.create({
      model: "openai-main/gpt-4o-mini",
      messages: [
        { role: "user", content: `Summarize these facts: ${JSON.stringify(context)}` },
      ],
    });
  });
} finally {
  await runtime.shutdown();
}

대화 그룹화와 턴 속성은 threads를 참고하세요.

문제 해결 (Troubleshooting)

Python

  • 스팬 없음: 모델 호출 전과 함수/바인딩 메서드 별칭 저장 전에 init()을 호출하세요. 프로세스 종료 전에 shutdown()을 호출해 버퍼링된 스팬이 내보내지도록 하세요.
  • 불완전한 스트림: shutdown 전에 스트림을 소비하거나 닫으세요.
  • 게이트웨이 라벨 누락: 프록시 클라이언트 사용 시 경로를 포함한 정확한 base URL을 등록하세요. OpenRouter와 Portkey 공개 OpenAI 엔드포인트는 자동 탐지돼요.

TypeScript

  • 스팬 없음: init()과 --import confident-trace/register를 모두 사용하세요. 클라이언트 통합과 지원 SDK 버전을 확인하려면 runtime.getInstrumentationStatus()를 확인하세요.
  • 불완전한 스트림: shutdown 전에 스트림을 소비하거나 취소하세요.
  • 게이트웨이 라벨 누락: 구성된 *ProxyUrls 항목이 경로를 포함해 클라이언트 baseURL과 정확히 일치하는지 확인하세요.
  • 콘텐츠 누락: 캡처 설정과 위의 지원 API 목록을 확인하세요. 게이트웨이 측 내보내기는 별도의 콘텐츠 컨트롤이 있어요.
  • 중복 기록: 같은 클라이언트 호출에 여러 계측기를 결합하지 마세요. 클라이언트 계측과 게이트웨이 측 내보내기가 한 요청의 별도 뷰를 보고할 수도 있어요.

일반적인 설정 이슈는 troubleshooting을 참고하세요.

TrueFoundry 계측 비활성화

init()에 통합 식별자 목록을 전달해 해당 통합만 옵트인해요. 퀵스타트는 Python에서 "openai", TypeScript에서 "openai"를 사용해요. Anthropic 클라이언트는 "anthropic"을 사용해요. 별도의 "truefoundry" 통합 선택자는 없어요. 빈 목록은 모든 자동 계측을 비활성화해요:

Python

from confident_trace import init

init(instrumentations=())
# To enable only the quickstart integration: instrumentations=("openai",)

TypeScript

import { init } from "confident-trace";

init({ instrumentations: [] });
// To enable only the quickstart integration: instrumentations: ["openai"]

선택 사항을 시작 시 init() 호출에 적용해요. 이는 SDK 훅을 제어하며 개별 게이트웨이 호스트를 제어하지 않고, 게이트웨이 자신의 내보내기 설정도 바꾸지 않아요. 수동으로 설치한 TypeScript 어댑터는 자체 복원 함수가 있어요.

다음 단계

온라인 평가 (Online Evals)

트레이스와 스팬이 Confident AI로 수집될 때 평가를 실행해 프로덕션 AI 품질을 모니터링해요.

스레드 (Threads)

멀티턴 대화를 스레드로 묶고 전체 대화를 단일 단위로 평가해요.

더 알아보기