Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial Hugging Face support #359

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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 DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Collate:
'provider-gemini.R'
'provider-github.R'
'provider-groq.R'
'provider-huggingface.r'
'provider-ollama.R'
'provider-openrouter.R'
'provider-perplexity.R'
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export(chat_deepseek)
export(chat_gemini)
export(chat_github)
export(chat_groq)
export(chat_hf)
export(chat_ollama)
export(chat_openai)
export(chat_openrouter)
Expand Down
58 changes: 58 additions & 0 deletions R/provider-huggingface.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#' Chat with a model hosted on Hugging Face Serverless Inference API
#'
#' @description
#' [Hugging Face](https://huggingface.co/) hosts a variety of open-source
#' and proprietary AI models available via their Inference API.
#' To use the Hugging Face API, you must have an Access Token, which you can obtain
#' from your [Hugging Face account](https://huggingface.co/settings/tokens).
#'
#' This function is a lightweight wrapper around [chat_openai()], with
#' the defaults adjusted for Hugging Face. Model defaults to `meta-llama/Llama-3.1-8B-Instruct`.
#'
#' ## Known limitations
#'
#' * Some models do not support the chat interface or parts of it, for example
#' `google/gemma-2-2b-it` does not support a system prompt. You will need to
#' carefully choose the model.
Comment on lines +15 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#' `google/gemma-2-2b-it` does not support a system prompt. You will need to
#' carefully choose the model.
#' `google/gemma-2-2b-it` does not support a system prompt. You will need to
#' carefully choose the model.

#'
#' @family chatbots
#' @param api_key The API key to use for authentication. You should not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please mimic the existing structure from the other chat functions? Or if you think it's worth being more explicit, it'd be useful to create a api_key_doc(key_name) function that could generate the docs for all of them, eliminating any inconsistencies or duplication. Please let me know if you need some more hints on the appropriate way to do that in roxygen2.

#' supply this directly; instead, store your Hugging Face API key as an
#' environment variable (`HUGGINGFACE_API_KEY`) in your `.Renviron` file.
#' Use `usethis::edit_r_environ()` to modify it.
#' @export
#' @inheritParams chat_openai
#' @inherit chat_openai return
#' @examples
#' \dontrun{
#' chat <- chat_hf()
#' chat$chat("Tell me three jokes about statisticians")
#' }
chat_hf <- function(system_prompt = NULL,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call this chat_huggingface for consistency with the other chat functions.

turns = NULL,
base_url = "https://api-inference.huggingface.co/models/",
api_key = hf_key(),
model = NULL,
seed = NULL,
api_args = list(),
echo = NULL) {

model <- set_default(model, "meta-llama/Llama-3.1-8B-Instruct")
echo <- check_echo(echo)

chat_openai(
system_prompt = system_prompt,
turns = turns,
# modify base_url for hugging face compatibility with openai
base_url = paste0(base_url, model, "/v1"),
api_key = api_key,
model = model,
seed = seed,
api_args = api_args,
echo = echo
)
}

hf_key <- function() {
key_get("HUGGINGFACE_API_KEY")
}
2 changes: 1 addition & 1 deletion R/provider-openai.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ NULL
#' Answer with a bulleted list
#' ")
#'
#' chat$chat("Tell me three funny jokes about statistcians")
#' chat$chat("Tell me three funny jokes about statisticians")
chat_openai <- function(system_prompt = NULL,
turns = NULL,
base_url = "https://api.openai.com/v1",
Expand Down
1 change: 1 addition & 0 deletions ellmer.Rproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Version: 1.0
ProjectId: cd6d3e25-62f1-4041-a95a-6833286990e5

RestoreWorkspace: No
SaveWorkspace: No
Expand Down
1 change: 1 addition & 0 deletions man/chat_bedrock.Rd

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

1 change: 1 addition & 0 deletions man/chat_claude.Rd

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

1 change: 1 addition & 0 deletions man/chat_cortex_analyst.Rd

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

1 change: 1 addition & 0 deletions man/chat_databricks.Rd

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

1 change: 1 addition & 0 deletions man/chat_deepseek.Rd

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

1 change: 1 addition & 0 deletions man/chat_gemini.Rd

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

1 change: 1 addition & 0 deletions man/chat_github.Rd

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

1 change: 1 addition & 0 deletions man/chat_groq.Rd

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

92 changes: 92 additions & 0 deletions man/chat_hf.Rd

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

1 change: 1 addition & 0 deletions man/chat_ollama.Rd

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

1 change: 1 addition & 0 deletions man/chat_openai.Rd

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

1 change: 1 addition & 0 deletions man/chat_openrouter.Rd

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

1 change: 1 addition & 0 deletions man/chat_perplexity.Rd

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

6 changes: 6 additions & 0 deletions tests/testthat/test-provider-huggingface.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
test_that("can make simple request", {
chat <- chat_hf("Be as terse as possible; no punctuation", model = "meta-llama/Llama-3.1-8B-Instruct")
resp <- chat$chat("What is 1 + 1?", echo = FALSE)
expect_match(resp, "2")
expect_equal(chat$last_turn()@tokens > 0, c(TRUE, TRUE))
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to add any other tests to verify that (eg.) tool calling works?

Loading