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.
data/README.md CHANGED
@@ -98,6 +98,67 @@ puts result.final_answer
98
98
  ruby examples/1_basic.rb
99
99
  ```
100
100
 
101
+ ## Rails Integration
102
+
103
+ ### Soka Rails
104
+
105
+ For Rails applications, we provide a dedicated gem `soka-rails` that offers seamless integration with Rails conventions:
106
+
107
+ ```ruby
108
+ # Gemfile
109
+ gem 'soka-rails'
110
+ ```
111
+
112
+ #### Features
113
+
114
+ - ๐Ÿš‚ **Native Rails Integration**: Following Rails conventions and best practices
115
+ - ๐Ÿ“ **Auto-loading Support**: Automatically loads the `app/soka` directory
116
+ - ๐Ÿ› ๏ธ **Generator Support**: Quickly generate Agent and Tool templates
117
+ - โš™๏ธ **Rails Configuration Integration**: Uses Rails' configuration system
118
+ - ๐Ÿงช **Rails Testing Integration**: Seamless integration with RSpec
119
+ - ๐Ÿ”„ **Rails Lifecycle Hooks**: Integrates with Rails logging and error tracking
120
+
121
+ #### Quick Setup
122
+
123
+ ```bash
124
+ # Install the gem
125
+ bundle add soka-rails
126
+
127
+ # Run the installation generator
128
+ rails generate soka:install
129
+
130
+ # Generate an agent
131
+ rails generate soka:agent customer_support
132
+
133
+ # Generate a tool
134
+ rails generate soka:tool order_lookup order_id:string
135
+ ```
136
+
137
+ #### Basic Usage in Rails
138
+
139
+ ```ruby
140
+ # app/soka/agents/customer_support_agent.rb
141
+ class CustomerSupportAgent < ApplicationAgent
142
+ tool OrderLookupTool
143
+ tool UserInfoTool
144
+ end
145
+
146
+ # app/controllers/conversations_controller.rb
147
+ class ConversationsController < ApplicationController
148
+ def create
149
+ agent = CustomerSupportAgent.new
150
+ result = agent.run(params[:message])
151
+
152
+ render json: {
153
+ answer: result.final_answer,
154
+ status: result.status
155
+ }
156
+ end
157
+ end
158
+ ```
159
+
160
+ For more details, visit the [soka-rails repository](https://github.com/jiunjiun/soka-rails).
161
+
101
162
  ## Core Concepts
102
163
 
103
164
  ### Global Configuration
@@ -180,6 +241,12 @@ class WeatherAgent < Soka::Agent
180
241
  # Custom tool (functional) - requires description as second parameter
181
242
  tool :get_weather, "Get weather for a location"
182
243
 
244
+ # Custom instructions (optional)
245
+ instructions "You are a weather expert. Provide detailed weather information."
246
+
247
+ # Thinking language (optional)
248
+ think_in 'en' # Default is 'en'
249
+
183
250
  # Lifecycle hooks
184
251
  before_action :track_action
185
252
  after_action :update_metrics
@@ -246,7 +313,6 @@ result = agent.run('What is the weather in Tokyo today?')
246
313
 
247
314
  # Result object provides rich information
248
315
  puts result.final_answer # Final answer
249
- puts result.confidence_score # Confidence score (0.0-1.0)
250
316
  puts result.iterations # Number of iterations used
251
317
  puts result.status # :success, :failed, :timeout, :max_iterations_reached
252
318
  puts result.execution_time # Execution time (if recorded)
@@ -293,16 +359,85 @@ puts agent.memory
293
359
  ```ruby
294
360
  # View complete thought process
295
361
  puts agent.thoughts_memory
296
- # <Soka::ThoughtsMemory> (3 sessions, 2 successful, 1 failed, avg confidence: 0.82, avg iterations: 2.3)
362
+ # <Soka::ThoughtsMemory> (3 sessions, 2 successful, 1 failed, avg iterations: 2.3)
297
363
 
298
364
  # Get detailed information for specific session
299
365
  last_session = agent.thoughts_memory.last_session
300
366
  puts last_session[:thoughts] # All thinking steps
301
- puts last_session[:confidence_score] # Confidence score for that execution
367
+ puts last_session[:final_answer] # Final answer for that execution
302
368
  ```
303
369
 
304
370
  ## Advanced Features
305
371
 
372
+ ### Custom Instructions
373
+
374
+ Customize your agent's personality and response style:
375
+
376
+ ```ruby
377
+ class FriendlyAgent < Soka::Agent
378
+ provider :gemini
379
+
380
+ # Method 1: Static string instructions
381
+ instructions <<~PROMPT
382
+ You are a friendly, helpful assistant.
383
+ Use casual language and be encouraging.
384
+ Add emojis when appropriate.
385
+ PROMPT
386
+ end
387
+
388
+ # Method 2: Dynamic instructions using method
389
+ class DynamicAgent < Soka::Agent
390
+ provider :gemini
391
+
392
+ # Reference a method for dynamic instructions
393
+ instructions :generate_instructions
394
+
395
+ private
396
+
397
+ def generate_instructions
398
+ hour = Time.now.hour
399
+ mood = hour < 12 ? 'cheerful morning' : 'relaxed afternoon'
400
+
401
+ <<~PROMPT
402
+ You are a #{mood} assistant.
403
+ Current Time: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}
404
+ Adjust your tone based on the time of day.
405
+ PROMPT
406
+ end
407
+ end
408
+
409
+ # Method 3: Override at runtime
410
+ agent = FriendlyAgent.new(
411
+ instructions: 'Be more formal and professional.'
412
+ )
413
+ result = agent.run("Help me with this task")
414
+ ```
415
+
416
+ ### Multilingual Thinking (Think In)
417
+
418
+ Optimize reasoning for specific languages:
419
+
420
+ ```ruby
421
+ class GlobalAgent < Soka::Agent
422
+ provider :gemini
423
+
424
+ # Set default thinking language
425
+ think_in 'zh-TW' # Think in Traditional Chinese
426
+ end
427
+
428
+ # Or set dynamically
429
+ agent = GlobalAgent.new(think_in: 'ja-JP')
430
+ result = agent.run("ๅนซๆˆ‘่งฃๆฑบ้€™ๅ€‹ๅ•้กŒ") # Input in Chinese
431
+ # Agent thinks in Japanese internally, responds in Chinese
432
+ ```
433
+
434
+ **Key Points:**
435
+ - Thinking language affects internal reasoning only
436
+ - Responses adapt to user's input language
437
+ - Default is English (`'en'`)
438
+ - No automatic language detection (explicit setting required)
439
+ - Improves reasoning quality for language-specific contexts
440
+
306
441
  ### ReAct Flow Format
307
442
 
308
443
  Soka uses a tagged ReAct format:
@@ -325,7 +460,6 @@ Parameters: {"query": "Tokyo weather", "location": "Japan"}
325
460
  result.input # User input
326
461
  result.thoughts # Array of thinking steps
327
462
  result.final_answer # Final answer
328
- result.confidence_score # Confidence score (0.0-1.0)
329
463
  result.status # Status (:success, :failed, :timeout, :max_iterations_reached)
330
464
  result.error # Error message (if any)
331
465
  result.execution_time # Execution time (seconds)
@@ -343,7 +477,6 @@ result.iterations # Number of iterations
343
477
  }
344
478
  ],
345
479
  final_answer: "Final answer",
346
- confidence_score: 0.85, # Calculated based on iterations
347
480
  status: :success, # :success, :failed, :timeout, :max_iterations_reached
348
481
  error: nil, # Error message (if any)
349
482
  execution_time: 1.23, # Execution time (seconds)
@@ -383,7 +516,7 @@ RSpec.describe WeatherAgent do
383
516
  expect(result).to be_successful
384
517
  expect(result.final_answer).to include("sunny")
385
518
  expect(result).to have_thoughts_count(1)
386
- expect(result).to have_confidence_score_above(0.8)
519
+ expect(result.status).to eq(:success)
387
520
  end
388
521
 
389
522
  it "handles tool errors gracefully" do
@@ -422,8 +555,7 @@ class CustomEngine < Soka::Engines::Base
422
555
  input: task,
423
556
  thoughts: thoughts,
424
557
  final_answer: answer,
425
- status: :success,
426
- confidence_score: calculate_confidence_score(thoughts, :success)
558
+ status: :success
427
559
  )
428
560
  end
429
561
  end
@@ -493,6 +625,27 @@ Demonstrates using different AI providers:
493
625
  - Comparing outputs across models
494
626
  - Cost optimization strategies
495
627
 
628
+ ### 9. Custom Instructions (`examples/9_custom_instructions.rb`)
629
+ Shows how to customize agent personality:
630
+ - Setting instructions at class level
631
+ - Runtime instruction override
632
+ - Creating different agent personalities
633
+ - Use cases for different domains
634
+
635
+ ### 10. Dynamic Instructions (`examples/10_dynamic_instructions.rb`)
636
+ Demonstrates dynamic instruction generation:
637
+ - Using methods to generate instructions dynamically
638
+ - Time-based instruction changes
639
+ - Environment-based configuration
640
+ - Session-based personality switching
641
+
642
+ ### 11. Multilingual Thinking (`examples/11_think_in_languages.rb`)
643
+ Demonstrates language-specific reasoning:
644
+ - Setting thinking language with `think_in`
645
+ - Class-level vs instance-level configuration
646
+ - Performance comparison across languages
647
+ - Cultural context optimization
648
+
496
649
  To run any example:
497
650
  ```bash
498
651
  # Make sure you have the required API keys in your .env file
@@ -526,6 +679,8 @@ ruby examples/1_basic.rb
526
679
  | `ai.provider` | Symbol | `:gemini` | AI provider |
527
680
  | `ai.model` | String | `"gemini-2.5-flash-lite"` | Model to use |
528
681
  | `ai.api_key` | String | nil | API key |
682
+ | `ai.instructions` | String | nil | Custom agent instructions |
683
+ | `ai.think_in` | String | `"en"` | Thinking language |
529
684
  | `performance.max_iterations` | Integer | 10 | Max iterations |
530
685
  | `performance.timeout` | Integer | 30 | Timeout (seconds) |
531
686
 
@@ -0,0 +1,248 @@
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 10: Dynamic Instructions via Method
10
+ #
11
+ # This example demonstrates how to use a method to generate instructions dynamically.
12
+ # Instead of static string instructions, you can define a method that returns
13
+ # instructions based on runtime conditions.
14
+ #
15
+ # Key concepts:
16
+ # - Using a Symbol to reference an instructions method
17
+ # - Dynamic instruction generation based on context
18
+ # - Maintaining compatibility with string-based instructions
19
+
20
+ # Example 1: Time-aware Assistant
21
+ # Instructions change based on time of day
22
+ class TimeAwareAssistant < Soka::Agent
23
+ provider :gemini
24
+ model 'gemini-2.5-flash-lite'
25
+
26
+ # Use a method to generate instructions
27
+ instructions :generate_time_based_instructions
28
+
29
+ class GreetingTool < Soka::AgentTool
30
+ desc 'Generate appropriate greetings'
31
+
32
+ params do
33
+ requires :name, String, desc: 'Name of the person to greet'
34
+ end
35
+
36
+ def call(name:)
37
+ "Greeting generated for #{name}"
38
+ end
39
+ end
40
+
41
+ tool GreetingTool
42
+
43
+ private
44
+
45
+ def generate_time_based_instructions
46
+ hour = Time.now.hour
47
+
48
+ base_instructions = if hour < 12
49
+ 'You are a cheerful morning assistant who is energetic and motivating.'
50
+ elsif hour < 17
51
+ 'You are a focused afternoon assistant who is professional and efficient.'
52
+ else
53
+ 'You are a relaxed evening assistant who is calm and supportive.'
54
+ end
55
+
56
+ <<~INSTRUCTIONS
57
+ #{base_instructions}
58
+ Current time: #{Time.now.strftime('%H:%M')}
59
+
60
+ You must:
61
+ - Acknowledge the time of day in your responses
62
+ - Adjust your tone based on the time period
63
+ - Be helpful while matching the appropriate energy level
64
+ INSTRUCTIONS
65
+ end
66
+ end
67
+
68
+ # Example 2: Environment-based Assistant
69
+ # Instructions change based on environment variables
70
+ class EnvironmentAwareAssistant < Soka::Agent
71
+ provider :gemini
72
+ model 'gemini-2.5-flash-lite'
73
+
74
+ # Use a method for environment-based instructions
75
+ instructions :build_environment_instructions
76
+
77
+ class CalculatorTool < Soka::AgentTool
78
+ desc 'Performs calculations'
79
+
80
+ params do
81
+ requires :expression, String, desc: 'Math expression'
82
+ end
83
+
84
+ def call(expression:)
85
+ calculator = Dentaku::Calculator.new
86
+ result = calculator.evaluate(expression)
87
+ "Result: #{expression} = #{result}"
88
+ rescue StandardError => e
89
+ "Error: #{e.message}"
90
+ end
91
+ end
92
+
93
+ tool CalculatorTool
94
+
95
+ private
96
+
97
+ def build_environment_instructions
98
+ user_level = ENV['USER_LEVEL'] || 'beginner'
99
+ debug_mode = ENV['DEBUG'] == 'true'
100
+
101
+ style = case user_level
102
+ when 'expert'
103
+ 'Use technical terminology and assume deep knowledge. Be concise.'
104
+ when 'intermediate'
105
+ 'Balance technical accuracy with clear explanations. Provide context when needed.'
106
+ else
107
+ 'Use simple language and explain concepts thoroughly. Avoid jargon.'
108
+ end
109
+
110
+ debug_info = if debug_mode
111
+ "\n- Include detailed technical information in responses"
112
+ else
113
+ "\n- Keep responses focused on the essential information"
114
+ end
115
+
116
+ <<~INSTRUCTIONS
117
+ You are an AI assistant adapting to the user's expertise level.
118
+
119
+ Communication style: #{style}
120
+ User level: #{user_level}
121
+ Debug mode: #{debug_mode}
122
+
123
+ Guidelines:#{debug_info}
124
+ - Adapt your responses to the #{user_level} level
125
+ - Maintain accuracy while adjusting complexity
126
+ INSTRUCTIONS
127
+ end
128
+ end
129
+
130
+ # Example 3: Session-based Assistant
131
+ # Instructions change based on a session ID
132
+ class SessionAssistant < Soka::Agent
133
+ provider :gemini
134
+ model 'gemini-2.5-flash-lite'
135
+
136
+ # Use method for session-based instructions
137
+ instructions :generate_session_instructions
138
+
139
+ class InfoTool < Soka::AgentTool
140
+ desc 'Provides information'
141
+
142
+ params do
143
+ requires :query, String, desc: 'Information query'
144
+ end
145
+
146
+ def call(query:)
147
+ "Information about: #{query}"
148
+ end
149
+ end
150
+
151
+ tool InfoTool
152
+
153
+ private
154
+
155
+ def generate_session_instructions
156
+ # Simulate different session types based on time
157
+ session_type = Time.now.min % 3
158
+
159
+ personality = case session_type
160
+ when 0
161
+ 'You are a formal, professional assistant.'
162
+ when 1
163
+ 'You are a friendly, casual assistant.'
164
+ else
165
+ 'You are an educational, patient assistant.'
166
+ end
167
+
168
+ <<~INSTRUCTIONS
169
+ #{personality}
170
+ Session ID: #{Time.now.to_i}
171
+
172
+ Guidelines:
173
+ - Maintain consistent personality throughout the session
174
+ - Provide helpful and accurate information
175
+ - Adapt your tone to match the session style
176
+ INSTRUCTIONS
177
+ end
178
+ end
179
+
180
+ # Run examples
181
+ puts '=== Time-Aware Assistant Example ==='
182
+ time_assistant = TimeAwareAssistant.new
183
+
184
+ time_assistant.run('Please greet John appropriately for the current time') do |event|
185
+ case event.type
186
+ when :thought
187
+ puts "โฐ Thinking: #{event.content}"
188
+ when :final_answer
189
+ puts "๐Ÿ“ Response: #{event.content}"
190
+ end
191
+ end
192
+
193
+ puts "\n=== Environment-based Assistant (Beginner) Example ==="
194
+ ENV['USER_LEVEL'] = 'beginner'
195
+ ENV['DEBUG'] = 'false'
196
+
197
+ beginner_assistant = EnvironmentAwareAssistant.new
198
+
199
+ beginner_assistant.run('Calculate 15% of 200') do |event|
200
+ case event.type
201
+ when :thought
202
+ puts "๐ŸŽ“ Thinking: #{event.content}"
203
+ when :final_answer
204
+ puts "๐Ÿ“š Response: #{event.content}"
205
+ end
206
+ end
207
+
208
+ puts "\n=== Environment-based Assistant (Expert) Example ==="
209
+ ENV['USER_LEVEL'] = 'expert'
210
+ ENV['DEBUG'] = 'true'
211
+
212
+ expert_assistant = EnvironmentAwareAssistant.new
213
+
214
+ expert_assistant.run('Calculate 15% of 200') do |event|
215
+ case event.type
216
+ when :final_answer
217
+ puts "๐Ÿ’ผ Response: #{event.content}"
218
+ end
219
+ end
220
+
221
+ puts "\n=== Session Assistant Example ==="
222
+ session_assistant = SessionAssistant.new
223
+
224
+ session_assistant.run('Tell me about Ruby') do |event|
225
+ case event.type
226
+ when :thought
227
+ puts "๐Ÿ”ง Thinking: #{event.content}"
228
+ when :final_answer
229
+ puts "๐Ÿ–ฅ๏ธ Response: #{event.content}"
230
+ end
231
+ end
232
+
233
+ puts "\n=== Mixed: String and Method Instructions ==="
234
+ # You can still use string instructions
235
+ class StringInstructionsAgent < Soka::Agent
236
+ provider :gemini
237
+ model 'gemini-2.5-flash-lite'
238
+
239
+ instructions 'You are a helpful assistant that always responds concisely.'
240
+ end
241
+
242
+ puts "String instructions work as before."
243
+
244
+ # And override at runtime
245
+ TimeAwareAssistant.new(
246
+ instructions: 'Override with a custom string instruction at runtime.'
247
+ )
248
+ puts "Runtime overrides still work with both string and method-based instructions."
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/soka'
4
+ require 'dotenv/load'
5
+ require 'dentaku'
6
+
7
+ # Example 10: Think In Languages Feature
8
+ #
9
+ # This example demonstrates the think_in feature that allows Agents to use
10
+ # a specific language for their internal reasoning process.
11
+ #
12
+ # Key concepts:
13
+ # - think_in specifies the language for internal thoughts
14
+ # - Final answers typically match the user's input language
15
+ # - Default thinking language is 'en' (English)
16
+ # - No automatic language detection - you must specify explicitly
17
+ #
18
+ # Benefits:
19
+ # - Improved reasoning quality for specific languages
20
+ # - Better cultural context understanding
21
+ # - Consistent reasoning patterns across teams
22
+ # - Reduced API calls (no language detection)
23
+
24
+ # Example: Multilingual Agent with configurable thinking language
25
+ class MultilingualAgent < Soka::Agent
26
+ provider ENV.fetch('AGENT_PROVIDER', :gemini).to_sym
27
+ model ENV.fetch('AGENT_MODEL', nil)
28
+
29
+ # Define a simple calculator tool
30
+ class CalculateTool < Soka::AgentTool
31
+ desc 'Perform mathematical calculations'
32
+
33
+ params do
34
+ requires :expression, String, desc: 'Mathematical expression to evaluate'
35
+ end
36
+
37
+ def call(expression:)
38
+ calculator = Dentaku::Calculator.new
39
+ result = calculator.evaluate(expression)
40
+ "The result of #{expression} is #{result}"
41
+ rescue StandardError => e
42
+ "Error calculating: #{e.message}"
43
+ end
44
+ end
45
+
46
+ tool CalculateTool
47
+ end
48
+
49
+ puts "=== Think In Languages Example ==="
50
+ puts
51
+
52
+ # Example 1: Default behavior - thinks in English
53
+ # Without specifying think_in, the agent defaults to English thinking
54
+ # but still understands and responds appropriately to Chinese input
55
+ puts "1. Chinese Input (Default English thinking):"
56
+ agent = MultilingualAgent.new # No think_in specified, defaults to 'en'
57
+ result = agent.run("ๅนซๆˆ‘่จˆ็ฎ— 123 + 456 ็š„็ตๆžœ")
58
+ puts "Answer: #{result.final_answer}"
59
+ puts
60
+
61
+ # Example 2: Explicit Japanese thinking
62
+ # Specifying think_in='ja-JP' makes the agent think in Japanese
63
+ # This can improve reasoning quality for Japanese cultural contexts
64
+ puts "2. English Input with Japanese Thinking:"
65
+ agent = MultilingualAgent.new(think_in: 'ja-JP')
66
+ result = agent.run("Calculate the sum of 789 and 321")
67
+ puts "Answer: #{result.final_answer}"
68
+ puts
69
+
70
+ # Example 3: DSL configuration for Korean thinking
71
+ # Using the DSL to set think_in at the class level
72
+ # All instances of KoreanAgent will think in Korean by default
73
+ puts "3. DSL Configuration (Korean thinking):"
74
+ class KoreanAgent < MultilingualAgent
75
+ think_in 'ko-KR' # Class-level configuration
76
+ end
77
+
78
+ agent = KoreanAgent.new
79
+ result = agent.run("What is 1000 minus 250?")
80
+ puts "Answer: #{result.final_answer}"
81
+ puts
82
+
83
+ # Example 4: Show the thinking process
84
+ puts "4. Showing Thinking Process:"
85
+ agent = MultilingualAgent.new(think_in: 'zh-TW')
86
+ result = agent.run("่ซ‹่จˆ็ฎ— 50 ไน˜ไปฅ 8") do |event|
87
+ case event.type
88
+ when :thought
89
+ puts "ๆ€่€ƒ: #{event.content}"
90
+ when :action
91
+ puts "่กŒๅ‹•: ไฝฟ็”จๅทฅๅ…ท #{event.content[:tool]}"
92
+ when :observation
93
+ puts "่ง€ๅฏŸ: #{event.content}"
94
+ when :final_answer
95
+ puts "ๆœ€็ต‚็ญ”ๆกˆ: #{event.content}"
96
+ end
97
+ end
98
+ puts
99
+
100
+ # Example 5: Multiple languages in sequence
101
+ puts "5. Multiple Languages:"
102
+ languages = {
103
+ 'en' => "Calculate 100 divided by 4",
104
+ 'zh-TW' => "่ซ‹่จˆ็ฎ— 100 ้™คไปฅ 4",
105
+ 'ja-JP' => "100ใ‚’4ใงๅ‰ฒใฃใŸ็ตๆžœใ‚’่จˆ็ฎ—ใ—ใฆใใ ใ•ใ„",
106
+ 'es' => "Calcula 100 dividido por 4"
107
+ }
108
+
109
+ languages.each do |lang, question|
110
+ agent = MultilingualAgent.new(think_in: lang)
111
+ result = agent.run(question)
112
+ puts "#{lang}: #{result.final_answer}"
113
+ end
@@ -4,6 +4,7 @@
4
4
  require 'bundler/setup'
5
5
  require 'soka'
6
6
  require 'dotenv/load'
7
+ require 'dentaku'
7
8
 
8
9
  # Configure Soka
9
10
  Soka.setup do |config|
@@ -21,14 +22,15 @@ end
21
22
 
22
23
  # Simple calculation tool
23
24
  class CalculatorTool < Soka::AgentTool
24
- desc 'Perform calculations'
25
+ desc 'Perform calculations using Dentaku (safe math evaluator)'
25
26
 
26
27
  params do
27
- requires :expression, String, desc: 'Mathematical expression to calculate'
28
+ requires :expression, String, desc: 'Mathematical expression (use ^ for power, e.g., "2^3" = 8)'
28
29
  end
29
30
 
30
31
  def call(expression:)
31
- result = eval(expression) # rubocop:disable Security/Eval
32
+ calculator = Dentaku::Calculator.new
33
+ result = calculator.evaluate(expression)
32
34
  "Result: #{expression} = #{result}"
33
35
  rescue StandardError => e
34
36
  "Error: #{e.message}"
@@ -109,7 +111,6 @@ puts '-' * 50
109
111
 
110
112
  result = agent.run('Calculate the area of a circle with radius 5')
111
113
  puts "Direct result: #{result.final_answer}"
112
- puts "Confidence: #{(result.confidence_score * 100).round(1)}%"
113
114
  puts "Iterations: #{result.iterations}"
114
115
 
115
116
  puts "\n=== Event Handling Benefits ==="
data/examples/3_memory.rb CHANGED
@@ -5,6 +5,7 @@ require 'bundler/setup'
5
5
  require 'soka'
6
6
  require 'dotenv/load'
7
7
  require 'singleton'
8
+ require 'dentaku'
8
9
 
9
10
  # Configure Soka
10
11
  Soka.setup do |config|
@@ -29,8 +30,9 @@ class CalculatorTool < Soka::AgentTool
29
30
  end
30
31
 
31
32
  def call(expression:)
32
- # Simple math expression evaluation (production should use safer methods)
33
- result = eval(expression) # rubocop:disable Security/Eval
33
+ # Safe math expression evaluation using Dentaku
34
+ calculator = Dentaku::Calculator.new
35
+ result = calculator.evaluate(expression)
34
36
  "Calculation result: #{expression} = #{result}"
35
37
  rescue StandardError => e
36
38
  "Calculation error: #{e.message}"
data/examples/4_hooks.rb CHANGED
@@ -59,7 +59,6 @@ class HookedAgent < Soka::Agent
59
59
  puts "๐ŸŸข [AFTER] Request completed"
60
60
  puts "๐ŸŸข [AFTER] Final answer: #{result.final_answer[0..100]}..."
61
61
  puts "๐ŸŸข [AFTER] Iterations: #{result.iterations}"
62
- puts "๐ŸŸข [AFTER] Confidence: #{(result.confidence_score * 100).round(1)}%"
63
62
  puts "๐ŸŸข [AFTER] Memory size: #{@memory.messages.size} messages"
64
63
  end
65
64