multilora_inference.py 4.18 KB
Newer Older
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""
4
5
This example shows how to use the multi-LoRA functionality
for offline inference.
6
7
8
9
10
11

Requires HuggingFace credentials for access to Llama2.
"""

from huggingface_hub import snapshot_download

12
from vllm import EngineArgs, LLMEngine, RequestOutput, SamplingParams
13
14
15
from vllm.lora.request import LoRARequest


16
def create_test_prompts(
17
    lora_path: str,
18
) -> list[tuple[str, SamplingParams, LoRARequest | None]]:
19
    """Create a list of test prompts with their sampling parameters.
20

21
22
23
    2 requests for base model, 4 requests for the LoRA. We define 2
    different LoRA adapters (using the same model for demo purposes).
    Since we also set `max_loras=1`, the expectation is that the requests
24
    with the second LoRA adapter will be run after all requests with the
25
26
27
    first adapter have finished.
    """
    return [
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        (
            "A robot may not injure a human being",
            SamplingParams(
                temperature=0.0, logprobs=1, prompt_logprobs=1, max_tokens=128
            ),
            None,
        ),
        (
            "To be or not to be,",
            SamplingParams(
                temperature=0.8, top_k=5, presence_penalty=0.2, max_tokens=128
            ),
            None,
        ),
42
43
        (
            "[user] Write a SQL query to answer the question based on the table schema.\n\n context: CREATE TABLE table_name_74 (icao VARCHAR, airport VARCHAR)\n\n question: Name the ICAO for lilongwe international airport [/user] [assistant]",  # noqa: E501
44
45
46
47
48
49
50
51
            SamplingParams(
                temperature=0.0,
                logprobs=1,
                prompt_logprobs=1,
                max_tokens=128,
            ),
            LoRARequest("sql-lora", 1, lora_path),
        ),
52
53
        (
            "[user] Write a SQL query to answer the question based on the table schema.\n\n context: CREATE TABLE table_name_74 (icao VARCHAR, airport VARCHAR)\n\n question: Name the ICAO for lilongwe international airport [/user] [assistant]",  # noqa: E501
54
55
56
57
58
59
60
61
            SamplingParams(
                temperature=0.0,
                logprobs=1,
                prompt_logprobs=1,
                max_tokens=128,
            ),
            LoRARequest("sql-lora2", 2, lora_path),
        ),
62
63
64
    ]


65
66
def process_requests(
    engine: LLMEngine,
67
    test_prompts: list[tuple[str, SamplingParams, LoRARequest | None]],
68
):
69
70
71
    """Continuously process a list of prompts and handle the outputs."""
    request_id = 0

72
    print("-" * 50)
73
74
75
    while test_prompts or engine.has_unfinished_requests():
        if test_prompts:
            prompt, sampling_params, lora_request = test_prompts.pop(0)
76
77
78
            engine.add_request(
                str(request_id), prompt, sampling_params, lora_request=lora_request
            )
79
80
            request_id += 1

81
        request_outputs: list[RequestOutput] = engine.step()
82
83
84
85

        for request_output in request_outputs:
            if request_output.finished:
                print(request_output)
86
                print("-" * 50)
87
88
89
90
91
92
93
94
95
96
97


def initialize_engine() -> LLMEngine:
    """Initialize the LLMEngine."""
    # max_loras: controls the number of LoRAs that can be used in the same
    #   batch. Larger numbers will cause higher memory usage, as each LoRA
    #   slot requires its own preallocated tensor.
    # max_lora_rank: controls the maximum supported rank of all LoRAs. Larger
    #   numbers will cause higher memory usage. If you know that all LoRAs will
    #   use the same rank, it is recommended to set this as low as possible.
    # max_cpu_loras: controls the size of the CPU LoRA cache.
98
    engine_args = EngineArgs(
99
        model="meta-llama/Llama-3.2-3B-Instruct",
100
101
102
103
104
105
        enable_lora=True,
        max_loras=1,
        max_lora_rank=8,
        max_cpu_loras=2,
        max_num_seqs=256,
    )
106
107
108
109
110
111
    return LLMEngine.from_engine_args(engine_args)


def main():
    """Main function that sets up and runs the prompt processing."""
    engine = initialize_engine()
112
    lora_path = snapshot_download(repo_id="jeeejeee/llama32-3b-text2sql-spider")
113
114
115
116
    test_prompts = create_test_prompts(lora_path)
    process_requests(engine, test_prompts)


117
if __name__ == "__main__":
118
    main()