Skip to content
Merged
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ The format is inspired by Keep a Changelog and this project follows Semantic Ver

### Changed

- (none yet)
- **Provider-agnostic `ModelConfig`** (#49): replaced `vitis_config: Option<VitisEpConfig>` with generic `backend_override: Option<String>` and `backend_config: HashMap<String, String>`. `VitisEpConfig` is retained as a CLI-level helper with `into_backend_config()` / `from_backend_config()` conversion methods.
- **Vitis EP reads via `backend_config` map** (#50): `onnx_vitis` functions (`discover_ort_dylib_path`, `build_base_session_builder_with_provider`, `build_session_with_vitis_cascade`) now read config values from the generic `backend_config` map instead of the Vitis-specific struct.
- **CPU EP unblocked by config refactor** (#51): `CpuBackend` and all non-Vitis callers now use `backend_override: None, backend_config: Default::default()`, removing any coupling to Vitis types.

### Fixed

Expand Down
3 changes: 2 additions & 1 deletion api_server/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ async fn run_investigation(task: &str, max_steps: usize) -> anyhow::Result<core_
max_new_tokens: 256,
temperature: 0.2,
dry_run: true,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
};
let engine = OnnxVitisEngine::new(model_config);
let tools = ToolRegistry::with_default_tools();
Expand Down
15 changes: 13 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4405,14 +4405,20 @@ fn run_model_pack_doctor_checks(runtime: &RuntimeConfig, report: &mut DoctorRepo
return;
}

let vitis_cfg = build_vitis_config(runtime);
let (bo, bc) = match vitis_cfg {
Some(cfg) => (Some("vitis".to_string()), cfg.into_backend_config()),
None => (None, Default::default()),
};
let compatibility = inspect_runtime_compatibility(
&ModelConfig {
model_path: runtime.model.clone(),
tokenizer_path: runtime.tokenizer.clone(),
max_new_tokens: 1,
temperature: runtime.temperature,
dry_run: false,
vitis_config: build_vitis_config(runtime),
backend_override: bo,
backend_config: bc,
},
true,
);
Expand Down Expand Up @@ -5734,13 +5740,18 @@ async fn run_agent_once(runtime: &RuntimeConfig, dry_run: bool) -> Result<RunRep
}

let vitis_config = build_vitis_config(runtime);
let (backend_override, backend_config) = match vitis_config {
Some(cfg) => (Some("vitis".to_string()), cfg.into_backend_config()),
None => (None, Default::default()),
};
let model_config = ModelConfig {
model_path: runtime.model.clone(),
tokenizer_path: runtime.tokenizer.clone(),
max_new_tokens: runtime.max_new_tokens,
temperature: runtime.temperature,
dry_run,
vitis_config,
backend_override,
backend_config,
};

// Determine capability tier: override > probe > default.
Expand Down
53 changes: 53 additions & 0 deletions docs/upgrades.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,58 @@
# Upgrade Notes

## Unreleased

### Breaking/visible changes

- **`ModelConfig` struct changed** (#49): the `vitis_config: Option<VitisEpConfig>` field is replaced by two new fields:
- `backend_override: Option<String>` — optional backend name hint (e.g. `"vitis"`)
- `backend_config: HashMap<String, String>` — generic key-value config map

Both fields default to empty via `#[serde(default)]`, so TOML/JSON deserialization is backward-compatible if you don't set them.

- **`VitisEpConfig` is still available** as a helper. Use `into_backend_config()` to convert to the new map and `from_backend_config()` to reconstruct from one.

### Migration

Before:
```rust
let config = ModelConfig {
// ...
vitis_config: Some(VitisEpConfig {
config_file: Some("/path/to/vitis.json".into()),
cache_dir: None,
cache_key: None,
}),
};
```

After:
```rust
use std::collections::HashMap;

let config = ModelConfig {
// ...
backend_override: Some("vitis".to_string()),
backend_config: HashMap::from([
("config_file".to_string(), "/path/to/vitis.json".to_string()),
]),
};
```

Or using the helper:
```rust
let vitis = VitisEpConfig {
config_file: Some("/path/to/vitis.json".into()),
cache_dir: None,
cache_key: None,
};
let config = ModelConfig {
// ...
backend_override: Some("vitis".to_string()),
backend_config: vitis.into_backend_config(),
};
```

## v1.3.0

### Breaking/visible changes
Expand Down
9 changes: 6 additions & 3 deletions inference_bridge/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ mod tests {
max_new_tokens: 1,
temperature: 0.0,
dry_run: true,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
};
let cpu = CpuBackend;
let session = cpu.build_session(&config, &BackendOptions::new());
Expand Down Expand Up @@ -529,7 +530,8 @@ mod tests {
max_new_tokens: 1,
temperature: 0.0,
dry_run: true,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
};
let result =
registry.build_session_with_fallback(&config, &BackendOptions::new(), None);
Expand All @@ -547,7 +549,8 @@ mod tests {
max_new_tokens: 1,
temperature: 0.0,
dry_run: true,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
};
let result =
registry.build_session_with_fallback(&config, &BackendOptions::new(), Some("CPU"));
Expand Down
40 changes: 37 additions & 3 deletions inference_bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ fn estimate_params_from_file_size(model_path: &PathBuf) -> f32 {

/// Detect which execution provider would be used for this config.
fn detect_execution_provider(config: &ModelConfig) -> String {
if config.vitis_config.is_some() {
if config.backend_override.as_deref() == Some("vitis")
|| config.backend_config.contains_key("config_file")
{
"VitisAIExecutionProvider".to_string()
} else if cfg!(feature = "onnx") {
// Without Vitis config, ONNX Runtime defaults to CPU.
Expand Down Expand Up @@ -129,14 +131,45 @@ pub struct VitisEpConfig {
pub cache_key: Option<String>,
}

impl VitisEpConfig {
/// Convert to a generic backend config map.
pub fn into_backend_config(self) -> std::collections::HashMap<String, String> {
let mut map = std::collections::HashMap::new();
if let Some(v) = self.config_file {
map.insert("config_file".to_string(), v);
}
if let Some(v) = self.cache_dir {
map.insert("cache_dir".to_string(), v);
}
if let Some(v) = self.cache_key {
map.insert("cache_key".to_string(), v);
}
map
}

/// Reconstruct from a generic backend config map.
pub fn from_backend_config(map: &std::collections::HashMap<String, String>) -> Self {
Self {
config_file: map.get("config_file").cloned(),
cache_dir: map.get("cache_dir").cloned(),
cache_key: map.get("cache_key").cloned(),
}
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelConfig {
pub model_path: PathBuf,
pub tokenizer_path: Option<PathBuf>,
pub max_new_tokens: usize,
pub temperature: f32,
pub dry_run: bool,
pub vitis_config: Option<VitisEpConfig>,
/// Explicit backend override (e.g., "cpu", "vitis", "cuda").
#[serde(default)]
pub backend_override: Option<String>,
/// Provider-specific key-value configuration.
#[serde(default)]
pub backend_config: std::collections::HashMap<String, String>,
}

#[async_trait]
Expand Down Expand Up @@ -356,7 +389,8 @@ mod tests {
max_new_tokens: 16,
temperature: 0.2,
dry_run: true,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
})
}

Expand Down
28 changes: 13 additions & 15 deletions inference_bridge/src/onnx_vitis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,8 @@ fn discover_ort_dylib_path(config: &ModelConfig) -> Option<PathBuf> {
let mut candidates = Vec::new();

if let Some(vitis_config_path) = config
.vitis_config
.as_ref()
.and_then(|cfg| cfg.config_file.as_deref())
.backend_config
.get("config_file")
{
let vitis_config_path = PathBuf::from(vitis_config_path);
if let Some(parent) = vitis_config_path.parent() {
Expand Down Expand Up @@ -1203,16 +1202,14 @@ fn build_base_session_builder_with_provider(
let mut vitis = ep::Vitis::default();

if use_vitis_provider {
if let Some(vitis_cfg) = &config.vitis_config {
if let Some(config_file) = &vitis_cfg.config_file {
vitis = vitis.with_config_file(config_file);
}
if let Some(cache_dir) = &vitis_cfg.cache_dir {
vitis = vitis.with_cache_dir(cache_dir);
}
if let Some(cache_key) = &vitis_cfg.cache_key {
vitis = vitis.with_cache_key(cache_key);
}
if let Some(config_file) = config.backend_config.get("config_file") {
vitis = vitis.with_config_file(config_file);
}
if let Some(cache_dir) = config.backend_config.get("cache_dir") {
vitis = vitis.with_cache_dir(cache_dir);
}
if let Some(cache_key) = config.backend_config.get("cache_key") {
vitis = vitis.with_cache_key(cache_key);
}
}

Expand Down Expand Up @@ -1254,7 +1251,7 @@ fn build_session_with_vitis_cascade(config: &ModelConfig) -> Result<Session> {
let force_cpu_provider = env_var_truthy("WRAITHRUN_FORCE_CPU_EP");
debug!(
model = %config.model_path.display(),
has_vitis_config = config.vitis_config.is_some(),
has_vitis_config = config.backend_config.contains_key("config_file"),
force_cpu_provider,
"building Vitis ONNX Runtime session"
);
Expand Down Expand Up @@ -2792,7 +2789,8 @@ mod tests {
max_new_tokens: 1,
temperature: 0.0,
dry_run: false,
vitis_config: None,
backend_override: None,
backend_config: Default::default(),
};

let report = inspect_runtime_compatibility(&config, true);
Expand Down
Loading