스트리밍 출력 — SSE로 토큰 단위 응답 받기
스트리밍 출력 — SSE로 토큰 단위 응답 받기
LLM 채팅을 만들다 보면, 전체 응답이 끝날 때까지 가만히 기다리기보다 글자가 만들어지는 대로 받아 보고 싶어요. Replicate는 server-sent events(SSE) 기반의 스트리밍 출력을 지원해서, 모델이 입력을 처리하는 동안 실시간으로 진행되는 결과를 받아볼 수 있어요. 이 글에서 스트리밍을 요청하고 소비하는 방법을 정리해요.
스트리밍 출력이란
스트리밍 출력은 모델이 입력을 처리하는 동안 실시간 점진적 업데이트를 받아볼 수 있게 해 줘요. 전체 예측이 끝날 때까지 기다리는 대신, 결과가 생성되는 즉시 접근할 수 있어서 즉각 응답이 필요한 채팅 봇 같은 애플리케이션에 잘 맞아요.
큰 그림은 이렇게 동작해요.
stream옵션을 켜고 예측을 만든다.- Replicate가 스트리밍 출력을 받을 URL이 담긴 예측을 돌려준다.
- 그 URL에 연결해 업데이트 스트림을 받는다.
어떤 모델이 스트리밍을 지원하나요
스트리밍은 Llama 3의 여러 변형을 포함해 다수의 언어 모델이 지원해요.
meta/meta-llama-3.1-405b-instruct: 4050억 파라미터 모델로 채팅 완성용 파인튜닝. 최고 정확도의 채팅 봇을 만들고 싶다면 이 모델을 써요.meta/meta-llama-3-70b-instruct: 700억 파라미터, 채팅 완성용 파인튜닝. 정확도와 비용의 균형이 좋아요.meta/meta-llama-3-70b: 700억 파라미터 베이스 모델. 사용자가 쓰다 만 글을 이어주는 것 같은 다른 종류의 언어 완성에 쓰기 좋아요.meta/meta/meta-llama-3-8b-instruct: 80억 파라미터, 채팅 완성용 파인튜닝. 정확도를 조금 희생하더라도 더 빠르고 저렴하게 채팅 봇을 만들고 싶을 때 써요.meta/meta/meta-llama-3-8b: 80억 파라미터 베이스 모델. 다양한 자연어 생성 작업에 쓸 수 있어요.
스트리밍을 지원하는 전체 모델 목록은 streaming language models 컬렉션에서 확인할 수 있어요.
스트리밍 요청하기
API로 예측을 만들면 응답에 urls 객체가 담겨요. 여기 예측과 상호작용할 여러 URL이 들어 있는데, 요청한 모델 버전이 스트리밍을 지원하면 urls에 stream URL이 포함돼요.
{
"web": "https://replicate.com/p/cky59275mdrm80cpw83rcn3ej0",
"get": "https://api.replicate.com/v1/predictions/cky59275mdrm80cpw83rcn3ej0",
"stream": "https://stream.replicate.com/v1/files/bcwr-3afcgaxf5opqtgeq5ababozl3erroi6ody73lpkwklvnu7bwtmrq",
"cancel": "https://api.replicate.com/v1/predictions/cky59275mdrm80cpw83rcn3ej0/cancel"
}
이 urls.stream URL을 server-sent events(SSE)로 스트리밍 출력을 받는 데 쓸 수 있어요.
EventSource는 서버 이벤트를 받는 표준 웹 브라우저 API예요. WebSocket 같은 완전한 양방향 연결 없이도 서버가 실시간 업데이트를 브라우저로 밀어줄 수 있게 해 주죠.
cURL로 stream: true를 켜고 예측을 만드는 예시입니다.
curl -X POST -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
-d '{"input": {"prompt": "Tell me a story"}, "stream": true}' \
"https://api.replicate.com/v1/models/meta/meta-llama-3-70b-instruct/predictions"
Python 클라이언트는 이렇게 간단해요.
import replicate
stream = replicate.stream("meta/meta-llama-3-70b-instruct", {
prompt: "Tell me a story",
})
이 방식의 모델 페이지는 https://replicate.com/meta/llama-3-70b-instruct 에서 볼 수 있어요.
스트리밍 출력 받기
urls.stream URL에 Accept: text/event-stream을 붙여 GET 요청을 보내면 스트리밍 이벤트가 와요.
curl -X GET -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
-H "Accept: text/event-stream" \
"https://streaming.api.replicate.com/v1/predictions/fuwwvjtbdmroc4xifxdcwqtdfq"
스트리밍 이벤트는 이렇게 생겼어요.
event: output
id: 1690212292:0
data: Once upon a time...
JavaScript 클라이언트에서는 예측의 stream URL로 EventSource를 구성해 받을 수 있어요. event가 output일 때마다 data를 모으면 전체 텍스트가 완성돼요.
const output = [];
for await (const { event, data } of stream) {
if (event === "output") {
output.push(data);
}
}
console.log(output.join(""));
예측의 이벤트 스트림은 다음 세 가지 이벤트 타입으로 구성돼요.
| 이벤트 | 형식 | 설명 |
|---|---|---|
output |
plain text | 예측이 새 출력을 반환할 때 방출 |
error |
JSON | 예측이 에러를 반환할 때 방출 |
done |
JSON | 예측이 끝났을 때 방출 |
done 이벤트는 예측이 성공적으로 끝나거나, 취소되거나, 에러가 났을 때 방출돼요.
예측이 성공하면 빈 JSON 페이로드와 함께 done 이벤트를 받아요.
event: output
id: 1690212292:0
data: Once upon a time...
event: output
id: 1690212293:0
data: The End.
event: done
data: {}
예측이 취소되면 {"reason": "canceled"} JSON 페이로드와 함께 done 이벤트를 받아요.
event: output
id: 1690212292:0
data: Once upon a time...
event: done
data: {"reason": "canceled"}
예측이 에러를 내면 에러 JSON 페이로드가 담긴 error 이벤트에 이어 {"reason": "error"} 페이로드의 done 이벤트를 받아요.
event: output
id: 1690212292:0
data: Once upon a time...
event: error
data: {"detail": "Something went wrong"}
event: done
data: {"reason": "error"}
408 Request timeout
이벤트 스트림 엔드포인트에는 30초 타임아웃이 있어요. 타임아웃에 닿으면 408: 408 Request Timeout이라는 텍스트를 담은 빈 이벤트가 스트림으로 내려와요.
:408: 408 Request Timeout
이런 경우는 보통 예측이 삭제된 뒤에 스트림에 연결하려고 하거나(API 예측은 1시간 후 만료), 클라이언트가 done 이벤트를 처리하고 연결을 닫는 데 실패했을 때 생겨요.
더 알아보기
- Create a prediction — 예측 만들기
- Prediction lifecycle — 예측 상태 이해하기
- llama.replicate.dev — Next.js 앱에서 스트리밍 출력 예시
- Replicate Node.js 클라이언트 API — Node.js·브라우저 사용법