메시지 메타데이터
메시지 메타데이터 (Message Metadata)
메시지 메타데이터를 사용하면 메시지 수준에서 커스텀 정보를 메시지에 붙일 수 있습니다. 타임스탬프, 모델 정보, 토큰 사용량, 사용자 컨텍스트, 그 외 메시지 수준 데이터를 추적하는 데 유용합니다.
메시지 메타데이터는 data parts와 달리 메시지 콘텐츠의 일부가 아니라 메시지 수준에 붙습니다. data parts는 메시지를 구성하는 동적 콘텐츠에 이상적인 반면, 메타데이터는 메시지 자체에 대한 정보를 담기에 적합합니다.
출처: 공식문서
본문
시작하기
메타데이터 타입 정의
타입 안전성을 위해 먼저 메타데이터 타입을 정의합니다:
app/types.ts
import { UIMessage } from 'ai';
import { z } from 'zod';
// Define your metadata schema
export const messageMetadataSchema = z.object({
createdAt: z.number().optional(),
model: z.string().optional(),
totalTokens: z.number().optional(),
});
export type MessageMetadata = z.infer<typeof messageMetadataSchema>;
// Create a typed UIMessage
export type MyUIMessage = UIMessage<MessageMetadata>;
서버에서 메타데이터 보내기
toUIMessageStream의 messageMetadata 콜백으로 다양한 스트리밍 단계에서 메타데이터를 보냅니다:
app/api/chat/route.ts
import {
convertToModelMessages,
createUIMessageStreamResponse,
streamText,
toUIMessageStream,
} from 'ai';
import type { MyUIMessage } from '@/types';
export async function POST(req: Request) {
const { messages }: { messages: MyUIMessage[] } = await req.json();
const result = streamText({
model: "xai/grok-4.6",
messages: await convertToModelMessages(messages),
});
return createUIMessageStreamResponse({
stream: toUIMessageStream({
stream: result.stream,
originalMessages: messages, // pass this in for type-safe return objects
messageMetadata: ({ part }) => {
// Send metadata when streaming starts
if (part.type === 'start') {
return {
createdAt: Date.now(),
model: 'your-model-id',
};
}
// Send additional metadata when streaming completes
if (part.type === 'finish') {
return {
totalTokens: part.totalUsage.totalTokens,
};
}
},
}),
});
}
messageMetadata에서 타입 안전한 메타데이터 반환 객체를 활성화하려면 originalMessages 파라미터를 UIMessage 타입으로 전달하세요.
클라이언트에서 메타데이터 접근
message.metadata 속성으로 메타데이터에 접근합니다:
app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import type { MyUIMessage } from '@/types';
export default function Chat() {
const { messages } = useChat<MyUIMessage>({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
});
return (
<div>
{messages.map(message => (
<div key={message.id}>
<div>
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.metadata?.createdAt && (
<span className="text-sm text-gray-500">
{new Date(message.metadata.createdAt).toLocaleTimeString()}
</span>
)}
</div>
{/* Render message content */}
{message.parts.map((part, index) =>
part.type === 'text' ? <div key={index}>{part.text}</div> : null,
)}
{/* Display additional metadata */}
{message.metadata?.totalTokens && (
<div className="text-xs text-gray-400">
{message.metadata.totalTokens} tokens
</div>
)}
</div>
))}
</div>
);
}
생성 중에 변하는 임의 데이터를 스트리밍하려면 data parts를 고려하세요.
흔한 유스케이스
메시지 메타데이터는 다음에 이상적입니다:
- 타임스탬프: 메시지가 생성되거나 완료된 시점.
- 모델 정보: 어떤 AI 모델이 사용되었는지.
- 토큰 사용량: 비용과 사용 한도 추적.
- 사용자 컨텍스트: 사용자 ID, 세션 정보.
- 성능 지표: 생성 시간, 첫 토큰까지의 시간.
- 품질 지표: 종료 사유, 신뢰 점수.