Integrate Bedrock model catalog metadata
This commit is contained in:
@@ -413,10 +413,14 @@ impl RequestParams {
|
||||
// server-side, drop the override; otherwise clamp it to the model's
|
||||
// current `[min, max]` range. This closes the window between an
|
||||
// in-flight model metadata refresh and the next request.
|
||||
let llm_preferences = LLMPreferences::as_ref(app);
|
||||
let selected_model = llm_preferences
|
||||
.get_llm_info(&request_input.model_id)
|
||||
.unwrap_or_else(|| llm_preferences.get_active_base_model(app, terminal_view_id));
|
||||
let context_window_limit = AIExecutionProfilesModel::as_ref(app)
|
||||
.active_profile(terminal_view_id, app)
|
||||
.data()
|
||||
.context_window_limit_for_request(app);
|
||||
.context_window_limit_for_model_request(selected_model, app);
|
||||
|
||||
Self {
|
||||
terminal_view_id,
|
||||
|
||||
@@ -8,6 +8,7 @@ use aws_config::BehaviorVersion;
|
||||
use aws_sdk_bedrock::Client;
|
||||
use aws_sdk_bedrockruntime::config::Region;
|
||||
use futures::{stream, StreamExt};
|
||||
use galaxy_bedrock_model_catalog::model_metadata;
|
||||
|
||||
use super::client::{BedrockClientConfig, BedrockError};
|
||||
use crate::settings::ai::BedrockModelConfig;
|
||||
@@ -71,20 +72,23 @@ pub async fn discover_available_models(
|
||||
return None;
|
||||
}
|
||||
|
||||
let display_name = summary
|
||||
.model_name()
|
||||
.map(str::to_owned)
|
||||
.unwrap_or_else(|| prettify_model_id(model_id));
|
||||
let metadata = model_metadata(model_id);
|
||||
let display_name = summary.model_name().map(str::to_owned).unwrap_or_else(|| {
|
||||
metadata
|
||||
.map(|metadata| metadata.model_name.clone())
|
||||
.unwrap_or_else(|| prettify_model_id(model_id))
|
||||
});
|
||||
let vision_supported = summary
|
||||
.input_modalities()
|
||||
.iter()
|
||||
.any(|modality| modality.as_str() == "IMAGE");
|
||||
.any(|modality| modality.as_str() == "IMAGE")
|
||||
|| metadata.is_some_and(|metadata| metadata.supports_vision_input());
|
||||
|
||||
Some(BedrockModelConfig {
|
||||
model_id: model_id.to_owned(),
|
||||
display_name,
|
||||
vision_supported,
|
||||
use_rig: false,
|
||||
use_rig: true,
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2050,7 +2050,7 @@ impl AgentInputFooter {
|
||||
let profile_context = AIExecutionProfilesModel::as_ref(ctx)
|
||||
.active_profile(Some(self.terminal_view_id), ctx)
|
||||
.data()
|
||||
.context_window_display_value(ctx);
|
||||
.context_window_display_value_for_model(active_model, ctx);
|
||||
let model_max_context = active_model
|
||||
.context_window
|
||||
.default_max
|
||||
|
||||
@@ -117,7 +117,17 @@ pub trait AIExecutionProfileAppExt {
|
||||
fn configurable_context_window(&self, app: &AppContext) -> Option<LLMContextWindow>;
|
||||
|
||||
fn context_window_display_value(&self, app: &AppContext) -> Option<u32>;
|
||||
fn context_window_display_value_for_model(
|
||||
&self,
|
||||
model: &LLMInfo,
|
||||
app: &AppContext,
|
||||
) -> Option<u32>;
|
||||
fn context_window_limit_for_request(&self, app: &AppContext) -> Option<u32>;
|
||||
fn context_window_limit_for_model_request(
|
||||
&self,
|
||||
model: &LLMInfo,
|
||||
app: &AppContext,
|
||||
) -> Option<u32>;
|
||||
fn should_show_long_context_pricing_warning(
|
||||
&self,
|
||||
context_window_limit: Option<u32>,
|
||||
@@ -139,20 +149,52 @@ impl AIExecutionProfileAppExt for AIExecutionProfile {
|
||||
}
|
||||
|
||||
fn context_window_display_value(&self, app: &AppContext) -> Option<u32> {
|
||||
let cw = self.configurable_context_window(app)?;
|
||||
Some(self.context_window_limit.unwrap_or(cw.default_max))
|
||||
self.context_window_display_value_for_model(effective_base_model(self, app), app)
|
||||
}
|
||||
fn context_window_limit_for_request(&self, app: &AppContext) -> Option<u32> {
|
||||
let llm = effective_base_model(self, app);
|
||||
|
||||
fn context_window_display_value_for_model(
|
||||
&self,
|
||||
model: &LLMInfo,
|
||||
app: &AppContext,
|
||||
) -> Option<u32> {
|
||||
if !has_configurable_context_window(
|
||||
llm,
|
||||
model,
|
||||
FeatureFlag::GPTConfigurableContextWindow.is_enabled(),
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let selected_limit = if effective_base_model(self, app).id == model.id {
|
||||
self.context_window_limit
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(
|
||||
selected_limit
|
||||
.unwrap_or(model.context_window.default_max)
|
||||
.clamp(model.context_window.min, model.context_window.max),
|
||||
)
|
||||
}
|
||||
|
||||
fn context_window_limit_for_request(&self, app: &AppContext) -> Option<u32> {
|
||||
self.context_window_limit_for_model_request(effective_base_model(self, app), app)
|
||||
}
|
||||
|
||||
fn context_window_limit_for_model_request(
|
||||
&self,
|
||||
model: &LLMInfo,
|
||||
app: &AppContext,
|
||||
) -> Option<u32> {
|
||||
if !has_configurable_context_window(
|
||||
model,
|
||||
FeatureFlag::GPTConfigurableContextWindow.is_enabled(),
|
||||
) || effective_base_model(self, app).id != model.id
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
self.context_window_limit
|
||||
.map(|limit| limit.clamp(llm.context_window.min, llm.context_window.max))
|
||||
.map(|limit| limit.clamp(model.context_window.min, model.context_window.max))
|
||||
}
|
||||
|
||||
fn should_show_long_context_pricing_warning(
|
||||
|
||||
+23
-2
@@ -11,6 +11,8 @@ use galaxy_agent_rig::{
|
||||
discover_anthropic_models, discover_gemini_models, validate_vertex_ai_credentials,
|
||||
vertex_ai_model_catalog, RigModelInfo,
|
||||
};
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use galaxy_bedrock_model_catalog::model_metadata;
|
||||
use galaxy_core::features::FeatureFlag;
|
||||
use galaxy_core::ui::icons::Icon;
|
||||
use galaxy_core::user_preferences::GetUserPreferences;
|
||||
@@ -873,11 +875,29 @@ impl LLMPreferences {
|
||||
|
||||
let effective = effective;
|
||||
for model in effective {
|
||||
let metadata = model_metadata(&model.model_id);
|
||||
if metadata.is_some_and(|metadata| metadata.supports_agent_runtime() == Some(false)) {
|
||||
log::debug!(
|
||||
"[bedrock] Excluding {} from Agent Mode because its catalog metadata marks it as incompatible with streaming Converse",
|
||||
model.model_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let model_id = if cross_region && !region.is_empty() {
|
||||
super::bedrock::models::apply_cross_region_prefix(&model.model_id, ®ion)
|
||||
} else {
|
||||
model.model_id.clone()
|
||||
};
|
||||
let context_window = metadata
|
||||
.and_then(|metadata| metadata.context_window_tokens)
|
||||
.map(|tokens| LLMContextWindow {
|
||||
is_configurable: false,
|
||||
min: tokens,
|
||||
max: tokens,
|
||||
default_max: tokens,
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let llm_info = LLMInfo {
|
||||
id: LLMId::from(model_id.as_str()),
|
||||
@@ -890,7 +910,8 @@ impl LLMPreferences {
|
||||
},
|
||||
description: Some("AWS Bedrock".to_string()),
|
||||
disable_reason: None,
|
||||
vision_supported: model.vision_supported,
|
||||
vision_supported: model.vision_supported
|
||||
|| metadata.is_some_and(|metadata| metadata.supports_vision_input()),
|
||||
spec: None,
|
||||
provider: LLMProvider::Bedrock,
|
||||
host_configs: HashMap::from([(
|
||||
@@ -901,7 +922,7 @@ impl LLMPreferences {
|
||||
},
|
||||
)]),
|
||||
discount_percentage: None,
|
||||
context_window: LLMContextWindow::default(),
|
||||
context_window,
|
||||
};
|
||||
self.models_by_feature
|
||||
.agent_mode
|
||||
|
||||
+39
-10
@@ -8,6 +8,7 @@ use galaxy_agent_rig::{
|
||||
GeminiRuntimeConfig, OpenAICompatibleRuntime, OpenAICompatibleRuntimeConfig, VertexAiRuntime,
|
||||
VertexAiRuntimeConfig,
|
||||
};
|
||||
use galaxy_bedrock_model_catalog::model_metadata;
|
||||
use uuid::Uuid;
|
||||
use warp_multi_agent_api::ToolType;
|
||||
|
||||
@@ -79,7 +80,11 @@ pub(crate) async fn prepare_provider_run(
|
||||
let (supported_tools, supported_cli_agent_tools) =
|
||||
crate::ai::agent::api::prepare_direct_provider_params(&mut params);
|
||||
let skill_path_origin = params.session_context.skill_path_origin();
|
||||
let max_context_tokens = params.context_window_limit;
|
||||
let max_context_tokens = provider_context_window_tokens(
|
||||
&base_provider_config,
|
||||
params.model.as_str(),
|
||||
params.context_window_limit,
|
||||
);
|
||||
let mut cli_params = params.clone();
|
||||
let cli_model_is_placeholder = params.cli_agent_model.as_str().trim().is_empty()
|
||||
|| params
|
||||
@@ -186,14 +191,17 @@ async fn prepare_provider_profile(
|
||||
),
|
||||
None => prepare_rig_turn(config, params, supported_tools, supported_cli_agent_tools),
|
||||
},
|
||||
crate::ai::provider::ProviderConfig::Bedrock(_) => prepare_bedrock_rig_turn_for_mode(
|
||||
model,
|
||||
Some(64_000),
|
||||
params,
|
||||
supported_tools,
|
||||
supported_cli_agent_tools,
|
||||
mode,
|
||||
),
|
||||
crate::ai::provider::ProviderConfig::Bedrock(_) => {
|
||||
let max_output_tokens = Some(bedrock_max_output_tokens(&model));
|
||||
prepare_bedrock_rig_turn_for_mode(
|
||||
model,
|
||||
max_output_tokens,
|
||||
params,
|
||||
supported_tools,
|
||||
supported_cli_agent_tools,
|
||||
mode,
|
||||
)
|
||||
}
|
||||
crate::ai::provider::ProviderConfig::None => {
|
||||
anyhow::bail!(
|
||||
"No AI runtime configured. Enable an agent runtime or model provider in settings."
|
||||
@@ -250,7 +258,7 @@ pub(crate) async fn provider_runtime_for_request(
|
||||
})),
|
||||
},
|
||||
crate::ai::provider::ProviderConfig::Bedrock(config) => {
|
||||
let max_output_tokens = Some(64_000);
|
||||
let max_output_tokens = Some(bedrock_max_output_tokens(&model));
|
||||
let cross_region_inference = config.cross_region_inference;
|
||||
let caching_config =
|
||||
CachingConfig::from_external_config(&ExternalBedrockConfig::load());
|
||||
@@ -275,6 +283,27 @@ pub(crate) async fn provider_runtime_for_request(
|
||||
Ok(runtime)
|
||||
}
|
||||
|
||||
fn bedrock_max_output_tokens(model: &str) -> u64 {
|
||||
model_metadata(model)
|
||||
.and_then(|metadata| metadata.max_output_tokens)
|
||||
.map(u64::from)
|
||||
.unwrap_or(64_000)
|
||||
}
|
||||
|
||||
fn provider_context_window_tokens(
|
||||
provider_config: &crate::ai::provider::ProviderConfig,
|
||||
model: &str,
|
||||
configured_limit: Option<u32>,
|
||||
) -> Option<u32> {
|
||||
configured_limit.or_else(|| match provider_config {
|
||||
crate::ai::provider::ProviderConfig::Bedrock(_) => {
|
||||
model_metadata(model).and_then(|metadata| metadata.context_window_tokens)
|
||||
}
|
||||
crate::ai::provider::ProviderConfig::OpenAI(_)
|
||||
| crate::ai::provider::ProviderConfig::None => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "rig_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
Reference in New Issue
Block a user