| 417 | |
| 418 | // OpenAI-style additive penalties. |
| 419 | sampler.freq_pen = body.value("frequency_penalty", 0.0f); |
| 420 | sampler.pres_pen = body.value( |
| 421 | "presence_penalty", |
| 422 | defaults.has_presence_penalty ? defaults.presence_penalty : 0.0f); |
| 423 | // HuggingFace-style multiplicative repetition penalty (also used by |
| 424 | // vLLM, llama.cpp, etc.). Accepts both "repetition_penalty" and the |
| 425 | // shorter "rep_pen" for daemon compatibility. |
| 426 | sampler.rep_pen = body.value( |
| 427 | "repetition_penalty", |
| 428 | body.value("rep_pen", |
| 429 | defaults.has_repetition_penalty |
| 430 | ? defaults.repetition_penalty |
| 431 | : 1.0f)); |
| 432 | if (body.contains("rep_window")) { |
| 433 | sampler.rep_window = body["rep_window"].get<int>(); |
| 434 | } |
| 435 | return sampler; |
| 436 | } |
| 437 | |
| 438 | json require_messages_array(const json & body) { |
| 439 | if (!body.contains("messages") || !body["messages"].is_array() || |
| 440 | body["messages"].empty()) { |
| 441 | throw std::invalid_argument("messages must be a non-empty array"); |
| 442 | } |
| 443 | return body["messages"]; |
| 444 | } |
| 445 | |
| 446 | static bool env_flag_enabled(const char * name) { |
| 447 | const char * raw = std::getenv(name); |
| 448 | if (!raw || !*raw) return false; |
| 449 | std::string value(raw); |
no test coverage detected