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

Code before:

    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);

                if (prefix.size() > longest) {
                    LOG_INFO("Slot with common prefix found", {{
                        "slot_id", s.id,
                        "characters", prefix.size()
                    }});
                    slot = &s;
                    longest = s_prompt.size();
                }
            }
        }

        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)
            {
                slot = get_slot(json_value(task.data, "slot_id", -1));
            }

            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}});

Review comment (refactor):
nit - doesn't this have the chance of popping out multiple times if we find later slots with longer matches?

Maybe move this to a block around line 1457 that says:
```c++
if (longest > 0)
{
  LOG_INFO("Slot with common prefix found", {{
                        "slot_id", slot.id,
                        "characters", prefix.size()
                    }});
}
```
(the prefix string would need to be defined earlier of course)

Code after:
        {
            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
                    send_error(task, "internal_error");
                    break;
                }
            } break;
            case TASK_TYPE_CANCEL: { // release slot linked with the task id
                for (auto & slot : slots)
                {
                    if (slot.task_id == task.target_id)
                    {
                        slot.release();
                        break;
                    }
                }
            } break;
            case TASK_TYPE_NEXT_RESPONSE: {
                // do nothing
            } break;
            case TASK_TYPE_METRICS: {
                json slots_data        = json::array();
                int n_idle_slots       = 0;
                int n_processing_slots = 0;

                for (server_slot &slot: slots) {
                    json slot_data = get_formated_generation(slot);
                    slot_data["id"] = slot.id;
                    slot_data["task_id"] = slot.task_id;
                    slot_data["state"] = slot.state;
                    slot_data["prompt"] = slot.prompt;
                    slot_data["next_token"] = {
                            {"has_next_token",       slot.has_next_token},
                            {"n_remain",             slot.n_remaining},