Mô hình và nền tảng AI
Tối ưu hóa việc triển khai LLM: vLLM PagedAttention và tương lai của việc phục vụ AI hiệu quả
Các mô hình ngôn ngữ lớn (LLM) khi được triển khai trên các ứng dụng thực tế gặp phải những thách thức độc đáo, đặc biệt là về tài nguyên tính toán, độ trễ và hiệu quả chi phí. Trong hướng dẫn toàn diện này, chúng tôi sẽ khám phá cảnh quan của việc phục vụ LLM, với sự tập trung đặc biệt vào vLLM (mô hình ngôn ngữ vector), một giải pháp đang thay đổi cách chúng ta triển khai và tương tác với những mô hình mạnh mẽ này.
Thách thức của việc phục vụ các mô hình ngôn ngữ lớn
Trước khi đi sâu vào các giải pháp cụ thể, hãy xem xét các thách thức chính làm cho việc phục vụ LLM trở thành một nhiệm vụ phức tạp:
Tài nguyên tính toán
LLM nổi tiếng với số lượng tham số khổng lồ, từ hàng tỷ đến hàng trăm tỷ. Ví dụ, GPT-3 có 175 tỷ tham số, trong khi các mô hình mới hơn như GPT-4 được ước tính có nhiều tham số hơn. Kích thước khổng lồ này chuyển thành yêu cầu tính toán đáng kể cho việc suy luận.
Ví dụ:
Hãy xem xét một mô hình LLM tương đối khiêm tốn với 13 tỷ tham số, chẳng hạn như LLaMA-13B. Ngay cả mô hình này cũng yêu cầu:
– Khoảng 26 GB bộ nhớ chỉ để lưu trữ các tham số mô hình (giả sử độ chính xác 16 bit)
– Bộ nhớ bổ sung cho các hoạt động, cơ chế chú ý và tính toán trung gian
– Năng lực tính toán GPU đáng kể cho suy luận thời gian thực
Độ trễ
Trong nhiều ứng dụng, chẳng hạn như các rô-bốt trò chuyện hoặc tạo nội dung thời gian thực, độ trễ thấp là rất quan trọng để có trải nghiệm người dùng tốt. Tuy nhiên, sự phức tạp của LLM có thể dẫn đến thời gian xử lý đáng kể, đặc biệt là đối với các chuỗi dài hơn.
Ví dụ:
Hãy tưởng tượng một rô-bốt dịch vụ khách hàng được hỗ trợ bởi LLM. Nếu mỗi phản hồi mất vài giây để tạo ra, cuộc trò chuyện sẽ cảm thấy không tự nhiên và khó chịu đối với người dùng.
Chi phí
Phần cứng cần thiết để chạy LLM ở quy mô lớn có thể rất tốn kém. Các GPU hoặc TPU cao cấp thường là cần thiết, và tiêu thụ năng lượng của những hệ thống này là đáng kể.
Ví dụ:
Chạy một cụm GPU NVIDIA A100 (thường được sử dụng cho suy luận LLM) có thể tiêu tốn hàng nghìn đô la mỗi ngày về phí tính toán trên đám mây.
Các phương pháp truyền thống để phục vụ LLM
Trước khi khám phá các giải pháp tiên tiến hơn, hãy xem xét một số phương pháp truyền thống để phục vụ LLM:
Triển khai đơn giản với Hugging Transformers
Thư viện Hugging Face Transformers cung cấp một cách đơn giản để triển khai LLM, nhưng nó không được tối ưu hóa cho việc phục vụ với lưu lượng truy cập cao.
Ví dụ mã:
“`python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_name = “meta-llama/Llama-2-13b-hf”
model = AutoModelForCausalLM.from_pretrained(model_name, device_map=”auto”)
tokenizer = AutoTokenizer.from_pretrained(model_name)
def generate_text(prompt, max_length=100):
inputs = tokenizer(prompt, return_tensors=”pt”).to(model.device)
outputs = model.generate(**inputs, max_length=max_length)
return tokenizer.decode(outputs[0], skip_special_tokens=True)
print(generate_text(“Tương lai của AI là”))
“`
Mặc dù phương pháp này hoạt động, nhưng nó không phù hợp cho các ứng dụng có lưu lượng truy cập cao do sử dụng tài nguyên không hiệu quả và thiếu tối ưu hóa cho việc phục vụ.
Sử dụng TorchServe hoặc các khung tương tự
Các khung như TorchServe cung cấp khả năng phục vụ mạnh mẽ hơn, bao gồm cân bằng tải và quản lý phiên bản mô hình. Tuy nhiên, chúng vẫn không giải quyết các thách thức cụ thể của việc phục vụ LLM, chẳng hạn như quản lý bộ nhớ hiệu quả cho các mô hình lớn.
Hiểu về quản lý bộ nhớ trong việc phục vụ LLM
Quản lý bộ nhớ hiệu quả là rất quan trọng để phục vụ các mô hình ngôn ngữ lớn (LLM) do yêu cầu tài nguyên tính toán đáng kể. Các hình ảnh sau minh họa các khía cạnh khác nhau của quản lý bộ nhớ, là một phần quan trọng của việc tối ưu hóa hiệu suất LLM.
Bộ nhớ phân đoạn so với bộ nhớ trang
Những hình ảnh này so sánh các kỹ thuật quản lý bộ nhớ phân đoạn và trang, thường được sử dụng trong các hệ điều hành (OS).
- Bộ nhớ phân đoạn: Kỹ thuật này chia bộ nhớ thành các phân đoạn khác nhau, mỗi phân đoạn tương ứng với một chương trình hoặc quá trình khác nhau. Ví dụ, trong bối cảnh phục vụ LLM, các phân đoạn khác nhau có thể được phân bổ cho các thành phần khác nhau của mô hình, chẳng hạn như phân tích từ, nhúng và cơ chế chú ý. Mỗi phân đoạn có thể tăng hoặc giảm kích thước độc lập, cung cấp tính linh hoạt nhưng có thể dẫn đến phân mảnh nếu các phân đoạn không được quản lý đúng cách.
- Bộ nhớ trang: Ở đây, bộ nhớ được chia thành các trang có kích thước cố định, được ánh xạ đến bộ nhớ vật lý. Các trang có thể được hoán đổi vào và ra khi cần, cho phép sử dụng hiệu quả tài nguyên bộ nhớ. Trong việc phục vụ LLM, điều này có thể quan trọng để quản lý lượng bộ nhớ lớn cần thiết để lưu trữ trọng số mô hình và tính toán trung gian.
Quản lý bộ nhớ trong OS so với vLLM
Hình ảnh này đối chiếu quản lý bộ nhớ truyền thống trong OS với cách tiếp cận quản lý bộ nhớ được sử dụng trong vLLM.
- Quản lý bộ nhớ trong OS: Trong các hệ điều hành truyền thống, các quá trình (ví dụ: Quá trình A và Quá trình B) được phân bổ các trang bộ nhớ (Trang 0, Trang 1, v.v.) trong bộ nhớ vật lý. Việc phân bổ này có thể dẫn đến phân mảnh theo thời gian khi các quá trình yêu cầu và giải phóng bộ nhớ.
- Quản lý bộ nhớ trong vLLM: Khung vLLM sử dụng bộ nhớ đệm Key-Value (KV) để quản lý bộ nhớ hiệu quả hơn. Các yêu cầu (ví dụ: Yêu cầu A và Yêu cầu B) được phân bổ các khối bộ nhớ đệm KV (Khối KV 0, Khối KV 1, v.v.). Cách tiếp cận này giúp giảm thiểu phân mảnh và tối ưu hóa sử dụng bộ nhớ, cho phép phục vụ mô hình nhanh hơn và hiệu quả hơn.
Cơ chế chú ý trong LLM
Cơ chế chú ý là một thành phần cơ bản của các mô hình transformer, thường được sử dụng cho LLM. Hình ảnh này minh họa công thức chú ý và các thành phần của nó:
- Truy vấn (Q): Một token mới trong bước giải mã hoặc token cuối cùng mà mô hình đã xem.
- Khóa (K): Bối cảnh trước đó mà mô hình nên chú ý.
- Giá trị (V): Tổng trọng số trên bối cảnh trước đó.
Công thức tính toán điểm chú ý bằng cách lấy tích của truy vấn với khóa, chia cho căn bậc hai của kích thước khóa, áp dụng hàm softmax và cuối cùng lấy tích với giá trị. Quá trình này cho phép mô hình tập trung vào các phần liên quan của chuỗi đầu vào khi tạo ra mỗi token.
So sánh thông lượng phục vụ
Hình ảnh này trình bày so sánh thông lượng phục vụ giữa các khung khác nhau (HF, TGI và vLLM) sử dụng mô hình LLaMA trên các thiết lập phần cứng khác nhau.
- LLaMA-13B, A100-40GB: vLLM đạt được thông lượng cao hơn 14 lần đến 24 lần so với HuggingFace Transformers (HF) và cao hơn 2,2 lần đến 2,5 lần so với HuggingFace Text Generation Inference (TGI).
- LLaMA-7B, A10G: Xu hướng tương tự được quan sát, với vLLM vượt trội so với cả HF và TGI.
vLLM: Kiến trúc phục vụ LLM mới
vLLM, được phát triển bởi các nhà nghiên cứu tại UC Berkeley, đại diện cho một bước nhảy vĩ đại trong công nghệ phục vụ LLM. Hãy khám phá các tính năng và đổi mới chính của nó:
PagedAttention
Ở trung tâm của vLLM là PagedAttention, một thuật toán chú ý mới được lấy cảm hứng từ quản lý bộ nhớ ảo trong các hệ điều hành. Đây là cách nó hoạt động:
– Phân vùng bộ nhớ đệm Key-Value (KV): Thay vì lưu trữ toàn bộ bộ nhớ đệm KV một cách liên tục trong bộ nhớ, PagedAttention chia nó thành các khối có kích thước cố định.
– Lưu trữ không liên tục: Các khối này có thể được lưu trữ không liên tục trong bộ nhớ, cho phép quản lý bộ nhớ linh hoạt hơn.
– Phân bổ theo yêu cầu: Các khối chỉ được phân bổ khi cần, giảm thiểu lãng phí bộ nhớ.
– Chia sẻ hiệu quả: Nhiều chuỗi có thể chia sẻ các khối, cho phép tối ưu hóa các kỹ thuật như lấy mẫu song song và tìm kiếm chùm.
Minh họa:
“`
Bộ nhớ đệm KV truyền thống:
[Token 1 KV][Token 2 KV][Token 3 KV]…[Token N KV]
(Phân bổ bộ nhớ liên tục)
“`
Bộ nhớ đệm KV PagedAttention:
[Block 1] -> Địa chỉ vật lý A
[Block 2] -> Địa chỉ vật lý C
[Block 3] -> Địa chỉ vật lý B
…
(Phân bổ bộ nhớ không liên tục)
“`
Cách tiếp cận này giảm thiểu đáng kể phân mảnh bộ nhớ và cho phép sử dụng bộ nhớ GPU hiệu quả hơn.
Đóng gói liên tục
vLLM thực hiện đóng gói liên tục, xử lý các yêu cầu một cách động khi chúng đến, thay vì chờ đợi để tạo thành các lô cố định. Điều này dẫn đến độ trễ thấp hơn và thông lượng cao hơn.
Ví dụ:
Hãy tưởng tượng một dòng yêu cầu đến:
“`
Thời gian 0ms: Yêu cầu A đến
Thời gian 10ms: Bắt đầu xử lý Yêu cầu A
Thời gian 15ms: Yêu cầu B đến
Thời gian 20ms: Bắt đầu xử lý Yêu cầu B (song song với A)
Thời gian 25ms: Yêu cầu C đến
…
“`
Với đóng gói liên tục, vLLM có thể bắt đầu xử lý mỗi yêu cầu ngay lập tức, thay vì chờ đợi để nhóm chúng vào các lô cố định.
Lấy mẫu song song hiệu quả
Đối với các ứng dụng yêu cầu nhiều mẫu đầu ra cho mỗi lời nhắc (ví dụ: các công cụ hỗ trợ viết sáng tạo), khả năng chia sẻ bộ nhớ của vLLM phát huy tác dụng. Nó có thể tạo ra nhiều đầu ra trong khi tái sử dụng bộ nhớ đệm KV cho các tiền tố chung.
Mã ví dụ sử dụng vLLM:
“`python
from vllm import LLM, SamplingParams
llm = LLM(model=”meta-llama/Llama-2-13b-hf”)
prompts = [“Tương lai của AI là”]
# Tạo 3 mẫu cho mỗi lời nhắc
sampling_params = SamplingParams(n=3, temperature=0.8, max_tokens=100)
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
print(f”Prompt: {output.prompt}”)
for i, out in enumerate(output.outputs):
print(f”Mẫu {i + 1}: {out.text}”)
“`
Mã này tạo ra nhiều mẫu một cách hiệu quả cho lời nhắc cho trước, tận dụng tối ưu hóa của vLLM.
Benchmark hiệu suất vLLM
Để thực sự đánh giá tác động của vLLM, hãy xem xét một số so sánh hiệu suất:
So sánh thông lượng
Dựa trên thông tin cung cấp, vLLM vượt trội so với các giải pháp phục vụ khác:
– Tăng thông lượng lên đến 24 lần so với Hugging Face Transformers
– Tăng thông lượng 2,2 đến 3,5 lần so với Hugging Face Text Generation Inference (TGI)
Minh họa:
“`
Thông lượng (Token/giây)
|
| ****
| ****
| ****
| **** ****
| **** **** ****
| **** **** ****
|————————
HF TGI vLLM
“`
Hiệu quả bộ nhớ
PagedAttention của vLLM dẫn đến sử dụng bộ nhớ gần như tối ưu:
– Chỉ khoảng 4% lãng phí bộ nhớ, so với 60-80% trong các hệ thống truyền thống
– Hiệu quả này cho phép phục vụ các mô hình lớn hơn hoặc xử lý nhiều yêu cầu đồng thời với cùng phần cứng
Bắt đầu với vLLM
Giờ đây chúng ta đã khám phá các lợi ích của vLLM, hãy đi qua quá trình thiết lập và sử dụng nó trong các dự án của bạn.
6.1 Cài đặt
Cài đặt vLLM là một quá trình đơn giản sử dụng pip:
“`python
!pip install vllm
“`
6.2 Sử dụng cơ bản cho suy luận ngoại tuyến
Đây là một ví dụ đơn giản về việc sử dụng vLLM cho tạo văn bản ngoại tuyến:
“`python
from vllm import LLM, SamplingParams
# Khởi tạo mô hình
llm = LLM(model=”meta-llama/Llama-2-13b-hf”)
# Chuẩn bị lời nhắc
prompts = [
“Viết một bài thơ ngắn về trí tuệ nhân tạo:”,
“Giải thích tính toán lượng tử bằng cách sử dụng ngôn ngữ đơn giản:”
]
# Thiết lập tham số lấy mẫu
sampling_params = SamplingParams(temperature=0.8, max_tokens=100)
# Tạo phản hồi
outputs = llm.generate(prompts, sampling_params)
# In kết quả
for output in outputs:
print(f”Prompt: {output.prompt}”)
print(f”Văn bản tạo ra: {output.outputs[0].text}\n”)
“`
Kịch bản này chứng tỏ cách tải mô hình, thiết lập tham số lấy mẫu và tạo văn bản cho nhiều lời nhắc.
6.3 Thiết lập máy chủ vLLM
Để phục vụ trực tuyến, vLLM cung cấp một máy chủ API tương thích với OpenAI. Đây là cách thiết lập nó:
1. Khởi động máy chủ:
“`bash
python -m vllm.entrypoints.openai.api_server –model meta-llama/Llama-2-13b-hf
“`
2. Truy vấn máy chủ bằng cách sử dụng curl:
“`bash
curl http://localhost:8000/v1/completions \
-H “Content-Type: application/json” \
-d ‘{
“model”: “meta-llama/Llama-2-13b-hf”,
“prompt”: “Lợi ích của trí tuệ nhân tạo bao gồm:”,
“max_tokens”: 100,
“temperature”: 0.7
}’
“`
Thiết lập này cho phép bạn phục vụ LLM của mình với giao diện tương thích với API của OpenAI, giúp dễ dàng tích hợp vào các ứng dụng hiện có.
Chủ đề nâng cao về vLLM
Mặc dù vLLM cung cấp những cải tiến đáng kể trong việc phục vụ LLM, vẫn có những vấn đề và chủ đề nâng cao cần được khám phá:
7.1 Quantization mô hình
Để phục vụ hiệu quả hơn, đặc biệt là trên phần cứng có bộ nhớ hạn chế, các kỹ thuật quantization có thể được sử dụng. Mặc dù vLLM không hỗ trợ quantization, nó có thể được sử dụng cùng với các mô hình đã được quantized:
“`python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# Tải mô hình đã được quantized
model_name = “meta-llama/Llama-2-13b-hf”
model = AutoModelForCausalLM.from_pretrained(model_name, device_map=”auto”, load_in_8bit=True)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# Sử dụng mô hình đã được quantized với vLLM
from vllm import LLM
llm = LLM(model=model, tokenizer=tokenizer)
“`
7.2 Suy luận phân tán
Đối với các mô hình cực lớn hoặc ứng dụng có lưu lượng truy cập cao, suy luận phân tán trên nhiều GPU hoặc máy có thể là cần thiết. Mặc dù vLLM không hỗ trợ phân tán một cách bản địa, nó có thể được tích hợp vào các hệ thống phân tán bằng cách sử dụng các khung như Ray:
“`python
import ray
from vllm import LLM
@ray.remote(num_gpus=1)
class DistributedLLM:
def __init__(self, model_name):
self.llm = LLM(model=model_name)
def generate(self, prompt, params):
return self.llm.generate(prompt, params)
# Khởi tạo các mô hình LLM phân tán
llm1 = DistributedLLM.remote(“meta-llama/Llama-2-13b-hf”)
llm2 = DistributedLLM.remote(“meta-llama/Llama-2-13b-hf”)
# Sử dụng chúng một cách song song
result1 = llm1.generate.remote(“Lời nhắc 1”, sampling_params)
result2 = llm2.generate.remote(“Lời nhắc 2”, sampling_params)
# Lấy kết quả
print(ray.get([result1, result2]))
“`
7.3 Giám sát và quan sát
Khi phục vụ LLM trong sản xuất, giám sát là rất quan trọng. Mặc dù vLLM không cung cấp giám sát tích hợp, bạn có thể tích hợp nó với các công cụ như Prometheus và Grafana:
“`python
from prometheus_client import start_http_server, Summary
from vllm import LLM
# Định nghĩa các chỉ số
REQUEST_TIME = Summary(‘request_processing_seconds’, ‘Thời gian xử lý yêu cầu’)
# Khởi tạo vLLM
llm = LLM(model=”meta-llama/Llama-2-13b-hf”)
# Tiếp xúc các chỉ số
start_http_server(8000)
# Sử dụng mô hình với giám sát
@REQUEST_TIME.time()
def process_request(prompt):
return llm.generate(prompt)
# Vòng lặp phục vụ của bạn ở đây
“`
Thiết lập này cho phép bạn theo dõi các chỉ số như thời gian xử lý yêu cầu, có thể được trực quan hóa trong các bảng điều khiển Grafana.
Kết luận
Phục vụ các mô hình ngôn ngữ lớn một cách hiệu quả là một nhiệm vụ phức tạp nhưng quan trọng trong thời đại AI. vLLM, với thuật toán chú ý PagedAttention sáng tạo và triển khai tối ưu, đại diện cho một bước tiến quan trọng trong việc làm cho việc triển khai LLM trở nên dễ tiếp cận và tiết kiệm chi phí hơn.
Bằng cách cải thiện đáng kể thông lượng, giảm lãng phí bộ nhớ và cho phép các tùy chọn phục vụ linh hoạt hơn, vLLM mở ra những khả năng mới để tích hợp các mô hình ngôn ngữ mạnh mẽ vào nhiều ứng dụng khác nhau. Cho dù bạn đang xây dựng một rô-bốt trò chuyện, một hệ thống tạo nội dung hoặc bất kỳ ứng dụng nào khác được hỗ trợ bởi NLP, việc hiểu và tận dụng các công cụ như vLLM sẽ là chìa khóa để thành công.
















