Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ add_library(dflash_common STATIC
src/common/backend_precision.cpp
src/common/daemon_loop.cpp
src/common/gguf_inspect.cpp
src/common/backend_plan.cpp
src/common/backend_factory.cpp
src/common/feature_gate.cpp
src/placement/placement_config.cpp
Expand Down Expand Up @@ -1816,16 +1817,18 @@ if(DFLASH27B_TESTS)
list(APPEND _raw_unit_test_targets test_model_smoke)
endif()

# Feature/architecture gate tests. check_feature_compatibility(),
# collect_feature_warnings() and the capability table are pure functions,
# so this target deliberately compiles only feature_gate.cpp and
# placement_config.cppno dflash_common, no ggml, no GPU toolkit. That
# keeps a gate rule testable in seconds instead of behind a full backend
# build, which is the whole reason these tests do not live in
# Backend planning and feature/architecture gate tests. The plan builder,
# check_feature_compatibility(), collect_feature_warnings(), and the
# capability table are pure policy, so this target compiles only their
# sources and placement_config.cpp. It needs no dflash_common, ggml, or GPU
# toolkit. This keeps policy rules testable in seconds instead of behind a
# full backend build, which is why these tests do not live in
# test_server_unit.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/test_feature_gate.cpp")
add_executable(test_feature_gate test/test_feature_gate.cpp)
target_sources(test_feature_gate PRIVATE
test/test_backend_plan.cpp
src/common/backend_plan.cpp
src/common/feature_gate.cpp
src/placement/placement_config.cpp)
target_include_directories(test_feature_gate PRIVATE
Expand Down
9 changes: 5 additions & 4 deletions server/src/bailingmoe3/bailingmoe3_backend.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#include "bailingmoe3_backend.h"

#include <cstdio>
#include <utility>

namespace dflash::common {
namespace {

Qwen35Config make_qwen_runtime_config(const BailingMoe3Config & cfg) {
Qwen35Config make_qwen_runtime_config(BailingMoe3Config cfg) {
Qwen35Config runtime;
runtime.target_path = cfg.model_path;
runtime.target_path = std::move(cfg.model_path);
runtime.device = cfg.device;
runtime.stream_fd = cfg.stream_fd;
// The Ling baseline uses the ordinary contiguous F16/Q4 KV cache and the
Expand All @@ -22,8 +23,8 @@ Qwen35Config make_qwen_runtime_config(const BailingMoe3Config & cfg) {

} // namespace

BailingMoe3Backend::BailingMoe3Backend(const BailingMoe3Config & cfg)
: Qwen35Backend(make_qwen_runtime_config(cfg)) {}
BailingMoe3Backend::BailingMoe3Backend(BailingMoe3Config cfg)
: Qwen35Backend(make_qwen_runtime_config(std::move(cfg))) {}

bool BailingMoe3Backend::load_target_model(ggml_backend_t backend,
TargetWeights & out) {
Expand Down
4 changes: 2 additions & 2 deletions server/src/bailingmoe3/bailingmoe3_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ namespace dflash::common {
// Ling backend implements. Speculative decode and expert offload can be added
// after the autoregressive path has a logits-equivalent baseline.
struct BailingMoe3Config {
const char * model_path = nullptr;
std::string model_path;
DevicePlacement device;
int stream_fd = -1;
};

class BailingMoe3Backend final : public Qwen35Backend {
public:
explicit BailingMoe3Backend(const BailingMoe3Config & cfg);
explicit BailingMoe3Backend(BailingMoe3Config cfg);

void print_ready_banner() const override;
bool supports_dflash_spec_decode() const override { return false; }
Expand Down
54 changes: 35 additions & 19 deletions server/src/common/backend_args.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Raw backend construction arguments.
//
// This contains only caller-requested configuration. Runtime facts derived
// from the model or compiled binary belong in ResolvedBackendPlan instead.
// from the model or compiled binary belong in BackendPlan instead.

#pragma once

#include <limits>
#include <optional>
#include <string>

#include "placement/draft_residency.h"
#include "placement/placement_config.h"
Expand All @@ -15,35 +17,40 @@

namespace dflash::common {

// Server-owned features that participate in backend admission even though
// they are not consumed by ModelBackend construction itself. Keep these
// separate from BackendArgs so the factory API remains usable by callers that
// do not run the HTTP server.
struct BackendFeatureConfig {
enum class KvFlashRequest {
Off,
Auto,
Fixed,
};

// Server-owned facts that participate in backend admission without becoming
// backend construction arguments. This is the only projection the HTTP server
// may pass into backend preparation.
struct BackendAdmissionContext {
bool pflash_enabled = false;
bool pflash_drafter_configured = false;
DraftResidencyPolicy draft_residency = DraftResidencyPolicy::Auto;

// MoE-only server features. Recorded here so the gate can report them as
// inert on a dense architecture; both are applied via env vars at parse
// time rather than through BackendArgs.
bool routing_stats_requested = false; // --freq / --collect-routing
bool adaptive_experts_requested = false; // --adaptive-experts
// Automatic sizing remains backend-owned because only the initialized
// backend has the VRAM budget. Fixed pools can participate in admission.
KvFlashRequest kvflash = KvFlashRequest::Off;

// A fixed KVFlash pool requested through DFLASH_KVFLASH. "auto" is
// resolved later by the backend because only it has the VRAM budget needed
// to know whether a pool will actually be active.
bool kvflash_enabled = false;
bool kvflash_requested() const {
return kvflash != KvFlashRequest::Off;
}
bool fixed_kvflash_requested() const {
return kvflash == KvFlashRequest::Fixed;
}
};

// A superset of all per-architecture config fields. The factory reads only
// those relevant to the resolved architecture; unused fields are ignored.
// A superset of all per-architecture config fields. Preparation projects only
// the effective fields into BackendPlan's concern-specific snapshots.
struct BackendArgs {
// Required
const char * model_path = nullptr; // target .gguf
std::string model_path; // target .gguf

// Optional: speculative decode draft model (qwen35 only)
const char * draft_path = nullptr;
std::optional<std::string> draft_path;

// Device placement
DevicePlacement device;
Expand Down Expand Up @@ -82,13 +89,22 @@ struct BackendArgs {
bool fast_rollback = true;
bool seq_verify = false;
bool specla_mode = false;
int specla_top_k = 4;
bool specla_top_k_explicit = false;
bool ddtree_mode = false;
int ddtree_budget = 22;
float ddtree_temp = 1.0f;
bool ddtree_chain_seed = true;
float ddtree_tau = std::numeric_limits<float>::infinity();
bool ddtree_tau_explicit = false;
int verify_width = 0; // chain spec verify width; 0 = adaptive
bool use_feature_mirror = false;

// MoE backend requests. The server currently realizes these through
// environment variables, but admission still treats them as explicit
// operator input rather than server-owned context.
bool routing_stats_requested = false;
bool adaptive_experts_requested = false;
};

} // namespace dflash::common
Loading
Loading