Среда вывода больших моделей Анализ исходного кода vLLM (1)
Среда вывода больших моделей Анализ исходного кода vLLM (1)

1. Quick Start

Создайте следующий код и назовите его run.py

Язык кода:javascript
копировать
from vllm import LLM, SamplingParams

prompts = [
	"Have you followed marsggbo in Zhihu?",
	«Ты ударил три раза подряд?»
] # входитьprompts
sampling_params = SamplingParams(temperature=0.8, top_k=50) # Стратегия выборки
llm = LLM(model="facebook/opt-125m", tensor_parallel_size=2) # инициализация LLM
outputs = llm.generate(prompts, sampling_params) # полное рассуждение
for output in outputs:
	prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

выполнить команду:python run.py。Скрипт автоматически Модель Параллельно с тензорамииз方式在两个 GPU Выполните вычисления вывода дальше.

Общий ход всего процесса рассуждений показан на рисунке ниже, а именно 1 Учитывая определенное количество подсказок (массив строк) 2. vllm будет использовать модуль Планировщика для автоматического планирования предложений, требующих рассуждения. 3. В соответствии с результатами планирования используйте токенизатор для преобразования строки в идентификатор приглашения, а затем передайте ее в модель для расчета, чтобы получить результаты прогнозирования логитов. 4. Выборка результатов в соответствии с результатами прогнозирования логитов и заранее установленной стратегией выборки для получения нового идентификатора токена. 5. Сохраните результаты отбора проб на вывод.

inferencce pipeline
inferencce pipeline

2. Общий основной модуль

Структурные связи между основными модулями vLLM. Далее мы начнем с простых модулей (т. е. ввода, выборки и вывода) и закончим подробным введением в модуль LLM.

3. Sequence

Модуль предложений
Модуль предложений

Как показано на рисунке выше, мы видим, что vLLM разработала множество подмодулей для входных предложений. Эти модули используются по-разному, но они связаны друг с другом. Подробно они представлены ниже.

3.1 SequenceStatus

впервые увидел SequenceStatus,Его исходный код выглядит следующим образом:

Язык кода:javascript
копировать
class SequenceStatus(enum.Enum):
    """Status of a sequence."""
    WAITING = enum.auto() # Ожидание середина, предложение не начало рассуждения, или рассуждение еще не закончилось
    RUNNING = enum.auto() # 运行середина    SWAPPED = enum.auto() # обменян
    FINISHED_STOPPED = enum.auto() # Остановлено
    FINISHED_LENGTH_CAPPED = enum.auto() # Длина ограничена
    FINISHED_ABORTED = enum.auto() # ужесередина止    FINISHED_IGNORED = enum.auto() # игнорируется

    @staticmethod
    def is_finished(status: "SequenceStatus") -> bool:
        # суждениесостояние Это Остановлено、Длина ограничена、ужесерединаостановись илиигнорируется
        return status in [
            SequenceStatus.FINISHED_STOPPED,
            SequenceStatus.FINISHED_LENGTH_CAPPED,
            SequenceStatus.FINISHED_ABORTED,
            SequenceStatus.FINISHED_IGNORED,
        ]

3.2 SequenceData

SequenceData Используется для хранения связанных с последовательностьюизданные。Этот класс имеет три атрибута:prompt_token_ids(подсказать словоизотметкаID)、output_token_ids(генерировать текстизотметкаID)иcumulative_logprob(совокупная логарифмическая вероятность)。

Язык кода:javascript
копировать
class SequenceData:
    def __init__(
        self,
        prompt_token_ids: List[int],
    ) -> None:
        self.prompt_token_ids = prompt_token_ids
        self.output_token_ids: List[int] = []
        self.cumulative_logprob = 0.0

3.3 Sequence

Sequence Используется для хранения изданных последовательностей.、состояниеиблокировать информация, и каждая последовательность имеет уникальный идентификатор,Прямо сейчасseq_id。Обратите внимание на следующееизкод:

  • данныеФактически, именно благодаря вышеизложенномуиз SequenceData Сохранять
  • по умолчаниюинициализациясостояние,все последовательности предложенийизсостояниеВсе SequenceStatus.WAITING
  • так называемыйблокировать информацию,на самом делето есть vLLM Определенное количество процессоров будет зарезервировано на этапе инициализации. и GPU память, обычно token как единицаиз,Например винициализацияизкогдабуду Ценности использовать – это все 0, размер (256, 128)из Prompt_ids делать warm вверх. Каждая последовательность будет применена в соответствии с фактическим размером block для записи использования памяти, т.е. последовательности token Чем больше число,свойствоlogical_token_blocksВключатьиз block Число будет больше.
Язык кода:javascript
копировать
class Sequence:
    def __init__(
        self,
        seq_id: int,
        prompt: str,
        prompt_token_ids: List[int],
        block_size: int,
    ) -> None:
        self.seq_id = seq_id
        self.prompt = prompt
        self.block_size = block_size

        self.data = SequenceData(prompt_token_ids) # данные

        self.logical_token_blocks: List[LogicalTokenBlock] = []
        # Initialize the logical token blocks with the prompt token ids.
        self._append_tokens_to_blocks(prompt_token_ids) # блокировать информацию
        self.status = SequenceStatus.WAITING # состояние
		...

3.3 SequenceGroup

Sequenceтолькоодинокийпоследовательностьиз Выражение,seq_idэтоизуникальный идентификатор。SequenceGroup则是为Понятно表示много个последовательность,request_idэтоизуникальный идентификатор,Указывает, какой это запрос.

Конкретно,можно увидеть__init__Функция имеет параметр, который seqs: List[Sequence],Он представляет собой один или несколько Sequence Состав исписок,тогда пройдетself.seqs_dict = {seq.seq_id: seq for seq in seqs}Преобразование в словарь для удобства управления.,Этот словарь из key это каждый Sequence изуникальный идентификаторseq_id

Язык кода:javascript
копировать
class SequenceGroup:
    def __init__(
        self,
        request_id: str,
        seqs: List[Sequence],
        sampling_params: SamplingParams,
        arrival_time: float,
        lora_request: Optional[LoRARequest] = None,
        prefix: Optional[Prefix] = None,
    ) -> None:
        self.request_id = request_id
        self.seqs_dict = {seq.seq_id: seq for seq in seqs}
        self.sampling_params = sampling_params
        self.arrival_time = arrival_time
		...

Ниже приведен пример сценария, в котором LLMEngine использует Sequence и SequenceGroup в vLLm:

Язык кода:javascript
копировать
class LLMEngine:
    def add_request(
        self,
        request_id: str,
        prompt: Optional[str],
        sampling_params: SamplingParams,
        prompt_token_ids: Optional[List[int]] = None,
        arrival_time: Optional[float] = None,
        lora_request: Optional[LoRARequest] = None,
        prefix_pos: Optional[int] = None,
    ) -> None:
        prompt_token_ids = self.encode_request(
            request_id=request_id,
            prompt=prompt,
            prompt_token_ids=prompt_token_ids,
            lora_request=lora_request) # Преобразовать последовательность строк в id

        # Create the sequences.
        block_size = self.cache_config.block_size
        seq_id = next(self.seq_counter)
        seq = Sequence(seq_id, prompt, prompt_token_ids, block_size,
                       lora_request)

        # Create the sequence group.
        seq_group = SequenceGroup(request_id, [seq], sampling_params,
                                  arrival_time)

        # Add the sequence group to the scheduler.
        self.scheduler.add_seq_group(seq_group)

можно увидетьSequenceGroupизseqsпараметр在最初阶段на самом делетолькоодинокийпоследовательность ,Прямо сейчас[seq]。但是我们知道на самом деле一个 prompt Может быть несколько выходных результатов,такSequenceGroupизглазиззаключается в управлениивходить promptизмногосгенерированная последовательностьинформация。Если мы установимSamplingParams.n=2(第 4 Знакомство с фестивалем),Затем в процессе рассуждениясередина,SequenceGroupБудет добавлен новый Последовательность, это новое Sequence из seq_id Оказывается, из этого Sequence В отличие от этого, конкретные детали кода будут представлены в следующей статье середина.

3.5 SequenceGroupMetadata

Язык кода:javascript
копировать
class SequenceGroupMetadata:
    def __init__(
        self,
        request_id: str,
        is_prompt: bool,
        seq_data: Dict[int, SequenceData],
        sampling_params: SamplingParams,
        block_tables: Dict[int, List[int]],
    ) -> None:
        self.request_id = request_id
        self.is_prompt = is_prompt
        self.seq_data = seq_data
        self.sampling_params = sampling_params
        self.block_tables = block_tables
		...

SequenceGroupMetadata Записывается некоторая метаинформация, как показано в следующем коде. Scheduler модуль是нравиться何生成这些информацияиз:

  • request_id то есть SequenceGroupиз request_id
  • seq_data это словарь, ключ это каждый Sequenceиз seq_id,value Это соответствует из data (Прямо сейчас SequenceData)
  • block_tablesтакжеэто словарь, ключ такжеэто каждый Sequenceиз seq_id,value Это переписка Sequence Применять block
Язык кода:javascript
копировать
class Scheduler:
    def schedule(self) -> Tuple[List[SequenceGroupMetadata], SchedulerOutputs]:
        scheduler_outputs = self._schedule()

        # Create input data structures.
        seq_group_metadata_list: List[SequenceGroupMetadata] = []
        for seq_group in scheduler_outputs.scheduled_seq_groups:
            seq_data: Dict[int, SequenceData] = {}
            block_tables: Dict[int, List[int]] = {}
            for seq in seq_group.get_seqs(status=SequenceStatus.RUNNING):
                seq_id = seq.seq_id
                seq_data[seq_id] = seq.data # одинокий SequenceData
                block_tables[seq_id] = self.block_manager.get_block_table(seq) # Соответствует информации о последовательности из блока

            seq_group_metadata = SequenceGroupMetadata(
                request_id=seq_group.request_id,
                is_prompt=scheduler_outputs.prompt_run,
                seq_data=seq_data,
                sampling_params=seq_group.sampling_params,
                block_tables=block_tables,
                lora_request=seq_group.lora_request,
                prefix=seq_group.prefix,
            )
            seq_group_metadata_list.append(seq_group_metadata)
        return seq_group_metadata_list, scheduler_outputs

3.6 Вывод последовательности и вывод группы последовательности

SequenceOutput и Отношения SequenceGroupOutputiz аналогичны Sequence и Группа последовательности. SequenceOutput фактически записывает предыдущий входить token id И соответствующий вывод из token id。

Язык кода:javascript
копировать
class SequenceOutput:
    def __init__(
        self,
        parent_seq_id: int,
        output_token: int,
        logprobs: Dict[int, float],
    ) -> None:
        self.parent_seq_id = parent_seq_id
        self.output_token = output_token
        self.logprobs = logprobs

class SequenceGroupOutput:
    def __init__(
        self,
        samples: List[SequenceOutput],
        prompt_logprobs: Optional[PromptLogprobs],
    ) -> None:
        self.samples = samples
        self.prompt_logprobs = prompt_logprobs

4. SamplingParams

SamplingParams содержит следующие параметры:

  • n:Чтобы создатьизпоследовательностьизколичество,По умолчанию — 1.
  • best_of:从много少个последовательностьсередина选择最佳последовательность,должно быть больше, чем n, значение по умолчанию равно n。
  • temperature:Используется для контроля результатов сборкиизслучайность,Более низкие температуры дадут более детерминированные результаты.,Более высокие температуры дадут более случайные результаты.
  • top_p:Используется для фильтрации сгенерированной лексики.середина Вероятность ниже заданного порогаизсловарный запас,Контролируйте случайность.
  • top_k:До выбора k кандидаты Жетон, контроль разнообразия.
  • presence_penalty:Используется для контроля результатов сборкисередина特定словарный запасизчастота появления。
  • frequency_penalty:Используется для контроля результатов сборкисерединасловарный запасизчастотное распределение。
  • repetition_penalty:Используется для контроля результатов сборкисерединаизсловарный запасстепень повторения。
  • use_beam_search:лииспользоватьпоиск луча для генерациипоследовательность.
  • length_penalty:Используется для контроля результатов сборкиизраспределение длины。
  • early_stopping:ли В процессе генерациисередина Остановитесь раньше。
  • stop:Чтобы прекратить генерироватьизсловарный запассписок。
  • stop_token_ids:Чтобы прекратить генерироватьизсловарный запасизIDсписок。
  • include_stop_str_in_output:ли在输出результатсередина Включать停止字符串。
  • ignore_eos:В процессе генерациисерединали忽略结束符号。
  • max_tokens:生成последовательностьизмаксимальная длина。
  • logprobs:Используется для записи процесса генерациииз概率информация。
  • prompt_logprobs:Используется для записи процесса генерациииз概率информация,для конкретных подсказок.
  • skip_special_tokens:ли跳过特殊符号。
  • spaces_between_special_tokens:ли在特殊符号之间添加空格。

Настройки этих параметров обычно зависят от конкретных требований и производительности модели. Вот некоторые общие рекомендации по настройке:

  • temperature:нижеизтемпература(нравиться0.2)даст больше уверенностиизрезультат,И вышеизтемпература(нравиться0.8)будет производить больше случайныхизрезультат。ты можешьв соответствии с Отрегулируйте в соответствии с вашими потребностями.
  • presence_penalty、frequency_penalty и repetition_penalty:这些параметр可以Используется для контроля результатов сборкисерединаизсловарный запас分布истепень повторения。ты можешьв соответствии с Отрегулируйте в соответствии с вашими потребностями.
  • use_beam_search:Поиск луча часто используется для получения изображений более высокого качества.изрезультат,Но это может снизить скорость генерации。ты можешьв соответствии с Отрегулируйте в соответствии с вашими потребностями.
  • length_penalty:这个параметр可以Используется для контроля результатов сборкииздлина。вышеиззначения будут производиться дольшеизрезультат,而нижеиззначение приведет к более короткомуизрезультат。ты можешьв соответствии с Отрегулируйте в соответствии с вашими потребностями.
  • early_stopping:нравиться果您不希望生成过长изрезультат,Для этого параметра можно установить значение True.
  • stop и stop_token_ids:ты можешьиспользовать这些параметр来指定生成результатизконечное состояние。

5. Модуль вывода

Outputмодуль
Outputмодуль

Вывод в основном используется для представления языковой модели (LLM) из сгенерированных результатов, включая следующие два модуля:

  • CompletionOutput
  • RequestOutput

Благодаря приведенному выше введению мы знаем request 可能Включатьмного个последовательность,CompletionOutput используется для выражения request середина某个последовательностьизполный выводизданные,Чтосерединаподизindex就表示该последовательность在 request расположение индекса серединаиз

Язык кода:javascript
копировать
class CompletionOutput:
    def __init__(
        self,
        index: int, # Вывод результатов в запрос серединаиз index
        text: str, # Создать из текста
        token_ids: List[int], # Создать из текст соответствует из token ID список
        cumulative_logprob: float,
        logprobs: Optional[SampleLogprobs],
        finish_reason: Optional[str] = None, # Причина завершения последовательности (SequenceStatus)
        lora_request: Optional[LoRARequest] = None,
    ) -> None:
        self.index = index
        self.text = text
        self.token_ids = token_ids
        self.finish_reason = finish_reason
		...

RequestOutput则表示 request 所有последовательностьиз输出результат,возьми этоизинициализация函数можно увидеть它记录Понятно对应из request_id

Язык кода:javascript
копировать
class RequestOutput:
    def __init__(
        self,
        request_id: str,
        prompt: str,
        prompt_token_ids: List[int],
        prompt_logprobs: Optional[PromptLogprobs],
        outputs: List[CompletionOutput],
        finished: bool,
        lora_request: Optional[LoRARequest] = None,
    ) -> None:
        self.request_id = request_id
        self.prompt = prompt
        self.prompt_token_ids = prompt_token_ids
        self.outputs = outputs
        self.finished = finished
		...

Давайте посмотримRequestOutputизfrom_seq_groupможно легко понятьCompletionOutputи RequestOutput是нравиться何использоватьиз Понятно。для простоты понимания,Код был удален,Но на конечный результат это не влияет:

Язык кода:javascript
копировать
class RequestOutput:
    @classmethod
    def from_seq_group(cls, seq_group: SequenceGroup) -> "RequestOutput":
        # 1. Get the top-n sequences.
        n = seq_group.sampling_params.n # Каждая последовательность возвращает количество сгенерированных последовательностей.
        seqs = seq_group.get_seqs()
		# в соответствии накопительный logprob значение, которое нужно выбрать перед n сгенерированная последовательность
		sorting_key = lambda seq: seq.get_cumulative_logprob()
        sorted_seqs = sorted(seqs, key=sorting_key, reverse=True)
        top_n_seqs = sorted_seqs[:n]

        # 2. Create the outputs.
        outputs: List[CompletionOutput] = []
        for seq in top_n_seqs:
            logprobs = seq.output_logprobs
            finshed_reason = SequenceStatus.get_finished_reason(seq.status)
            output = CompletionOutput(seqs.index(seq), seq.output_text,
                                      seq.get_output_token_ids(),
                                      seq.get_cumulative_logprob(), logprobs,
                                      finshed_reason)
            outputs.append(output)

        # Every sequence in the sequence group should have the same prompt.
        prompt = seq_group.prompt
        prompt_token_ids = seq_group.prompt_token_ids
        prompt_logprobs = seq_group.prompt_logprobs
        finished = seq_group.is_finished()
        return cls(seq_group.request_id,
                   prompt,
                   prompt_token_ids,
                   prompt_logprobs,
                   outputs,
                   finished,
                   lora_request=seq_group.lora_request)

RequestOutputпередается черезизseq_group: SequenceGroupПосле анализа получаемиз。В процессе разбора есть два основных этапа.:

  1. Get the top-n последовательности: этот этап есть генерировать последовательность в соответствии cumulative_logprob Отсортируйте и, наконец, выберите top-n последовательность.
  2. Create the выходные данные: преобразовать все первые n сгенерированных последовательностей в CompletionOutputсписок,и какRequestOutputизинициализацияпараметр。
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose