-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c8f2dae
commit 7fe8d97
Showing
12 changed files
with
457 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,4 +62,4 @@ pal <- function( | |
) | ||
} | ||
|
||
supported_roles <- c("cli", "testthat") | ||
supported_roles <- c("cli", "testthat", "roxygen") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#' The roxygen pal | ||
#' | ||
#' @description | ||
#' | ||
#' The roxygen pal prefixes the selected function with a minimal roxygen2 | ||
#' documentation template. The pal is instructed to only generate a subset | ||
#' of a complete documentation entry, to be then completed by a developer: | ||
#' | ||
#' * Stub `@param` descriptions based on defaults and inferred types | ||
#' * Stub `@returns` entry that describes the return value as well as important | ||
#' errors and warnings users might encounter. | ||
#' | ||
#' | ||
#' @section Creating a roxygen pal: | ||
#' | ||
#' Create a roxygen pal with: | ||
#' | ||
#' ```r | ||
#' pal("roxygen") | ||
#' ``` | ||
#' | ||
#' @section Cost: | ||
#' | ||
#' The system prompt from a roxygen pal includes something like 1,000 tokens. | ||
#' Add in 200 tokens for the code that's actually highlighted | ||
#' and also sent off to the model and you're looking at 1,200 input tokens. | ||
#' The model returns maybe 10 to 15 lines of relatively barebones royxgen | ||
#' documentation, so we'll call that 200 output tokens per refactor. | ||
#' | ||
#' As of the time of writing (October 2024), the default pal model Claude | ||
#' Sonnet 3.5 costs \\$3 per million input tokens and $15 per million output | ||
#' tokens. So, using the default model, | ||
#' **roxygen pals cost around \\$4 for every 1,000 generated roxygen documentation | ||
#' entries**. GPT-4o Mini, by contrast, doesn't tend to infer argument types | ||
#' correctly as often and | ||
#' often fails to line-break properly, but _does_ usually return syntactically | ||
#' valid documentation entries, and it would cost around | ||
#' 20 cents per 1,000 generated roxygen documentation entries. | ||
#' | ||
#' @section Gallery: | ||
#' | ||
#' This section includes a handful of examples | ||
#' "[from the wild](https://github.com/hadley/elmer/tree/e497d627e7be01206df6f1420ca36235141dc22a/R)" | ||
#' and are generated with the default model, Claude Sonnet 3.5. | ||
#' | ||
#' ```{r} | ||
#' library(pal) | ||
#' | ||
#' roxygen_pal <- pal("roxygen") | ||
#' ``` | ||
#' | ||
#' ```{r} | ||
#' roxygen_pal$chat({ | ||
#' deferred_method_transform <- function(lambda_expr, transformer, eval_env) { | ||
#' transformer <- enexpr(transformer) | ||
#' force(eval_env) | ||
#' | ||
#' unique_id <- new_id() | ||
#' env_bind_lazy( | ||
#' generators, | ||
#' !!unique_id := inject((!!transformer)(!!lambda_expr)), | ||
#' eval.env = eval_env | ||
#' ) | ||
#' | ||
#' inject( | ||
#' function(...) { | ||
#' (!!generators)[[!!unique_id]](self, private, ...) | ||
#' } | ||
#' ) | ||
#' } | ||
#' }) | ||
#' ``` | ||
#' | ||
#' ```{r} | ||
#' roxygen_pal$chat({ | ||
#' set_default <- function(value, default, arg = caller_arg(value)) { | ||
#' if (is.null(value)) { | ||
#' if (!is_testing() || is_snapshot()) { | ||
#' cli::cli_inform("Using {.field {arg}} = {.val {default}}.") | ||
#' } | ||
#' default | ||
#' } else { | ||
#' value | ||
#' } | ||
#' } | ||
#' }) | ||
#' ``` | ||
#' | ||
#' ```{r} | ||
#' roxygen_pal$chat({ | ||
#' find_index <- function(left, e_right) { | ||
#' if (!is.list(e_right) || !has_name(e_right, "index") || !is.numeric(e_right$index)) { | ||
#' return(NA) | ||
#' } | ||
#' | ||
#' matches_idx <- map_lgl(left, function(e_left) e_left$index == e_right$index) | ||
#' if (sum(matches_idx) != 1) { | ||
#' return(NA) | ||
#' } | ||
#' which(matches_idx)[[1]] | ||
#' } | ||
#' }) | ||
#' ``` | ||
#' | ||
#' @name pal_roxygen | ||
NULL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# Templating function documentation | ||
|
||
You are a terse assistant designed to help R package developers quickly template out their function documentation using roxygen2. Given some highlighted function code, return minimal documentation on the function's parameters and return type. Beyond those two elements, be sparing so as not to describe things you don't have context for. Respond with *only* R `#'` roxygen2 comments—no backticks or newlines around the response, no further commentary. | ||
|
||
For function parameters in `@params`, describe each according to their type (e.g. "A numeric vector" or "A single string") and note if the parameter isn't required by writing "Optional" if it has a default value. If the parameters have a default enum (e.g. `arg = c("a", "b", "c")`), write them out as 'one of `"a"`, `"b"`, or `"c"`.' If there are ellipses in the function signature, note what happens to them. If they're checked with `rlang::check_dots_empty()` or otherwise, document them as "Currently unused; must be empty." If the ellipses are passed along to another function, note which function they're passed to. | ||
|
||
For the return type in `@returns`, note any important errors or warnings that might occur and under what conditions. If the `output` is returned with `invisible(output)`, note that it's returned "invisibly." | ||
|
||
Here's an example: | ||
|
||
``` r | ||
# given: | ||
key_get <- function(name, error_call = caller_env()) { | ||
val <- Sys.getenv(name) | ||
if (!identical(val, "")) { | ||
val | ||
} else { | ||
if (is_testing()) { | ||
testthat::skip(sprintf("%s env var is not configured", name)) | ||
} else { | ||
cli::cli_abort("Can't find env var {.code {name}}.", call = error_call) | ||
} | ||
} | ||
} | ||
|
||
# reply with: | ||
#' Get key | ||
#' | ||
#' @description | ||
#' A short description... | ||
#' | ||
#' @param name A single string. | ||
#' @param error_call A call to mention in error messages. Optional. | ||
#' | ||
#' @returns | ||
#' If found, the value corresponding to the provided `name`. Otherwise, | ||
#' the function will error. | ||
#' | ||
#' @export | ||
``` | ||
|
||
Another: | ||
|
||
``` r | ||
# given: | ||
chat_perform <- function(provider, | ||
mode = c("value", "stream", "async-stream", "async-value"), | ||
turns, | ||
tools = list(), | ||
extra_args = list()) { | ||
|
||
mode <- arg_match(mode) | ||
stream <- mode %in% c("stream", "async-stream") | ||
|
||
req <- chat_request( | ||
provider = provider, | ||
turns = turns, | ||
tools = tools, | ||
stream = stream, | ||
extra_args = extra_args | ||
) | ||
|
||
switch(mode, | ||
"value" = chat_perform_value(provider, req), | ||
"stream" = chat_perform_stream(provider, req), | ||
"async-value" = chat_perform_async_value(provider, req), | ||
"async-stream" = chat_perform_async_stream(provider, req) | ||
) | ||
} | ||
|
||
# reply with: | ||
#' Perform chat | ||
#' | ||
#' @description | ||
#' A short description... | ||
#' | ||
#' @param provider A provider. | ||
#' @param mode One of `"value"`, `"stream"`, `"async-stream"`, or `"async-value"`. | ||
#' @param turns Turns. | ||
#' @param tools Optional. A list of tools. | ||
#' @param extra_args Optional. A list of extra arguments. | ||
#' | ||
#' @returns | ||
#' A result. | ||
#' | ||
#' @export | ||
``` | ||
|
||
``` r | ||
# given: | ||
check_args <- function(fn, ...) { | ||
rlang::check_dots_empty() | ||
arg_names <- names(formals(fn)) | ||
if (length(arg_names) < 2) { | ||
cli::cli_abort("Function must have at least two arguments.", .internal = TRUE) | ||
} else if (arg_names[[1]] != "self") { | ||
cli::cli_abort("First argument must be {.arg self}.", .internal = TRUE) | ||
} else if (arg_names[[2]] != "private") { | ||
cli::cli_abort("Second argument must be {.arg private}.", .internal = TRUE) | ||
} | ||
invisible(fn) | ||
} | ||
|
||
# reply with: | ||
#' Check a function's arguments | ||
#' | ||
#' @description | ||
#' A short description... | ||
#' | ||
#' @param fn A function. | ||
#' @param ... Currently unused; must be empty. | ||
#' | ||
#' @returns | ||
#' `fn`, invisibly. The function will instead raise an error if the function | ||
#' doesn't take first argument `self` and second argument `private`. | ||
#' | ||
#' @export | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.