Class: RubyLLM::Contract::Step::Base
Constant Summary
collapse
- KNOWN_CONTEXT_KEYS =
%i[adapter model temperature max_tokens provider assume_model_exists].freeze
Class Method Summary
collapse
Methods included from Dsl
around_call, class_validates, contract, input_type, max_cost, max_input, max_output, model, output_schema, output_type, prompt, retry_policy, temperature, validate
clear_file_sourced_evals!, compare_models, define_eval, eval_defined?, eval_names, run_eval
Class Method Details
.build_messages(input) ⇒ Object
86
87
88
89
90
91
92
93
|
# File 'lib/ruby_llm/contract/step/base.rb', line 86
def build_messages(input)
dynamic = prompt.arity >= 1
builder_input = dynamic ? input : Prompt::Builder::NOT_PROVIDED
ast = Prompt::Builder.build(input: builder_input, &prompt)
variables = dynamic ? {} : { input: input }
variables.merge!(input.transform_keys(&:to_sym)) if !dynamic && input.is_a?(Hash)
Prompt::Renderer.render(ast, variables: variables)
end
|
.estimate_cost(input:, model: nil) ⇒ Object
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/ruby_llm/contract/step/base.rb', line 26
def estimate_cost(input:, model: nil)
model_name = model || RubyLLM::Contract.configuration.default_model
messages = build_messages(input)
input_tokens = TokenEstimator.estimate(messages)
output_tokens = max_output || 256
model_info = CostCalculator.send(:find_model, model_name)
return nil unless model_info
estimated = CostCalculator.send(:compute_cost, model_info,
{ input_tokens: input_tokens, output_tokens: output_tokens })
{
model: model_name,
input_tokens: input_tokens,
output_tokens_estimate: output_tokens,
estimated_cost: estimated
}
end
|
.estimate_eval_cost(eval_name, models: nil) ⇒ Object
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/ruby_llm/contract/step/base.rb', line 45
def estimate_eval_cost(eval_name, models: nil)
defn = send(:all_eval_definitions)[eval_name.to_s]
raise ArgumentError, "No eval '#{eval_name}' defined" unless defn
model_list = models || [RubyLLM::Contract.configuration.default_model].compact
cases = defn.build_dataset.cases
model_list.each_with_object({}) do |model_name, result|
per_case = cases.sum do |c|
est = estimate_cost(input: c.input, model: model_name)
est ? est[:estimated_cost] : 0.0
end
result[model_name] = per_case.round(6)
end
end
|
.eval_case(input:, expected: nil, expected_traits: nil, evaluator: nil, context: {}) ⇒ Object
17
18
19
20
21
22
23
24
|
# File 'lib/ruby_llm/contract/step/base.rb', line 17
def eval_case(input:, expected: nil, expected_traits: nil, evaluator: nil, context: {})
dataset = Eval::Dataset.define("single_case") do
add_case("inline", input: input, expected: expected,
expected_traits: expected_traits, evaluator: evaluator)
end
report = Eval::Runner.run(step: self, dataset: dataset, context: context)
report.results.first
end
|
.inherited(subclass) ⇒ Object
7
8
9
10
|
# File 'lib/ruby_llm/contract/step/base.rb', line 7
def self.inherited(subclass)
super
Contract.register_eval_host(subclass) if respond_to?(:eval_defined?) && eval_defined?
end
|
.run(input, context: {}) ⇒ Object
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
# File 'lib/ruby_llm/contract/step/base.rb', line 65
def run(input, context: {})
context = safe_context(context)
warn_unknown_context_keys(context)
adapter = resolve_adapter(context)
default_model = context[:model] || model || RubyLLM::Contract.configuration.default_model
policy = retry_policy
ctx_temp = context[:temperature]
= context.slice(:provider, :assume_model_exists, :max_tokens)
result = if policy
run_with_retry(input, adapter: adapter, default_model: default_model,
policy: policy, context_temperature: ctx_temp, extra_options: )
else
run_once(input, adapter: adapter, model: default_model,
context_temperature: ctx_temp, extra_options: )
end
log_result(result)
invoke_around_call(input, result)
end
|