Class: Phronomy::Context::Assembler

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/context/assembler.rb

Overview

Assembler collects all four context regions and produces the final messages: hash consumed by Agent::Base.

Regions:

  1. Instruction — system prompt text set via #add_instruction
  2. Capability — tool definitions (handled by RubyLLM, not here)
  3. Knowledge — external facts injected via #add_knowledge (generates XML tags)
  4. Conversation — historical messages added via #add_messages

Token budgeting: When a budget is given, conversation messages are trimmed from oldest to newest until they fit. Knowledge chunks are always included in full (they are assumed to be pre-screened by the caller). When no budget is given all messages are passed through unchanged.

Examples:

assembler = Phronomy::Context::Assembler.new(budget: budget)
assembler.add_instruction("You are a helpful assistant.")
assembler.add_knowledge("The user lives in Tokyo.", type: :entity, trusted: false)
assembler.add_messages(manager.load(thread_id: "t1", query: user_input))
context = assembler.build
# => { system: "You are ...\n<context ...>...</context>", messages: [...] }

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(budget: nil) ⇒ Assembler

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Assembler.

Parameters:



46
47
48
49
50
51
# File 'lib/phronomy/context/assembler.rb', line 46

def initialize(budget: nil)
  @budget = budget
  @instruction = nil
  @knowledge_chunks = []
  @messages = []
end

Class Method Details

.xml_tag(text, type:, trusted: false) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Builds a single XML context tag string. Exposed as a class method so callers (e.g. Agent::Base) can build static knowledge XML tags independently of an Assembler instance.

Parameters:

  • text (String)
  • type (Symbol, String)
  • trusted (Boolean) (defaults to: false)

Returns:

  • (String)


39
40
41
# File 'lib/phronomy/context/assembler.rb', line 39

def self.xml_tag(text, type:, trusted: false)
  "<context type=\"#{CGI.escapeHTML(type.to_s)}\" trusted=\"#{trusted}\">\n#{CGI.escapeHTML(text.to_s)}\n</context>"
end

Instance Method Details

#add_instruction(text) ⇒ self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set the system instruction text (Region 1). Calling this multiple times replaces the previous value.

Parameters:

  • text (String)

Returns:

  • (self)


59
60
61
62
# File 'lib/phronomy/context/assembler.rb', line 59

def add_instruction(text)
  @instruction = text.to_s
  self
end

#add_knowledge(text, type:, trusted: false, source: nil) ⇒ self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Append a knowledge chunk (Region 3). The chunk is wrapped in an XML context tag automatically.

Parameters:

  • text (String)
  • type (Symbol, String)

    semantic label for the context tag (e.g. :entity, :rag, :static)

  • trusted (Boolean) (defaults to: false)

    false (default) indicates externally sourced data

  • source (String, nil) (defaults to: nil)

    optional source label (e.g. filename); included in the XML tag so the LLM can produce grounded citations. Omitted when nil.

Returns:

  • (self)


74
75
76
77
# File 'lib/phronomy/context/assembler.rb', line 74

def add_knowledge(text, type:, trusted: false, source: nil)
  @knowledge_chunks << {text: text.to_s, type: type.to_s, trusted: trusted, source: source}
  self
end

#add_messages(messages) ⇒ self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set conversation messages (Region 4). Replaces any previously set messages.

Parameters:

  • messages (Array)

    message-like objects with #role and #content

Returns:

  • (self)


84
85
86
87
# File 'lib/phronomy/context/assembler.rb', line 84

def add_messages(messages)
  @messages = Array(messages)
  self
end

#buildHash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Assemble the context.

Returns:

  • (Hash{Symbol => Object})

    :system [String, nil] combined system prompt (instruction + knowledge XML tags) :messages [Array] conversation messages, trimmed to budget if set



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/phronomy/context/assembler.rb', line 95

def build
  knowledge_text = @knowledge_chunks.map { |c| xml_context_tag(c) }.join("\n\n")
  system_parts = [@instruction, knowledge_text.empty? ? nil : knowledge_text].compact
  system_text = system_parts.join("\n\n")

  messages = if @budget
    trim_messages_to_budget(@messages, system_text)
  else
    @messages
  end

  {
    system: system_text.empty? ? nil : system_text,
    messages: messages
  }
end