boxcars 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,147 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Boxcars
4
- # @abstract
5
- class Conductor
6
- attr_reader :engine, :boxcars, :name, :description, :prompt, :engine_boxcar, :return_values
7
-
8
- # A Conductor will use a engine to run a series of boxcars.
9
- # @param engine [Boxcars::Engine] The engine to use for this conductor.
10
- # @param boxcars [Array<Boxcars::Boxcar>] The boxcars to run.
11
- # @abstract
12
- def initialize(engine:, boxcars:, prompt:, name: nil, description: nil)
13
- @engine = engine
14
- @boxcars = boxcars
15
- @prompt = prompt
16
- @name = name || self.class.name
17
- @description = description
18
- @return_values = [:output]
19
- @engine_boxcar = EngineBoxcar.new(prompt: prompt, engine: engine)
20
- end
21
-
22
- # Get an answer from the conductor.
23
- # @param question [String] The question to ask the conductor.
24
- # @return [String] The answer to the question.
25
- def run(question)
26
- raise NotImplementedError
27
- end
28
-
29
- # Extract the boxcar name and input from the text.
30
- def extract_boxcar_and_input(text)
31
- end
32
-
33
- def stop
34
- ["\n#{observation_prefix}"]
35
- end
36
-
37
- def construct_scratchpad(intermediate_steps)
38
- thoughts = ""
39
- intermediate_steps.each do |action, observation|
40
- thoughts += action.is_a?(String) ? action : action.log
41
- thoughts += "\n#{observation_prefix}#{observation}\n#{engine_prefix}"
42
- end
43
- thoughts
44
- end
45
-
46
- def get_next_action(full_inputs)
47
- full_output = engine_boxcar.predict(**full_inputs)
48
- parsed_output = extract_boxcar_and_input(full_output)
49
- while parsed_output.nil?
50
- full_output = _fix_text(full_output)
51
- full_inputs[:agent_scratchpad] += full_output
52
- output = engine_boxcar.predict(**full_inputs)
53
- full_output += output
54
- parsed_output = extract_boxcar_and_input(full_output)
55
- end
56
- ConductorAction.new(boxcar: parsed_output[0], boxcar_input: parsed_output[1], log: full_output)
57
- end
58
-
59
- # Given input, decided what to do.
60
- # @param intermediate_steps [Array<Hash>] The intermediate steps taken so far along with observations.
61
- # @param kwargs [Hash] User inputs.
62
- # @return [Boxcars::Action] Action specifying what boxcar to use.
63
- def plan(intermediate_steps, **kwargs)
64
- thoughts = construct_scratchpad(intermediate_steps)
65
- new_inputs = { agent_scratchpad: thoughts, stop: stop }
66
- full_inputs = kwargs.merge(new_inputs)
67
- action = get_next_action(full_inputs)
68
- return ConductorFinish.new({ output: action.boxcar_input }, log: action.log) if action.boxcar == finish_boxcar_name
69
-
70
- action
71
- end
72
-
73
- # Prepare the agent for new call, if needed
74
- def prepare_for_new_call
75
- end
76
-
77
- # Name of the boxcar to use to finish the chain
78
- def finish_boxcar_name
79
- "Final Answer"
80
- end
81
-
82
- def input_keys
83
- # Return the input keys
84
- list = prompt.input_variables
85
- list.delete(:agent_scratchpad)
86
- list
87
- end
88
-
89
- # Check that all inputs are present.
90
- def validate_inputs(inputs:)
91
- missing_keys = input_keys - inputs.keys
92
- raise "Missing some input keys: #{missing_keys}" if missing_keys.any?
93
- end
94
-
95
- def validate_prompt(values: Dict)
96
- prompt = values["engine_chain"].prompt
97
- unless prompt.input_variables.include?(:agent_scratchpad)
98
- logger.warning("`agent_scratchpad` should be a variable in prompt.input_variables. Not found, adding it at the end.")
99
- prompt.input_variables.append(:agent_scratchpad)
100
- case prompt
101
- when PromptTemplate
102
- prompt.template += "\n%<agent_scratchpad>s"
103
- when FewShotPromptTemplate
104
- prompt.suffix += "\n%<agent_scratchpad>s"
105
- else
106
- raise ValueError, "Got unexpected prompt type #{type(prompt)}"
107
- end
108
- end
109
- values
110
- end
111
-
112
- def return_stopped_response(early_stopping_method, intermediate_steps, **kwargs)
113
- case early_stopping_method
114
- when "force"
115
- ConductorFinish({ output: "Agent stopped due to max iterations." }, "")
116
- when "generate"
117
- thoughts = ""
118
- intermediate_steps.each do |action, observation|
119
- thoughts += action.log
120
- thoughts += "\n#{observation_prefix}#{observation}\n#{engine_prefix}"
121
- end
122
- thoughts += "\n\nI now need to return a final answer based on the previous steps:"
123
- new_inputs = { agent_scratchpad: thoughts, stop: _stop }
124
- full_inputs = kwargs.merge(new_inputs)
125
- full_output = engine_boxcar.predict(**full_inputs)
126
- parsed_output = extract_boxcar_and_input(full_output)
127
- if parsed_output.nil?
128
- ConductorFinish({ output: full_output }, full_output)
129
- else
130
- boxcar, boxcar_input = parsed_output
131
- if boxcar == finish_boxcar_name
132
- ConductorFinish({ output: boxcar_input }, full_output)
133
- else
134
- ConductorFinish({ output: full_output }, full_output)
135
- end
136
- end
137
- else
138
- raise "early_stopping_method should be one of `force` or `generate`, got #{early_stopping_method}"
139
- end
140
- end
141
- end
142
- end
143
-
144
- require "boxcars/conductor/conductor_action"
145
- require "boxcars/conductor/conductor_finish"
146
- require "boxcars/conductor/conductor_executer"
147
- require "boxcars/conductor/zero_shot"