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.



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

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



931
932
933
934
935
# File 'lib/kward/compactor.rb', line 931

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



906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
# File 'lib/kward/compactor.rb', line 906

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



924
925
926
927
928
929
# File 'lib/kward/compactor.rb', line 924

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



880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
# File 'lib/kward/compactor.rb', line 880

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)


873
874
875
876
877
878
# File 'lib/kward/compactor.rb', line 873

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

#compaction_messages(custom_instructions = nil) ⇒ Object



937
938
939
# File 'lib/kward/compactor.rb', line 937

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