Running Inference on Local LLMs with vLLM
This guide explains how to run inference on local LLMs with vLLM using GPUs on DCC. Unlike Ollama, it does not require launching a separate inference server and can be run directly as a Python application.
The code for this example is available at: https://github.com/DukeRC/code/tree/main/Running-Inference-on-Local-LLMs-with-vLLM
As large language models (LLMs) continue to grow in popularity, efficient and scalable inference tools are becoming increasingly important in HPC environments. While Ollama is a strong option for smaller-scale inference, vLLM is better suited for larger-scale HPC workloads allowing for higher throughput, lower latency, and more concurrent requests. For a detailed performance comparison, see Ollama vs. vLLM: A deep dive into performance benchmarking.
This guide walks you through setting up and running inference on local LLMs with vLLM on DCC GPUs.
Initial setup
Assuming you have a Python environment available (e.g., Miniconda, Miniforge), first create a new environment and activate it.
Then install vLLM,
Additionally, install the dotenv package to manage environment variables,
Running Inference with vLLM
We will run inference on a single NVIDIA RTX 5000 Ada Generation GPU using the Qwen/Qwen2-7B model from Hugging Face. We will first need to set up some environment variables to ensure that vLLM can access the model directory and connect to Hugging Face to download it if it is not already cached.
First, create a directory in your work directory for this example,
Within this directory, create a .env file to store the environment variables,
echo 'HF_TOKEN=your_hugging_face_api_token' > /work/${USER}/vLLM/.env
chmod 600 /work/${USER}/vLLM/.env
The 600 permission ensures that only the owner can read and write the file, keeping your Hugging Face API token secure.
Next, add the following to your ~/.bashrc to set the Hugging Face cache directory,
Save the following Python script in the working directory as vllm_local.py,
#!/usr/bin/env python
#
# An example of using vLLM with a local model.
#
# Usage:
# 1. Set HF_HOME to control where Hugging Face cache is stored.
# export HF_HOME=/path/to/hf_cache
# 2. Set the HF_TOKEN environmental variable in a .env file in the root of the directory.
# 3. Run the script:
# ./vllm_local.py
import os
from dotenv import load_dotenv
os.environ["VLLM_CONFIGURE_LOGGING"] = "0"
from vllm import LLM, SamplingParams
# Model configuration
MODEL = "Qwen/Qwen2-7B"
SAMPLING_PARAMS = SamplingParams(temperature=0.1, top_p=0.95, max_tokens=256)
# Array of prompts
PROMPTS = ["Tell me about Sri Lanka", "Why is the sky blue?", "Write a Python code that calculates the Fibonacci sequence up to 15."]
def main():
# Connect to Hugging Face with HF_TOKEN from .env
load_dotenv()
# Launch LLM
llm = LLM(model=MODEL, trust_remote_code=True)
outputs = llm.generate(PROMPTS, SAMPLING_PARAMS)
print("-" * 60)
print(f"Model: {MODEL}")
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}")
print("Output:")
print(generated_text.strip())
print("-" * 60)
if __name__ == "__main__":
main()
Feel free to change the prompts in the PROMPTS array as you like.
Let's request a slurm interactive session on an NVIDIA RTX 5000 Ada Generation GPU. You may also submit the script as a slurm batch job if you prefer.
Once your allocation is ready, activate the conda environment we created earlier and run the script,
You should see the generated outputs for each prompt in the terminal.
If you would like a chat session instead of hard-coded prompts, use the following script,
#!/usr/bin/env python
#
# An example of using vLLM with a local model for interactive chat.
#
# Usage:
# 1. Set HF_HOME to control where Hugging Face cache is stored.
# export HF_HOME=/path/to/hf_cache
# 2. Set the HF_TOKEN environmental variable in a .env file in the root of the directory.
# 3. Run the script:
# ./vllm_local_chat.py
import os
from dotenv import load_dotenv
os.environ["VLLM_CONFIGURE_LOGGING"] = "0"
from vllm import LLM, SamplingParams
# Model configuration
MODEL = "Qwen/Qwen2-7B"
SAMPLING_PARAMS = SamplingParams(temperature=0.1, top_p=0.95, max_tokens=256)
SYSTEM_PROMPT = "You are a helpful assistant."
def main() -> None:
# Connect to Hugging Face with HF_TOKEN from .env
load_dotenv()
llm = LLM(model=MODEL, trust_remote_code=True)
conversation = [{"role": "system", "content": SYSTEM_PROMPT}]
print(f"Model: {MODEL}")
print(f"Enter {sorted({"exit", "quit", "q"})} to exit.")
print("-" * 60)
while True:
try:
user_text = input("You: ").strip()
except (EOFError, KeyboardInterrupt):
print("\nExiting chat.")
break
if not user_text:
continue
if user_text.lower() in {"exit", "quit", "q"}:
print("Exiting chat.")
break
conversation.append({"role": "user", "content": user_text})
outputs = llm.chat(
conversation, sampling_params=SAMPLING_PARAMS, use_tqdm=False
)
assistant_text = outputs[0].outputs[0].text.strip()
print(f"Assistant: {assistant_text}\n")
conversation.append({"role": "assistant", "content": assistant_text})
if __name__ == "__main__":
main()