Generation in Rbebelm is event-based. The Rust decode
loop emits a finite event protocol reported by
bebel_event_types().
library(Rbebelm)
bebel_event_types()
#> [1] "start" "thinking_start" "thinking_delta" "thinking_end"
#> [5] "text_start" "text_delta" "text_end" "tool_list_start"
#> [9] "tool_list_delta" "tool_list_end" "tool_call_start" "tool_call_delta"
#> [13] "tool_call_end" "done"Events describe stream lifecycle, thinking blocks, answer text
blocks, tool-list blocks, tool-call blocks, and completion. Console
output is just one event handler:
bebel_console_event().
Collect text deltas
Use on_event = NULL for silent generation, or provide a
callback to consume selected events.
model <- bebel_model_load(Sys.getenv("BEBELM_WEIGHTS_FILE"), num_threads = 2)
text <- character()
thinking <- character()
turn <- bebel_generate(
model,
"A text delta callback can",
greedy = TRUE,
max_gen = 12,
max_think = 16,
on_event = bebel_event_handler(
text_delta = function(event) text <<- c(text, event$delta),
thinking_delta = function(event) thinking <<- c(thinking, event$delta)
)
)
paste0(text, collapse = "")
#> [1] " be used to update a text field in a UI component."
turn[c("stop", "generated_tokens")]
#> $stop
#> [1] "max_new"
#>
#> $generated_tokens
#> [1] 12Handler lists
A named list can also be supplied directly. Unknown handler names are rejected so stale event code fails early.
counts <- c(text_delta = 0L, thinking_delta = 0L, done = 0L)
invisible(bebel_generate(
model,
"An event handler list can",
greedy = TRUE,
max_gen = 4,
max_think = 16,
on_event = list(
text_delta = function(event) counts["text_delta"] <<- counts[["text_delta"]] + 1L,
thinking_delta = function(event) counts["thinking_delta"] <<- counts[["thinking_delta"]] + 1L,
done = function(event) counts["done"] <<- counts[["done"]] + 1L
)
))
counts
#> text_delta thinking_delta done
#> 4 0 1SSE example
An SSE endpoint can serialize each event as it arrives. The sketch below shows the adapter shape; the exact response object depends on the web framework.
sse_handler <- function(response) {
bebel_event_handler(
default = function(event) {
payload <- event$delta
if (is.null(payload)) payload <- event$content
if (is.null(payload)) payload <- ""
response$write(paste0("event: ", event$type, "\n"))
response$write(paste0("data: ", payload, "\n\n"))
response$flush()
}
)
}
bebel_agent_generate(agent, on_event = sse_handler(response))Tool adapters use the same event stream.
bebel_agent_run() listens for tool_call_end
events, parses their accumulated content, invokes R tools, and appends
tool results to the transcript.