mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-18 08:44:49 +02:00
migrate server
This commit is contained in:
+1
-1
@@ -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);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <vector>
|
||||
|
||||
using chat_template_caps = jinja::caps;
|
||||
using json = nlohmann::ordered_json;
|
||||
|
||||
struct common_chat_templates;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "server-task.h"
|
||||
#include "server-queue.h"
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include "json.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user