Skip to content

Commit 169384d

Browse files
authored
Better handling of whitespace-only content (#393)
For `chat_claude()` and `chat_bedrock()`. Fixes #376.
1 parent 388678d commit 169384d

File tree

7 files changed

+38
-2
lines changed

7 files changed

+38
-2
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# ellmer (development version)
22

3+
* `chat_claude()` and `chat_bedrock()` no longer choke after receiving an
4+
output that consists only of whitespace (#376).
5+
36
* `live_browser()` now initializes `shinychat::chat_ui()` with the messages from
47
the chat turns, rather than replaying the turns server-side (#381).
58

R/provider-bedrock.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ method(as_json, list(ProviderBedrock, Turn)) <- function(provider, x) {
284284
}
285285

286286
method(as_json, list(ProviderBedrock, ContentText)) <- function(provider, x) {
287-
list(text = x@text)
287+
if (is_whitespace(x@text)) {
288+
list(text = "[empty string]")
289+
} else {
290+
list(text = x@text)
291+
}
288292
}
289293

290294
method(as_json, list(ProviderBedrock, ContentImageRemote)) <- function(

R/provider-claude.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,11 @@ method(as_json, list(ProviderClaude, Turn)) <- function(provider, x) {
266266
}
267267

268268
method(as_json, list(ProviderClaude, ContentText)) <- function(provider, x) {
269-
list(type = "text", text = x@text)
269+
if (is_whitespace(x@text)) {
270+
list(type = "text", text = "[empty string]")
271+
} else {
272+
list(type = "text", text = x@text)
273+
}
270274
}
271275

272276
method(as_json, list(ProviderClaude, ContentPDF)) <- function(provider, x) {

R/utils.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,7 @@ modify_list <- function(x, y) {
128128

129129
utils::modifyList(x, y)
130130
}
131+
132+
is_whitespace <- function(x) {
133+
grepl("^(\\s|\n)*$", x)
134+
}

tests/testthat/test-provider-bedrock.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ test_that("can use pdfs", {
7272
test_pdf_local(chat_fun)
7373
})
7474

75+
# Provider idiosynchronies -----------------------------------------------
76+
77+
test_that("continues to work after whitespace only outputs (#376)", {
78+
chat <- chat_bedrock()
79+
chat$chat("Respond with only two blank lines")
80+
expect_equal(chat$chat("What's 1+1? Just give me the number"), "2")
81+
})
7582

7683
# Auth --------------------------------------------------------------------
7784

tests/testthat/test-provider-claude.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,9 @@ test_that("can set beta headers", {
6262
req <- chat_request(provider)
6363
expect_equal(req$headers$`anthropic-beta`, c("a", "b"))
6464
})
65+
66+
test_that("continues to work after whitespace only outputs (#376)", {
67+
chat <- chat_claude()
68+
chat$chat("Respond with only two blank lines")
69+
expect_equal(chat$chat("What's 1+1? Just give me the number"), "2")
70+
})

tests/testthat/test-utils.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,11 @@ test_that("informative error if no key", {
1010
expect_false(key_exists("FOO"))
1111
expect_snapshot(key_get("FOO"), error = TRUE)
1212
})
13+
14+
test_that("detects whitespace", {
15+
expect_true(is_whitespace("\n\n\n \t"))
16+
expect_true(is_whitespace(""))
17+
18+
expect_false(is_whitespace("a"))
19+
expect_false(is_whitespace("."))
20+
})

0 commit comments

Comments
 (0)