Skip to content

Commit

Permalink
Merge pull request #125 from MichelNivard/stream-performance-improvem…
Browse files Browse the repository at this point in the history
…ents

Stream performance improvements
  • Loading branch information
JamesHWade authored Jul 7, 2023
2 parents fa22953 + f1ce826 commit aea61dc
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 86 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: gptstudio
Title: Use Large Language Models Directly in your Development Environment
Version: 0.2.0.9004
Version: 0.2.0.9005
Authors@R: c(
person("Michel", "Nivard", , "[email protected]", role = c("aut", "cph")),
person("James", "Wade", , "[email protected]", role = c("aut", "cre", "cph"),
Expand Down
2 changes: 1 addition & 1 deletion R/api_skeletons.R
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ new_gptstudio_request_skeleton_palm <- function(


gptstudio_create_skeleton <- function(service = "openai",
prompt = "What is a ggplot?",
prompt = "Name the top 5 packages in R.",
history = list(
list(
role = "system",
Expand Down
44 changes: 44 additions & 0 deletions R/app_config.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
save_user_config <- function(code_style,
skill, task,
language,
service,
model,
custom_prompt,
stream) {
config <-
data.frame(
code_style,
skill,
task,
language,
service,
model,
custom_prompt,
stream
)
print(config)
user_config_path <- tools::R_user_dir("gptstudio", which = "config")
user_config <- file.path(user_config_path, "config.yml")
if (!dir.exists(user_config_path)) {
dir.create(user_config_path, recursive = TRUE)
}
yaml::write_yaml(config, user_config)
set_user_options(config)
}

set_user_options <- function(config) {
op <- options()

op_gptstudio <- list(
gptstudio.code_style = config$code_style,
gptstudio.skill = config$skill,
gptstudio.task = config$task,
gptstudio.language = config$language,
gptstudio.service = config$service,
gptstudio.model = config$model,
gptstudio.custom_prompt = config$custom_prompt,
gptstudio.stream = config$stream
)
options(op_gptstudio)
invisible()
}
88 changes: 22 additions & 66 deletions R/mod_chat.R
Original file line number Diff line number Diff line change
Expand Up @@ -120,30 +120,32 @@ mod_chat_server <- function(id,
}) %>%
bindEvent(input$clear_history, ignoreNULL = FALSE)

auto_invalidate <- reactiveTimer(10)
reactive_stream <- reactiveFileReader(intervalMillis = 10,
session = session,
filePath = streaming_file(),
readFunc = app_server_file_stream)
reactive_skeleton <- reactiveFileReader(intervalMillis = 10,
session = session,
filePath = skeleton_file(),
readFunc = get_skeleton)

output$streaming <- renderUI({
auto_invalidate()
if (file.exists(streaming_file())) {
app_server_file_stream()
if (reactive_stream() != "No stream file found") {
list(
list(
role = "assistant",
content = gptstudio_env$current_stream
content = reactive_stream()
)
) %>%
style_chat_history(ide_colors = ide_colors)
}
})

observe({
auto_invalidate()
if (file.exists(skeleton_file())) {
Sys.sleep(0.01)
rv$skeleton <- get_skeleton()
rv$chat_history <- rv$skeleton$history
file.remove(skeleton_file())
}
req(!is.null(reactive_skeleton()))
rv$skeleton <- reactive_skeleton()
rv$chat_history <- rv$skeleton$history
file.remove(skeleton_file())
})

output$history <- renderUI({
Expand Down Expand Up @@ -264,19 +266,16 @@ mod_chat_server <- function(id,
}


app_server_file_stream <- function() {
current_stream <- streaming_file() %>% readRDS() %>% try(silent = TRUE)
if (!inherits(current_stream, "try-error")) {
gptstudio_env$current_stream <- current_stream
}
invisible()
app_server_file_stream <- function(path) {
ifelse(file.exists(path), readRDS(path), "No stream file found")
}

gptstudio_submit_job <- function(skeleton,
skill,
style,
task,
custom_prompt) {
cat_print(skeleton)
rs <- r_session_start()
if (rs$get_state() != "idle") {
cli_inform("Background session status: {rs$read()}")
Expand Down Expand Up @@ -329,6 +328,7 @@ gptstudio_job <- function(skeleton = gptstudio_create_skeleton(),
gptstudio_request_perform() %>%
gptstudio_response_process() %>%
save_skeleton()
file.remove(streaming_file())
}

r_session_start <- function() {
Expand All @@ -355,60 +355,16 @@ delete_skeleton <- function() {
if (file.exists(skeleton_file())) file.remove(skeleton_file())
}

get_skeleton <- function() {
if (!file.exists(skeleton_file())) {
get_skeleton <- function(path = skeleton_file()) {
if (!file.exists(path)) {
cli_inform("Not chat history found.")
NULL
} else {
readRDS(skeleton_file())
readRDS(path)
}
}

get_current_history <- function() {
history <- get_skeleton() %>% purrr::pluck("history")
gptstudio_env$current_history <- history
}

save_user_config <- function(code_style,
skill, task,
language,
service,
model,
custom_prompt,
stream) {
config <-
data.frame(
code_style,
skill,
task,
language,
service,
model,
custom_prompt,
stream
)
print(config)
user_config_path <- tools::R_user_dir("gptstudio", which = "config")
user_config <- file.path(user_config_path, "config.yml")
if (!dir.exists(user_config_path)) {
dir.create(user_config_path, recursive = TRUE)
}
yaml::write_yaml(config, user_config)
set_user_options(config)
}

set_user_options <- function(config) {
op <- options()

op_gptstudio <- list(
gptstudio.code_style = config$code_style,
gptstudio.skill = config$skill,
gptstudio.task = config$task,
gptstudio.language = config$language,
gptstudio.service = config$service,
gptstudio.model = config$model,
gptstudio.custom_prompt = config$custom_prompt,
gptstudio.stream = config$stream
)
options(op_gptstudio)
invisible()
}
42 changes: 24 additions & 18 deletions R/openai_streaming.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
stream_chat_completion <- function(prompt,
model = "gpt-3.5-turbo",
openai_api_key = Sys.getenv("OPENAI_API_KEY")) {
if (file.exists(streaming_file())) file.remove(streaming_file())

base_url <- getOption("gptstudio.openai_url")
body <- list(
"model" = model,
Expand All @@ -46,22 +48,17 @@ stream_chat_completion <- function(prompt,
gptstudio_env$stream$raw <- NULL
gptstudio_env$current_stream <- TRUE

response <-
httr2::request(base_url) %>%
httr2::request(base_url) %>%
httr2::req_url_path_append("chat/completions") %>%
httr2::req_body_json(body) %>%
httr2::req_auth_bearer_token(openai_api_key) %>%
httr2::req_headers("Content-Type" = "application/json") %>%
httr2::req_method("POST")

httr2::req_stream(response, callback = function(x) {
openai_stream_parse(x)
TRUE
}, buffer_kb = 0.05)

httr2::req_method("POST") %>%
httr2::req_stream(callback = function(x) {openai_stream_parse(x); TRUE},
buffer_kb = 0.05)
chat_response <- readRDS(streaming_file())
gptstudio_env$current_stream <- NULL
file.remove(streaming_file())
cli_inform("File exists: {file.exists(streaming_file())}")
chat_response
}

Expand All @@ -88,17 +85,26 @@ openai_stream_parse <- function(x) {
paste0(collapse = "") %>%
strsplit("data: ") %>%
unlist() %>%
purrr::discard(~ .x == "") %>%
purrr::discard(~ .x == "")
if (length(res) > 1) {
gptstudio_env$stream$raw <- res[2]
set_to_null <- FALSE
} else {
set_to_null <- TRUE
}
res <- res %>%
purrr::keep(~ substr(.x, (nchar(.x) - 2), nchar(.x)) == "}\n\n")

if (length(res) > 0) {
res <- purrr::map(res, jsonlite::fromJSON) %>%
purrr::map(~ .x$choices$delta$content) %>%
purrr::reduce(paste0)
if (length(res) > 0) {
saveRDS(res, file = streaming_file())
return(res)
}
new_response <- jsonlite::fromJSON(res)
new_response <- new_response$choices$delta$content
gptstudio_env$stream$parsed <- paste0(
gptstudio_env$stream$parsed,
new_response,
collapse = ""
)
if (set_to_null) gptstudio_env$stream$raw <- NULL
saveRDS(gptstudio_env$stream$parsed, file = streaming_file())
} else {
json_res <- try(jsonlite::fromJSON(x), silent = TRUE)
if (!inherits(json_res, "try-error")) {
Expand Down

0 comments on commit aea61dc

Please sign in to comment.