Merge branch 'upstream' into concedo_experimental

# Conflicts:
#	.github/workflows/release.yml
#	.github/workflows/server.yml
#	examples/model-conversion/requirements.txt
#	examples/model-conversion/scripts/causal/run-casual-gen-embeddings-org.py
#	examples/speculative-simple/README.md
#	examples/speculative-simple/speculative-simple.cpp
#	ggml/src/ggml-opencl/ggml-opencl.cpp
#	requirements/requirements-convert_hf_to_gguf.txt
#	requirements/requirements-convert_lora_to_gguf.txt
#	scripts/hip/gcn-cdna-vgpr-check.py
#	tests/test-backend-ops.cpp
#	tests/test-chat.cpp
#	tools/imatrix/imatrix.cpp
#	tools/mtmd/CMakeLists.txt
This commit is contained in:
Concedo
2026-08-12 21:34:23 +08:00
79 changed files with 3714 additions and 282 deletions
+1 -6
View File
@@ -397,12 +397,7 @@ struct server_slot {
bool need_embd() const {
GGML_ASSERT(task);
return task->need_embd() || (spec && common_speculative_need_embd(spec));
}
bool need_embd_nextn() const {
GGML_ASSERT(task);
return spec && common_speculative_need_embd_nextn(spec);
return task->need_embd();
}
// if the context does not have a memory module then all embeddings have to be computed within a single ubatch
+30
View File
@@ -1,6 +1,7 @@
#include "server-tools.h"
#include "subproc.h"
#include "base64.hpp"
#include <filesystem>
#include <fstream>
@@ -864,6 +865,7 @@ static bool path_glob_match(const std::string & pattern, const std::string & rel
//
static constexpr size_t SERVER_TOOL_READ_FILE_MAX_SIZE = 16 * 1024; // 16 KB
static constexpr size_t SERVER_TOOL_READ_FILE_MAX_SIZE_BASE64 = 32 * 1024 * 1024; // 32 MB
struct server_tool_read_file : server_tool {
server_tool_read_file() {
@@ -899,6 +901,8 @@ struct server_tool_read_file : server_tool {
int start_line = json_value(params, "start_line", 1);
int end_line = json_value(params, "end_line", -1); // -1 = no limit
bool append_loc = json_value(params, "append_loc", false);
// comes from the x-resp-type header, the model cannot ask for it
bool as_base64 = json_value(params, "resp_type", std::string()) == "base64";
auto io = make_tools_io(params);
@@ -906,6 +910,23 @@ struct server_tool_read_file : server_tool {
if (!io->file_size(path, file_size)) {
return {{"error", "cannot stat file: " + path}};
}
if (as_base64) {
if (file_size > SERVER_TOOL_READ_FILE_MAX_SIZE_BASE64) {
return {{"error", string_format(
"file too large (%zu bytes, max %zu)",
(size_t)file_size, SERVER_TOOL_READ_FILE_MAX_SIZE_BASE64)}};
}
std::string content;
if (!io->read_file(path, content)) {
return {{"error", "failed to open file: " + path}};
}
return {
{"base64", base64::encode(content.data(), content.size())},
{"size_bytes", (size_t) content.size()},
};
}
if (file_size > SERVER_TOOL_READ_FILE_MAX_SIZE && end_line == -1) {
return {{"error", string_format(
"file too large (%zu bytes, max %zu). Use start_line/end_line to read a portion.",
@@ -2135,6 +2156,15 @@ void server_tools::setup(const std::vector<std::string> & enabled_tools,
params["runtime"] = runtime->spec();
}
// x-resp-type header is only used by read_file for now
if (params.contains("resp_type")) {
params.erase("resp_type");
}
auto resp_type = get_header(req.headers, "x-resp-type");
if (!resp_type.empty()) {
params["resp_type"] = resp_type;
}
server_tool & tool = find_tool(tools, tool_name, stream);
if (stream) {
+2 -4
View File
@@ -27,8 +27,8 @@ def test_with_and_without_draft():
global server
request = {
"prompt": "I believe the meaning of life is",
"temperature": 0.8,
"top_k": 40,
"temperature": 0.2,
"top_k": 5,
"seed": 4242,
"n_predict": 16,
"return_tokens": True,
@@ -36,7 +36,6 @@ def test_with_and_without_draft():
server.model_draft = None # disable draft model
server.spec_type = None
server.backend_sampling = True
server.start()
res = server.make_request("POST", "/completion", data=request)
assert res.status_code == 200
@@ -45,7 +44,6 @@ def test_with_and_without_draft():
# create new server with draft model
create_server()
server.backend_sampling = True
server.start()
res = server.make_request("POST", "/completion", data=request)
assert res.status_code == 200