#include "ling3/chat_protocol.h" #include "ling3/context_options.h" #include "ling3/runtime_requirements.h" #include using namespace ling3::chat; void Check(bool condition, const char * message) { if (!condition) throw std::runtime_error(message); } int main() { Json body {{"model", kModel}, {"messages", Json::array({ {{"role", "system"}, {"content", "请用中文回答"}}, {{"role", "user"}, {"content", "你好"}}, {{"role", "assistant"}, {"content", "你好!"}}, {{"role", "user"}, {"content", "继续"}}})}}; const auto r = Parse(body); Check(r.cache_prompt, "prefix cache should default on"); Check(r.max_tokens == SIZE_MAX, "default must use remaining context, not 128 tokens"); Check(OutputBudget(100, 4096, SIZE_MAX) == 3996, "unbounded budget overflow"); Check(OutputBudget(4095, 4096, 65536) == 1, "near-full prompt rejected"); Check(OutputBudget(4096, 4096, 10) == 0, "full prompt must finish with zero output"); Check(OutputBudget(100, 4096, 2) == 2, "explicit output budget ignored"); bool oversized = false; try { OutputBudget(4097, 4096, 1); } catch (const Error &) { oversized = true; } Check(oversized, "oversized input accepted"); auto large_output=body;large_output["max_tokens"]=65536; Check(Parse(large_output).max_tokens==65536,"large output budget rejected before context validation"); large_output["max_tokens"] = UINT64_MAX; Check(Parse(large_output).max_tokens == SIZE_MAX, "uint64 output budget overflow"); auto uncached = body; uncached["cache_prompt"] = false; uncached["user"] = "alice"; Check(!Parse(uncached).cache_prompt && Parse(uncached).cache_user == "alice", "cache controls"); Check(r.prompt == "SYSTEM请用中文回答\ndetailed thinking off<|role_end|>" "HUMAN你好<|role_end|>ASSISTANT\n你好!<|role_end|>" "HUMAN继续<|role_end|>ASSISTANT\n", "template mismatch"); for (const auto & mutation : std::vector{ {{"tools", Json::array()}}, {{"temperature", -1}}, {{"stream", "true"}}, {{"max_tokens", -1}}, {{"max_completion_tokens", 1.5}}, {{"n", 2}}, {{"model", "other"}}, {{"messages", Json::array()}}, {{"stop", ""}}, {{"cache_prompt", "false"}}}) { auto bad = body; bad.update(mutation); bool failed = false; try { Parse(bad); } catch (const Error &) { failed = true; } Check(failed, "invalid parameter accepted"); } TextFilter unicode({}); Check(unicode.Push("\xe4").empty(), "UTF8 split leaked"); Check(unicode.Push("\xbd").empty(), "UTF8 split leaked"); Check(unicode.Push("\xa0") == "你", "UTF8 split failed"); TextFilter stop({"END"}); Check(stop.Push("hello E") == "hello ", "stop prefix leaked"); Check(stop.Push("N").empty(), "stop prefix leaked"); Check(stop.Push("D trailing").empty() && stop.stopped, "split stop not recognized"); TextFilter tail({"END"}); Check(tail.Push("E").empty() && tail.Push({}, true) == "E", "tail flush failed"); Check(ling3::ParseContext("256K") == 262144, "context parsing"); Check(ling3::EstimateContextMiB(262144) + 1536 < 32000, "256K exceeds memory ceiling"); Check(!ling3::QualifiedRknpuDriver(0, 9, 7), "old driver accepted"); Check(ling3::QualifiedRknpuDriver(0, 9, 8), "minimum driver rejected"); Check(ling3::QualifiedRknpuDriver(0, 10, 0), "numeric version comparison failed"); std::cout << "chat protocol, UTF8, stop, context estimates passed\n"; }