mirror of
https://github.com/block/goose.git
synced 2026-10-19 09:34:12 +00:00
refactor(local-inference): use eredu naming without legacy aliases
This commit is contained in:
parent
7f9f023c3c
commit
af2737dea9
12 changed files with 68 additions and 111 deletions
|
|
@ -118,7 +118,7 @@ local-inference = ["goose/local-inference"]
|
|||
aws-providers = ["goose/aws-providers"]
|
||||
cuda = ["goose/cuda", "local-inference"]
|
||||
vulkan = ["goose/vulkan", "local-inference"]
|
||||
mlx = ["goose/mlx", "local-inference"]
|
||||
eredu = ["goose/eredu", "local-inference"]
|
||||
telemetry = ["goose/telemetry"]
|
||||
otel = ["goose/otel"]
|
||||
system-keyring = ["goose/system-keyring"]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ workspace = true
|
|||
default = []
|
||||
cuda = ["llama-cpp-2/cuda"]
|
||||
vulkan = ["llama-cpp-2/vulkan"]
|
||||
mlx = [
|
||||
eredu = [
|
||||
"dep:eredu",
|
||||
"dep:eredu-core",
|
||||
"dep:eredu-backend-mlx",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub(super) trait BackendLoadedModel: Send {
|
|||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "mlx"), allow(dead_code))]
|
||||
#[cfg_attr(not(feature = "eredu"), allow(dead_code))]
|
||||
pub(super) struct LocalGenerationRequest<'a> {
|
||||
pub model_name: String,
|
||||
pub system: &'a str,
|
||||
|
|
|
|||
|
|
@ -89,14 +89,14 @@ pub(crate) const EREDU_BACKEND_ID: &str = "eredu";
|
|||
pub(crate) fn unavailable_reason() -> Option<&'static str> {
|
||||
if !cfg!(all(target_os = "macos", target_arch = "aarch64")) {
|
||||
Some("The eredu backend in Goose requires Apple silicon macOS.")
|
||||
} else if !cfg!(feature = "mlx") {
|
||||
Some("Eredu support was not compiled in. Rebuild with the `mlx` feature.")
|
||||
} else if !cfg!(feature = "eredu") {
|
||||
Some("Eredu support was not compiled in. Rebuild with the `eredu` feature.")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "mlx", target_os = "macos", target_arch = "aarch64"))]
|
||||
#[cfg(all(feature = "eredu", target_os = "macos", target_arch = "aarch64"))]
|
||||
mod imp {
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -1041,7 +1041,7 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "mlx", target_os = "macos", target_arch = "aarch64")))]
|
||||
#[cfg(not(all(feature = "eredu", target_os = "macos", target_arch = "aarch64")))]
|
||||
mod imp {
|
||||
use super::*;
|
||||
use crate::backend::{BackendLoadedModel, LocalGenerationRequest, LocalInferenceBackend};
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ use serde::{Deserialize, Serialize};
|
|||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::eredu::snapshot_files_are_complete as mlx_snapshot_files_are_complete;
|
||||
use crate::eredu::snapshot_files_are_complete;
|
||||
use crate::huggingface_auth;
|
||||
|
||||
const HF_DOWNLOAD_BASE: &str = "https://huggingface.co";
|
||||
const LLAMACPP_BACKEND_ID: &str = "llamacpp";
|
||||
const MLX_BACKEND_ID: &str = "eredu";
|
||||
const EREDU_BACKEND_ID: &str = "eredu";
|
||||
const GGUF_FORMAT: &str = "gguf";
|
||||
const MLX_FORMAT: &str = "safetensors";
|
||||
const MLX_VARIANT_ID: &str = "default";
|
||||
const SAFETENSORS_FORMAT: &str = "safetensors";
|
||||
const SAFETENSORS_VARIANT_ID: &str = "default";
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HfModelInfo {
|
||||
|
|
@ -1143,10 +1143,10 @@ mod tests {
|
|||
unsupported_reason: None,
|
||||
};
|
||||
let mlx_variant = HfModelVariant {
|
||||
variant_id: MLX_VARIANT_ID.to_string(),
|
||||
variant_id: SAFETENSORS_VARIANT_ID.to_string(),
|
||||
label: "Default".to_string(),
|
||||
backend_id: MLX_BACKEND_ID.to_string(),
|
||||
format: MLX_FORMAT.to_string(),
|
||||
backend_id: EREDU_BACKEND_ID.to_string(),
|
||||
format: SAFETENSORS_FORMAT.to_string(),
|
||||
model_id: repo_id.clone(),
|
||||
download_id: repo_id.clone(),
|
||||
size_bytes: 8,
|
||||
|
|
@ -1195,7 +1195,7 @@ mod tests {
|
|||
assert!(models[0]
|
||||
.variants
|
||||
.iter()
|
||||
.any(|variant| variant.backend_id == MLX_BACKEND_ID));
|
||||
.any(|variant| variant.backend_id == EREDU_BACKEND_ID));
|
||||
}
|
||||
|
||||
fn sibling(filename: &str) -> RepoSibling {
|
||||
|
|
@ -1258,18 +1258,18 @@ mod tests {
|
|||
}
|
||||
});
|
||||
|
||||
assert!(!mlx_snapshot_files_are_complete(&cached, Some(&index)));
|
||||
assert!(!snapshot_files_are_complete(&cached, Some(&index)));
|
||||
cached.insert("model-00002-of-00002.safetensors");
|
||||
assert!(mlx_snapshot_files_are_complete(&cached, Some(&index)));
|
||||
assert!(snapshot_files_are_complete(&cached, Some(&index)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mlx_snapshot_requires_every_numbered_safetensors_shard_without_an_index() {
|
||||
let mut cached = std::collections::HashSet::from(["model-00001-of-00002.safetensors"]);
|
||||
|
||||
assert!(!mlx_snapshot_files_are_complete(&cached, None));
|
||||
assert!(!snapshot_files_are_complete(&cached, None));
|
||||
cached.insert("model-00002-of-00002.safetensors");
|
||||
assert!(mlx_snapshot_files_are_complete(&cached, None));
|
||||
assert!(snapshot_files_are_complete(&cached, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1277,7 +1277,7 @@ mod tests {
|
|||
let cached =
|
||||
std::collections::HashSet::from(["model.safetensors", "vision_model.safetensors"]);
|
||||
|
||||
assert!(mlx_snapshot_files_are_complete(&cached, None));
|
||||
assert!(snapshot_files_are_complete(&cached, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2137,8 +2137,8 @@ fn mlx_variants_from_model_info(
|
|||
vec![HfModelVariant {
|
||||
variant_id: variant_id.clone(),
|
||||
label: mlx_variant_label(&variant_id),
|
||||
backend_id: MLX_BACKEND_ID.to_string(),
|
||||
format: MLX_FORMAT.to_string(),
|
||||
backend_id: EREDU_BACKEND_ID.to_string(),
|
||||
format: SAFETENSORS_FORMAT.to_string(),
|
||||
model_id: repo_id.to_string(),
|
||||
download_id: repo_id.to_string(),
|
||||
size_bytes,
|
||||
|
|
@ -2243,14 +2243,14 @@ fn mlx_config_support(config: &Option<serde_json::Value>) -> Option<String> {
|
|||
mlx_config_support_for_value(config)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "mlx", target_os = "macos", target_arch = "aarch64"))]
|
||||
#[cfg(all(feature = "eredu", target_os = "macos", target_arch = "aarch64"))]
|
||||
fn mlx_config_support_for_value(config: &serde_json::Value) -> Option<String> {
|
||||
eredu_architectures::configuration::resolve_model_config(config)
|
||||
.err()
|
||||
.map(|error| error.to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "mlx", target_os = "macos", target_arch = "aarch64")))]
|
||||
#[cfg(not(all(feature = "eredu", target_os = "macos", target_arch = "aarch64")))]
|
||||
fn mlx_config_support_for_value(_config: &serde_json::Value) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
|
@ -2367,11 +2367,11 @@ fn mlx_variant_id(repo_id: &str, config: &Option<serde_json::Value>) -> String {
|
|||
.and_then(|config| config.get("torch_dtype"))
|
||||
.and_then(|value| value.as_str())
|
||||
.map(|dtype| dtype.replace("float", "f"))
|
||||
.unwrap_or_else(|| MLX_VARIANT_ID.to_string())
|
||||
.unwrap_or_else(|| SAFETENSORS_VARIANT_ID.to_string())
|
||||
}
|
||||
|
||||
fn mlx_variant_label(variant_id: &str) -> String {
|
||||
if variant_id == MLX_VARIANT_ID {
|
||||
if variant_id == SAFETENSORS_VARIANT_ID {
|
||||
"SafeTensors".to_string()
|
||||
} else {
|
||||
format!("SafeTensors {}", variant_id.to_uppercase())
|
||||
|
|
@ -2384,8 +2384,8 @@ pub async fn resolve_local_model_selection(
|
|||
variant_id: Option<&str>,
|
||||
) -> Result<ResolvedLocalModel> {
|
||||
match backend_id {
|
||||
MLX_BACKEND_ID | "mlx" => {
|
||||
resolve_mlx_model(repo_id, variant_id.unwrap_or(MLX_VARIANT_ID)).await
|
||||
EREDU_BACKEND_ID => {
|
||||
resolve_mlx_model(repo_id, variant_id.unwrap_or(SAFETENSORS_VARIANT_ID)).await
|
||||
}
|
||||
LLAMACPP_BACKEND_ID => {
|
||||
let quantization = variant_id.ok_or_else(|| {
|
||||
|
|
@ -2496,7 +2496,7 @@ pub async fn resolve_local_model_spec(spec: &str) -> Result<ResolvedLocalModel>
|
|||
let variants = get_repo_local_variants(spec).await?;
|
||||
let mlx_variants: Vec<_> = variants
|
||||
.iter()
|
||||
.filter(|variant| variant.backend_id == MLX_BACKEND_ID)
|
||||
.filter(|variant| variant.backend_id == EREDU_BACKEND_ID)
|
||||
.collect();
|
||||
if mlx_variants.len() == 1
|
||||
&& !variants
|
||||
|
|
@ -2907,7 +2907,7 @@ pub async fn cached_local_models() -> Result<Vec<CachedLocalModel>> {
|
|||
if is_mlx_compatible_repo(&config, &repo_siblings)
|
||||
&& is_mlx_runtime_supported(&config)
|
||||
&& valid_index
|
||||
&& mlx_snapshot_files_are_complete(&cached_filenames, index.as_ref())
|
||||
&& snapshot_files_are_complete(&cached_filenames, index.as_ref())
|
||||
{
|
||||
let cached_files: Vec<_> = revision
|
||||
.files
|
||||
|
|
@ -2918,9 +2918,9 @@ pub async fn cached_local_models() -> Result<Vec<CachedLocalModel>> {
|
|||
let model = CachedLocalModel {
|
||||
id: repo.repo_id.clone(),
|
||||
repo_id: repo.repo_id.clone(),
|
||||
filename: MLX_VARIANT_ID.to_string(),
|
||||
filename: SAFETENSORS_VARIANT_ID.to_string(),
|
||||
quantization: mlx_variant_id(&repo.repo_id, &config),
|
||||
backend_id: MLX_BACKEND_ID.to_string(),
|
||||
backend_id: EREDU_BACKEND_ID.to_string(),
|
||||
model_path: revision.snapshot_path.clone(),
|
||||
size_bytes: cached_files.iter().map(|file| file.size_on_disk).sum(),
|
||||
mmproj_path: None,
|
||||
|
|
@ -3029,7 +3029,7 @@ pub async fn delete_cached_local_model(model_id: &str) -> Result<()> {
|
|||
.flat_map(|repo| &repo.revisions)
|
||||
.flat_map(|revision| &revision.files)
|
||||
.filter(|file| {
|
||||
if model.backend_id == MLX_BACKEND_ID {
|
||||
if model.backend_id == EREDU_BACKEND_ID {
|
||||
should_download_for_mlx(&file.file_name)
|
||||
} else {
|
||||
let is_model_weight = file.file_name.ends_with(".gguf")
|
||||
|
|
|
|||
|
|
@ -184,7 +184,12 @@ impl InferenceRuntime {
|
|||
let state = slot.state.lock().await;
|
||||
if let ModelSlotState::Loaded { resolved, .. } = &*state {
|
||||
if selected_backend(&resolved.model_path, backend_id).ok()
|
||||
== Some(key_backend(&resolved.backend_id))
|
||||
== Some(
|
||||
resolved
|
||||
.backend_id
|
||||
.as_deref()
|
||||
.unwrap_or(LLAMACPP_BACKEND_ID),
|
||||
)
|
||||
{
|
||||
return Some(resolved.as_ref().clone());
|
||||
}
|
||||
|
|
@ -264,14 +269,6 @@ struct ExplicitModelPath {
|
|||
model_path: PathBuf,
|
||||
}
|
||||
|
||||
fn key_backend(id: &Option<String>) -> &str {
|
||||
match id.as_deref() {
|
||||
Some("mlx") => EREDU_BACKEND_ID,
|
||||
Some(id) => id,
|
||||
None => LLAMACPP_BACKEND_ID,
|
||||
}
|
||||
}
|
||||
|
||||
fn selected_backend(path: &Path, requested: Option<&str>) -> Result<&'static str> {
|
||||
let gguf = has_extension(path, "gguf");
|
||||
match requested {
|
||||
|
|
@ -280,7 +277,7 @@ fn selected_backend(path: &Path, requested: Option<&str>) -> Result<&'static str
|
|||
} else {
|
||||
EREDU_BACKEND_ID
|
||||
}),
|
||||
Some("eredu" | "mlx") => Ok(EREDU_BACKEND_ID),
|
||||
Some("eredu") => Ok(EREDU_BACKEND_ID),
|
||||
Some("llamacpp") if gguf => Ok(LLAMACPP_BACKEND_ID),
|
||||
Some("llamacpp") => {
|
||||
bail!("llama.cpp requires a GGUF checkpoint; use eredu for SafeTensors")
|
||||
|
|
@ -326,14 +323,14 @@ fn explicit_model_path(model_id: &str) -> Result<Option<ExplicitModelPath>> {
|
|||
return Ok(Some(ExplicitModelPath { model_path: path }));
|
||||
}
|
||||
|
||||
let mlx_directory = if path.is_dir() {
|
||||
let safetensors_directory = if path.is_dir() {
|
||||
Some(path.as_path())
|
||||
} else if path.is_file() && has_extension(&path, "safetensors") {
|
||||
path.parent()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(directory) = mlx_directory {
|
||||
if let Some(directory) = safetensors_directory {
|
||||
if is_safetensors_model_directory(directory)? {
|
||||
eredu::validate_model_directory(directory)
|
||||
.map_err(|error| anyhow::anyhow!(error.to_string()))?;
|
||||
|
|
@ -761,7 +758,7 @@ impl ProviderDescriptor for LocalInferenceProvider {
|
|||
ProviderMetadata::new(
|
||||
PROVIDER_NAME,
|
||||
"Local Inference",
|
||||
"Local inference using GGUF (llama.cpp) and MLX models",
|
||||
"Local inference using llama.cpp and Eredu",
|
||||
"",
|
||||
vec![],
|
||||
"https://github.com/utilityai/llama-cpp-rs",
|
||||
|
|
@ -1080,7 +1077,7 @@ mod tests {
|
|||
assert_eq!(selected_backend(gguf, None).unwrap(), "llamacpp");
|
||||
assert_eq!(selected_backend(safetensors, None).unwrap(), "eredu");
|
||||
assert_eq!(selected_backend(gguf, Some("eredu")).unwrap(), "eredu");
|
||||
assert_eq!(selected_backend(safetensors, Some("mlx")).unwrap(), "eredu");
|
||||
assert!(selected_backend(safetensors, Some("mlx")).is_err());
|
||||
assert!(selected_backend(safetensors, Some("llamacpp")).is_err());
|
||||
assert!(selected_backend(gguf, Some("unknown")).is_err());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ pub async fn download_model(
|
|||
) -> Result<LocalInferenceModelDownloadResponse> {
|
||||
let selection = explicit_model_selection(&req)?;
|
||||
let model_id = local_model_id_from_request(&req, selection.as_ref()).await?;
|
||||
if matches!(req.backend_id.as_deref(), Some("eredu" | "mlx"))
|
||||
if req.backend_id.as_deref() == Some("eredu")
|
||||
&& selection
|
||||
.as_ref()
|
||||
.is_some_and(|selection| selection.backend_id == "llamacpp")
|
||||
|
|
@ -251,10 +251,7 @@ fn settings_model_path(model_id: &str) -> Result<std::path::PathBuf> {
|
|||
}
|
||||
|
||||
pub fn get_model_settings(model_id: &str) -> Result<LocalInferenceModelSettingsReadResponse> {
|
||||
let mut settings = crate::config_resolver::model_settings(model_id)?;
|
||||
if settings.backend_id.as_deref() == Some("mlx") {
|
||||
settings.backend_id = Some("eredu".into());
|
||||
}
|
||||
let settings = crate::config_resolver::model_settings(model_id)?;
|
||||
let path = settings_model_path(model_id)?;
|
||||
let default_backend = crate::selected_backend(&path, None)?.to_string();
|
||||
let mut available_backends = Vec::new();
|
||||
|
|
@ -588,7 +585,7 @@ fn explicit_model_selection(
|
|||
) -> Result<Option<LocalModelSelection>> {
|
||||
let format_backend = match req.format.as_deref() {
|
||||
Some("gguf") => Some("llamacpp"),
|
||||
Some("safetensors" | "mlx-safetensors") => Some("eredu"),
|
||||
Some("safetensors") => Some("eredu"),
|
||||
Some(format) => anyhow::bail!("Unknown local checkpoint format '{format}'"),
|
||||
None => None,
|
||||
};
|
||||
|
|
@ -607,12 +604,12 @@ fn explicit_model_selection(
|
|||
let is_gguf = format_backend == Some("llamacpp") || parsed_variant_id.is_some();
|
||||
let variant_id = req.variant_id.clone().or(parsed_variant_id);
|
||||
match backend_id {
|
||||
"eredu" | "mlx" if is_gguf => Ok(Some(LocalModelSelection {
|
||||
"eredu" if is_gguf => Ok(Some(LocalModelSelection {
|
||||
repo_id,
|
||||
backend_id: "llamacpp".into(),
|
||||
variant_id: variant_id.map(|id| hf_models::canonicalize_quantization(&id)),
|
||||
})),
|
||||
"mlx" | "eredu" => Ok(Some(LocalModelSelection {
|
||||
"eredu" => Ok(Some(LocalModelSelection {
|
||||
repo_id,
|
||||
backend_id: backend_id.to_string(),
|
||||
variant_id,
|
||||
|
|
@ -636,7 +633,7 @@ async fn local_model_id_from_request(
|
|||
) -> Result<String> {
|
||||
if let Some(selection) = selection {
|
||||
return match selection.backend_id.as_str() {
|
||||
"mlx" | "eredu" => Ok(selection.repo_id.clone()),
|
||||
"eredu" => Ok(selection.repo_id.clone()),
|
||||
"llamacpp" => {
|
||||
let quantization = selection.variant_id.as_deref().ok_or_else(|| {
|
||||
anyhow!(
|
||||
|
|
@ -664,11 +661,11 @@ async fn local_model_id_from_request(
|
|||
let has_llamacpp = variants
|
||||
.iter()
|
||||
.any(|variant| variant.backend_id == "llamacpp");
|
||||
let mlx_variants: Vec<_> = variants
|
||||
let eredu_variants: Vec<_> = variants
|
||||
.iter()
|
||||
.filter(|variant| variant.backend_id == "eredu")
|
||||
.collect();
|
||||
if mlx_variants.len() == 1 && !has_llamacpp {
|
||||
if eredu_variants.len() == 1 && !has_llamacpp {
|
||||
Ok(req.spec.clone())
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
|
|
|
|||
|
|
@ -6,23 +6,23 @@
|
|||
|
||||
use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag};
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
use goose_provider_types::conversation::message::{Message, MessageContent};
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
use rmcp::model::{CallToolRequestParams, Tool};
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
use serde_json::json;
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
use std::borrow::Cow;
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
pub(crate) const SHELL_TOOL: &str = "developer__shell";
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
pub(crate) const CODE_EXECUTION_TOOL: &str = "code_execution__execute_typescript";
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
pub(crate) fn load_tiny_model_prompt() -> String {
|
||||
use std::env;
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ pub(crate) fn load_tiny_model_prompt() -> String {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
pub(crate) fn build_emulator_tool_description(tools: &[Tool], code_mode_enabled: bool) -> String {
|
||||
let mut tool_desc = String::new();
|
||||
|
||||
|
|
@ -466,7 +466,7 @@ impl StreamingEmulatorParser {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
pub(crate) fn message_for_emulator_action(
|
||||
action: &EmulatorAction,
|
||||
message_id: &str,
|
||||
|
|
@ -721,7 +721,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mlx")]
|
||||
#[cfg(feature = "eredu")]
|
||||
#[test]
|
||||
fn tool_description_uses_execute_typescript_fence() {
|
||||
let description = build_emulator_tool_description(&[], true);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ local-inference = ["dep:goose-local-inference"]
|
|||
local-inference-hf-hub = ["local-inference", "goose-local-inference/hf-hub"]
|
||||
cuda = ["local-inference", "goose-local-inference/cuda"]
|
||||
vulkan = ["local-inference", "goose-local-inference/vulkan"]
|
||||
mlx = ["local-inference", "goose-local-inference/mlx"]
|
||||
eredu = ["local-inference", "goose-local-inference/eredu"]
|
||||
rustls-tls = [
|
||||
"reqwest/rustls",
|
||||
"rmcp/reqwest",
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ aws-providers = [
|
|||
]
|
||||
cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "goose-providers/cuda"]
|
||||
vulkan = ["local-inference", "goose-providers/vulkan"]
|
||||
mlx = ["local-inference", "goose-providers/mlx"]
|
||||
eredu = ["local-inference", "goose-providers/eredu"]
|
||||
rustls-tls = [
|
||||
"dep:rustls",
|
||||
"dep:rcgen",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ activities:
|
|||
- Validate ACP thinking-effort discovery, forwarding, and provider switching
|
||||
- Validate GDK observability hook lifecycle events and payload opt-in
|
||||
- Validate capped and uncapped auto-compaction thresholds and Desktop editing
|
||||
- Validate local eredu inference, tool round trips, and interruption recovery
|
||||
- Test error boundaries including nested delegation prevention
|
||||
- Generate comprehensive test report
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ parameters:
|
|||
input_type: string
|
||||
requirement: optional
|
||||
default: "all"
|
||||
description: "Which test phases to run: all, basic, extensions, delegation, declared-vision, reasoning, zai-coding-plan, acp-effort, compaction, local-inference, advanced"
|
||||
description: "Which test phases to run: all, basic, extensions, delegation, declared-vision, reasoning, zai-coding-plan, acp-effort, compaction, advanced"
|
||||
|
||||
- key: test_depth
|
||||
input_type: string
|
||||
|
|
@ -59,41 +58,6 @@ instructions: |
|
|||
You are testing yourself - a running goose instance validating its own capabilities through meta-testing.
|
||||
This is true first-person integration testing where you use your own tools to test your own functionality.
|
||||
|
||||
## Local inference migration checks
|
||||
When test_phases includes local-inference, or includes all and this session uses
|
||||
the local provider, validate the currently selected cached model without downloading
|
||||
new weights. Record the model ID, format, selected backend, and agent-loop mode.
|
||||
Use a tool to write a small file, read it back in a later turn, and confirm that
|
||||
tool arguments and results survive the round trip. Request a response long enough
|
||||
to observe streaming, interrupt it, and verify a subsequent request still works.
|
||||
Check that reasoning is separated from the visible answer and that completed
|
||||
native or emulated tool calls execute only once. Record unavailable hardware,
|
||||
models, or interruption controls as skipped checks, not successful checks.
|
||||
Repeat this phase with a supported SafeTensors model using the automatic eredu
|
||||
default and a cached GGUF explicitly set to eredu, then restore the GGUF to its
|
||||
automatic llama.cpp default. Confirm switching engines does not download weights.
|
||||
With a cached eredu vision model, send image attachments of different sizes and
|
||||
check prompt usage against eredu's prepared-input model-position count. Confirm
|
||||
that text plus media consumes the configured context budget, including rejection
|
||||
of an oversized input, and that image_token_estimate does not change that count.
|
||||
Skip these image checks explicitly if no compatible cached vision model exists.
|
||||
Inspect the eredu inference response log for memory_forecast on ordinary and,
|
||||
when an already-cached compatible drafter is available, speculative requests.
|
||||
Confirm the forecast uses the actual input/output budget and preserves unknown
|
||||
bounds. A forecast error must be diagnostic only, allowing valid generation to
|
||||
continue. Record unavailable log access or draft models as skipped checks.
|
||||
Repeat a request with a cached mixed-precision GGUF and inspect the loaded
|
||||
forecasts before and after warm-up. Check each reported conversion-retention
|
||||
group's effective policy and that retained payload plus reservations stays within
|
||||
its bound (256 MiB by default); unavailable observations are not zero usage.
|
||||
Target and external drafter budgets are separate. Reset may preserve admitted
|
||||
conversions. Do not add their payload to residency a second time or treat either
|
||||
the conversion-retention budget or allocator-cache ceiling as a total-memory
|
||||
limit: unsupported projection layouts, arithmetic or row counts may still need
|
||||
temporary full-weight casts. Supported multi-row Metal prefill can now avoid them.
|
||||
Skip this comparison if no suitable checkpoint or forecast log is available.
|
||||
Run the same tool round trip with both legacy and GOOSE_STATE_MACHINE=1 sessions.
|
||||
|
||||
## Understanding First-Person Integration Testing
|
||||
This is a crucial distinction - as a running goose instance, you are testing yourself using your own capabilities.
|
||||
This is meta-testing in the truest sense: not unit tests or external test harnesses, but you using your tools
|
||||
|
|
|
|||
|
|
@ -472,8 +472,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
|||
save({ ...settings, [key]: value });
|
||||
};
|
||||
|
||||
const effectiveBackend =
|
||||
settings.backendId === 'mlx' ? 'eredu' : settings.backendId || defaultBackend;
|
||||
const effectiveBackend = settings.backendId || defaultBackend;
|
||||
const usesEredu = effectiveBackend === 'eredu';
|
||||
|
||||
const samplingType: SamplingType = settings.sampling?.type ?? 'Temperature';
|
||||
|
|
@ -571,7 +570,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
|||
<SelectField<string>
|
||||
label={intl.formatMessage(i18n.inferenceBackend)}
|
||||
description={intl.formatMessage(i18n.inferenceBackendDescription)}
|
||||
value={settings.backendId === 'mlx' ? 'eredu' : settings.backendId || 'auto'}
|
||||
value={settings.backendId || 'auto'}
|
||||
options={[
|
||||
{ value: 'auto', label: intl.formatMessage(i18n.automaticBackend) },
|
||||
...Array.from(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue