From 30ab48e314840282e1fea703153c46b04e8fd036 Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Fri, 7 Feb 2025 16:49:19 +0800 Subject: [PATCH] add vLLM (#3145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 增加 vllm * feat: add vLLM --- vllm/0.7.2/data.yml | 51 ++++++++++++++++++++++++++++++++++ vllm/0.7.2/docker-compose.yml | 27 ++++++++++++++++++ vllm/README.md | 49 ++++++++++++++++++++++++++++++++ vllm/README_en.md | 49 ++++++++++++++++++++++++++++++++ vllm/data.yml | 28 +++++++++++++++++++ vllm/logo.png | Bin 0 -> 10410 bytes 6 files changed, 204 insertions(+) create mode 100644 vllm/0.7.2/data.yml create mode 100644 vllm/0.7.2/docker-compose.yml create mode 100644 vllm/README.md create mode 100644 vllm/README_en.md create mode 100644 vllm/data.yml create mode 100644 vllm/logo.png diff --git a/vllm/0.7.2/data.yml b/vllm/0.7.2/data.yml new file mode 100644 index 000000000..8bd46de46 --- /dev/null +++ b/vllm/0.7.2/data.yml @@ -0,0 +1,51 @@ +additionalProperties: + formFields: + - default: 8800 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + label: + en: Port + ja: ポート + ms: Port + pt-br: Porta + ru: Порт + zh-Hant: 端口 + zh: 端口 + ko: 포트 + - default: "" + edit: true + envKey: HUGGING_FACE_HUB_TOKEN + labelEn: Hugging Face Token + labelZh: Hugging Face Token + required: true + type: text + label: + en: Hugging Face Token + ja: Hugging Face Token + ms: Hugging Face Token + pt-br: Hugging Face Token + ru: Hugging Face Token + zh-Hant: Hugging Face Token + zh: Hugging Face Token + ko: Hugging Face Token + - default: facebook/opt-125m + edit: true + envKey: MODEL + labelEn: 模型 + labelZh: Model + required: true + type: text + label: + en: Model + ja: モデル + ms: Model + pt-br: Modelo + ru: Модель + zh-Hant: 模型 + zh: Model + ko: 모델 \ No newline at end of file diff --git a/vllm/0.7.2/docker-compose.yml b/vllm/0.7.2/docker-compose.yml new file mode 100644 index 000000000..da2c82ed0 --- /dev/null +++ b/vllm/0.7.2/docker-compose.yml @@ -0,0 +1,27 @@ +services: + vllm: + image: vllm/vllm-openai:v0.7.2 + container_name: ${CONTAINER_NAME} + restart: always + runtime: nvidia + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [gpu] + networks: + - 1panel-network + volumes: + - ./cache/huggingface:/root/.cache/huggingface + environment: + HUGGING_FACE_HUB_TOKEN: ${HUGGING_FACE_HUB_TOKEN} + HF_ENDPOINT: https://hf-mirror.com + ports: + - ${PANEL_APP_PORT_HTTP}:8000 + ipc: host + command: --model ${MODEL} +networks: + 1panel-network: + external: true diff --git a/vllm/README.md b/vllm/README.md new file mode 100644 index 000000000..e22e0bc9e --- /dev/null +++ b/vllm/README.md @@ -0,0 +1,49 @@ +## 使用说明 +1. 在 https://huggingface.co/ 注册账号并获取模型权限创建 token +2. 机器上有 Nvidia GPU +3. 修改 /etc/docker/daemon.json 并增加 +``` + "runtimes": { + "nvidia": { + "path": "nvidia-container-runtime", + "runtimeArgs": [] + } + } +``` +4. 安装 nvidia-container-runtime 和 nvidia-docker2 组件 + + +## About +vLLM is a fast and easy-to-use library for LLM inference and serving. + +vLLM is fast with: + +- State-of-the-art serving throughput +- Efficient management of attention key and value memory with **PagedAttention** +- Continuous batching of incoming requests +- Fast model execution with CUDA/HIP graph +- Quantizations: [GPTQ](https://arxiv.org/abs/2210.17323), [AWQ](https://arxiv.org/abs/2306.00978), INT4, INT8, and FP8. +- Optimized CUDA kernels, including integration with FlashAttention and FlashInfer. +- Speculative decoding +- Chunked prefill + +**Performance benchmark**: We include a [performance benchmark](https://buildkite.com/vllm/performance-benchmark/builds/4068) that compares the performance of vLLM against other LLM serving engines ([TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM), [text-generation-inference](https://github.com/huggingface/text-generation-inference) and [lmdeploy](https://github.com/InternLM/lmdeploy)). + +vLLM is flexible and easy to use with: + +- Seamless integration with popular Hugging Face models +- High-throughput serving with various decoding algorithms, including *parallel sampling*, *beam search*, and more +- Tensor parallelism and pipeline parallelism support for distributed inference +- Streaming outputs +- OpenAI-compatible API server +- Support NVIDIA GPUs, AMD CPUs and GPUs, Intel CPUs and GPUs, PowerPC CPUs, TPU, and AWS Neuron. +- Prefix caching support +- Multi-lora support + +vLLM seamlessly supports most popular open-source models on HuggingFace, including: +- Transformer-like LLMs (e.g., Llama) +- Mixture-of-Expert LLMs (e.g., Mixtral) +- Embedding Models (e.g. E5-Mistral) +- Multi-modal LLMs (e.g., LLaVA) + +Find the full list of supported models [here](https://docs.vllm.ai/en/latest/models/supported_models.html). \ No newline at end of file diff --git a/vllm/README_en.md b/vllm/README_en.md new file mode 100644 index 000000000..49926969a --- /dev/null +++ b/vllm/README_en.md @@ -0,0 +1,49 @@ +## 使用说明 +1. Register an account at https://huggingface.co/ and get model access to create a token. +2. Ensure the machine has an Nvidia GPU. +3. Modify the /etc/docker/daemon.json file and add: +``` + "runtimes": { + "nvidia": { + "path": "nvidia-container-runtime", + "runtimeArgs": [] + } + } +``` +4. Install the nvidia-container-runtime and nvidia-docker2 components. + + +## About +vLLM is a fast and easy-to-use library for LLM inference and serving. + +vLLM is fast with: + +- State-of-the-art serving throughput +- Efficient management of attention key and value memory with **PagedAttention** +- Continuous batching of incoming requests +- Fast model execution with CUDA/HIP graph +- Quantizations: [GPTQ](https://arxiv.org/abs/2210.17323), [AWQ](https://arxiv.org/abs/2306.00978), INT4, INT8, and FP8. +- Optimized CUDA kernels, including integration with FlashAttention and FlashInfer. +- Speculative decoding +- Chunked prefill + +**Performance benchmark**: We include a [performance benchmark](https://buildkite.com/vllm/performance-benchmark/builds/4068) that compares the performance of vLLM against other LLM serving engines ([TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM), [text-generation-inference](https://github.com/huggingface/text-generation-inference) and [lmdeploy](https://github.com/InternLM/lmdeploy)). + +vLLM is flexible and easy to use with: + +- Seamless integration with popular Hugging Face models +- High-throughput serving with various decoding algorithms, including *parallel sampling*, *beam search*, and more +- Tensor parallelism and pipeline parallelism support for distributed inference +- Streaming outputs +- OpenAI-compatible API server +- Support NVIDIA GPUs, AMD CPUs and GPUs, Intel CPUs and GPUs, PowerPC CPUs, TPU, and AWS Neuron. +- Prefix caching support +- Multi-lora support + +vLLM seamlessly supports most popular open-source models on HuggingFace, including: +- Transformer-like LLMs (e.g., Llama) +- Mixture-of-Expert LLMs (e.g., Mixtral) +- Embedding Models (e.g. E5-Mistral) +- Multi-modal LLMs (e.g., LLaVA) + +Find the full list of supported models [here](https://docs.vllm.ai/en/latest/models/supported_models.html). \ No newline at end of file diff --git a/vllm/data.yml b/vllm/data.yml new file mode 100644 index 000000000..5c934dda3 --- /dev/null +++ b/vllm/data.yml @@ -0,0 +1,28 @@ +name: vLLM +tags: + - AI / 大模型 +title: 用于大语言模型的高吞吐量和内存高效的推理和服务引擎 +description: 用于大语言模型的高吞吐量和内存高效的推理和服务引擎 +additionalProperties: + key: vllm + name: vLLM + tags: + - AI + shortDescZh: 用于大语言模型的高吞吐量和内存高效的推理和服务引擎 + shortDescEn: A high-throughput and memory-efficient inference and serving engine for LLMs + description: + en: A high-throughput and memory-efficient inference and serving engine for LLMs + ja: 大規模言語モデル向けの高スループットでメモリ効率の良い推論およびサービスエンジン + ms: Enjin inferens dan perkhidmatan yang cekap memori dan berkapasiti tinggi untuk LLM + pt-br: Motor de inferência e serviço eficiente em memória e de alto rendimento para LLMs + ru: Высокопроизводительный и эффективный по памяти движок вывода и обслуживания для LLM + zh-Hant: 用於大語言模型的高吞吐量和內存高效的推理和服務引擎 + zh: 用于大语言模型的高吞吐量和内存高效的推理和服务引擎 + ko: 대형 언어 모델을 위한 고 처리량 및 메모리 효율적 추론 및 서비스 엔진 + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 13 + website: https://github.com/vllm-project/vllm + github: https://github.com/vllm-project/vllm + document: https://docs.vllm.ai/en/latest/ diff --git a/vllm/logo.png b/vllm/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a8fe10f3be4f80898188004748a01c665ed9f5d4 GIT binary patch literal 10410 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