importosfromoptimum.rblnimportRBLNLlamaForCausalLMmodel_id="meta-llama/Llama-3.1-8B-Instruct"# Compile and exportmodel=RBLNLlamaForCausalLM.from_pretrained(model_id=model_id,export=True,rbln_batch_size=1,rbln_max_seq_len=131_072,rbln_num_devices=1,rbln_kvcache_partition_len=8_192,)# Save compiled results to diskmodel.save_pretrained(os.path.basename(model_id))
importosfromoptimum.rblnimportRBLNLlamaForCausalLMmodel_id="meta-llama/Llama-3.1-8B-Instruct"# Compile and exportmodel=RBLNLlamaForCausalLM.from_pretrained(model_id=model_id,export=True,rbln_batch_size=1,rbln_max_seq_len=131_072,rbln_num_devices=8,rbln_kvcache_partition_len=16_384,)# Save compiled results to diskmodel.save_pretrained(os.path.basename(model_id))
Ray Serve에서 리소스를 할당하는 방식은 각 서빙 작업(Actor, Deployment)별로 resources 파라미터를 통해 NPU 자원을 할당할 수 있습니다.
아래 Actor는 @ray.remote(resources={"RBLN": <NUM_NPUS>})로 RBLN NPU 리소스를 요청하는 방법을 보여줍니다. <NUM_NPUS>는 컴파일할 때 사용한 rbln_num_devices 값과 같게 설정합니다. RBLNActor 클래스는 할당된 RBLN NPU ID를 Serve Deployment로 전달하는데 사용합니다. 이에 대한 자세한 내용은 Ray에서 RBLN NPU 사용에서 확인할 수 있습니다.
Ray Serve deployment는 @serve.deployment 데코레이터를 활용하여 클래스를 하나의 Deployment(배포 단위)로 정의합니다. 이 데코레이터를 적용하면 해당 클래스가 Ray Serve의 서비스 엔드포인트로 등록되어, 각 Deployment의 라이프사이클(배포, 확장, 업데이트 등)과 관리를 Ray Serve가 담당하게 됩니다.
importjsonimportosfromunittest.mockimportMagicMockimportrayfromfastapiimportFastAPI,HTTPExceptionfromrayimportservefromstarlette.requestsimportRequestfromstarlette.responsesimportStreamingResponsefromvllmimportAsyncEngineArgs,AsyncLLMEnginefromvllm.entrypoints.openai.chat_completion.protocolimport(ChatCompletionRequest,ChatCompletionResponse,)fromvllm.entrypoints.openai.chat_completion.servingimportOpenAIServingChatfromvllm.entrypoints.openai.completion.protocolimportCompletionRequestfromvllm.entrypoints.openai.completion.servingimportOpenAIServingCompletionfromvllm.entrypoints.openai.models.protocolimportBaseModelPathfromvllm.entrypoints.openai.models.servingimportOpenAIServingModelsfromvllm.entrypoints.serve.engine.protocolimportErrorResponsefromvllm.renderers.online_rendererimportOnlineRendererapp=FastAPI()ray.init(resources={"RBLN":1})@ray.remote(resources={"RBLN":1})classRBLNActor:defgetDeviceId(self):returnray.get_runtime_context().get_accelerator_ids()["RBLN"]@serve.deployment(num_replicas=1,ray_actor_options={"num_cpus":16})@serve.ingress(app)classLlama3_1__8B:def__init__(self,rbln_actor:RBLNActor):""" Initialize actor. :return: """self.engine=Noneself.rbln_actor=rbln_actorself.model_name="Llama-3.1-8B-Instruct"self.raw_request=Noneself.vllm_engine=Noneself.openai_serving_models=Noneself.completion_service=Noneself.chat_completion_service=Noneself.ids=ray.get(rbln_actor.getDeviceId.remote())self.os_environment_vars()self.initialize()defos_environment_vars(self):""" Redefine the environment variables to be passed to the RBLN runtime and vLLM :return: """ifself.idsisNoneorlen(self.ids)<=0:os.environ.pop("RBLN_DEVICES")os.environ["RBLN_DEVICES"]=",".join(self.ids)os.environ["VLLM_WORKER_MULTIPROC_METHOD"]="spawn"definitialize(self):""" Initialize model. This will be called during model loading time :return: """vllm_engine_args=AsyncEngineArgs(model=self.model_name)self.vllm_engine=AsyncLLMEngine.from_engine_args(vllm_engine_args)self.openai_serving_models=OpenAIServingModels(engine_client=self.vllm_engine,base_model_paths=[BaseModelPath(name=self.model_name,model_path=os.getcwd())],)openai_serving_render=OnlineRenderer(model_config=self.vllm_engine.model_config,renderer=self.vllm_engine.renderer,request_logger=None,chat_template=None,chat_template_content_format="auto",)self.completion_service=OpenAIServingCompletion(self.vllm_engine,self.openai_serving_models,online_renderer=openai_serving_render,request_logger=None,)self.chat_completion_service=OpenAIServingChat(self.vllm_engine,self.openai_serving_models,"assistant",online_renderer=openai_serving_render,request_logger=None,chat_template_content_format="auto",chat_template=None,)asyncdefisd():returnFalseself.raw_request=MagicMock()self.raw_request.headers={}self.raw_request.is_disconnected=isd@app.post("/v1/chat/completions")asyncdefchat_completion(self,http_request:Request):""" Handle chat completion request. :param http_request: The HTTP request object :return: The chat completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:ChatCompletionRequest=ChatCompletionRequest.model_validate(json_string)g=awaitself.chat_completion_service.create_chat_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]@app.post("/v1/completions")asyncdefcompletion(self,http_request:Request):""" Handle completion request. :param http_request: The HTTP request object :return: The completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:CompletionRequest=CompletionRequest.model_validate(json_string)g=awaitself.completion_service.create_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]rbln_actor=RBLNActor.remote()app=Llama3_1__8B.bind(rbln_actor)
importjsonimportosfromunittest.mockimportMagicMockimportrayfromfastapiimportFastAPI,HTTPExceptionfromrayimportservefromstarlette.requestsimportRequestfromstarlette.responsesimportStreamingResponsefromvllmimportAsyncEngineArgs,AsyncLLMEnginefromvllm.entrypoints.openai.chat_completion.protocolimport(ChatCompletionRequest,ChatCompletionResponse,)fromvllm.entrypoints.openai.chat_completion.servingimportOpenAIServingChatfromvllm.entrypoints.openai.completion.protocolimportCompletionRequestfromvllm.entrypoints.openai.completion.servingimportOpenAIServingCompletionfromvllm.entrypoints.openai.models.protocolimportBaseModelPathfromvllm.entrypoints.openai.models.servingimportOpenAIServingModelsfromvllm.entrypoints.serve.engine.protocolimportErrorResponsefromvllm.renderers.online_rendererimportOnlineRendererapp=FastAPI()ray.init(resources={"RBLN":8})@ray.remote(resources={"RBLN":8})classRBLNActor:defgetDeviceId(self):returnray.get_runtime_context().get_accelerator_ids()["RBLN"]@serve.deployment(num_replicas=1,ray_actor_options={"num_cpus":16})@serve.ingress(app)classLlama3_1__8B:def__init__(self,rbln_actor:RBLNActor):""" Initialize actor. :return: """self.engine=Noneself.rbln_actor=rbln_actorself.model_name="Llama-3.1-8B-Instruct"self.raw_request=Noneself.vllm_engine=Noneself.openai_serving_models=Noneself.completion_service=Noneself.chat_completion_service=Noneself.ids=ray.get(rbln_actor.getDeviceId.remote())self.os_environment_vars()self.initialize()defos_environment_vars(self):""" Redefine the environment variables to be passed to the RBLN runtime and vLLM :return: """ifself.idsisNoneorlen(self.ids)<=0:os.environ.pop("RBLN_DEVICES")os.environ["RBLN_DEVICES"]=",".join(self.ids)os.environ["VLLM_WORKER_MULTIPROC_METHOD"]="spawn"definitialize(self):""" Initialize model. This will be called during model loading time :return: """vllm_engine_args=AsyncEngineArgs(model=self.model_name)self.vllm_engine=AsyncLLMEngine.from_engine_args(vllm_engine_args)self.openai_serving_models=OpenAIServingModels(engine_client=self.vllm_engine,base_model_paths=[BaseModelPath(name=self.model_name,model_path=os.getcwd())],)openai_serving_render=OnlineRenderer(model_config=self.vllm_engine.model_config,renderer=self.vllm_engine.renderer,request_logger=None,chat_template=None,chat_template_content_format="auto",)self.completion_service=OpenAIServingCompletion(self.vllm_engine,self.openai_serving_models,online_renderer=openai_serving_render,request_logger=None,)self.chat_completion_service=OpenAIServingChat(self.vllm_engine,self.openai_serving_models,"assistant",online_renderer=openai_serving_render,request_logger=None,chat_template_content_format="auto",chat_template=None,)asyncdefisd():returnFalseself.raw_request=MagicMock()self.raw_request.headers={}self.raw_request.is_disconnected=isd@app.post("/v1/chat/completions")asyncdefchat_completion(self,http_request:Request):""" Handle chat completion request. :param http_request: The HTTP request object :return: The chat completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:ChatCompletionRequest=ChatCompletionRequest.model_validate(json_string)g=awaitself.chat_completion_service.create_chat_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]@app.post("/v1/completions")asyncdefcompletion(self,http_request:Request):""" Handle completion request. :param http_request: The HTTP request object :return: The completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:CompletionRequest=CompletionRequest.model_validate(json_string)g=awaitself.completion_service.create_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]rbln_actor=RBLNActor.remote()app=Llama3_1__8B.bind(rbln_actor)
echo'{"model": "Llama-3.1-8B-Instruct","prompt": "A robot may not injure a human being","stream": false}'|curl-sN-H"Content-Type: application/json"-XPOST--data-binary@-\http://localhost:8000/v1/completions|jq.
[{"id":"cmpl-790b3169a1c1428a8912140848b42753","object":"text_completion","created":1762993969,"model":"Llama-3.1-8B-Instruct","choices":[{"index":0,"text":" or, through inaction, allow a human being to come to harm.\nA","logprobs":null,"finish_reason":"length","stop_reason":null,"token_ids":null,"prompt_logprobs":null,"prompt_token_ids":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":10,"total_tokens":26,"completion_tokens":16,"prompt_tokens_details":null},"kv_transfer_params":null}]
echo'{"model": "Llama-3.1-8B-Instruct","messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Who won the world series in 2020?"}, {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, {"role": "user", "content": "Where was it played?"}],"temperature": 0.0,"max_tokens": 50,"stream": false}'|curl-sN-H"Content-Type: application/json"-XPOST--data-binary@-\http://localhost:8000/v1/chat/completions|jq.
[{"id":"chatcmpl-bad227512c58497eb40dcc1287f29b50","object":"chat.completion","created":1762994293,"model":"Llama-3.1-8B-Instruct","choices":[{"index":0,"message":{"role":"assistant","content":"The 2020 World Series was played at Globe Life Field in Arlington, Texas. It was a neutral site due to the COVID-19 pandemic, and the Dodgers played the Tampa Bay Rays in the series.","refusal":null,"annotations":null,"audio":null,"function_call":null,"tool_calls":[],"reasoning_content":null},"logprobs":null,"finish_reason":"stop","stop_reason":null,"token_ids":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":79,"total_tokens":122,"completion_tokens":43,"prompt_tokens_details":null},"prompt_logprobs":null,"prompt_token_ids":null,"kv_transfer_params":null}]