migrate server

This commit is contained in:
Xuan Son Nguyen
2026-08-21 21:05:03 +02:00
parent f262180084
commit d1a9e5a8e6
11 changed files with 267 additions and 211 deletions
+1 -1
View File
@@ -973,7 +973,7 @@ static std::string common_chat_template_direct_apply_impl(
jinja::caps_apply_reasoning_effort(ctx, reasoning_effort);
}
jinja::global_from_json(ctx, common_json_ref_from_raw(inp), inputs.mark_input);
jinja::global_from_json(ctx, common_json_from_raw(inp), inputs.mark_input);
// render
jinja::runtime runtime(ctx);
-1
View File
@@ -17,7 +17,6 @@
#include <vector>
using chat_template_caps = jinja::caps;
using json = nlohmann::ordered_json;
struct common_chat_templates;
+2 -3
View File
@@ -1355,7 +1355,7 @@ const func_builtins & value_undefined_t::get_builtins() const {
//////////////////////////////////
static value from_json(const common_json_ref & j, bool mark_input) {
static value from_json(const common_json & j, bool mark_input) {
if (j.is_null()) {
return mk_val<value_none>();
} else if (j.is_boolean()) {
@@ -1462,8 +1462,7 @@ void global_from_json(context & ctx, const T_JSON & json_obj, bool mark_input) {
}
}
template void global_from_json<common_json> (context &, const common_json &, bool);
template void global_from_json<common_json_ref>(context &, const common_json_ref &, bool);
template void global_from_json<common_json>(context &, const common_json &, bool);
// recursively convert value to JSON string
// TODO: avoid circular references
+1 -1
View File
@@ -86,7 +86,7 @@ struct context; // forward declaration
// marking input can be useful for tracking data provenance
// and preventing template injection attacks
//
// Note: T_JSON can be common_json or common_json_ref
// Note: T_JSON can be common_json
template<typename T_JSON>
void global_from_json(context & ctx, const T_JSON & json_obj, bool mark_input);
+156 -114
View File
@@ -6,27 +6,30 @@
#include <nlohmann/json.hpp>
#include <iterator>
#include <new>
#include <set>
#include <vector>
using nlohmann::ordered_json;
// common_json_node is never defined, it only stands for an ordered_json in this file
static ordered_json & as_json(common_json_node * node) {
return *reinterpret_cast<ordered_json *>(node);
// a common_json is the backing value, so any value of a tree can be used as a common_json
static_assert(sizeof(ordered_json) <= sizeof(common_json), "common_json storage is too small");
static_assert(alignof(ordered_json) <= alignof(common_json), "common_json alignment is too weak");
static ordered_json & as_json(common_json * self) {
return *reinterpret_cast<ordered_json *>(self);
}
static common_json_node * as_node(ordered_json * json) {
return reinterpret_cast<common_json_node *>(json);
static const ordered_json & as_json(const common_json * self) {
return *reinterpret_cast<const ordered_json *>(self);
}
void common_json_node_deleter::operator()(common_json_node * node) const {
delete reinterpret_cast<ordered_json *>(node);
static common_json & as_common(ordered_json & json) {
return *reinterpret_cast<common_json *>(&json);
}
static common_json make_json(const ordered_json & val) {
common_json out;
as_json(out.get_node()) = val;
return out;
static const common_json & as_common(const ordered_json & json) {
return *reinterpret_cast<const common_json *>(&json);
}
static ordered_json to_json(const common_json_value & val) {
@@ -37,33 +40,33 @@ static ordered_json to_json(const common_json_value & val) {
case common_json_value::VAL_UINT: return val.val_uint;
case common_json_value::VAL_DOUBLE: return val.val_double;
case common_json_value::VAL_STRING: return val.val_string;
case common_json_value::VAL_JSON: return as_json(val.val_json->get_node());
case common_json_value::VAL_JSON: return as_json(val.val_json.get());
}
return nullptr;
}
template <typename T> T & common_json_raw(common_json_ref & json) {
return as_json(json.get_node());
template <typename T> T & common_json_raw(common_json & json) {
return as_json(&json);
}
template <typename T> const T & common_json_raw(const common_json_ref & json) {
return as_json(json.get_node());
template <typename T> const T & common_json_raw(const common_json & json) {
return as_json(&json);
}
template <typename T> common_json common_json_from_raw(const T & json) {
return make_json(json);
return common_json(as_common(json));
}
template <typename T> common_json_ref common_json_ref_from_raw(T & json) {
return common_json_ref(as_node(&json));
template <typename T> common_json & common_json_ref_from_raw(T & json) {
return as_common(json);
}
// the bridge is usable only for the type below
template ordered_json & common_json_raw<ordered_json>(common_json_ref &);
template const ordered_json & common_json_raw<ordered_json>(const common_json_ref &);
template ordered_json & common_json_raw<ordered_json>(common_json &);
template const ordered_json & common_json_raw<ordered_json>(const common_json &);
template common_json common_json_from_raw<ordered_json>(const ordered_json &);
template common_json_ref common_json_ref_from_raw<ordered_json>(ordered_json &);
template common_json & common_json_ref_from_raw<ordered_json>(ordered_json &);
common_json_value::common_json_value(const char * val) {
if (val) {
@@ -77,86 +80,29 @@ common_json_value::common_json_value(const char * val) {
common_json_value::common_json_value(const common_json & val) :
type(VAL_JSON), val_json(std::make_shared<common_json>(val)) {}
common_json_value::common_json_value(const std::vector<std::string> & vals) : type(VAL_JSON) {
common_json out = common_json::array();
for (const auto & val : vals) {
out.push_back(val);
}
val_json = std::make_shared<common_json>(std::move(out));
}
common_json_value::common_json_value(std::initializer_list<common_json_item> items) :
type(VAL_JSON), val_json(std::make_shared<common_json>(items)) {}
common_json_value::common_json_value(const common_json_ref & val) :
type(VAL_JSON), val_json(std::make_shared<common_json>(make_json(as_json(val.get_node())))) {}
bool common_json_ref::is_null() const { return as_json(node).is_null(); }
bool common_json_ref::is_object() const { return as_json(node).is_object(); }
bool common_json_ref::is_array() const { return as_json(node).is_array(); }
bool common_json_ref::is_string() const { return as_json(node).is_string(); }
bool common_json_ref::is_boolean() const { return as_json(node).is_boolean(); }
bool common_json_ref::is_number() const { return as_json(node).is_number(); }
bool common_json_ref::is_number_integer() const { return as_json(node).is_number_integer(); }
bool common_json_ref::is_number_float() const { return as_json(node).is_number_float(); }
bool common_json_ref::empty() const { return as_json(node).empty(); }
size_t common_json_ref::size() const { return as_json(node).size(); }
bool common_json_ref::contains(const std::string & key) const {
return as_json(node).contains(key);
common_json::common_json() {
new (storage) ordered_json(ordered_json::object());
}
bool common_json_ref::operator==(const common_json_value & val) const {
return as_json(node) == to_json(val);
common_json::common_json(const common_json & other) {
new (storage) ordered_json(as_json(&other));
}
bool common_json_ref::operator!=(const common_json_value & val) const {
return !(*this == val);
}
common_json_ref common_json_ref::at(const std::string & key) const {
return common_json_ref(as_node(&as_json(node).at(key)));
}
common_json_ref common_json_ref::operator[](const std::string & key) const {
return common_json_ref(as_node(&as_json(node)[key]));
}
common_json_ref common_json_ref::operator[](size_t idx) const {
return common_json_ref(as_node(&as_json(node)[idx]));
}
void common_json_ref::assign(const common_json_value & val) {
as_json(node) = to_json(val);
}
void common_json_ref::set(const common_json_item & item) {
as_json(node)[item.key] = to_json(item.val);
}
void common_json_ref::push_back(const common_json_value & val) {
as_json(node).push_back(to_json(val));
}
std::string common_json_ref::dump(int indent) const {
return as_json(node).dump(indent);
}
// an array is indexed directly, an object needs a walk from the start
common_json_ref common_json_ref::iterator::operator*() const {
if (as_json(node).is_object()) {
return common_json_ref(as_node(&std::next(as_json(node).begin(), idx).value()));
}
return common_json_ref(as_node(&as_json(node)[idx]));
}
std::string common_json_ref::iterator::key() const {
return std::next(as_json(node).begin(), idx).key();
}
std::pair<std::string, common_json_ref> common_json_ref::items_view::iterator::operator*() const {
auto it = std::next(as_json(node).begin(), idx);
return { it.key(), common_json_ref(as_node(&it.value())) };
}
common_json::common_json() :
common_json_ref(nullptr), pimpl(as_node(new ordered_json(ordered_json::object()))) {
node = pimpl.get();
common_json::common_json(common_json && other) noexcept {
new (storage) ordered_json(std::move(as_json(&other)));
}
common_json::common_json(std::initializer_list<common_json_item> items) : common_json() {
@@ -165,43 +111,40 @@ common_json::common_json(std::initializer_list<common_json_item> items) : common
}
}
common_json::common_json(const common_json & other) :
common_json_ref(nullptr), pimpl(as_node(new ordered_json(as_json(other.node)))) {
node = pimpl.get();
common_json::common_json(const common_json_value & val) {
new (storage) ordered_json(to_json(val));
}
common_json::common_json(common_json && other) noexcept :
common_json_ref(other.node), pimpl(std::move(other.pimpl)) {
other.node = nullptr;
common_json::common_json(std::nullptr_t) {
new (storage) ordered_json(nullptr);
}
common_json & common_json::operator=(const common_json & other) {
as_json(node) = as_json(other.node);
as_json(this) = as_json(&other);
return *this;
}
common_json & common_json::operator=(common_json && other) noexcept {
pimpl = std::move(other.pimpl);
node = pimpl.get();
other.node = nullptr;
as_json(this) = std::move(as_json(&other));
return *this;
}
common_json::~common_json() = default;
common_json::~common_json() {
as_json(this).~basic_json();
}
common_json common_json::parse(const std::string & text) {
try {
return make_json(ordered_json::parse(text));
return common_json_from_raw(ordered_json::parse(text));
} catch (const std::exception & e) {
throw common_json_error(e.what());
}
}
common_json common_json::array() {
return make_json(ordered_json::array());
return common_json_from_raw(ordered_json::array());
}
common_json common_json::array(std::initializer_list<common_json_value> vals) {
@@ -211,7 +154,7 @@ common_json common_json::array(std::initializer_list<common_json_value> vals) {
out.push_back(to_json(val));
}
return make_json(out);
return common_json_from_raw(out);
}
common_json common_json::object() {
@@ -219,16 +162,114 @@ common_json common_json::object() {
}
common_json common_json::make(const common_json_value & val) {
return make_json(to_json(val));
return common_json(val);
}
template <typename T> T common_json_ref::get() const {
return as_json(node).get<T>();
bool common_json::is_null() const { return as_json(this).is_null(); }
bool common_json::is_object() const { return as_json(this).is_object(); }
bool common_json::is_array() const { return as_json(this).is_array(); }
bool common_json::is_string() const { return as_json(this).is_string(); }
bool common_json::is_boolean() const { return as_json(this).is_boolean(); }
bool common_json::is_number() const { return as_json(this).is_number(); }
bool common_json::is_number_integer() const { return as_json(this).is_number_integer(); }
bool common_json::is_number_float() const { return as_json(this).is_number_float(); }
bool common_json::empty() const { return as_json(this).empty(); }
size_t common_json::size() const { return as_json(this).size(); }
bool common_json::contains(const std::string & key) const {
return as_json(this).contains(key);
}
bool common_json::operator==(const common_json_value & val) const {
return as_json(this) == to_json(val);
}
bool common_json::operator!=(const common_json_value & val) const {
return !(*this == val);
}
common_json & common_json::at(const std::string & key) { return as_common(as_json(this).at(key)); }
const common_json & common_json::at(const std::string & key) const { return as_common(as_json(this).at(key)); }
common_json & common_json::at(size_t idx) { return as_common(as_json(this).at(idx)); }
const common_json & common_json::at(size_t idx) const { return as_common(as_json(this).at(idx)); }
common_json & common_json::operator[](const std::string & key) { return as_common(as_json(this)[key]); }
const common_json & common_json::operator[](const std::string & key) const { return as_common(as_json(this).at(key)); }
common_json & common_json::operator[](size_t idx) { return as_common(as_json(this)[idx]); }
const common_json & common_json::operator[](size_t idx) const { return as_common(as_json(this).at(idx)); }
common_json & common_json::front() { return as_common(as_json(this).front()); }
const common_json & common_json::front() const { return as_common(as_json(this).front()); }
common_json & common_json::back() { return as_common(as_json(this).back()); }
const common_json & common_json::back() const { return as_common(as_json(this).back()); }
void common_json::erase(const std::string & key) {
as_json(this).erase(key);
}
void common_json::erase(size_t idx) {
as_json(this).erase(idx);
}
void common_json::assign(const common_json_value & val) {
as_json(this) = to_json(val);
}
void common_json::set(const common_json_item & item) {
as_json(this)[item.key] = to_json(item.val);
}
void common_json::push_back(const common_json_value & val) {
as_json(this).push_back(to_json(val));
}
std::string common_json::dump(int indent) const {
return as_json(this).dump(indent);
}
std::string common_json::dump_safe(int indent) const {
return as_json(this).dump(indent, ' ', false, ordered_json::error_handler_t::replace);
}
// an array is indexed directly, an object needs a walk from the start
common_json & common_json::iterator::operator*() const {
if (as_json(node).is_object()) {
return as_common(std::next(as_json(node).begin(), idx).value());
}
return as_common(as_json(node)[idx]);
}
std::string common_json::iterator::key() const {
return std::next(as_json(node).begin(), idx).key();
}
common_json::iterator common_json::begin() const {
return iterator(const_cast<common_json *>(this), 0);
}
common_json::iterator common_json::end() const {
return iterator(const_cast<common_json *>(this), size());
}
common_json::items_view::entry common_json::items_view::iterator::operator*() const {
auto it = std::next(as_json(node).begin(), idx);
return { it.key(), as_common(it.value()) };
}
common_json::items_view common_json::items() const {
return items_view(const_cast<common_json *>(this), size());
}
template <typename T> T common_json::get() const {
return as_json(this).get<T>();
}
// get<T>() is usable only for the types below
#define COMMON_JSON_GET(...) template __VA_ARGS__ common_json_ref::get<__VA_ARGS__>() const;
#define COMMON_JSON_GET(...) template __VA_ARGS__ common_json::get<__VA_ARGS__>() const;
COMMON_JSON_GET(bool)
COMMON_JSON_GET(int)
@@ -241,5 +282,6 @@ COMMON_JSON_GET(float)
COMMON_JSON_GET(double)
COMMON_JSON_GET(std::string)
COMMON_JSON_GET(std::vector<std::string>)
COMMON_JSON_GET(std::set<std::string>)
#undef COMMON_JSON_GET
+80 -69
View File
@@ -2,6 +2,7 @@
// JSON object, it works without the need to include a JSON library header
// the underlay library is pimpl, it should never be exposed here
// the backing value lives inside this object, so at() and the iterators give a real reference to it
// note: object keys keep the order in which they are added
#include <cstddef>
@@ -12,20 +13,13 @@
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
class common_json;
class common_json_ref;
// common_json_value holds a list of these, and each of them holds a value, so one must come first
struct common_json_item;
// one value of the backing library, only json.cpp knows what it is
struct common_json_node;
struct common_json_node_deleter {
void operator()(common_json_node * node) const;
};
struct common_json_error : std::runtime_error {
using std::runtime_error::runtime_error;
};
@@ -59,7 +53,7 @@ struct common_json_value {
common_json_value(std::string val) : type(VAL_STRING), val_string(std::move(val)) {}
common_json_value(const char * val);
common_json_value(const common_json & val);
common_json_value(const common_json_ref & val);
common_json_value(const std::vector<std::string> & vals);
// nested object, e.g. {"fn", {{"name", "x"}}}
common_json_value(std::initializer_list<common_json_item> items);
@@ -90,15 +84,31 @@ struct common_json_item {
key(std::move(key)), val(items) {}
};
// view to a value owned by a common_json, it goes stale if the owner gets a new key
class common_json_ref {
class common_json {
public:
explicit common_json_ref(common_json_node * node) : node(node) {}
common_json();
common_json(const common_json & other);
common_json(common_json && other) noexcept;
common_json(std::initializer_list<common_json_item> items);
common_json(const common_json_value & val);
common_json_ref(const common_json_ref &) = default;
// direct, a value would need two conversions in a row
common_json(std::nullptr_t);
// rebinding a view is almost always a write-through by mistake, use assign() to write
common_json_ref & operator=(const common_json_ref &) = delete;
common_json & operator=(const common_json & other);
common_json & operator=(common_json && other) noexcept;
~common_json();
// throws common_json_error if the text is not valid JSON
static common_json parse(const std::string & text);
static common_json array();
static common_json array(std::initializer_list<common_json_value> vals);
static common_json object();
// holds a single value, e.g. make("abc").dump() gives "\"abc\""
static common_json make(const common_json_value & val);
bool is_null() const;
bool is_object() const;
@@ -118,9 +128,23 @@ class common_json_ref {
bool operator!=(const common_json_value & val) const;
// at() throws if the key is missing, operator[] adds a null value instead
common_json_ref at(const std::string & key) const;
common_json_ref operator[](const std::string & key) const;
common_json_ref operator[](size_t idx) const;
common_json & at(const std::string & key);
const common_json & at(const std::string & key) const;
common_json & at(size_t idx);
const common_json & at(size_t idx) const;
common_json & operator[](const std::string & key);
const common_json & operator[](const std::string & key) const;
common_json & operator[](size_t idx);
const common_json & operator[](size_t idx) const;
common_json & front();
const common_json & front() const;
common_json & back();
const common_json & back() const;
void erase(const std::string & key);
void erase(size_t idx);
// only for the types instantiated in json.cpp, the rest fails at link time
template <typename T> T get() const;
@@ -138,21 +162,26 @@ class common_json_ref {
void set(const common_json_item & item);
void push_back(const common_json_value & val);
template <typename T>
common_json_ref & operator=(T && val) {
// a common_json goes through the copy assignment above, everything else becomes a value
template <typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, common_json>::value, int>::type = 0>
common_json & operator=(T && val) {
assign(common_json_value(std::forward<T>(val)));
return *this;
}
std::string dump(int indent = -1) const;
// same as dump(), but bad UTF-8 gets replaced instead of throwing
std::string dump_safe(int indent = -1) const;
// walks an array by index, or an object in insertion order
class iterator {
public:
iterator(common_json_node * node, size_t idx) : node(node), idx(idx) {}
iterator(common_json * node, size_t idx) : node(node), idx(idx) {}
common_json_ref operator*() const;
std::string key() const;
common_json & operator*() const;
common_json & value() const { return **this; }
std::string key() const;
iterator & operator++() {
idx++;
@@ -163,23 +192,32 @@ class common_json_ref {
bool operator==(const iterator & other) const { return idx == other.idx; }
private:
common_json_node * node;
size_t idx;
common_json * node;
size_t idx;
};
iterator begin() const { return iterator(node, 0); }
iterator end() const { return iterator(node, size()); }
iterator begin() const;
iterator end() const;
// allows: for (const auto & [key, val] : obj.items())
class items_view {
public:
items_view(common_json_node * node, size_t n) : node(node), n(n) {}
// the members are public, so an entry also works with structured bindings
struct entry {
std::string k;
common_json & v;
const std::string & key() const { return k; }
common_json & value() const { return v; }
};
items_view(common_json * node, size_t n) : node(node), n(n) {}
class iterator {
public:
iterator(common_json_node * node, size_t idx) : node(node), idx(idx) {}
iterator(common_json * node, size_t idx) : node(node), idx(idx) {}
std::pair<std::string, common_json_ref> operator*() const;
entry operator*() const;
iterator & operator++() {
idx++;
@@ -189,62 +227,35 @@ class common_json_ref {
bool operator!=(const iterator & other) const { return idx != other.idx; }
private:
common_json_node * node;
size_t idx;
common_json * node;
size_t idx;
};
iterator begin() const { return iterator(node, 0); }
iterator end() const { return iterator(node, n); }
private:
common_json_node * node;
size_t n;
common_json * node;
size_t n;
};
items_view items() const { return items_view(node, size()); }
common_json_node * get_node() const { return node; }
protected:
common_json_node * node;
};
// owns the value it points to
class common_json : public common_json_ref {
public:
common_json();
common_json(std::initializer_list<common_json_item> items);
common_json(const common_json & other);
common_json(common_json && other) noexcept;
common_json & operator=(const common_json & other);
common_json & operator=(common_json && other) noexcept;
// out-of-line, the deleter needs to know the real type
~common_json();
// throws common_json_error if the text is not valid JSON
static common_json parse(const std::string & text);
static common_json array();
static common_json array(std::initializer_list<common_json_value> vals);
static common_json object();
// holds a single value, e.g. make("abc").dump() gives "\"abc\""
static common_json make(const common_json_value & val);
items_view items() const;
private:
std::unique_ptr<common_json_node, common_json_node_deleter> pimpl;
// the backing value is built here, json.cpp checks that it fits
alignas(8) unsigned char storage[32];
};
using common_json_entry = common_json::items_view::entry;
// bridge for code that still uses internal component from nlohmann::json
// usage: common_json_raw<nlohmann::ordered_json>(j)
// TODO: maybe completely remove this in the future
template <typename T> T & common_json_raw(common_json_ref & json);
template <typename T> const T & common_json_raw(const common_json_ref & json);
template <typename T> T & common_json_raw(common_json & json);
template <typename T> const T & common_json_raw(const common_json & json);
template <typename T> common_json common_json_from_raw(const T & json);
// view over a value of the backing library, it does not copy
template <typename T> common_json_ref common_json_ref_from_raw(T & json);
template <typename T> common_json & common_json_ref_from_raw(T & json);
+1 -2
View File
@@ -6,9 +6,8 @@
#include "server-common.h"
#include "server-http.h"
#include <nlohmann/json_fwd.hpp>
#include "json.h"
using json = nlohmann::ordered_json;
// Convert OpenAI Responses API format to OpenAI Chat Completions API format
json server_chat_convert_responses_to_chatcmpl(const json & body);
+20 -13
View File
@@ -9,6 +9,9 @@
#include "server-common.h"
// the chat API is not migrated yet, so this file still needs the bridge
#include <nlohmann/json.hpp>
#include <random>
#include <sstream>
#include <fstream>
@@ -977,9 +980,9 @@ static server_tokens tokenize_input_subprompt(const llama_vocab * vocab, mtmd_co
// JSON object with prompt and multimodal key.
std::vector<raw_buffer> files;
for (const auto & entry : json_prompt.at(JSON_MTMD_DATA_KEY)) {
files.push_back(base64_decode(entry));
files.push_back(base64_decode(entry.get<std::string>()));
}
return process_mtmd_prompt(mctx, json_prompt.at(JSON_STRING_PROMPT_KEY), files);
return process_mtmd_prompt(mctx, json_prompt.at(JSON_STRING_PROMPT_KEY).get<std::string>(), files);
} else {
// Not multimodal, but contains a subobject.
llama_tokens tmp = tokenize_mixed(vocab, json_prompt.at(JSON_STRING_PROMPT_KEY), add_special, parse_special);
@@ -1258,8 +1261,8 @@ json oaicompat_chat_params_parse(
auto caps = common_chat_templates_get_caps(opt.tmpls.get());
common_chat_templates_inputs inputs;
inputs.messages = common_chat_msgs_parse_oaicompat(messages);
inputs.tools = common_chat_tools_parse_oaicompat(tools);
inputs.messages = common_chat_msgs_parse_oaicompat(common_json_raw<nlohmann::ordered_json>(messages));
inputs.tools = common_chat_tools_parse_oaicompat(common_json_raw<nlohmann::ordered_json>(tools));
inputs.tool_choice = common_chat_tool_choice_parse_oaicompat(tool_choice);
inputs.json_schema = json_schema.is_null() ? "" : json_schema.dump();
inputs.grammar = grammar;
@@ -1267,7 +1270,7 @@ json oaicompat_chat_params_parse(
inputs.parallel_tool_calls = json_value(body, "parallel_tool_calls", caps["supports_parallel_tool_calls"]);
inputs.add_generation_prompt = json_value(body, "add_generation_prompt", true);
inputs.continue_final_message = body.contains("continue_final_message") ?
common_chat_continuation_parse(body.at("continue_final_message")) :
common_chat_continuation_parse(common_json_raw<nlohmann::ordered_json>(body.at("continue_final_message"))) :
COMMON_CHAT_CONTINUATION_NONE;
if (inputs.continue_final_message == COMMON_CHAT_CONTINUATION_NONE && opt.prefill_assistant
&& !inputs.messages.empty() && inputs.messages.back().role == "assistant") {
@@ -1300,7 +1303,8 @@ json oaicompat_chat_params_parse(
}
// parse the "enable_thinking" kwarg to override the default value
auto enable_thinking_kwarg = json_value(inputs.chat_template_kwargs, "enable_thinking", std::string(""));
const auto kwarg_it = inputs.chat_template_kwargs.find("enable_thinking");
std::string enable_thinking_kwarg = kwarg_it == inputs.chat_template_kwargs.end() ? "" : kwarg_it->second;
if (enable_thinking_kwarg == "true") {
inputs.enable_thinking = true;
} else if (enable_thinking_kwarg == "false") {
@@ -1316,7 +1320,7 @@ json oaicompat_chat_params_parse(
inputs.enable_thinking = false;
inputs.chat_template_kwargs.erase("reasoning_effort");
} else if (!reasoning_effort.empty()) {
inputs.chat_template_kwargs["reasoning_effort"] = json(reasoning_effort).dump();
inputs.chat_template_kwargs["reasoning_effort"] = json::make(reasoning_effort).dump();
}
}
@@ -1347,7 +1351,7 @@ json oaicompat_chat_params_parse(
llama_params["chat_parser"] = chat_params.parser;
}
llama_params["message_delimiters"] = chat_params.message_delimiters.to_json();
llama_params["message_delimiters"] = common_json_from_raw(chat_params.message_delimiters.to_json());
// Reasoning budget: pass parameters through to sampling layer
{
@@ -1465,7 +1469,10 @@ json format_response_rerank(
});
elements.resize(std::min(top_n, (int)elements.size()));
json results = elements;
json results = json::array();
for (const auto & el : elements) {
results.push_back(el);
}
if (is_tei_format) return results;
@@ -1540,7 +1547,7 @@ std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int i
}
std::string safe_json_to_str(const json & data) {
return data.dump(-1, ' ', false, json::error_handler_t::replace);
return data.dump_safe();
}
// TODO: reuse llama_detokenize
@@ -1790,12 +1797,12 @@ server_tokens format_prompt_rerank(
std::string prompt = rerank_prompt;
string_replace_all(prompt, "{query}" , query);
string_replace_all(prompt, "{document}", doc );
server_tokens tokens = tokenize_input_subprompt(vocab, mctx, prompt, false, true);
server_tokens tokens = tokenize_input_subprompt(vocab, mctx, json::make(prompt), false, true);
result.push_back(tokens);
} else {
// Get EOS token - use SEP token as fallback if EOS is not available
server_tokens query_tokens = tokenize_input_subprompt(vocab, mctx, query, false, false);
server_tokens doc_tokens = tokenize_input_subprompt(vocab, mctx, doc, false, false);
server_tokens query_tokens = tokenize_input_subprompt(vocab, mctx, json::make(query), false, false);
server_tokens doc_tokens = tokenize_input_subprompt(vocab, mctx, json::make(doc), false, false);
llama_token eos_token = llama_vocab_eos(vocab);
if (eos_token == LLAMA_TOKEN_NULL) {
eos_token = llama_vocab_sep(vocab);
+5 -5
View File
@@ -7,7 +7,7 @@
#include "mtmd.h"
#define JSON_ASSERT GGML_ASSERT
#include <nlohmann/json.hpp>
#include "json.h"
#include <atomic>
#include <chrono>
@@ -19,7 +19,7 @@
#include <string>
#include <vector>
using json = nlohmann::ordered_json;
using json = common_json;
#define SLT_DBG(slot, fmt, ...) LOG_DBG("slot %12.*s: id %2d | task %d | " fmt, 12, __func__, (slot).id, ((slot).task ? (slot).task->id : -1), __VA_ARGS__)
#define SLT_TRC(slot, fmt, ...) LOG_TRC("slot %12.*s: id %2d | task %d | " fmt, 12, __func__, (slot).id, ((slot).task ? (slot).task->id : -1), __VA_ARGS__)
@@ -42,9 +42,9 @@ static T json_value(const json & body, const std::string & key, const T & defaul
// Fallback null to default value
if (body.contains(key) && !body.at(key).is_null()) {
try {
return body.at(key);
} catch (NLOHMANN_JSON_NAMESPACE::detail::type_error const & err) {
LOG_WRN("Wrong type supplied for parameter '%s'. Expected '%s', using default value: %s\n", key.c_str(), json(default_value).type_name(), err.what());
return body.at(key).get<T>();
} catch (const std::exception & err) {
LOG_WRN("Wrong type supplied for parameter '%s', using default value: %s\n", key.c_str(), err.what());
return default_value;
}
} else {
+1 -1
View File
@@ -4,7 +4,7 @@
#include "server-task.h"
#include "server-queue.h"
#include <nlohmann/json_fwd.hpp>
#include "json.h"
#include <cstddef>
#include <memory>
-1
View File
@@ -11,7 +11,6 @@
// TODO: prevent including the whole server-common.h as we only use server_tokens
#include "server-common.h"
using json = nlohmann::ordered_json;
enum server_task_type {
SERVER_TASK_TYPE_COMPLETION,