Build a role-flipped message array from a multi-speaker transcript
Source:R/transcript_messages.R
transcript_as_messages.RdRenders a shared, speaker-attributed transcript into a message array from
one speaker's point of view, the way a stateful chat is post-trained to read
it: the current speaker's own past turns become assistant messages (their
own voice), and every other speaker's turns become user messages labeled
with the speaker's name. An optional system block (persona, instructions)
leads the array, and an optional instruction (the current question or "your
turn" cue) closes it as a trailing user message. The result is passed
through ensure_alternating_messages() so it is provider-safe.
Usage
transcript_as_messages(
transcript,
speaker,
system = NULL,
instruction = NULL,
label = function(id) paste0(id, ": "),
sanitize = TRUE,
ensure_final_user = TRUE
)Arguments
- transcript
A data.frame/tibble with character columns
speakerandtext, in chronological order.- speaker
The current speaker's id (matched against
transcript$speaker). Rows with this speaker becomeassistantturns; all others become labeleduserturns.- system
Optional system text (persona, standing instructions) placed as the leading
systemmessage.NULLto omit.- instruction
Optional trailing instruction (current question, "your turn" cue) placed as the final
usermessage.NULLto omit.- label
A function
(speaker_id) -> prefixproducing the in-content label for other speakers' turns; the default renders"<id>: ". The speaker's own turns are never labeled.- sanitize
If
TRUE(default), strip forged role headers and chat control tokens from other speakers' text before embedding.- ensure_final_user
If
TRUE(default) and noinstructionis supplied and the last turn is the speaker's own (anassistantturn), append a minimalusercue so the array ends on a user turn (a sound next-turn generation boundary). SetFALSEfor verbatim archival conversion. Missingtextis coerced to""; a missingspeakeris an error.
Value
A list of message objects (list(role=, content=)) suitable for
call_llm(), guaranteed alternating and user-leading after any system.
Details
Putting the speaker's own turns in the assistant role gives the model a
structural handle on "what I already said", which reduces self-repetition in
multi-agent conversations relative to flattening the whole transcript into one
user block. Other speakers' text stays in user turns (never assistant),
which preserves the trust boundary and is sanitized against forged role
headers.
Examples
tx <- data.frame(
speaker = c("Ana", "Ben", "Cy"),
text = c("I think we ban it.", "Too costly for renters.", "Phase it in."),
stringsAsFactors = FALSE
)
# From Ben's perspective: his line is assistant, Ana's and Cy's are user.
transcript_as_messages(tx, speaker = "Ben",
system = "You are Ben, a renter.",
instruction = "Your turn, Ben.")