mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
fix(gateway): normalize Gemini Vertex embedding transport
This commit is contained in:
@@ -2304,7 +2304,7 @@ async fn provider_query_execute_standard_test_candidate(
|
||||
}
|
||||
"openai:embedding" | "gemini:embedding" | "jina:embedding" | "doubao:embedding"
|
||||
| "openai:rerank" | "jina:rerank" => {
|
||||
let Some(provider_request_body) =
|
||||
let Some(mut provider_request_body) =
|
||||
crate::ai_serving::build_standard_request_body_with_model_directives_and_request_headers(
|
||||
&request_body,
|
||||
client_api_format,
|
||||
@@ -2324,6 +2324,18 @@ async fn provider_query_execute_standard_test_candidate(
|
||||
format!("Provider request body could not be built for {provider_api_format}"),
|
||||
));
|
||||
};
|
||||
if let Err(err) = crate::provider_transport::apply_transport_request_body_semantics(
|
||||
&mut provider_request_body,
|
||||
&transport,
|
||||
normalized_provider_api_format.as_str(),
|
||||
) {
|
||||
return Ok(provider_query_skipped_execution_outcome(
|
||||
provider_request_body,
|
||||
format!(
|
||||
"Provider request body is not compatible with transport semantics: {err}"
|
||||
),
|
||||
));
|
||||
}
|
||||
provider_request_body
|
||||
}
|
||||
_ => {
|
||||
@@ -2404,7 +2416,7 @@ async fn provider_query_execute_standard_test_candidate(
|
||||
*synthetic_request.headers_mut() = incoming_request_headers;
|
||||
let (parts, _) = synthetic_request.into_parts();
|
||||
|
||||
let request_url = crate::provider_transport::build_transport_request_url(
|
||||
let request_url = crate::provider_transport::build_transport_request_url_for_request_body(
|
||||
&transport,
|
||||
crate::provider_transport::TransportRequestUrlParams {
|
||||
provider_api_format,
|
||||
@@ -2413,6 +2425,7 @@ async fn provider_query_execute_standard_test_candidate(
|
||||
request_query: parts.uri.query(),
|
||||
kiro_api_region: None,
|
||||
},
|
||||
Some(&provider_request_body),
|
||||
);
|
||||
let Some(request_url) = request_url else {
|
||||
return Ok(provider_query_skipped_execution_outcome(
|
||||
|
||||
@@ -62,10 +62,10 @@ pub(super) fn provider_query_standard_test_unsupported_reason(
|
||||
api_format,
|
||||
)
|
||||
}
|
||||
"gemini:generate_content"
|
||||
if crate::provider_transport::is_vertex_api_key_transport_context(transport) =>
|
||||
"gemini:generate_content" | "gemini:embedding"
|
||||
if crate::provider_transport::is_vertex_transport_context(transport) =>
|
||||
{
|
||||
aether_provider_transport::vertex::local_vertex_api_key_gemini_transport_unsupported_reason_with_network(
|
||||
aether_provider_transport::vertex::local_vertex_gemini_transport_unsupported_reason_with_network(
|
||||
transport,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,29 @@ pub(super) fn provider_query_test_attempt_payload(
|
||||
candidate: &ProviderQueryTestCandidate,
|
||||
execution: &ProviderQueryExecutionOutcome,
|
||||
) -> Value {
|
||||
let endpoint_route = provider_query_endpoint_route_payload(candidate, execution);
|
||||
let endpoint_product = endpoint_route
|
||||
.get("product")
|
||||
.cloned()
|
||||
.unwrap_or(Value::Null);
|
||||
let endpoint_variant = endpoint_route
|
||||
.get("variant")
|
||||
.cloned()
|
||||
.unwrap_or(Value::Null);
|
||||
let endpoint_action = endpoint_route.get("action").cloned().unwrap_or(Value::Null);
|
||||
let endpoint_batch_strategy = endpoint_route
|
||||
.get("batch_strategy")
|
||||
.cloned()
|
||||
.unwrap_or(Value::Null);
|
||||
json!({
|
||||
"candidate_index": candidate_index,
|
||||
"retry_index": 0,
|
||||
"endpoint_api_format": candidate.endpoint.api_format,
|
||||
"endpoint_base_url": candidate.endpoint.base_url,
|
||||
"endpoint_product": endpoint_product,
|
||||
"endpoint_variant": endpoint_variant,
|
||||
"endpoint_action": endpoint_action,
|
||||
"endpoint_batch_strategy": endpoint_batch_strategy,
|
||||
"key_name": provider_query_key_display_name(&candidate.key),
|
||||
"key_id": candidate.key.id,
|
||||
"auth_type": candidate.key.auth_type,
|
||||
@@ -29,6 +47,129 @@ pub(super) fn provider_query_test_attempt_payload(
|
||||
})
|
||||
}
|
||||
|
||||
fn provider_query_endpoint_route_payload(
|
||||
candidate: &ProviderQueryTestCandidate,
|
||||
execution: &ProviderQueryExecutionOutcome,
|
||||
) -> Value {
|
||||
let api_format = aether_ai_formats::normalize_api_format_alias(&candidate.endpoint.api_format);
|
||||
let request_url = execution.request_url.to_ascii_lowercase();
|
||||
let base_url = candidate.endpoint.base_url.to_ascii_lowercase();
|
||||
let is_vertex = request_url.contains("aiplatform.googleapis.com")
|
||||
|| base_url.contains("aiplatform.googleapis.com");
|
||||
let is_gemini_api = request_url.contains("generativelanguage.googleapis.com")
|
||||
|| base_url.contains("generativelanguage.googleapis.com");
|
||||
let is_openai_compat =
|
||||
request_url.contains("/endpoints/openapi") || request_url.contains("/openai/");
|
||||
let is_batch = execution
|
||||
.request_body
|
||||
.get("requests")
|
||||
.and_then(Value::as_array)
|
||||
.is_some_and(|items| !items.is_empty());
|
||||
let vertex_instance_count = execution
|
||||
.request_body
|
||||
.get("instances")
|
||||
.and_then(Value::as_array)
|
||||
.map(Vec::len)
|
||||
.unwrap_or(0);
|
||||
|
||||
let (product, variant, action, batch_strategy) = match api_format.as_str() {
|
||||
"gemini:embedding" if is_vertex => (
|
||||
"Vertex AI",
|
||||
"vertex_native",
|
||||
"predict",
|
||||
if vertex_instance_count > 1 {
|
||||
"predict_instances"
|
||||
} else {
|
||||
"single_instance"
|
||||
},
|
||||
),
|
||||
"gemini:embedding" if is_gemini_api => (
|
||||
"Gemini API",
|
||||
"gemini_native",
|
||||
if is_batch {
|
||||
"batchEmbedContents"
|
||||
} else {
|
||||
"embedContent"
|
||||
},
|
||||
if is_batch {
|
||||
"native_batch"
|
||||
} else {
|
||||
"single_native"
|
||||
},
|
||||
),
|
||||
"gemini:embedding" => (
|
||||
"Gemini native",
|
||||
"gemini_native",
|
||||
if is_batch {
|
||||
"batchEmbedContents"
|
||||
} else {
|
||||
"embedContent"
|
||||
},
|
||||
if is_batch {
|
||||
"native_batch"
|
||||
} else {
|
||||
"single_native"
|
||||
},
|
||||
),
|
||||
"gemini:generate_content" if is_vertex => {
|
||||
("Vertex AI", "vertex_native", "generateContent", "")
|
||||
}
|
||||
"gemini:generate_content" if is_gemini_api => {
|
||||
("Gemini API", "gemini_native", "generateContent", "")
|
||||
}
|
||||
"gemini:generate_content" => ("Gemini native", "gemini_native", "generateContent", ""),
|
||||
"openai:embedding" if is_vertex && is_openai_compat => (
|
||||
"Vertex AI OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"embeddings",
|
||||
"openai_batch",
|
||||
),
|
||||
"openai:embedding" if is_gemini_api && is_openai_compat => (
|
||||
"Gemini API OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"embeddings",
|
||||
"openai_batch",
|
||||
),
|
||||
"openai:embedding" => (
|
||||
"OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"embeddings",
|
||||
"openai_batch",
|
||||
),
|
||||
"openai:chat" if is_vertex && is_openai_compat => (
|
||||
"Vertex AI OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"chat/completions",
|
||||
"",
|
||||
),
|
||||
"openai:chat" if is_gemini_api && is_openai_compat => (
|
||||
"Gemini API OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"chat/completions",
|
||||
"",
|
||||
),
|
||||
"openai:chat" => (
|
||||
"OpenAI-compatible",
|
||||
"openai_compatible",
|
||||
"chat/completions",
|
||||
"",
|
||||
),
|
||||
_ => (
|
||||
"Provider endpoint",
|
||||
"provider_native",
|
||||
"provider_request",
|
||||
"",
|
||||
),
|
||||
};
|
||||
|
||||
json!({
|
||||
"product": product,
|
||||
"variant": variant,
|
||||
"action": action,
|
||||
"batch_strategy": batch_strategy,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn provider_query_candidate_summary_payload(
|
||||
total_candidates: usize,
|
||||
total_attempts: usize,
|
||||
|
||||
Reference in New Issue
Block a user