## ----eval=FALSE--------------------------------------------------------------- # install.packages("ollamar") ## ----eval=FALSE--------------------------------------------------------------- # # install.packages("remotes") # run this line if you don't have the remotes library # remotes::install_github("hauselin/ollamar") ## ----eval=FALSE--------------------------------------------------------------- # library(ollamar) # # test_connection() # test connection to Ollama server # # if you see "Ollama local server not running or wrong server," Ollama app/server isn't running # # # generate a response/text based on a prompt; returns an httr2 response by default # resp <- generate("llama3.1", "tell me a 5-word story") # resp # # #' interpret httr2 response object # #' # #' Status: 200 OK # if successful, status code should be 200 OK # #' Content-Type: application/json # #' Body: In memory (414 bytes) # # # get just the text from the response object # resp_process(resp, "text") # # get the text as a tibble dataframe # resp_process(resp, "df") # # # alternatively, specify the output type when calling the function initially # txt <- generate("llama3.1", "tell me a 5-word story", output = "text") # # # list available models (models you've pulled/downloaded) # list_models() # name size parameter_size quantization_level modified # 1 codegemma:7b 5 GB 9B Q4_0 2024-07-27T23:44:10 # 2 llama3.1:latest 4.7 GB 8.0B Q4_0 2024-07-31T07:44:33 ## ----eval=FALSE--------------------------------------------------------------- # pull("llama3.1") # download a model (equivalent bash code: ollama run llama3.1) # list_models() # verify you've pulled/downloaded the model ## ----eval=FALSE--------------------------------------------------------------- # list_models() # see the models you've pulled/downloaded # delete("all-minilm:latest") # returns a httr2 response object ## ----eval=FALSE--------------------------------------------------------------- # resp <- generate("llama3.1", "Tomorrow is a...") # return httr2 response object by default # resp # # resp_process(resp, "text") # process the response to return text/vector output # # generate("llama3.1", "Tomorrow is a...", output = "text") # directly return text/vector output # generate("llama3.1", "Tomorrow is a...", stream = TRUE) # return httr2 response object and stream output # generate("llama3.1", "Tomorrow is a...", output = "df", stream = TRUE) # # # image prompt # # use a vision/multi-modal model # generate("benzie/llava-phi-3", "What is in the image?", images = "image.png", output = 'text') ## ----eval=FALSE--------------------------------------------------------------- # messages <- create_message("what is the capital of australia") # default role is user # resp <- chat("llama3.1", messages) # default returns httr2 response object # resp # # resp_process(resp, "text") # process the response to return text/vector output # # # specify output type when calling the function # chat("llama3.1", messages, output = "text") # text vector # chat("llama3.1", messages, output = "df") # data frame/tibble # chat("llama3.1", messages, output = "jsonlist") # list # chat("llama3.1", messages, output = "raw") # raw string # chat("llama3.1", messages, stream = TRUE) # stream output and return httr2 response object # # # create chat history # messages <- create_messages( # create_message("end all your sentences with !!!", role = "system"), # create_message("Hello!"), # default role is user # create_message("Hi, how can I help you?!!!", role = "assistant"), # create_message("What is the capital of Australia?"), # create_message("Canberra!!!", role = "assistant"), # create_message("what is your name?") # ) # cat(chat("llama3.1", messages, output = "text")) # print the formatted output # # # image prompt # messages <- create_message("What is in the image?", images = "image.png") # # use a vision/multi-modal model # chat("benzie/llava-phi-3", messages, output = "text") ## ----eval=FALSE--------------------------------------------------------------- # messages <- create_message("Tell me a 1-paragraph story.") # # # use "llama3.1" model, provide list of messages, return text/vector output, and stream the output # chat("llama3.1", messages, output = "text", stream = TRUE) # # chat(model = "llama3.1", messages = messages, output = "text", stream = TRUE) # same as above ## ----eval=FALSE--------------------------------------------------------------- # list( # main list containing all the messages # list(role = "user", content = "Hello!"), # first message as a list # list(role = "assistant", content = "Hi! How are you?") # second message as a list # ) ## ----eval=FALSE--------------------------------------------------------------- # # create a chat history with one message # messages <- create_message(content = "Hi! How are you? (1ST MESSAGE)", role = "assistant") # # or simply, messages <- create_message("Hi! How are you?", "assistant") # messages[[1]] # get 1st message # # # append (add to the end) a new message to the existing messages # messages <- append_message("I'm good. How are you? (2ND MESSAGE)", "user", messages) # messages[[1]] # get 1st message # messages[[2]] # get 2nd message (newly added message) # # # prepend (add to the beginning) a new message to the existing messages # messages <- prepend_message("I'm good. How are you? (0TH MESSAGE)", "user", messages) # messages[[1]] # get 0th message (newly added message) # messages[[2]] # get 1st message # messages[[3]] # get 2nd message # # # insert a new message at a specific index/position (2nd position in the example below) # # by default, the message is inserted at the end of the existing messages (position -1 is the end/default) # messages <- insert_message("I'm good. How are you? (BETWEEN 0 and 1 MESSAGE)", "user", messages, 2) # messages[[1]] # get 0th message # messages[[2]] # get between 0 and 1 message (newly added message) # messages[[3]] # get 1st message # messages[[4]] # get 2nd message # # # delete a message at a specific index/position (2nd position in the example below) # messages <- delete_message(messages, 2) # # # create a chat history with multiple messages # messages <- create_messages( # create_message("You're a knowledgeable tour guide.", role = "system"), # create_message("What is the capital of Australia?") # default role is user # ) ## ----eval=FALSE--------------------------------------------------------------- # # create a list of messages # messages <- create_messages( # create_message("You're a knowledgeable tour guide.", role = "system"), # create_message("What is the capital of Australia?") # ) # # # convert to dataframe # df <- dplyr::bind_rows(messages) # with dplyr library # df <- data.table::rbindlist(messages) # with data.table library # # # convert dataframe to list with apply, purrr functions # apply(df, 1, as.list) # convert each row to a list with base R apply # purrr::transpose(df) # with purrr library ## ----eval=FALSE--------------------------------------------------------------- # embed("llama3.1", "Hello, how are you?") # # # don't normalize embeddings # embed("llama3.1", "Hello, how are you?", normalize = FALSE) ## ----eval=FALSE--------------------------------------------------------------- # # get embeddings for similar prompts # e1 <- embed("llama3.1", "Hello, how are you?") # e2 <- embed("llama3.1", "Hi, how are you?") # # # compute cosine similarity # sum(e1 * e2) # not equals to 1 # sum(e1 * e1) # 1 (identical vectors/embeddings) # # # non-normalized embeddings # e3 <- embed("llama3.1", "Hello, how are you?", normalize = FALSE) # e4 <- embed("llama3.1", "Hi, how are you?", normalize = FALSE) ## ----eval=FALSE--------------------------------------------------------------- # resp <- list_models(output = "resp") # returns a httr2 response object # # # # Status: 200 OK # # Content-Type: application/json # # # process the httr2 response object with the resp_process() function # resp_process(resp, "df") # # or list_models(output = "df") # resp_process(resp, "jsonlist") # list # # or list_models(output = "jsonlist") # resp_process(resp, "raw") # raw string # # or list_models(output = "raw") # resp_process(resp, "resp") # returns the input httr2 response object # # or list_models() or list_models("resp") # resp_process(resp, "text") # text vector # # or list_models("text") ## ----eval=FALSE--------------------------------------------------------------- # add_two_numbers <- function(x, y) { # return(x + y) # } # # multiply_two_numbers <- function(a, b) { # return(a * b) # } # # # each tool needs to be in a list # tool1 <- list(type = "function", # "function" = list( # name = "add_two_numbers", # function name # description = "add two numbers", # parameters = list( # type = "object", # required = list("x", "y"), # function parameters # properties = list( # x = list(class = "numeric", description = "first number"), # y = list(class = "numeric", description = "second number"))) # ) # ) # # tool2 <- list(type = "function", # "function" = list( # name = "multiply_two_numbers", # function name # description = "multiply two numbers", # parameters = list( # type = "object", # required = list("a", "b"), # function parameters # properties = list( # x = list(class = "numeric", description = "first number"), # y = list(class = "numeric", description = "second number"))) # ) # ) ## ----eval=FALSE--------------------------------------------------------------- # msg <- create_message("what is three plus one?") # resp <- chat("llama3.1", msg, tools = list(tool1), output = "tools") # tool <- resp[[1]] # get the first tool/function # # # call the tool function with arguments: add_two_numbers(3, 1) # do.call(tool$name, tool$arguments) ## ----eval=FALSE--------------------------------------------------------------- # msg <- create_message("what is three multiplied by four?") # resp <- chat("llama3.1", msg, tools = list(tool1, tool2), output = "tools") # tool <- resp[[1]] # get the first tool/function # # # call the tool function with arguments: multiply_two_numbers(3, 4) # do.call(tool$name, tool$arguments) ## ----eval=FALSE--------------------------------------------------------------- # msg <- create_message("add three plus four. then multiply by ten") # resp <- chat("llama3.1", msg, tools = list(tool1, tool2), output = "tools") # # # first tool/function: add_two_numbers(3, 4) # do.call(resp[[1]]$name, resp[[1]]$arguments) # 7 # # second tool/function: multiply_two_numbers(7, 10) # do.call(resp[[2]]$name, resp[[2]]$arguments) # 70 ## ----eval=FALSE--------------------------------------------------------------- # # define a JSON schema as a list to constrain a model's output # format <- list( # type = "object", # properties = list( # name = list(type = "string"), # capital = list(type = "string"), # languages = list(type = "array", # items = list(type = "string") # ) # ), # required = list("name", "capital", "languages") # ) # # generate("llama3.1", "tell me about Canada", output = "structured", format = format) # # msg <- create_message("tell me about Canada") # chat("llama3.1", msg, format = format, output = "structured") ## ----eval=FALSE--------------------------------------------------------------- # prompt <- "Tell me a 10-word story" # req <- generate("llama3.1", prompt, output = "req") # returns a httr2_request object ## ----eval=FALSE--------------------------------------------------------------- # library(httr2) # # prompt <- "Tell me a 5-word story" # # # create 5 httr2_request objects that generate a response to the same prompt # reqs <- lapply(1:5, function(r) generate("llama3.1", prompt, output = "req")) # # # make parallel requests and get response # resps <- req_perform_parallel(reqs) # list of httr2_request objects # # # process the responses # sapply(resps, resp_process, "text") # get responses as text # # [1] "She found him in Paris." "She found the key upstairs." # # [3] "She found her long-lost sister." "She found love on Mars." # # [5] "She found the diamond ring." # ## ----eval=FALSE--------------------------------------------------------------- # library(httr2) # library(glue) # library(dplyr) # # # text to classify # texts <- c('I love this product', 'I hate this product', 'I am neutral about this product') # # # create httr2_request objects for each text, using the same system prompt # reqs <- lapply(texts, function(text) { # prompt <- glue("Your only task/role is to evaluate the sentiment of product reviews, and your response should be one of the following:'positive', 'negative', or 'other'. Product review: {text}") # generate("llama3.1", prompt, output = "req") # }) # # # make parallel requests and get response # resps <- req_perform_parallel(reqs) # list of httr2_request objects # # # process the responses # sapply(resps, resp_process, "text") # get responses as text # # [1] "Positive" "Negative." # # [3] "'neutral' translates to... 'other'." # # ## ----eval=FALSE--------------------------------------------------------------- # library(httr2) # library(dplyr) # # # text to classify # texts <- c('I love this product', 'I hate this product', 'I am neutral about this product') # # # create system prompt # chat_history <- create_message("Your only task/role is to evaluate the sentiment of product reviews provided by the user. Your response should simply be 'positive', 'negative', or 'other'.", "system") # # # create httr2_request objects for each text, using the same system prompt # reqs <- lapply(texts, function(text) { # messages <- append_message(text, "user", chat_history) # chat("llama3.1", messages, output = "req") # }) # # # make parallel requests and get response # resps <- req_perform_parallel(reqs) # list of httr2_request objects # # # process the responses # bind_rows(lapply(resps, resp_process, "df")) # get responses as dataframes # # # A tibble: 3 × 4 # # model role content created_at # # # # 1 llama3.1 assistant Positive 2024-08-05T17:54:27.758618Z # # 2 llama3.1 assistant negative 2024-08-05T17:54:27.657525Z # # 3 llama3.1 assistant other 2024-08-05T17:54:27.657067Z #