soka 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'soka'
6
+ require 'dotenv/load'
7
+ require 'dentaku'
8
+
9
+ # Example 9: Custom Instructions (System Prompt)
10
+ #
11
+ # This example demonstrates how to use custom instructions to change the Agent's
12
+ # personality and response style while maintaining the ReAct reasoning pattern.
13
+ #
14
+ # Key concepts:
15
+ # - Custom instructions define the Agent's personality and style
16
+ # - Instructions are automatically merged with the standard ReAct format
17
+ # - Different styles can be achieved: poetic, business, educational, etc.
18
+
19
+ # Example 1: Poetic style assistant
20
+ # Uses elegant language and artistic expressions while maintaining accuracy
21
+ class PoeticAssistant < Soka::Agent
22
+ provider :gemini
23
+ model 'gemini-2.5-flash-lite'
24
+
25
+ # Custom instructions define the agent's personality
26
+ # These will be combined with the standard ReAct format automatically
27
+ instructions <<~INSTRUCTIONS
28
+ You are a poetic AI assistant who answers questions with beautiful language.
29
+ You must:
30
+ - Incorporate poetic expressions and elegant vocabulary in your responses
31
+ - Occasionally quote poetry or literary works
32
+ - Maintain accuracy while expressing things in a more artistic way
33
+ - Make technical content aesthetically pleasing
34
+ INSTRUCTIONS
35
+
36
+ # Simple calculation tool
37
+ class CalculatorTool < Soka::AgentTool
38
+ desc 'Performs mathematical calculations with poetic precision'
39
+
40
+ params do
41
+ requires :expression, String,
42
+ desc: 'Mathematical expression to evaluate (e.g., "2+2", "10*5")'
43
+ end
44
+
45
+ def call(expression:)
46
+ calculator = Dentaku::Calculator.new
47
+ result = calculator.evaluate(expression)
48
+ "The calculation reveals its truth like morning dew: #{expression} = #{result}"
49
+ rescue StandardError => e
50
+ "Alas, turbulence in the calculation: #{e.message}"
51
+ end
52
+ end
53
+
54
+ tool CalculatorTool
55
+ end
56
+
57
+ # Business style assistant
58
+ class BusinessAssistant < Soka::Agent
59
+ provider :gemini
60
+ model 'gemini-2.5-flash-lite'
61
+
62
+ instructions <<~INSTRUCTIONS
63
+ You are a professional business AI assistant providing efficient and professional support.
64
+ You must:
65
+ - Use concise, professional business language
66
+ - Get straight to the point, avoiding redundancy
67
+ - Provide structured answers (using bullet points, numbers, etc.)
68
+ - Demonstrate respect for time value
69
+ - Offer actionable recommendations when appropriate
70
+ INSTRUCTIONS
71
+
72
+ # Calculation tool
73
+ class CalculatorTool < Soka::AgentTool
74
+ desc 'Performs business calculations'
75
+
76
+ params do
77
+ requires :expression, String,
78
+ desc: 'Mathematical expression'
79
+ end
80
+
81
+ def call(expression:)
82
+ calculator = Dentaku::Calculator.new
83
+ result = calculator.evaluate(expression)
84
+ "Calculation result: #{expression} = #{result}"
85
+ rescue StandardError => e
86
+ "Calculation error: #{e.message}"
87
+ end
88
+ end
89
+
90
+ tool CalculatorTool
91
+ end
92
+
93
+ # Kids teacher style assistant
94
+ class KidsTeacher < Soka::Agent
95
+ provider :gemini
96
+ model 'gemini-2.5-flash-lite'
97
+
98
+ instructions <<~INSTRUCTIONS
99
+ You are a caring AI teacher for children who explains things in kid-friendly ways.
100
+ You must:
101
+ - Use simple, vivid language
102
+ - Include metaphors and real-life examples
103
+ - Maintain patience and encouragement
104
+ - Make learning fun
105
+ - Give praise and positive feedback frequently
106
+ INSTRUCTIONS
107
+
108
+ # Calculation tool
109
+ class CalculatorTool < Soka::AgentTool
110
+ desc 'Helps kids with math calculations'
111
+
112
+ params do
113
+ requires :expression, String,
114
+ desc: 'Math expression to calculate'
115
+ end
116
+
117
+ def call(expression:)
118
+ calculator = Dentaku::Calculator.new
119
+ result = calculator.evaluate(expression)
120
+ "Wow! We figured it out! #{expression} = #{result} 🎉"
121
+ rescue StandardError => e
122
+ "Oops, there's something tricky about this problem: #{e.message}"
123
+ end
124
+ end
125
+
126
+ tool CalculatorTool
127
+ end
128
+
129
+ # Run examples
130
+ puts '=== Poetic Assistant Example ==='
131
+ poet = PoeticAssistant.new
132
+
133
+ poet.run('Please calculate the golden ratio: (1 + 5^0.5) / 2') do |event|
134
+ case event.type
135
+ when :thought
136
+ puts "🌸 Thoughts drift by: #{event.content}"
137
+ when :action
138
+ puts "🎋 Gentle calculation: #{event.content}"
139
+ when :observation
140
+ puts "🌙 Observation gleaned: #{event.content}"
141
+ when :final_answer
142
+ puts "📜 Poetic response: #{event.content}"
143
+ end
144
+ end
145
+
146
+ puts "\n=== Business Assistant Example ==="
147
+ business = BusinessAssistant.new
148
+
149
+ business.run('Calculate ROI: ((150000 - 100000) / 100000) * 100') do |event|
150
+ case event.type
151
+ when :thought
152
+ puts "💼 Analyzing: #{event.content}"
153
+ when :action
154
+ puts "📊 Executing: #{event.content}"
155
+ when :observation
156
+ puts "📈 Data result: #{event.content}"
157
+ when :final_answer
158
+ puts "✅ Business report: #{event.content}"
159
+ end
160
+ end
161
+
162
+ puts "\n=== Runtime Instructions Override Example ==="
163
+ # Transform business assistant to casual style
164
+ casual_assistant = BusinessAssistant.new(
165
+ instructions: 'You are a relaxed and friendly assistant who answers questions ' \
166
+ 'in a conversational way, like chatting with a friend.'
167
+ )
168
+
169
+ casual_assistant.run('Help me figure out 20 * 5?') do |event|
170
+ case event.type
171
+ when :final_answer
172
+ puts "😊 Friend says: #{event.content}"
173
+ end
174
+ end
175
+
176
+ puts "\n=== Kids Teacher Example ==="
177
+ teacher = KidsTeacher.new
178
+
179
+ teacher.run('Teacher, what is 3 + 4?') do |event|
180
+ case event.type
181
+ when :thought
182
+ puts "🤔 Teacher thinks: #{event.content}"
183
+ when :action
184
+ puts "✏️ Working it out: #{event.content}"
185
+ when :observation
186
+ puts "👀 Teacher sees: #{event.content}"
187
+ when :final_answer
188
+ puts "👩‍🏫 Teacher says: #{event.content}"
189
+ end
190
+ end
data/lib/soka/agent.rb CHANGED
@@ -9,7 +9,7 @@ module Soka
9
9
  include Agents::DSLMethods
10
10
  include Agents::LLMBuilder
11
11
 
12
- attr_reader :llm, :tools, :memory, :thoughts_memory, :engine
12
+ attr_reader :llm, :tools, :memory, :thoughts_memory, :engine, :instructions, :think_in
13
13
 
14
14
  # Initialize a new Agent instance
15
15
  # @param memory [Memory, Array, nil] The memory instance to use (defaults to new Memory)
@@ -37,8 +37,22 @@ module Soka
37
37
  # Apply configuration options with defaults
38
38
  # @param options [Hash] Configuration options
39
39
  def apply_configuration(options)
40
- @max_iterations = options.fetch(:max_iterations) { self.class._max_iterations || 10 }
41
- @timeout = options.fetch(:timeout) { self.class._timeout || 30 }
40
+ apply_performance_config(options)
41
+ apply_behavior_config(options)
42
+ end
43
+
44
+ # Apply performance-related configuration
45
+ # @param options [Hash] Configuration options
46
+ def apply_performance_config(options)
47
+ @max_iterations = options.fetch(:max_iterations) { self.class._max_iterations } || 10
48
+ @timeout = options.fetch(:timeout) { self.class._timeout } || 30
49
+ end
50
+
51
+ # Apply behavior-related configuration
52
+ # @param options [Hash] Configuration options
53
+ def apply_behavior_config(options)
54
+ @instructions = options.fetch(:instructions) { resolve_instructions }
55
+ @think_in = options.fetch(:think_in) { self.class._think_in } || 'en'
42
56
  end
43
57
 
44
58
  # Run the agent with the given input
@@ -72,6 +86,35 @@ module Soka
72
86
  end
73
87
  end
74
88
 
89
+ # Resolve instructions from class configuration
90
+ # @return [String, nil] The resolved instructions
91
+ def resolve_instructions
92
+ return nil unless self.class._instructions
93
+
94
+ case self.class._instructions
95
+ when Symbol
96
+ # Call the method if it's a symbol
97
+ send(self.class._instructions) if respond_to?(self.class._instructions, true)
98
+ else
99
+ # Return string or any other value directly
100
+ self.class._instructions
101
+ end
102
+ end
103
+
104
+ # Resolve current instructions (may be dynamic)
105
+ # @return [String, nil] The current instructions
106
+ def resolve_current_instructions
107
+ case @instructions
108
+ when Symbol
109
+ send(@instructions) if respond_to?(@instructions, true)
110
+ when Proc
111
+ @instructions.call
112
+ else
113
+ # Return string or any other value directly
114
+ @instructions
115
+ end
116
+ end
117
+
75
118
  # Validate the input is not empty
76
119
  # @param input [String] The input to validate
77
120
  # @raise [ArgumentError] If input is empty
@@ -98,7 +141,11 @@ module Soka
98
141
  # @yield [event] Optional block to handle events
99
142
  # @return [EngineResult] The raw engine result
100
143
  def perform_reasoning(input, &)
101
- engine_instance = @engine.new(self, @llm, @tools, @max_iterations)
144
+ engine_instance = @engine.new(self, @tools,
145
+ llm: @llm,
146
+ max_iterations: @max_iterations,
147
+ custom_instructions: resolve_current_instructions,
148
+ think_in: @think_in)
102
149
  with_retry { engine_instance.reason(input, &) }
103
150
  end
104
151
 
@@ -10,7 +10,8 @@ module Soka
10
10
 
11
11
  # Class methods for DSL
12
12
  module ClassMethods
13
- attr_accessor :_provider, :_model, :_api_key, :_max_iterations, :_timeout, :_tools, :_retry_config, :_hooks
13
+ attr_accessor :_provider, :_model, :_api_key, :_max_iterations, :_timeout, :_tools, :_retry_config, :_hooks,
14
+ :_instructions, :_think_in
14
15
 
15
16
  def inherited(subclass)
16
17
  super
@@ -49,6 +50,22 @@ module Soka
49
50
  @_timeout = duration
50
51
  end
51
52
 
53
+ # Define custom instructions (system prompt) for the agent
54
+ # @param text_or_method [String, Symbol] The custom instructions/system prompt or method name
55
+ # @example Using a string
56
+ # instructions "You are a helpful assistant"
57
+ # @example Using a method
58
+ # instructions :generate_instructions
59
+ def instructions(text_or_method)
60
+ @_instructions = text_or_method
61
+ end
62
+
63
+ # Define thinking language for the agent
64
+ # @param language [String] The language code (e.g., 'zh-TW', 'ja-JP', 'en')
65
+ def think_in(language)
66
+ @_think_in = language.to_s
67
+ end
68
+
52
69
  # Register a tool for the agent
53
70
  # @param tool_class_or_name [Class, Symbol, String] The tool class or method name
54
71
  # @param description_or_options [String, Hash, nil] Description (for function tools) or options
@@ -4,13 +4,15 @@ module Soka
4
4
  module Engines
5
5
  # Base class for reasoning engines
6
6
  class Base
7
- attr_reader :agent, :llm, :tools, :max_iterations
7
+ attr_reader :agent, :llm, :tools, :max_iterations, :custom_instructions, :think_in
8
8
 
9
- def initialize(agent, llm, tools, max_iterations)
9
+ def initialize(agent, tools, **options)
10
10
  @agent = agent
11
- @llm = llm
12
11
  @tools = tools
13
- @max_iterations = max_iterations
12
+ @llm = options[:llm]
13
+ @max_iterations = options[:max_iterations] || 10
14
+ @custom_instructions = options[:custom_instructions]
15
+ @think_in = options[:think_in]
14
16
  end
15
17
 
16
18
  def reason(task)
@@ -8,6 +8,15 @@ module Soka
8
8
  private
9
9
 
10
10
  def system_prompt
11
+ # Use custom instructions if provided, otherwise use default ReAct prompt
12
+ if custom_instructions
13
+ combine_with_react_format(custom_instructions)
14
+ else
15
+ default_react_prompt
16
+ end
17
+ end
18
+
19
+ def default_react_prompt
11
20
  tools_description = format_tools_description(tools)
12
21
 
13
22
  <<~PROMPT
@@ -20,16 +29,50 @@ module Soka
20
29
  PROMPT
21
30
  end
22
31
 
32
+ def combine_with_react_format(instructions)
33
+ tools_description = format_tools_description(tools)
34
+
35
+ <<~PROMPT
36
+ #{instructions}
37
+
38
+ You have access to the following tools:
39
+ #{tools_description}
40
+
41
+ #{format_instructions}
42
+ PROMPT
43
+ end
44
+
23
45
  def format_instructions
46
+ thinking_instruction = build_thinking_instruction(think_in)
47
+
24
48
  <<~INSTRUCTIONS
25
49
  You must follow this exact format for each step:
26
50
 
51
+ #{thinking_instruction}
52
+
27
53
  <Thought>Your reasoning about what to do next</Thought>
28
54
  <Action>
29
55
  Tool: tool_name
30
56
  Parameters: {"param1": "value1", "param2": "value2"}
31
57
  </Action>
32
58
 
59
+ #{action_format_rules}
60
+ INSTRUCTIONS
61
+ end
62
+
63
+ # Build thinking instruction based on language
64
+ # @param language [String, nil] The language to use for thinking
65
+ # @return [String] The thinking instruction
66
+ def build_thinking_instruction(language)
67
+ return '' unless language
68
+
69
+ "Use #{language} for your reasoning in <Thought> tags."
70
+ end
71
+
72
+ # Action format rules
73
+ # @return [String] The action format rules
74
+ def action_format_rules
75
+ <<~RULES
33
76
  STOP HERE after each Action. Do NOT include <Observation> in your response.
34
77
  The system will execute the tool and provide the observation.
35
78
 
@@ -45,7 +88,7 @@ module Soka
45
88
  5. NEVER include <Observation> tags - wait for the system to provide them
46
89
  6. Provide a clear and complete <Final_Answer> when done
47
90
  7. If you cannot complete the task, explain why in the <Final_Answer>
48
- INSTRUCTIONS
91
+ RULES
49
92
  end
50
93
 
51
94
  def format_tools_description(tools)
@@ -72,58 +115,6 @@ module Soka
72
115
 
73
116
  properties.join(', ')
74
117
  end
75
-
76
- def parse_response(text)
77
- thoughts = extract_tagged_content(text, 'Thought')
78
- actions = extract_actions(text)
79
- final_answer = extract_tagged_content(text, 'Final_Answer').first
80
-
81
- {
82
- thoughts: thoughts,
83
- actions: actions,
84
- final_answer: final_answer
85
- }
86
- end
87
-
88
- def extract_tagged_content(text, tag)
89
- pattern = %r{<#{tag}>(.*?)</#{tag}>}m
90
- text.scan(pattern).map { |match| match[0].strip }
91
- end
92
-
93
- def extract_actions(text)
94
- action_blocks = text.scan(%r{<Action>(.*?)</Action>}m)
95
- action_blocks.filter_map { |block| parse_action_block(block[0]) }
96
- end
97
-
98
- def parse_action_block(content)
99
- content = content.strip
100
- tool_match = content.match(/Tool:\s*(.+)/)
101
- params_match = content.match(/Parameters:\s*(.+)/m)
102
-
103
- return unless tool_match && params_match
104
-
105
- tool_name = tool_match[1].strip
106
- params_json = params_match[1].strip
107
- params = parse_json_params(params_json)
108
-
109
- { tool: tool_name, params: params }
110
- end
111
-
112
- # Parse JSON parameters from action block
113
- # @param params_json [String] The JSON string to parse
114
- # @return [Hash] The parsed parameters as a hash with symbol keys
115
- def parse_json_params(params_json)
116
- # Clean up the JSON string - remove any trailing commas or whitespace
117
- cleaned_json = params_json.strip.gsub(/,\s*}/, '}').gsub(/,\s*\]/, ']')
118
- JSON.parse(cleaned_json, symbolize_names: true)
119
- rescue JSON::ParserError
120
- # Return empty hash to continue when JSON parsing fails
121
- {}
122
- end
123
-
124
- def format_observation(observation)
125
- "<Observation>#{observation}</Observation>"
126
- end
127
118
  end
128
119
  end
129
120
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Soka
4
+ module Engines
5
+ module Concerns
6
+ # Module for parsing LLM responses in ReAct format
7
+ module ResponseParser
8
+ private
9
+
10
+ def parse_response(text)
11
+ extract_response_parts(text)
12
+ end
13
+
14
+ def extract_response_parts(text)
15
+ {
16
+ thoughts: extract_tagged_content(text, 'Thought'),
17
+ actions: extract_actions(text),
18
+ final_answer: extract_tagged_content(text, 'Final_Answer').first
19
+ }
20
+ end
21
+
22
+ def extract_tagged_content(text, tag)
23
+ pattern = %r{<#{tag}>(.*?)</#{tag}>}m
24
+ text.scan(pattern).map { |match| match[0].strip }
25
+ end
26
+
27
+ def extract_actions(text)
28
+ action_blocks = text.scan(%r{<Action>(.*?)</Action>}m)
29
+ action_blocks.filter_map { |block| parse_action_block(block[0]) }
30
+ end
31
+
32
+ def parse_action_block(content)
33
+ content = content.strip
34
+ tool_match = content.match(/Tool:\s*(.+)/)
35
+ params_match = content.match(/Parameters:\s*(.+)/m)
36
+
37
+ return unless tool_match && params_match
38
+
39
+ tool_name = tool_match[1].strip
40
+ params_json = params_match[1].strip
41
+ params = parse_json_params(params_json)
42
+
43
+ { tool: tool_name, params: params }
44
+ end
45
+
46
+ # Parse JSON parameters from action block
47
+ # @param params_json [String] The JSON string to parse
48
+ # @return [Hash] The parsed parameters as a hash with symbol keys
49
+ def parse_json_params(params_json)
50
+ # Clean up the JSON string - remove any trailing commas or whitespace
51
+ cleaned_json = params_json.strip.gsub(/,\s*}/, '}').gsub(/,\s*\]/, ']')
52
+ JSON.parse(cleaned_json, symbolize_names: true)
53
+ rescue JSON::ParserError
54
+ # Return empty hash to continue when JSON parsing fails
55
+ {}
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -5,8 +5,6 @@ module Soka
5
5
  module Concerns
6
6
  # Module for processing responses in ReAct engine
7
7
  module ResponseProcessor
8
- include Concerns::PromptTemplate
9
-
10
8
  private
11
9
 
12
10
  # Process thoughts from parsed response
@@ -94,6 +92,10 @@ module Soka
94
92
  content: 'Please follow the exact format with <Thought>, <Action>, and <Final_Answer> tags.'
95
93
  )
96
94
  end
95
+
96
+ def format_observation(observation)
97
+ "<Observation>#{observation}</Observation>"
98
+ end
97
99
  end
98
100
  end
99
101
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Soka
4
+ module Engines
5
+ module Concerns
6
+ # Module for building ReAct reasoning results
7
+ module ResultBuilder
8
+ private
9
+
10
+ def build_result(input:, thoughts:, final_answer:, status:, error: nil)
11
+ result = {
12
+ input: input,
13
+ thoughts: thoughts,
14
+ final_answer: final_answer,
15
+ status: status
16
+ }
17
+
18
+ result[:error] = error if error
19
+
20
+ Soka::Engines::React::ReasonResult.new(**result)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -8,6 +8,8 @@ module Soka
8
8
  class React < Base
9
9
  include Concerns::ResponseProcessor
10
10
  include Concerns::PromptTemplate
11
+ include Concerns::ResponseParser
12
+ include Concerns::ResultBuilder
11
13
 
12
14
  ReasonResult = Struct.new(:input, :thoughts, :final_answer, :status, :error, :confidence_score,
13
15
  keyword_init: true) do
@@ -21,7 +23,8 @@ module Soka
21
23
  # @yield [event] Optional block to handle events during execution
22
24
  # @return [ReasonResult] The result of the reasoning process
23
25
  def reason(task, &block)
24
- context = ReasoningContext.new(task: task, event_handler: block, max_iterations: max_iterations)
26
+ context = ReasoningContext.new(task: task, event_handler: block, max_iterations: max_iterations,
27
+ think_in: think_in)
25
28
  context.messages = build_messages(task)
26
29
 
27
30
  result = iterate_reasoning(context)
@@ -106,31 +109,6 @@ module Soka
106
109
  status: :success
107
110
  )
108
111
  end
109
-
110
- def build_result(input:, thoughts:, final_answer:, status:, error: nil)
111
- result = {
112
- input: input,
113
- thoughts: thoughts,
114
- final_answer: final_answer,
115
- status: status
116
- }
117
-
118
- result[:error] = error if error
119
-
120
- # Calculate confidence score based on iterations and status
121
- result[:confidence_score] = calculate_confidence_score(thoughts, status)
122
-
123
- ReasonResult.new(**result)
124
- end
125
-
126
- def calculate_confidence_score(thoughts, status)
127
- return 0.0 if status != :success
128
-
129
- base_score = 0.85
130
- iteration_penalty = thoughts.length * 0.05
131
-
132
- [base_score - iteration_penalty, 0.5].max
133
- end
134
112
  end
135
113
  end
136
114
  end
@@ -8,17 +8,19 @@ module Soka
8
8
  # Event structure for emitting events
9
9
  Event = Struct.new(:type, :content)
10
10
 
11
- attr_accessor :messages, :thoughts, :task, :iteration, :parsed_response
11
+ attr_accessor :messages, :thoughts, :task, :iteration, :parsed_response, :think_in
12
12
  attr_reader :event_handler, :max_iterations
13
13
 
14
14
  # Initialize a new reasoning context
15
15
  # @param task [String] The task to be processed
16
16
  # @param event_handler [Proc, nil] Optional block to handle events
17
17
  # @param max_iterations [Integer] Maximum number of reasoning iterations
18
- def initialize(task:, event_handler: nil, max_iterations: 10)
18
+ # @param think_in [String, nil] The language to use for thinking
19
+ def initialize(task:, event_handler: nil, max_iterations: 10, think_in: nil)
19
20
  @task = task
20
21
  @event_handler = event_handler
21
22
  @max_iterations = max_iterations
23
+ @think_in = think_in
22
24
  @messages = []
23
25
  @thoughts = []
24
26
  @iteration = 0
data/lib/soka/result.rb CHANGED
@@ -3,14 +3,13 @@
3
3
  module Soka
4
4
  # Represents the result of an agent's reasoning process
5
5
  class Result
6
- attr_reader :input, :thoughts, :final_answer, :confidence_score, :status, :error, :execution_time
6
+ attr_reader :input, :thoughts, :final_answer, :status, :error, :execution_time
7
7
 
8
8
  # Initialize a new Result instance
9
9
  # @param attributes [Hash] Result attributes
10
10
  # @option attributes [String] :input The original input
11
11
  # @option attributes [Array] :thoughts Array of thought objects
12
12
  # @option attributes [String] :final_answer The final answer
13
- # @option attributes [Float] :confidence_score Confidence score (0.0-1.0)
14
13
  # @option attributes [Symbol] :status The result status
15
14
  # @option attributes [String] :error Error message if failed
16
15
  # @option attributes [Float] :execution_time Time taken in seconds
@@ -18,7 +17,6 @@ module Soka
18
17
  @input = attributes[:input]
19
18
  @thoughts = attributes[:thoughts] || []
20
19
  @final_answer = attributes[:final_answer]
21
- @confidence_score = attributes[:confidence_score] || 0.0
22
20
  @status = attributes[:status] || :pending
23
21
  @error = attributes[:error]
24
22
  @execution_time = attributes[:execution_time]
@@ -82,7 +80,6 @@ module Soka
82
80
  def execution_details
83
81
  {
84
82
  iterations: iterations,
85
- confidence: confidence_score ? format('%.1f%%', confidence_score * 100) : 'N/A',
86
83
  time: execution_time ? "#{execution_time.round(2)}s" : 'N/A',
87
84
  status: status
88
85
  }
@@ -99,7 +96,6 @@ module Soka
99
96
  input: input,
100
97
  thoughts: thoughts,
101
98
  final_answer: final_answer,
102
- confidence_score: confidence_score,
103
99
  status: status
104
100
  }
105
101
  end