Repository: ollama/ollama
File: llm/ext_server/server.cpp (C++)

Code before:
    }

    void split_multiprompt_task(int multitask_id, task_server &multiprompt_task)
    {
        int prompt_count = multiprompt_task.data.at("prompt").size();
        if (prompt_count <= 1)
        {
            send_error(multiprompt_task, "error while handling multiple prompts");
            return;
        }

        // generate all the ID for subtask
        std::vector<int> subtask_ids(prompt_count);
        for (int i = 0; i < prompt_count; i++)
        {
            subtask_ids[i] = queue_tasks.get_new_id();
        }

        // queue up the multitask so we can track its subtask progression
        queue_tasks.add_multitask(multitask_id, subtask_ids);

        // add subtasks
        for (int i = 0; i < prompt_count; i++)
        {
            json subtask_data = multiprompt_task.data;
            subtask_data["prompt"] = subtask_data["prompt"][i];

            // subtasks inherit everything else (embedding mode, etc.)
            request_completion(subtask_ids[i], subtask_data, multiprompt_task.embedding_mode, multitask_id);
        }
    }

    std::string common_prefix(const std::string& str1, const std::string& str2) {
        auto mismatch_pair = std::mismatch(str1.begin(), str1.end(), str2.begin());
        return std::string(str1.begin(), mismatch_pair.first);
    }

    // Find the slot that has the greatest common prefix
    server_slot *prefix_slot(const json &prompt) {
        if (!prompt.is_string()) {
            return nullptr;
        }

        std::string prompt_str = prompt.get<std::string>();
        server_slot *slot = nullptr;
        size_t longest = 1;

        for (server_slot &s : slots) {
            if (s.available() && s.prompt.is_string()) {
                std::string s_prompt = s.prompt.get<std::string>();
                std::string prefix = common_prefix(s_prompt, prompt_str);

Review comment (suggestion):
maybe pedantic, but just thinking this could check for nil and call `get_slot` so callers don't have to do that.

Code after:

        std::string prompt_str = prompt.get<std::string>();
        server_slot *slot = nullptr;
        size_t longest = 0;

        for (server_slot &s : slots) {
            if (s.available() && s.prompt.is_string()) {
                std::string s_prompt = s.prompt.get<std::string>();
                std::string prefix = common_prefix(s_prompt, prompt_str);

                if (prefix.size() > longest) {
                    slot = &s;
                    longest = prefix.size();
                }
            }
        }

        if (!slot) {
            return get_slot(-1);
        }

        LOG_INFO("slot with common prefix found", {{
            "slot_id", slot->id,
            "characters", longest
        }});
        return slot;
    }

    void process_single_task(task_server& task)
    {
        switch (task.type)
        {
            case TASK_TYPE_COMPLETION: {
                server_slot *slot = prefix_slot(task.data["prompt"]);
                if (slot == nullptr)
                {
                    // if no slot is available, we defer this task for processing later
                    LOG_VERBOSE("no slot is available", {{"task_id", task.id}});
                    queue_tasks.defer(task);
                    break;
                }

                slot->reset();

                slot->embedding    = task.embedding_mode;
                slot->task_id      = task.id;
                slot->multitask_id = task.multitask_id;

                if (!launch_slot_with_data(slot, task.data))
                {
                    // send error result