createUIMessageStream — UI 메시지 스트림 만들기

createUIMessageStream — UI 메시지 스트림 만들기

createUIMessageStream 함수는 메시지 병합, 에러 처리, 완료 콜백 같은 고급 기능을 갖춘 UI 메시지용 readable stream을 만들 수 있게 해줘요. 채팅 UI 응답을 서버에서 직접 조립할 때 쓰는 함수예요.

출처: 문서

본문

createUIMessageStream 함수는 메시지 병합, 에러 처리, 완료 콜백 같은 고급 기능과 함께 UI 메시지용 readable stream을 만들 수 있게 해줘요.

Import

import { createUIMessageStream } from "ai"

예시

const existingMessages: UIMessage[] = [
  /* ... */
];

const stream = createUIMessageStream({
  async execute({ writer }) {
    // 외부 스트림이 어시스턴트 메시지 라이프사이클을 소유해요.
    writer.write({ type: 'start' });

    // 텍스트 메시지 시작
    // 참고: id는 text-start, text-delta, text-end 단계에서 일관되어야 해요
    // 그래야 시스템이 이들이 같은 텍스트 블록에 속한다는 걸 올바르게 식별할 수 있어요
    writer.write({
      type: 'text-start',
      id: 'example-text',
    });

    // 메시지 청크 쓰기
    writer.write({
      type: 'text-delta',
      id: 'example-text',
      delta: 'Hello',
    });

    // 텍스트 메시지 끝
    writer.write({
      type: 'text-end',
      id: 'example-text',
    });

    // streamText의 다른 스트림 병합
    const result = streamText({
      model: __MODEL__,
      prompt: 'Write a haiku about AI',
    });

    writer.merge(
      toUIMessageStream({
        stream: result.stream,
        sendStart: false,
        onEnd: ({ outcome }) => {
          // 컴포저가 모델 스트림의 outcome이 곧
          // 전체 스트림의 outcome이라고 결정해요.
          writer.setOutcome(outcome);
        },
      }),
    );
  },
  onError: error => `Custom error: ${error.message}`,
  originalMessages: existingMessages,
  onEnd: ({ messages, isContinuation, outcome, responseMessage }) => {
    console.log('Stream ended with messages:', messages);
    console.log('Stream outcome:', outcome.status);
  },
});

setOutcome은 청크를 쓰거나 스트림을 닫지 않고 컴포저의 정책을 기록해요. setOutcome으로 선언된 첫 번째 outcome은 유지되지만, 치명적인 실행·병합·에러 처리·하위 처리 실패가 발생하면 최종 onEnd의 outcome이 failed가 돼요. 개별 error 청크는 그 자체로 outcome을 바꾸지 않아요. 여러 하위(child) 스트림을 병합할 때는 outcome을 모두 합쳐 setOutcome을 한 번만 호출하세요.

API 시그니처

파라미터

  • execute: (options: { writer: UIMessageStreamWriterWithOutcome }) => Promise<void> | void — writer 인스턴스를 받아 UI 메시지 청크를 스트림에 쓰는 데 사용하는 함수.
    • write: (part: UIMessageChunk) => void — UI 메시지 청크를 스트림에 써요.
    • merge: (stream: ReadableStream<UIMessageChunk>) => void — 다른 UI 메시지 스트림의 내용을 이 스트림으로 병합해요.
    • setOutcome: (outcome: UIMessageStreamOutcome) => void — 구성된 스트림의 작업 수준 outcome을 선언해요. 이 메서드로 선언된 첫 번째 outcome은 유지되고, 치명적인 실행·병합·에러 처리·하위 처리 실패가 발생하면 선언을 덮어써요. 지원하는 상태는 'completed', 'failed', 'aborted', 'unknown'이에요. outcome을 선언해도 청크를 쓰거나 스트림을 닫지 않아요.
    • onError: (error: unknown) => string — 병합된 스트림의 에러를 처리하기 위해 스트림 writer가 사용하는 에러 핸들러.
  • onError: (error: unknown) => string — 에러를 처리하고 에러 메시지 문자열을 반환하는 함수. 기본값은 에러 메시지를 반환해요.
  • originalMessages: UIMessage[] | undefined — 원본 메시지. 제공하면 영속(persistence) 모드로 간주되고 응답 메시지에 메시지 ID가 제공돼요.
  • onEnd: (options: { messages: UIMessage[]; isContinuation: boolean; isAborted: boolean; isCancelled?: true; outcome: UIMessageStreamOutcome; responseMessage: UIMessage; finishReason?: FinishReason }) => PromiseLike<void> | void — 스트림이 끝날 때 호출되는 콜백 함수.
    • messages: UIMessage[] — 업데이트된 UI 메시지 목록.
    • isContinuation: boolean — 응답 메시지가 마지막 원본 메시지의 연속인지, 아니면 새 메시지가 생성됐는지를 나타내요.
    • isAborted: boolean — 스트림이 중단됐는지 나타내요.
    • isCancelled: true | undefined — outcome이 선언되기 전에 소비자가 스트림을 취소했을 때(예: 클라이언트 연결 해제) 존재하며 true예요.
    • outcome: UIMessageStreamOutcome = { status: 'completed' } | { status: 'failed'; error?: unknown } | { status: 'aborted' } | { status: 'unknown' } — 스트림의 작업 수준 outcome. 치명적인 스트림 처리 실패가 없는 한 스트림 소유자의 선언을 반영하며, 모델 finish reason이나 개별 error 청크와는 별개예요. 소비자가 outcome 선언 전에 취소하면 'unknown'으로 남아요. 선언된 outcome 없이 정상 종료된 경우와 구분하려면 isCancelled를 확인하세요.
    • responseMessage: UIMessage — 응답으로 클라이언트에 보내진 메시지 (확장된 원본 메시지 포함).
    • finishReason: FinishReason | undefined — 생성이 끝난 이유. 'stop', 'length', 'content-filter', 'tool-calls', 'error', 'other' 중 하나예요.
  • onFinish: (options: { messages: UIMessage[]; isContinuation: boolean; isAborted: boolean; isCancelled?: true; outcome: UIMessageStreamOutcome; responseMessage: UIMessage; finishReason?: FinishReason }) => PromiseLike<void> | void — onEnd의 deprecated 별칭.
  • generateId: IdGenerator | undefined — 메시지의 고유 ID를 생성하는 함수. 제공하지 않으면 기본 ID 생성기를 사용해요.

반환값

ReadableStream<UIMessageChunk> — UI 메시지 청크를 내보내는 readable stream을 반환해요. 스트림은 에러 전파, 여러 스트림의 병합, 모든 작업이 완료됐을 때의 적절한 정리를 자동으로 처리해요.

더 알아보기 (Learn more)