Lmml. Narrative. Segment
(lmml v0.2.0)
View Source
Splits a resolved lmml narrative into an ordered list of role-labeled
turns (messages), each renderable to the same typed content-part shape
Lmml.Narrative.Renderer already produces.
A bare lmml narrative is a single blob of prose plus embeds, rendered
as one message. But a narrative frequently represents a multi-turn
conversation -- the examples/ narrative uses headings like
## Turn 1 -- user / ## Turn 2 -- assistant. Segment turns that
structural convention into an actual list of messages, so a whole
conversation carried in one .lmml/.lmmlz can be sent to a chat
completion API as a sequence of {role, content} messages rather than
a single prompt.
Turn delimiters
A role delimiter splits the narrative and opens a new turn. Two spellings are recognized, both case-insensitive:
- A Markdown heading whose text names a role, e.g.
## Turn 1 -- user,# assistant,### system. The role is the first whole-word role token in the heading's text. - An HTML comment containing only a role, e.g.
<!-- user -->,<!-- assistant -->.
The supported roles are :user, :assistant, :system, and :tool
(see roles/0). The delimiter line itself is a structural marker and is
not included in the turn it opens.
Preamble and consecutive roles
Narrative text before the first delimiter is a preamble and becomes a
:context turn (so nothing the author wrote is ever dropped). Consecutive
delimiters with the same role still open separate turns -- ## Turn 1 -- user followed by ## Turn 2 -- user yields two distinct :user messages,
since consecutive user messages are legitimately distinct in a transcript.
Which embeds belong to which turn
Each embed's marker is located by byte offset in the full narrative, and
the embed is assigned to the turn whose text region contains that offset.
Inline @@@name ... @@@ fences and in-prose @name references are both
handled; an embed opened inside one turn belongs to that turn even if its
fence were to span a boundary. Because a resolved narrative lists each
distinct embed name once (first occurrence), only first occurrences are
located.
Rendering
render_turns/2 maps each turn through Lmml.Narrative.Renderer (by
building a per-turn Lmml.Narrative.Resolver), yielding
[%{role: role, content: [content_part, ...]}] ready to hand to an API's
messages field.
Summary
Functions
The roles that map onto real message roles (:context is excluded).
Segments resolved and renders each turn through Lmml.Narrative.Renderer,
returning [%{role: role, content: [content_part, ...]}] -- the shape a
chat completion API's messages field expects.
Every role Segment recognizes, including the synthetic :context preamble role.
Splits a resolved narrative into an ordered list of t() turns.
Types
@type role() :: :context | :user | :assistant | :system | :tool
@type t() :: %Lmml.Narrative.Segment{ embeds: [Lmml.Narrative.Resolver.resolved_embed()], narrative: binary(), role: role() }
Functions
@spec message_roles() :: [role()]
The roles that map onto real message roles (:context is excluded).
@spec render_turns( Lmml.Narrative.Resolver.t(), keyword() ) :: [%{role: role(), content: [map()]}]
Segments resolved and renders each turn through Lmml.Narrative.Renderer,
returning [%{role: role, content: [content_part, ...]}] -- the shape a
chat completion API's messages field expects.
opts are forwarded to Lmml.Narrative.Renderer.render/2 (see its
:max_embed_bytes), so a per-message payload budget applies uniformly.
@spec roles() :: [role()]
Every role Segment recognizes, including the synthetic :context preamble role.
@spec segment( Lmml.Narrative.Resolver.t(), keyword() ) :: [t()]
Splits a resolved narrative into an ordered list of t() turns.
Segmentation of an already-resolved narrative is pure text processing
and cannot fail, so this returns the turn list directly (like
Lmml.Narrative.Renderer.render/1), not a tagged tuple.
See the moduledoc for the delimiter convention, preamble handling, and
embed-to-turn assignment. opts currently accepts no options (reserved
for future use) but is part of the public signature for forward
compatibility.