Class: Insika::Distill::Distiller

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/distill.rb

Overview

The model's answer, filtered into data the command then dedups and a human then gates. Pure over an injected ask — the Refinement::Proposer shape: unit-testable without a provider, and the real ask is a lambda built by DistillerFactory (ruby_llm required lazily, load_guard stays green).

Defined Under Namespace

Classes: Unusable

Constant Summary collapse

MAX_NAME_LENGTH =
120
MAX_VALUE_LENGTH =
500
MAX_TURNS =
20
ALLOWED_KEYS =
%w[name value confidence turns].freeze
DROP_KEYS =

The E4 audit counters: schema (shape/type/confidence range), unknown_key (a model-authored key — the D1 escape), oversized (length caps), bad_turns (evidence indexes), duplicate (exact repeats), capped (a survivor over max_proposals).

%w[schema unknown_key oversized bad_turns duplicate capped].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ask:, model: "utility_model") ⇒ Distiller

Returns a new instance of Distiller.



80
81
82
83
# File 'lib/insika/distill.rb', line 80

def initialize(ask:, model: "utility_model")
  @ask = ask
  @model = model.to_s
end

Instance Attribute Details

#modelObject (readonly)

ask: ->(prompt) { "" } | something answering #content (+ #input_tokens/#output_tokens/#cached_tokens for cost). model: the ref recorded in the events ("utility_model" default).



78
79
80
# File 'lib/insika/distill.rb', line 78

def model
  @model
end

Instance Method Details

#distill(prompt:, message_count:, max_proposals: 10) ⇒ Object

-> { proposals: [{ "name", "value", "confidence"?, "turns"? }], dropped: { "schema" => N, "unknown_key" => N, "oversized" => N, "bad_turns" => N, "duplicate" => N }, cost: { "spent" => N, "cached" => N } | nil } prompt: the pack prompt or DEFAULT_PROMPT (the caller resolved it). message_count: the session transcript size — turns are validated against it (an index >= message_count drops the proposal). max_proposals: cap on surviving proposals (the model may return more). Drops are counted, never fixed up.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/insika/distill.rb', line 94

def distill(prompt:, message_count:, max_proposals: 10)
  answer = @ask.call(prompt)
  raw = parse(text_of(answer))
  proposals = []
  dropped = DROP_KEYS.to_h { |k| [k, 0] }
  seen = {}
  raw.each do |item|
    verdict, reason = classify(item, message_count)
    case verdict
    when :keep
      tuple = [item["name"].to_s, item["value"].to_s]
      if seen[tuple]
        dropped["duplicate"] += 1
      elsif proposals.size >= max_proposals
        dropped["capped"] += 1
      else
        seen[tuple] = true
        proposals << normalize(item)
      end
    when :drop
      dropped[reason] += 1
    end
  end
  { proposals: proposals, dropped: dropped, cost: cost_of(answer) }
end