mirror of
https://github.com/katanemo/plano.git
synced 2026-05-10 16:22:42 +02:00
support base_url path for model providers (#608)
* adding support for base_url * updated docs * fixed tests for config generator * making fixes based on PR comments --------- Co-authored-by: Salman Paracha <salmanparacha@MacBook-Pro-288.local>
This commit is contained in:
parent
5108013df4
commit
cdfcfb9169
7 changed files with 459 additions and 46 deletions
|
|
@ -77,70 +77,85 @@ impl SupportedAPIs {
|
|||
request_path: &str,
|
||||
model_id: &str,
|
||||
is_streaming: bool,
|
||||
base_url_path_prefix: Option<&str>,
|
||||
) -> String {
|
||||
let default_endpoint = "/v1/chat/completions".to_string();
|
||||
// Helper function to build endpoint with optional prefix override
|
||||
let build_endpoint = |provider_prefix: &str, suffix: &str| -> String {
|
||||
let prefix = base_url_path_prefix
|
||||
.map(|p| p.trim_matches('/'))
|
||||
.filter(|p| !p.is_empty())
|
||||
.unwrap_or(provider_prefix.trim_matches('/'));
|
||||
|
||||
let suffix = suffix.trim_start_matches('/');
|
||||
if prefix.is_empty() {
|
||||
format!("/{}", suffix)
|
||||
} else {
|
||||
format!("/{}/{}", prefix, suffix)
|
||||
}
|
||||
};
|
||||
|
||||
match self {
|
||||
SupportedAPIs::AnthropicMessagesAPI(AnthropicApi::Messages) => match provider_id {
|
||||
ProviderId::Anthropic => "/v1/messages".to_string(),
|
||||
ProviderId::Anthropic => build_endpoint("/v1", "/messages"),
|
||||
ProviderId::AmazonBedrock => {
|
||||
if request_path.starts_with("/v1/") && !is_streaming {
|
||||
format!("/model/{}/converse", model_id)
|
||||
build_endpoint("", &format!("/model/{}/converse", model_id))
|
||||
} else if request_path.starts_with("/v1/") && is_streaming {
|
||||
format!("/model/{}/converse-stream", model_id)
|
||||
build_endpoint("", &format!("/model/{}/converse-stream", model_id))
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
_ => default_endpoint,
|
||||
_ => build_endpoint("/v1", "/chat/completions"),
|
||||
},
|
||||
_ => match provider_id {
|
||||
ProviderId::Groq => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
format!("/openai{}", request_path)
|
||||
build_endpoint("/openai", request_path)
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
ProviderId::Zhipu => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
"/api/paas/v4/chat/completions".to_string()
|
||||
build_endpoint("/api/paas/v4", "/chat/completions")
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
ProviderId::Qwen => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
"/compatible-mode/v1/chat/completions".to_string()
|
||||
build_endpoint("/compatible-mode/v1", "/chat/completions")
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
ProviderId::AzureOpenAI => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
format!("/openai/deployments/{}/chat/completions?api-version=2025-01-01-preview", model_id)
|
||||
build_endpoint("/openai/deployments", &format!("/{}/chat/completions?api-version=2025-01-01-preview", model_id))
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
ProviderId::Gemini => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
"/v1beta/openai/chat/completions".to_string()
|
||||
build_endpoint("/v1beta/openai", "/chat/completions")
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
ProviderId::AmazonBedrock => {
|
||||
if request_path.starts_with("/v1/") {
|
||||
if !is_streaming {
|
||||
format!("/model/{}/converse", model_id)
|
||||
build_endpoint("", &format!("/model/{}/converse", model_id))
|
||||
} else {
|
||||
format!("/model/{}/converse-stream", model_id)
|
||||
build_endpoint("", &format!("/model/{}/converse-stream", model_id))
|
||||
}
|
||||
} else {
|
||||
default_endpoint
|
||||
build_endpoint("/v1", "/chat/completions")
|
||||
}
|
||||
}
|
||||
_ => default_endpoint,
|
||||
_ => build_endpoint("/v1", "/chat/completions"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -245,4 +260,327 @@ mod tests {
|
|||
OpenAIApi::all_variants().len() + AnthropicApi::all_variants().len()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_endpoint_without_base_url_prefix() {
|
||||
let api = SupportedAPIs::OpenAIChatCompletions(OpenAIApi::ChatCompletions);
|
||||
|
||||
// Test default OpenAI provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::OpenAI,
|
||||
"/v1/chat/completions",
|
||||
"gpt-4",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/v1/chat/completions"
|
||||
);
|
||||
|
||||
// Test Groq provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Groq,
|
||||
"/v1/chat/completions",
|
||||
"llama2",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/openai/v1/chat/completions"
|
||||
);
|
||||
|
||||
// Test Zhipu provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/api/paas/v4/chat/completions"
|
||||
);
|
||||
|
||||
// Test Qwen provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Qwen,
|
||||
"/v1/chat/completions",
|
||||
"qwen-turbo",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/compatible-mode/v1/chat/completions"
|
||||
);
|
||||
|
||||
// Test Azure OpenAI provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AzureOpenAI,
|
||||
"/v1/chat/completions",
|
||||
"gpt-4",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/openai/deployments/gpt-4/chat/completions?api-version=2025-01-01-preview"
|
||||
);
|
||||
|
||||
// Test Gemini provider
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Gemini,
|
||||
"/v1/chat/completions",
|
||||
"gemini-pro",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/v1beta/openai/chat/completions"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_endpoint_with_base_url_prefix() {
|
||||
let api = SupportedAPIs::OpenAIChatCompletions(OpenAIApi::ChatCompletions);
|
||||
|
||||
// Test Zhipu with custom base_url_path_prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
Some("/api/coding/paas/v4")
|
||||
),
|
||||
"/api/coding/paas/v4/chat/completions"
|
||||
);
|
||||
|
||||
// Test with prefix without leading slash
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
Some("api/coding/paas/v4")
|
||||
),
|
||||
"/api/coding/paas/v4/chat/completions"
|
||||
);
|
||||
|
||||
// Test with prefix with trailing slash
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
Some("/api/coding/paas/v4/")
|
||||
),
|
||||
"/api/coding/paas/v4/chat/completions"
|
||||
);
|
||||
|
||||
// Test OpenAI with custom prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::OpenAI,
|
||||
"/v1/chat/completions",
|
||||
"gpt-4",
|
||||
false,
|
||||
Some("/custom/api/v2")
|
||||
),
|
||||
"/custom/api/v2/chat/completions"
|
||||
);
|
||||
|
||||
// Test Groq with custom prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Groq,
|
||||
"/v1/chat/completions",
|
||||
"llama2",
|
||||
false,
|
||||
Some("/api/v2")
|
||||
),
|
||||
"/api/v2/v1/chat/completions"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_endpoint_with_empty_base_url_prefix() {
|
||||
let api = SupportedAPIs::OpenAIChatCompletions(OpenAIApi::ChatCompletions);
|
||||
|
||||
// Test with just slashes - trims to empty, uses provider default
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
Some("/")
|
||||
),
|
||||
"/api/paas/v4/chat/completions"
|
||||
);
|
||||
|
||||
// Test with None - uses provider default
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/v1/chat/completions",
|
||||
"chatglm",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/api/paas/v4/chat/completions"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_amazon_bedrock_endpoints() {
|
||||
let api = SupportedAPIs::AnthropicMessagesAPI(AnthropicApi::Messages);
|
||||
|
||||
// Test Bedrock non-streaming without prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AmazonBedrock,
|
||||
"/v1/messages",
|
||||
"us.amazon.nova-pro-v1:0",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/model/us.amazon.nova-pro-v1:0/converse"
|
||||
);
|
||||
|
||||
// Test Bedrock streaming without prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AmazonBedrock,
|
||||
"/v1/messages",
|
||||
"us.amazon.nova-pro-v1:0",
|
||||
true,
|
||||
None
|
||||
),
|
||||
"/model/us.amazon.nova-pro-v1:0/converse-stream"
|
||||
);
|
||||
|
||||
// Test Bedrock non-streaming with prefix (prefix shouldn't affect bedrock)
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AmazonBedrock,
|
||||
"/v1/messages",
|
||||
"us.amazon.nova-pro-v1:0",
|
||||
false,
|
||||
Some("/custom/path")
|
||||
),
|
||||
"/custom/path/model/us.amazon.nova-pro-v1:0/converse"
|
||||
);
|
||||
|
||||
// Test Bedrock streaming with prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AmazonBedrock,
|
||||
"/v1/messages",
|
||||
"us.amazon.nova-pro-v1:0",
|
||||
true,
|
||||
Some("/custom/path")
|
||||
),
|
||||
"/custom/path/model/us.amazon.nova-pro-v1:0/converse-stream"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anthropic_messages_endpoint() {
|
||||
let api = SupportedAPIs::AnthropicMessagesAPI(AnthropicApi::Messages);
|
||||
|
||||
// Test Anthropic without prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Anthropic,
|
||||
"/v1/messages",
|
||||
"claude-3-opus",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/v1/messages"
|
||||
);
|
||||
|
||||
// Test Anthropic with prefix
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Anthropic,
|
||||
"/v1/messages",
|
||||
"claude-3-opus",
|
||||
false,
|
||||
Some("/api/v2")
|
||||
),
|
||||
"/api/v2/messages"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_v1_request_paths() {
|
||||
let api = SupportedAPIs::OpenAIChatCompletions(OpenAIApi::ChatCompletions);
|
||||
|
||||
// Test Groq with non-v1 path (should use default)
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Groq,
|
||||
"/custom/path",
|
||||
"llama2",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/v1/chat/completions"
|
||||
);
|
||||
|
||||
// Test Zhipu with non-v1 path
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/custom/path",
|
||||
"chatglm",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/v1/chat/completions"
|
||||
);
|
||||
|
||||
// Test with prefix on non-v1 path
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::Zhipu,
|
||||
"/custom/path",
|
||||
"chatglm",
|
||||
false,
|
||||
Some("/api/v2")
|
||||
),
|
||||
"/api/v2/chat/completions"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_azure_openai_with_query_params() {
|
||||
let api = SupportedAPIs::OpenAIChatCompletions(OpenAIApi::ChatCompletions);
|
||||
|
||||
// Test Azure without prefix - should include query params
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AzureOpenAI,
|
||||
"/v1/chat/completions",
|
||||
"gpt-4-deployment",
|
||||
false,
|
||||
None
|
||||
),
|
||||
"/openai/deployments/gpt-4-deployment/chat/completions?api-version=2025-01-01-preview"
|
||||
);
|
||||
|
||||
// Test Azure with prefix - prefix should replace /openai/deployments
|
||||
assert_eq!(
|
||||
api.target_endpoint_for_provider(
|
||||
&ProviderId::AzureOpenAI,
|
||||
"/v1/chat/completions",
|
||||
"gpt-4-deployment",
|
||||
false,
|
||||
Some("/custom/azure/path")
|
||||
),
|
||||
"/custom/azure/path/gpt-4-deployment/chat/completions?api-version=2025-01-01-preview"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue