mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-11 22:53:00 +00:00
Use the lithos closest_supported_effort on ModelCapabilities
The reasoning-effort substitution rule now lives on lithos's ModelCapabilities, so the workflow fallback planner calls it directly and fabro-types drops its controls module. ReasoningEffort is re-exported from lithos alongside the other request types. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
87e1e3a00f
commit
f8df58966b
3 changed files with 4 additions and 84 deletions
|
|
@ -20,7 +20,7 @@ use fabro_types::settings::run::RunModelControls;
|
|||
use fabro_types::{
|
||||
AgentProfileKind, FailoverProps, Message, ModelHandle, ModelId, ModelRef, PermissionLevel,
|
||||
ProviderId, ReasoningEffort, Role, RunId, SessionCapability, Speed, StageId, StageTiming,
|
||||
TokenCounts, ToolDefinition as LlmToolDefinition, UsdMicros, billing, controls,
|
||||
TokenCounts, ToolDefinition as LlmToolDefinition, UsdMicros, billing,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use tokio::sync::mpsc;
|
||||
|
|
@ -897,9 +897,7 @@ impl AgentApiBackend {
|
|||
return FallbackControls::Usable(requested);
|
||||
};
|
||||
let capabilities = offering.model.capabilities();
|
||||
let effective_effort = controls::closest_supported_effort(requested_effort, |effort| {
|
||||
capabilities.reasoning_effort(effort).is_supported()
|
||||
});
|
||||
let effective_effort = capabilities.closest_supported_effort(requested_effort);
|
||||
match effective_effort {
|
||||
Some(effort) => FallbackControls::Usable(EffectiveRequestControls {
|
||||
reasoning_effort: Some(effort),
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
//! Helpers over the lithos request-control enums.
|
||||
//!
|
||||
//! lithos owns [`ReasoningEffort`] and [`Speed`], their spellings, and their
|
||||
//! parsing (`ALL`, `as_str`, `Display`, `FromStr`). What stays here is
|
||||
//! Fabro's own rule for substituting a reasoning level a model lacks.
|
||||
|
||||
pub use lithos_llm::types::{ReasoningEffort, Speed};
|
||||
|
||||
/// Position of an effort in the least-to-most ordering.
|
||||
fn effort_rank(effort: ReasoningEffort) -> usize {
|
||||
ReasoningEffort::ALL
|
||||
.iter()
|
||||
.position(|candidate| *candidate == effort)
|
||||
.unwrap_or(ReasoningEffort::ALL.len())
|
||||
}
|
||||
|
||||
/// Selects the supported effort nearest to `requested`.
|
||||
///
|
||||
/// When two supported values are equally distant, the higher effort wins.
|
||||
/// Returns `None` when nothing is supported.
|
||||
#[must_use]
|
||||
pub fn closest_supported_effort(
|
||||
requested: ReasoningEffort,
|
||||
supported: impl Fn(ReasoningEffort) -> bool,
|
||||
) -> Option<ReasoningEffort> {
|
||||
let target = effort_rank(requested);
|
||||
ReasoningEffort::ALL
|
||||
.into_iter()
|
||||
.filter(|effort| supported(*effort))
|
||||
.min_by_key(|effort| {
|
||||
let rank = effort_rank(*effort);
|
||||
(rank.abs_diff(target), std::cmp::Reverse(rank))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lithos_spellings_match_serde() {
|
||||
for effort in ReasoningEffort::ALL {
|
||||
let json = serde_json::to_string(&effort).unwrap();
|
||||
assert_eq!(json, format!("\"{effort}\""));
|
||||
assert_eq!(effort.as_str().parse::<ReasoningEffort>().unwrap(), effort);
|
||||
}
|
||||
for speed in Speed::ALL {
|
||||
let json = serde_json::to_string(&speed).unwrap();
|
||||
assert_eq!(json, format!("\"{speed}\""));
|
||||
assert_eq!(speed.as_str().parse::<Speed>().unwrap(), speed);
|
||||
}
|
||||
assert!("standard".parse::<ReasoningEffort>().is_err());
|
||||
assert!("standard".parse::<Speed>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closest_supported_prefers_the_higher_neighbor_on_ties() {
|
||||
let supported = |effort| matches!(effort, ReasoningEffort::Low | ReasoningEffort::High);
|
||||
assert_eq!(
|
||||
closest_supported_effort(ReasoningEffort::Medium, supported),
|
||||
Some(ReasoningEffort::High)
|
||||
);
|
||||
assert_eq!(
|
||||
closest_supported_effort(ReasoningEffort::Max, supported),
|
||||
Some(ReasoningEffort::High)
|
||||
);
|
||||
assert_eq!(
|
||||
closest_supported_effort(ReasoningEffort::Minimal, supported),
|
||||
Some(ReasoningEffort::Low)
|
||||
);
|
||||
assert_eq!(
|
||||
closest_supported_effort(ReasoningEffort::Medium, |_| false),
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ pub mod catalog_api;
|
|||
pub mod checkpoint;
|
||||
pub mod command_output;
|
||||
pub mod conclusion;
|
||||
pub mod controls;
|
||||
pub mod dense;
|
||||
pub mod diff;
|
||||
pub mod event_envelope;
|
||||
|
|
@ -76,7 +75,6 @@ pub use catalog_api::{Model, ModelControls, ModelCosts, ModelFeatures, ModelLimi
|
|||
pub use checkpoint::Checkpoint;
|
||||
pub use command_output::{CommandOutputStream, CommandTermination};
|
||||
pub use conclusion::{Conclusion, StageSummary};
|
||||
pub use controls::ReasoningEffort;
|
||||
pub use dense::{ServerSettings, UserSettings, WorkflowSettings};
|
||||
pub use diff::{DiffStats, DiffSummary, RunDiff};
|
||||
pub use event_envelope::EventEnvelope;
|
||||
|
|
@ -94,8 +92,8 @@ pub use interview::{
|
|||
};
|
||||
pub use lithos_llm::catalog::{ModelHandle, ModelId, ProviderId};
|
||||
pub use lithos_llm::types::{
|
||||
FinishReason, ReasoningOutput, Request, RequestBuildError, RequestBuilder, Response,
|
||||
ResponseFormat, StreamEvent,
|
||||
FinishReason, ReasoningEffort, ReasoningOutput, Request, RequestBuildError, RequestBuilder,
|
||||
Response, ResponseFormat, StreamEvent,
|
||||
};
|
||||
pub use llm_backend::AgentBackend;
|
||||
pub use manifest_path::{ManifestPath, ManifestPathParseError};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue