bread-utils extracts genuinely duplicated logic found across breadbox, breadclip, breadmon, breadcrumbs, bos-settings, and breadhelp: - hypr: Hyprland socket1 request/response client (breadbox's get_active_workspace + breadclip's position.rs hyprctl_json were near-identical), socket2 path resolution (breadmon), and a version-tolerant `fullscreen` field parser (Hyprland has shipped both bool and int representations across versions). - singleton: correct flock-based single-instance toggle, replacing the TOCTOU-prone read-pid/check-proc/kill/write-pid pattern duplicated verbatim between breadbox and breadclip (breadclip's own comment says "matches breadbox pattern"). - proc: breadcrumbs' timeout-guarded subprocess runner, promoted verbatim as the one implementation in the ecosystem that already got this right. - atomic + xdg: atomic (temp-then-rename) file writes with an optional .bak-before-overwrite variant, and XDG path helpers that never fall back to a literal "~/..." string (the exact breadclip-core and breadpad-shared bug: PathBuf never expands `~`). - tomlcfg (feature "toml"): the load_doc/save_doc TOML-editing discipline bos-settings and breadhelp both implemented byte-for-byte identically in the same fix pass that introduced it. - gtk_popup (feature "gtk"): layer-shell overlay window setup, visible-row navigation, and click-outside-close, deduplicated from breadbox and breadclip (~150 duplicated lines, per both apps' own "same as breadbox" comments). bread-onnx extracts the embedding pipeline (tokenize -> tensor build -> mean-pool -> L2-normalize) duplicated near-verbatim between breadarr and breadsearch, a shared execution-provider session builder with loud EP- registration logging, and a model download+integrity helper. Defaults AMD iGPU acceleration to ort::ep::MIGraphX (not ROCm) per this machine's own breadsearch-gpu-backends lesson: ROCMExecutionProvider silently no-ops to CPU on distro ROCm onnxruntime builds compiled with --use_migraphx. Both crates build and pass their own test suites standalone. Consumer migrations follow in subsequent commits.
49 lines
2.1 KiB
Rust
49 lines
2.1 KiB
Rust
//! Session construction with execution-provider fallback.
|
|
//!
|
|
//! Builds one `ort::session::Session` whose execution-provider dispatch
|
|
//! list is exactly `providers` (in order) with an implicit `CPU` appended
|
|
//! if the caller didn't already include one — ONNX Runtime tries each
|
|
//! listed EP per-node and falls through the list on failure, so this
|
|
//! mirrors (and replaces) the identical `.with_execution_providers([primary,
|
|
//! CPU])` pattern already proven out in `breadmill/src/embed.rs::rocm_session`
|
|
//! /`cuda_session`/`openvino_session`/`npu_session`.
|
|
|
|
use std::path::Path;
|
|
|
|
use ort::session::builder::GraphOptimizationLevel;
|
|
use ort::session::Session;
|
|
|
|
use crate::provider::Provider;
|
|
|
|
/// Build a session, trying each of `providers` in order (ONNX Runtime falls
|
|
/// through per-node on registration failure) with a trailing `CPU` fallback
|
|
/// implicitly appended if not already present. Always logs which provider
|
|
/// was requested — see [`Provider::log_selection`] — regardless of whether
|
|
/// `tracing_subscriber` is initialized, so at minimum the *attempt* is
|
|
/// visible even without wired-up logging; the actual per-EP success/failure
|
|
/// detail only surfaces once a subscriber is listening.
|
|
pub fn build_session(
|
|
model_path: &Path,
|
|
opt_level: GraphOptimizationLevel,
|
|
providers: &[Provider],
|
|
) -> anyhow::Result<Session> {
|
|
let mut dispatch = Vec::with_capacity(providers.len() + 1);
|
|
for p in providers {
|
|
p.log_selection();
|
|
dispatch.push(p.to_dispatch()?);
|
|
}
|
|
if !providers.iter().any(|p| matches!(p, Provider::Cpu)) {
|
|
dispatch.push(Provider::Cpu.to_dispatch()?);
|
|
}
|
|
|
|
let mut builder = Session::builder()
|
|
.map_err(|e| anyhow::anyhow!("failed to create ort session builder: {e}"))?
|
|
.with_optimization_level(opt_level)
|
|
.map_err(|e| anyhow::anyhow!("failed to set optimization level: {e}"))?
|
|
.with_execution_providers(dispatch)
|
|
.map_err(|e| anyhow::anyhow!("failed to configure execution providers: {e}"))?;
|
|
|
|
builder
|
|
.commit_from_file(model_path)
|
|
.map_err(|e| anyhow::anyhow!("failed to load model from {}: {e}", model_path.display()))
|
|
}
|