Class: Kward::Compactor

Inherits:
Object
  • Object
show all
Defined in:
lib/kward/compactor.rb

Defined Under Namespace

Classes: Result

Constant Summary collapse

NothingToCompact =
Compaction::NothingToCompact
AlreadyCompacted =
Compaction::AlreadyCompacted
EmptySummary =
Compaction::SummarizationFailed
SummarizationFailed =
Compaction::SummarizationFailed
AUTO_COMPACTION_GUARD_RATIO =
0.10
AUTO_COMPACTION_EXTRA_GUARD_CAP =
12_000

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conversation:, client:, tool_result_summarizer: nil, settings: nil, summarizer: nil) ⇒ Compactor

Returns a new instance of Compactor.



798
799
800
801
802
803
804
805
806
# File 'lib/kward/compactor.rb', line 798

def initialize(conversation:, client:, tool_result_summarizer: nil, settings: nil, summarizer: nil)
  @conversation = conversation
  @client = client
  @settings = settings || Compaction::Settings.from_config
  @prompt_builder = Compaction::PromptBuilder.new(
    serializer: Compaction::ConversationSerializer.new(tool_result_summarizer: tool_result_summarizer)
  )
  @summarizer = summarizer || Compaction::Summarizer.new(client: client, prompt_builder: @prompt_builder)
end

Class Method Details

.auto_compaction_reserve_tokens(context_window:, configured_reserve_tokens:) ⇒ Object



866
867
868
869
870
# File 'lib/kward/compactor.rb', line 866

def self.auto_compaction_reserve_tokens(context_window:, configured_reserve_tokens:)
  context_window_i = context_window.to_i
  dynamic_guard = (context_window_i * AUTO_COMPACTION_GUARD_RATIO).to_i
  [configured_reserve_tokens.to_i, dynamic_guard, AUTO_COMPACTION_EXTRA_GUARD_CAP].max
end

Instance Method Details

#auto_compact_if_needed(context_tokens: nil, context_window: nil, custom_instructions: nil) ⇒ Object



841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
# File 'lib/kward/compactor.rb', line 841

def auto_compact_if_needed(context_tokens: nil, context_window: nil, custom_instructions: nil)
  return nil unless @settings.enabled

  context_window ||= @settings.context_window
  return nil unless context_window

  context_tokens ||= Compaction::TokenEstimator.new.context_tokens(@conversation.messages)
  reserve_tokens = auto_compaction_reserve_tokens(context_window: context_window.to_i)
  return nil unless context_tokens.to_i > context_window.to_i - reserve_tokens

  compact(custom_instructions: custom_instructions)
rescue Compaction::NothingToCompact, Compaction::AlreadyCompacted
  nil
rescue StandardError => e
  warn "Auto-compaction failed: #{e.message}"
  nil
end

#auto_compaction_reserve_tokens(context_window:) ⇒ Object



859
860
861
862
863
864
# File 'lib/kward/compactor.rb', line 859

def auto_compaction_reserve_tokens(context_window:)
  self.class.auto_compaction_reserve_tokens(
    context_window: context_window,
    configured_reserve_tokens: @settings.reserve_tokens
  )
end

#compact(custom_instructions: nil, compaction_summary: true) ⇒ Object



815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
# File 'lib/kward/compactor.rb', line 815

def compact(custom_instructions: nil, compaction_summary: true)
  old_count = @conversation.messages.length
  preparation = prepare
  summary = @summarizer.summarize(preparation, custom_instructions: custom_instructions)
  summary = append_files_section(summary, preparation.file_ops)
  raise Compaction::SummarizationFailed, "Compaction produced an empty summary; context was not changed." if summary.strip.empty?

  @conversation.compact!(
    summary,
    compaction_summary: compaction_summary,
    first_kept_entry_id: preparation.first_kept_entry_id,
    tokens_before: preparation.tokens_before,
    from_hook: false,
    details: preparation.file_ops,
    keep_messages: preparation.kept_messages
  )
  Result.new(
    summary: summary,
    old_message_count: old_count,
    new_message_count: @conversation.messages.length,
    first_kept_entry_id: preparation.first_kept_entry_id,
    tokens_before: preparation.tokens_before,
    details: preparation.file_ops
  )
end

#compactable?Boolean

Returns:

  • (Boolean)


808
809
810
811
812
813
# File 'lib/kward/compactor.rb', line 808

def compactable?
  prepare
  true
rescue Compaction::NothingToCompact, Compaction::AlreadyCompacted
  false
end

#compaction_messages(custom_instructions = nil) ⇒ Object



872
873
874
# File 'lib/kward/compactor.rb', line 872

def compaction_messages(custom_instructions = nil)
  @prompt_builder.build(prepare, custom_instructions: custom_instructions)
end