vLLM과 함께 쓰기
vLLM과 함께 쓰기
Vast.ai의 vLLM 서버리스 템플릿을 쓰면 Vast GPU 인스턴스에서 대규모 언어 모델을 추론할 수 있어요. 이 문서는 시작하기 위한 필수 환경 변수와 엔드포인트를 정리해 줘요. 완전한 PyWorker와 Client 구현은 vllm-pyworker 저장소에서 볼 수 있어요.
환경 변수 (Environment Variables)
Serverless Quickstart의 Configuration 섹션에서 이 설정들을 확인할 수 있어요.
MODEL_NAME(string): 추론에 사용할 모델 이름. 지원되는 HuggingFace 모델 목록은 TGI 문서에서 확인하세요.VLLM_ARGS(string): 템플릿에 이미 사전 설정되어 있는 vLLM 전용 인자예요.
엔드포인트
/v1/completions/
주어진 프롬프트의 맥락이나 패턴에 맞춰 텍스트 완성을 생성하는 엔드포인트예요. 텍스트 프롬프트를 주면 모델이 이어질 내용을 예측해 반환해요. 단일 턴 작업에 잘 맞고, 다중 턴 대화에는 /v1/chat/completions가 최적화되어 있어요.
다음은 vastai pip 패키지로 빠르게 시작하는 예시예요.
import asyncio
from vastai import Serverless
MAX_TOKENS = 128
async def main():
async with Serverless() as client:
endpoint = await client.get_endpoint(name="my-endpoint")
payload = {
"input" : {
"model": "Qwen/Qwen3-8B",
"prompt" : "Who are you?",
"max_tokens" : MAX_TOKENS,
"temperature" : 0.7
}
}
response = await endpoint.request("/v1/completions", payload, cost=MAX_TOKENS)
print(response["response"]["choices"][0]["text"])
if __name__ == "__main__":
asyncio.run(main())
/v1/chat/completions/
입력 (Inputs)
input:model(string): 텍스트 완성 생성에 사용할 모델의 특정 식별자예요.messages(array): 대화 히스토리를 형성하는 메시지 객체 목록이에요.role(string): 메시지 작성자의 역할.system,user,assistant중 하나예요.content(string): 메시지의 내용이에요.
stream(boolean): true면 생성되는 대로 토큰 단위 이벤트 스트림을 보내고, false면 완료된 전체 응답을 한 번에 보내요. 기본값은 false예요.tools(optional, List[Dict[str, Any]]): 모델이 외부 동작을 수행하기 위해 호출할 수 있는 함수 정의 목록이에요.
출력 (Outputs)
choices:index(int): 목록에서 선택지의 인덱스(첫 선택이면 0)예요.message:role(string): 메시지 작성자의 역할.system,user,assistant중 하나예요.content(string): 모델이 생성한 메시지 내용이에요.
스트리밍 (Streaming)
스트리밍 예시에서는 reasoning(추론) 토큰과 최종 답변 토큰을 구분해 화면에 출력하는 흐름을 확인할 수 있어요.
import asyncio
from vastai import Serverless
MAX_TOKENS = 1024
async def main():
async with Serverless() as client:
endpoint = await client.get_endpoint(name="my-vllm-endpoint")
system_prompt = (
"You are Qwen.\n"
"You are to only speak in English.\n"
)
user_prompt = "What is the integral of 2x^2 from 0 to 5?"
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
]
payload = {
"model": "Qwen/Qwen3-8B",
"messages": messages,
"max_tokens": MAX_TOKENS,
"temperature": 0.7,
"stream": True,
}
resp = await endpoint.request("/v1/chat/completions", payload, cost=MAX_TOKENS, stream=True)
stream = resp["response"]
printed_reasoning = False
printed_answer = False
async for event in stream:
delta = (event.get("choices") or [{}])[0].get("delta") or {}
reasoning = delta.get("reasoning_content")
if reasoning:
if not printed_reasoning:
printed_reasoning = True
print("Reasoning:\n")
print(reasoning, end="", flush=True)
content = delta.get("content", None)
if content:
if not printed_answer:
printed_answer = True
print("\n\nAnswer:\n")
print(content, end="", flush=True)
if __name__ == "__main__":
asyncio.run(main())