vLLM과 함께 쓰기

vLLM과 함께 쓰기

Vast.ai의 vLLM 서버리스 템플릿을 쓰면 Vast GPU 인스턴스에서 대규모 언어 모델을 추론할 수 있어요. 이 문서는 시작하기 위한 필수 환경 변수와 엔드포인트를 정리해 줘요. 완전한 PyWorker와 Client 구현은 vllm-pyworker 저장소에서 볼 수 있어요.

출처: Vast.ai 공식 문서 — vLLM with Vast.ai Serverless

환경 변수 (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())

더 알아보기 (Learn more)