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

Rename elmer to ellmer #237

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Changes from 1 commit
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
Next Next commit
Rename elmer to ellmer
To avoid case-insensitive clash with ELMER on bioconductor.
hadley committed Dec 19, 2024
commit a2cb7dcd07ac52dfdeb94efbc13f1fa869c31583
2 changes: 1 addition & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
^elmer\.Rproj$
^ellmer\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^\.github$
8 changes: 4 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Package: elmer
Package: ellmer
Title: Call LLM APIs from R
Version: 0.0.0.9000
Authors@R: c(
@@ -9,8 +9,8 @@ Authors@R: c(
Description: A consistent interface for calling LLM APIs. Includes support
for streaming.
License: MIT + file LICENSE
URL: https://elmer.tidyverse.org, https://github.com/tidyverse/elmer
BugReports: https://github.com/tidyverse/elmer/issues
URL: https://ellmer.tidyverse.org, https://github.com/tidyverse/ellmer
BugReports: https://github.com/tidyverse/ellmer/issues
Imports:
cli,
coro (>= 1.1.0),
@@ -55,7 +55,7 @@ Collate:
'chat.R'
'content-image.R'
'content-tools.R'
'elmer-package.R'
'ellmer-package.R'
'httr2.R'
'import-standalone-obj-type.R'
'import-standalone-purrr.R'
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
YEAR: 2024
COPYRIGHT HOLDER: elmer authors
COPYRIGHT HOLDER: ellmer authors
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2024 elmer authors
Copyright (c) 2024 ellmer authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
4 changes: 2 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# elmer (development version)
# ellmer (development version)

* New `chat_vllm()` to chat with models served by vLLM (#140).

@@ -28,7 +28,7 @@

* The `echo` can now be one of three values: "none", "text", or "all". If "all", you'll now see both user and assistant turns, and all content types will be printed, not just text. When running in the global environment, `echo` defaults to "text", and when running inside a function it defaults to "none".

* You can now log low-level JSON request/response info by setting `options(elmer_verbosity = 2)`.
* You can now log low-level JSON request/response info by setting `options(ellmer_verbosity = 2)`.

* `chat$register_tool()` now takes an object created by `Tool()`. This makes it a little easier to reuse tool definitions (#32).

6 changes: 3 additions & 3 deletions R/chat.R
Original file line number Diff line number Diff line change
@@ -249,13 +249,13 @@ Chat <- R6::R6Class("Chat",
},

#' @description Register a tool (an R function) that the chatbot can use.
#' If the chatbot decides to use the function, elmer will automatically
#' If the chatbot decides to use the function, ellmer will automatically
#' call it and submit the results back.
#'
#'
#' The return value of the function. Generally, this should either be a
#' string, or a JSON-serializable value. If you must have more direct
#' control of the structure of the JSON that's returned, you can return a
#' JSON-serializable value wrapped in [base::I()], which elmer will leave
#' JSON-serializable value wrapped in [base::I()], which ellmer will leave
#' alone until the entire request is JSON-serialized.
#' @param tool_def Tool definition created by [tool()].
register_tool = function(tool_def) {
6 changes: 3 additions & 3 deletions R/content-image.R
Original file line number Diff line number Diff line change
@@ -15,12 +15,12 @@
#' the `chat()`, `stream()`, `chat_async()`, or `stream_async()` methods.
#'
#' @export
#' @examplesIf elmer:::openai_key_exists()
#' @examplesIf ellmer:::openai_key_exists()
#' chat <- chat_openai(echo = TRUE)
#' chat$chat(
#' "What do you see in these images?",
#' content_image_url("https://www.r-project.org/Rlogo.png"),
#' content_image_file(system.file("httr2.png", package = "elmer"))
#' content_image_file(system.file("httr2.png", package = "ellmer"))
#' )
#'
#' \dontshow{dev.control('enable')}
@@ -144,7 +144,7 @@ content_image_plot <- function(width = 768, height = 768) {

old <- grDevices::dev.cur()

path <- tempfile("elmer-plot-", fileext = ".png")
path <- tempfile("ellmer-plot-", fileext = ".png")
defer(unlink(path))

grDevices::png(path, width = width, height = height)
14 changes: 7 additions & 7 deletions R/content.R
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@
NULL

#' Format contents into a textual representation
#'
#'
#' @description
#' These generic functions can be use to convert [Turn] contents or [Content]
#' objects into textual representations.
#'
#' objects into textual representations.
#'
#' * `contents_text()` is the most minimal and only includes [ContentText]
#' objects in the output.
#' * `contents_markdown()` returns the text content (which it assumes to be
@@ -15,7 +15,7 @@ NULL
#' * `contents_html()` returns the text content, converted from markdown to
#' HTML with [commonmark::markdown_html()], plus HTML representations of
#' images and other content types.
#'
#'
#' @examples
#' turns <- list(
#' Turn("user", contents = list(
@@ -30,12 +30,12 @@ NULL
#' if (rlang::is_installed("commonmark")) {
#' contents_html(turns[[1]])
#' }
#'
#'
#' @param content The [Turn] or [Content] object to be converted into text.
#' `contents_markdown()` also accepts [Chat] instances to turn the entire
#' conversation history into markdown text.
#' @param ... Additional arguments passed to methods.
#'
#'
#' @return A string of text, markdown or HTML.
#' @export
contents_text <- new_generic("contents_text", "content")
@@ -52,7 +52,7 @@ contents_markdown <- new_generic("contents_markdown", "content")
#' Content types received from and sent to a chatbot
#'
#' @description
#' elmer abstracts away differences in the way that different [Provider]s
#' ellmer abstracts away differences in the way that different [Provider]s
#' represent various types of content, allowing you to more easily write
#' code that works with any chatbot.
#'
File renamed without changes.
2 changes: 1 addition & 1 deletion R/httr2.R
Original file line number Diff line number Diff line change
@@ -153,5 +153,5 @@ cat_with_prefix <- function(prefix, lines) {
}

log_http_traffic <- function() {
getOption("elmer_verbosity", 0L) >= 2L
getOption("ellmer_verbosity", 0L) >= 2L
}
4 changes: 2 additions & 2 deletions R/provider-bedrock.R
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ method(chat_resp_stream, ProviderBedrock) <- function(provider, resp) {
resp_stream_aws(resp)
}

# Bedrock -> elmer -------------------------------------------------------------
# Bedrock -> ellmer -------------------------------------------------------------

method(stream_parse, ProviderBedrock) <- function(provider, event) {
if (is.null(event)) {
@@ -216,7 +216,7 @@ method(value_turn, ProviderBedrock) <- function(provider, result, has_type = FAL
Turn(result$output$message$role, contents, json = result, tokens = tokens)
}

# elmer -> Bedrock -------------------------------------------------------------
# ellmer -> Bedrock -------------------------------------------------------------

# https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ContentBlock.html
method(as_json, list(ProviderBedrock, Turn)) <- function(provider, x) {
4 changes: 2 additions & 2 deletions R/provider-claude.R
Original file line number Diff line number Diff line change
@@ -136,7 +136,7 @@ method(chat_request, ProviderClaude) <- function(provider,
req
}

# Claude -> elmer --------------------------------------------------------------
# Claude -> ellmer --------------------------------------------------------------

method(stream_parse, ProviderClaude) <- function(provider, event) {
if (is.null(event)) {
@@ -221,7 +221,7 @@ method(value_turn, ProviderClaude) <- function(provider, result, has_type = FALS
Turn(result$role, contents, json = result, tokens = tokens)
}

# elmer -> Claude --------------------------------------------------------------
# ellmer -> Claude --------------------------------------------------------------

method(as_json, list(ProviderClaude, Turn)) <- function(provider, x) {
if (x@role == "system") {
10 changes: 5 additions & 5 deletions R/provider-cortex.R
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ NULL
#' @inheritParams chat_openai
#' @inherit chat_openai return
#' @family chatbots
#' @examplesIf elmer:::cortex_credentials_exist()
#' @examplesIf ellmer:::cortex_credentials_exist()
#' chat <- chat_cortex(
#' model_file = "@my_db.my_schema.my_stage/model.yaml"
#' )
@@ -137,11 +137,11 @@ method(chat_request, ProviderCortex) <- function(provider,
req <- req_error(req, body = function(resp) resp_body_json(resp)$message)

# Snowflake uses the User Agent header to identify "parter applications",
# so identify requests as coming from "r_elmer" (unless an explicit
# so identify requests as coming from "r_ellmer" (unless an explicit
# partner application is set via the ambient SF_PARTNER environment
# variable).
req <- req_user_agent(
req, paste0("r_elmer/", utils::packageVersion("elmer"))
req, paste0("r_ellmer/", utils::packageVersion("ellmer"))
)
if (nchar(Sys.getenv("SF_PARTNER")) != 0) {
req <- req_user_agent(req, Sys.getenv("SF_PARTNER"))
@@ -158,7 +158,7 @@ method(chat_request, ProviderCortex) <- function(provider,
req
}

# Cortex -> elmer --------------------------------------------------------------
# Cortex -> ellmer --------------------------------------------------------------

method(stream_parse, ProviderCortex) <- function(provider, event) {
# While undocumented, Cortex seems to mostly follow OpenAI API conventions for
@@ -281,7 +281,7 @@ method(value_turn, ProviderCortex) <- function(provider, result, has_type = FALS
}


# elmer -> Cortex --------------------------------------------------------------
# ellmer -> Cortex --------------------------------------------------------------

# Cortex supports not only "text" content, but also bespoke "suggestions" and
# "sql" types.
6 changes: 3 additions & 3 deletions R/provider-databricks.R
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
#'
#' Databricks models do not support images, but they do support structured
#' outputs. Tool calling support is also very limited at present; too limited
#' for `elmer`'s tool calling features to work properly at all.
#' for `ellmer`'s tool calling features to work properly at all.
#'
#' ## Authentication
#'
@@ -188,7 +188,7 @@ databricks_token <- function(workspace = databricks_workspace(), token = NULL) {
paste0("https://", host, "/oidc/v1/token"),
secret = client_secret,
auth = "header",
name = "elmer-databricks-m2m"
name = "ellmer-databricks-m2m"
),
oauth_flow_client_credentials,
# The "all-apis" scope translates to "everything this service principal
@@ -239,7 +239,7 @@ databricks_token <- function(workspace = databricks_workspace(), token = NULL) {
"databricks-cli",
paste0("https://", host, "/oidc/v1/token"),
auth = "body",
name = "elmer-databricks-u2m"
name = "ellmer-databricks-u2m"
),
oauth_flow_auth_code,
flow_params = list(
4 changes: 2 additions & 2 deletions R/provider-gemini.R
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ method(chat_request, ProviderGemini) <- function(provider,
req
}

# Gemini -> elmer --------------------------------------------------------------
# Gemini -> ellmer --------------------------------------------------------------

method(stream_parse, ProviderGemini) <- function(provider, event) {
if (is.null(event)) {
@@ -169,7 +169,7 @@ method(value_turn, ProviderGemini) <- function(provider, result, has_type = FALS
Turn("assistant", contents, json = result, tokens = tokens)
}

# elmer -> Gemini --------------------------------------------------------------
# ellmer -> Gemini --------------------------------------------------------------

# https://ai.google.dev/api/caching#Content
method(as_json, list(ProviderGemini, Turn)) <- function(provider, x) {
6 changes: 3 additions & 3 deletions R/provider-openai.R
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ NULL
#' @family chatbots
#' @export
#' @returns A [Chat] object.
#' @examplesIf elmer:::openai_key_exists()
#' @examplesIf ellmer:::openai_key_exists()
#' chat <- chat_openai()
#' chat$chat("
#' What is the difference between a tibble and a data frame?
@@ -143,7 +143,7 @@ method(chat_request, ProviderOpenAI) <- function(provider,
req
}

# OpenAI -> elmer --------------------------------------------------------------
# OpenAI -> ellmer --------------------------------------------------------------

method(stream_parse, ProviderOpenAI) <- function(provider, event) {
if (is.null(event)) {
@@ -202,7 +202,7 @@ method(value_turn, ProviderOpenAI) <- function(provider, result, has_type = FALS
Turn(message$role, content, json = result, tokens = tokens)
}

# elmer -> OpenAI --------------------------------------------------------------
# ellmer -> OpenAI --------------------------------------------------------------

method(as_json, list(ProviderOpenAI, Turn)) <- function(provider, x) {
if (x@role == "system") {
2 changes: 1 addition & 1 deletion R/provider-vllm.R
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ chat_vllm_test <- function(...) {
ProviderVllm <- new_class(
"ProviderVllm",
parent = ProviderOpenAI,
package = "elmer",
package = "ellmer",
)

# Just like OpenAI but no strict
2 changes: 1 addition & 1 deletion R/tools-def-auto.R
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ create_tool_def <- function(topic,

topic_str <- format(expr)

tool_prompt <- readLines(system.file("tool_prompt.md", package = "elmer"), warn = FALSE)
tool_prompt <- readLines(system.file("tool_prompt.md", package = "ellmer"), warn = FALSE)
tool_prompt <- paste(tool_prompt, collapse = "\n")

payload <- paste0(
2 changes: 1 addition & 1 deletion R/tools-def.R
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ NULL
#' function. Each element should be created by a [`type_*()`][type_boolean]
#' function.
#' @export
#' @examplesIf elmer:::openai_key_exists()
#' @examplesIf ellmer:::openai_key_exists()
#'
#' # First define the metadata that the model uses to figure out when to
#' # call the tool
4 changes: 2 additions & 2 deletions R/turns.R
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ NULL
#'
#' Note that a call to `$chat()` and related functions may result in multiple
#' user-assistant turn cycles. For example, if you have registered tools,
#' elmer will automatically handle the tool calling loop, which may result in
#' ellmer will automatically handle the tool calling loop, which may result in
#' any number of additional cycles. Learn more about tool calling in
#' `vignette("tool-calling")`.
#'
@@ -21,7 +21,7 @@ NULL
#' @param json The serialized JSON corresponding to the underlying data of
#' the turns. Currently only provided for assistant.
#'
#' This is useful if there's information returned by the provider that elmer
#' This is useful if there's information returned by the provider that ellmer
#' doesn't otherwise expose.
#' @param tokens A numeric vector of length 2 representing the number of
#' input and output tokens (respectively) used in this turn. Currently
2 changes: 1 addition & 1 deletion R/types.R
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ NULL
#' Type definitions for function calling and structured data extraction.
#'
#' These S7 classes are provided for use by package devlopers who are
#' extending elmer. In every day use, use [type_boolean()] and friends.
#' extending ellmer. In every day use, use [type_boolean()] and friends.
#'
#' @name Type
#' @inheritParams type_boolean
2 changes: 1 addition & 1 deletion R/utils-coro.R
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ async_method <- function(fn) {
# upon first call. This is necessary because the transformation needs to be done
# not at package build time, but after package load time.
#
# Elsewhere in elmer, we use rlang::on_load to defer the transformation of
# Elsewhere in ellmer, we use rlang::on_load to defer the transformation of
# generators until after package load time. We can't do that for R6 methods
# because nesting R6 class definitions inside of rlang::on_load causes roxygen2
# to get confused.
Loading