Skip to content
Kward Search API index

Class: Kward::Compactor

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

Overview

Compaction support object used by conversation summarization.

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

Creates an object for conversation compaction.



737
738
739
740
741
742
743
744
745
# File 'lib/kward/compactor.rb', line 737

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



805
806
807
808
809
# File 'lib/kward/compactor.rb', line 805

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



780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
# File 'lib/kward/compactor.rb', line 780

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.context_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



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

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



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/kward/compactor.rb', line 754

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)


747
748
749
750
751
752
# File 'lib/kward/compactor.rb', line 747

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

#compaction_messages(custom_instructions = nil) ⇒ Object



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

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