* server: add model management and proxy * fix compile error * does this fix windows? * fix windows build * use subprocess.h, better logging * add test * fix windows * feat: Model/Router server architecture WIP * more stable * fix unsafe pointer * also allow terminate loading model * add is_active() * refactor: Architecture improvements * tmp apply upstream fix * address most problems * address thread safety issue * address review comment * add docs (first version) * address review comment * feat: Improved UX for model information, modality interactions etc * chore: update webui build output * refactor: Use only the message data `model` property for displaying model used info * chore: update webui build output * add --models-dir param * feat: New Model Selection UX WIP * chore: update webui build output * feat: Add auto-mic setting * feat: Attachments UX improvements * implement LRU * remove default model path * better --models-dir * add env for args * address review comments * fix compile * refactor: Chat Form Submit component * ad endpoint docs * Merge remote-tracking branch 'webui/allozaur/server_model_management_v1_2' into xsn/server_model_maagement_v1_2 Co-authored-by: Aleksander <aleksander.grygier@gmail.com> * feat: Add copy to clipboard to model name in model info dialog * feat: Model unavailable UI state for model selector * feat: Chat Form Actions UI logic improvements * feat: Auto-select model from last assistant response * chore: update webui build output * expose args and exit_code in API * add note * support extra_args on loading model * allow reusing args if auto_load * typo docs * oai-compat /models endpoint * cleaner * address review comments * feat: Use `model` property for displaying the `repo/model-name` naming format * refactor: Attachments data * chore: update webui build output * refactor: Enum imports * feat: Improve Model Selector responsiveness * chore: update webui build output * refactor: Cleanup * refactor: Cleanup * refactor: Formatters * chore: update webui build output * refactor: Copy To Clipboard Icon component * chore: update webui build output * refactor: Cleanup * chore: update webui build output * refactor: UI badges * chore: update webui build output * refactor: Cleanup * refactor: Cleanup * chore: update webui build output * add --models-allow-extra-args for security * nits * add stdin_file * fix merge * fix: Retrieve lost setting after resolving merge conflict * refactor: DatabaseStore -> DatabaseService * refactor: Database, Conversations & Chat services + stores architecture improvements (WIP) * refactor: Remove redundant settings * refactor: Multi-model business logic WIP * chore: update webui build output * feat: Switching models logic for ChatForm or when regenerating messges + modality detection logic * chore: update webui build output * fix: Add `untrack` inside chat processing info data logic to prevent infinite effect * fix: Regenerate * feat: Remove redundant settigns + rearrange * fix: Audio attachments * refactor: Icons * chore: update webui build output * feat: Model management and selection features WIP * chore: update webui build output * refactor: Improve server properties management * refactor: Icons * chore: update webui build output * feat: Improve model loading/unloading status updates * chore: update webui build output * refactor: Improve API header management via utility functions * remove support for extra args * set hf_repo/docker_repo as model alias when posible * refactor: Remove ConversationsService * refactor: Chat requests abort handling * refactor: Server store * tmp webui build * refactor: Model modality handling * chore: update webui build output * refactor: Processing state reactivity * fix: UI * refactor: Services/Stores syntax + logic improvements Refactors components to access stores directly instead of using exported getter functions. This change centralizes store access and logic, simplifying component code and improving maintainability by reducing the number of exported functions and promoting direct store interaction. Removes exported getter functions from `chat.svelte.ts`, `conversations.svelte.ts`, `models.svelte.ts` and `settings.svelte.ts`. * refactor: Architecture cleanup * feat: Improve statistic badges * feat: Condition available models based on modality + better model loading strategy & UX * docs: Architecture documentation * feat: Update logic for PDF as Image * add TODO for http client * refactor: Enhance model info and attachment handling * chore: update webui build output * refactor: Components naming * chore: update webui build output * refactor: Cleanup * refactor: DRY `getAttachmentDisplayItems` function + fix UI * chore: update webui build output * fix: Modality detection improvement for text-based PDF attachments * refactor: Cleanup * docs: Add info comment * refactor: Cleanup * re * refactor: Cleanup * refactor: Cleanup * feat: Attachment logic & UI improvements * refactor: Constants * feat: Improve UI sidebar background color * chore: update webui build output * refactor: Utils imports + move types to `app.d.ts` * test: Fix Storybook mocks * chore: update webui build output * test: Update Chat Form UI tests * refactor: Tooltip Provider from core layout * refactor: Tests to separate location * decouple server_models from server_routes * test: Move demo test to tests/server * refactor: Remove redundant method * chore: update webui build output * also route anthropic endpoints * fix duplicated arg * fix invalid ptr to shutdown_handler * server : minor * rm unused fn * add ?autoload=true|false query param * refactor: Remove redundant code * docs: Update README documentations + architecture & data flow diagrams * fix: Disable autoload on calling server props for the model * chore: update webui build output * fix ubuntu build * fix: Model status reactivity * fix: Modality detection for MODEL mode * chore: update webui build output --------- Co-authored-by: Aleksander Grygier <aleksander.grygier@gmail.com> Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
174 lines
5.9 KiB
C++
174 lines
5.9 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
#include "server-http.h"
|
|
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <functional>
|
|
#include <memory>
|
|
|
|
/**
|
|
* state diagram:
|
|
*
|
|
* UNLOADED ──► LOADING ──► LOADED
|
|
* ▲ │ │
|
|
* └───failed───┘ │
|
|
* ▲ │
|
|
* └────────unloaded─────────┘
|
|
*/
|
|
enum server_model_status {
|
|
// TODO: also add downloading state when the logic is added
|
|
SERVER_MODEL_STATUS_UNLOADED,
|
|
SERVER_MODEL_STATUS_LOADING,
|
|
SERVER_MODEL_STATUS_LOADED
|
|
};
|
|
|
|
static server_model_status server_model_status_from_string(const std::string & status_str) {
|
|
if (status_str == "unloaded") {
|
|
return SERVER_MODEL_STATUS_UNLOADED;
|
|
}
|
|
if (status_str == "loading") {
|
|
return SERVER_MODEL_STATUS_LOADING;
|
|
}
|
|
if (status_str == "loaded") {
|
|
return SERVER_MODEL_STATUS_LOADED;
|
|
}
|
|
throw std::runtime_error("invalid server model status");
|
|
}
|
|
|
|
static std::string server_model_status_to_string(server_model_status status) {
|
|
switch (status) {
|
|
case SERVER_MODEL_STATUS_UNLOADED: return "unloaded";
|
|
case SERVER_MODEL_STATUS_LOADING: return "loading";
|
|
case SERVER_MODEL_STATUS_LOADED: return "loaded";
|
|
default: return "unknown";
|
|
}
|
|
}
|
|
|
|
struct server_model_meta {
|
|
std::string name;
|
|
std::string path;
|
|
std::string path_mmproj; // only available if in_cache=false
|
|
bool in_cache = false; // if true, use -hf; use -m otherwise
|
|
int port = 0;
|
|
server_model_status status = SERVER_MODEL_STATUS_UNLOADED;
|
|
int64_t last_used = 0; // for LRU unloading
|
|
std::vector<std::string> args; // additional args passed to the model instance (used for debugging)
|
|
int exit_code = 0; // exit code of the model instance process (only valid if status == FAILED)
|
|
|
|
bool is_active() const {
|
|
return status == SERVER_MODEL_STATUS_LOADED || status == SERVER_MODEL_STATUS_LOADING;
|
|
}
|
|
|
|
bool is_failed() const {
|
|
return status == SERVER_MODEL_STATUS_UNLOADED && exit_code != 0;
|
|
}
|
|
};
|
|
|
|
struct subprocess_s;
|
|
|
|
struct server_models {
|
|
private:
|
|
struct instance_t {
|
|
std::shared_ptr<subprocess_s> subproc; // shared between main thread and monitoring thread
|
|
std::thread th;
|
|
server_model_meta meta;
|
|
FILE * stdin_file = nullptr;
|
|
};
|
|
|
|
std::mutex mutex;
|
|
std::condition_variable cv;
|
|
std::map<std::string, instance_t> mapping;
|
|
|
|
common_params base_params;
|
|
std::vector<std::string> base_args;
|
|
std::vector<std::string> base_env;
|
|
|
|
void update_meta(const std::string & name, const server_model_meta & meta);
|
|
|
|
// unload least recently used models if the limit is reached
|
|
void unload_lru();
|
|
|
|
public:
|
|
server_models(const common_params & params, int argc, char ** argv, char ** envp);
|
|
|
|
// check if a model instance exists
|
|
bool has_model(const std::string & name);
|
|
|
|
// return a copy of model metadata
|
|
std::optional<server_model_meta> get_meta(const std::string & name);
|
|
|
|
// return a copy of all model metadata
|
|
std::vector<server_model_meta> get_all_meta();
|
|
|
|
// if auto_load is true, load the model with previous args if any
|
|
void load(const std::string & name, bool auto_load);
|
|
void unload(const std::string & name);
|
|
void unload_all();
|
|
|
|
// update the status of a model instance
|
|
void update_status(const std::string & name, server_model_status status);
|
|
|
|
// wait until the model instance is fully loaded
|
|
// return when the model is loaded or failed to load
|
|
void wait_until_loaded(const std::string & name);
|
|
|
|
// load the model if not loaded, otherwise do nothing
|
|
// return false if model is already loaded; return true otherwise (meta may need to be refreshed)
|
|
bool ensure_model_loaded(const std::string & name);
|
|
|
|
// proxy an HTTP request to the model instance
|
|
server_http_res_ptr proxy_request(const server_http_req & req, const std::string & method, const std::string & name, bool update_last_used);
|
|
|
|
// notify the router server that a model instance is ready
|
|
// return the monitoring thread (to be joined by the caller)
|
|
static std::thread setup_child_server(const common_params & base_params, int router_port, const std::string & name, std::function<void(int)> & shutdown_handler);
|
|
};
|
|
|
|
struct server_models_routes {
|
|
common_params params;
|
|
server_models models;
|
|
server_models_routes(const common_params & params, int argc, char ** argv, char ** envp)
|
|
: params(params), models(params, argc, argv, envp) {
|
|
init_routes();
|
|
}
|
|
|
|
void init_routes();
|
|
// handlers using lambda function, so that they can capture `this` without `std::bind`
|
|
server_http_context::handler_t get_router_props;
|
|
server_http_context::handler_t proxy_get;
|
|
server_http_context::handler_t proxy_post;
|
|
server_http_context::handler_t get_router_models;
|
|
server_http_context::handler_t post_router_models_load;
|
|
server_http_context::handler_t post_router_models_status;
|
|
server_http_context::handler_t post_router_models_unload;
|
|
};
|
|
|
|
/**
|
|
* A simple HTTP proxy that forwards requests to another server
|
|
* and relays the responses back.
|
|
*/
|
|
struct server_http_proxy : server_http_res {
|
|
std::function<void()> cleanup = nullptr;
|
|
public:
|
|
server_http_proxy(const std::string & method,
|
|
const std::string & host,
|
|
int port,
|
|
const std::string & path,
|
|
const std::map<std::string, std::string> & headers,
|
|
const std::string & body,
|
|
const std::function<bool()> should_stop);
|
|
~server_http_proxy() {
|
|
if (cleanup) {
|
|
cleanup();
|
|
}
|
|
}
|
|
private:
|
|
std::thread thread;
|
|
struct msg_t {
|
|
std::map<std::string, std::string> headers;
|
|
int status = 0;
|
|
std::string data;
|
|
};
|
|
};
|