Maxim Observability

Maxim Observability

Maxim AI는 전통적인 소프트웨어 모범 사례를 비결정적 AI 워크플로우에 적용해 AI 애플리케이션 개발과 배포를 효율화해요. 우리의 평가 및 관측성 도구는 팀이 AI 애플리케이션 수명주기 전반에 걸쳐 품질, 신뢰성, 속도를 유지하도록 도와줘요. Maxim은 AI SDK와 통합해 다음을 제공해요:

  • 자동 관측성 – 간단한 래퍼로 AI SDK 호출에 트레이싱, 로깅, 메타데이터를 추가해요.

  • 통합 모델 래핑 – OpenAI, Anthropic, Google 등의 모델을 균일하게 지원해요.

  • 커스텀 메타데이터 및 태깅 – trace 이름, 태그, 세션 ID를 첨부해 사용량을 추적할 수 있게 해줘요.

  • 스트리밍 및 구조화된 출력 지원 – 스트리밍 응답과 구조화된 출력을 원활하게 처리해요.

출처: 문서

본문

AI SDK와 함께 Maxim 설정하기

요구사항

"ai"
"@ai-sdk/openai"
"@ai-sdk/anthropic"
"@ai-sdk/google"
"@maximai/maxim-js"

환경 변수

MAXIM_API_KEY=
MAXIM_LOG_REPO_ID=
OPENAI_API_KEY=
ANTHROPIC_API_KEY=

로거 초기화

import { Maxim } from '@maximai/maxim-js';

async function initializeMaxim() {
  const apiKey = process.env.MAXIM_API_KEY || '';
  if (!apiKey) {
    throw new Error(
      'MAXIM_API_KEY is not defined in the environment variables',
    );
  }

  const maxim = new Maxim({ apiKey });
  const logger = await maxim.logger({
    id: process.env.MAXIM_LOG_REPO_ID || '',
  });

  if (!logger) {
    throw new Error('Logger is not available');
  }

  return { maxim, logger };
}

AI SDK 모델을 Maxim으로 감싸기

import { openai } from '@ai-sdk/openai';
import { wrapMaximAISDKModel } from '@maximai/maxim-js/vercel-ai-sdk';

const model = wrapMaximAISDKModel(openai('gpt-6-astra'), logger);

감싼 모델로 LLM 호출하기

import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { wrapMaximAISDKModel } from '@maximai/maxim-js/vercel-ai-sdk';

const model = wrapMaximAISDKModel(openai('gpt-5'), logger);

// Generate text with automatic logging
const response = await generateText({
  model: model,
  prompt: 'Write a haiku about recursion in programming.',
  temperature: 0.8,
  system: 'You are a helpful assistant.',
});

console.log('Response:', response.text);

다양한 AI SDK 함수와 함께 사용하기

감싼 모델은 모든 Vercel AI SDK 함수와 원활하게 동작해요:

구조화된 출력

import { generateText, Output } from 'ai';
import { z } from 'zod';

const response = await generateText({
  model: model,
  prompt: 'Generate a user profile for John Doe',
  output: Output.object({
    schema: z.object({
      name: z.string(),
      age: z.number(),
      email: z.string().email(),
      interests: z.array(z.string()),
    }),
  }),
});

console.log(response.output);

스트림 텍스트

import { streamText } from 'ai';

const { textStream } = await streamText({
  model: model,
  prompt: 'Write a short story about space exploration',
  system: 'You are a creative writer',
});

for await (const textPart of textStream) {
  process.stdout.write(textPart);
}

커스텀 메타데이터와 트레이싱

커스텀 메타데이터 사용

import { MaximVercelProviderMetadata } from '@maximai/maxim-js/vercel-ai-sdk';

const response = await generateText({
  model: model,
  prompt: 'Hello, how are you?',
  providerOptions: {
    maxim: {
      traceName: 'custom-trace-name',
      traceTags: {
        type: 'demo',
        priority: 'high',
      },
    } as MaximVercelProviderMetadata,
  },
});

사용 가능한 메타데이터 필드

엔티티 이름 지정:

  • sessionName - 기본 세션 이름 재정의
  • traceName - 기본 trace 이름 재정의
  • spanName - 기본 span 이름 재정의
  • generationName - 기본 LLM 생성 이름 재정의

엔티티 태깅:

  • sessionTags - 세션에 커스텀 태그 추가 (object: {key: value})
  • traceTags - trace에 커스텀 태그 추가 (object: {key: value})
  • spanTags - span에 커스텀 태그 추가 (object: {key: value})
  • generationTags - LLM 생성에 커스텀 태그 추가 (object: {key: value})

ID 참조:

  • sessionId - 이 trace를 기존 세션에 연결
  • traceId - 특정 trace ID 사용
  • spanId - 특정 span ID 사용

Maxim 데모

스트리밍 지원

import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { wrapMaximAISDKModel, MaximVercelProviderMetadata } from '@maximai/maxim-js/vercel-ai-sdk';

const model = wrapMaximAISDKModel(openai('gpt-6-astra'), logger);

const { textStream } = await streamText({
  model: model,
  prompt: 'Write a story about a robot learning to paint.',
  system: 'You are a creative storyteller',
  providerOptions: {
    maxim: {
      traceName: 'Story Generation',
      traceTags: {
        type: 'creative',
        format: 'streaming'
      },
    } as MaximVercelProviderMetadata,
  },
});

for await (const textPart of textStream) {
  process.stdout.write(textPart);
}

다중 프로바이더 지원

import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
import { wrapMaximAISDKModel } from '@maximai/maxim-js/vercel-ai-sdk';

// Wrap different provider models
const openaiModel = wrapMaximAISDKModel(openai('gpt-6-astra'), logger);
const anthropicModel = wrapMaximAISDKModel(
  anthropic('claude-sonnet-5'),
  logger,
);
const googleModel = wrapMaximAISDKModel(google('gemini-pro'), logger);

// Use them with the same interface
const responses = await Promise.all([
  generateText({ model: openaiModel, prompt: 'Hello from OpenAI' }),
  generateText({ model: anthropicModel, prompt: 'Hello from Anthropic' }),
  generateText({ model: googleModel, prompt: 'Hello from Google' }),
]);

Next.js 통합

API 라우트 예시

// app/api/chat/route.js
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { wrapMaximAISDKModel, MaximVercelProviderMetadata } from '@maximai/maxim-js/vercel-ai-sdk';
import { Maxim } from "@maximai/maxim-js";

const maxim = new Maxim({ apiKey });
const logger = await maxim.logger({ id: process.env.MAXIM_LOG_REPO_ID });
const model = wrapMaximAISDKModel(openai('gpt-6-astra'), logger);

export async function POST(req) {
  const { messages } = await req.json();

  const result = await streamText({
    model: model,
    messages,
    system: 'You are a helpful assistant',
    providerOptions: {
      maxim: {
        traceName: 'Chat API',
        traceTags: {
          endpoint: '/api/chat',
          type: 'conversation'
        },
      } as MaximVercelProviderMetadata,
    },
  });

  return result.toAIStreamResponse();
}

클라이언트 측 통합

// components/Chat.jsx
import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: '/api/chat',
  });

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Say something..."
        />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

더 알아보기

  • Vercel AI SDK용 Maxim 트레이싱을 설정한 후에는 다른 Maxim 플랫폼 기능을 탐색할 수 있어요:
    • Prompt Management: 환경과 에이전트 전반에 걸쳐 프롬프트를 버전 관리하고, 관리하며, 동적으로 적용.
    • Evaluations: trace, 생성, 전체 에이전트 궤적에 대한 자동 및 수동 평가 실행.
    • Simulations: 시뮬레이션된 다중 턴 상호작용과 워크플로우로 실제 시나리오에서 에이전트 테스트.

자세한 내용은 Vercel AI SDK의 Maxim 통합 문서를 확인하세요.

더 알아보기 (Learn more)