forked from simonpcouch/pal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
doc-pal-cli.R
186 lines (186 loc) · 5.4 KB
/
doc-pal-cli.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#' The cli pal
#'
#' @description
#'
#' A couple years ago, the tidyverse team began migrating to the cli R package
#' for raising errors, transitioning away from base R (e.g. `stop()`),
#' rlang (e.g. `rlang::abort()`), glue, and homegrown combinations of them.
#' cli's new syntax is easier to work with as a developer and more visually
#' pleasing as a user.
#'
#' In some cases, transitioning is as simple as Finding + Replacing
#' `rlang::abort()` to `cli::cli_abort()`. In others, there's a mess of
#' ad-hoc pluralization, `paste0()`s, glue interpolations, and other
#' assorted nonsense to sort through. Total pain, especially with thousands
#' upon thousands of error messages thrown across the tidyverse, r-lib, and
#' tidymodels organizations.
#'
#' The cli pal helps you convert your R package to use cli for error messages.
#'
#' @section Cost:
#'
# TODO: make this a template that takes in the token counts and prices as input
#'
#' The system prompt from a pal includes something like 4,000 tokens.
#' Add in (a generous) 100 tokens for the code that's actually highlighted
#' and also sent off to the model and you're looking at 4,100 input tokens.
#' The model returns approximately the same number of output tokens as it
#' receives, so we'll call that 100 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,
#' **cli pals cost around $15 for every 1,000 refactored pieces of code**. GPT-4o
#' Mini, by contrast, doesn't tend to get cli markup classes right but _does_
#' return syntactically valid calls to cli functions, and it would cost around
#' 75 cents per 1,000 refactored pieces of code.
#'
#' @section Gallery:
#'
#' This section includes a handful of examples
#' ["from the wild"](https://github.com/tidymodels/tune/blob/f8d734ac0fa981fae3a87ed2871a46e9c40d509d/R/checks.R)
#' and are generated with the default model, Claude Sonnet 3.5.
#'
#' At its simplest, a one-line message with a little bit of markup:
#'
#' ```r
#' rlang::abort("`save_pred` can only be used if the initial results saved predictions.")
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort("{.arg save_pred} can only be used if the initial results saved predictions.")
#' ```
#'
#' Some strange vector collapsing and funky line breaking:
#'
#' ```r
#' extra_grid_params <- glue::single_quote(extra_grid_params)
#' extra_grid_params <- glue::glue_collapse(extra_grid_params, sep = ", ")
#'
#' msg <- glue::glue(
#' "The provided `grid` has the following parameter columns that have ",
#' "not been marked for tuning by `tune()`: {extra_grid_params}."
#' )
#'
#' rlang::abort(msg)
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort(
#' "The provided {.arg grid} has parameter columns that have not been
#' marked for tuning by {.fn tune}: {.val {extra_grid_params}}."
#' )
#' ```
#'
#' A message that probably best lives as two separate elements:
#'
#' ```r
#' rlang::abort(
#' paste(
#' "Some model parameters require finalization but there are recipe",
#' "parameters that require tuning. Please use ",
#' "`extract_parameter_set_dials()` to set parameter ranges ",
#' "manually and supply the output to the `param_info` argument."
#' )
#' )
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort(
#' c(
#' "Some model parameters require finalization but there are recipe
#' parameters that require tuning.",
#' "i" = "Please use {.fn extract_parameter_set_dials} to set parameter
#' ranges manually and supply the output to the {.arg param_info}
#' argument."
#' )
#' )
#' ```
#'
#' Gnarly ad-hoc pluralization:
#'
#' ```r
#' msg <- "Creating pre-processing data to finalize unknown parameter"
#' unk_names <- pset$id[unk]
#' if (length(unk_names) == 1) {
#' msg <- paste0(msg, ": ", unk_names)
#' } else {
#' msg <- paste0(msg, "s: ", paste0("'", unk_names, "'", collapse = ", "))
#' }
#' rlang::inform(msg)
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_inform(
#' "Creating pre-processing data to finalize unknown parameter{?s}: {.val {unk_names}}"
#' )
#' ```
#'
#' Some `paste0()` wonk:
#'
#' ```r
#' rlang::abort(paste0(
#' "The workflow has arguments to be tuned that are missing some ",
#' "parameter objects: ",
#' paste0("'", pset$id[!params], "'", collapse = ", ")
#' ))
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort(
#' "The workflow has arguments to be tuned that are missing some
#' parameter objects: {.val {pset$id[!params]}}"
#' )
#' ```
#'
#' The model is instructed to only return a call to a cli function, so
#' erroring code that's run conditionally can get borked:
#'
#' ```r
#' cls <- paste(cls, collapse = " or ")
#' if (!fine) {
#' msg <- glue::glue("Argument '{deparse(cl$x)}' should be a {cls} or NULL")
#' if (!is.null(where)) {
#' msg <- glue::glue(msg, " in `{where}`")
#' }
#' rlang::abort(msg)
#' }
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort(
#' "Argument {.code {deparse(cl$x)}} should be {?a/an} {.cls {cls}} or {.code NULL}{?in {where}}."
#' )
#' ```
#'
#' Note that `?in where` is not valid cli markup.
#'
#' Sprintf-style statements aren't an issue:
#'
#' ```r
#' abort(sprintf("No such '%s' function: `%s()`.", package, name))
#' ```
#'
#' Returns:
#'
#' ```r
#' cli::cli_abort("No such {.pkg {package}} function: {.fn {name}}.")
#' ```
#'
#' @templateVar role cli
#' @template manual-interface
#'
#' @name pal_cli
NULL