Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* `models_ollama()` was fixed to correctly query model capabilities from remote Ollama servers (#746).

* `chat_claude()` is no longer deprecated and is an alias for `chat_anthropic()`, reflecting Anthropic's recent rebranding of developer tools under the Claude name (#758).
* The `virtual_key` argument in `chat_portkey()` was deprecated as it is no longer supported by PortkeyAI (#786).

# ellmer 0.3.2

Expand Down
54 changes: 29 additions & 25 deletions R/provider-portkey.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,53 @@
#' @family chatbots
#' @param api_key `r api_key_param("PORTKEY_API_KEY")`
#' @param model `r param_model("gpt-4o", "openai")`
#' @param virtual_key A virtual identifier storing LLM provider's API key. See
#' [documentation](https://portkey.ai/docs/product/ai-gateway/virtual-keys).
#' Can be read from the `PORTKEY_VIRTUAL_KEY` environment variable.
#' @param virtual_key `r lifecycle::badge("deprecated")` No longer supported by Portkey.
#' Read more: https://portkey.ai/docs/support/upgrade-to-model-catalog
#' @param model_provider Optional, model provider from Portkey Model Catalog.
#' @export
#' @inheritParams chat_openai
#' @inherit chat_openai return
#' @examples
#' \dontrun{
#' chat <- chat_portkey(virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"))
#' chat <- chat_portkey()
#' chat$chat("Tell me three jokes about statisticians")
#' }
chat_portkey <- function(
system_prompt = NULL,
base_url = "https://api.portkey.ai/v1",
api_key = portkey_key(),
virtual_key = portkey_virtual_key(),
virtual_key = deprecated(),
model = NULL,
model_provider = "",
params = NULL,
api_args = list(),
echo = NULL,
api_headers = character()
) {
model <- set_default(model, "gpt-4o")
echo <- check_echo(echo)

if (lifecycle::is_present(virtual_key)) {
lifecycle::deprecate_soft(
when = "0.4.0",
what = "chat_portkey(virtual_key=)",
with = "chat_portkey(model_provider=)",
)
} else {
virtual_key <- NULL
}
if (model_provider != "") {
model_provider <- paste0("@", model_provider)
}
params <- params %||% params()
provider <- ProviderPortkeyAI(
name = "PortkeyAI",
base_url = base_url,
model = model,
virtual_key = virtual_key,
model_provider = model_provider,
params = params,
extra_args = api_args,
api_key = api_key,
virtual_key = virtual_key,
extra_headers = api_headers
)
Chat$new(provider = provider, system_prompt = system_prompt, echo = echo)
Expand All @@ -67,7 +80,8 @@ ProviderPortkeyAI <- new_class(
"ProviderPortkeyAI",
parent = ProviderOpenAI,
properties = list(
virtual_key = prop_string(allow_null = TRUE)
virtual_key = prop_string(allow_null = TRUE),
model_provider = prop_string(allow_null = TRUE)
)
)

Expand All @@ -79,21 +93,13 @@ portkey_key <- function() {
key_get("PORTKEY_API_KEY")
}

portkey_virtual_key <- function() {
val <- Sys.getenv("PORTKEY_VIRTUAL_KEY")
if (!identical(val, "")) {
val
} else {
NULL
}
}

method(base_request, ProviderPortkeyAI) <- function(provider) {
req <- request(provider@base_url)
req <- httr2::req_headers(
req,
`x-portkey-api-key` = provider@api_key,
`x-portkey-virtual-key` = provider@virtual_key
`x-portkey-virtual-key` = provider@virtual_key,
`x-portkey-provider` = provider@model_provider
)
req <- ellmer_req_robustify(req)
req <- ellmer_req_user_agent(req)
Expand All @@ -106,15 +112,13 @@ method(base_request, ProviderPortkeyAI) <- function(provider) {
#' @rdname chat_portkey
models_portkey <- function(
base_url = "https://api.portkey.ai/v1",
api_key = portkey_key(),
virtual_key = NULL
api_key = portkey_key()
) {
provider <- ProviderPortkeyAI(
name = "PortkeyAI",
model = "",
base_url = base_url,
api_key = api_key,
virtual_key = virtual_key
api_key = api_key
)

req <- base_request(provider)
Expand All @@ -124,11 +128,11 @@ models_portkey <- function(
json <- resp_body_json(resp)

id <- map_chr(json$data, "[[", "id")
created_at <- as.POSIXct(map_dbl(json$data, "[[", "created_at"))
slug <- map_chr(json$data, "[[", "slug")

df <- data.frame(
id = id,
created_at = created_at
slug = slug
)
df[order(-xtfrm(df$created_at)), ]
df
}
18 changes: 8 additions & 10 deletions man/chat_portkey.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions tests/testthat/test-provider-portkey.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

test_that("can make simple request", {
chat <- chat_portkey_test(
virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"),
"Be as terse as possible; no punctuation"
)
resp <- chat$chat("What is 1 + 1?", echo = FALSE)
Expand All @@ -12,7 +11,6 @@ test_that("can make simple request", {

test_that("can make simple streaming request", {
chat <- chat_portkey_test(
virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"),
"Be as terse as possible; no punctuation"
)
resp <- coro::collect(chat$stream("What is 1 + 1?"))
Expand All @@ -27,15 +25,15 @@ test_that("defaults are reported", {

test_that("supports tool calling", {
chat_fun <- \(...) {
chat_portkey_test(virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"))
chat_portkey_test()
}

test_tools_simple(chat_fun)
})

test_that("can extract data", {
chat_fun <- \(...) {
chat_portkey_test(virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"))
chat_portkey_test()
}

test_data_extraction(chat_fun)
Expand All @@ -44,7 +42,6 @@ test_that("can extract data", {
test_that("can use images", {
chat_fun <- \(...) {
chat_portkey_test(
virtual_key = Sys.getenv("PORTKEY_VIRTUAL_KEY"),
model = "gpt-4.1-mini",
...
)
Expand Down