├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── check-release.yaml │ └── pkgdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── OpenAIR.Rproj ├── R ├── OpenAIR-package.R ├── add_roxygen.R ├── add_to_chatlog.R ├── chat.R ├── chat_completion.R ├── class.R ├── clean_output.R ├── clear_chatlog.R ├── contains_r_func.R ├── contains_roxygen.R ├── count_tokens.R ├── created.R ├── data.R ├── df_to_csv.R ├── edit_code.R ├── extract_blocks.R ├── extract_blocks_content.R ├── extract_entities.R ├── extract_r_code.R ├── extract_roxygen2.R ├── get_chatlog.R ├── grapes_c_grapes.R ├── id.R ├── initialize_messages.R ├── install_tiktoken.R ├── is_chaglog.R ├── is_json.R ├── is_python.R ├── is_r.R ├── is_xml.R ├── java_to_r.R ├── messages.R ├── messages_content.R ├── methods.R ├── model.R ├── nested_to_pipe.R ├── num_tokens.R ├── num_tokens_file.R ├── object.R ├── openai_api_key.R ├── parse_response.R ├── python_to_r.R ├── r_to_python.R ├── read_text.R ├── read_text_batches.R ├── refactor.R ├── references_to_bibtex.R ├── regenerate.R ├── replace_file_extension.R ├── set_chatlog.R ├── split_text.R ├── start_chat.R ├── usage.R ├── utils-pipe.R ├── write_code.R ├── write_test.R └── zzz.R ├── README.md ├── _pkgdown.yml ├── data ├── add_roxygen_prompt.rda ├── extract_entities_prompt.rda ├── java_to_r_prompt.rda ├── nested_to_pipe_prompt.rda ├── python_to_r_prompt.rda ├── r_to_python_prompt.rda ├── refactor_prompt.rda ├── references_to_bibtex_prompt.rda ├── trump.rda └── write_test_prompt.rda ├── index.md ├── inst ├── code_of_conduct.md └── text │ ├── func.R │ ├── lorem.txt │ ├── persons.json │ └── ref.txt ├── man ├── TheOpenAIR-package.Rd ├── add_roxygen.Rd ├── add_roxygen_prompt.Rd ├── add_to_chatlog.Rd ├── chat.Rd ├── chat_completion.Rd ├── chatlog-class.Rd ├── clean_output.Rd ├── clear_chatlog.Rd ├── contains_r_func.Rd ├── contains_roxygen.Rd ├── count_tokens.Rd ├── created.Rd ├── df_to_csv.Rd ├── edit_code.Rd ├── extract_blocks.Rd ├── extract_blocks_content.Rd ├── extract_entities.Rd ├── extract_entities_prompt.Rd ├── extract_r_code.Rd ├── extract_roxygen2.Rd ├── figures │ └── logo.png ├── get_chatlog.Rd ├── grapes-c-grapes.Rd ├── id.Rd ├── initialize_messages.Rd ├── install_tiktoken.Rd ├── is_chatlog.Rd ├── is_json.Rd ├── is_python.Rd ├── is_r.Rd ├── is_xml.Rd ├── java_to_r.Rd ├── java_to_r_prompt.Rd ├── messages.Rd ├── messages_content.Rd ├── model.Rd ├── nested_to_pipe.Rd ├── nested_to_pipe_prompt.Rd ├── num_tokens.Rd ├── num_tokens_file.Rd ├── object.Rd ├── openai_api_key.Rd ├── parse_response.Rd ├── pipe.Rd ├── python_to_r.Rd ├── python_to_r_prompt.Rd ├── r_to_python.Rd ├── r_to_python_prompt.Rd ├── read_text.Rd ├── read_text_batches.Rd ├── refactor.Rd ├── refactor_prompt.Rd ├── references_to_bibtex.Rd ├── references_to_bibtex_prompt.Rd ├── regenerate.Rd ├── replace_file_extension.Rd ├── set_chatlog.Rd ├── split_text.Rd ├── start_chat.Rd ├── trump.Rd ├── usage.Rd ├── write_code.Rd ├── write_test.Rd └── write_test_prompt.Rd ├── pkgdown └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico └── tests ├── testthat.R └── testthat ├── test-%c%.R ├── test-add_roxygen.R ├── test-chat.R ├── test-chat_completion.R ├── test-clean_output.R ├── test-count_tokens.R ├── test-df_to_csv.R ├── test-extract_blocks.R ├── test-extract_entities.R ├── test-extract_r_code.R ├── test-extract_roxygen2.R ├── test-is_json.R ├── test-is_python.R ├── test-is_r.R ├── test-is_xml.R ├── test-messages.R ├── test-nested_to_pipe.R ├── test-parse_response.R ├── test-python_to_r.R ├── test-r_to_python.R ├── test-read_text.R ├── test-refactor.R ├── test-references_to_bibtex.R ├── test-regenerate.R ├── test-split_text.R └── test-write_test.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^_pkgdown\.yml$ 5 | ^docs$ 6 | ^pkgdown$ 7 | ^\.github$ 8 | ^inst/slides 9 | ^cran-comments\.md$ 10 | ^code-of-conduct\.md$ 11 | ^index\.md$ 12 | ^CRAN-SUBMISSION$ 13 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | R_KEEP_PKG_SOURCE: yes 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::rcmdcheck 27 | needs: check 28 | 29 | - uses: r-lib/actions/check-r-package@v2 30 | -------------------------------------------------------------------------------- /.github/workflows/check-release.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | R_KEEP_PKG_SOURCE: yes 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::rcmdcheck 27 | needs: check 28 | 29 | - uses: r-lib/actions/check-r-package@v2 30 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::. 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@v4.4.1 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | token: ${{ secrets.GH_PAGES_TOKEN }} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | docs 6 | tests/_notes.R 7 | inst/slides/ 8 | inst/text/func.R 9 | inst/doc 10 | .aider* 11 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: TheOpenAIR 2 | Type: Package 3 | Title: Integrate 'OpenAI' Large Language Models into Your 'R' Workflows 4 | Version: 0.1.0 5 | Authors@R: c(person("Ulrich", "Matter", email = "umatter@protonmail.com", role = c("aut", "cre", "cph")), person("Jonathan", "Chassot", email = "jonathan.chassot@unisg.ch", role = "aut")) 6 | Maintainer: Ulrich Matter 7 | Description: Utilizing the 'OpenAI' API as the back end (), 'TheOpenAIR' offers 'R' wrapper functions for the 'ChatGPT' endpoint and several high-level functions that enable the integration of 'ChatGPT' capabilities in diverse data-related tasks, such as data cleansing and automated analytics script generation. 8 | License: MIT + file LICENSE 9 | Encoding: UTF-8 10 | LazyData: true 11 | RoxygenNote: 7.2.3 12 | Suggests: 13 | readr, 14 | jsonlite, 15 | tidyr, 16 | dplyr, 17 | lubridate, 18 | testthat (>= 3.0.0), 19 | knitr, 20 | rmarkdown 21 | Config/testthat/edition: 3 22 | Config/reticulate: 23 | list( 24 | packages = list( 25 | list(package = "tiktoken") 26 | ) 27 | ) 28 | Imports: 29 | reticulate, 30 | magrittr, 31 | tibble, 32 | methods, 33 | stringr, 34 | stringi, 35 | data.table, 36 | httr, 37 | R.utils, 38 | xml2, 39 | utils, 40 | cli, 41 | rstudioapi 42 | URL: http://openair-lib.org/ 43 | Depends: 44 | R (>= 2.10) 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2023 2 | COPYRIGHT HOLDER: TheOpenAIR authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2023 TheOpenAIR authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export("%c%") 5 | export(add_roxygen) 6 | export(add_to_chatlog) 7 | export(chat) 8 | export(chat_completion) 9 | export(clean_output) 10 | export(clear_chatlog) 11 | export(contains_r_func) 12 | export(contains_roxygen) 13 | export(count_tokens) 14 | export(created) 15 | export(df_to_csv) 16 | export(edit_code) 17 | export(extract_blocks) 18 | export(extract_blocks_content) 19 | export(extract_entities) 20 | export(extract_r_code) 21 | export(extract_roxygen2) 22 | export(get_chatlog) 23 | export(id) 24 | export(initialize_messages) 25 | export(is_chatlog) 26 | export(is_json) 27 | export(is_python) 28 | export(is_r) 29 | export(is_xml) 30 | export(java_to_r) 31 | export(messages) 32 | export(messages_content) 33 | export(model) 34 | export(nested_to_pipe) 35 | export(object) 36 | export(openai_api_key) 37 | export(parse_response) 38 | export(python_to_r) 39 | export(r_to_python) 40 | export(read_text) 41 | export(read_text_batches) 42 | export(refactor) 43 | export(references_to_bibtex) 44 | export(regenerate) 45 | export(replace_file_extension) 46 | export(set_chatlog) 47 | export(split_text) 48 | export(start_chat) 49 | export(usage) 50 | export(write_code) 51 | export(write_test) 52 | exportClasses(chatlog) 53 | import(methods) 54 | import(reticulate) 55 | import(stringr) 56 | importFrom(R.utils,isUrl) 57 | importFrom(data.table,.N) 58 | importFrom(data.table,data.table) 59 | importFrom(httr,GET) 60 | importFrom(httr,content) 61 | importFrom(magrittr,"%>%") 62 | importFrom(reticulate,py_install) 63 | importFrom(stringi,stri_split_regex) 64 | importFrom(utils,file.edit) 65 | importFrom(xml2,read_xml) 66 | -------------------------------------------------------------------------------- /OpenAIR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: XeLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /R/OpenAIR-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | ## usethis namespace: start 5 | #' @importFrom utils file.edit 6 | #' @importFrom xml2 read_xml 7 | ## usethis namespace: end 8 | NULL 9 | -------------------------------------------------------------------------------- /R/add_roxygen.R: -------------------------------------------------------------------------------- 1 | #' Add Roxygen2 documentation to an R function 2 | #' 3 | #' This function adds Roxygen2 documentation to an R function. 4 | #' 5 | #' @param file A character string indicating the path to the file containing the 6 | #' R function. 7 | #' @param ... Additional arguments to pass to the chat_completion() function. 8 | #' @return If the path provided is a character string, this function returns the 9 | #' documented function as a character string. If the input is a file path, this 10 | #' function returns the path of the file to which documentation was added to the 11 | #' file. 12 | #' @export 13 | #' @author Ulrich Matter umatter@protonmail.com 14 | 15 | add_roxygen <- function(file, ...) { 16 | 17 | # import, process text 18 | r_function <- read_text(file) 19 | text <- 20 | r_function$text %>% 21 | paste0(collapse = "\n") 22 | 23 | # Make sure intput is an R function 24 | if (!contains_r_func(text) | nchar(text) == 0) { 25 | stop("The input does not contain a valid R function.") 26 | } 27 | 28 | # initial user input 29 | n_msgs <- nrow(add_roxygen_prompt) 30 | add_roxygen_prompt$content[n_msgs] <- 31 | sprintf(fmt = add_roxygen_prompt$content[n_msgs], text) 32 | 33 | # chat 34 | cli::cli_alert_info("Code documentation in progress. Hold on tight!") 35 | resp <- chat_completion(add_roxygen_prompt, ...) 36 | total_tokens_used <- usage(resp)$total_tokens 37 | info_token <- paste0("Total tokens used: ", total_tokens_used) 38 | cli::cli_inform(info_token) 39 | 40 | # extract roxygen2 documentation 41 | output <- 42 | resp %>% 43 | messages_content() %>% 44 | extract_roxygen2() 45 | 46 | # prepare output 47 | filename <- unique(r_function$file) 48 | if (filename == "character string") { 49 | return(output) 50 | 51 | } else { 52 | rfunc <- readLines(filename) 53 | rfunc_documented <- c(output, rfunc) 54 | output <- paste0(rfunc_documented, collapse = "\n") 55 | cat(output, file = filename) 56 | cli::cli_alert_success(paste0("Added documentation to ", filename)) 57 | return(filename) 58 | } 59 | } -------------------------------------------------------------------------------- /R/add_to_chatlog.R: -------------------------------------------------------------------------------- 1 | #' Add data to a chat log 2 | #' 3 | #' This function adds data to the in-memory chat log, which is in the global 4 | #' environment. The data can be any R object, such as a vector, list, or data 5 | #' frame. The function supports adding data to the chat log by providing either 6 | #' a data.frame or a chatlog object. 7 | #' 8 | #' @param msgs A chatlog object or a data.frame containing the messages to be 9 | #' added to the chat log. 10 | #' @param chatlog_id The id of the chatlog object. Required when the provided 11 | #' msgs is a data.frame. 12 | #' 13 | #' @return The updated chatlog object with the newly added messages. 14 | #' @author Ulrich Matter umatter@protonmail.com 15 | #' @examples 16 | #' \dontrun{ 17 | #' # Add a data frame of messages to an existing chat log 18 | #' chatlog_df <- data.frame( 19 | #' user = c("user1", "user2"), 20 | #' message = c("Hello!", "Hi!") 21 | #' ) 22 | #' updated_chatlog <- add_to_chatlog(chatlog_df, "existing_chatlog_id") 23 | #' 24 | #' # Add messages from one chat log to another 25 | #' chatlog1 <- create_chatlog("chatlog1") 26 | #' chatlog2 <- create_chatlog("chatlog2") 27 | #' chatlog1 <- add_message(chatlog1, "user1", "Hello!") 28 | #' chatlog2 <- add_message(chatlog2, "user2", "Hi!") 29 | #' merged_chatlog <- add_to_chatlog(chatlog1, chatlog2@chatlog_id) 30 | #' } 31 | #' @export 32 | add_to_chatlog <- function(msgs, chatlog_id = NULL) { 33 | 34 | if (is.data.frame(msgs) & !is.null(chatlog_id)) { 35 | 36 | # make sure latest state of log is used 37 | current <- get_chatlog(chatlog_id) 38 | # update the chatlog 39 | current@messages <- dplyr::bind_rows(current@messages, 40 | msgs) 41 | assign(chatlog_id, current, envir = OpenAIR_env) 42 | 43 | return(current) 44 | } 45 | 46 | if (is_chatlog(msgs)){ 47 | 48 | # make sure latest state of log is used 49 | current <- get_chatlog(msgs@chatlog_id) 50 | # update the chatlog 51 | current@messages <- dplyr::bind_rows(current@messages, 52 | msgs@messages) 53 | assign(chatlog_id, current, envir = OpenAIR_env) 54 | 55 | return(current) 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /R/chat.R: -------------------------------------------------------------------------------- 1 | #' Start or continue a chat conversation 2 | #' 3 | #' This function starts or continues a chat conversation by adding the user's 4 | #' message to the conversation. 5 | #' If the conversation does not exist, a new one will be initiated. The response 6 | #' can be displayed in the 7 | #' console, returned as a character vector, or returned as a full response 8 | #' object from the ChatGPT API. 9 | #' 10 | #' @param message A character string representing the message to be added to the 11 | #' chat conversation. 12 | #' @param chatlog_id A character string representing the ID of the chat 13 | #' conversation to start or continue. Default is ".__CURRENTCHAT__". 14 | #' @param output A character string indicating the output format of the 15 | #' response. Default is "message_to_console". Valid options are 16 | #' "message_to_console", "message", or "response_object". 17 | #' @param ... Additional arguments to pass to the chat_completion() function. 18 | #' @author Ulrich Matter umatter@protonmail.com 19 | #' 20 | #' @return Depending on the value of the 'output' argument, this function 21 | #' returns one of the following: 22 | #' * "message_to_console": a message containing the response text is printed to 23 | #' the console (default). 24 | #' * "message": the response text as a character vector. 25 | #' * "response_object": the full response object from the ChatGPT API. 26 | #' 27 | #' @examples 28 | #' \dontrun{ 29 | #' # Start a new chat and print the response to the console 30 | #' chat("What's the weather like today?") 31 | #' 32 | #' # Continue the chat, but return the response as a character vector 33 | #' response_text <- chat("What about tomorrow's weather?", output = "message") 34 | #' } 35 | #' @export 36 | 37 | 38 | chat <- function(message, chatlog_id = ".__CURRENTCHAT__", 39 | output = "message_to_console", ...) { 40 | 41 | # check input validity 42 | if (!output %in% c("message_to_console", "message", "response_object")) { 43 | stop(paste0("Argument output needs to be one of 'message_to_console', ", 44 | "'message', or 'response_object")) 45 | } 46 | 47 | # check if chat is ongoing 48 | # if not, initiate new chat 49 | if (!exists(chatlog_id, envir = OpenAIR_env)) { 50 | # initialize chatlog 51 | cl <- start_chat(chatlog_id = chatlog_id) 52 | 53 | } else { 54 | # fetch current chat status 55 | cl <- get_chatlog(chatlog_id) 56 | 57 | } 58 | 59 | # add new message to conversation, send 60 | resp <- 61 | initialize_messages(initial_role = "user", initial_content = message) %>% 62 | add_to_chatlog(chatlog_id) %>% 63 | chat_completion(...) 64 | 65 | # update chatlog 66 | resp %>% 67 | messages() %>% 68 | add_to_chatlog(chatlog_id) 69 | 70 | if (output == "message_to_console") { 71 | # process response 72 | messages <- 73 | resp %>% 74 | messages() 75 | 76 | # show response message in console 77 | resp_parts <- parse_response(messages$content) 78 | 79 | for (i in 1:length(resp_parts)){ 80 | part <- resp_parts[[i]] 81 | if (part$type == "text") { 82 | cli::cli_text(part$content) 83 | cli::cli_text() 84 | } else { 85 | cli::cli_code(part$content) 86 | cli::cli_text() 87 | } 88 | } 89 | } 90 | 91 | if (output == "message") { 92 | # process response 93 | messages <- 94 | resp %>% 95 | messages() 96 | 97 | return(messages$content) 98 | 99 | } 100 | 101 | if (output == "response_object") { 102 | # return full response object 103 | return(resp) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /R/class.R: -------------------------------------------------------------------------------- 1 | #' chatlog class 2 | #' 3 | #' @slot messages The message data of the object 4 | #' @slot chatlog_id The chatlog's ID 5 | #' @export 6 | setClass("chatlog", slots = list(messages = "data.frame", 7 | chatlog_id = "character")) 8 | -------------------------------------------------------------------------------- /R/clean_output.R: -------------------------------------------------------------------------------- 1 | #' Clean Output From Code Responses 2 | #' 3 | #' This function extracts the content from a given text string that is enclosed 4 | #' between the '```' markers. It can be used to extract any kind of code or text 5 | #' content. 6 | #' 7 | #' @param text A character string containing the code or text content with 8 | #' '```' markers. 9 | #' 10 | #' @return A character string containing the extracted code or text content. 11 | #' @author Ulrich Matter umatter@protonmail.com 12 | #' @export 13 | #' @examples 14 | #' code_text <- "``` 15 | #' example_code <- function(x) { 16 | #' return(x * 2) 17 | #' } 18 | #'```" 19 | #' clean_output(code_text) 20 | 21 | clean_output <- function(text) { 22 | # Define the pattern with the (?s) flag for dot-matching newline characters 23 | pattern <- "(?s)```(.*?)```" 24 | 25 | # Match the pattern using gregexpr and extract the content 26 | matches <- gregexpr(pattern, text, perl = TRUE) 27 | 28 | # Check if there's a match 29 | if (length(matches[[1]]) > 0 && matches[[1]][1] != -1) { 30 | content <- regmatches(text, matches)[[1]] 31 | 32 | # Remove the '```' markers from the content 33 | cleaned_content <- gsub("^[a-zA-Z]*(```)", "", content) 34 | cleaned_content <- gsub("(```)", "", cleaned_content) 35 | cleaned_content <- gsub("\\{[a-zA-Z]*\\}", "", cleaned_content) 36 | 37 | return(cleaned_content) 38 | } else { 39 | # If there's no match, return the original text 40 | return(text) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /R/clear_chatlog.R: -------------------------------------------------------------------------------- 1 | 2 | #' Clear a chat log 3 | #' 4 | #' This function clears a chat log, leaving only the initial (system) message. 5 | #' 6 | #' @param chatlog_id character string indicating the name of the chat log to 7 | #' clear. 8 | #' Default is ".__CURRENTCHAT__". 9 | #' @return This function does not return anything. 10 | #' @author Ulrich Matter umatter@protonmail.com 11 | #' @export 12 | #' @examples 13 | #' \dontrun{ 14 | #' # Clear the current chat log 15 | #' clear_chatlog() 16 | #' } 17 | clear_chatlog <- function(chatlog_id = ".__CURRENTCHAT__") { 18 | # get the current chatlog 19 | current <- get_chatlog(chatlog_id) 20 | # remove all but the initial (system) message 21 | current@messages <- current@messages[1, ] 22 | assign(chatlog_id, current, envir = OpenAIR_env) 23 | } 24 | -------------------------------------------------------------------------------- /R/contains_r_func.R: -------------------------------------------------------------------------------- 1 | #' Check if a text file or character string contains an R function definition 2 | #' 3 | #' This function parses a text file or a character string and returns TRUE if it 4 | #' contains 5 | #' a valid R function definition. It uses a regex pattern to identify 6 | #' possible R function definitions and then attempts to parse the matched 7 | #' lines as R code. 8 | #' 9 | #' @param input A character string specifying the path to the text file, or a 10 | #' character 11 | #' string containing the text to be checked for an R function definition. 12 | #' @return A logical value (TRUE or FALSE) indicating whether the input 13 | #' contains a valid R function definition. 14 | #' @export 15 | #' @examples 16 | #' # Create a temporary file with an R function definition 17 | #' temp_file <- tempfile(fileext = ".R") 18 | #' writeLines("example_function <- function(x) {\n return(x * 2)\n}", 19 | #' temp_file) 20 | #' 21 | #' # Check if the temporary file contains an R function definition 22 | #' result <- contains_r_func(temp_file) 23 | #' print(result) # Should print TRUE 24 | #' 25 | #' # Check if a character string contains an R function definition 26 | #' result <- contains_r_func( 27 | #' "example_function <- function(x) { return(x * 2) }") 28 | #' print(result) # Should print TRUE 29 | #' 30 | #' # Remove the temporary file 31 | #' file.remove(temp_file) 32 | contains_r_func <- function(input) { 33 | # Check if the input is a file path or a character string 34 | is_file <- file.exists(input) 35 | 36 | # Read the lines 37 | lines <- if (is_file) readLines(input) else strsplit(input, 38 | split = "\\n")[[1]] 39 | 40 | # Define the regex pattern to identify an R function definition 41 | pattern <- "^\\s*\\w+\\s*<-\\s*function\\s*\\(" 42 | 43 | # Check if any line in the input contains a function definition 44 | match_indices <- which(sapply(lines, 45 | function(line) grepl(pattern, line, perl = TRUE))) 46 | 47 | # If no match is found, return FALSE 48 | if (length(match_indices) == 0) { 49 | return(FALSE) 50 | } 51 | 52 | # Otherwise, check if the matched code is valid R code 53 | for (i in match_indices) { 54 | # Extract the function definition and save it as a temporary file 55 | func_def <- lines[i:(i + 1)] 56 | temp_file <- tempfile(fileext = ".R") 57 | writeLines(func_def, temp_file) 58 | 59 | # Attempt to parse the temporary file 60 | error_occurred <- FALSE 61 | tryCatch({ 62 | parse(file = temp_file) 63 | }, error = function(e) { 64 | error_occurred <- TRUE 65 | }) 66 | 67 | # Remove the temporary file 68 | file.remove(temp_file) 69 | 70 | # If parsing succeeded, return TRUE 71 | if (!error_occurred) { 72 | return(TRUE) 73 | } 74 | } 75 | 76 | # If none of the matched lines were valid R code, return FALSE 77 | return(FALSE) 78 | } 79 | -------------------------------------------------------------------------------- /R/contains_roxygen.R: -------------------------------------------------------------------------------- 1 | #' Check if a text file or character string contains Roxygen2 documentation 2 | #' 3 | #' This function parses a text file or a character string and returns TRUE if it 4 | #' contains 5 | #' Roxygen2 documentation. It uses a regex pattern to identify 6 | #' possible Roxygen2 documentation lines. 7 | #' 8 | #' @param input A character string specifying the path to the text file, or a 9 | #' character 10 | #' string containing the text to be checked for Roxygen2 documentation. 11 | #' @return A logical value (TRUE or FALSE) indicating whether the input 12 | #' contains Roxygen2 documentation. 13 | #' @export 14 | contains_roxygen <- function(input) { 15 | # Check if the input is a file path or a character string 16 | is_file <- file.exists(input) 17 | 18 | # Read the lines 19 | lines <- if (is_file) readLines(input) else strsplit(input, 20 | split = "\\n")[[1]] 21 | 22 | # Define the regex pattern to identify Roxygen2 documentation 23 | pattern <- "^#'" 24 | 25 | # Check if any line in the input contains Roxygen2 documentation 26 | result <- any(sapply(lines, function(line) grepl(pattern, line, perl = TRUE))) 27 | 28 | return(result) 29 | } 30 | -------------------------------------------------------------------------------- /R/count_tokens.R: -------------------------------------------------------------------------------- 1 | #' Count the number of tokens in a text string 2 | #' 3 | #' This function takes a file path, URL or character string as input and 4 | #' returns the number of tokens in the text. Tokens are defined as words and/or 5 | #' special characters. 6 | #' 7 | #' @param text A file path, URL or character string representing the text to be 8 | #' tokenized. 9 | #' 10 | #' @return An integer representing the number of tokens in the text. 11 | #' 12 | #' @examples 13 | #' \dontrun{ 14 | #' # Example 1: File path 15 | #' test_file_path <- tempfile() 16 | #' writeLines("This is a test.", test_file_path) 17 | #' expect_equal(count_tokens(test_file_path), 5) 18 | #' file.remove(test_file_path) 19 | #' 20 | #' # Example 2: URL 21 | #' url <- "https://www.gutenberg.org/files/2701/2701-0.txt" 22 | #' count_tokens(url) 23 | #' 24 | #' # Example 3: Character string 25 | #' text <- "This is a test string." 26 | #' count_tokens(text) 27 | #' } 28 | #' 29 | #' @importFrom stringi stri_split_regex 30 | #' @importFrom httr GET content 31 | #' @importFrom R.utils isUrl 32 | #' @importFrom data.table data.table .N 33 | #' 34 | #' @export 35 | count_tokens <- function(text) { 36 | 37 | # Check if input is a file path 38 | if (is.character(text) && file.exists(text)) { 39 | text_string <- readLines(text, warn = FALSE) 40 | 41 | # Check if input is a URL 42 | } else if (isUrl(text)) { 43 | response <- GET(text) 44 | text_string <- content(response, "text") 45 | 46 | # Check if input is a character string 47 | } else if (is.character(text)) { 48 | text_string <- text 49 | 50 | # If input is not valid, return an error message 51 | } else { 52 | stop("Input must be a file path, a valid URL, or a character string.") 53 | } 54 | 55 | # Tokenize the text 56 | tokens <- stri_split_regex(text_string, "\\s+|(?=\\W)|(?<=\\W)") 57 | tokens <- unlist(tokens) 58 | 59 | # Remove empty and whitespace-only tokens 60 | tokens <- tokens[tokens != "" & !grepl("^\\s+$", tokens)] 61 | 62 | # Count the number of non-empty tokens using data.table package 63 | tokens_dt <- data.table(tokens) 64 | num_tokens <- tokens_dt[, .N, by = NULL][[1]] 65 | 66 | return(num_tokens) 67 | } 68 | -------------------------------------------------------------------------------- /R/created.R: -------------------------------------------------------------------------------- 1 | #' Extract Created DateTime from OpenAI API response 2 | #' 3 | #' This function extracts the date-time string of when the response was created 4 | #' from the parsed HTTP response of an API call to the 5 | #' OpenAI chat completions endpoint. 6 | #' 7 | #' @param response a list object representing the HTTP response 8 | #' @return a Date object representing the date-time string of when the response 9 | #' was created 10 | #' 11 | #' @author Ulrich Matter umatter@protonmail.com 12 | #' @export 13 | #' 14 | created <- function(response) { 15 | # Check if the response is a list 16 | if (!is.list(response)) { 17 | stop("Invalid response format. Expected list object.") 18 | } 19 | 20 | # Extract the created date-time integer from the response 21 | datetime <- response$created 22 | # Check if the ID is a character integer 23 | if (!is.integer(datetime)) { 24 | stop("Invalid response format. created must be an integer.") 25 | } 26 | # Convert to more user-friendly Date() 27 | datetime <- lubridate::as_datetime(datetime) 28 | 29 | # Return the ID 30 | return(datetime) 31 | } 32 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Essay on How Donald Trump Became President of the United States 2 | #' 3 | #' This dataset contains an essay describing how Donald Trump became the 45th 4 | #' President of the United States in 2016. The essay is written in the style of 5 | #' Mark Twain, a famous American writer known for his satirical and humorous 6 | #' style. 7 | #' 8 | #' @format ## `trump` 9 | #' A character string. 10 | #' @source This essay was written by a language model trained by OpenAI. 11 | #' 12 | "trump" 13 | 14 | 15 | 16 | #' Input: message content template for extract_entities() 17 | #' 18 | #' This message content serves as user input for the extract_entities function. 19 | #' 20 | #' @format ## `extract_entities_prompt` 21 | #' A data frame with 2 rows and 2 columns representing the messages object in 22 | #' API calls. 23 | #' @source Contributed by umatter 24 | #' 25 | "extract_entities_prompt" 26 | 27 | 28 | #' Input: message content template for references_to_bibtex() 29 | #' 30 | #' This message content serves as user input for the references_to_bibtex 31 | #' function. 32 | #' 33 | #' @format ## `references_to_bibtex_prompt` 34 | #' A data frame with 4 rows and 2 columns representing the messages object in 35 | #' API calls. 36 | #' @source Contributed by umatter 37 | #' 38 | "references_to_bibtex_prompt" 39 | 40 | 41 | #' Input: message content template for add_roxygen() 42 | #' 43 | #' This message content serves as user input for the add_roxygen function. 44 | #' 45 | #' @format ## `add_roxygen_prompt` 46 | #' A data frame with 2 rows and 2 columns representing the messages object in 47 | #' API calls. 48 | #' @source Contributed by umatter 49 | #' 50 | "add_roxygen_prompt" 51 | 52 | 53 | #' Input: message content template for write_test() 54 | #' 55 | #' This message content serves as user input for the write_test function. 56 | #' 57 | #' @format ## `write_test_prompt` 58 | #' A data frame with 2 rows and 2 columns representing the messages object in 59 | #' API calls. 60 | #' @source Contributed by umatter 61 | #' 62 | "write_test_prompt" 63 | 64 | 65 | #' Input: message content template for r_to_python() 66 | #' 67 | #' This message content serves as user input for the r_to_python() function. 68 | #' 69 | #' @format ## `r_to_python_prompt` 70 | #' A data frame with 2 rows and 2 columns representing the messages object in 71 | #' API calls. 72 | #' @source Contributed by umatter 73 | #' 74 | "r_to_python_prompt" 75 | 76 | 77 | #' Input: message content template for python_to_r() 78 | #' 79 | #' This message content serves as user input for the python_to_r() function. 80 | #' 81 | #' @format ## `python_to_r_prompt` 82 | #' A data frame with 2 rows and 2 columns representing the messages object in 83 | #' API calls. 84 | #' @source Contributed by umatter 85 | #' 86 | "python_to_r_prompt" 87 | 88 | 89 | #' Input: message content template for java_to_r() 90 | #' 91 | #' This message content serves as user input for the java_to_r() function. 92 | #' 93 | #' @format ## `java_to_r_prompt` 94 | #' A data frame with 2 rows and 2 columns representing the messages object in 95 | #' API calls. 96 | #' @source Contributed by umatter 97 | #' 98 | "java_to_r_prompt" 99 | 100 | #' Input: message content template for nested_to_pipe() 101 | #' 102 | #' This message content serves as user input for the nested_to_pipe() function. 103 | #' 104 | #' @format ## `nested_to_pipe_prompt` 105 | #' A data frame with 4 rows and 2 columns representing the messages object in 106 | #' API calls. 107 | #' @source Contributed by umatter 108 | #' 109 | "nested_to_pipe_prompt" 110 | 111 | 112 | #' Input: message content template for refactor() 113 | #' 114 | #' This message content serves as user input for the refactor() function. 115 | #' 116 | #' @format ## `nested_to_pipe_prompt` 117 | #' A data frame with 2 rows and 2 columns representing the messages object in 118 | #' API calls. 119 | #' @source Contributed by umatter 120 | #' 121 | "refactor_prompt" -------------------------------------------------------------------------------- /R/df_to_csv.R: -------------------------------------------------------------------------------- 1 | #' Convert a data.frame to a CSV-formatted character string 2 | #' 3 | #' The `df_to_csv` function takes a data.frame as input and returns a character 4 | #' string representing the content of the original data.frame formatted as a CSV 5 | #' file. 6 | #' The resulting CSV-formatted string can be written to a file or further 7 | #' processed 8 | #' as needed. 9 | #' 10 | #' @param df A data.frame to be converted to a CSV-formatted character string. 11 | #' @return A character string representing the data values in the input 12 | #' data.frame 13 | #' formatted as a CSV file. 14 | #' @export 15 | #' @examples 16 | #' # Create a data.frame 17 | #' example_data <- data.frame( 18 | #' Name = c("Alice", "Bob", "Carol"), 19 | #' Age = c(30, 25, 28), 20 | #' Height = c(168, 175, 162), 21 | #' stringsAsFactors = FALSE 22 | #' ) 23 | #' 24 | #' # Convert the data.frame to a CSV-formatted character string 25 | #' csv_string <- df_to_csv(example_data) 26 | #' cat(csv_string) 27 | df_to_csv <- function(df) { 28 | 29 | requireNamespace("utils", quietly = TRUE) 30 | 31 | if (!is.data.frame(df)){ 32 | stop("df must be an object of class data.frame") 33 | } 34 | # Convert the data.frame to a CSV-formatted character string using write.csv 35 | output <- tempfile(fileext = ".csv") 36 | utils::write.csv(df, file = output, row.names = FALSE) 37 | 38 | # Read the CSV file content and store it in a character string 39 | csv_string <- paste(readLines(output), collapse = "\n") 40 | 41 | # Remove the temporary file 42 | file.remove(output) 43 | 44 | return(csv_string) 45 | } 46 | -------------------------------------------------------------------------------- /R/extract_blocks.R: -------------------------------------------------------------------------------- 1 | #' Extract blocks of a specified type from a list of blocks 2 | #' 3 | #' @param block_list A list of blocks 4 | #' @param block_type The type of blocks to be extracted 5 | #' 6 | #' @return A list of blocks of the specified type 7 | #' 8 | #' @author Jonathan Chassot 9 | #' 10 | #' 11 | #' @examples 12 | #' \dontrun{ 13 | #' # Example 1: Extract 'code' blocks 14 | #' blocks <- list( 15 | #' list(type = "text", content = "Hello world!"), 16 | #' list(type = "code", content = "print('Hello world!')") 17 | #' ) 18 | #' extract_blocks(blocks, "code") 19 | #' # Output: 20 | #' # [[1]] 21 | #' # $type 22 | #' # [1] "code" 23 | #' # 24 | #' # $content 25 | #' # [1] "print('Hello world!')" 26 | #' 27 | #' # Example 2: Extract 'text' blocks 28 | #' blocks <- list( 29 | #' list(type = "text", content = "Hello world!"), 30 | #' list(type = "code", content = "print('Hello world!')") 31 | #' ) 32 | #' extract_blocks(blocks, "text") 33 | #' # Output: 34 | #' # [[1]] 35 | #' # $type 36 | #' # [1] "text" 37 | #' # 38 | #' # $content 39 | #' # [1] "Hello world!" 40 | #' } 41 | #' @export 42 | extract_blocks <- function(block_list, block_type) { 43 | # Extract the blocks of the specified type 44 | blocks <- lapply(block_list, function(x) { 45 | if (x$type == block_type) { 46 | x 47 | } else { 48 | NULL 49 | } 50 | }) 51 | # Remove the NULL elements 52 | blocks <- blocks[!sapply(blocks, is.null)] 53 | # Return the blocks 54 | return(blocks) 55 | } 56 | -------------------------------------------------------------------------------- /R/extract_blocks_content.R: -------------------------------------------------------------------------------- 1 | #' Extract the content parts of blocks 2 | #' 3 | #' This function takes a list of blocks and returns a list of their content 4 | #' parts. 5 | #' 6 | #' @param block_list A list of blocks to extract the content from 7 | #' @return A list of content parts 8 | #' @export 9 | extract_blocks_content <- function(block_list) { 10 | # Extract the content parts 11 | contents <- lapply(block_list, function(x) { 12 | x$content 13 | }) 14 | # Remove the NULL elements 15 | contents <- contents[!sapply(contents, is.null)] 16 | # Return the blocks 17 | return(contents) 18 | } -------------------------------------------------------------------------------- /R/extract_entities.R: -------------------------------------------------------------------------------- 1 | #' Extract Entities from a Text 2 | #' 3 | #' This function takes a character string or a path to a text file and returns 4 | #' a tibble describing the entities found in the text. The type of entities to 5 | #' be searched for and extracted can be defined by the user. 6 | #' 7 | #' @param text A character string containing the text to be processed, or a path 8 | #' to a text file 9 | #' @param entity_types A character vector containing names of entity types to 10 | #' be extracted. Defaults to c("locations", "persons", "organizations"). 11 | #' @param batch_size An integer indicating the size of each batch, if the text 12 | #' input is supposed to be processed in batches. Set this to NULL to process all 13 | #' at once. 14 | #' @param ... Additional arguments to pass to the chat_completion() function. 15 | #' 16 | #' @return A tibble 17 | #' @author Ulrich Matter umatter@protonmail.com 18 | #' @examples 19 | #' \dontrun{ 20 | #' extract_entities("Hello, how are you?") 21 | #' extract_entities("path/to/text/file.txt", batch_size = 100) 22 | #' } 23 | #' 24 | #' @export 25 | extract_entities <- function(text, entity_types=c("locations", "persons", 26 | "organizations"), batch_size = NULL, ...) { 27 | 28 | requireNamespace("dplyr", quietly = TRUE) 29 | if (is.null(batch_size)) { 30 | # process the entire text at once 31 | # import, process text 32 | text <- 33 | read_text(text)$text %>% 34 | paste0(collapse = "\n") 35 | } else { 36 | text <- 37 | read_text_batches(text, batch_size = batch_size) %>% 38 | lapply(FUN = function(x) paste0(x$text, collapse = "")) 39 | } 40 | 41 | results_list <- 42 | lapply(text, FUN = function(tbatch) { 43 | 44 | # initial user input 45 | entity_types <- paste0(entity_types, collapse = ", ") 46 | extract_entities_prompt$content[2] <- sprintf(fmt = 47 | extract_entities_prompt$content[2], entity_types, text) 48 | 49 | # chat 50 | cli::cli_alert_info("Entity extraction in progress. Hold on tight!") 51 | resp <- chat_completion(extract_entities_prompt, ...) 52 | total_tokens_used <- usage(resp)$total_tokens 53 | info_token <- paste0("Total tokens used: ", total_tokens_used) 54 | cli::cli_inform(info_token) 55 | 56 | # process response 57 | msg_resp <- messages(resp) 58 | entities <- readr::read_csv(msg_resp$content) 59 | 60 | return(entities) 61 | }) 62 | 63 | # stack results 64 | entities_df <- dplyr::bind_rows(results_list) 65 | 66 | # Return the processed text 67 | return(entities_df) 68 | } -------------------------------------------------------------------------------- /R/extract_r_code.R: -------------------------------------------------------------------------------- 1 | #' Extract R code and comments from a given input string. 2 | #' 3 | #' This function takes an input string, detects R code and comments, and returns 4 | #' a character vector containing the R code and comments. The input string is 5 | #' split into lines based on newline characters, and each line is examined for R 6 | #' code and comment patterns. Only the lines that match either of these patterns 7 | #' are returned. 8 | #' 9 | #' @param input_string A character string containing R code and comments, mixed 10 | #' with other text. The string may contain multiple lines separated by newline 11 | #' characters. 12 | #' 13 | #' @return A character vector containing R code and comment lines extracted from 14 | #' the input string. Each element in the vector corresponds to one line of code 15 | #' or a comment. 16 | #' @export 17 | #' 18 | #' @examples 19 | #' example_string <- 20 | #' "This is a text string with R code and comments.\n 21 | #' # A comment\n 22 | #' x <- 5\ 23 | #' ny = 10\n 24 | #' z <- x + y\n 25 | #' Another line of text." 26 | #' extract_r_code(example_string) 27 | extract_r_code <- function(input_string) { 28 | 29 | # Split the input string into lines based on newline characters 30 | lines <- strsplit(input_string, "\n")[[1]] 31 | 32 | # Define a regular expression pattern to detect R code and comments 33 | r_code_pattern <- "^\\s*[^#\\s].*(<-|=|\\().*$" 34 | r_comment_pattern <- "^\\s*#.*$" 35 | 36 | # Initialize an empty vector to store the lines containing R code and comments 37 | # Iterate over each line to identify R code and comment lines 38 | r_code_and_comment_lines <- character(0) 39 | for (line in lines) { 40 | if (grepl(r_code_pattern, line) | grepl(r_comment_pattern, line)) { 41 | r_code_and_comment_lines <- c(r_code_and_comment_lines, line) 42 | } 43 | } 44 | 45 | # Return the R code and comment lines 46 | return(r_code_and_comment_lines) 47 | } 48 | -------------------------------------------------------------------------------- /R/extract_roxygen2.R: -------------------------------------------------------------------------------- 1 | #' Extract roxygen2 documentation lines from a function definition 2 | #' 3 | #' This function takes a character vector containing the lines of a function 4 | #' definition and returns a character string containing only the lines 5 | #' belonging to the roxygen2 documentation (lines starting with "#'"). 6 | #' 7 | #' @param func_def A character vector containing the lines of a function 8 | #' definition 9 | #' @return A character string containing the roxygen2 documentation lines 10 | #' @export 11 | #' @examples 12 | #' func_def <- c( 13 | #' "#' Extracts object from a response list", 14 | #' "#'", 15 | #' "#' @export", 16 | #' "object <- function(response) {", 17 | #' " if (!is.list(response)) {", 18 | #' " stop('Invalid response format. Expected list object.')", 19 | #' " }", 20 | #' "}") 21 | #' 22 | #' roxygen2_docu <- extract_roxygen2(func_def) 23 | #' print(roxygen2_docu) 24 | extract_roxygen2 <- function(func_def) { 25 | 26 | func_def <- strsplit(func_def, split = "\\n")[[1]] 27 | roxygen2_lines <- grep("^#'", func_def, value = TRUE) 28 | roxygen2_docu <- paste(roxygen2_lines, collapse = "\n") 29 | 30 | return(roxygen2_docu) 31 | } 32 | -------------------------------------------------------------------------------- /R/get_chatlog.R: -------------------------------------------------------------------------------- 1 | #' Get the current chatlog 2 | #' 3 | #' This function extracts the current chatlog of a given chat from the chat 4 | #' environment. 5 | #' 6 | #' @param x either a chatlog object r, or a character string representing the id 7 | #' of a chatlog (the default is ".__CURRENTCHAT__", the current log of the 8 | #' chat()-function) 9 | #' @return a chatlog object 10 | #' 11 | #' @author Ulrich Matter umatter@protonmail.com 12 | #' 13 | #' @export 14 | get_chatlog <- function(x = ".__CURRENTCHAT__") { 15 | 16 | # verify type of input to extract chatlog (needs to be improved) 17 | if (is_chatlog(x)) { 18 | chatlog_id <- x@chatlog_id 19 | } else { 20 | chatlog_id <- x 21 | } 22 | 23 | # Extract the choices from the response 24 | clog <- get(chatlog_id, envir = OpenAIR_env) 25 | 26 | # Return the choices 27 | return(clog) 28 | } 29 | -------------------------------------------------------------------------------- /R/grapes_c_grapes.R: -------------------------------------------------------------------------------- 1 | #' Send a message to ChatGPT and assign the response to a variable 2 | #' 3 | #' This function sends a message to the ChatGPT API using the 'chat()' function 4 | #' and returns the response in the specified output format. 5 | #' 6 | #' @param message A character string containing the message to be sent to the 7 | #' ChatGPT API. 8 | #' @param output A character string specifying the output format. Valid options 9 | #' are "message_to_console", "message", or "response_object". Default is 10 | #' "message_to_console". 11 | #' 12 | #' @return Depending on the value of the 'output' argument, this function 13 | #' returns one of the following: 14 | #' * "message_to_console": a message containing the response text to be 15 | #' printed to the console. 16 | #' * "message": the response text as a character vector. 17 | #' * "response_object": the full response object from the ChatGPT API. 18 | #' 19 | #' @author Ulrich Matter umatter@protonmail.com 20 | #' @export 21 | #' 22 | #' @examples 23 | #' \dontrun{ 24 | #' # Send a message and assign the response to a variable 25 | #' response_var <- "Hello, ChatGPT!" %c% "message" 26 | #' 27 | #' # Print the response 28 | #' print(response_var) 29 | #' 30 | #' # Send a message and return the full response object 31 | #' response_obj <- "Hello, ChatGPT!" %c% "response_object" 32 | #' 33 | #' # Print the response 34 | #' print(response_obj) 35 | #'} 36 | `%c%` <- function(message, output) { 37 | # send message to ChatGPT and return the response 38 | chat(message = message, output = output) 39 | } 40 | -------------------------------------------------------------------------------- /R/id.R: -------------------------------------------------------------------------------- 1 | #' Extract ID from OpenAI API response 2 | #' 3 | #' This function extracts the ID from the parsed HTTP response of an API call 4 | #' to the OpenAI chat completions endpoint. 5 | #' 6 | #' @param response a list object representing the HTTP response 7 | #' @return a character string representing the ID from the response 8 | #' 9 | #' @author Ulrich Matter umatter@protonmail.com 10 | #' @export 11 | #' 12 | #' 13 | id <- function(response) { 14 | # Check if the response is a list 15 | if (!is.list(response)) { 16 | stop("Invalid response format. Expected list object.") 17 | } 18 | 19 | # Extract the ID from the response 20 | id <- response$id 21 | 22 | # Check if the ID is a character string 23 | if (!is.character(id)) { 24 | stop("Invalid response format. ID must be a character string.") 25 | } 26 | 27 | # Return the ID 28 | return(id) 29 | } 30 | -------------------------------------------------------------------------------- /R/initialize_messages.R: -------------------------------------------------------------------------------- 1 | #' Initialize a new messages object for OpenAI API chat completions 2 | #' 3 | #' This function initializes a new messages object as a template for messages 4 | #' sent to the OpenAI API https://api.openai.com/v1/chat/completions endpoint. 5 | #' By default, the template contains a single message from the system to the 6 | #' user with the initial content "You are a helpful assistant.", but you can 7 | #' customize the content by specifying a different value for the 8 | #' "initial_system_content" parameter. 9 | #' 10 | #' @param initial_role A character string representing the role issueing the 11 | #' initial content (per default: "system") 12 | #' @param initial_content A character string representing the initial message 13 | #' from the system 14 | #' 15 | #' @return A data frame containing a single message from the system to the user, 16 | #' with columns for the 17 | #' message role and content. 18 | #' @author Ulrich Matter umatter@protonmail.com 19 | #' @examples 20 | #' messages <- initialize_messages() 21 | #' messages_custom <- initialize_messages("Hello! How can I assist you today?") 22 | #' 23 | #' @export 24 | 25 | initialize_messages <- function(initial_role = "system", 26 | initial_content = "You are a helpful assistant.") { 27 | # Create a new data frame with the message 28 | messages <- data.frame(role = initial_role, 29 | content = initial_content) 30 | 31 | # Return the resulting data frame 32 | return(messages) 33 | } 34 | -------------------------------------------------------------------------------- /R/install_tiktoken.R: -------------------------------------------------------------------------------- 1 | #' Install the tiktoken Python package 2 | #' 3 | #' This function installs the tiktoken Python package using the specified 4 | #' installation method and Conda environment (if any). 5 | #' 6 | #' @param method The installation method to use. Can be one of "auto" (default), 7 | #' "conda", "virtualenv", "pip", or "windows". 8 | #' @param conda The name or path of the Conda environment to use for the 9 | #' installation, or "auto" (default) to let reticulate automatically manage the 10 | #' environment. 11 | #' 12 | #' @importFrom reticulate py_install 13 | install_tiktoken <- function(method = "auto", conda = "auto") { 14 | reticulate::py_install("tiktoken", method = method, conda = conda) 15 | } 16 | -------------------------------------------------------------------------------- /R/is_chaglog.R: -------------------------------------------------------------------------------- 1 | 2 | #' Determine if an object is a chatlog 3 | #' 4 | #' This function checks if an object is of class "chatlog". 5 | #' 6 | #' @param object An R object to check 7 | #' @return TRUE if the object is of class "chatlog", FALSE otherwise 8 | #' @author Ulrich Matter umatter@protonmail.com 9 | #' @export 10 | #' @examples 11 | #' is_chatlog("Hello, World!") 12 | #' # [1] FALSE 13 | #' 14 | #' chat <- new("chatlog") 15 | #' is_chatlog(chat) 16 | #' # [1] TRUE 17 | is_chatlog <- function(object) { 18 | return(class(object)[1] == "chatlog") 19 | } 20 | -------------------------------------------------------------------------------- /R/is_json.R: -------------------------------------------------------------------------------- 1 | #' Check if the provided string is in valid JSON format. 2 | #' 3 | #' @param input_string A character string to be checked for JSON format. 4 | #' 5 | #' @return A logical value. If the input string is in valid JSON format, returns 6 | #' TRUE, otherwise returns FALSE. 7 | #' 8 | #' @author Ulrich Matter umatter@protonmail.com 9 | #' 10 | #' @examples 11 | #' is_json('{"name": "John", "age": 30}') 12 | #' # TRUE 13 | #' 14 | #' is_json('{"name": "John", age: 30}') 15 | #' # FALSE 16 | #' 17 | #' is_json('') 18 | #' # FALSE 19 | #' @export 20 | is_json <- function(input_string) { 21 | 22 | if (!is.character(input_string)) { 23 | warning("Input is not a character string.") 24 | return(FALSE) 25 | } 26 | 27 | if (nchar(input_string) == 0) { 28 | message("Empty string provided.") 29 | return(FALSE) 30 | } 31 | 32 | tryCatch({ 33 | jsonlite::fromJSON(input_string, simplifyVector = FALSE) 34 | return(TRUE) 35 | }, error = function(e) { 36 | return(FALSE) 37 | }) 38 | } -------------------------------------------------------------------------------- /R/is_python.R: -------------------------------------------------------------------------------- 1 | #' Check if a Character String Contains Valid Python Code 2 | #' 3 | #' This function takes a character string as input and checks if it contains 4 | #' valid Python code. It returns TRUE if the string contains valid Python code, 5 | #' and FALSE otherwise. 6 | #' 7 | #' @param code A character string containing code to be checked for Python code 8 | #' validity. 9 | #' 10 | #' @return A logical value: TRUE if the input character string contains valid 11 | #' Python code, and FALSE otherwise. 12 | #' @details This function presuposes that python is installed on the system. 13 | #' @examples 14 | #' \dontrun{ 15 | #' # Check if the string contains valid Python code 16 | #' is_python("print('Hello, World!')") 17 | #' 18 | #' # Check if the string contains invalid Python code 19 | #' is_python("prit('Hello, World!')") 20 | #'} 21 | #' @export 22 | #' 23 | is_python <- function(code) { 24 | # Write the input code to a temporary file 25 | temp_file <- tempfile(fileext = ".py") 26 | writeLines(code, temp_file) 27 | 28 | # Redirect the output to a temporary file 29 | temp_stdout <- tempfile() 30 | temp_stderr <- tempfile() 31 | 32 | # Attempt to run the code with "python" 33 | exit_code_python <- tryCatch({ 34 | suppressWarnings(system2("python", temp_file, stdout = temp_stdout, 35 | stderr = temp_stderr)) 36 | }, error = function(e) { 37 | NA 38 | }) 39 | 40 | # Attempt to run the code with "python3" 41 | exit_code_python3 <- tryCatch({ 42 | suppressWarnings(system2("python3", temp_file, stdout = temp_stdout, 43 | stderr = temp_stderr)) 44 | }, error = function(e) { 45 | NA 46 | }) 47 | 48 | # Remove the temporary files 49 | file.remove(temp_file, temp_stdout, temp_stderr) 50 | 51 | # If either of the exit codes is 0, the Python code is valid; else, it is not 52 | return(any(exit_code_python == 0, exit_code_python3 == 0)) 53 | } 54 | -------------------------------------------------------------------------------- /R/is_r.R: -------------------------------------------------------------------------------- 1 | #' Check if a character string contains valid R code 2 | #' 3 | #' This function takes a character string as input and attempts to parse it as 4 | #' R code using the `parse` function. If the parsing is successful, the function 5 | #' returns TRUE, indicating that the input string contains valid R code. If 6 | #' parsing fails, the function returns FALSE. 7 | #' 8 | #' @param code A character string containing the R code to be checked. 9 | #' 10 | #' @return A logical value indicating whether the input code string contains 11 | #' valid R code or not. 12 | #' 13 | #' @examples 14 | #' # Valid R code 15 | #' valid_code <- "x <- 5; y <- 10; z <- x + y" 16 | #' is_r(valid_code) 17 | #' 18 | #' # Invalid R code 19 | #' invalid_code <- "x <- 5 + 'a'" 20 | #' is_r(invalid_code) 21 | #' 22 | #' @export 23 | is_r <- function(code) { 24 | # Make sure input is character string 25 | if (!is.character(code) || nchar(code) == 0) { 26 | return(FALSE) 27 | } else { 28 | return(!inherits(try(eval(parse(text = code)), silent = TRUE), "try-error")) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /R/is_xml.R: -------------------------------------------------------------------------------- 1 | #' Check if the provided string is in valid XML format. 2 | #' 3 | #' @param input_string A character string to be checked for XML format. 4 | #' 5 | #' @return A logical value. If the input string is in valid XML format, returns 6 | #' TRUE, otherwise returns FALSE. 7 | #' 8 | #' @author Ulrich Matter umatter@protonmail.com 9 | #' 10 | #' @examples 11 | #' is_xml('value') 12 | #' # TRUE 13 | #' 14 | #' is_xml('value') 15 | #' # FALSE 16 | #' 17 | #' is_xml('') 18 | #' # FALSE 19 | #' @export 20 | is_xml <- function(input_string) { 21 | 22 | if (!is.character(input_string)) { 23 | warning("Input is not a character string.") 24 | return(FALSE) 25 | } 26 | 27 | if (nchar(input_string) == 0) { 28 | message("Empty string provided.") 29 | return(FALSE) 30 | } 31 | 32 | tryCatch({ 33 | xml2::read_xml(input_string) 34 | return(TRUE) 35 | }, error = function(e) { 36 | return(FALSE) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /R/java_to_r.R: -------------------------------------------------------------------------------- 1 | #' Convert Java code to R code 2 | #' 3 | #' This function takes Java code as input and returns the corresponding R code. 4 | #' It uses GPT-4 powered chat to perform the code conversion. 5 | #' 6 | #' @param java A character string containing the Java code to be converted to R, 7 | #' or a filename with the Java code. 8 | #' @param ... Additional arguments to pass to the chat_completion() function. 9 | #' 10 | #' @return If the input is a character string, the resulting R code will be 11 | #' printed and returned as a character string. If the input is a filename, the 12 | #' resulting R code will be saved as a file with the same name as the input 13 | #' file, but with the extension `.R`, and the filename will be returned. 14 | #' 15 | #' @details This function is not guaranteed to provide perfect conversions and 16 | #' might produce invalid R code in some cases. Users are encouraged to verify 17 | #' the output code carefully. 18 | #' 19 | #' @examples 20 | #' \dontrun{ 21 | #' # Convert a simple Java code snippet to R 22 | #' java_code <- "public class HelloWorld { 23 | #' public static void main(String[] args) { 24 | #' System.out.println(\"Hello, world!\"); 25 | #' } 26 | #' }" 27 | #' r_code <- java_to_r(java_code) 28 | #' cat(r_code) 29 | #' 30 | #' # Convert Java code from a file and save the result to an R file 31 | #' input_file <- "path/to/java_file.java" 32 | #' output_file <- java_to_r(input_file) 33 | #' } 34 | #' 35 | #' @export 36 | 37 | 38 | java_to_r <- function(java, ...) { 39 | 40 | # import, process text 41 | java <- read_text(java) 42 | text <- 43 | java$text %>% 44 | paste0(collapse = "\n") 45 | 46 | # initial user input 47 | n_msgs <- nrow(java_to_r_prompt) 48 | java_to_r_prompt$content[n_msgs] <- 49 | sprintf(fmt = java_to_r_prompt$content[n_msgs], text) 50 | 51 | # chat 52 | cli::cli_alert_info("Code writing in progress. Hold on tight!") 53 | resp <- chat_completion(java_to_r_prompt, ...) 54 | total_tokens_used <- usage(resp)$total_tokens 55 | info_token <- paste0("Total tokens used: ", total_tokens_used) 56 | cli::cli_inform(info_token) 57 | 58 | 59 | # extract output 60 | output <- 61 | resp %>% 62 | messages_content() %>% 63 | clean_output() 64 | output <- gsub("^[Jj]ava", "", output) 65 | 66 | # validate output 67 | if (is_r(output) == FALSE) { 68 | cli::cli_alert_warning(paste0("The conversion from Java to R has ", 69 | "potentially resulted in invalid R code. Please verify the output code ", 70 | "carefully!")) 71 | } 72 | 73 | # Return the processed java as R code 74 | filename <- unique(java$file) 75 | if (filename == "character string") { 76 | message(output) 77 | return(output) 78 | 79 | } else { 80 | output_file <- replace_file_extension(filename, new_extension = ".R") 81 | writeLines(output, output_file) 82 | return(output_file) 83 | 84 | } 85 | } -------------------------------------------------------------------------------- /R/messages.R: -------------------------------------------------------------------------------- 1 | #' Extract messages from a response object or a chatlog object 2 | #' 3 | #' This function takes a response object or a chatlog object as input and 4 | #' returns the messages. If the input is a response object, the function 5 | #' extracts and returns the messages from the choices. If the input is a 6 | #' chatlog object, the function returns the messages directly. 7 | #' 8 | #' @param x A list representing a response object or a chatlog object 9 | #' @return A data.frame containing the messages 10 | #' @export 11 | #' @examples 12 | #' \dontrun{ 13 | #' # Using a response object 14 | #' response <- list(choices = list(message = "This is a message.")) 15 | #' messages_from_response <- messages(response) 16 | #' print(messages_from_response) 17 | #' 18 | #' # Using a chatlog object 19 | #' chatlog_id <- chat("Hello, how are you?") 20 | #' chatlog <- get_chatlog(chatlog_id) 21 | #' messages_from_chatlog <- messages(chatlog) 22 | #' print(messages_from_chatlog) 23 | #' } 24 | messages <- function(x) { 25 | # Check input format 26 | if (!is.list(x) & !is_chatlog(x)) { 27 | stop("Invalid parameter value. Expecting list or chatlog object.") 28 | } 29 | 30 | if (is_chatlog(x)) { 31 | return(x@messages) 32 | } 33 | 34 | # Extract the choices from the x 35 | choices <- x$choices 36 | # Check if the choices are a list 37 | if (!is.list(choices)) { 38 | stop("Invalid response format. Choices must be a list object.") 39 | } 40 | # flatten 41 | message <- choices$message 42 | 43 | # Return the choices 44 | return(message) 45 | } 46 | -------------------------------------------------------------------------------- /R/messages_content.R: -------------------------------------------------------------------------------- 1 | #' Extract Messages Content from OpenAI API Response 2 | #' 3 | #' This function extracts the messages content from the HTTP response of an API 4 | #' call to the OpenAI chat completions endpoint. 5 | #' 6 | #' @param response a list object representing the HTTP response 7 | #' @return a character string representing the choices/messages from the 8 | #' response 9 | #' 10 | #' @author Ulrich Matter umatter@protonmail.com 11 | #' 12 | #' @export 13 | messages_content <- function(response) { 14 | # Check if the response is a list 15 | if (!is.list(response)) { 16 | stop("Invalid response format. Expected list object.") 17 | } 18 | 19 | # Extract the choices from the response 20 | choices <- response$choices 21 | # Check if the choices are a list 22 | if (!is.list(choices)) { 23 | stop("Invalid response format. Choices must be a list object.") 24 | } 25 | # flatten 26 | mc <- choices$message$content 27 | 28 | # Return the choices 29 | return(mc) 30 | } 31 | -------------------------------------------------------------------------------- /R/methods.R: -------------------------------------------------------------------------------- 1 | #'@import methods 2 | 3 | # function definition 4 | print.chatlog <- function(x) { 5 | cat("Chatlog ID: ", x@chatlog_id, "\n") 6 | print(x@messages) 7 | } 8 | 9 | # Register the method 10 | setMethod(f = "print", 11 | signature = "chatlog", 12 | definition = print.chatlog) -------------------------------------------------------------------------------- /R/model.R: -------------------------------------------------------------------------------- 1 | #' Extract Model from OpenAI API response 2 | #' 3 | #' This function extracts the model from the parsed HTTP response of an API 4 | #' call to the OpenAI chat completions endpoint. 5 | #' 6 | #' @param response a list object representing the HTTP response 7 | #' @return a character string representing the model from the response 8 | #' @author Ulrich Matter umatter@protonmail.com 9 | #' @export 10 | #' 11 | model <- function(response) { 12 | # Check if the response is a list 13 | if (!is.list(response)) { 14 | stop("Invalid response format. Expected list object.") 15 | } 16 | 17 | # Extract the model from the response 18 | m <- response$model 19 | 20 | # Check if the model is a character string 21 | if (!is.character(m)) { 22 | stop("Invalid response format. model must be a character string.") 23 | } 24 | 25 | # Return the model 26 | return(m) 27 | } 28 | -------------------------------------------------------------------------------- /R/nested_to_pipe.R: -------------------------------------------------------------------------------- 1 | #' Convert nested R code to pipe syntax 2 | #' 3 | #' This function takes an R script containing traditional (nested syntax) R 4 | #' code and converts it to magrittr-style syntax, using the pipe (%>%) operator. 5 | #' It also validates the input and output code to ensure proper R syntax. 6 | #' 7 | #' @param r A file path or character string containing the R code to be 8 | #' converted. 9 | #' @param n_tokens_limit The maximum number of tokens allowed in the input text 10 | #' (default: 3000). 11 | #' @param ... Additional arguments to pass to the chat_completion() function. 12 | #' 13 | #' @return If r is a character string, the function returns the converted R code 14 | #' as a character string. If r is a file path, the function writes the converted 15 | #' code to a new file with the same name and a "-pipe.R" suffix, and returns the 16 | #' path to the output file. 17 | #' 18 | #' @examples 19 | #' \dontrun{ 20 | #' # Converting a character string 21 | #' input <- "result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)" 22 | #' output <- nested_to_pipe(input) 23 | #' cat(output) 24 | #' 25 | #' # Converting a file 26 | #' # Create a temporary input file 27 | #' input_file <- tempfile(fileext = ".R") 28 | #' write("result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)", input_file) 29 | #' 30 | #' # Convert the file using nested_to_pipe 31 | #' output_file <- nested_to_pipe(input_file) 32 | #' 33 | #' # Check the converted file content 34 | #' cat(readLines(output_file)) 35 | #' } 36 | #' @export 37 | 38 | nested_to_pipe <- function(r, n_tokens_limit=3000, ...) { 39 | 40 | # import, process text 41 | r <- read_text(r) 42 | text <- 43 | r$text %>% 44 | paste0(collapse = "\n") 45 | 46 | # Make sure intput is an R function 47 | if (!is_r(text) | nchar(text) == 0) { 48 | stop("The input does not contain valid R code.") 49 | } 50 | 51 | # Make sure the text input is not too long 52 | n_tokens <- count_tokens(text) 53 | if (n_tokens_limit < n_tokens) { 54 | stop("Text input contains too many tokens!") 55 | } 56 | 57 | # initial user input 58 | n_msgs <- nrow(nested_to_pipe_prompt) 59 | nested_to_pipe_prompt$content[n_msgs] <- 60 | sprintf(fmt = nested_to_pipe_prompt$content[n_msgs], text) 61 | 62 | # chat 63 | cli::cli_alert_info("Code writing in progress. Hold on tight!") 64 | resp <- chat_completion(nested_to_pipe_prompt, ...) 65 | total_tokens_used <- usage(resp)$total_tokens 66 | info_token <- paste0("Total tokens used: ", total_tokens_used) 67 | cli::cli_inform(info_token) 68 | 69 | # extract output 70 | output <- 71 | resp %>% 72 | messages_content() %>% 73 | clean_output() 74 | 75 | # validate output 76 | if (is_r(output) == FALSE) { 77 | cli::cli_alert_warning(paste0("The conversion has potentially resulted in ", 78 | "invalid R code. Please verify the output code carefully!")) 79 | } 80 | 81 | # Return the processed r as BibTeX entries 82 | filename <- unique(r$file) 83 | if (filename == "character string") { 84 | return(output) 85 | 86 | } else { 87 | output_file <- paste0(replace_file_extension(filename, new_extension = ""), 88 | "-pipe.R") 89 | writeLines(output, output_file) 90 | return(output_file) 91 | 92 | } 93 | } -------------------------------------------------------------------------------- /R/num_tokens.R: -------------------------------------------------------------------------------- 1 | #' Get number of tokens in a string using OpenAI's tiktoken library 2 | #' 3 | #' This function uses the num_tokens_from_string function provided in OpenAI's 4 | #' tiktoken python library to get the number of tokens in a string. 5 | #' 6 | #' @param text a character string to count the number of tokens from 7 | #' @param encoding a character string that specifies how text is converted into 8 | #' tokens. The default is "cl100k_base" (for ChatGPT models; see 9 | #' https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb 10 | #' for details) 11 | #' @return an integer indicating the number of tokens in the input string 12 | #' @references https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb 13 | #' 14 | #' @import reticulate 15 | num_tokens <- function(text, encoding = "cl100k_base") { 16 | # Load necessary dependencies 17 | if (!requireNamespace("reticulate", quietly = TRUE)) { 18 | stop("reticulate package not installed.") 19 | } 20 | 21 | # Load python dependency 22 | # Note: this will install the dependency (and Miniconda, if no suitable 23 | # python installation could be found) 24 | # Using this function for the first time thus takes a while to process. 25 | tiktoken <- import("tiktoken") 26 | 27 | # Fetch encoding 28 | encoding <- tiktoken$get_encoding(encoding) 29 | 30 | # Count no. of encoded tokens 31 | num_tokens <- length(encoding$encode(text)) 32 | 33 | # Return the number of tokens 34 | return(num_tokens) 35 | } 36 | -------------------------------------------------------------------------------- /R/num_tokens_file.R: -------------------------------------------------------------------------------- 1 | #' Compute total number of tokens in a text file 2 | #' 3 | #' The function batch-wise computes the total number of tokens in a text file. 4 | #' The function returns a numeric value indicating the total number of tokens 5 | #' in the file. The function can be used on very large text files. 6 | #' 7 | #' @param filename character string indicating the name of the text file to 8 | #' read in 9 | #' @param batch_size integer indicating the number of lines to read in per batch 10 | #' (default is 1000) 11 | #' @param encoding character string indicating the encoding to use 12 | #' (default is "cl100k_base") 13 | #' @return a numeric value indicating the total number of tokens in the text 14 | #' file 15 | #' 16 | num_tokens_file <- function(filename, batch_size = 1000, 17 | encoding = "cl100k_base") { 18 | # Load necessary dependencies 19 | if (!requireNamespace("reticulate", quietly = TRUE)) { 20 | stop("reticulate package not installed.") 21 | } 22 | # dependencies 23 | requireNamespace("readr", quietly = TRUE) 24 | 25 | # Define callback function to compute number of tokens per batch 26 | tokens_batch <- function(lines, index) { 27 | # Concatenate the lines into a single text string 28 | text <- paste0(lines, collapse = " ") 29 | # Compute the number of tokens in the text string 30 | nt <- num_tokens(text, encoding = encoding) 31 | return(nt) 32 | } 33 | 34 | # Read in the text file in batches and compute the number of tokens per batch 35 | all_token_counts <- readr::read_lines_chunked(filename, 36 | callback = readr::ListCallback$new(tokens_batch), chunk_size = batch_size) 37 | 38 | # Compute the total number of tokens in the text file 39 | total_tokens <- sum(unlist(all_token_counts)) 40 | 41 | # Return the total number of tokens 42 | return(total_tokens) 43 | } 44 | -------------------------------------------------------------------------------- /R/object.R: -------------------------------------------------------------------------------- 1 | #' Extract object information from OpenAI API response 2 | #' 3 | #' This function extracts the object data from the parsed HTTP response of an 4 | #' API call to the OpenAI chat completions endpoint (provides information about 5 | #' the endpoint). 6 | #' 7 | #' @param response a list object representing the HTTP response 8 | #' @return a data frame with the usage statistics of the API call (how many 9 | #' tokens used) 10 | #' @author Ulrich Matter umatter@protonmail.com 11 | #' @export 12 | #' 13 | object <- function(response) { 14 | # Check if the response is a list 15 | if (!is.list(response)) { 16 | stop("Invalid response format. Expected list object.") 17 | } 18 | 19 | # Extract the object from the response 20 | object <- response$object 21 | 22 | # Check if the object is a character string 23 | if (!is.character(object)) { 24 | stop("Invalid response format. object must be a character string.") 25 | } 26 | 27 | # Return the object 28 | return(object) 29 | } 30 | -------------------------------------------------------------------------------- /R/openai_api_key.R: -------------------------------------------------------------------------------- 1 | #' Set OpenAI API Key as an Environment Variable 2 | #' 3 | #' This function sets the OpenAI API key as an environment variable in the 4 | #' current R session. It takes the API key as an input and stores it as an 5 | #' environment variable, allowing other functions to access the key when needed. 6 | #' 7 | #' @param api_key A character string containing the OpenAI API key. 8 | #' @return Nothing is returned; the function is called for its side effects. 9 | #' @author Ulrich Matter umatter@protonmail.com 10 | #' @seealso \url{https://platform.openai.com/docs/} for more information 11 | #' on the OpenAI API. 12 | #' @examples 13 | #' \dontrun{ 14 | #' # Set the OpenAI API key for the current R session 15 | #' openai_api_key("your_api_key_here") 16 | #' } 17 | #' @export 18 | openai_api_key <- function(api_key) { 19 | Sys.setenv(OPENAI_API_KEY = api_key) 20 | } 21 | -------------------------------------------------------------------------------- /R/parse_response.R: -------------------------------------------------------------------------------- 1 | #' Parse a Response From the API 2 | #' 3 | #' This function takes an input string containing both text and code blocks, 4 | #' and returns a list of blocks with their respective type, content, and 5 | #' language (if applicable). 6 | #' Each block is either of type 'text' or 'code'. 7 | #' 8 | #' @param input_string The response from the API 9 | #' @return A list of blocks with type, content, and language (for code blocks) 10 | #' @author Jonathan Chassot 11 | #' 12 | #' @examples 13 | #' \dontrun{ 14 | #' parse_response("Hello world!") 15 | #' # [[1]] 16 | #' # [[1]]$type 17 | #' # [1] "text" 18 | #' # 19 | #' # [[1]]$content 20 | #' # [1] "Hello world!" 21 | #' # 22 | #' parse_response("```python\nprint('Hello world!')\n```") 23 | #' # [[1]] 24 | #' # [[1]]$type 25 | #' # [1] "code" 26 | #' # 27 | #' # [[1]]$content 28 | #' # [1] "print('Hello world!')" 29 | #' # 30 | #' # [[1]]$language 31 | #' # [1] "python" 32 | #' # 33 | #' parse_response("Hello world!\n\n```python\nprint('Hello world!')\n```") 34 | #' # [[1]] 35 | #' # [[1]]$type 36 | #' # [1] "text" 37 | #' # 38 | #' # [[1]]$content 39 | #' # [1] "Hello world!" 40 | #' # 41 | #' # [[2]] 42 | #' # [[2]]$type 43 | #' # [1] "code" 44 | #' # 45 | #' # [[2]]$content 46 | #' # [1] "print('Hello world!')" 47 | #' # 48 | #' # [[2]]$language 49 | #' # [1] "python" 50 | #' # 51 | #' } 52 | #' @export 53 | parse_response <- function(input_string) { 54 | 55 | # Extract content between "```" using regex 56 | regex_pattern <- "`{3}([\\s\\S]*?)`{3}" 57 | res <- gregexpr(regex_pattern, input_string, perl = TRUE)[[1]] 58 | 59 | # If no matches, return the input string 60 | if (res[1] == -1) { 61 | return(list(list(type = "text", content = input_string))) 62 | } 63 | 64 | # start_text is the start for text blocks, start_code is the start for code 65 | # end_text is the end for text blocks, end_code is the end for code 66 | start_code <- as.numeric(res) 67 | end_code <- start_code + attr(res, "match.length") - 1 68 | start_text <- end_code + 1 69 | end_text <- start_code - 1 70 | # Correct for first and last blocks 71 | if (start_code[1] != 1) { 72 | start_text <- c(1, start_text) 73 | } else { 74 | end_text <- end_text[-1] 75 | } 76 | if (end_code[length(end_code)] != nchar(input_string)) { 77 | end_text <- c(end_text, nchar(input_string)) 78 | } else { 79 | start_text <- start_text[-length(start_text)] 80 | } 81 | 82 | if (0 < length(start_text) && 0 < length(end_text)) { 83 | text_blocks <- substring(input_string, start_text, end_text) 84 | text_list <- mapply(function(block, start) { 85 | list(type = "text", content = block, start = start) 86 | }, text_blocks, start_text, SIMPLIFY = FALSE) 87 | 88 | } else { 89 | # no text in response 90 | text_list <- NULL 91 | } 92 | 93 | if (0 < length(start_code) && 0 < length(end_code)) { 94 | code_blocks <- substring(input_string, start_code, end_code) 95 | code_list <- mapply(function(block, start) { 96 | # Remove the ticks 97 | block <- gsub("^```|```$", "", block) 98 | # Extract the language 99 | res <- regexpr("\\n", block, perl = TRUE)[[1]][1] 100 | if (res == -1) { 101 | lang <- "" 102 | } else { 103 | lang <- tolower(trimws(substr(block, 1, res))) 104 | block <- substr(block, res + 1, nchar(block)) 105 | } 106 | lang <- ifelse(lang == "", "plaintext", lang) 107 | list(type = "code", content = block, start = start, language = lang) 108 | }, code_blocks, start_code, SIMPLIFY = FALSE) 109 | } else { 110 | code_list <- NULL 111 | } 112 | 113 | # Create output list 114 | full_list <- c(text_list, code_list) 115 | names(full_list) <- NULL 116 | 117 | full_list <- lapply( 118 | full_list[order(sapply(full_list, function(x) x$start))], 119 | function(x) { 120 | x$start <- NULL 121 | x 122 | } 123 | ) 124 | 125 | # Return code blocks 126 | return(full_list) 127 | } 128 | -------------------------------------------------------------------------------- /R/r_to_python.R: -------------------------------------------------------------------------------- 1 | #' Convert R Code to Python Code 2 | #' 3 | #' This function takes an R code file as input and uses a language model to 4 | #' convert the R code to Python code. The converted Python code is then either 5 | #' returned as a character string or written to a file, depending on the input. 6 | #' 7 | #' @param r The R code file to be converted to Python code. This should be a 8 | #' file path in the form of a character string. 9 | #' @param ... Additional arguments to pass to the chat_completion() function. 10 | #' 11 | #' @return If the input filename is a "character string", the converted Python 12 | #' code will be returned as a character string. Otherwise, a new Python file 13 | #' will be created with the same name as the input file but with a ".py" 14 | #' extension, and the function will return the file path of the newly created 15 | #' Python file. 16 | #' 17 | #' @examples 18 | #' \dontrun{ 19 | #' # Convert R code to Python code and display the result as a character string 20 | #' r_to_python("example.R") 21 | #' 22 | #' # Convert R code to Python code and save it to a file 23 | #' r_to_python("example.R", output_file = "example.py") 24 | #'} 25 | #' @export 26 | r_to_python <- function(r, ...) { 27 | 28 | # import, process text 29 | r <- read_text(r) 30 | text <- 31 | r$text %>% 32 | paste0(collapse = "\n") 33 | 34 | # initial user input 35 | n_msgs <- nrow(r_to_python_prompt) 36 | r_to_python_prompt$content[n_msgs] <- 37 | sprintf(fmt = r_to_python_prompt$content[n_msgs], text) 38 | 39 | # chat 40 | cli::cli_alert_info("Python-code writing in progress. Hold on tight!") 41 | resp <- chat_completion(r_to_python_prompt, ...) 42 | total_tokens_used <- usage(resp)$total_tokens 43 | info_token <- paste0("Total tokens used: ", total_tokens_used) 44 | cli::cli_inform(info_token) 45 | 46 | # extract output 47 | output <- 48 | resp %>% 49 | messages_content() %>% 50 | clean_output() 51 | 52 | output <- gsub("^python", "", output) 53 | 54 | # validate output 55 | if (is_python(output) == FALSE) { 56 | cli::cli_alert_warning(paste0("The conversion from R to Python has ", 57 | "potentially resulted in invalid Python code. Please verify the output ", 58 | "code carefully!")) 59 | } 60 | 61 | # Return the processed r as BibTeX entries 62 | filename <- unique(r$file) 63 | if (filename == "character string") { 64 | return(output) 65 | 66 | } else { 67 | output_file <- replace_file_extension(filename, new_extension = ".py") 68 | writeLines(output, output_file) 69 | return(output_file) 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /R/read_text.R: -------------------------------------------------------------------------------- 1 | #' Convert Text to Tidy-Text Format 2 | #' 3 | #' This function takes a character string or a path to a text file as input and 4 | #' converts it to tidy-text format. The resulting tibble contains one row for 5 | #' each line of the input text, along with the file name, and line number. 6 | #' 7 | #' @param text A character string containing the text to be converted, or a 8 | #' path to a text file. 9 | #' 10 | #' @return A tibble containing the converted text in tidy-text format, 11 | #' with columns for the text, 12 | #' file name, line number, and batch index (if applicable). 13 | #' 14 | #' @examples 15 | #' read_text("Hello, how are you?") 16 | #' read_text("path/to/text/file.txt") 17 | #' 18 | #' @importFrom R.utils isUrl 19 | #'@export 20 | 21 | read_text <- function(text) { 22 | 23 | # read text (either from file or string) 24 | if(text == "" || (!file.exists(text) & !R.utils::isUrl(text))) { 25 | fn <- "character string" 26 | # read the data, split into lines 27 | lines <- readr::read_lines(I(text)) 28 | } else { 29 | fn <- text 30 | # read the data, split into lines 31 | lines <- readr::read_lines(text) 32 | } 33 | 34 | 35 | # convert to tidy-text format 36 | text_df <- 37 | tibble::tibble(text = lines, 38 | file = fn, 39 | line = seq_along(lines), 40 | batch_index = 1) 41 | return(text_df) 42 | } 43 | -------------------------------------------------------------------------------- /R/read_text_batches.R: -------------------------------------------------------------------------------- 1 | #' Load data from text files in batches 2 | #' 3 | #' This function reads in data from text files in batches using 4 | #' the read_lines_chunked function from the readr package. 5 | #' 6 | #' @param text character string, either containing a path to a text file to read 7 | #' in or containing the text. 8 | #' @param batch_size integer indicating the number of lines to read in per batch 9 | #' (default is 3500) 10 | #' @return a numeric value indicating the total number of tokens in the text 11 | #' file 12 | #' @author Ulrich Matter umatter@protonmail.com 13 | #' @examples 14 | #' \dontrun{ 15 | #' data_path <- system.file("text", "lorem.txt", package = "OpenAIR") 16 | #' text_data <- read_text_batches(data_path) 17 | #' } 18 | #' @export 19 | read_text_batches <- function(text, batch_size = 3500) { 20 | 21 | # dependencies 22 | requireNamespace("readr", quietly = TRUE) 23 | 24 | # Define callback function to compute number of tokens per batch 25 | text_batch <- function(lines, index) { 26 | if(file.exists(text)) { 27 | fn <- text 28 | } else { 29 | fn <- "character string" 30 | } 31 | # convert to tidy-text format 32 | text <- 33 | data.frame(text = lines, 34 | file = fn, 35 | line = seq_along(lines), 36 | batch_index = index) 37 | return(text) 38 | } 39 | 40 | # Read in the text file in batches and compute the number of tokens per batch 41 | all_batches <- readr::read_lines_chunked(text, 42 | callback = readr::ListCallback$new(text_batch), chunk_size = batch_size) 43 | 44 | # Return the total number of tokens 45 | return(all_batches) 46 | } 47 | -------------------------------------------------------------------------------- /R/refactor.R: -------------------------------------------------------------------------------- 1 | #' Refactor R Code with AI Assistance 2 | #' 3 | #' This function refactors R code with the assistance of an AI chatbot. 4 | #' 5 | #' @param file character, file name of a file containing R code to be refactored 6 | #' or a character string containing R code to be refactored 7 | #' @param ... Additional arguments to pass to the chat_completion() function. 8 | #' 9 | #' @return The refactored code either to the console (if the input `file` was a 10 | #' character string) or written to a file (if the input was a file name). 11 | #' 12 | #' @examples 13 | #' \dontrun{ 14 | #' # Create a sample R function file 15 | #' cat("my_sum <- function(a, b) {", "return(a + b)", "}", 16 | #' file = "sample_function.R") 17 | #' 18 | #' # Refactor the R function and return the output 19 | #' refactored_function <- refactor(file = "sample_function.R") 20 | #' 21 | #' # Refactor the R function and write the output to the same file 22 | #' refactor(file = "sample_function.R") 23 | #' } 24 | #' @export 25 | refactor <- function(file, ...) { 26 | 27 | # import, process text 28 | r_code <- read_text(file) 29 | text <- 30 | r_code$text %>% 31 | paste0(collapse = "\n") 32 | text_commented_out <- 33 | r_code$text %>% 34 | paste0("# ") %>% 35 | paste0(collapse = "\n") 36 | 37 | # Make sure intput is R code 38 | if (!is_r(text) | nchar(text) == 0) { 39 | stop("The input does not contain a valid R code.") 40 | } 41 | 42 | # initial user input 43 | n_msgs <- nrow(refactor_prompt) 44 | refactor_prompt$content[n_msgs] <- 45 | sprintf(fmt = refactor_prompt$content[n_msgs], text) 46 | 47 | 48 | # chat 49 | cli::cli_alert_info("Code writing in progress. Hold on tight!") 50 | resp <- chat_completion(refactor_prompt, ...) 51 | total_tokens_used <- usage(resp)$total_tokens 52 | info_token <- paste0("Total tokens used: ", total_tokens_used) 53 | cli::cli_inform(info_token) 54 | 55 | # extract refactored R code 56 | output <- 57 | resp %>% 58 | messages_content() %>% 59 | clean_output() 60 | 61 | # validate output 62 | if (is_r(output) == FALSE) { 63 | cli::cli_alert_warning(paste0("Refactoring has potentially resulted in ", 64 | "invalid R code. Verify the generated code carefully!")) 65 | } 66 | 67 | # prepare output 68 | filename <- unique(r_code$file) 69 | if (filename == "character string") { 70 | return(output) 71 | 72 | } else { 73 | cat(output, 74 | "\n\n # OLD VERSION ---\n\n", 75 | text_commented_out, 76 | file = filename) 77 | cli::cli_alert_success(paste0("Wrote refactored version to ", filename)) 78 | 79 | return(filename) 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /R/references_to_bibtex.R: -------------------------------------------------------------------------------- 1 | #' Convert references in plain text to BibTeX format 2 | #' 3 | #' This function takes a character string or a file path to plain text 4 | #' references and converts them into BibTeX format. The function reads the input 5 | #' text, processes it, and returns a character string containing the references 6 | #' in BibTeX format. If a file path is provided, the function also writes the 7 | #' BibTeX entries to a .bib file in the same directory. 8 | #' 9 | #' @param references A character string or a file path to a file containing the 10 | #' plain text references to convert. 11 | #' @param ... Additional arguments to pass to the chat_completion() function. 12 | #' 13 | #' @return A character string containing the references in BibTeX format or, if 14 | #' a file path is provided, the function writes the BibTeX entries to a .bib 15 | #' file in the same directory and returns the file path of the newly created 16 | #' .bib file. 17 | #' @author Ulrich Matter umatter@protonmail.com 18 | #' @seealso \url{https://ctan.org/pkg/bibtex} for more information on BibTeX 19 | #' format 20 | #' @examples 21 | #' \dontrun{ 22 | #' # Convert plain text references to BibTeX format 23 | #' references <- "Doe, J., & Smith, J. (2020). The title of the paper. 24 | #' Journal of Scientific Computing, 12, 45-67." 25 | #' references_to_bibtex(references) 26 | #' } 27 | #' @export 28 | 29 | 30 | references_to_bibtex <- function(references, ...) { 31 | 32 | # import, process text 33 | references <- read_text(references) 34 | text <- 35 | references$text %>% 36 | paste0(collapse = "\n") 37 | 38 | # initial user input 39 | n_msgs <- nrow(references_to_bibtex_prompt) 40 | references_to_bibtex_prompt$content[n_msgs] <- 41 | sprintf(fmt = references_to_bibtex_prompt$content[n_msgs], text) 42 | 43 | # chat 44 | cli::cli_alert_info("Bibtex writing in progress. Hold on tight!") 45 | resp <- chat_completion(references_to_bibtex_prompt, ...) 46 | total_tokens_used <- usage(resp)$total_tokens 47 | info_token <- paste0("Total tokens used: ", total_tokens_used) 48 | cli::cli_inform(info_token) 49 | 50 | # extract output 51 | output <- 52 | resp %>% 53 | messages_content() %>% 54 | clean_output() 55 | 56 | # Return the processed references as BibTeX entries 57 | filename <- unique(references$file) 58 | if (filename == "character string") { 59 | return(output) 60 | 61 | } else { 62 | output_file <- replace_file_extension(filename, new_extension = ".bib") 63 | writeLines(output, output_file) 64 | return(output_file) 65 | 66 | } 67 | } -------------------------------------------------------------------------------- /R/regenerate.R: -------------------------------------------------------------------------------- 1 | #' Regenerate the last response in an ongoing chat 2 | #' 3 | #' This function removes the last response in a chatlog, generates a new 4 | #' response based on the updated chatlog, and updates the chatlog accordingly. 5 | #' The output can be displayed as a message in the console, returned as a 6 | #' message, or returned as a response object. 7 | #' 8 | #' @param chatlog_id A character string specifying the ID of the chatlog 9 | #' (default: '.__CURRENTCHAT__') 10 | #' @param output A character string specifying the output format. Options are 11 | #' 'message_to_console', 'message', or 'response_object' 12 | #' (default: 'message_to_console') 13 | #' @param ... Additional arguments to pass to the chat_completion() function. 14 | #' @return If output is 'message_to_console', the function returns NULL 15 | #' andprints the message to the console. If output is 'message', the function 16 | #' returns a character string containing the message. If output is 17 | #' 'response_object', the function returns the full response object. 18 | #' @export 19 | #' @examples 20 | #' \dontrun{ 21 | #' # Start a new chat and save the chatlog ID 22 | #' chatlog_id <- chat("Hello, how are you?") 23 | #' 24 | #' # Regenerate the last response in the chat and display it in the console 25 | #' regenerate(chatlog_id) 26 | #' 27 | #' # Regenerate the last response in the chat and return it as a message 28 | #' message <- regenerate(chatlog_id, output = "message") 29 | #' print(message) 30 | #' 31 | #' # Regenerate the last response in the chat and return it as a response object 32 | #' response_object <- regenerate(chatlog_id, output = "response_object") 33 | #' print(response_object) 34 | #' } 35 | regenerate <- function(chatlog_id = ".__CURRENTCHAT__", 36 | output = "message_to_console", ...) { 37 | 38 | # check input validity 39 | if (!output %in% c("message_to_console", "message", "response_object")) { 40 | stop("Argument output needs to be one of 'message_to_console', 'message', ", 41 | "or 'sponse_object") 42 | } 43 | # check if chat is ongoing 44 | if (!exists(chatlog_id, envir = OpenAIR_env)) { 45 | stop("No chatlog found. Please start a new chat with chat() first.") 46 | } else { 47 | # fetch current chat status 48 | cl <- get_chatlog(chatlog_id) 49 | } 50 | 51 | # remove last chatlog entry 52 | cl@messages <- cl@messages[-nrow(cl@messages), ] 53 | assign(chatlog_id, cl, envir = OpenAIR_env) 54 | 55 | # regenerate 56 | resp <- chat_completion(cl, ...) 57 | 58 | # update chatlog 59 | resp %>% 60 | messages() %>% 61 | add_to_chatlog(chatlog_id) 62 | 63 | if (output == "message_to_console") { 64 | # process response 65 | messages <- 66 | resp %>% 67 | messages() 68 | 69 | # show response message in console 70 | return(message(messages$content)) 71 | } 72 | 73 | if (output == "message") { 74 | 75 | # process response 76 | messages <- 77 | resp %>% 78 | messages() 79 | 80 | return(messages$content) 81 | 82 | } 83 | 84 | if (output == "response_object") { 85 | # return full response object 86 | return(resp) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /R/replace_file_extension.R: -------------------------------------------------------------------------------- 1 | #' Replace File Extension 2 | #' 3 | #' This function replaces the file extension of a given filename with a 4 | #' specified new extension. It validates the input to ensure the filename and 5 | #' the new extension are single character strings. Then, it replaces the old 6 | #' extension with the new one and returns the modified filename. 7 | #' 8 | #' @param filename The input filename as a character string. 9 | #' @param new_extension The new file extension to replace the old one 10 | #' (including the dot, e.g., ".bib"). 11 | #' @return A character string representing the filename with the replaced file 12 | #' extension. 13 | #' @author Ulrich Matter umatter@protonmail.com 14 | #' @export 15 | #' @examples 16 | #' \dontrun{ 17 | #' # Replace the file extension of a text file with a BibTeX extension 18 | #' new_filename <- replace_file_extension("example_document.txt", ".bib") 19 | #' print(new_filename) # "example_document.bib" 20 | #' } 21 | replace_file_extension <- function(filename, new_extension) { 22 | # Validate input 23 | if (!is.character(filename) || length(filename) != 1) { 24 | stop("filename must be a single character string.") 25 | } 26 | 27 | if (!is.character(new_extension) || length(new_extension) != 1) { 28 | stop("new_extension must be a single character string.") 29 | } 30 | 31 | # Replace the file extension with the new_extension 32 | new_filename <- sub("\\.[^.]+$", new_extension, filename) 33 | 34 | return(new_filename) 35 | } 36 | -------------------------------------------------------------------------------- /R/set_chatlog.R: -------------------------------------------------------------------------------- 1 | #' Set up a new chatlog 2 | #' 3 | #' This function sets up a new chatlog object for a conversation. 4 | #' 5 | #' @param initial_role A character string representing the role issueing the 6 | #' initial content (per default: "system") 7 | #' @param initial_content A character string representing the initial message 8 | #' from the system 9 | #' @param chatlog_id A character string representing the ID of this 10 | #' conversation. Per default, this will be set automatically. 11 | #' @return A new chatlog object 12 | #' @export 13 | #' @examples 14 | #' chat <- set_chatlog("Welcome to our chat!") 15 | #' is_chatlog(chat) 16 | #' chat 17 | set_chatlog <- function(initial_role="system", 18 | initial_content = "You are a helpful assistant.", chatlog_id=NULL) { 19 | 20 | # Create a new data frame with the initial system message 21 | msgs <- data.frame(role = initial_role, 22 | content = initial_content) 23 | 24 | # Create the id of the current chat 25 | if (is.null(chatlog_id)){ 26 | chatlog_id <- paste0(".chatlog_", format(Sys.time(), "%Y%m%d%H%M%S")) 27 | } 28 | 29 | # Create a new chatlog object 30 | chatlog <- new("chatlog", 31 | messages = msgs, 32 | chatlog_id = chatlog_id) 33 | 34 | # Prepare chat environment, store chatlog object there 35 | assign(chatlog_id, chatlog, envir=OpenAIR_env) 36 | 37 | return(chatlog) 38 | } 39 | -------------------------------------------------------------------------------- /R/split_text.R: -------------------------------------------------------------------------------- 1 | #' Split Text into Chunks 2 | #' 3 | #' This function splits a text string into a vector of strings with a 4 | #' specified number of tokens each. 5 | #' 6 | #' @param text A character vector containing the text to be split. 7 | #' @param N An integer specifying the number of tokens per chunk. 8 | #' 9 | #' @return A character vector containing the chunks of text with N tokens each. 10 | #' @export 11 | #' @import stringr 12 | #' 13 | #' @examples 14 | #' large_text <- "This is an example of a large text string 15 | #' that will be split into chunks of N tokens each by our custom R function." 16 | #' num_tokens_per_chunk <- 5 17 | #' split_text(large_text, num_tokens_per_chunk) 18 | split_text <- function(text, N) { 19 | # Check if the input N is a positive integer 20 | if (!is.numeric(N) || N <= 0 || round(N) != N) { 21 | stop("Error: N must be a positive integer.") 22 | } 23 | 24 | # Tokenize the input text using stringr package 25 | tokens <- stringr::str_split(text, "\\s+")[[1]] 26 | 27 | # Count the number of tokens 28 | num_tokens <- length(tokens) 29 | 30 | # Calculate the number of chunks 31 | num_chunks <- ceiling(num_tokens / N) 32 | 33 | # Initialize an empty vector to store the chunks 34 | chunks <- vector("list", num_chunks) 35 | 36 | # Iterate through the tokens and split them into chunks 37 | for (i in seq_along(chunks)) { 38 | start_index <- (i - 1) * N + 1 39 | end_index <- min(i * N, num_tokens) 40 | chunk_tokens <- tokens[start_index:end_index] 41 | chunks[[i]] <- stringr::str_c(chunk_tokens, collapse = " ") 42 | } 43 | 44 | # Return the vector of chunks 45 | return(chunks) 46 | } 47 | -------------------------------------------------------------------------------- /R/start_chat.R: -------------------------------------------------------------------------------- 1 | 2 | #' Start a new chat session 3 | #' 4 | #' This function starts a new chat session by initializing a messages object 5 | #' with an initial system message, creating a new log environment to store the 6 | #' messages, and adding the messages object to the log environment. 7 | #' 8 | #' @param initial_role A character string representing the role issueing the 9 | #' initial content (per default: "system") 10 | #' @param initial_content A character string representing the initial message 11 | #' from the system 12 | #' @param show Logical, if TRUE, the current chat log is displayed via View(). 13 | #' Default is FALSE. 14 | #' @param chatlog_id A character string representing the ID of this 15 | #' conversation. Per default, this will be set automatically. 16 | #' 17 | #' @return A character string indicating the name of the log environment 18 | #' created for the chat session. 19 | #' 20 | #' @examples 21 | #' # Start a new chat session with the default system message 22 | #' chatlog_id <- start_chat() 23 | #' 24 | #' # Start a new chat session with a custom system message 25 | #' chatlog_id <- start_chat("How can I assist you today?") 26 | #' 27 | #'@export 28 | start_chat <- function(initial_role="system", 29 | initial_content = "You are a helpful assistant.", show = FALSE, 30 | chatlog_id = NULL){ 31 | 32 | cl <- set_chatlog(initial_role = initial_role, 33 | initial_content = initial_content, chatlog_id) 34 | 35 | if (show == TRUE) { 36 | # Open current chatlog 37 | utils::View(cl@messages, 38 | title = paste0("Current chat (ID: ", 39 | cl@chatlog_id, 40 | ")")) 41 | } 42 | 43 | return(cl) 44 | } 45 | -------------------------------------------------------------------------------- /R/usage.R: -------------------------------------------------------------------------------- 1 | #' Extract usage data from OpenAI API response 2 | #' 3 | #' This function extracts the usage data from the parsed HTTP response of an 4 | #' API call to the OpenAI chat completions endpoint. 5 | #' 6 | #' @param response a list object representing the HTTP response 7 | #' @return a data frame with the usage statistics of the API call 8 | #' (how many tokens used) 9 | #' 10 | #' @export 11 | #' 12 | usage <- function(response) { 13 | # Check if the response is a list 14 | if (!is.list(response)) { 15 | stop("Invalid response format. Expected list object.") 16 | } 17 | 18 | # Extract the usage stats from the response 19 | u <- response$usage 20 | 21 | # Check if the usage stats object is a list 22 | if (!is.list(u)) { 23 | stop("Invalid response format. usage must be a character string.") 24 | } 25 | 26 | # Convert to data frame 27 | u <- as.data.frame(u) 28 | 29 | # Return the usage stats 30 | return(u) 31 | } 32 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | #' @param lhs A value or the magrittr placeholder. 12 | #' @param rhs A function call using the magrittr semantics. 13 | #' @return The result of calling `rhs(lhs)`. 14 | NULL 15 | -------------------------------------------------------------------------------- /R/write_code.R: -------------------------------------------------------------------------------- 1 | #' Write code based on user's input 2 | #' 3 | #' The `write_code` function prompts the user to provide a plain English 4 | #' description of a program or function and the programming language it should 5 | #' be written in. The function then generates the code based on the user's input 6 | #' and writes it to a specified file. 7 | #' 8 | #' @param filename A character string representing the name of the file where 9 | #' the generated code will be saved. 10 | #' @param chatlog_id An optional character string representing the chatlog ID. 11 | #' Defaults to ".__CURRENTCODEFILE__". This ID is used to maintain the 12 | #' conversation history with the chatbot API. 13 | #' @param ... Additional arguments to pass to the chat_completion() function. 14 | #' 15 | #' @author Ulrich Matter 16 | #' @return Returns the name of the file containing the generated code. 17 | #' 18 | #' @examples 19 | #' \dontrun{ 20 | #' # Generate code based on user input and save it to a file 21 | #' generated_code_file <- write_code("example_code.R") 22 | #' 23 | #' # Check the content of the generated code file 24 | #' cat(readLines(generated_code_file)) 25 | #' 26 | #' # Clean up 27 | #' unlink(generated_code_file) 28 | #' } 29 | #' @export 30 | 31 | write_code <- 32 | function(filename, chatlog_id = ".__CURRENTCODEFILE__", ...) { 33 | 34 | # check if code writing session was already initialized 35 | # if not, initialize new session 36 | if (!exists(chatlog_id, envir = OpenAIR_env)) { 37 | # initialize chatlog 38 | cl <- start_chat(chatlog_id = chatlog_id) 39 | 40 | } else { 41 | # fetch current chat status 42 | cl <- get_chatlog(chatlog_id) 43 | 44 | } 45 | 46 | # create and open the new file 47 | file.create(filename) 48 | rstudioapi::navigateToFile(filename) 49 | 50 | # Initialize an empty character vector to store input text 51 | input_text <- character(0) 52 | 53 | # Prompt the user for input, and add each line to the input vector 54 | cli::cli_h2(paste0("Explain in plain English what the program you want to ", 55 | "write should do and in what language it should be written.")) 56 | cli::cli_h2("Type 'GO!' to finish.\n") 57 | while (TRUE) { 58 | input_line <- readline("Instruction:") 59 | if (tolower(input_line) == "go!") { 60 | break 61 | } 62 | input_text <- c(input_text, input_line) 63 | } 64 | 65 | # make prompt more robust 66 | instructions <- paste0("Return everything in one code block! Do not add ", 67 | "any explanations, simply return the code.") 68 | input_text <- c(input_text, instructions) 69 | message <- paste0(input_text, collapse = "\n") 70 | 71 | # add new message to conversation, send 72 | cli::cli_alert_info("Code writing in progress. Hold on tight!") 73 | 74 | resp <- 75 | initialize_messages(initial_role = "user", initial_content = message) %>% 76 | add_to_chatlog(chatlog_id) %>% 77 | chat_completion(...) 78 | 79 | # process response 80 | messages <- 81 | resp %>% 82 | messages() 83 | 84 | # update chatlog 85 | add_to_chatlog(messages) 86 | 87 | # process, format output 88 | resp_parts <- parse_response(messages$content) 89 | code <- 90 | extract_blocks(resp_parts, "code") %>% 91 | extract_blocks_content() %>% 92 | unlist() %>% 93 | paste0(collapse = "\n") 94 | 95 | text <- 96 | extract_blocks(resp_parts, "text") %>% 97 | extract_blocks_content() %>% 98 | unlist() %>% 99 | str_replace(pattern = "\\:$", replacement = ".") %>% 100 | paste0(collapse = "\n") 101 | 102 | # Write the output to the file 103 | if (nchar(code) == 0) { 104 | if (is_r(text)) { 105 | writeLines(text, filename) 106 | } else { 107 | cli::cli_alert_danger( 108 | "No clearly defined code block has been returned!") 109 | } 110 | } else { 111 | writeLines(code, filename) 112 | } 113 | rstudioapi::navigateToFile(filename) 114 | 115 | if (nchar(text)==0){ 116 | cli::cli_alert_success("Here you go!") 117 | } else { 118 | cat(text) 119 | } 120 | 121 | return(filename) 122 | } 123 | -------------------------------------------------------------------------------- /R/write_test.R: -------------------------------------------------------------------------------- 1 | #' Write test for an R function 2 | #' 3 | #' This function reads an R function from a file and generates a test file with 4 | #' documentation. 5 | #' 6 | #' @param file The file path of the R function. 7 | #' @param ... Additional arguments to pass to the chat_completion() function. 8 | #' 9 | #' @return If the input is a character string, the function returns the 10 | #' generated output without creating a test file. Otherwise, it creates a test 11 | #' file and returns the file name. 12 | #' 13 | #' @examples 14 | #' \dontrun{ 15 | #' # Write test for an R function 16 | #' write_test("path/to/file.R") 17 | #' } 18 | #' @export 19 | write_test <- function(file, ...) { 20 | 21 | # import, process text 22 | r_function <- read_text(file) 23 | 24 | # Read the content of the file 25 | text <- 26 | r_function$text %>% 27 | paste0(collapse = "\n") 28 | 29 | # Make sure intput is an R function 30 | if (!contains_r_func(text) || nchar(text) == 0) { 31 | stop("The input does not contain a valid R function.") 32 | } 33 | 34 | # Create user input 35 | n_msgs <- nrow(write_test_prompt) 36 | write_test_prompt$content[n_msgs] <- 37 | sprintf(fmt = write_test_prompt$content[n_msgs], text) 38 | 39 | # chat 40 | cli::cli_alert_info("Test-writing in progress. Hold on tight!") 41 | resp <- chat_completion(write_test_prompt, ...) 42 | total_tokens_used <- usage(resp)$total_tokens 43 | info_token <- paste0("Total tokens used: ", total_tokens_used) 44 | cli::cli_inform(info_token) 45 | 46 | # extract output 47 | output <- 48 | resp %>% 49 | messages_content() 50 | 51 | # Prepare/process output 52 | filename <- unique(r_function$file) 53 | 54 | if (filename == "character string") { 55 | return(output) 56 | 57 | } else { 58 | filename <- paste0(replace_file_extension(filename, new_extension = ""), 59 | "-test.R") 60 | writeLines(output, filename) 61 | file.edit(filename) 62 | return(filename) 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | # initialize package env 2 | OpenAIR_env <- new.env(parent = emptyenv()) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # OpenAIR 3 | 4 | 5 | [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) 6 | [![R-CMD-check](https://github.com/umatter/OpenAIR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/umatter/OpenAIR/actions/workflows/R-CMD-check.yaml) 7 | 8 | 9 | Integrate OpenAI's GPT models into your R workflows. 10 | 11 | 12 | 13 | ## Installation 14 | 15 | You can install the development version of TheOpenAIR from [GitHub](https://github.com/) with: 16 | 17 | ``` r 18 | # install.packages("devtools") 19 | devtools::install_github("umatter/OpenAIR") 20 | ``` 21 | 22 | ## Usage 23 | 24 | To use the package, you'll need to have an OpenAI API key. You can sign up for an API key [here](https://platform.openai.com/signup/). Once you have your API key, you can start using *TheOpenAIR*: 25 | 26 | ``` r 27 | # load the package 28 | library("TheOpenAIR") 29 | 30 | # register your api key 31 | openai_api_key("YOUR-API-KEY") 32 | 33 | ``` 34 | 35 | Then, you can start chatting with the model. The simplest way of interacting with ChatGPT is the `chat()`-function. Using it is essentially the same as interacting with ChatGPT via the web GUI (https://chat.openai.com/chat). 36 | 37 | ```r 38 | # use chat() to interact with ChatGPT through the R console 39 | chat("Write a 100 words essay on why TheOpenAIR, 40 | an R package to integrate GPT models into your R workflows is fantastic. 41 | Write it in the style of product launches moderated by Steve Jobs.") 42 | ``` 43 | 44 | ``` 45 | Ladies and gentlemen, let me introduce you to TheOpenAIR, the latest and greatest addition to the R community. Thanks to TheOpenAIR, you can now integrate the cutting-edge GPT models right into your R workflows, unlocking a world of possibilities for predictive modeling and natural language processing. Whether you're an experienced data scientist or a newcomer to the field, TheOpenAIR makes it easier than ever to create powerful models that generate high-quality text. From business applications to academic research, TheOpenAIR has the power to transform the way we work with language data. So what are you waiting for? Join the excitement and embrace the future of data science with TheOpenAIR! 46 | ``` 47 | 48 | ```r 49 | chat("Now shorten the essay to 30 words.") 50 | ``` 51 | 52 | ``` 53 | TheOpenAIR - unleash the full power of GPT models in R workflows. 54 | ``` 55 | 56 | `chat()` is primarily useful for interactive mode. For writing short scripts and developing functions based on TheOpenAIR, the infix function `%c%` provides an alternative syntax to send messages to the model and indicate what output format is required. 57 | 58 | ```r 59 | # output to console 60 | "Remove all numeric characters from '5XC-2a09ujnap9o2q0MP'" %c% "message_to_console" 61 | ``` 62 | 63 | ``` 64 | The string without numeric characters would be 'XC-aujnapqMP'. 65 | ``` 66 | 67 | ```r 68 | # return the message as a string 69 | resp <- 70 | "Remove all numeric characters from '5XC-2a09ujnap9o2q0MP' 71 | In your response, only provide what remains from the string" %c% 72 | "message" 73 | 74 | resp 75 | ``` 76 | 77 | ``` 78 | [1] "XC-aujnapoqMP" 79 | ``` 80 | 81 | ## Code of Conduct 82 | 83 | For information about our code of conduct, please see the [Code of Conduct](inst/code_of_conduct.md) page. -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://openair-lib.org 2 | template: 3 | bootstrap: 5 4 | bslib: 5 | base_font: 6 | google: Raleway 7 | heading_font: 8 | google: Raleway 9 | code_font: 10 | google: JetBrains Mono 11 | authors: 12 | Ulrich Matter: 13 | href: http://umatter.github.io 14 | Jonathan Chassot: 15 | href: http://www.jldc.ch 16 | menu: 17 | - text: Code of Conduct 18 | href: CODE_OF_CONDUCT.md 19 | 20 | -------------------------------------------------------------------------------- /data/add_roxygen_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/add_roxygen_prompt.rda -------------------------------------------------------------------------------- /data/extract_entities_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/extract_entities_prompt.rda -------------------------------------------------------------------------------- /data/java_to_r_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/java_to_r_prompt.rda -------------------------------------------------------------------------------- /data/nested_to_pipe_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/nested_to_pipe_prompt.rda -------------------------------------------------------------------------------- /data/python_to_r_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/python_to_r_prompt.rda -------------------------------------------------------------------------------- /data/r_to_python_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/r_to_python_prompt.rda -------------------------------------------------------------------------------- /data/refactor_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/refactor_prompt.rda -------------------------------------------------------------------------------- /data/references_to_bibtex_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/references_to_bibtex_prompt.rda -------------------------------------------------------------------------------- /data/trump.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/trump.rda -------------------------------------------------------------------------------- /data/write_test_prompt.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/data/write_test_prompt.rda -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | 2 | # TheOpenAIR 3 | 4 | 5 | [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) 6 | [![R-CMD-check](https://github.com/umatter/OpenAIR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/umatter/OpenAIR/actions/workflows/R-CMD-check.yaml) 7 | 8 | 9 | Integrate OpenAI's GPT models into your R workflows. 10 | 11 | 12 | 13 | 14 | 15 | ## Installation 16 | 17 | You can install the development version of OpenAIR from [GitHub](https://github.com/) with: 18 | 19 | ``` r 20 | # install.packages("devtools") 21 | devtools::install_github("umatter/OpenAIR") 22 | ``` 23 | 24 | ## Usage 25 | 26 | To use the package, you'll need to have an OpenAI API key. You can sign up for an API key [here](https://platform.openai.com/signup/). Once you have your API key, you can start using *TheOpenAIR*: 27 | 28 | ``` r 29 | # load the package 30 | library("TheOpenAIR") 31 | 32 | # register your api key 33 | openai_api_key("YOUR-API-KEY") 34 | 35 | ``` 36 | 37 | Then, you can start chatting with the model. The simplest way of interacting with ChatGPT is the `chat()`-function. Using it is essentially the same as interacting with with ChatGPT via the web GUI (https://chat.openai.com/chat). 38 | 39 | ```r 40 | # use chat() to interact with ChatGPT through the R console 41 | chat("Write a 100 words essay on why TheOpenAIR, 42 | an R package to integrate GPT models into your R workflows is fantastic. 43 | Write it in the style of product launches moderated by Steve Jobs.") 44 | ``` 45 | 46 | ``` 47 | Ladies and gentlemen, let me introduce you to TheOpenAIR, the latest and greatest addition to the R community. Thanks to TheOpenAIR, you can now integrate the cutting-edge GPT models right into your R workflows, unlocking a world of possibilities for predictive modeling and natural language processing. Whether you're an experienced data scientist or a newcomer to the field, TheOpenAIR makes it easier than ever to create powerful models that generate high-quality text. From business applications to academic research, TheOpenAIR has the power to transform the way we work with language data. So what are you waiting for? Join the excitement and embrace the future of data science with TheOpenAIR! 48 | ``` 49 | 50 | ```r 51 | chat("Now shorten the essay to 30 words.") 52 | ``` 53 | 54 | ``` 55 | TheOpenAIR - unleash the full power of GPT models in R workflows. 56 | ``` 57 | 58 | `chat()` is primarily useful for interactive mode. For writing short scripts and developing functions based on TheOpenAIR, the infix function `%c%` provides an alternative syntax to send messages to the model and indicate what output format is required. 59 | 60 | ```r 61 | # output to console 62 | "Remove all numeric characters from '5XC-2a09ujnap9o2q0MP'" %c% 63 | "message_to_console" 64 | ``` 65 | 66 | ``` 67 | The string without numeric characters would be 'XC-aujnapqMP'. 68 | ``` 69 | 70 | ```r 71 | # return the message as a string 72 | resp <- 73 | "Remove all numeric characters from '5XC-2a09ujnap9o2q0MP' 74 | In your response, only provide what remains from the string" %c% 75 | "message" 76 | 77 | resp 78 | ``` 79 | 80 | ``` 81 | [1] "XC-aujnapoqMP" 82 | ``` 83 | 84 | ## Code of Conduct 85 | 86 | For information about our code of conduct, please see the [Code of Conduct](inst/code_of_conduct.md) page. -------------------------------------------------------------------------------- /inst/code_of_conduct.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Code of Conduct 3 | 4 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 5 | 6 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 7 | 8 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 9 | 10 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 11 | 12 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 13 | 14 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html 15 | -------------------------------------------------------------------------------- /inst/text/func.R: -------------------------------------------------------------------------------- 1 | 2 | object <- function(response) { 3 | # Check if the response is a list 4 | if (!is.list(response)) { 5 | stop("Invalid response format. Expected list object.") 6 | } 7 | 8 | # Extract the object from the response 9 | object <- response$object 10 | 11 | # Check if the object is a character string 12 | if (!is.character(object)) { 13 | stop("Invalid response format. object must be a character string.") 14 | } 15 | 16 | # Return the object 17 | return(object) 18 | } -------------------------------------------------------------------------------- /inst/text/persons.json: -------------------------------------------------------------------------------- 1 | {"firstName": "John", 2 | "lastName": "Smith", 3 | "age": 25, 4 | "address": { 5 | "streetAddress": "21 2nd Street", 6 | "city": "New York", 7 | "state": "NY", 8 | "postalCode": "10021" 9 | }, 10 | "phoneNumber": [ 11 | { 12 | "type": "home", 13 | "number": "212 555-1234" 14 | }, 15 | { 16 | "type": "fax", 17 | "number": "646 555-4567" 18 | } 19 | ], 20 | "gender": { 21 | "type": "male" 22 | } 23 | } -------------------------------------------------------------------------------- /inst/text/ref.txt: -------------------------------------------------------------------------------- 1 | Kuansan Wang, Zhihong Shen, Chiyuan Huang, Chieh-Han Wu , Yuxiao Dong, and Anshul Kanakia. 2020. Microsoft Academic Graph: When experts are not enough. Quantitative Science Studies , Vol. 1, 1 (2020), 396--413.Google ScholarCross RefOpenURL Universitat St Gallen 2 | Xiao Wang, Houye Ji, Chuan Shi, Bai Wang, Yanfang Ye, Peng Cui, and Philip S. Yu. 2019. Heterogeneous Graph Attention Network. In WWW 2019 .Google ScholarOpenURL Universitat St Gallen 3 | Thomas Wolf, Lysandre Debut, Victor Sanh, Julien Chaumond, Clement Delangue, Anthony Moi, Pierric Cistac, Tim Rault, Rémi Louf, Morgan Funtowicz, and Jamie Brew. 2019. Transformers: State-of-the-art Natural Language Processing. arxiv: cs.CL/1910.03771Google ScholarOpenURL Universitat St Gallen 4 | Zhilin Yang, Zihang Dai, Yiming Yang, Jaime G. Carbonell, Ruslan Salakhutdinov, and Quoc V. Le. 2019. XLNet: Generalized Autoregressive Pretraining for Language Understanding. In NeurIPS 2019 .Google ScholarOpenURL Universitat St Gallen 5 | Rex Ying, Ruining He, Kaifeng Chen, Pong Eksombatchai, William L. Hamilton, and Jure Leskovec. 2018. Graph Convolutional Neural Networks for Web-Scale Recommender Systems. In KDD 2018 .Google ScholarOpenURL Universitat St Gallen 6 | Jiaxuan You, Rex Ying, Xiang Ren, William L. Hamilton, and Jure Leskovec. 2018. GraphRNN: Generating Realistic Graphs with Deep Auto-regressive Models. In ICML 2018 .Google ScholarOpenURL Universitat St Gallen 7 | Fanjin Zhang, Xiao Liu, Jie Tang, Yuxiao Dong, Peiran Yao, Jie Zhang, Xiaotao Gu, Yan Wang, Bin Shao, Rui Li, and Kuansan Wang. 2019. OAG: Toward Linking Large-scale Heterogeneous Entity Graphs. In KDD 2019 .Google ScholarDigital LibraryOpenURL Universitat St Gallen 8 | Difan Zou, Ziniu Hu, Yewen Wang, Song Jiang, Yizhou Sun, and Quanquan Gu. 2019. Layer-Dependent Importance Sampling for Training Deep and Large Graph Convolutional Networks. In NeurIPS 2019 .Google ScholarOpenURL Universitat St Gallen -------------------------------------------------------------------------------- /man/TheOpenAIR-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/OpenAIR-package.R 3 | \docType{package} 4 | \name{TheOpenAIR-package} 5 | \alias{TheOpenAIR} 6 | \alias{TheOpenAIR-package} 7 | \title{TheOpenAIR: Integrate 'OpenAI' Large Language Models into Your 'R' Workflows} 8 | \description{ 9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} 10 | 11 | Utilizing the 'OpenAI' API as the back end (\url{https://platform.openai.com/docs/api-reference}), 'TheOpenAIR' offers 'R' wrapper functions for the 'ChatGPT' endpoint and several high-level functions that enable the integration of 'ChatGPT' capabilities in diverse data-related tasks, such as data cleansing and automated analytics script generation. 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{http://openair-lib.org/} 17 | } 18 | 19 | } 20 | \author{ 21 | \strong{Maintainer}: Ulrich Matter \email{umatter@protonmail.com} [copyright holder] 22 | 23 | Authors: 24 | \itemize{ 25 | \item Jonathan Chassot \email{jonathan.chassot@unisg.ch} 26 | } 27 | 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/add_roxygen.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/add_roxygen.R 3 | \name{add_roxygen} 4 | \alias{add_roxygen} 5 | \title{Add Roxygen2 documentation to an R function} 6 | \usage{ 7 | add_roxygen(file, ...) 8 | } 9 | \arguments{ 10 | \item{file}{A character string indicating the path to the file containing the 11 | R function.} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | If the path provided is a character string, this function returns the 17 | documented function as a character string. If the input is a file path, this 18 | function returns the path of the file to which documentation was added to the 19 | file. 20 | } 21 | \description{ 22 | This function adds Roxygen2 documentation to an R function. 23 | } 24 | \author{ 25 | Ulrich Matter umatter@protonmail.com 26 | } 27 | -------------------------------------------------------------------------------- /man/add_roxygen_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{add_roxygen_prompt} 5 | \alias{add_roxygen_prompt} 6 | \title{Input: message content template for add_roxygen()} 7 | \format{ 8 | ## `add_roxygen_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | add_roxygen_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the add_roxygen function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/add_to_chatlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/add_to_chatlog.R 3 | \name{add_to_chatlog} 4 | \alias{add_to_chatlog} 5 | \title{Add data to a chat log} 6 | \usage{ 7 | add_to_chatlog(msgs, chatlog_id = NULL) 8 | } 9 | \arguments{ 10 | \item{msgs}{A chatlog object or a data.frame containing the messages to be 11 | added to the chat log.} 12 | 13 | \item{chatlog_id}{The id of the chatlog object. Required when the provided 14 | msgs is a data.frame.} 15 | } 16 | \value{ 17 | The updated chatlog object with the newly added messages. 18 | } 19 | \description{ 20 | This function adds data to the in-memory chat log, which is in the global 21 | environment. The data can be any R object, such as a vector, list, or data 22 | frame. The function supports adding data to the chat log by providing either 23 | a data.frame or a chatlog object. 24 | } 25 | \examples{ 26 | \dontrun{ 27 | # Add a data frame of messages to an existing chat log 28 | chatlog_df <- data.frame( 29 | user = c("user1", "user2"), 30 | message = c("Hello!", "Hi!") 31 | ) 32 | updated_chatlog <- add_to_chatlog(chatlog_df, "existing_chatlog_id") 33 | 34 | # Add messages from one chat log to another 35 | chatlog1 <- create_chatlog("chatlog1") 36 | chatlog2 <- create_chatlog("chatlog2") 37 | chatlog1 <- add_message(chatlog1, "user1", "Hello!") 38 | chatlog2 <- add_message(chatlog2, "user2", "Hi!") 39 | merged_chatlog <- add_to_chatlog(chatlog1, chatlog2@chatlog_id) 40 | } 41 | } 42 | \author{ 43 | Ulrich Matter umatter@protonmail.com 44 | } 45 | -------------------------------------------------------------------------------- /man/chat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/chat.R 3 | \name{chat} 4 | \alias{chat} 5 | \title{Start or continue a chat conversation} 6 | \usage{ 7 | chat( 8 | message, 9 | chatlog_id = ".__CURRENTCHAT__", 10 | output = "message_to_console", 11 | ... 12 | ) 13 | } 14 | \arguments{ 15 | \item{message}{A character string representing the message to be added to the 16 | chat conversation.} 17 | 18 | \item{chatlog_id}{A character string representing the ID of the chat 19 | conversation to start or continue. Default is ".__CURRENTCHAT__".} 20 | 21 | \item{output}{A character string indicating the output format of the 22 | response. Default is "message_to_console". Valid options are 23 | "message_to_console", "message", or "response_object".} 24 | 25 | \item{...}{Additional arguments to pass to the chat_completion() function.} 26 | } 27 | \value{ 28 | Depending on the value of the 'output' argument, this function 29 | returns one of the following: 30 | * "message_to_console": a message containing the response text is printed to 31 | the console (default). 32 | * "message": the response text as a character vector. 33 | * "response_object": the full response object from the ChatGPT API. 34 | } 35 | \description{ 36 | This function starts or continues a chat conversation by adding the user's 37 | message to the conversation. 38 | If the conversation does not exist, a new one will be initiated. The response 39 | can be displayed in the 40 | console, returned as a character vector, or returned as a full response 41 | object from the ChatGPT API. 42 | } 43 | \examples{ 44 | \dontrun{ 45 | # Start a new chat and print the response to the console 46 | chat("What's the weather like today?") 47 | 48 | # Continue the chat, but return the response as a character vector 49 | response_text <- chat("What about tomorrow's weather?", output = "message") 50 | } 51 | } 52 | \author{ 53 | Ulrich Matter umatter@protonmail.com 54 | } 55 | -------------------------------------------------------------------------------- /man/chat_completion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/chat_completion.R 3 | \name{chat_completion} 4 | \alias{chat_completion} 5 | \title{Generate Text Using the OpenAI API's Chat Endpoint} 6 | \usage{ 7 | chat_completion( 8 | msgs, 9 | functions = NULL, 10 | function_call = NULL, 11 | model = "gpt-3.5-turbo", 12 | temperature = NULL, 13 | max_tokens = NULL, 14 | n = NULL, 15 | stop = NULL, 16 | presence_penalty = NULL, 17 | frequency_penalty = NULL, 18 | best_of = NULL, 19 | logit_bias = NULL, 20 | stream = FALSE, 21 | top_p = NULL, 22 | user = NULL 23 | ) 24 | } 25 | \arguments{ 26 | \item{msgs}{A data.frame containing the chat history to generate text from or 27 | a chatlog object} 28 | 29 | \item{functions}{An optional list of functions to use for the function call.} 30 | 31 | \item{function_call}{An optional list specifying the function call to use.} 32 | 33 | \item{model}{A character string specifying the ID of the model to use. 34 | The default value is "gpt-3.5-turbo".} 35 | 36 | \item{temperature}{An optional numeric scalar specifying the sampling 37 | temperature to use.} 38 | 39 | \item{max_tokens}{An optional integer scalar specifying the maximum number of 40 | tokens to generate in the text.} 41 | 42 | \item{n}{An optional integer scalar specifying the number of text completions 43 | to generate.} 44 | 45 | \item{stop}{An optional character string or character vector specifying one 46 | or more stop sequences to use when generating the text.} 47 | 48 | \item{presence_penalty}{An optional numeric scalar specifying the presence 49 | penalty to use when generating the text. The default value is NULL.} 50 | 51 | \item{frequency_penalty}{An optional numeric scalar specifying the frequency 52 | penalty to use when generating the text. The default value is NULL.} 53 | 54 | \item{best_of}{An optional integer scalar specifying the number of 55 | completions to generate and return the best one. The default value is NULL.} 56 | 57 | \item{logit_bias}{An optional named numeric vector specifying the logit bias 58 | to use for each token in the generated text.} 59 | 60 | \item{stream}{An optional logical scalar specifying whether to use the 61 | streaming API. The default value is \code{FALSE}.} 62 | 63 | \item{top_p}{An optional numeric scalar specifying the top p sampling ratio. 64 | The default value is NULL.} 65 | 66 | \item{user}{A unique identifier representing your end-user, which can help 67 | OpenAI to monitor and detect abuse.} 68 | } 69 | \value{ 70 | A character vector containing the generated text(s). 71 | } 72 | \description{ 73 | This function generates natural language text in a conversational style using 74 | the OpenAI API's chat endpoint. It takes a series of chat messages as input, 75 | either as a data.frame or a chatlog object, and generates a text completion 76 | based on the conversation history and the specified model parameters. 77 | } 78 | \examples{ 79 | \dontrun{ 80 | openai_api_key("your_api_key_here") 81 | msgs_df <- data.frame( 82 | role = c( 83 | "system", 84 | "user", 85 | "assistant", 86 | "user" 87 | ), 88 | content = c( 89 | "You are a helpful assistant", 90 | "Who won the world series in 2020?", 91 | "The Los Angeles Dodgers won the World Series in 2020.", 92 | "Where was it played?" 93 | ) 94 | ) 95 | chat_completion(msgs_df) 96 | } 97 | } 98 | \seealso{ 99 | \url{https://platform.openai.com/docs/} for more information on the 100 | OpenAI API. 101 | } 102 | \author{ 103 | Ulrich Matter umatter@protonmail.com 104 | } 105 | -------------------------------------------------------------------------------- /man/chatlog-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/class.R 3 | \docType{class} 4 | \name{chatlog-class} 5 | \alias{chatlog-class} 6 | \title{chatlog class} 7 | \description{ 8 | chatlog class 9 | } 10 | \section{Slots}{ 11 | 12 | \describe{ 13 | \item{\code{messages}}{The message data of the object} 14 | 15 | \item{\code{chatlog_id}}{The chatlog's ID} 16 | }} 17 | 18 | -------------------------------------------------------------------------------- /man/clean_output.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clean_output.R 3 | \name{clean_output} 4 | \alias{clean_output} 5 | \title{Clean Output From Code Responses} 6 | \usage{ 7 | clean_output(text) 8 | } 9 | \arguments{ 10 | \item{text}{A character string containing the code or text content with 11 | '```' markers.} 12 | } 13 | \value{ 14 | A character string containing the extracted code or text content. 15 | } 16 | \description{ 17 | This function extracts the content from a given text string that is enclosed 18 | between the '```' markers. It can be used to extract any kind of code or text 19 | content. 20 | } 21 | \examples{ 22 | code_text <- "``` 23 | example_code <- function(x) { 24 | return(x * 2) 25 | } 26 | ```" 27 | clean_output(code_text) 28 | } 29 | \author{ 30 | Ulrich Matter umatter@protonmail.com 31 | } 32 | -------------------------------------------------------------------------------- /man/clear_chatlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clear_chatlog.R 3 | \name{clear_chatlog} 4 | \alias{clear_chatlog} 5 | \title{Clear a chat log} 6 | \usage{ 7 | clear_chatlog(chatlog_id = ".__CURRENTCHAT__") 8 | } 9 | \arguments{ 10 | \item{chatlog_id}{character string indicating the name of the chat log to 11 | clear. 12 | Default is ".__CURRENTCHAT__".} 13 | } 14 | \value{ 15 | This function does not return anything. 16 | } 17 | \description{ 18 | This function clears a chat log, leaving only the initial (system) message. 19 | } 20 | \examples{ 21 | \dontrun{ 22 | # Clear the current chat log 23 | clear_chatlog() 24 | } 25 | } 26 | \author{ 27 | Ulrich Matter umatter@protonmail.com 28 | } 29 | -------------------------------------------------------------------------------- /man/contains_r_func.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contains_r_func.R 3 | \name{contains_r_func} 4 | \alias{contains_r_func} 5 | \title{Check if a text file or character string contains an R function definition} 6 | \usage{ 7 | contains_r_func(input) 8 | } 9 | \arguments{ 10 | \item{input}{A character string specifying the path to the text file, or a 11 | character 12 | string containing the text to be checked for an R function definition.} 13 | } 14 | \value{ 15 | A logical value (TRUE or FALSE) indicating whether the input 16 | contains a valid R function definition. 17 | } 18 | \description{ 19 | This function parses a text file or a character string and returns TRUE if it 20 | contains 21 | a valid R function definition. It uses a regex pattern to identify 22 | possible R function definitions and then attempts to parse the matched 23 | lines as R code. 24 | } 25 | \examples{ 26 | # Create a temporary file with an R function definition 27 | temp_file <- tempfile(fileext = ".R") 28 | writeLines("example_function <- function(x) {\n return(x * 2)\n}", 29 | temp_file) 30 | 31 | # Check if the temporary file contains an R function definition 32 | result <- contains_r_func(temp_file) 33 | print(result) # Should print TRUE 34 | 35 | # Check if a character string contains an R function definition 36 | result <- contains_r_func( 37 | "example_function <- function(x) { return(x * 2) }") 38 | print(result) # Should print TRUE 39 | 40 | # Remove the temporary file 41 | file.remove(temp_file) 42 | } 43 | -------------------------------------------------------------------------------- /man/contains_roxygen.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/contains_roxygen.R 3 | \name{contains_roxygen} 4 | \alias{contains_roxygen} 5 | \title{Check if a text file or character string contains Roxygen2 documentation} 6 | \usage{ 7 | contains_roxygen(input) 8 | } 9 | \arguments{ 10 | \item{input}{A character string specifying the path to the text file, or a 11 | character 12 | string containing the text to be checked for Roxygen2 documentation.} 13 | } 14 | \value{ 15 | A logical value (TRUE or FALSE) indicating whether the input 16 | contains Roxygen2 documentation. 17 | } 18 | \description{ 19 | This function parses a text file or a character string and returns TRUE if it 20 | contains 21 | Roxygen2 documentation. It uses a regex pattern to identify 22 | possible Roxygen2 documentation lines. 23 | } 24 | -------------------------------------------------------------------------------- /man/count_tokens.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/count_tokens.R 3 | \name{count_tokens} 4 | \alias{count_tokens} 5 | \title{Count the number of tokens in a text string} 6 | \usage{ 7 | count_tokens(text) 8 | } 9 | \arguments{ 10 | \item{text}{A file path, URL or character string representing the text to be 11 | tokenized.} 12 | } 13 | \value{ 14 | An integer representing the number of tokens in the text. 15 | } 16 | \description{ 17 | This function takes a file path, URL or character string as input and 18 | returns the number of tokens in the text. Tokens are defined as words and/or 19 | special characters. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | # Example 1: File path 24 | test_file_path <- tempfile() 25 | writeLines("This is a test.", test_file_path) 26 | expect_equal(count_tokens(test_file_path), 5) 27 | file.remove(test_file_path) 28 | 29 | # Example 2: URL 30 | url <- "https://www.gutenberg.org/files/2701/2701-0.txt" 31 | count_tokens(url) 32 | 33 | # Example 3: Character string 34 | text <- "This is a test string." 35 | count_tokens(text) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /man/created.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/created.R 3 | \name{created} 4 | \alias{created} 5 | \title{Extract Created DateTime from OpenAI API response} 6 | \usage{ 7 | created(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a Date object representing the date-time string of when the response 14 | was created 15 | } 16 | \description{ 17 | This function extracts the date-time string of when the response was created 18 | from the parsed HTTP response of an API call to the 19 | OpenAI chat completions endpoint. 20 | } 21 | \author{ 22 | Ulrich Matter umatter@protonmail.com 23 | } 24 | -------------------------------------------------------------------------------- /man/df_to_csv.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/df_to_csv.R 3 | \name{df_to_csv} 4 | \alias{df_to_csv} 5 | \title{Convert a data.frame to a CSV-formatted character string} 6 | \usage{ 7 | df_to_csv(df) 8 | } 9 | \arguments{ 10 | \item{df}{A data.frame to be converted to a CSV-formatted character string.} 11 | } 12 | \value{ 13 | A character string representing the data values in the input 14 | data.frame 15 | formatted as a CSV file. 16 | } 17 | \description{ 18 | The `df_to_csv` function takes a data.frame as input and returns a character 19 | string representing the content of the original data.frame formatted as a CSV 20 | file. 21 | The resulting CSV-formatted string can be written to a file or further 22 | processed 23 | as needed. 24 | } 25 | \examples{ 26 | # Create a data.frame 27 | example_data <- data.frame( 28 | Name = c("Alice", "Bob", "Carol"), 29 | Age = c(30, 25, 28), 30 | Height = c(168, 175, 162), 31 | stringsAsFactors = FALSE 32 | ) 33 | 34 | # Convert the data.frame to a CSV-formatted character string 35 | csv_string <- df_to_csv(example_data) 36 | cat(csv_string) 37 | } 38 | -------------------------------------------------------------------------------- /man/edit_code.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/edit_code.R 3 | \name{edit_code} 4 | \alias{edit_code} 5 | \title{Edit code based on user's input} 6 | \usage{ 7 | edit_code(filename, chatlog_id = ".__CURRENTCODEFILE__", ...) 8 | } 9 | \arguments{ 10 | \item{filename}{A character string representing the name of the file 11 | containing the code to be edited.} 12 | 13 | \item{chatlog_id}{An optional character string representing the chatlog ID. 14 | Defaults to ".__CURRENTCODEFILE__". This ID is used to maintain the 15 | conversation history with the AI.} 16 | 17 | \item{...}{Additional arguments to pass to the chat_completion() function.} 18 | } 19 | \value{ 20 | Returns the name of the file containing the modified code. 21 | } 22 | \description{ 23 | The `edit_code` function prompts the user to provide a plain English 24 | description of how the code in a given file should be modified. The function 25 | then generates the modified code based on the user's input and writes it back 26 | to the specified file. 27 | } 28 | \examples{ 29 | \dontrun{ 30 | # Edit code in an existing file based on user input 31 | modified_code_file <- edit_code("example_code.R") 32 | 33 | # Check the content of the modified code file 34 | cat(readLines(modified_code_file)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /man/extract_blocks.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_blocks.R 3 | \name{extract_blocks} 4 | \alias{extract_blocks} 5 | \title{Extract blocks of a specified type from a list of blocks} 6 | \usage{ 7 | extract_blocks(block_list, block_type) 8 | } 9 | \arguments{ 10 | \item{block_list}{A list of blocks} 11 | 12 | \item{block_type}{The type of blocks to be extracted} 13 | } 14 | \value{ 15 | A list of blocks of the specified type 16 | } 17 | \description{ 18 | Extract blocks of a specified type from a list of blocks 19 | } 20 | \examples{ 21 | \dontrun{ 22 | # Example 1: Extract 'code' blocks 23 | blocks <- list( 24 | list(type = "text", content = "Hello world!"), 25 | list(type = "code", content = "print('Hello world!')") 26 | ) 27 | extract_blocks(blocks, "code") 28 | # Output: 29 | # [[1]] 30 | # $type 31 | # [1] "code" 32 | # 33 | # $content 34 | # [1] "print('Hello world!')" 35 | 36 | # Example 2: Extract 'text' blocks 37 | blocks <- list( 38 | list(type = "text", content = "Hello world!"), 39 | list(type = "code", content = "print('Hello world!')") 40 | ) 41 | extract_blocks(blocks, "text") 42 | # Output: 43 | # [[1]] 44 | # $type 45 | # [1] "text" 46 | # 47 | # $content 48 | # [1] "Hello world!" 49 | } 50 | } 51 | \author{ 52 | Jonathan Chassot 53 | } 54 | -------------------------------------------------------------------------------- /man/extract_blocks_content.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_blocks_content.R 3 | \name{extract_blocks_content} 4 | \alias{extract_blocks_content} 5 | \title{Extract the content parts of blocks} 6 | \usage{ 7 | extract_blocks_content(block_list) 8 | } 9 | \arguments{ 10 | \item{block_list}{A list of blocks to extract the content from} 11 | } 12 | \value{ 13 | A list of content parts 14 | } 15 | \description{ 16 | This function takes a list of blocks and returns a list of their content 17 | parts. 18 | } 19 | -------------------------------------------------------------------------------- /man/extract_entities.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_entities.R 3 | \name{extract_entities} 4 | \alias{extract_entities} 5 | \title{Extract Entities from a Text} 6 | \usage{ 7 | extract_entities( 8 | text, 9 | entity_types = c("locations", "persons", "organizations"), 10 | batch_size = NULL, 11 | ... 12 | ) 13 | } 14 | \arguments{ 15 | \item{text}{A character string containing the text to be processed, or a path 16 | to a text file} 17 | 18 | \item{entity_types}{A character vector containing names of entity types to 19 | be extracted. Defaults to c("locations", "persons", "organizations").} 20 | 21 | \item{batch_size}{An integer indicating the size of each batch, if the text 22 | input is supposed to be processed in batches. Set this to NULL to process all 23 | at once.} 24 | 25 | \item{...}{Additional arguments to pass to the chat_completion() function.} 26 | } 27 | \value{ 28 | A tibble 29 | } 30 | \description{ 31 | This function takes a character string or a path to a text file and returns 32 | a tibble describing the entities found in the text. The type of entities to 33 | be searched for and extracted can be defined by the user. 34 | } 35 | \examples{ 36 | \dontrun{ 37 | extract_entities("Hello, how are you?") 38 | extract_entities("path/to/text/file.txt", batch_size = 100) 39 | } 40 | 41 | } 42 | \author{ 43 | Ulrich Matter umatter@protonmail.com 44 | } 45 | -------------------------------------------------------------------------------- /man/extract_entities_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{extract_entities_prompt} 5 | \alias{extract_entities_prompt} 6 | \title{Input: message content template for extract_entities()} 7 | \format{ 8 | ## `extract_entities_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | extract_entities_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the extract_entities function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/extract_r_code.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_r_code.R 3 | \name{extract_r_code} 4 | \alias{extract_r_code} 5 | \title{Extract R code and comments from a given input string.} 6 | \usage{ 7 | extract_r_code(input_string) 8 | } 9 | \arguments{ 10 | \item{input_string}{A character string containing R code and comments, mixed 11 | with other text. The string may contain multiple lines separated by newline 12 | characters.} 13 | } 14 | \value{ 15 | A character vector containing R code and comment lines extracted from 16 | the input string. Each element in the vector corresponds to one line of code 17 | or a comment. 18 | } 19 | \description{ 20 | This function takes an input string, detects R code and comments, and returns 21 | a character vector containing the R code and comments. The input string is 22 | split into lines based on newline characters, and each line is examined for R 23 | code and comment patterns. Only the lines that match either of these patterns 24 | are returned. 25 | } 26 | \examples{ 27 | example_string <- 28 | "This is a text string with R code and comments.\n 29 | # A comment\n 30 | x <- 5\ 31 | ny = 10\n 32 | z <- x + y\n 33 | Another line of text." 34 | extract_r_code(example_string) 35 | } 36 | -------------------------------------------------------------------------------- /man/extract_roxygen2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_roxygen2.R 3 | \name{extract_roxygen2} 4 | \alias{extract_roxygen2} 5 | \title{Extract roxygen2 documentation lines from a function definition} 6 | \usage{ 7 | extract_roxygen2(func_def) 8 | } 9 | \arguments{ 10 | \item{func_def}{A character vector containing the lines of a function 11 | definition} 12 | } 13 | \value{ 14 | A character string containing the roxygen2 documentation lines 15 | } 16 | \description{ 17 | This function takes a character vector containing the lines of a function 18 | definition and returns a character string containing only the lines 19 | belonging to the roxygen2 documentation (lines starting with "#'"). 20 | } 21 | \examples{ 22 | func_def <- c( 23 | "#' Extracts object from a response list", 24 | "#'", 25 | "#' @export", 26 | "object <- function(response) {", 27 | " if (!is.list(response)) {", 28 | " stop('Invalid response format. Expected list object.')", 29 | " }", 30 | "}") 31 | 32 | roxygen2_docu <- extract_roxygen2(func_def) 33 | print(roxygen2_docu) 34 | } 35 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/man/figures/logo.png -------------------------------------------------------------------------------- /man/get_chatlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_chatlog.R 3 | \name{get_chatlog} 4 | \alias{get_chatlog} 5 | \title{Get the current chatlog} 6 | \usage{ 7 | get_chatlog(x = ".__CURRENTCHAT__") 8 | } 9 | \arguments{ 10 | \item{x}{either a chatlog object r, or a character string representing the id 11 | of a chatlog (the default is ".__CURRENTCHAT__", the current log of the 12 | chat()-function)} 13 | } 14 | \value{ 15 | a chatlog object 16 | } 17 | \description{ 18 | This function extracts the current chatlog of a given chat from the chat 19 | environment. 20 | } 21 | \author{ 22 | Ulrich Matter umatter@protonmail.com 23 | } 24 | -------------------------------------------------------------------------------- /man/grapes-c-grapes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grapes_c_grapes.R 3 | \name{\%c\%} 4 | \alias{\%c\%} 5 | \title{Send a message to ChatGPT and assign the response to a variable} 6 | \usage{ 7 | message \%c\% output 8 | } 9 | \arguments{ 10 | \item{message}{A character string containing the message to be sent to the 11 | ChatGPT API.} 12 | 13 | \item{output}{A character string specifying the output format. Valid options 14 | are "message_to_console", "message", or "response_object". Default is 15 | "message_to_console".} 16 | } 17 | \value{ 18 | Depending on the value of the 'output' argument, this function 19 | returns one of the following: 20 | * "message_to_console": a message containing the response text to be 21 | printed to the console. 22 | * "message": the response text as a character vector. 23 | * "response_object": the full response object from the ChatGPT API. 24 | } 25 | \description{ 26 | This function sends a message to the ChatGPT API using the 'chat()' function 27 | and returns the response in the specified output format. 28 | } 29 | \examples{ 30 | \dontrun{ 31 | # Send a message and assign the response to a variable 32 | response_var <- "Hello, ChatGPT!" \%c\% "message" 33 | 34 | # Print the response 35 | print(response_var) 36 | 37 | # Send a message and return the full response object 38 | response_obj <- "Hello, ChatGPT!" \%c\% "response_object" 39 | 40 | # Print the response 41 | print(response_obj) 42 | } 43 | } 44 | \author{ 45 | Ulrich Matter umatter@protonmail.com 46 | } 47 | -------------------------------------------------------------------------------- /man/id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/id.R 3 | \name{id} 4 | \alias{id} 5 | \title{Extract ID from OpenAI API response} 6 | \usage{ 7 | id(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a character string representing the ID from the response 14 | } 15 | \description{ 16 | This function extracts the ID from the parsed HTTP response of an API call 17 | to the OpenAI chat completions endpoint. 18 | } 19 | \author{ 20 | Ulrich Matter umatter@protonmail.com 21 | } 22 | -------------------------------------------------------------------------------- /man/initialize_messages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/initialize_messages.R 3 | \name{initialize_messages} 4 | \alias{initialize_messages} 5 | \title{Initialize a new messages object for OpenAI API chat completions} 6 | \usage{ 7 | initialize_messages( 8 | initial_role = "system", 9 | initial_content = "You are a helpful assistant." 10 | ) 11 | } 12 | \arguments{ 13 | \item{initial_role}{A character string representing the role issueing the 14 | initial content (per default: "system")} 15 | 16 | \item{initial_content}{A character string representing the initial message 17 | from the system} 18 | } 19 | \value{ 20 | A data frame containing a single message from the system to the user, 21 | with columns for the 22 | message role and content. 23 | } 24 | \description{ 25 | This function initializes a new messages object as a template for messages 26 | sent to the OpenAI API https://api.openai.com/v1/chat/completions endpoint. 27 | By default, the template contains a single message from the system to the 28 | user with the initial content "You are a helpful assistant.", but you can 29 | customize the content by specifying a different value for the 30 | "initial_system_content" parameter. 31 | } 32 | \examples{ 33 | messages <- initialize_messages() 34 | messages_custom <- initialize_messages("Hello! How can I assist you today?") 35 | 36 | } 37 | \author{ 38 | Ulrich Matter umatter@protonmail.com 39 | } 40 | -------------------------------------------------------------------------------- /man/install_tiktoken.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install_tiktoken.R 3 | \name{install_tiktoken} 4 | \alias{install_tiktoken} 5 | \title{Install the tiktoken Python package} 6 | \usage{ 7 | install_tiktoken(method = "auto", conda = "auto") 8 | } 9 | \arguments{ 10 | \item{method}{The installation method to use. Can be one of "auto" (default), 11 | "conda", "virtualenv", "pip", or "windows".} 12 | 13 | \item{conda}{The name or path of the Conda environment to use for the 14 | installation, or "auto" (default) to let reticulate automatically manage the 15 | environment.} 16 | } 17 | \description{ 18 | This function installs the tiktoken Python package using the specified 19 | installation method and Conda environment (if any). 20 | } 21 | -------------------------------------------------------------------------------- /man/is_chatlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is_chaglog.R 3 | \name{is_chatlog} 4 | \alias{is_chatlog} 5 | \title{Determine if an object is a chatlog} 6 | \usage{ 7 | is_chatlog(object) 8 | } 9 | \arguments{ 10 | \item{object}{An R object to check} 11 | } 12 | \value{ 13 | TRUE if the object is of class "chatlog", FALSE otherwise 14 | } 15 | \description{ 16 | This function checks if an object is of class "chatlog". 17 | } 18 | \examples{ 19 | is_chatlog("Hello, World!") 20 | # [1] FALSE 21 | 22 | chat <- new("chatlog") 23 | is_chatlog(chat) 24 | # [1] TRUE 25 | } 26 | \author{ 27 | Ulrich Matter umatter@protonmail.com 28 | } 29 | -------------------------------------------------------------------------------- /man/is_json.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is_json.R 3 | \name{is_json} 4 | \alias{is_json} 5 | \title{Check if the provided string is in valid JSON format.} 6 | \usage{ 7 | is_json(input_string) 8 | } 9 | \arguments{ 10 | \item{input_string}{A character string to be checked for JSON format.} 11 | } 12 | \value{ 13 | A logical value. If the input string is in valid JSON format, returns 14 | TRUE, otherwise returns FALSE. 15 | } 16 | \description{ 17 | Check if the provided string is in valid JSON format. 18 | } 19 | \examples{ 20 | is_json('{"name": "John", "age": 30}') 21 | # TRUE 22 | 23 | is_json('{"name": "John", age: 30}') 24 | # FALSE 25 | 26 | is_json('') 27 | # FALSE 28 | } 29 | \author{ 30 | Ulrich Matter umatter@protonmail.com 31 | } 32 | -------------------------------------------------------------------------------- /man/is_python.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is_python.R 3 | \name{is_python} 4 | \alias{is_python} 5 | \title{Check if a Character String Contains Valid Python Code} 6 | \usage{ 7 | is_python(code) 8 | } 9 | \arguments{ 10 | \item{code}{A character string containing code to be checked for Python code 11 | validity.} 12 | } 13 | \value{ 14 | A logical value: TRUE if the input character string contains valid 15 | Python code, and FALSE otherwise. 16 | } 17 | \description{ 18 | This function takes a character string as input and checks if it contains 19 | valid Python code. It returns TRUE if the string contains valid Python code, 20 | and FALSE otherwise. 21 | } 22 | \details{ 23 | This function presuposes that python is installed on the system. 24 | } 25 | \examples{ 26 | \dontrun{ 27 | # Check if the string contains valid Python code 28 | is_python("print('Hello, World!')") 29 | 30 | # Check if the string contains invalid Python code 31 | is_python("prit('Hello, World!')") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /man/is_r.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is_r.R 3 | \name{is_r} 4 | \alias{is_r} 5 | \title{Check if a character string contains valid R code} 6 | \usage{ 7 | is_r(code) 8 | } 9 | \arguments{ 10 | \item{code}{A character string containing the R code to be checked.} 11 | } 12 | \value{ 13 | A logical value indicating whether the input code string contains 14 | valid R code or not. 15 | } 16 | \description{ 17 | This function takes a character string as input and attempts to parse it as 18 | R code using the `parse` function. If the parsing is successful, the function 19 | returns TRUE, indicating that the input string contains valid R code. If 20 | parsing fails, the function returns FALSE. 21 | } 22 | \examples{ 23 | # Valid R code 24 | valid_code <- "x <- 5; y <- 10; z <- x + y" 25 | is_r(valid_code) 26 | 27 | # Invalid R code 28 | invalid_code <- "x <- 5 + 'a'" 29 | is_r(invalid_code) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /man/is_xml.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is_xml.R 3 | \name{is_xml} 4 | \alias{is_xml} 5 | \title{Check if the provided string is in valid XML format.} 6 | \usage{ 7 | is_xml(input_string) 8 | } 9 | \arguments{ 10 | \item{input_string}{A character string to be checked for XML format.} 11 | } 12 | \value{ 13 | A logical value. If the input string is in valid XML format, returns 14 | TRUE, otherwise returns FALSE. 15 | } 16 | \description{ 17 | Check if the provided string is in valid XML format. 18 | } 19 | \examples{ 20 | is_xml('value') 21 | # TRUE 22 | 23 | is_xml('value') 24 | # FALSE 25 | 26 | is_xml('') 27 | # FALSE 28 | } 29 | \author{ 30 | Ulrich Matter umatter@protonmail.com 31 | } 32 | -------------------------------------------------------------------------------- /man/java_to_r.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/java_to_r.R 3 | \name{java_to_r} 4 | \alias{java_to_r} 5 | \title{Convert Java code to R code} 6 | \usage{ 7 | java_to_r(java, ...) 8 | } 9 | \arguments{ 10 | \item{java}{A character string containing the Java code to be converted to R, 11 | or a filename with the Java code.} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | If the input is a character string, the resulting R code will be 17 | printed and returned as a character string. If the input is a filename, the 18 | resulting R code will be saved as a file with the same name as the input 19 | file, but with the extension `.R`, and the filename will be returned. 20 | } 21 | \description{ 22 | This function takes Java code as input and returns the corresponding R code. 23 | It uses GPT-4 powered chat to perform the code conversion. 24 | } 25 | \details{ 26 | This function is not guaranteed to provide perfect conversions and 27 | might produce invalid R code in some cases. Users are encouraged to verify 28 | the output code carefully. 29 | } 30 | \examples{ 31 | \dontrun{ 32 | # Convert a simple Java code snippet to R 33 | java_code <- "public class HelloWorld { 34 | public static void main(String[] args) { 35 | System.out.println(\"Hello, world!\"); 36 | } 37 | }" 38 | r_code <- java_to_r(java_code) 39 | cat(r_code) 40 | 41 | # Convert Java code from a file and save the result to an R file 42 | input_file <- "path/to/java_file.java" 43 | output_file <- java_to_r(input_file) 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /man/java_to_r_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{java_to_r_prompt} 5 | \alias{java_to_r_prompt} 6 | \title{Input: message content template for java_to_r()} 7 | \format{ 8 | ## `java_to_r_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | java_to_r_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the java_to_r() function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/messages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/messages.R 3 | \name{messages} 4 | \alias{messages} 5 | \title{Extract messages from a response object or a chatlog object} 6 | \usage{ 7 | messages(x) 8 | } 9 | \arguments{ 10 | \item{x}{A list representing a response object or a chatlog object} 11 | } 12 | \value{ 13 | A data.frame containing the messages 14 | } 15 | \description{ 16 | This function takes a response object or a chatlog object as input and 17 | returns the messages. If the input is a response object, the function 18 | extracts and returns the messages from the choices. If the input is a 19 | chatlog object, the function returns the messages directly. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | # Using a response object 24 | response <- list(choices = list(message = "This is a message.")) 25 | messages_from_response <- messages(response) 26 | print(messages_from_response) 27 | 28 | # Using a chatlog object 29 | chatlog_id <- chat("Hello, how are you?") 30 | chatlog <- get_chatlog(chatlog_id) 31 | messages_from_chatlog <- messages(chatlog) 32 | print(messages_from_chatlog) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /man/messages_content.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/messages_content.R 3 | \name{messages_content} 4 | \alias{messages_content} 5 | \title{Extract Messages Content from OpenAI API Response} 6 | \usage{ 7 | messages_content(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a character string representing the choices/messages from the 14 | response 15 | } 16 | \description{ 17 | This function extracts the messages content from the HTTP response of an API 18 | call to the OpenAI chat completions endpoint. 19 | } 20 | \author{ 21 | Ulrich Matter umatter@protonmail.com 22 | } 23 | -------------------------------------------------------------------------------- /man/model.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/model.R 3 | \name{model} 4 | \alias{model} 5 | \title{Extract Model from OpenAI API response} 6 | \usage{ 7 | model(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a character string representing the model from the response 14 | } 15 | \description{ 16 | This function extracts the model from the parsed HTTP response of an API 17 | call to the OpenAI chat completions endpoint. 18 | } 19 | \author{ 20 | Ulrich Matter umatter@protonmail.com 21 | } 22 | -------------------------------------------------------------------------------- /man/nested_to_pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nested_to_pipe.R 3 | \name{nested_to_pipe} 4 | \alias{nested_to_pipe} 5 | \title{Convert nested R code to pipe syntax} 6 | \usage{ 7 | nested_to_pipe(r, n_tokens_limit = 3000, ...) 8 | } 9 | \arguments{ 10 | \item{r}{A file path or character string containing the R code to be 11 | converted.} 12 | 13 | \item{n_tokens_limit}{The maximum number of tokens allowed in the input text 14 | (default: 3000).} 15 | 16 | \item{...}{Additional arguments to pass to the chat_completion() function.} 17 | } 18 | \value{ 19 | If r is a character string, the function returns the converted R code 20 | as a character string. If r is a file path, the function writes the converted 21 | code to a new file with the same name and a "-pipe.R" suffix, and returns the 22 | path to the output file. 23 | } 24 | \description{ 25 | This function takes an R script containing traditional (nested syntax) R 26 | code and converts it to magrittr-style syntax, using the pipe (%>%) operator. 27 | It also validates the input and output code to ensure proper R syntax. 28 | } 29 | \examples{ 30 | \dontrun{ 31 | # Converting a character string 32 | input <- "result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)" 33 | output <- nested_to_pipe(input) 34 | cat(output) 35 | 36 | # Converting a file 37 | # Create a temporary input file 38 | input_file <- tempfile(fileext = ".R") 39 | write("result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)", input_file) 40 | 41 | # Convert the file using nested_to_pipe 42 | output_file <- nested_to_pipe(input_file) 43 | 44 | # Check the converted file content 45 | cat(readLines(output_file)) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /man/nested_to_pipe_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{nested_to_pipe_prompt} 5 | \alias{nested_to_pipe_prompt} 6 | \title{Input: message content template for nested_to_pipe()} 7 | \format{ 8 | ## `nested_to_pipe_prompt` 9 | A data frame with 4 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | nested_to_pipe_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the nested_to_pipe() function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/num_tokens.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/num_tokens.R 3 | \name{num_tokens} 4 | \alias{num_tokens} 5 | \title{Get number of tokens in a string using OpenAI's tiktoken library} 6 | \usage{ 7 | num_tokens(text, encoding = "cl100k_base") 8 | } 9 | \arguments{ 10 | \item{text}{a character string to count the number of tokens from} 11 | 12 | \item{encoding}{a character string that specifies how text is converted into 13 | tokens. The default is "cl100k_base" (for ChatGPT models; see 14 | https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb 15 | for details)} 16 | } 17 | \value{ 18 | an integer indicating the number of tokens in the input string 19 | } 20 | \description{ 21 | This function uses the num_tokens_from_string function provided in OpenAI's 22 | tiktoken python library to get the number of tokens in a string. 23 | } 24 | \references{ 25 | https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb 26 | } 27 | -------------------------------------------------------------------------------- /man/num_tokens_file.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/num_tokens_file.R 3 | \name{num_tokens_file} 4 | \alias{num_tokens_file} 5 | \title{Compute total number of tokens in a text file} 6 | \usage{ 7 | num_tokens_file(filename, batch_size = 1000, encoding = "cl100k_base") 8 | } 9 | \arguments{ 10 | \item{filename}{character string indicating the name of the text file to 11 | read in} 12 | 13 | \item{batch_size}{integer indicating the number of lines to read in per batch 14 | (default is 1000)} 15 | 16 | \item{encoding}{character string indicating the encoding to use 17 | (default is "cl100k_base")} 18 | } 19 | \value{ 20 | a numeric value indicating the total number of tokens in the text 21 | file 22 | } 23 | \description{ 24 | The function batch-wise computes the total number of tokens in a text file. 25 | The function returns a numeric value indicating the total number of tokens 26 | in the file. The function can be used on very large text files. 27 | } 28 | -------------------------------------------------------------------------------- /man/object.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/object.R 3 | \name{object} 4 | \alias{object} 5 | \title{Extract object information from OpenAI API response} 6 | \usage{ 7 | object(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a data frame with the usage statistics of the API call (how many 14 | tokens used) 15 | } 16 | \description{ 17 | This function extracts the object data from the parsed HTTP response of an 18 | API call to the OpenAI chat completions endpoint (provides information about 19 | the endpoint). 20 | } 21 | \author{ 22 | Ulrich Matter umatter@protonmail.com 23 | } 24 | -------------------------------------------------------------------------------- /man/openai_api_key.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/openai_api_key.R 3 | \name{openai_api_key} 4 | \alias{openai_api_key} 5 | \title{Set OpenAI API Key as an Environment Variable} 6 | \usage{ 7 | openai_api_key(api_key) 8 | } 9 | \arguments{ 10 | \item{api_key}{A character string containing the OpenAI API key.} 11 | } 12 | \value{ 13 | Nothing is returned; the function is called for its side effects. 14 | } 15 | \description{ 16 | This function sets the OpenAI API key as an environment variable in the 17 | current R session. It takes the API key as an input and stores it as an 18 | environment variable, allowing other functions to access the key when needed. 19 | } 20 | \examples{ 21 | \dontrun{ 22 | # Set the OpenAI API key for the current R session 23 | openai_api_key("your_api_key_here") 24 | } 25 | } 26 | \seealso{ 27 | \url{https://platform.openai.com/docs/} for more information 28 | on the OpenAI API. 29 | } 30 | \author{ 31 | Ulrich Matter umatter@protonmail.com 32 | } 33 | -------------------------------------------------------------------------------- /man/parse_response.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse_response.R 3 | \name{parse_response} 4 | \alias{parse_response} 5 | \title{Parse a Response From the API} 6 | \usage{ 7 | parse_response(input_string) 8 | } 9 | \arguments{ 10 | \item{input_string}{The response from the API} 11 | } 12 | \value{ 13 | A list of blocks with type, content, and language (for code blocks) 14 | } 15 | \description{ 16 | This function takes an input string containing both text and code blocks, 17 | and returns a list of blocks with their respective type, content, and 18 | language (if applicable). 19 | Each block is either of type 'text' or 'code'. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | parse_response("Hello world!") 24 | # [[1]] 25 | # [[1]]$type 26 | # [1] "text" 27 | # 28 | # [[1]]$content 29 | # [1] "Hello world!" 30 | # 31 | parse_response("```python\nprint('Hello world!')\n```") 32 | # [[1]] 33 | # [[1]]$type 34 | # [1] "code" 35 | # 36 | # [[1]]$content 37 | # [1] "print('Hello world!')" 38 | # 39 | # [[1]]$language 40 | # [1] "python" 41 | # 42 | parse_response("Hello world!\n\n```python\nprint('Hello world!')\n```") 43 | # [[1]] 44 | # [[1]]$type 45 | # [1] "text" 46 | # 47 | # [[1]]$content 48 | # [1] "Hello world!" 49 | # 50 | # [[2]] 51 | # [[2]]$type 52 | # [1] "code" 53 | # 54 | # [[2]]$content 55 | # [1] "print('Hello world!')" 56 | # 57 | # [[2]]$language 58 | # [1] "python" 59 | # 60 | } 61 | } 62 | \author{ 63 | Jonathan Chassot 64 | } 65 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \arguments{ 10 | \item{lhs}{A value or the magrittr placeholder.} 11 | 12 | \item{rhs}{A function call using the magrittr semantics.} 13 | } 14 | \value{ 15 | The result of calling `rhs(lhs)`. 16 | } 17 | \description{ 18 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 19 | } 20 | \keyword{internal} 21 | -------------------------------------------------------------------------------- /man/python_to_r.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/python_to_r.R 3 | \name{python_to_r} 4 | \alias{python_to_r} 5 | \title{Convert Python code to R code} 6 | \usage{ 7 | python_to_r(py, ...) 8 | } 9 | \arguments{ 10 | \item{py}{A file path or character string containing the Python code to be 11 | converted.} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | If the input is a character string, the function returns the 17 | converted R code as a character string. If the input is a file, the function 18 | writes the converted R code to a new file with the same name and a ".R" 19 | extension, and returns the output file path. 20 | } 21 | \description{ 22 | This function takes a Python code file or character string as input and 23 | attempts to convert the code to R using the OpenAI API. The function provides 24 | feedback on the total tokens used during the conversion and warns if the 25 | output might not be valid R code. 26 | } 27 | \examples{ 28 | \dontrun{ 29 | # Convert a Python code string to R code 30 | python_code <- "x = 5" 31 | r_code <- python_to_r(python_code) 32 | print(r_code) 33 | 34 | # Convert a Python code file to an R code file 35 | python_file <- "path/to/your/python_file.py" 36 | r_file <- python_to_r(python_file) 37 | cat(readLines(r_file), sep = "\n") 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /man/python_to_r_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{python_to_r_prompt} 5 | \alias{python_to_r_prompt} 6 | \title{Input: message content template for python_to_r()} 7 | \format{ 8 | ## `python_to_r_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | python_to_r_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the python_to_r() function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/r_to_python.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/r_to_python.R 3 | \name{r_to_python} 4 | \alias{r_to_python} 5 | \title{Convert R Code to Python Code} 6 | \usage{ 7 | r_to_python(r, ...) 8 | } 9 | \arguments{ 10 | \item{r}{The R code file to be converted to Python code. This should be a 11 | file path in the form of a character string.} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | If the input filename is a "character string", the converted Python 17 | code will be returned as a character string. Otherwise, a new Python file 18 | will be created with the same name as the input file but with a ".py" 19 | extension, and the function will return the file path of the newly created 20 | Python file. 21 | } 22 | \description{ 23 | This function takes an R code file as input and uses a language model to 24 | convert the R code to Python code. The converted Python code is then either 25 | returned as a character string or written to a file, depending on the input. 26 | } 27 | \examples{ 28 | \dontrun{ 29 | # Convert R code to Python code and display the result as a character string 30 | r_to_python("example.R") 31 | 32 | # Convert R code to Python code and save it to a file 33 | r_to_python("example.R", output_file = "example.py") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /man/r_to_python_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{r_to_python_prompt} 5 | \alias{r_to_python_prompt} 6 | \title{Input: message content template for r_to_python()} 7 | \format{ 8 | ## `r_to_python_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | r_to_python_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the r_to_python() function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/read_text.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/read_text.R 3 | \name{read_text} 4 | \alias{read_text} 5 | \title{Convert Text to Tidy-Text Format} 6 | \usage{ 7 | read_text(text) 8 | } 9 | \arguments{ 10 | \item{text}{A character string containing the text to be converted, or a 11 | path to a text file.} 12 | } 13 | \value{ 14 | A tibble containing the converted text in tidy-text format, 15 | with columns for the text, 16 | file name, line number, and batch index (if applicable). 17 | } 18 | \description{ 19 | This function takes a character string or a path to a text file as input and 20 | converts it to tidy-text format. The resulting tibble contains one row for 21 | each line of the input text, along with the file name, and line number. 22 | } 23 | \examples{ 24 | read_text("Hello, how are you?") 25 | read_text("path/to/text/file.txt") 26 | 27 | } 28 | -------------------------------------------------------------------------------- /man/read_text_batches.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/read_text_batches.R 3 | \name{read_text_batches} 4 | \alias{read_text_batches} 5 | \title{Load data from text files in batches} 6 | \usage{ 7 | read_text_batches(text, batch_size = 3500) 8 | } 9 | \arguments{ 10 | \item{text}{character string, either containing a path to a text file to read 11 | in or containing the text.} 12 | 13 | \item{batch_size}{integer indicating the number of lines to read in per batch 14 | (default is 3500)} 15 | } 16 | \value{ 17 | a numeric value indicating the total number of tokens in the text 18 | file 19 | } 20 | \description{ 21 | This function reads in data from text files in batches using 22 | the read_lines_chunked function from the readr package. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | data_path <- system.file("text", "lorem.txt", package = "OpenAIR") 27 | text_data <- read_text_batches(data_path) 28 | } 29 | } 30 | \author{ 31 | Ulrich Matter umatter@protonmail.com 32 | } 33 | -------------------------------------------------------------------------------- /man/refactor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/refactor.R 3 | \name{refactor} 4 | \alias{refactor} 5 | \title{Refactor R Code with AI Assistance} 6 | \usage{ 7 | refactor(file, ...) 8 | } 9 | \arguments{ 10 | \item{file}{character, file name of a file containing R code to be refactored 11 | or a character string containing R code to be refactored} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | The refactored code either to the console (if the input `file` was a 17 | character string) or written to a file (if the input was a file name). 18 | } 19 | \description{ 20 | This function refactors R code with the assistance of an AI chatbot. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | # Create a sample R function file 25 | cat("my_sum <- function(a, b) {", "return(a + b)", "}", 26 | file = "sample_function.R") 27 | 28 | # Refactor the R function and return the output 29 | refactored_function <- refactor(file = "sample_function.R") 30 | 31 | # Refactor the R function and write the output to the same file 32 | refactor(file = "sample_function.R") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /man/refactor_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{refactor_prompt} 5 | \alias{refactor_prompt} 6 | \title{Input: message content template for refactor()} 7 | \format{ 8 | ## `nested_to_pipe_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | refactor_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the refactor() function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/references_to_bibtex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/references_to_bibtex.R 3 | \name{references_to_bibtex} 4 | \alias{references_to_bibtex} 5 | \title{Convert references in plain text to BibTeX format} 6 | \usage{ 7 | references_to_bibtex(references, ...) 8 | } 9 | \arguments{ 10 | \item{references}{A character string or a file path to a file containing the 11 | plain text references to convert.} 12 | 13 | \item{...}{Additional arguments to pass to the chat_completion() function.} 14 | } 15 | \value{ 16 | A character string containing the references in BibTeX format or, if 17 | a file path is provided, the function writes the BibTeX entries to a .bib 18 | file in the same directory and returns the file path of the newly created 19 | .bib file. 20 | } 21 | \description{ 22 | This function takes a character string or a file path to plain text 23 | references and converts them into BibTeX format. The function reads the input 24 | text, processes it, and returns a character string containing the references 25 | in BibTeX format. If a file path is provided, the function also writes the 26 | BibTeX entries to a .bib file in the same directory. 27 | } 28 | \examples{ 29 | \dontrun{ 30 | # Convert plain text references to BibTeX format 31 | references <- "Doe, J., & Smith, J. (2020). The title of the paper. 32 | Journal of Scientific Computing, 12, 45-67." 33 | references_to_bibtex(references) 34 | } 35 | } 36 | \seealso{ 37 | \url{https://ctan.org/pkg/bibtex} for more information on BibTeX 38 | format 39 | } 40 | \author{ 41 | Ulrich Matter umatter@protonmail.com 42 | } 43 | -------------------------------------------------------------------------------- /man/references_to_bibtex_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{references_to_bibtex_prompt} 5 | \alias{references_to_bibtex_prompt} 6 | \title{Input: message content template for references_to_bibtex()} 7 | \format{ 8 | ## `references_to_bibtex_prompt` 9 | A data frame with 4 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | references_to_bibtex_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the references_to_bibtex 20 | function. 21 | } 22 | \keyword{datasets} 23 | -------------------------------------------------------------------------------- /man/regenerate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/regenerate.R 3 | \name{regenerate} 4 | \alias{regenerate} 5 | \title{Regenerate the last response in an ongoing chat} 6 | \usage{ 7 | regenerate(chatlog_id = ".__CURRENTCHAT__", output = "message_to_console", ...) 8 | } 9 | \arguments{ 10 | \item{chatlog_id}{A character string specifying the ID of the chatlog 11 | (default: '.__CURRENTCHAT__')} 12 | 13 | \item{output}{A character string specifying the output format. Options are 14 | 'message_to_console', 'message', or 'response_object' 15 | (default: 'message_to_console')} 16 | 17 | \item{...}{Additional arguments to pass to the chat_completion() function.} 18 | } 19 | \value{ 20 | If output is 'message_to_console', the function returns NULL 21 | andprints the message to the console. If output is 'message', the function 22 | returns a character string containing the message. If output is 23 | 'response_object', the function returns the full response object. 24 | } 25 | \description{ 26 | This function removes the last response in a chatlog, generates a new 27 | response based on the updated chatlog, and updates the chatlog accordingly. 28 | The output can be displayed as a message in the console, returned as a 29 | message, or returned as a response object. 30 | } 31 | \examples{ 32 | \dontrun{ 33 | # Start a new chat and save the chatlog ID 34 | chatlog_id <- chat("Hello, how are you?") 35 | 36 | # Regenerate the last response in the chat and display it in the console 37 | regenerate(chatlog_id) 38 | 39 | # Regenerate the last response in the chat and return it as a message 40 | message <- regenerate(chatlog_id, output = "message") 41 | print(message) 42 | 43 | # Regenerate the last response in the chat and return it as a response object 44 | response_object <- regenerate(chatlog_id, output = "response_object") 45 | print(response_object) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /man/replace_file_extension.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/replace_file_extension.R 3 | \name{replace_file_extension} 4 | \alias{replace_file_extension} 5 | \title{Replace File Extension} 6 | \usage{ 7 | replace_file_extension(filename, new_extension) 8 | } 9 | \arguments{ 10 | \item{filename}{The input filename as a character string.} 11 | 12 | \item{new_extension}{The new file extension to replace the old one 13 | (including the dot, e.g., ".bib").} 14 | } 15 | \value{ 16 | A character string representing the filename with the replaced file 17 | extension. 18 | } 19 | \description{ 20 | This function replaces the file extension of a given filename with a 21 | specified new extension. It validates the input to ensure the filename and 22 | the new extension are single character strings. Then, it replaces the old 23 | extension with the new one and returns the modified filename. 24 | } 25 | \examples{ 26 | \dontrun{ 27 | # Replace the file extension of a text file with a BibTeX extension 28 | new_filename <- replace_file_extension("example_document.txt", ".bib") 29 | print(new_filename) # "example_document.bib" 30 | } 31 | } 32 | \author{ 33 | Ulrich Matter umatter@protonmail.com 34 | } 35 | -------------------------------------------------------------------------------- /man/set_chatlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/set_chatlog.R 3 | \name{set_chatlog} 4 | \alias{set_chatlog} 5 | \title{Set up a new chatlog} 6 | \usage{ 7 | set_chatlog( 8 | initial_role = "system", 9 | initial_content = "You are a helpful assistant.", 10 | chatlog_id = NULL 11 | ) 12 | } 13 | \arguments{ 14 | \item{initial_role}{A character string representing the role issueing the 15 | initial content (per default: "system")} 16 | 17 | \item{initial_content}{A character string representing the initial message 18 | from the system} 19 | 20 | \item{chatlog_id}{A character string representing the ID of this 21 | conversation. Per default, this will be set automatically.} 22 | } 23 | \value{ 24 | A new chatlog object 25 | } 26 | \description{ 27 | This function sets up a new chatlog object for a conversation. 28 | } 29 | \examples{ 30 | chat <- set_chatlog("Welcome to our chat!") 31 | is_chatlog(chat) 32 | chat 33 | } 34 | -------------------------------------------------------------------------------- /man/split_text.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/split_text.R 3 | \name{split_text} 4 | \alias{split_text} 5 | \title{Split Text into Chunks} 6 | \usage{ 7 | split_text(text, N) 8 | } 9 | \arguments{ 10 | \item{text}{A character vector containing the text to be split.} 11 | 12 | \item{N}{An integer specifying the number of tokens per chunk.} 13 | } 14 | \value{ 15 | A character vector containing the chunks of text with N tokens each. 16 | } 17 | \description{ 18 | This function splits a text string into a vector of strings with a 19 | specified number of tokens each. 20 | } 21 | \examples{ 22 | large_text <- "This is an example of a large text string 23 | that will be split into chunks of N tokens each by our custom R function." 24 | num_tokens_per_chunk <- 5 25 | split_text(large_text, num_tokens_per_chunk) 26 | } 27 | -------------------------------------------------------------------------------- /man/start_chat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/start_chat.R 3 | \name{start_chat} 4 | \alias{start_chat} 5 | \title{Start a new chat session} 6 | \usage{ 7 | start_chat( 8 | initial_role = "system", 9 | initial_content = "You are a helpful assistant.", 10 | show = FALSE, 11 | chatlog_id = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{initial_role}{A character string representing the role issueing the 16 | initial content (per default: "system")} 17 | 18 | \item{initial_content}{A character string representing the initial message 19 | from the system} 20 | 21 | \item{show}{Logical, if TRUE, the current chat log is displayed via View(). 22 | Default is FALSE.} 23 | 24 | \item{chatlog_id}{A character string representing the ID of this 25 | conversation. Per default, this will be set automatically.} 26 | } 27 | \value{ 28 | A character string indicating the name of the log environment 29 | created for the chat session. 30 | } 31 | \description{ 32 | This function starts a new chat session by initializing a messages object 33 | with an initial system message, creating a new log environment to store the 34 | messages, and adding the messages object to the log environment. 35 | } 36 | \examples{ 37 | # Start a new chat session with the default system message 38 | chatlog_id <- start_chat() 39 | 40 | # Start a new chat session with a custom system message 41 | chatlog_id <- start_chat("How can I assist you today?") 42 | 43 | } 44 | -------------------------------------------------------------------------------- /man/trump.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{trump} 5 | \alias{trump} 6 | \title{Essay on How Donald Trump Became President of the United States} 7 | \format{ 8 | ## `trump` 9 | A character string. 10 | } 11 | \source{ 12 | This essay was written by a language model trained by OpenAI. 13 | } 14 | \usage{ 15 | trump 16 | } 17 | \description{ 18 | This dataset contains an essay describing how Donald Trump became the 45th 19 | President of the United States in 2016. The essay is written in the style of 20 | Mark Twain, a famous American writer known for his satirical and humorous 21 | style. 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/usage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/usage.R 3 | \name{usage} 4 | \alias{usage} 5 | \title{Extract usage data from OpenAI API response} 6 | \usage{ 7 | usage(response) 8 | } 9 | \arguments{ 10 | \item{response}{a list object representing the HTTP response} 11 | } 12 | \value{ 13 | a data frame with the usage statistics of the API call 14 | (how many tokens used) 15 | } 16 | \description{ 17 | This function extracts the usage data from the parsed HTTP response of an 18 | API call to the OpenAI chat completions endpoint. 19 | } 20 | -------------------------------------------------------------------------------- /man/write_code.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/write_code.R 3 | \name{write_code} 4 | \alias{write_code} 5 | \title{Write code based on user's input} 6 | \usage{ 7 | write_code(filename, chatlog_id = ".__CURRENTCODEFILE__", ...) 8 | } 9 | \arguments{ 10 | \item{filename}{A character string representing the name of the file where 11 | the generated code will be saved.} 12 | 13 | \item{chatlog_id}{An optional character string representing the chatlog ID. 14 | Defaults to ".__CURRENTCODEFILE__". This ID is used to maintain the 15 | conversation history with the chatbot API.} 16 | 17 | \item{...}{Additional arguments to pass to the chat_completion() function.} 18 | } 19 | \value{ 20 | Returns the name of the file containing the generated code. 21 | } 22 | \description{ 23 | The `write_code` function prompts the user to provide a plain English 24 | description of a program or function and the programming language it should 25 | be written in. The function then generates the code based on the user's input 26 | and writes it to a specified file. 27 | } 28 | \examples{ 29 | \dontrun{ 30 | # Generate code based on user input and save it to a file 31 | generated_code_file <- write_code("example_code.R") 32 | 33 | # Check the content of the generated code file 34 | cat(readLines(generated_code_file)) 35 | 36 | # Clean up 37 | unlink(generated_code_file) 38 | } 39 | } 40 | \author{ 41 | Ulrich Matter 42 | } 43 | -------------------------------------------------------------------------------- /man/write_test.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/write_test.R 3 | \name{write_test} 4 | \alias{write_test} 5 | \title{Write test for an R function} 6 | \usage{ 7 | write_test(file, ...) 8 | } 9 | \arguments{ 10 | \item{file}{The file path of the R function.} 11 | 12 | \item{...}{Additional arguments to pass to the chat_completion() function.} 13 | } 14 | \value{ 15 | If the input is a character string, the function returns the 16 | generated output without creating a test file. Otherwise, it creates a test 17 | file and returns the file name. 18 | } 19 | \description{ 20 | This function reads an R function from a file and generates a test file with 21 | documentation. 22 | } 23 | \examples{ 24 | \dontrun{ 25 | # Write test for an R function 26 | write_test("path/to/file.R") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /man/write_test_prompt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{write_test_prompt} 5 | \alias{write_test_prompt} 6 | \title{Input: message content template for write_test()} 7 | \format{ 8 | ## `write_test_prompt` 9 | A data frame with 2 rows and 2 columns representing the messages object in 10 | API calls. 11 | } 12 | \source{ 13 | Contributed by umatter 14 | } 15 | \usage{ 16 | write_test_prompt 17 | } 18 | \description{ 19 | This message content serves as user input for the write_test function. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umatter/OpenAIR/2bedfbd63f67c6daa758a145aeb8519b1eb5b820/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/tests.html 7 | # * https://testthat.r-lib.org/reference/test_package.html#special-files 8 | 9 | library(testthat) 10 | library(TheOpenAIR) 11 | 12 | test_check("TheOpenAIR") 13 | -------------------------------------------------------------------------------- /tests/testthat/test-%c%.R: -------------------------------------------------------------------------------- 1 | if (!nchar(Sys.getenv("OPENAI_API_KEY"))==0) { 2 | test_that("High-level inflix chat function works", { 3 | 4 | # example, start conversation 5 | resp <- 6 | "Write a CV of a person worthy of joining the OpenAIR team as a developer" %c% 7 | "response_object" 8 | resp 9 | }) 10 | } else { 11 | skip("API key not set, skipping test.") 12 | } 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/testthat/test-add_roxygen.R: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Check if the API key is available 4 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 5 | 6 | # Begin the test 7 | test_that("add_roxygen function works correctly", { 8 | # Test that function returns NULL for valid input 9 | test_that("add_roxygen returns NULL for valid input", { 10 | # Create a test file 11 | test_file <- tempfile(fileext = ".R") 12 | write("test_function <- function(x) { x + 1 }\n", test_file) 13 | 14 | # Test function 15 | result <- add_roxygen(test_file) 16 | 17 | # Check result 18 | expect_type(result, "character") 19 | }) 20 | 21 | # Test that function adds Roxygen2 documentation to a file 22 | test_that("add_roxygen adds Roxygen2 documentation to a file", { 23 | # Create a test file 24 | test_file <- tempfile(fileext = ".R") 25 | write("test_function <- function(x) { x + 1 } \n", test_file) 26 | 27 | # Test function 28 | add_roxygen(test_file) 29 | 30 | # Check that file now contains Roxygen2 documentation 31 | expect_true(contains_roxygen(test_file)) 32 | }) 33 | 34 | # Test that function throws an error for invalid input 35 | test_that("add_roxygen throws an error for invalid input", { 36 | # Test function with invalid input 37 | expect_error(add_roxygen("nonexistent_file.R")) 38 | }) 39 | }) 40 | 41 | } else { 42 | test_that("add_roxygen skips test if API key not set", { 43 | skip("API key not set, skipping test.") 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /tests/testthat/test-chat.R: -------------------------------------------------------------------------------- 1 | if (!nchar(Sys.getenv("OPENAI_API_KEY"))==0) { 2 | test_that("High-level chat conversation works", { 3 | 4 | # chat conversation starts 5 | chat("Please write a 200 words essay explaining what ChatGPT is. However, instead of writing it in a common sense style, write it in the style of a speech by Donald Trump.") 6 | # follow-up message/task 7 | chat("Now rewrate the essay, but this time write it in the style of the late Steve Jobs.") 8 | }) 9 | } else { 10 | skip("API key not set, skipping test.") 11 | } 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/testthat/test-chat_completion.R: -------------------------------------------------------------------------------- 1 | if (!nchar(Sys.getenv("OPENAI_API_KEY"))==0) { 2 | test_that("Basic chat completion works", { 3 | msgs_df <- data.frame(role=c("system", 4 | "user", 5 | "assistant", 6 | "user"), 7 | content=c("You are a helpful assistant", 8 | "Who won the world series in 2020?", 9 | "The Los Angeles Dodgers won the World Series in 2020.", 10 | "Where was it played?")) 11 | resp <- chat_completion(msgs_df) 12 | # test util functions 13 | # extract ID 14 | resp %>% id() 15 | 16 | # extract response messages 17 | resp %>% messages() 18 | 19 | # extract model 20 | resp %>% model() 21 | 22 | # extract usage stats 23 | resp %>% usage() 24 | 25 | # extract timestamp in user-friendly format 26 | resp %>% created() 27 | 28 | # extract object info from response 29 | resp %>% object() 30 | # Add any other tests as needed 31 | }) 32 | } else { 33 | skip("API key not set, skipping test.") 34 | } 35 | -------------------------------------------------------------------------------- /tests/testthat/test-clean_output.R: -------------------------------------------------------------------------------- 1 | test_that("clean_output function works correctly", { 2 | # Test with the example provided in the function documentation 3 | code_text <- "``` 4 | example_code <- function(x) { 5 | return(x * 2) 6 | } 7 | ```" 8 | expected_output <- "\nexample_code <- function(x) {\n return(x * 2)\n}\n" 9 | expect_equal(clean_output(code_text), expected_output) 10 | 11 | # Test with a string without newline characters 12 | code_text <- "```example_code <- function(x) {return(x * 2)}```" 13 | expected_output <- "example_code <- function(x) {return(x * 2)}" 14 | expect_equal(clean_output(code_text), expected_output) 15 | 16 | # Test with a string without '```' markers 17 | code_text <- "example_code <- function(x) {return(x * 2)}" 18 | expected_output <- "example_code <- function(x) {return(x * 2)}" 19 | expect_equal(clean_output(code_text), expected_output) 20 | 21 | # Test with an empty string 22 | code_text <- "" 23 | expected_output <- "" 24 | expect_equal(clean_output(code_text), expected_output) 25 | }) 26 | -------------------------------------------------------------------------------- /tests/testthat/test-count_tokens.R: -------------------------------------------------------------------------------- 1 | 2 | # Test the function 3 | test_that("count_tokens() correctly counts the number of tokens in a text string", { 4 | 5 | # Test with a simple string 6 | expect_equal(count_tokens("This is a test."), 5) 7 | 8 | # Test with a string containing special characters 9 | expect_equal(count_tokens("Hello, world! This is a test."), 9) 10 | 11 | # Test with an empty string 12 | expect_equal(count_tokens(""), 0) 13 | 14 | # Test with a string containing only whitespace 15 | expect_equal(count_tokens(" "), 0) 16 | 17 | # Test with a file path 18 | test_file_path <- tempfile() 19 | writeLines("This is a test.", test_file_path) 20 | expect_equal(count_tokens(test_file_path), 5) 21 | file.remove(test_file_path) 22 | 23 | # Test with a long string 24 | long_string <- paste(rep("This is a test.", 1000), collapse = " ") 25 | expect_equal(count_tokens(long_string), 5000) 26 | 27 | # Test with a string containing non-ASCII characters 28 | expect_equal(count_tokens("Voilà! C'est un test."), 8) 29 | 30 | }) 31 | -------------------------------------------------------------------------------- /tests/testthat/test-df_to_csv.R: -------------------------------------------------------------------------------- 1 | # Begin the test 2 | test_that("df_to_csv function works correctly", { 3 | # Test that function returns output for valid data.frame input 4 | test_that("df_to_csv returns output for valid data.frame input", { 5 | # Create a data.frame 6 | example_data <- data.frame( 7 | Name = c("Alice", "Bob", "Carol"), 8 | Age = c(30, 25, 28), 9 | Height = c(168, 175, 162), 10 | stringsAsFactors = FALSE 11 | ) 12 | 13 | # Test function 14 | result <- df_to_csv(example_data) 15 | 16 | # Check result 17 | expect_type(result, "character") 18 | # Check if the content matches the expected CSV structure 19 | expected_csv_string <- "Name,Age,Height\nAlice,30,168\nBob,25,175\nCarol,28,162" 20 | expect_equal(readr::read_csv(result), readr::read_csv(expected_csv_string)) 21 | }) 22 | 23 | # Test that function throws an error for invalid input 24 | test_that("df_to_csv throws an error for invalid input", { 25 | # Test function with invalid input 26 | expect_error(df_to_csv("nonexistent_file.csv")) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /tests/testthat/test-extract_blocks.R: -------------------------------------------------------------------------------- 1 | 2 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 3 | test_that("extract_blocks function works", { 4 | 5 | # Test 1: Extract 'text' blocks 6 | input_blocks1 <- list( 7 | list(type = "text", content = "Hello world!"), 8 | list(type = "code", content = "print('Hello world!')") 9 | ) 10 | expected_output1 <- list(list(type = "text", content = "Hello world!")) 11 | 12 | test_that("Text blocks are extracted correctly", { 13 | expect_equal(extract_blocks(input_blocks1, "text"), expected_output1) 14 | }) 15 | 16 | # Test 2: Extract 'code' blocks 17 | input_blocks2 <- list( 18 | list(type = "text", content = "Hello world!"), 19 | list(type = "code", content = "print('Hello world!')") 20 | ) 21 | expected_output2 <- list(list(type = "code", content = "print('Hello world!')")) 22 | 23 | test_that("Code blocks are extracted correctly", { 24 | expect_equal(extract_blocks(input_blocks2, "code"), expected_output2) 25 | }) 26 | 27 | # Test 3: Extract non-existent block type 28 | input_blocks3 <- list( 29 | list(type = "text", content = "Hello world!"), 30 | list(type = "code", content = "print('Hello world!')") 31 | ) 32 | expected_output3 <- list() 33 | 34 | test_that("Non-existent block type returns an empty list", { 35 | expect_equal(extract_blocks(input_blocks3, "unknown"), expected_output3) 36 | }) 37 | 38 | # Test 4: Empty input list 39 | input_blocks4 <- list() 40 | expected_output4 <- list() 41 | 42 | test_that("Empty input list returns an empty list", { 43 | expect_equal(extract_blocks(input_blocks4, "text"), expected_output4) 44 | }) 45 | 46 | }) 47 | } else { 48 | skip("API key not set, skipping test.") 49 | } 50 | -------------------------------------------------------------------------------- /tests/testthat/test-extract_entities.R: -------------------------------------------------------------------------------- 1 | if (!nchar(Sys.getenv("OPENAI_API_KEY"))==0) { 2 | test_that("Entity extraction works", { 3 | 4 | extract_entities(trump) 5 | 6 | }) 7 | } else { 8 | skip("API key not set, skipping test.") 9 | } 10 | -------------------------------------------------------------------------------- /tests/testthat/test-extract_r_code.R: -------------------------------------------------------------------------------- 1 | 2 | test_that("extract_r_code works correctly", { 3 | 4 | # Test with a valid input string 5 | input_string <- "This is a text string with R code and comments.\n# A comment\nx <- 5\ny = 10\nz <- x + y\nAnother line of text." 6 | expected_output <- c("# A comment", "x <- 5", "y = 10", "z <- x + y") 7 | test_output <- extract_r_code(input_string) 8 | expect_equal(test_output, expected_output) 9 | 10 | # Test with an empty input string 11 | test_output_empty <- extract_r_code("") 12 | expect_equal(test_output_empty, character(0)) 13 | 14 | # Test with an input string that has no R code or comments 15 | input_no_code <- "This is a text string without R code and comments." 16 | test_output_no_code <- extract_r_code(input_no_code) 17 | expect_equal(test_output_no_code, character(0)) 18 | 19 | # Test with an input string that only contains R code 20 | input_only_code <- "x <- 5\ny = 10\nz <- x + y" 21 | expected_output_only_code <- c("x <- 5", "y = 10", "z <- x + y") 22 | test_output_only_code <- extract_r_code(input_only_code) 23 | expect_equal(test_output_only_code, expected_output_only_code) 24 | }) 25 | -------------------------------------------------------------------------------- /tests/testthat/test-extract_roxygen2.R: -------------------------------------------------------------------------------- 1 | # Test the extract_roxygen2 function 2 | 3 | test_that("extract_roxygen2 returns the correct roxygen2 documentation lines", { 4 | # Define a function with roxygen2 documentation 5 | func_def <- c( 6 | "#' This function adds two numbers together.", 7 | "#'", 8 | "#' @param x A number to be added.", 9 | "#' @param y A number to be added.", 10 | "#'", 11 | "#' @return The sum of x and y.", 12 | "#'", 13 | "#' @examples", 14 | "#' add(2, 3)", 15 | "#'", 16 | "#' @export", 17 | "add <- function(x, y) {", 18 | " return(x + y)", 19 | "}" 20 | ) %>% paste0(collapse = "\n") 21 | 22 | # Extract the roxygen2 documentation 23 | roxygen2_lines <- extract_roxygen2(func_def) 24 | 25 | # Check that the roxygen2 documentation is correct 26 | expect_equal(roxygen2_lines, 27 | "#' This function adds two numbers together.\n#'\n#' @param x A number to be added.\n#' @param y A number to be added.\n#'\n#' @return The sum of x and y.\n#'\n#' @examples\n#' add(2, 3)\n#'\n#' @export") 28 | }) 29 | 30 | test_that("extract_roxygen2 returns an empty string if no roxygen2 documentation is found", { 31 | # Define a function with no roxygen2 documentation 32 | func_def <- c( 33 | "add <- function(x, y) {", 34 | " return(x + y)", 35 | "}" 36 | ) 37 | 38 | # Extract the roxygen2 documentation 39 | roxygen2_lines <- extract_roxygen2(func_def) 40 | 41 | # Check that the roxygen2 documentation is an empty string 42 | expect_equal(roxygen2_lines, "") 43 | }) 44 | -------------------------------------------------------------------------------- /tests/testthat/test-is_json.R: -------------------------------------------------------------------------------- 1 | 2 | # Begin the test 3 | test_that("is_json function works correctly", { 4 | # Test that function returns TRUE for valid input 5 | test_that("is_json returns TRUE for valid input", { 6 | # Test function with valid input 7 | expect_true(is_json('{"name": "John", "age": 30}')) 8 | }) 9 | 10 | # Test that function returns FALSE for invalid input 11 | test_that("is_json returns FALSE for invalid input", { 12 | # Test function with invalid input 13 | expect_false(is_json('{"name": "John", age: 30}')) 14 | }) 15 | 16 | # Test that function returns FALSE for empty input 17 | test_that("is_json returns FALSE for empty input", { 18 | # Test function with empty input 19 | expect_false(is_json('')) 20 | }) 21 | 22 | # Test that function throws a warning for non-character input 23 | test_that("is_json throws a warning for non-character input", { 24 | # Test function with non-character input 25 | expect_warning(is_json(123)) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /tests/testthat/test-is_python.R: -------------------------------------------------------------------------------- 1 | if (all(nchar(Sys.which(c("python", "python3")))) == 0) { 2 | skip("Python not installed, skipping test.") 3 | } else { 4 | # Test that the is_python function recognizes valid Python code 5 | test_that("is_python recognizes valid Python code", { 6 | expect_true(is_python("print('Hello, World!')")) 7 | expect_true(is_python("x = 5")) 8 | code <- 9 | " 10 | x = 5 11 | if x > 0: 12 | print('x is positive') 13 | " 14 | expect_true(is_python(code)) 15 | }) 16 | 17 | # Test that the is_python function recognizes invalid Python code 18 | test_that("is_python recognizes invalid Python code", { 19 | expect_false(is_python("prit('Hello, World!')")) 20 | expect_false(is_python("x == 5")) 21 | expect_false(is_python("if x > 0\n print('x is positive')")) 22 | }) 23 | } -------------------------------------------------------------------------------- /tests/testthat/test-is_r.R: -------------------------------------------------------------------------------- 1 | 2 | test_that("is_r checks for valid R code", { 3 | # Test with valid R code 4 | valid_code <- "x <- 5; y <- 10; z <- x + y" 5 | expect_true(is_r(valid_code)) 6 | 7 | # Test with invalid R code 8 | invalid_code <- "x <- 5 + 'a'" 9 | expect_false(is_r(invalid_code)) 10 | 11 | # Test with an empty string 12 | empty_code <- "" 13 | expect_false(is_r(empty_code)) 14 | 15 | # Test with a non-character input 16 | non_char_input <- 123 17 | expect_false(is_r(non_char_input)) 18 | }) 19 | -------------------------------------------------------------------------------- /tests/testthat/test-is_xml.R: -------------------------------------------------------------------------------- 1 | 2 | # Begin the test 3 | test_that("is_xml function works correctly", { 4 | # Test that function returns TRUE for valid input 5 | test_that("is_xml returns TRUE for valid input", { 6 | # Test function with valid input 7 | expect_true(is_xml('value')) 8 | }) 9 | 10 | # Test that function returns FALSE for invalid input 11 | test_that("is_xml returns FALSE for invalid input", { 12 | # Test function with invalid input 13 | expect_false(is_xml('value% messages() 6 | 7 | # Check that the returned value is a character string 8 | expect_type(messages_from_response$content, "character") 9 | 10 | # Start a chat and save the chatlog ID 11 | chatlog_id <- "testid" 12 | chat("tell me a joke", chatlog_id = chatlog_id) 13 | 14 | # Using a chatlog object 15 | chatlog <- get_chatlog(chatlog_id) 16 | messages_from_chatlog <- messages(chatlog) 17 | 18 | # Check that the returned value is a data.frame 19 | expect_s3_class(messages_from_chatlog, "data.frame") 20 | 21 | # Check that the returned messages are not empty 22 | expect_true(nrow(messages_from_chatlog) > 0) 23 | 24 | }) 25 | } else { 26 | skip("API key not set, skipping test.") 27 | } 28 | -------------------------------------------------------------------------------- /tests/testthat/test-nested_to_pipe.R: -------------------------------------------------------------------------------- 1 | # Check if the API key is available 2 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 3 | test_that("nested_to_pipe function works correctly", { 4 | 5 | # Test that function returns a character string for valid input 6 | test_that("nested_to_pipe returns a character string for valid input", { 7 | input <- "result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)" 8 | output <- nested_to_pipe(input) 9 | expect_type(output, "character") 10 | }) 11 | 12 | # Test that function writes to a file and returns the output file path for valid input 13 | test_that("nested_to_pipe writes to a file and returns the output file path for valid input", { 14 | input_file <- tempfile(fileext = ".R") 15 | write("result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)", input_file) 16 | 17 | output_file <- nested_to_pipe(input_file) 18 | expect_true(file.exists(output_file)) 19 | expect_match(output_file, "-pipe.R$") 20 | 21 | }) 22 | 23 | # Test that function throws an error for invalid input 24 | test_that("nested_to_pipe throws an error for invalid input", { 25 | input <- "invalid_input <- x + y" 26 | expect_error(nested_to_pipe(input), "The input does not contain valid R code.") 27 | }) 28 | 29 | # Test that function throws an error if the input exceeds the token limit 30 | test_that("nested_to_pipe throws an error if the input exceeds the token limit", { 31 | long_input <- paste(rep("result <- mean(sqrt(abs(rnorm(10, 0, 1))), na.rm = TRUE)", 200), collapse = "\n") 32 | expect_error(nested_to_pipe(long_input, n_tokens_limit = 3000), "Text input contains too many tokens!") 33 | }) 34 | 35 | }) 36 | 37 | } else { 38 | test_that("add_roxygen skips test if API key not set", { 39 | skip("API key not set, skipping test.") 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /tests/testthat/test-parse_response.R: -------------------------------------------------------------------------------- 1 | 2 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 3 | test_that("parse_response function works", { 4 | 5 | # Test 1: Text only 6 | input1 <- "Hello world!" 7 | expected_output1 <- list(list(type = "text", content = "Hello world!")) 8 | 9 | test_that("Text only is parsed correctly", { 10 | expect_equal(parse_response(input1), expected_output1) 11 | }) 12 | 13 | # Test 2: Code block only 14 | input2 <- "```python\nprint('Hello world!')\n```" 15 | expected_output2 <- list(list(type = "code", content = "print('Hello world!')\n", language = "python")) 16 | 17 | test_that("Code block only is parsed correctly", { 18 | expect_equal(parse_response(input2), expected_output2) 19 | }) 20 | 21 | # Test 3: Text and code block 22 | input3 <- "Hello world!\n\n```python\nprint('Hello world!')\n```" 23 | expected_output3 <- list( 24 | list(type = "text", content = "Hello world!\n\n"), 25 | list(type = "code", content = "print('Hello world!')\n", language = "python") 26 | ) 27 | 28 | test_that("Text and code block are parsed correctly", { 29 | expect_equal(parse_response(input3), expected_output3) 30 | }) 31 | 32 | # Test 4: Empty input 33 | input4 <- "" 34 | expected_output4 <- list(list(type = "text", content = "")) 35 | 36 | test_that("Empty input is parsed correctly", { 37 | expect_equal(parse_response(input4), expected_output4) 38 | }) 39 | 40 | }) 41 | } else { 42 | skip("API key not set, skipping test.") 43 | } 44 | -------------------------------------------------------------------------------- /tests/testthat/test-python_to_r.R: -------------------------------------------------------------------------------- 1 | # Check if the OPENAI_API_KEY environment variable is set 2 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 3 | test_that("python_to_r converts Python code to R code", { 4 | # Test with a Python code string 5 | python_code_string <- "x = 5\ny = 10\nprint(x + y)" 6 | expected_output <- 15 7 | 8 | # Convert the Python code to R code and evaluate it 9 | r_code_string <- python_to_r(python_code_string) 10 | r_output <- eval(parse(text = r_code_string)) 11 | 12 | # Check if the Python and R outputs match 13 | expect_equal(r_output, expected_output) 14 | 15 | # Test with a Python code file 16 | python_file_path <- "test_python_code.py" 17 | python_code_string <- "x = 5\ny = 10\nprint(x + y)" 18 | expected_output <- 15 19 | 20 | # Write the Python code to a file and convert it to R code 21 | write(python_code_string, file = python_file_path) 22 | r_file_path <- python_to_r(python_file_path) 23 | r_code_string <- readLines(r_file_path) %>% paste(collapse = "\n") 24 | r_output <- eval(parse(text = r_code_string)) 25 | 26 | # Check if the Python and R outputs match 27 | expect_equal(r_output, expected_output) 28 | 29 | # Test with a Python code string that contains syntax that doesn't have a direct equivalent in R 30 | test_python_code <- "try:\n x = 5\nexcept Exception as e:\n print(e)" 31 | expect_message(python_to_r(test_python_code), "The Python code contains syntax that doesn't have a direct equivalent in R.") 32 | 33 | # Test with an empty string 34 | expect_equal(python_to_r(""), "") 35 | 36 | # Test with a non-Python code string 37 | test_non_python_code <- "This is not Python code." 38 | expect_message(python_to_r(test_non_python_code), "The input string does not appear to be valid Python code.") 39 | 40 | }) 41 | } else { 42 | skip("API key not set, skipping test.") 43 | } 44 | 45 | # Clean up temporary files created during the test 46 | file.remove("test_python_code.py", "test_python_code.R") 47 | -------------------------------------------------------------------------------- /tests/testthat/test-r_to_python.R: -------------------------------------------------------------------------------- 1 | # Check if the OPENAI_API_KEY environment variable is set 2 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 3 | test_that("r_to_python converts R code to Python code", { 4 | # Define the R code and the expected output 5 | test_r_code <- "x <- 5; y <- 10; z <- x + y; print(z)" 6 | expected_output <- 15 7 | 8 | # Convert the R code to Python code and run it 9 | python_code <- r_to_python(test_r_code) 10 | temp_file <- tempfile() 11 | writeLines(python_code, temp_file) 12 | temp_stdout <- tempfile() 13 | temp_stderr <- tempfile() 14 | 15 | # Attempt to run the code with "python" 16 | exit_code_python <- tryCatch({ 17 | suppressWarnings(system2("python", temp_file, stdout = temp_stdout, stderr = temp_stderr)) 18 | }, error = function(e) { 19 | NA 20 | }) 21 | 22 | # Attempt to run the code with "python3" 23 | exit_code_python3 <- tryCatch({ 24 | suppressWarnings(system2("python3", temp_file, stdout = temp_stdout, stderr = temp_stderr )) 25 | }, error = function(e) { 26 | NA 27 | }) 28 | 29 | # Check if the Python output matches the expected output 30 | python_output <- NA 31 | if (!is.na(exit_code_python)) { 32 | python_output <- as.numeric(trimws(readLines(temp_stdout))) 33 | } else if (!is.na(exit_code_python3)) { 34 | python_output <- as.numeric(trimws(readLines(temp_stdout))) 35 | } 36 | expect_equal(python_output, expected_output) 37 | }) 38 | } else { 39 | skip("API key not set, skipping test.") 40 | } 41 | -------------------------------------------------------------------------------- /tests/testthat/test-read_text.R: -------------------------------------------------------------------------------- 1 | 2 | test_that("read_text handles character strings correctly", { 3 | text <- "Hello, how are you?\nI'm doing well, thanks!" 4 | 5 | result <- read_text(text) 6 | 7 | expect_s3_class(result, "tbl_df") 8 | expect_equal(nrow(result), 2) 9 | expect_equal(ncol(result), 4) 10 | expect_equal(unique(result$file), "character string") 11 | expect_equal(result$line, c(1, 2)) 12 | expect_equal(unique(result$batch_index), 1) 13 | }) 14 | 15 | test_that("read_text handles text files correctly", { 16 | text <- "Hello, how are you?\nI'm doing well, thanks!" 17 | temp_file <- tempfile(fileext = ".txt") 18 | writeLines(text, con = temp_file) 19 | 20 | result <- read_text(temp_file) 21 | 22 | expect_s3_class(result, "tbl_df") 23 | expect_equal(nrow(result), 2) 24 | expect_equal(ncol(result), 4) 25 | expect_equal(unique(result$file), temp_file) 26 | expect_equal(result$line, c(1, 2)) 27 | expect_equal(unique(result$batch_index), 1) 28 | }) 29 | 30 | test_that("read_text handles non-existent files correctly", { 31 | non_existent_file <- "non_existent_file.txt" 32 | 33 | # expect_warning(read_text(non_existent_file)) 34 | # It seems reasonable to allow strings containing non-existent files in 35 | # the context of OpenAIR 36 | }) -------------------------------------------------------------------------------- /tests/testthat/test-refactor.R: -------------------------------------------------------------------------------- 1 | 2 | # Check if the API key is available 3 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 4 | 5 | test_that("refactor function works correctly", { 6 | 7 | # Test that function returns a character string for a valid input 8 | test_that("refactor returns a character string for a valid input", { 9 | # Create a test file 10 | test_file <- tempfile(fileext = ".R") 11 | write("my_sum <- function(a, b) { return(a + b) }\n", test_file) 12 | 13 | # Test function 14 | result <- refactor(test_file) 15 | 16 | # Check result 17 | expect_type(result, "character") 18 | 19 | # Clean up temporary files 20 | file.remove(test_file) 21 | }) 22 | 23 | # Test that function stops execution and returns an error message for an invalid input 24 | test_that("refactor stops execution for an invalid input", { 25 | # Create an invalid test file 26 | invalid_test_file <- tempfile(fileext = ".R") 27 | write("This is not a valid R function file.\n", invalid_test_file) 28 | 29 | # Test function with invalid input 30 | expect_error(refactor(invalid_test_file), "The input does not contain a valid R code.") 31 | 32 | # Clean up temporary files 33 | file.remove(invalid_test_file) 34 | }) 35 | 36 | }) 37 | 38 | } else { 39 | test_that("refactor skips test if API key not set", { 40 | skip("API key not set, skipping test.") 41 | }) 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /tests/testthat/test-references_to_bibtex.R: -------------------------------------------------------------------------------- 1 | 2 | # Check if the API key is available 3 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 4 | 5 | # Begin the test 6 | test_that("references_to_bibtex function works correctly", { 7 | # Test with a character string containing a plain text reference 8 | references <- "Doe, J., & Smith, J. (2020). The title of the paper. Journal of Scientific Computing, 12, 45-67." 9 | 10 | # Call the references_to_bibtex function (assuming the function has been modified to use an API key) 11 | bibtex_output <- references_to_bibtex(references) 12 | 13 | # Test the output format (modify the regular expression to match the desired output format) 14 | expect_match(bibtex_output, "^[@|\n@].+\\{.+,.+\\}", all = TRUE) 15 | }) 16 | 17 | } else { 18 | skip("API key not set, skipping test.") 19 | } 20 | -------------------------------------------------------------------------------- /tests/testthat/test-regenerate.R: -------------------------------------------------------------------------------- 1 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 2 | test_that("Regenerate function works", { 3 | 4 | # clean up 5 | #clear_chatlog() 6 | 7 | # Start a chat and save the chatlog ID 8 | chat("Tell me a joke.") 9 | 10 | # Regenerate the last response in the chat and return it as a message 11 | message1 <- regenerate(output = "message") 12 | 13 | # Regenerate the last response in the chat and return it as a response object 14 | response_object <- regenerate(output = "response_object") 15 | 16 | # Check that the response object has the correct class 17 | expect_type(response_object, "list") 18 | 19 | # Check that the response object has the correct elements 20 | expect_true("id" %in% names(response_object)) 21 | expect_true("object" %in% names(response_object)) 22 | expect_true("created" %in% names(response_object)) 23 | expect_true("model" %in% names(response_object)) 24 | expect_true("usage" %in% names(response_object)) 25 | expect_true("choices" %in% names(response_object)) 26 | 27 | }) 28 | } else { 29 | skip("API key not set, skipping test.") 30 | } 31 | -------------------------------------------------------------------------------- /tests/testthat/test-split_text.R: -------------------------------------------------------------------------------- 1 | 2 | test_that("split_text returns the correct number of chunks and tokens", { 3 | text <- "This is an example of a large text string that will be split into chunks of N tokens each by our custom R function." 4 | N <- 5 5 | 6 | result <- split_text(text, N) 7 | 8 | expected_num_chunks <- ceiling(length(str_split(text, "\\s+")[[1]]) / N) 9 | expect_equal(length(result), expected_num_chunks) 10 | 11 | for (chunk in result[-length(result)]) { 12 | expect_equal(length(str_split(chunk, "\\s+")[[1]]), N) 13 | } 14 | }) 15 | 16 | test_that("split_text works with non-integer N values", { 17 | text <- "This is an example of a large text string that will be split into chunks of N tokens each by our custom R function." 18 | N <- 5.2 19 | 20 | expect_error(split_text(text, N), "Error: N must be a positive integer.") 21 | }) 22 | 23 | test_that("split_text works with negative N values", { 24 | text <- "This is an example of a large text string that will be split into chunks of N tokens each by our custom R function." 25 | N <- -5 26 | 27 | expect_error(split_text(text, N), "Error: N must be a positive integer.") 28 | }) 29 | -------------------------------------------------------------------------------- /tests/testthat/test-write_test.R: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Check if the API key is available 4 | if (!nchar(Sys.getenv("OPENAI_API_KEY")) == 0) { 5 | 6 | # Begin the test 7 | test_that("write_test function works correctly", { 8 | # Test that function returns character for valid input 9 | test_that("write_test returns character for valid input", { 10 | 11 | # Test function 12 | result <- write_test("test_function <- function(x) { x + 1 }") 13 | 14 | # Check result 15 | expect_type(result, "character") 16 | }) 17 | 18 | 19 | # Test that function throws an error for invalid input 20 | test_that("write_test throws an error for invalid input", { 21 | # Test function with invalid input 22 | expect_error(write_test("nonexistent_file.R")) 23 | }) 24 | }) 25 | 26 | } else { 27 | test_that("write_test skips test if API key not set", { 28 | skip("API key not set, skipping test.") 29 | }) 30 | } 31 | --------------------------------------------------------------------------------