llm.rb 12.6.0 → 13.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +387 -0
- data/LICENSE +21 -93
- data/README.md +46 -155
- data/data/deepinfra.json +3 -0
- data/data/xai.json +1 -1
- data/lib/llm/a2a.rb +1 -1
- data/lib/llm/active_record/acts_as_llm.rb +6 -6
- data/lib/llm/agent.rb +62 -23
- data/lib/llm/buffer.rb +85 -3
- data/lib/llm/compactor/null.rb +19 -0
- data/lib/llm/compactor/truncate.rb +80 -0
- data/lib/llm/compactor.rb +42 -124
- data/lib/llm/context.rb +31 -37
- data/lib/llm/contract.rb +4 -25
- data/lib/llm/function/array.rb +15 -14
- data/lib/llm/function/async/group.rb +54 -0
- data/lib/llm/function/async/reactor.rb +48 -0
- data/lib/llm/function/async/task.rb +83 -0
- data/lib/llm/function/fiber/group.rb +46 -0
- data/lib/llm/function/fiber/task.rb +62 -0
- data/lib/llm/function/{fork_group.rb → fork/group.rb} +14 -5
- data/lib/llm/function/fork/job.rb +2 -2
- data/lib/llm/function/fork/task.rb +19 -10
- data/lib/llm/function/group.rb +40 -0
- data/lib/llm/function/{ractor_group.rb → ractor/group.rb} +13 -5
- data/lib/llm/function/ractor/job.rb +9 -3
- data/lib/llm/function/ractor/mailbox.rb +2 -0
- data/lib/llm/function/ractor/task.rb +23 -15
- data/lib/llm/function/{call_group.rb → sequential/group.rb} +12 -8
- data/lib/llm/function/sequential/task.rb +49 -0
- data/lib/llm/function/task.rb +25 -48
- data/lib/llm/function/thread/group.rb +46 -0
- data/lib/llm/function/thread/task.rb +60 -0
- data/lib/llm/function.rb +54 -64
- data/lib/llm/loop_guard.rb +1 -2
- data/lib/llm/mcp.rb +22 -0
- data/lib/llm/object.rb +2 -1
- data/lib/llm/provider.rb +6 -3
- data/lib/llm/providers/google.rb +2 -2
- data/lib/llm/repl/command.rb +35 -8
- data/lib/llm/repl/commands/compact.rb +33 -0
- data/lib/llm/repl/input.rb +80 -15
- data/lib/llm/repl/markdown/table.rb +76 -0
- data/lib/llm/repl/markdown.rb +31 -1
- data/lib/llm/repl/status.rb +1 -1
- data/lib/llm/repl/stream.rb +10 -3
- data/lib/llm/repl/transcript.rb +1 -1
- data/lib/llm/repl/walker.rb +46 -0
- data/lib/llm/repl.rb +18 -12
- data/lib/llm/response.rb +10 -0
- data/lib/llm/schema/leaf.rb +5 -0
- data/lib/llm/schema/object.rb +11 -5
- data/lib/llm/sequel/plugin.rb +6 -6
- data/lib/llm/stream.rb +24 -17
- data/lib/llm/tool.rb +20 -4
- data/lib/llm/tools/chdir.rb +0 -2
- data/lib/llm/tools/git.rb +8 -4
- data/lib/llm/tools/mkdir.rb +1 -1
- data/lib/llm/tools/pwd.rb +0 -2
- data/lib/llm/tools/read_file.rb +0 -2
- data/lib/llm/tools/rg.rb +8 -4
- data/lib/llm/tools/shell.rb +8 -4
- data/lib/llm/tools/utils.rb +31 -0
- data/lib/llm/version.rb +1 -1
- data/lib/llm.rb +25 -5
- data/llm.gemspec +3 -3
- data/resources/deepdive.md +645 -58
- metadata +24 -13
- data/lib/llm/function/call_task.rb +0 -46
- data/lib/llm/function/fiber_group.rb +0 -105
- data/lib/llm/function/task_group.rb +0 -97
- data/lib/llm/function/thread_group.rb +0 -102
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 13.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- robert
|
|
@@ -73,14 +73,14 @@ dependencies:
|
|
|
73
73
|
requirements:
|
|
74
74
|
- - "~>"
|
|
75
75
|
- !ruby/object:Gem::Version
|
|
76
|
-
version:
|
|
76
|
+
version: 1.1.0
|
|
77
77
|
type: :development
|
|
78
78
|
prerelease: false
|
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
|
80
80
|
requirements:
|
|
81
81
|
- - "~>"
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
|
-
version:
|
|
83
|
+
version: 1.1.0
|
|
84
84
|
- !ruby/object:Gem::Dependency
|
|
85
85
|
name: rake
|
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -241,14 +241,14 @@ dependencies:
|
|
|
241
241
|
requirements:
|
|
242
242
|
- - "~>"
|
|
243
243
|
- !ruby/object:Gem::Version
|
|
244
|
-
version: '0.
|
|
244
|
+
version: '0.22'
|
|
245
245
|
type: :development
|
|
246
246
|
prerelease: false
|
|
247
247
|
version_requirements: !ruby/object:Gem::Requirement
|
|
248
248
|
requirements:
|
|
249
249
|
- - "~>"
|
|
250
250
|
- !ruby/object:Gem::Version
|
|
251
|
-
version: '0.
|
|
251
|
+
version: '0.22'
|
|
252
252
|
- !ruby/object:Gem::Dependency
|
|
253
253
|
name: pg
|
|
254
254
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -317,6 +317,8 @@ files:
|
|
|
317
317
|
- lib/llm/agent.rb
|
|
318
318
|
- lib/llm/buffer.rb
|
|
319
319
|
- lib/llm/compactor.rb
|
|
320
|
+
- lib/llm/compactor/null.rb
|
|
321
|
+
- lib/llm/compactor/truncate.rb
|
|
320
322
|
- lib/llm/context.rb
|
|
321
323
|
- lib/llm/context/deserializer.rb
|
|
322
324
|
- lib/llm/context/serializer.rb
|
|
@@ -331,22 +333,27 @@ files:
|
|
|
331
333
|
- lib/llm/file.rb
|
|
332
334
|
- lib/llm/function.rb
|
|
333
335
|
- lib/llm/function/array.rb
|
|
334
|
-
- lib/llm/function/
|
|
335
|
-
- lib/llm/function/
|
|
336
|
-
- lib/llm/function/
|
|
336
|
+
- lib/llm/function/async/group.rb
|
|
337
|
+
- lib/llm/function/async/reactor.rb
|
|
338
|
+
- lib/llm/function/async/task.rb
|
|
339
|
+
- lib/llm/function/fiber/group.rb
|
|
340
|
+
- lib/llm/function/fiber/task.rb
|
|
337
341
|
- lib/llm/function/fork.rb
|
|
342
|
+
- lib/llm/function/fork/group.rb
|
|
338
343
|
- lib/llm/function/fork/job.rb
|
|
339
344
|
- lib/llm/function/fork/task.rb
|
|
340
|
-
- lib/llm/function/
|
|
345
|
+
- lib/llm/function/group.rb
|
|
341
346
|
- lib/llm/function/ractor.rb
|
|
347
|
+
- lib/llm/function/ractor/group.rb
|
|
342
348
|
- lib/llm/function/ractor/job.rb
|
|
343
349
|
- lib/llm/function/ractor/mailbox.rb
|
|
344
350
|
- lib/llm/function/ractor/task.rb
|
|
345
|
-
- lib/llm/function/ractor_group.rb
|
|
346
351
|
- lib/llm/function/registry.rb
|
|
352
|
+
- lib/llm/function/sequential/group.rb
|
|
353
|
+
- lib/llm/function/sequential/task.rb
|
|
347
354
|
- lib/llm/function/task.rb
|
|
348
|
-
- lib/llm/function/
|
|
349
|
-
- lib/llm/function/
|
|
355
|
+
- lib/llm/function/thread/group.rb
|
|
356
|
+
- lib/llm/function/thread/task.rb
|
|
350
357
|
- lib/llm/function/tracing.rb
|
|
351
358
|
- lib/llm/json_adapter.rb
|
|
352
359
|
- lib/llm/loop_guard.rb
|
|
@@ -469,13 +476,16 @@ files:
|
|
|
469
476
|
- lib/llm/repl.rb
|
|
470
477
|
- lib/llm/repl/bar.rb
|
|
471
478
|
- lib/llm/repl/command.rb
|
|
479
|
+
- lib/llm/repl/commands/compact.rb
|
|
472
480
|
- lib/llm/repl/commands/exit.rb
|
|
473
481
|
- lib/llm/repl/commands/help.rb
|
|
474
482
|
- lib/llm/repl/input.rb
|
|
475
483
|
- lib/llm/repl/markdown.rb
|
|
484
|
+
- lib/llm/repl/markdown/table.rb
|
|
476
485
|
- lib/llm/repl/status.rb
|
|
477
486
|
- lib/llm/repl/stream.rb
|
|
478
487
|
- lib/llm/repl/transcript.rb
|
|
488
|
+
- lib/llm/repl/walker.rb
|
|
479
489
|
- lib/llm/repl/window.rb
|
|
480
490
|
- lib/llm/response.rb
|
|
481
491
|
- lib/llm/schema.rb
|
|
@@ -515,6 +525,7 @@ files:
|
|
|
515
525
|
- lib/llm/tools/rg.rb
|
|
516
526
|
- lib/llm/tools/shell.rb
|
|
517
527
|
- lib/llm/tools/swap_text.rb
|
|
528
|
+
- lib/llm/tools/utils.rb
|
|
518
529
|
- lib/llm/tools/which.rb
|
|
519
530
|
- lib/llm/tools/write_file.rb
|
|
520
531
|
- lib/llm/tracer.rb
|
|
@@ -543,7 +554,7 @@ files:
|
|
|
543
554
|
- resources/deepdive.md
|
|
544
555
|
homepage: https://r.uby.dev/llm/
|
|
545
556
|
licenses:
|
|
546
|
-
-
|
|
557
|
+
- MIT
|
|
547
558
|
metadata:
|
|
548
559
|
homepage_uri: https://r.uby.dev/llm/
|
|
549
560
|
source_code_uri: https://github.com/r-uby-dev/llm.rb
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class LLM::Function
|
|
4
|
-
##
|
|
5
|
-
# The {LLM::Function::CallTask} class wraps a single direct function call
|
|
6
|
-
# behind the same task-like interface used by spawned concurrency modes.
|
|
7
|
-
class CallTask
|
|
8
|
-
##
|
|
9
|
-
# @return [LLM::Function]
|
|
10
|
-
attr_reader :function
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
# @param [LLM::Function] function
|
|
14
|
-
# @return [LLM::Function::CallTask]
|
|
15
|
-
def initialize(function)
|
|
16
|
-
@function = function
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
##
|
|
20
|
-
# @return [Boolean]
|
|
21
|
-
def alive?
|
|
22
|
-
false
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
##
|
|
26
|
-
# @return [nil]
|
|
27
|
-
def interrupt!
|
|
28
|
-
function.interrupt!
|
|
29
|
-
nil
|
|
30
|
-
end
|
|
31
|
-
alias_method :cancel!, :interrupt!
|
|
32
|
-
|
|
33
|
-
##
|
|
34
|
-
# @return [LLM::Function::Return]
|
|
35
|
-
def wait
|
|
36
|
-
function.call
|
|
37
|
-
end
|
|
38
|
-
alias_method :value, :wait
|
|
39
|
-
|
|
40
|
-
##
|
|
41
|
-
# @return [Class]
|
|
42
|
-
def group_class
|
|
43
|
-
LLM::Function::TaskGroup
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class LLM::Function
|
|
4
|
-
##
|
|
5
|
-
# The {LLM::Function::FiberGroup} class wraps an array of
|
|
6
|
-
# `Fiber` objects that are running {LLM::Function} calls
|
|
7
|
-
# concurrently using scheduler-backed fibers.
|
|
8
|
-
#
|
|
9
|
-
# This class provides the same interface as {LLM::Function::ThreadGroup}
|
|
10
|
-
# but uses scheduler-backed fibers for cooperative concurrency.
|
|
11
|
-
#
|
|
12
|
-
# @example
|
|
13
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
14
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
15
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
16
|
-
# grp = ctx.functions.spawn(:fiber)
|
|
17
|
-
# # do other work while tools run...
|
|
18
|
-
# ctx.talk(grp.wait)
|
|
19
|
-
#
|
|
20
|
-
# @see LLM::Function::Array#spawn
|
|
21
|
-
# @see LLM::Function::ThreadGroup
|
|
22
|
-
# @see LLM::Function::TaskGroup
|
|
23
|
-
class FiberGroup
|
|
24
|
-
##
|
|
25
|
-
# Creates a new {LLM::Function::FiberGroup} from an array
|
|
26
|
-
# of fiber objects.
|
|
27
|
-
#
|
|
28
|
-
# @param [Array<Fiber>] fibers
|
|
29
|
-
# An array of fibers, each running an `LLM::Function#spawn_fiber` call.
|
|
30
|
-
#
|
|
31
|
-
# @return [LLM::Function::FiberGroup]
|
|
32
|
-
# Returns a new fiber group.
|
|
33
|
-
def initialize(fibers)
|
|
34
|
-
@fibers = fibers
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
# Returns whether any fiber in the group is still alive.
|
|
39
|
-
#
|
|
40
|
-
# This method checks if any of the fibers in the group are
|
|
41
|
-
# still running. It can be useful for monitoring concurrent
|
|
42
|
-
# tool execution without blocking.
|
|
43
|
-
#
|
|
44
|
-
# @example
|
|
45
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
46
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
47
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
48
|
-
# grp = ctx.functions.spawn(:fiber)
|
|
49
|
-
# while grp.alive?
|
|
50
|
-
# puts "Tools are still running..."
|
|
51
|
-
# sleep 1
|
|
52
|
-
# end
|
|
53
|
-
# ctx.talk(grp.wait)
|
|
54
|
-
#
|
|
55
|
-
# @return [Boolean]
|
|
56
|
-
# Returns true if any fiber in the group is still alive,
|
|
57
|
-
# false otherwise.
|
|
58
|
-
def alive?
|
|
59
|
-
@fibers.any?(&:alive?)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
##
|
|
63
|
-
# @return [nil]
|
|
64
|
-
def interrupt!
|
|
65
|
-
@fibers.each { _1.task.raise(LLM::Interrupt) if _1.task.alive? }
|
|
66
|
-
nil
|
|
67
|
-
end
|
|
68
|
-
alias_method :cancel!, :interrupt!
|
|
69
|
-
|
|
70
|
-
##
|
|
71
|
-
# Waits for all fibers in the group to finish and returns
|
|
72
|
-
# their {LLM::Function::Return} values.
|
|
73
|
-
#
|
|
74
|
-
# This method blocks until every fiber in the group has
|
|
75
|
-
# completed. If a fiber raised an exception, the exception
|
|
76
|
-
# is caught and wrapped in an {LLM::Function::Return} with
|
|
77
|
-
# error information.
|
|
78
|
-
#
|
|
79
|
-
# @example
|
|
80
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
81
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
82
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
83
|
-
# grp = ctx.functions.spawn(:fiber)
|
|
84
|
-
# returns = grp.wait
|
|
85
|
-
# # returns is now an array of LLM::Function::Return objects
|
|
86
|
-
# ctx.talk(returns)
|
|
87
|
-
#
|
|
88
|
-
# @return [Array<LLM::Function::Return>]
|
|
89
|
-
# Returns an array of function return values, in the same
|
|
90
|
-
# order as the original fibers.
|
|
91
|
-
def wait
|
|
92
|
-
@fibers.map do |fiber|
|
|
93
|
-
fiber.alive? ? scheduler.run : nil
|
|
94
|
-
fiber.value
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
alias_method :value, :wait
|
|
98
|
-
|
|
99
|
-
private
|
|
100
|
-
|
|
101
|
-
def scheduler
|
|
102
|
-
Fiber.scheduler
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class LLM::Function
|
|
4
|
-
##
|
|
5
|
-
# The {LLM::Function::TaskGroup} class wraps an array of
|
|
6
|
-
# `Async::Task` objects that are running {LLM::Function} calls
|
|
7
|
-
# concurrently using the async gem.
|
|
8
|
-
#
|
|
9
|
-
# This class provides the same interface as {LLM::Function::ThreadGroup}
|
|
10
|
-
# but uses async tasks for lightweight concurrency with automatic
|
|
11
|
-
# scheduling and I/O management.
|
|
12
|
-
#
|
|
13
|
-
# @example
|
|
14
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
15
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
16
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
17
|
-
# grp = ctx.functions.spawn(:task)
|
|
18
|
-
# # do other work while tools run...
|
|
19
|
-
# ctx.talk(grp.wait)
|
|
20
|
-
#
|
|
21
|
-
# @see LLM::Function::Array#spawn
|
|
22
|
-
# @see LLM::Function::ThreadGroup
|
|
23
|
-
# @see LLM::Function::FiberGroup
|
|
24
|
-
class TaskGroup
|
|
25
|
-
##
|
|
26
|
-
# Creates a new {LLM::Function::TaskGroup} from an array
|
|
27
|
-
# of async task objects.
|
|
28
|
-
#
|
|
29
|
-
# @param [Array<Async::Task>] tasks
|
|
30
|
-
# An array of async tasks, each running an `LLM::Function#spawn_async` call.
|
|
31
|
-
#
|
|
32
|
-
# @return [LLM::Function::TaskGroup]
|
|
33
|
-
# Returns a new task group.
|
|
34
|
-
def initialize(tasks)
|
|
35
|
-
@tasks = tasks
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
##
|
|
39
|
-
# Returns whether any task in the group is still alive.
|
|
40
|
-
#
|
|
41
|
-
# This method checks if any of the tasks in the group are
|
|
42
|
-
# still running. It can be useful for monitoring concurrent
|
|
43
|
-
# tool execution without blocking.
|
|
44
|
-
#
|
|
45
|
-
# @example
|
|
46
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
47
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
48
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
49
|
-
# grp = ctx.functions.spawn(:task)
|
|
50
|
-
# while grp.alive?
|
|
51
|
-
# puts "Tools are still running..."
|
|
52
|
-
# sleep 1
|
|
53
|
-
# end
|
|
54
|
-
# ctx.talk(grp.wait)
|
|
55
|
-
#
|
|
56
|
-
# @return [Boolean]
|
|
57
|
-
# Returns true if any task in the group is still alive,
|
|
58
|
-
# false otherwise.
|
|
59
|
-
def alive?
|
|
60
|
-
@tasks.any?(&:alive?)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
##
|
|
64
|
-
# @return [nil]
|
|
65
|
-
def interrupt!
|
|
66
|
-
@tasks.each(&:interrupt!)
|
|
67
|
-
nil
|
|
68
|
-
end
|
|
69
|
-
alias_method :cancel!, :interrupt!
|
|
70
|
-
|
|
71
|
-
##
|
|
72
|
-
# Waits for all tasks in the group to finish and returns
|
|
73
|
-
# their {LLM::Function::Return} values.
|
|
74
|
-
#
|
|
75
|
-
# This method blocks until every task in the group has
|
|
76
|
-
# completed. If a task raised an exception, the exception
|
|
77
|
-
# is caught and wrapped in an {LLM::Function::Return} with
|
|
78
|
-
# error information.
|
|
79
|
-
#
|
|
80
|
-
# @example
|
|
81
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
82
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
83
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
84
|
-
# grp = ctx.functions.spawn(:task)
|
|
85
|
-
# returns = grp.wait
|
|
86
|
-
# # returns is now an array of LLM::Function::Return objects
|
|
87
|
-
# ctx.talk(returns)
|
|
88
|
-
#
|
|
89
|
-
# @return [Array<LLM::Function::Return>]
|
|
90
|
-
# Returns an array of function return values, in the same
|
|
91
|
-
# order as the original tasks.
|
|
92
|
-
def wait
|
|
93
|
-
@tasks.map(&:wait)
|
|
94
|
-
end
|
|
95
|
-
alias_method :value, :wait
|
|
96
|
-
end
|
|
97
|
-
end
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class LLM::Function
|
|
4
|
-
##
|
|
5
|
-
# The {LLM::Function::ThreadGroup} class wraps an array of
|
|
6
|
-
# `Thread` objects that are running {LLM::Function} calls
|
|
7
|
-
# concurrently. It provides a single {#wait} method that
|
|
8
|
-
# collects the {LLM::Function::Return} values from those
|
|
9
|
-
# threads.
|
|
10
|
-
#
|
|
11
|
-
# This class is returned by {LLM::Function::Array#spawn}
|
|
12
|
-
# when you call `ctx.functions.spawn` on the collection
|
|
13
|
-
# returned by {LLM::Context#functions}. It is a lightweight
|
|
14
|
-
# wrapper that does not inherit from Ruby's built-in
|
|
15
|
-
# {::ThreadGroup}.
|
|
16
|
-
#
|
|
17
|
-
# @example
|
|
18
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
19
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
20
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
21
|
-
# grp = ctx.functions.spawn
|
|
22
|
-
# # do other work while tools run...
|
|
23
|
-
# ctx.talk(grp.wait)
|
|
24
|
-
#
|
|
25
|
-
# @see LLM::Function::Array#spawn
|
|
26
|
-
# @see LLM::Function::Array#wait
|
|
27
|
-
class ThreadGroup
|
|
28
|
-
##
|
|
29
|
-
# Creates a new {LLM::Function::ThreadGroup} from an array
|
|
30
|
-
# of `Thread` objects.
|
|
31
|
-
#
|
|
32
|
-
# @param [Array<Thread>] threads
|
|
33
|
-
# An array of threads, each running an {LLM::Function#spawn}
|
|
34
|
-
# call. The thread's `Thread#value` will be an
|
|
35
|
-
# {LLM::Function::Return}.
|
|
36
|
-
#
|
|
37
|
-
# @return [LLM::Function::ThreadGroup]
|
|
38
|
-
# Returns a new thread group.
|
|
39
|
-
def initialize(threads)
|
|
40
|
-
@threads = threads
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
# Returns whether any thread in the group is still alive.
|
|
45
|
-
#
|
|
46
|
-
# This method checks if any of the threads in the group are
|
|
47
|
-
# still running. It can be useful for monitoring concurrent
|
|
48
|
-
# tool execution without blocking.
|
|
49
|
-
#
|
|
50
|
-
# @example
|
|
51
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
52
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
53
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
54
|
-
# grp = ctx.functions.spawn
|
|
55
|
-
# while grp.alive?
|
|
56
|
-
# puts "Tools are still running..."
|
|
57
|
-
# sleep 1
|
|
58
|
-
# end
|
|
59
|
-
# ctx.talk(grp.wait)
|
|
60
|
-
#
|
|
61
|
-
# @return [Boolean]
|
|
62
|
-
# Returns true if any thread in the group is still alive,
|
|
63
|
-
# false otherwise.
|
|
64
|
-
def alive?
|
|
65
|
-
@threads.any?(&:alive?)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
##
|
|
69
|
-
# @return [nil]
|
|
70
|
-
def interrupt!
|
|
71
|
-
@threads.each { _1.task.raise LLM::Interrupt }
|
|
72
|
-
nil
|
|
73
|
-
end
|
|
74
|
-
alias_method :cancel!, :interrupt!
|
|
75
|
-
|
|
76
|
-
##
|
|
77
|
-
# Waits for all threads in the group to finish and returns
|
|
78
|
-
# their {LLM::Function::Return} values.
|
|
79
|
-
#
|
|
80
|
-
# This method blocks until every thread in the group has
|
|
81
|
-
# completed. If a thread raised an exception, the exception
|
|
82
|
-
# is caught and wrapped in an {LLM::Function::Return} with
|
|
83
|
-
# error information.
|
|
84
|
-
#
|
|
85
|
-
# @example
|
|
86
|
-
# llm = LLM.openai(key: ENV["KEY"])
|
|
87
|
-
# ctx = LLM::Context.new(llm, tools: [Weather, News, Stocks])
|
|
88
|
-
# ctx.talk "Summarize the weather, headlines, and stock price."
|
|
89
|
-
# grp = ctx.functions.spawn
|
|
90
|
-
# returns = grp.wait
|
|
91
|
-
# # returns is now an array of LLM::Function::Return objects
|
|
92
|
-
# ctx.talk(returns)
|
|
93
|
-
#
|
|
94
|
-
# @return [Array<LLM::Function::Return>]
|
|
95
|
-
# Returns an array of function return values, in the same
|
|
96
|
-
# order as the original threads.
|
|
97
|
-
def wait
|
|
98
|
-
@threads.map(&:value)
|
|
99
|
-
end
|
|
100
|
-
alias_method :value, :wait
|
|
101
|
-
end
|
|
102
|
-
end
|