From 2940d16231defb5126dc497a4aff16e0126d2153 Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Fri, 3 May 2024 23:55:47 +1000 Subject: [PATCH 1/6] Prelimarily support for Databricks foundational models API (DBRX, Meta Llama 3 70B, Mixtral 8x7B) --- NAMESPACE | 2 + R/backend-databricks.R | 137 ++++++++++++++++++++++++ inst/configs/databricks-dbrx.yml | 33 ++++++ inst/configs/databricks-llama3-70b.yml | 33 ++++++ inst/configs/databricks-mixtral8x7b.yml | 33 ++++++ 5 files changed, 238 insertions(+) create mode 100644 R/backend-databricks.R create mode 100644 inst/configs/databricks-dbrx.yml create mode 100644 inst/configs/databricks-llama3-70b.yml create mode 100644 inst/configs/databricks-mixtral8x7b.yml diff --git a/NAMESPACE b/NAMESPACE index 6e7b18c..0626120 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,9 @@ # Generated by roxygen2: do not edit by hand +S3method(app_init_message,ch_databricks) S3method(app_init_message,ch_openai) S3method(app_init_message,default) +S3method(ch_submit,ch_databricks) S3method(ch_submit,ch_llamagpt) S3method(ch_submit,ch_openai) S3method(ch_submit,ch_test_backend) diff --git a/R/backend-databricks.R b/R/backend-databricks.R new file mode 100644 index 0000000..028b1e8 --- /dev/null +++ b/R/backend-databricks.R @@ -0,0 +1,137 @@ +#' @export +ch_submit.ch_databricks <- function( + defaults, + prompt = NULL, + stream = NULL, + prompt_build = TRUE, + preview = FALSE, + ...) { + if (prompt_build) { + # re-use OpenAI prompt + prompt <- ch_openai_prompt(defaults, prompt) + } + ret <- NULL + if (preview) { + ret <- prompt + } else { + ret <- ch_databricks_complete( + prompt = prompt, + defaults = defaults + ) + } + ret +} + + +ch_databricks_complete <- function(prompt, defaults, stream = TRUE) { + ret <- NULL + req_body <- c( + list(messages = prompt), + defaults$model_arguments + ) + + token <- ch_databricks_token(defaults) + host <- ch_databricks_host(defaults) + + req_result <- host %>% + request() %>% + req_url_path_append(defaults$path) %>% + req_url_path_append(defaults$model) %>% + req_url_path_append("invocations") %>% + req_auth_bearer_token(token) %>% + req_body_json(req_body) + + req_result <- req_result %>% + req_perform_stream( + function(x) { + char_x <- rawToChar(x) + ret <<- paste0(ret, char_x) + # print(ret) + cat(ch_openai_parse(char_x, defaults)) + TRUE + }, + buffer_kb = 0.05, round = "line" + ) + ret <- ch_openai_parse(ret, defaults) + if (req_result$status_code != 200) { + ch_openai_error(ret, use_abort = FALSE) + if (inherits(req_result, "httr2_response")) { + req_result <- paste0( + resp_status(req_result), + " - ", + resp_status_desc(req_result) + ) + } + if (!inherits(req_result, "character")) { + req_result <- "Undefined error" + } + cli_abort(req_result, call = NULL) + } + ch_openai_error(ret) + ret +} + +ch_databricks_token <- function(defaults, fail = TRUE) { + env_key <- Sys.getenv("DATABRICKS_TOKEN", unset = NA) + ret <- NULL + if (!is.na(env_key)) { + ret <- env_key + } + if (is.null(ret) && file_exists(Sys.getenv("R_CONFIG_FILE", "config.yml"))) { + ret <- config::get("databricks-token") + } + if (is.null(ret) && fail) { + abort( + "No token found + - Add your key to the \"DATABRICKS_TOKEN\" environment variable + - or - Add \"databricks-token\" to a `config` YAML file" + ) + } + ret +} + +ch_databricks_host <- function(defaults, fail = TRUE) { + env_key <- Sys.getenv("DATABRICKS_HOST", unset = NA) + ret <- NULL + if (!is.na(env_key)) { + ret <- env_key + } + if (is.null(ret) && file_exists(Sys.getenv("R_CONFIG_FILE", "config.yml"))) { + ret <- config::get("databricks-host") + } + if (is.null(ret) && fail) { + abort( + "No host found + - Add your workspace url to the \"DATABRICKS_HOST\" environment variable + - or - Add \"databricks-host\" to a `config` YAML file" + ) + } + ret +} + +#' @export +app_init_message.ch_databricks <- function(defaults) { + print_provider(defaults) + if (defaults$max_data_files > 0) { + cli_alert_warning( + paste0( + "A list of the top {defaults$max_data_files} files will ", + "be sent externally to Databricks with every request\n", + "To avoid this, set the number of files to be sent to 0 ", + "using {.run chattr::chattr_defaults(max_data_files = 0)}" + ) + ) + } + + if (defaults$max_data_frames > 0) { + cli_alert_warning( + paste0( + "A list of the top {defaults$max_data_frames} data.frames ", + "currently in your R session will be sent externally to ", + "Databricks with every request\n To avoid this, set the number ", + "of data.frames to be sent to 0 using ", + "{.run chattr::chattr_defaults(max_data_frames = 0)}" + ) + ) + } +} diff --git a/inst/configs/databricks-dbrx.yml b/inst/configs/databricks-dbrx.yml new file mode 100644 index 0000000..7cb272a --- /dev/null +++ b/inst/configs/databricks-dbrx.yml @@ -0,0 +1,33 @@ +default: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + provider: Databricks + path: serving-endpoints + model: databricks-dbrx-instruct + label: DBRX (Databricks) + max_data_files: 0 + max_data_frames: 0 + include_doc_contents: FALSE + include_history: TRUE + system_msg: You are a helpful coding assistant + model_arguments: + temperature: 0.01 + max_tokens: 1000 + stream: TRUE +chat: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For code output, use RMarkdown code chunks + Avoid all code chunk options +console: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code +script: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code diff --git a/inst/configs/databricks-llama3-70b.yml b/inst/configs/databricks-llama3-70b.yml new file mode 100644 index 0000000..5950b13 --- /dev/null +++ b/inst/configs/databricks-llama3-70b.yml @@ -0,0 +1,33 @@ +default: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + provider: Databricks + path: serving-endpoints + model: databricks-meta-llama-3-70b-instruct + label: Meta Llama 3 70B (Databricks) + max_data_files: 0 + max_data_frames: 0 + include_doc_contents: FALSE + include_history: TRUE + system_msg: You are a helpful coding assistant + model_arguments: + temperature: 0.01 + max_tokens: 1000 + stream: TRUE +chat: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For code output, use RMarkdown code chunks + Avoid all code chunk options +console: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code +script: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code diff --git a/inst/configs/databricks-mixtral8x7b.yml b/inst/configs/databricks-mixtral8x7b.yml new file mode 100644 index 0000000..600e1fb --- /dev/null +++ b/inst/configs/databricks-mixtral8x7b.yml @@ -0,0 +1,33 @@ +default: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + provider: Databricks + path: serving-endpoints + model: databricks-mixtral-8x7b-instruct + label: Mixtral 8x7b (Datbricks) + max_data_files: 0 + max_data_frames: 0 + include_doc_contents: FALSE + include_history: TRUE + system_msg: You are a helpful coding assistant + model_arguments: + temperature: 0.01 + max_tokens: 1000 + stream: TRUE +chat: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For code output, use RMarkdown code chunks + Avoid all code chunk options +console: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code +script: + prompt: | + {readLines(system.file('prompt/base.txt', package = 'chattr'))} + For any line that is not code, prefix with a: # + Keep each line of explanations to no more than 80 characters + DO NOT use Markdown for the code From 120042a6e2bc3ad3f1a27d8ca4fcdf4f2f03e061 Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Mon, 6 May 2024 23:27:29 +1000 Subject: [PATCH 2/6] Updating documentation & adding tests --- R/chattr-use.R | 10 +++ README.qmd | 13 +-- tests/testthat/_snaps/backend-databricks.md | 58 +++++++++++++ tests/testthat/test-backend-databricks.R | 91 +++++++++++++++++++++ 4 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 tests/testthat/_snaps/backend-databricks.md create mode 100644 tests/testthat/test-backend-databricks.R diff --git a/R/chattr-use.R b/R/chattr-use.R index ce76be8..9387422 100644 --- a/R/chattr-use.R +++ b/R/chattr-use.R @@ -55,6 +55,10 @@ ch_get_ymls <- function(menu = TRUE) { gpt_token <- ch_openai_token(fail = FALSE) gpt_exists <- !is.null(gpt_token) + dbrx_token <- ch_databricks_token(fail = FALSE) + dbrx_host <- ch_databricks_host(fail = FALSE) + dbrx_exists <- !is.null(dbrx_token) && !is.null(dbrx_host) + llama_defaults <- "configs/llamagpt.yml" %>% package_file() %>% read_yaml() @@ -87,6 +91,12 @@ ch_get_ymls <- function(menu = TRUE) { prep_files$gpt4 <- NULL } + if (!dbrx_exists) { + prep_files$`databricks-dbrx` <- NULL + prep_files$`databricks-llama3-70b` <- NULL + prep_files$`databricks-mixtral8x7b` <- NULL + } + if (!llama_exists) { prep_files$llamagpt <- NULL } diff --git a/README.qmd b/README.qmd index 537a2f3..1fff03c 100644 --- a/README.qmd +++ b/README.qmd @@ -47,7 +47,7 @@ url <- urls[grepl(".io", urls)][[1]] `chattr` is an interface to LLMs (Large Language Models). It enables interaction with the model directly from the RStudio IDE. `chattr` allows you to submit a prompt to the LLM from your script, or by using the provided Shiny Gadget. -This package's main goal is to aid in exploratory data analysis (EDA) tasks. The additional information appended to your request, provides a sort of “guard rails”, so that the packages and techniques we usually recommend as best practice, are used in the model’s responses. +This package's main goal is to aid in exploratory data analysis (EDA) tasks. The additional information appended to your request, provides a sort of "guard rails", so that the packages and techniques we usually recommend as best practice, are used in the model's responses. ## Install {#install} @@ -62,11 +62,12 @@ remotes::install_github("mlverse/chattr") `chattr` provides two main integration with two main LLM back-ends. Each back-end provides access to multiple LLM types. The plan is to add more back-ends as time goes by: -| Provider | Models | Setup Instructions | -|:-----------------:|:--------------------------------:|:-----------------:| -| OpenAI | GPT Models accessible via the OpenAI's REST API. `chattr` provides a convenient way to interact with GPT 4, and 3.5. | [Interact with OpenAI GPT models](https://mlverse.github.io/chattr/articles/openai-gpt.html) | -| [LLamaGPT-Chat](https://github.com/kuvaus/LlamaGPTJ-chat) | LLM models available in your computer. Including GPT-J, LLaMA, and MPT. Tested on a [GPT4ALL](https://gpt4all.io/index.html) model. **LLamaGPT-Chat** is a command line chat program for models written in C++. | [Interact with local models](https://mlverse.github.io/chattr/articles/backend-llamagpt.html) | -| [GitHub Copilot](https://docs.posit.co/ide/user/ide/guide/tools/copilot.html) | AI pair programmer that offers autocomplete-style suggestions as you code | [Interact with GitHub Copilot Chat](https://mlverse.github.io/chattr/articles/copilot-chat.html) | +| Provider | Models | Setup Instructions | +|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:| +| OpenAI | GPT Models accessible via the OpenAI's REST API. `chattr` provides a convenient way to interact with GPT 4, and 3.5. | [Interact with OpenAI GPT models](https://mlverse.github.io/chattr/articles/openai-gpt.html) | +| [LLamaGPT-Chat](https://github.com/kuvaus/LlamaGPTJ-chat) | LLM models available in your computer. Including GPT-J, LLaMA, and MPT. Tested on a [GPT4ALL](https://gpt4all.io/index.html) model. **LLamaGPT-Chat** is a command line chat program for models written in C++. | [Interact with local models](https://mlverse.github.io/chattr/articles/backend-llamagpt.html) | +| [GitHub Copilot](https://docs.posit.co/ide/user/ide/guide/tools/copilot.html) | AI pair programmer that offers autocomplete-style suggestions as you code | [Interact with GitHub Copilot Chat](https://mlverse.github.io/chattr/articles/copilot-chat.html) | +| [Databricks](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#databricks-foundation-model-apis) | DBRX, Meta Llama 3 70B, and Mixtral 8x7B via [Databricks foundational model REST API](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#pay-per-token-foundation-model-apis). | Interact with Databricks foundation chat models | ## Using {#using} diff --git a/tests/testthat/_snaps/backend-databricks.md b/tests/testthat/_snaps/backend-databricks.md new file mode 100644 index 0000000..48e13e3 --- /dev/null +++ b/tests/testthat/_snaps/backend-databricks.md @@ -0,0 +1,58 @@ +# Submit method works + + Code + ch_submit(def, "test", preview = TRUE) + Output + [[1]] + [[1]]$role + [1] "system" + + [[1]]$content + [1] "You are a helpful coding assistant" + + + [[2]] + [[2]]$role + [1] "user" + + [[2]]$content + [1] "* Use the 'Tidy Modeling with R' (https://www.tmwr.org/) book as main reference \n* Use the 'R for Data Science' (https://r4ds.had.co.nz/) book as main reference \n* Use tidyverse packages: readr, ggplot2, dplyr, tidyr \n* For models, use tidymodels packages: recipes, parsnip, yardstick, workflows, broom \n* Avoid explanations unless requested by user, expecting code only\ntest" + + + +--- + + Code + ch_submit(def, "test", preview = TRUE) + Output + [[1]] + [[1]]$role + [1] "system" + + [[1]]$content + [1] "You are a helpful coding assistant" + + + [[2]] + [[2]]$role + [1] "user" + + [[2]]$content + [1] "* Use the 'Tidy Modeling with R' (https://www.tmwr.org/) book as main reference \n* Use the 'R for Data Science' (https://r4ds.had.co.nz/) book as main reference \n* Use tidyverse packages: readr, ggplot2, dplyr, tidyr \n* For models, use tidymodels packages: recipes, parsnip, yardstick, workflows, broom \n* Avoid explanations unless requested by user, expecting code only\ntest" + + + +# Init messages work + + Code + app_init_message(def) + Message + * Provider: Databricks + * Path/URL: serving-endpoints + * Model: databricks-meta-llama-3-70b-instruct + * Label: Meta Llama 3 70B (Databricks) + ! A list of the top 10 files will be sent externally to Databricks with every request + To avoid this, set the number of files to be sent to 0 using `chattr::chattr_defaults(max_data_files = 0)` + ! A list of the top 10 data.frames currently in your R session will be sent externally to Databricks with every request + To avoid this, set the number of data.frames to be sent to 0 using `chattr::chattr_defaults(max_data_frames = 0)` + diff --git a/tests/testthat/test-backend-databricks.R b/tests/testthat/test-backend-databricks.R new file mode 100644 index 0000000..5a0342b --- /dev/null +++ b/tests/testthat/test-backend-databricks.R @@ -0,0 +1,91 @@ +test_that("Submit method works", { + local_mocked_bindings( + ch_databricks_complete = function(...) { + return("test return") + } + ) + def <- test_simulate_model("databricks-llama3-70b.yml") + expect_equal( + ch_submit(def, "test"), + "test return" + ) + expect_snapshot( + ch_submit(def, "test", preview = TRUE) + ) + def$include_history <- FALSE + expect_snapshot( + ch_submit(def, "test", preview = TRUE) + ) +}) + +test_that("Completion function works", { + withr::with_envvar( + new = c( + "DATABRICKS_HOST" = "test", + "DATABRICKS_TOKEN" = "test" + ), + { + local_mocked_bindings( + req_perform_stream = function(...) { + x <- list() + x$status_code <- 200 + x + } + ) + def <- test_simulate_model("databricks-llama3-70b.yml") + expect_null( + ch_databricks_complete( + prompt = "test", + defaults = def, + ) + ) + } + ) +}) + +test_that("Error when status is not 200", { + withr::with_envvar( + new = c( + "DATABRICKS_HOST" = "test", + "DATABRICKS_TOKEN" = "test" + ), + { + local_mocked_bindings( + req_perform_stream = function(...) { + x <- list() + x$status_code <- 400 + x + } + ) + def <- test_simulate_model("databricks-llama3-70b.yml") + expect_error( + ch_databricks_complete( + prompt = "test", + defaults = def, + ) + ) + } + ) +}) + +test_that("Missing token returns error", { + withr::with_envvar( + new = c("DATABRICKS_TOKEN" = NA), + expect_error(ch_databricks_token(d)) + ) +}) + +test_that("Missing host returns error", { + withr::with_envvar( + new = c("DATABRICKS_HOST" = NA), + expect_error(ch_databricks_host(d)) + ) +}) + + +test_that("Init messages work", { + def <- test_simulate_model("databricks-llama3-70b.yml") + def$max_data_files <- 10 + def$max_data_frames <- 10 + expect_snapshot(app_init_message(def)) +}) From b03b1294252ddc9ce500811deab4c68457f2e4c9 Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Mon, 6 May 2024 23:29:24 +1000 Subject: [PATCH 3/6] Rendering README --- README.md | 52 ++++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 0837df3..8c363e3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # chattr - [![R-CMD-check](https://github.com/mlverse/chattr/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/mlverse/chattr/actions/workflows/R-CMD-check.yaml) @@ -55,9 +54,9 @@ back-ends as time goes by: ---+++ @@ -98,6 +97,16 @@ autocomplete-style suggestions as you code href="https://mlverse.github.io/chattr/articles/copilot-chat.html">Interact with GitHub Copilot Chat + + + + +
DatabricksDBRX, Meta Llama 3 70B, and Mixtral 8x7B +via Databricks +foundational model REST API.Interact with Databricks foundation chat +models
@@ -144,12 +153,8 @@ chattr_use("gpt35") chattr_app() ``` -
- - -
+![Screenshot of the Sniny gadget app in a dark mode RStudio +theme](man/figures/readme/chat1.png)
@@ -184,12 +189,7 @@ The screen that opens will contain the following: information attached to your prompt. Including the number of max data files, and data frames sent to the LLM. -
- - -
+![Screenshot of the Sniny gadget options](man/figures/readme/chat2.png) ### Additional ways to interact @@ -204,12 +204,8 @@ structure of data frames currently in your environment, the path for the data files in your working directory. If supported by the model, `chattr` will include the current chat history. -
- - -
+![Diagram that illustrates how `chattr` handles model +requests](man/figures/readme/chattr-diagram.png) To see what `chattr` will send to the model, set the `preview` argument to `TRUE`: @@ -272,30 +268,18 @@ section. - Select *Tools* in the top menu, and then select *Modify Keyboard Shortcuts* -
Screenshot that shows where to find the option to modify the keyboard shortcuts - -
- Search for the `chattr` adding by writing “open chat”, in the search box -
Screenshot that shows where to input the addin search - -
- To select a key combination for your shortcut, click on the Shortcut box and then type *press* the key combination in your keyboard. In my case, I chose *Ctrl+Shift+C* -
Screenshot that shows what the interface looks like when a shortcut has been selected - -
From 6f2c41c9f30acb9bcb696544320e578b0ed34386 Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Mon, 6 May 2024 23:57:30 +1000 Subject: [PATCH 4/6] Adding user agent --- R/backend-databricks.R | 2 ++ tests/testthat/_snaps/ch_context.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/R/backend-databricks.R b/R/backend-databricks.R index 028b1e8..4d6ccc1 100644 --- a/R/backend-databricks.R +++ b/R/backend-databricks.R @@ -32,6 +32,7 @@ ch_databricks_complete <- function(prompt, defaults, stream = TRUE) { token <- ch_databricks_token(defaults) host <- ch_databricks_host(defaults) + user_agent <-paste0("chattr/", utils::packageVersion('chattr')) req_result <- host %>% request() %>% @@ -39,6 +40,7 @@ ch_databricks_complete <- function(prompt, defaults, stream = TRUE) { req_url_path_append(defaults$model) %>% req_url_path_append("invocations") %>% req_auth_bearer_token(token) %>% + req_user_agent(user_agent) %>% req_body_json(req_body) req_result <- req_result %>% diff --git a/tests/testthat/_snaps/ch_context.md b/tests/testthat/_snaps/ch_context.md index d30a072..472dfd2 100644 --- a/tests/testthat/_snaps/ch_context.md +++ b/tests/testthat/_snaps/ch_context.md @@ -20,7 +20,7 @@ Code ch_context_data_files(file_types = "R") Output - [1] "Data files available: \n|- helper-utils.R\n|- setup.R\n|- test-app-server.R\n|- test-app-ui.R\n|- test-backend-llamagpt.R\n|- test-backend-openai.R\n|- test-ch-defaults-save.R\n|- test-ch_context.R\n|- test-ch_defaults.R\n|- test-chattr-test.R\n|- test-chattr-use.R\n|- test-chattr.R\n|- test-ide.R\n|- test-utils.R" + [1] "Data files available: \n|- helper-utils.R\n|- setup.R\n|- test-app-server.R\n|- test-app-ui.R\n|- test-backend-databricks.R\n|- test-backend-llamagpt.R\n|- test-backend-openai.R\n|- test-ch-defaults-save.R\n|- test-ch_context.R\n|- test-ch_defaults.R\n|- test-chattr-test.R\n|- test-chattr-use.R\n|- test-chattr.R\n|- test-ide.R\n|- test-utils.R" --- From 1795f95b3bd60e470c7ccd1afff765863f79c697 Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Tue, 7 May 2024 01:11:50 +1000 Subject: [PATCH 5/6] Adding vignette, updating docs, --- R/chattr-use.R | 8 +- ...70b.yml => databricks-meta-llama3-70b.yml} | 0 man/chattr_use.Rd | 5 +- tests/testthat/test-backend-databricks.R | 8 +- vignettes/backend-databricks.Rmd | 142 ++++++++++++++++++ 5 files changed, 156 insertions(+), 7 deletions(-) rename inst/configs/{databricks-llama3-70b.yml => databricks-meta-llama3-70b.yml} (100%) create mode 100644 vignettes/backend-databricks.Rmd diff --git a/R/chattr-use.R b/R/chattr-use.R index 9387422..d3e00e7 100644 --- a/R/chattr-use.R +++ b/R/chattr-use.R @@ -1,6 +1,7 @@ #' Sets the LLM model to use in your session #' @param x The label of the LLM model to use, or the path of a valid YAML -#' default file . Valid values are 'copilot', 'gpt4', 'gpt35', and 'llamagpt'. +#' default file . Valid values are 'copilot', 'gpt4', 'gpt35', 'llamagpt', +#' 'databricks-dbrx', 'databricks-meta-llama3-70b', and 'databricks-mixtral8x7b'. #' The value 'test' is also acceptable, but it is meant for package examples, #' and internal testing. #' @param ... Default values to modify. @@ -18,6 +19,9 @@ #' R. `chattr` will look for the default location where RStudio saves the #' Copilot authentication information. #' +#' * Databricks - `chattr` checks for presence of R user's Databricks host and +#' token ('DATABRICKS_HOST' and 'DATABRICKS TOKEN' environment variables). +#' #' Use the 'CHATTR_MODEL' environment variable to set it for the #' R session, or create a YAML file named 'chattr.yml' in your working directory #' to control the model, and the defaults it will use to communicate with such @@ -93,7 +97,7 @@ ch_get_ymls <- function(menu = TRUE) { if (!dbrx_exists) { prep_files$`databricks-dbrx` <- NULL - prep_files$`databricks-llama3-70b` <- NULL + prep_files$`databricks-meta-llama3-70b` <- NULL prep_files$`databricks-mixtral8x7b` <- NULL } diff --git a/inst/configs/databricks-llama3-70b.yml b/inst/configs/databricks-meta-llama3-70b.yml similarity index 100% rename from inst/configs/databricks-llama3-70b.yml rename to inst/configs/databricks-meta-llama3-70b.yml diff --git a/man/chattr_use.Rd b/man/chattr_use.Rd index 223401c..b9f1893 100644 --- a/man/chattr_use.Rd +++ b/man/chattr_use.Rd @@ -8,7 +8,8 @@ chattr_use(x = NULL, ...) } \arguments{ \item{x}{The label of the LLM model to use, or the path of a valid YAML -default file . Valid values are 'copilot', 'gpt4', 'gpt35', and 'llamagpt'. +default file . Valid values are 'copilot', 'gpt4', 'gpt35', 'llamagpt', +'databricks-dbrx', 'databricks-meta-llama3-70b', and 'databricks-mixtral8x7b'. The value 'test' is also acceptable, but it is meant for package examples, and internal testing.} @@ -33,6 +34,8 @@ environment variable. Then restart R, and try again. \item GitHub Copilot - Setup GitHub Copilot in your RStudio IDE, and restart R. \code{chattr} will look for the default location where RStudio saves the Copilot authentication information. +\item Databricks - \code{chattr} checks for presence of R user's Databricks host and +token ('DATABRICKS_HOST' and 'DATABRICKS TOKEN' environment variables). } Use the 'CHATTR_MODEL' environment variable to set it for the diff --git a/tests/testthat/test-backend-databricks.R b/tests/testthat/test-backend-databricks.R index 5a0342b..990a906 100644 --- a/tests/testthat/test-backend-databricks.R +++ b/tests/testthat/test-backend-databricks.R @@ -4,7 +4,7 @@ test_that("Submit method works", { return("test return") } ) - def <- test_simulate_model("databricks-llama3-70b.yml") + def <- test_simulate_model("databricks-meta-llama3-70b.yml") expect_equal( ch_submit(def, "test"), "test return" @@ -32,7 +32,7 @@ test_that("Completion function works", { x } ) - def <- test_simulate_model("databricks-llama3-70b.yml") + def <- test_simulate_model("databricks-meta-llama3-70b.yml") expect_null( ch_databricks_complete( prompt = "test", @@ -57,7 +57,7 @@ test_that("Error when status is not 200", { x } ) - def <- test_simulate_model("databricks-llama3-70b.yml") + def <- test_simulate_model("databricks-meta-llama3-70b.yml") expect_error( ch_databricks_complete( prompt = "test", @@ -84,7 +84,7 @@ test_that("Missing host returns error", { test_that("Init messages work", { - def <- test_simulate_model("databricks-llama3-70b.yml") + def <- test_simulate_model("databricks-meta-llama3-70b.yml") def$max_data_files <- 10 def$max_data_frames <- 10 expect_snapshot(app_init_message(def)) diff --git a/vignettes/backend-databricks.Rmd b/vignettes/backend-databricks.Rmd new file mode 100644 index 0000000..9e55b3c --- /dev/null +++ b/vignettes/backend-databricks.Rmd @@ -0,0 +1,142 @@ +--- +title: "Interact with Databricks foundation models" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Interact with Databricks foundation models} + %\VignetteEncoding{UTF-8} + %\VignetteEngine{knitr::rmarkdown} +editor_options: + markdown: + wrap: 72 +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +## Intro + +[Databricks](https://docs.databricks.com/en/introduction/index.html) +customers have access to [foundation model +APIs](https://docs.databricks.com/en/machine-learning/foundation-models/index.html) +like DBRX, Meta Llama 3 70B, and Mixtral 8x7B. Databricks also provides +the ability to train and [deploy custom +models](https://docs.databricks.com/en/machine-learning/foundation-models/deploy-prov-throughput-foundation-model-apis.html). + +`chattr` supports the following models on Databricks by default: + +| Model | Databricks Model Name | `chattr` Name | +|---------------------|------------------------------|---------------------| +| DBRX Instruct | `databricks-dbrx-instruct` | `databricks-dbrx` | +| Meta-Llama-3-70B-Instruct | `databricks-meta-llama-3-70b-instruct` | `databricks-meta-llama3-70b` | +| Mixtral-8x7B Instruct | `databricks-mixtral-8x7b-instruct` | `databricks-mixtral8x7b` | + +: [Supported Databricks pay-per-token foundation +models](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#pay-per-token-foundation-model-apis) + +## Authentication + +Databricks requires a +[**host**](https://docs.databricks.com/en/workspace/workspace-details.html#workspace-instance-names-urls-and-ids) +(workspace URL) and +[**token**](https://docs.databricks.com/en/dev-tools/auth/pat.html#databricks-personal-access-tokens-for-workspace-users) +to authenticate. Both are required for any non-Databricks application, +such as `chattr`, to interact with the models in the Databricks +workspace. + +The token can be generated by the user in the workspace under the +developer settings +([docs](https://docs.databricks.com/en/dev-tools/auth/pat.html#databricks-personal-access-tokens-for-workspace-users)) +and the host can be found in the workspaces URL +([docs](https://docs.databricks.com/en/workspace/workspace-details.html#workspace-instance-names-urls-and-ids)). + +By default, `chattr` will look for the credentials in environment +variables: + +- `DATABRICKS_HOST` + +- `DATABRICKS_TOKEN` + +Use `Sys.setenv()` to set the variable. The downside of using this +method is that the variable will only be available during the current R +session: + +``` r +Sys.setenv("DATABRICKS_HOST" = "https://xxxxx.cloud.databricks.com") +Sys.setenv("DATABRICKS_TOKEN" = "####################") +``` + +A preferred method is to save the secret key to the `.Renviron` file. +This way, there is no need to load the environment variable every time +you start a new R session. The `.Renviron` file is available in your +home directory. Here is an example of the entry: + +``` +DATABRICKS_HOST = https://xxxxx.cloud.databricks.com +DATABRICKS_TOKEN = #################### +``` + +## Change the model + +### Supported Models + +By default, `chattr` is setup to interact with GPT 4 (`gpt-4`). To +switch to Meta Llama 3 70B you can run: + +```{r} +library(chattr) + +chattr_use("databricks-meta-llama3-70b") +``` + +#### Custom Models + +If a model doesn't appear in the supported table but is deployed on +[Databricks model +serving](https://docs.databricks.com/en/machine-learning/model-serving/index.html) +as OpenAI-compatible ([configured with `llm/v1/chat` in +mlflow](https://mlflow.org/docs/latest/llms/deployments/index.html#general-configuration-parameters)) +then you can specify the model name explicitly with `chattr_use()` + +For example if you have deployed a fine-tuned version LLM with an +endpoint name of `"CustomLLM"`: + +```{r} +library(chattr) + +# use any existing databricks foundation model name (e.g. datarbicks-dbrx) +# then adjust the default model name to 'CustomMixtral' +chattr_use(x = "databricks-dbrx", model = "CustomLLM") +``` + +## Data files and data frames + +Because it is information about your environment and work space, by +default `chattr` avoids sending any data files, and data frame +information to Databricks. Sending this information is convenient +because it creates a shorthand for your requests. If you wish to submit +this information as part of your prompts, use `chattr_defaults()`, for +example: + +- `chattr_defaults(max_data_files = 10)` +- `chattr_defaults(max_data_frames = 10)` + +These two commands will send 10 data frames, and 10 data files as part +of your prompt. You can decide the number to limit this by. The more you +send, the larger your prompt. + +If any of these is set to anything but 0, a warning will show up every +time you start the Shiny app: + +``` +• Provider: Databricks +• Path/URL: serving-endpoints +• Model: databricks-dbrx-instruct +• Label: DBRX (Databricks) +! A list of the top 10 files will be sent externally to Databricks with every request +To avoid this, set the number of files to be sent to 0 using chattr::chattr_defaults(max_data_files = 0)Î +``` + From cb6a8b446aaab7801ea3761b4e992129d3b4fe7c Mon Sep 17 00:00:00 2001 From: Zac Davies Date: Tue, 7 May 2024 10:48:11 +1000 Subject: [PATCH 6/6] Adding vignette link in README and update to NEWS --- NEWS.md | 5 +++++ README.md | 11 ++++++----- README.qmd | 12 ++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/NEWS.md b/NEWS.md index 812ccb6..4313cd8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,11 @@ * Fixes how it identifies the user's current UI (console, app, notebook) and appropriately outputs the response from the model end-point (#92) +## Databricks + +* Adding support for Databricks foundation model API (DBRX, Meta Llama 3 70B, +Mixtral 8x7B) (#99) + ## OpenAI * Fixes how it displays error from the model end-point when being used in a diff --git a/README.md b/README.md index 8c363e3..c64955a 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,11 @@ remotes::install_github("mlverse/chattr") back-end provides access to multiple LLM types. The plan is to add more back-ends as time goes by: - +
--++ @@ -104,8 +104,9 @@ href="https://docs.databricks.com/en/machine-learning/foundation-models/index.ht via Databricks foundational model REST API. - +
Interact with Databricks foundation chat -modelsInteract +with Databricks foundation chat models
diff --git a/README.qmd b/README.qmd index 1fff03c..91f87b6 100644 --- a/README.qmd +++ b/README.qmd @@ -62,12 +62,12 @@ remotes::install_github("mlverse/chattr") `chattr` provides two main integration with two main LLM back-ends. Each back-end provides access to multiple LLM types. The plan is to add more back-ends as time goes by: -| Provider | Models | Setup Instructions | -|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:| -| OpenAI | GPT Models accessible via the OpenAI's REST API. `chattr` provides a convenient way to interact with GPT 4, and 3.5. | [Interact with OpenAI GPT models](https://mlverse.github.io/chattr/articles/openai-gpt.html) | -| [LLamaGPT-Chat](https://github.com/kuvaus/LlamaGPTJ-chat) | LLM models available in your computer. Including GPT-J, LLaMA, and MPT. Tested on a [GPT4ALL](https://gpt4all.io/index.html) model. **LLamaGPT-Chat** is a command line chat program for models written in C++. | [Interact with local models](https://mlverse.github.io/chattr/articles/backend-llamagpt.html) | -| [GitHub Copilot](https://docs.posit.co/ide/user/ide/guide/tools/copilot.html) | AI pair programmer that offers autocomplete-style suggestions as you code | [Interact with GitHub Copilot Chat](https://mlverse.github.io/chattr/articles/copilot-chat.html) | -| [Databricks](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#databricks-foundation-model-apis) | DBRX, Meta Llama 3 70B, and Mixtral 8x7B via [Databricks foundational model REST API](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#pay-per-token-foundation-model-apis). | Interact with Databricks foundation chat models | +| Provider | Models | Setup Instructions | +|:-------------------:|:--------------------------------:|:----------------:| +| OpenAI | GPT Models accessible via the OpenAI's REST API. `chattr` provides a convenient way to interact with GPT 4, and 3.5. | [Interact with OpenAI GPT models](https://mlverse.github.io/chattr/articles/openai-gpt.html) | +| [LLamaGPT-Chat](https://github.com/kuvaus/LlamaGPTJ-chat) | LLM models available in your computer. Including GPT-J, LLaMA, and MPT. Tested on a [GPT4ALL](https://gpt4all.io/index.html) model. **LLamaGPT-Chat** is a command line chat program for models written in C++. | [Interact with local models](https://mlverse.github.io/chattr/articles/backend-llamagpt.html) | +| [GitHub Copilot](https://docs.posit.co/ide/user/ide/guide/tools/copilot.html) | AI pair programmer that offers autocomplete-style suggestions as you code | [Interact with GitHub Copilot Chat](https://mlverse.github.io/chattr/articles/copilot-chat.html) | +| [Databricks](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#databricks-foundation-model-apis) | DBRX, Meta Llama 3 70B, and Mixtral 8x7B via [Databricks foundational model REST API](https://docs.databricks.com/en/machine-learning/foundation-models/index.html#pay-per-token-foundation-model-apis). | [Interact with Databricks foundation chat models](https://mlverse.github.io/chattr/articles/backend-databricks.html) | ## Using {#using}