-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1439 from jasonrandrews/new-content
New vLLM Learning Path
- Loading branch information
Showing
6 changed files
with
414 additions
and
0 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
content/learning-paths/servers-and-cloud-computing/vLLM/_index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
title: Large language models (LLMs) on Arm servers with vLLM | ||
|
||
draft: true | ||
cascade: | ||
draft: true | ||
|
||
minutes_to_complete: 45 | ||
|
||
who_is_this_for: This is an introductory topic for software developers and AI engineers interested in learning how to use vLLM (Virtual Large Language Model) on Arm servers. | ||
|
||
learning_objectives: | ||
- Build vLLM from source on an Arm server. | ||
- Download a Qwen LLM from Hugging Face. | ||
- Run local batch inference using vLLM. | ||
- Create and interact with an OpenAI compatible server provided by vLLM on your Arm server.. | ||
|
||
prerequisites: | ||
- An [Arm-based instance](/learning-paths/servers-and-cloud-computing/csp/) from a cloud service provider or a local Arm Linux computer with at least 8 CPUs and 16 GB RAM. | ||
|
||
author_primary: Jason Andrews | ||
|
||
### Tags | ||
skilllevels: Introductory | ||
subjects: ML | ||
armips: | ||
- Neoverse | ||
operatingsystems: | ||
- Linux | ||
tools_software_languages: | ||
- vLLM | ||
- LLM | ||
- GenAI | ||
- Python | ||
|
||
|
||
### FIXED, DO NOT MODIFY | ||
# ================================================================================ | ||
weight: 1 # _index.md always has weight of 1 to order correctly | ||
layout: "learningpathall" # All files under learning paths have this same wrapper | ||
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. | ||
--- |
28 changes: 28 additions & 0 deletions
28
content/learning-paths/servers-and-cloud-computing/vLLM/_next-steps.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
next_step_guidance: > | ||
Thank you for completing this learning path on how to build and run vLLM on Arm servers. You might be interested in learning how to further optimize and benchmark LLM performance on Arm-based platforms. | ||
recommended_path: "/learning-paths/servers-and-cloud-computing/benchmark-nlp/" | ||
|
||
further_reading: | ||
- resource: | ||
title: vLLM Documentation | ||
link: https://docs.vllm.ai/ | ||
type: documentation | ||
- resource: | ||
title: vLLM GitHub Repository | ||
link: https://github.com/vllm-project/vllm | ||
type: github | ||
- resource: | ||
title: Hugging Face Model Hub | ||
link: https://huggingface.co/models | ||
type: website | ||
|
||
|
||
# ================================================================================ | ||
# FIXED, DO NOT MODIFY | ||
# ================================================================================ | ||
weight: 21 # set to always be larger than the content in this path, and one more than 'review' | ||
title: "Next Steps" # Always the same | ||
layout: "learningpathall" # All files under learning paths have this same wrapper | ||
--- |
44 changes: 44 additions & 0 deletions
44
content/learning-paths/servers-and-cloud-computing/vLLM/_review.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
--- | ||
review: | ||
- questions: | ||
question: > | ||
What is the primary purpose of vLLM? | ||
answers: | ||
- "Operating System Development" | ||
- "Large Language Model Inference and Serving" | ||
- "Database Management" | ||
correct_answer: 2 | ||
explanation: > | ||
vLLM is designed for fast and efficient Large Language Model inference and serving. | ||
|
||
- questions: | ||
question: > | ||
In addition to Python, which extra programming languages are required by the vLLM build system? | ||
answers: | ||
- "Java" | ||
- "Rust" | ||
- "C++" | ||
- "Rust and C++" | ||
correct_answer: 4 | ||
explanation: > | ||
The vLLM build system requires the Rust toolchain and GCC for its compilation. | ||
|
||
- questions: | ||
question: > | ||
What is the VLLM_TARGET_DEVICE environment variable set to for building vLLM for Arm CPUs? | ||
answers: | ||
- "cuda" | ||
- "gpu" | ||
- "cpu" | ||
correct_answer: 3 | ||
explanation: > | ||
The VLLM_TARGET_DEVICE environment variable needs to be set to cpu to target the Arm processor. | ||
|
||
# ================================================================================ | ||
# FIXED, DO NOT MODIFY | ||
# ================================================================================ | ||
title: "Review" # Always the same title | ||
weight: 20 # Set to always be larger than the content in this path | ||
layout: "learningpathall" # All files under learning paths have this same wrapper | ||
--- |
110 changes: 110 additions & 0 deletions
110
content/learning-paths/servers-and-cloud-computing/vLLM/vllm-run.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
--- | ||
title: Run batch inference using vLLM | ||
weight: 3 | ||
|
||
### FIXED, DO NOT MODIFY | ||
layout: learningpathall | ||
--- | ||
|
||
## Use a model from Hugging Face | ||
|
||
vLLM is designed to work seamlessly with models from the Hugging Face Hub, | ||
|
||
The first time you run vLLM it downloads the required model. This means you don't have to explicitly download any models. | ||
|
||
If you want to use a model that requires you to request access or accept terms, you need to log in to Hugging Face using a token. | ||
|
||
```bash | ||
huggingface-cli login | ||
``` | ||
|
||
Enter your Hugging Face token. You can generate a token from [Hugging Face Hub](https://huggingface.co/) by clicking your profile on the top right corner and selecting `Access Tokens`. | ||
|
||
You also need to visit the Hugging Face link printed in the login output and accept the terms by clicking the "Agree and access repository" button or filling out the request for access form (depending on the model). | ||
|
||
To run batched inference without the need for a login, you can use the `Qwen/Qwen2.5-0.5B-Instruct` model. | ||
|
||
## Create a batch script | ||
|
||
To run inference with multiple prompts you can create a simple Python script to load a model and run the prompts. | ||
|
||
Use a text editor to save the Python script below in a file called `batch.py`. | ||
|
||
```python | ||
import json | ||
from vllm import LLM, SamplingParams | ||
|
||
# Sample prompts. | ||
prompts = [ | ||
"Write a hello world program in C", | ||
"Write a hello world program in Java", | ||
"Write a hello world program in Rust", | ||
] | ||
|
||
# Create a sampling params object. | ||
sampling_params = SamplingParams(temperature=0.8, top_p=0.95, max_tokens=256) | ||
|
||
# Create an LLM. | ||
llm = LLM(model="Qwen/Qwen2.5-0.5B-Instruct", dtype="bfloat16") | ||
|
||
# Generate texts from the prompts. The output is a list of RequestOutput objects | ||
# that contain the prompt, generated text, and other information. | ||
outputs = llm.generate(prompts, sampling_params) | ||
|
||
# Print the outputs. | ||
for output in outputs: | ||
prompt = output.prompt | ||
generated_text = output.outputs[0].text | ||
result = { | ||
"Prompt": prompt, | ||
"Generated text": generated_text | ||
} | ||
print(json.dumps(result, indent=4)) | ||
``` | ||
|
||
The script uses `bfloat16` precision. | ||
|
||
You can also change the length of the output using the `max_tokens` value. | ||
|
||
Run the Python script: | ||
|
||
```bash | ||
python ./batch.py | ||
``` | ||
|
||
The output shows vLLM starting, the model loading, and the batch processing of the 3 prompts: | ||
|
||
```output | ||
INFO 12-12 22:52:57 config.py:441] This model supports multiple tasks: {'generate', 'reward', 'embed', 'score', 'classify'}. Defaulting to 'generate'. | ||
WARNING 12-12 22:52:57 config.py:567] Async output processing is not supported on the current platform type cpu. | ||
WARNING 12-12 22:52:57 cpu.py:56] CUDA graph is not supported on CPU, fallback to the eager mode. | ||
WARNING 12-12 22:52:57 cpu.py:68] Environment variable VLLM_CPU_KVCACHE_SPACE (GB) for CPU backend is not set, using 4 by default. | ||
INFO 12-12 22:52:57 importing.py:15] Triton not installed or not compatible; certain GPU-related functions will not be available. | ||
INFO 12-12 22:52:57 llm_engine.py:250] Initializing an LLM engine (v0.6.4.post2.dev322+g72ff3a96) with config: VllmConfig(model_config=<vllm.config.ModelConfig object at 0xe1e8054ef5e0>, cache_config=<vllm.config.CacheConfig object at 0xe1e84500d780>, parallel_config=ParallelConfig(pipeline_parallel_size=1, tensor_parallel_size=1, worker_use_ray=False, max_parallel_loading_workers=None, disable_custom_all_reduce=False, tokenizer_pool_config=None, ray_workers_use_nsight=False, placement_group=None, distributed_executor_backend=None, worker_cls='vllm.worker.cpu_worker.CPUWorker', sd_worker_cls='auto', world_size=1, rank=0), scheduler_config=SchedulerConfig(runner_type='generate', max_num_batched_tokens=32768, max_num_seqs=256, max_model_len=32768, num_lookahead_slots=0, delay_factor=0.0, enable_chunked_prefill=False, is_multimodal_model=False, preemption_mode=None, num_scheduler_steps=1, multi_step_stream_outputs=True, send_delta_data=False, policy='fcfs', chunked_prefill_enabled=False), device_config=<vllm.config.DeviceConfig object at 0xe1e845163f40>, load_config=LoadConfig(load_format=<LoadFormat.AUTO: 'auto'>, download_dir=None, model_loader_extra_config=None, ignore_patterns=['original/**/*']), lora_config=None, speculative_config=None, decoding_config=DecodingConfig(guided_decoding_backend='xgrammar'), observability_config=ObservabilityConfig(otlp_traces_endpoint=None, collect_model_forward_time=False, collect_model_execute_time=False), prompt_adapter_config=None, quant_config=None, compilation_config=CompilationConfig(level=0, debug_dump_path='', backend='', custom_ops=[], splitting_ops=['vllm.unified_attention', 'vllm.unified_attention_with_output'], use_inductor=True, candidate_compile_sizes=[], inductor_compile_config={}, inductor_passes={}, use_cudagraph=False, cudagraph_num_of_warmups=0, cudagraph_capture_sizes=None, cudagraph_copy_inputs=False, pass_config=PassConfig(dump_graph_stages=[], dump_graph_dir=PosixPath('.'), enable_fusion=True, enable_reshape=True), compile_sizes=[], capture_sizes=[256, 248, 240, 232, 224, 216, 208, 200, 192, 184, 176, 168, 160, 152, 144, 136, 128, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 4, 2, 1], enabled_custom_ops=Counter(), disabled_custom_ops=Counter(), compilation_time=0.0, static_forward_context={}), kv_transfer_config=None, instance_id='5c715'),use_cached_outputs=False, | ||
INFO 12-12 22:52:58 cpu.py:33] Cannot use _Backend.FLASH_ATTN backend on CPU. | ||
INFO 12-12 22:52:58 selector.py:141] Using Torch SDPA backend. | ||
INFO 12-12 22:52:58 weight_utils.py:243] Using model weights format ['*.safetensors'] | ||
INFO 12-12 22:52:58 weight_utils.py:288] No model.safetensors.index.json found in remote. | ||
Loading safetensors checkpoint shards: 0% Completed | 0/1 [00:00<?, ?it/s] | ||
Loading safetensors checkpoint shards: 100% Completed | 1/1 [00:00<00:00, 12.97it/s] | ||
INFO 12-12 22:52:58 cpu_executor.py:186] # CPU blocks: 21845 | ||
INFO 12-12 22:52:59 llm_engine.py:447] init engine (profile, create kv cache, warmup model) took 0.25 seconds | ||
Processed prompts: 100%|███████████████████████████████████████| 3/3 [00:33<00:00, 11.10s/it, est. speed input: 0.63 toks/s, output: 20.61 toks/s] | ||
{ | ||
"Prompt": "Write a hello world program in C", | ||
"Generated text": "\n\nHere's a simple \"Hello, World!\" program written in C:\n\n```c\n#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}\n```\n\nThis program does the following:\n\n1. Includes the `<stdio.h>` header to use the `printf` function.\n2. Defines a `main` function, which is the entry point of the program.\n3. Uses `printf` to output the message \"Hello, World!\" to the console.\n4. Returns 0 to indicate that the program executed successfully.\n\nWhen you run this program, you should see the output:\n\n```\nHello, World!\n``` \n\nThis is the basic structure of a C program, providing a simple example of how to create, run, and display a basic program. Note that C is a high-level programming language, meaning that it provides low-level operations for users to interact with the hardware, but at the same time, it is a low-level language that needs to be compiled and linked into an executable file (.exe) that the computer's operating system can load and run. C, as a compiled language, often requires additional libraries and tools for use. For more information, you can refer to the C Programming Language documentation." | ||
} | ||
{ | ||
"Prompt": "Write a hello world program in Java", | ||
"Generated text": "\n\nCertainly! Below is a simple `HelloWorld.java` file that prints \"Hello, World!\" to the console when you run it:\n\n```java\npublic class HelloWorld {\n public static void main(String[] args) {\n System.out.println(\"Hello, World!\");\n }\n}\n```\n\nTo compile this program, you would use an integrated development environment (IDE) like IntelliJ IDEA, Eclipse, or NetBeans. Here is how you can compile it:\n\n1. Open a terminal or command prompt.\n2. Navigate to the directory where you saved the `HelloWorld.java` file.\n3. Compile the program using the following command:\n ```bash\n javac HelloWorld.java\n ```\n4. Run the compiled program using the following command:\n ```bash\n java HelloWorld\n ```\n\nThis will output:\n```\nHello, World!\n```" | ||
} | ||
{ | ||
"Prompt": "Write a hello world program in Rust", | ||
"Generated text": "\n\nCertainly! Here is a simple example of a `HelloWorld` program in Rust:\n\n```rust\nfn main() {\n println!(\"Hello, world!\");\n}\n```\n\n### Explanation:\n\n- `fn main()`: This is the entry point of the program.\n- `println!`: This function is used to print out the message `Hello, world!` to the console.\n- `println!`: The `println!` macro is used to print messages in Rust.\n\n### How to Run the Program:\n\n1. Make sure you have Rust installed on your system.\n2. Save the above code in a file with a `.rs` extension, e.g., `hello.rs`.\n3. Open a terminal or command prompt and navigate to the directory where the file is saved.\n4. Run the program by typing `rustc hello.rs` (if you're using `rustc`, you don't need to specify the file extension).\n5. After the program runs, it should print the message `Hello, world!` to the console.\n\n### Running in Development:\n\nIf you want to run the program in development mode to see the output in the terminal, you can use the `-o` flag:\n\n```sh\nrustc -o hello-dev hello.rs\n./" | ||
} | ||
``` | ||
|
||
You can try with other prompts and models such as `meta-llama/Llama-3.2-1B`. | ||
|
||
Continue to learn how to setup an OpenAI compatible server. |
83 changes: 83 additions & 0 deletions
83
content/learning-paths/servers-and-cloud-computing/vLLM/vllm-server.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
--- | ||
title: Run an OpenAI compatible server | ||
weight: 4 | ||
|
||
### FIXED, DO NOT MODIFY | ||
layout: learningpathall | ||
--- | ||
|
||
Instead of a batch run from Python, you can create an OpenAI compatible server. This allows you to leverage the power of large language models without relying on external APIs. | ||
|
||
Running a local LLM offers several advantages: | ||
|
||
Cost-Effective: Avoids the costs associated with using external APIs, especially for high-usage scenarios. | ||
Privacy: Keeps your data and prompts within your local environment, enhancing privacy and security. | ||
Offline Capability: Enables operation without an internet connection, making it ideal for scenarios with limited or unreliable network access. | ||
|
||
OpenAI compatibility means you can reuse existing software which was designed to communicate with OpenAI and have it talk to your local vLLM service. | ||
|
||
Run vLLM with the same `Qwen/Qwen2.5-0.5B-Instruct` model: | ||
|
||
```bash | ||
python3 -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2.5-0.5B-Instruct --dtype float16 | ||
``` | ||
|
||
The server output displays that it is ready for requests: | ||
|
||
```output | ||
INFO 12-12 22:54:40 cpu_executor.py:186] # CPU blocks: 21845 | ||
INFO 12-12 22:54:40 llm_engine.py:447] init engine (profile, create kv cache, warmup model) took 0.26 seconds | ||
INFO 12-12 22:54:41 api_server.py:560] Using supplied chat template: | ||
INFO 12-12 22:54:41 api_server.py:560] None | ||
INFO 12-12 22:54:41 launcher.py:19] Available routes are: | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /openapi.json, Methods: HEAD, GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /docs, Methods: HEAD, GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /docs/oauth2-redirect, Methods: HEAD, GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /redoc, Methods: HEAD, GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /health, Methods: GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /tokenize, Methods: POST | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /detokenize, Methods: POST | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /v1/models, Methods: GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /version, Methods: GET | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /v1/chat/completions, Methods: POST | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /v1/completions, Methods: POST | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /v1/embeddings, Methods: POST | ||
INFO 12-12 22:54:41 launcher.py:27] Route: /v1/score, Methods: POST | ||
INFO: Started server process [12905] | ||
INFO: Waiting for application startup. | ||
INFO: Application startup complete. | ||
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) | ||
``` | ||
|
||
You can submit requests to the server using the `curl` command. | ||
|
||
For example, run the command below using another terminal on the same server: | ||
|
||
```bash | ||
curl http://0.0.0.0:8000/v1/chat/completions \ | ||
-H "Content-Type: application/json" \ | ||
-H "Authorization: Bearer DUMMY" \ | ||
-d '{ | ||
"model": "Qwen/Qwen2.5-0.5B-Instruct", | ||
"messages": [ | ||
{ | ||
"role": "system", | ||
"content": "You are a helpful assistant." | ||
}, | ||
{ | ||
"role": "user", | ||
"content": "Write a hello world program in C" | ||
} | ||
] | ||
}' | ||
``` | ||
|
||
The server processes the request and the output prints the results: | ||
|
||
```output | ||
"id":"chatcmpl-6677cb4263b34d18b436b9cb8c6a5a65","object":"chat.completion","created":1734044182,"model":"Qwen/Qwen2.5-0.5B-Instruct","choices":[{"index":0,"message":{"role":"assistant","content":"Certainly! Here is a simple \"Hello, World!\" program in C:\n\n```c\n#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}\n```\n\nThis program defines a function called `main` which contains the body of the program. Inside the `main` function, it calls the `printf` function to display the text \"Hello, World!\" to the console. The `return 0` statement indicates that the program was successful and the program has ended.\n\nTo compile and run this program:\n\n1. Save the code above to a file named `hello.c`.\n2. Open a terminal or command prompt.\n3. Navigate to the directory where you saved the file.\n4. Compile the program using the following command:\n ```\n gcc hello.c -o hello\n ```\n5. Run the compiled program using the following command:\n ```\n ./hello\n ```\n Or simply type `hello` in the terminal.\n\nYou should see the output:\n\n```\nHello, World!\n```","tool_calls":[]},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"usage":{"prompt_tokens":26,"total_tokens":241,"completion_tokens":215,"prompt_tokens_details":null},"prompt_logprobs":null} | ||
``` | ||
|
||
There are many other experiments you can try. Most Hugging Face models have a `Use this model` button on the top right of the model card with the instructions for vLLM. You can now use these instructions on your Arm Linux computer. | ||
|
||
You can also try out OpenAI compatible chat clients to connect to the served model. |
Oops, something went wrong.