llm.rb 12.0.0 → 12.2.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 +193 -1
- data/LICENSE +5 -4
- data/README.md +56 -18
- data/data/anthropic.json +85 -372
- data/data/bedrock.json +498 -3
- data/data/deepinfra.json +567 -47
- data/data/deepseek.json +4 -0
- data/data/google.json +54 -0
- data/data/mistral.json +968 -0
- data/data/openai.json +51 -0
- data/data/xai.json +67 -0
- data/data/zai.json +14 -0
- data/lib/llm/agent.rb +41 -1
- data/lib/llm/context.rb +9 -1
- data/lib/llm/function.rb +6 -0
- data/lib/llm/json_adapter.rb +29 -3
- data/lib/llm/provider.rb +3 -3
- data/lib/llm/providers/anthropic.rb +2 -2
- data/lib/llm/providers/google.rb +3 -1
- data/lib/llm/providers/llamacpp.rb +5 -5
- data/lib/llm/providers/mistral/request_adapter/completion.rb +122 -0
- data/lib/llm/providers/mistral/request_adapter.rb +20 -0
- data/lib/llm/providers/mistral.rb +96 -0
- data/lib/llm/repl/input.rb +64 -0
- data/lib/llm/repl/status.rb +30 -0
- data/lib/llm/repl/stream.rb +46 -0
- data/lib/llm/repl/transcript.rb +61 -0
- data/lib/llm/repl/window.rb +107 -0
- data/lib/llm/repl.rb +78 -0
- data/lib/llm/tools/chdir.rb +23 -0
- data/lib/llm/tools/git.rb +41 -0
- data/lib/llm/tools/mkdir.rb +32 -0
- data/lib/llm/tools/pwd.rb +20 -0
- data/lib/llm/tools/read_file.rb +40 -0
- data/lib/llm/tools/rg.rb +46 -0
- data/lib/llm/tools/shell.rb +48 -0
- data/lib/llm/tools/swap_text.rb +25 -0
- data/lib/llm/tools/write_file.rb +24 -0
- data/lib/llm/tools.rb +5 -0
- data/lib/llm/version.rb +1 -1
- data/lib/llm.rb +9 -0
- data/llm.gemspec +1 -1
- data/resources/deepdive.md +32 -0
- metadata +22 -2
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LLM::Repl
|
|
4
|
+
##
|
|
5
|
+
# The {LLM::Repl::Window LLM::Repl::Window} class draws the
|
|
6
|
+
# curses screen for the REPL.
|
|
7
|
+
# @api private
|
|
8
|
+
class Window
|
|
9
|
+
##
|
|
10
|
+
# @return [LLM::Repl::Status]
|
|
11
|
+
attr_reader :status
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# @return [LLM::Repl::Transcript]
|
|
15
|
+
attr_reader :transcript
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# @return [LLM::Repl::Input]
|
|
19
|
+
attr_reader :input
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @param [LLM::Repl::Status] status
|
|
23
|
+
# @param [LLM::Repl::Transcript] transcript
|
|
24
|
+
# @param [LLM::Repl::Input] input
|
|
25
|
+
# @return [LLM::Repl::Window]
|
|
26
|
+
def initialize(status, transcript, input)
|
|
27
|
+
@status = status
|
|
28
|
+
@transcript = transcript
|
|
29
|
+
@input = input
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# @yield
|
|
34
|
+
# @return [void]
|
|
35
|
+
def open
|
|
36
|
+
Curses.init_screen
|
|
37
|
+
Curses.cbreak
|
|
38
|
+
Curses.noecho
|
|
39
|
+
Curses.stdscr.keypad(true)
|
|
40
|
+
yield
|
|
41
|
+
ensure
|
|
42
|
+
Curses.close_screen
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# @return [void]
|
|
47
|
+
def redraw
|
|
48
|
+
Curses.clear
|
|
49
|
+
draw_status
|
|
50
|
+
draw_transcript
|
|
51
|
+
draw_input
|
|
52
|
+
Curses.refresh
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# @return [Integer]
|
|
57
|
+
def rows
|
|
58
|
+
[Curses.lines - 3, 1].max
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# @return [Object]
|
|
63
|
+
def getch
|
|
64
|
+
Curses.getch
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
##
|
|
68
|
+
# @return [void]
|
|
69
|
+
def scroll_up
|
|
70
|
+
transcript.scroll_up(rows)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
# @return [void]
|
|
75
|
+
def scroll_down
|
|
76
|
+
transcript.scroll_down
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def draw_status
|
|
82
|
+
Curses.setpos(0, 0)
|
|
83
|
+
Curses.addstr(status.to_s)
|
|
84
|
+
provider = status.provider.to_s
|
|
85
|
+
Curses.setpos(0, [columns - provider.length, 0].max)
|
|
86
|
+
Curses.addstr(provider)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def draw_transcript
|
|
90
|
+
visible = transcript.visible(rows)
|
|
91
|
+
visible.each_with_index do |row, index|
|
|
92
|
+
Curses.setpos(index + 2, 0)
|
|
93
|
+
Curses.addstr(row)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def draw_input
|
|
98
|
+
Curses.setpos(Curses.lines - 1, 0)
|
|
99
|
+
Curses.clrtoeol
|
|
100
|
+
Curses.addstr(input.to_s)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def columns
|
|
104
|
+
Curses.cols
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
data/lib/llm/repl.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
LLM.require "curses"
|
|
4
|
+
|
|
5
|
+
module LLM
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Repl LLM::Repl} class provides a small
|
|
8
|
+
# read-eval-print loop around an instance of
|
|
9
|
+
# {LLM::Agent LLM::Agent}.
|
|
10
|
+
#
|
|
11
|
+
# It can be used to keep talking to an agent after it
|
|
12
|
+
# has been set up or has performed a task. This can be
|
|
13
|
+
# useful when you want to confirm the agent handled the
|
|
14
|
+
# task correctly, or for it to correct course after a
|
|
15
|
+
# mistake was made.
|
|
16
|
+
class Repl
|
|
17
|
+
require_relative "repl/window"
|
|
18
|
+
require_relative "repl/status"
|
|
19
|
+
require_relative "repl/transcript"
|
|
20
|
+
require_relative "repl/input"
|
|
21
|
+
require_relative "repl/stream"
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# @param [LLM::Agent] agent
|
|
25
|
+
# @return [LLM::Repl]
|
|
26
|
+
def initialize(agent)
|
|
27
|
+
@agent = agent
|
|
28
|
+
@provider = agent.llm.name
|
|
29
|
+
@status = Status.new(@provider)
|
|
30
|
+
@transcript = Transcript.new
|
|
31
|
+
@input = Input.new(@provider)
|
|
32
|
+
@window = Window.new(@status, @transcript, @input)
|
|
33
|
+
@stream = Stream.new(self)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# @return [void]
|
|
38
|
+
def start
|
|
39
|
+
window.open do
|
|
40
|
+
loop do
|
|
41
|
+
window.redraw
|
|
42
|
+
text = input.readline(window)
|
|
43
|
+
break if text.nil?
|
|
44
|
+
next if text.empty?
|
|
45
|
+
status.text = "thinking"
|
|
46
|
+
write("user: #{text}\n")
|
|
47
|
+
window.redraw
|
|
48
|
+
write("agent: ")
|
|
49
|
+
agent.talk(text, stream:)
|
|
50
|
+
status.text = "idle"
|
|
51
|
+
write("\n\n")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# @param [String] chars
|
|
58
|
+
# @return [void]
|
|
59
|
+
def write(chars)
|
|
60
|
+
transcript.write(chars)
|
|
61
|
+
window.redraw
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# @param [String] value
|
|
66
|
+
# @return [void]
|
|
67
|
+
def status=(value)
|
|
68
|
+
status.text = value
|
|
69
|
+
window.redraw
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
attr_reader :agent, :provider, :stream,
|
|
75
|
+
:status, :transcript, :input,
|
|
76
|
+
:window
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::Chdir LLM::Tool::Chdir} class implements
|
|
8
|
+
# a tool that can change the current working directory.
|
|
9
|
+
class Chdir < self
|
|
10
|
+
name "chdir"
|
|
11
|
+
description "change the current working directory"
|
|
12
|
+
parameter :path, String, "the new working directory"
|
|
13
|
+
required %i[path]
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# @param [String] path
|
|
17
|
+
# @return [Hash]
|
|
18
|
+
def call(path:)
|
|
19
|
+
Dir.chdir(path)
|
|
20
|
+
{ok: true, cwd: path}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::Git LLM::Tool::Git} class implements
|
|
8
|
+
# a tool that can perform a select number of git actions.
|
|
9
|
+
# The actions it can perform are read-only - at least for
|
|
10
|
+
# the time being.
|
|
11
|
+
class Git < self
|
|
12
|
+
name "git"
|
|
13
|
+
description "perform an action with git"
|
|
14
|
+
parameter :action, Enum["log", "diff", "commit", "checkout", "branch", "show"], "the git operation to perform"
|
|
15
|
+
parameter :arguments, Array[String], "one or more arguments for the git action"
|
|
16
|
+
required %i[action]
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# @param [String] path
|
|
20
|
+
# @param [Integer] start
|
|
21
|
+
# @param [Integer] stop
|
|
22
|
+
# @return [Hash]
|
|
23
|
+
def call(action:, arguments: nil)
|
|
24
|
+
command = spawn(action:, arguments:)
|
|
25
|
+
{ok: command.success?, stdout: command.stdout, stderr: command.stderr}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def spawn(action:, arguments:)
|
|
31
|
+
Command
|
|
32
|
+
.new("git")
|
|
33
|
+
.argv(action)
|
|
34
|
+
.argv(*[*arguments])
|
|
35
|
+
.spawn
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
LLM.require "test-cmd.rb"
|
|
39
|
+
Command = Test::Cmd
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LLM::Tool
|
|
4
|
+
##
|
|
5
|
+
# The {LLM::Tool::Mkdir LLM::Tool::Mkdir} class implements
|
|
6
|
+
# a tool that can create a tree of new directories.
|
|
7
|
+
class Mkdir < self
|
|
8
|
+
name "mkdir"
|
|
9
|
+
description "create a new directory"
|
|
10
|
+
parameter :path, String, "the path to the directory"
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# @param [String] path
|
|
14
|
+
# @return [Hash]
|
|
15
|
+
def call(path:)
|
|
16
|
+
command = spawn(path:)
|
|
17
|
+
{ok: command.success?, stdout: command.stdout, stderr: command.stderr}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def spawn(path:)
|
|
23
|
+
Command
|
|
24
|
+
.new("mkdir")
|
|
25
|
+
.argv("-p", path)
|
|
26
|
+
.spawn
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
LLM.require "test-cmd.rb"
|
|
30
|
+
Command = Test::Cmd
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::Pwd LLM::Tool::Pwd} class implements
|
|
8
|
+
# a tool that can reveal the current working directory.
|
|
9
|
+
class Pwd < self
|
|
10
|
+
name "pwd"
|
|
11
|
+
description "returns the current working directory"
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# @param [String] path
|
|
15
|
+
# @return [Hash]
|
|
16
|
+
def call
|
|
17
|
+
{ok: true, cwd: Dir.getwd}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::ReadFile LLM::Tool::ReadFile} class implements
|
|
8
|
+
# a tool that can read the contents of a file. The tool accepts
|
|
9
|
+
# two optional offsets: a start line, and a stop line. Without
|
|
10
|
+
# either the entire file contents are read into memory.
|
|
11
|
+
class ReadFile < self
|
|
12
|
+
name "read-file"
|
|
13
|
+
description "read the contents of a file"
|
|
14
|
+
parameter :path, String, "the path to the file"
|
|
15
|
+
parameter :start, Integer, "start line number"
|
|
16
|
+
parameter :stop, Integer, "stop line number"
|
|
17
|
+
required %i[path]
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# @param [String] path
|
|
21
|
+
# @param [Integer] start
|
|
22
|
+
# @param [Integer] stop
|
|
23
|
+
# @return [Hash]
|
|
24
|
+
def call(path:, start: 1, stop: -1)
|
|
25
|
+
content, cursor = nil, 1
|
|
26
|
+
File.open(path, "r") do |f|
|
|
27
|
+
while cursor < start
|
|
28
|
+
f.gets
|
|
29
|
+
cursor += 1
|
|
30
|
+
end
|
|
31
|
+
if stop == -1
|
|
32
|
+
content = f.read
|
|
33
|
+
else
|
|
34
|
+
content = start.upto(stop).map { f.gets }.join
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
{ok: true, content:}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/llm/tools/rg.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::Rg LLM::Tool::Rg} class implements
|
|
8
|
+
# a frontend to the popular 'rg' tool. The tool can
|
|
9
|
+
# recursively search the current working directory
|
|
10
|
+
# for one or more patterns.
|
|
11
|
+
class Rg < self
|
|
12
|
+
name "rg"
|
|
13
|
+
description "recursively search the current directory for lines matching a pattern"
|
|
14
|
+
parameter :patterns, Array[String], "one or more search patterns"
|
|
15
|
+
parameter :path, String, "the path where the search is performed (default is cwd)"
|
|
16
|
+
required %i[patterns]
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# @param [String] pattern
|
|
20
|
+
# @return [Hash]
|
|
21
|
+
def call(patterns:, path: Dir.getwd)
|
|
22
|
+
validate!(patterns:, path:)
|
|
23
|
+
command = spawn(patterns:, path:)
|
|
24
|
+
{ok: command.success?, stdout: command.stdout, stderr: command.stderr}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate!(patterns:, path:)
|
|
30
|
+
if path == "/"
|
|
31
|
+
raise RuntimeError, "you can't search from the root of the filesystem"
|
|
32
|
+
elsif patterns == ["."]
|
|
33
|
+
raise RuntimeError, "narrow your search"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def spawn(patterns:, path:)
|
|
38
|
+
Command.new("rg")
|
|
39
|
+
.argv(*[*patterns].flat_map { ["-e", _1] }, path)
|
|
40
|
+
.spawn
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
LLM.require "test-cmd.rb"
|
|
44
|
+
Command = Test::Cmd
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# frozen_string_literal
|
|
4
|
+
|
|
5
|
+
class LLM::Tool
|
|
6
|
+
##
|
|
7
|
+
# The {LLM::Tool::Shell} class implements a tool that can
|
|
8
|
+
# spawn a command. That can be dangerous given a low-quality
|
|
9
|
+
# model, or a high-quality model that simply makes a bad
|
|
10
|
+
# decision. The risk can be reduced through a confirmation
|
|
11
|
+
# step such as {LLM::Agent.confirm LLM::Agent.confirm}, or
|
|
12
|
+
# by managing the tool loop manually through
|
|
13
|
+
# {LLM::Context LLM::Context}.
|
|
14
|
+
class Shell < self
|
|
15
|
+
name "shell"
|
|
16
|
+
description "run a shell command"
|
|
17
|
+
parameter :name, String, "the command name"
|
|
18
|
+
parameter :arguments, Array[String], "one or more command arguments"
|
|
19
|
+
required %i[name]
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @param [String] name
|
|
23
|
+
# The name of a command
|
|
24
|
+
# @param [Array<String>] arguments
|
|
25
|
+
# One or more command-line arguments
|
|
26
|
+
# @return [Hash]
|
|
27
|
+
def call(name:, arguments: nil)
|
|
28
|
+
command = spawn(name:, arguments:)
|
|
29
|
+
{ok: command.success?, stdout: command.stdout, stderr: command.stderr}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# @param [String] name
|
|
36
|
+
# @param [Array<String>] arguments
|
|
37
|
+
# @return [Command]
|
|
38
|
+
def spawn(name:, arguments:)
|
|
39
|
+
Command
|
|
40
|
+
.new(name)
|
|
41
|
+
.argv(*[*arguments])
|
|
42
|
+
.spawn
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
LLM.require "test-cmd.rb"
|
|
46
|
+
Command = Test::Cmd
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LLM::Tool
|
|
4
|
+
##
|
|
5
|
+
# The {LLM::Tool::SwapText LLM::Tool::SwapText} class
|
|
6
|
+
# implements a tool that can substitute one piece of
|
|
7
|
+
# text for another piece of text in a given file.
|
|
8
|
+
class SwapText < self
|
|
9
|
+
name "swap-text"
|
|
10
|
+
description "Replace an exact snippet in a file"
|
|
11
|
+
parameter :path, String, "Path to file"
|
|
12
|
+
parameter :before, String, "Exact text to replace"
|
|
13
|
+
parameter :after, String, "Replacement text"
|
|
14
|
+
parameter :expected_count, Integer, "How many matches should be replaced"
|
|
15
|
+
required %i[path before after]
|
|
16
|
+
|
|
17
|
+
def call(path:, before:, after:, expected_count: 1)
|
|
18
|
+
content = File.read(path)
|
|
19
|
+
count = content.scan(before).length
|
|
20
|
+
raise "expected #{expected_count} match(es), found #{count}" unless count == expected_count.to_i
|
|
21
|
+
File.write(path, content.sub(before, after))
|
|
22
|
+
{ok: true, replaced: count}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LLM::Tool
|
|
4
|
+
##
|
|
5
|
+
# The {LLM::Tool::WriteFile LLM::Tool::WriteFile} class
|
|
6
|
+
# implements a tool that can write a given string to a
|
|
7
|
+
# given file path.
|
|
8
|
+
class WriteFile < self
|
|
9
|
+
name "write-file"
|
|
10
|
+
description "write to a file"
|
|
11
|
+
parameter :path, String, "The file path"
|
|
12
|
+
parameter :content, String, "The file content"
|
|
13
|
+
required %i[path content]
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# @param [String] path
|
|
17
|
+
# @param [String] content
|
|
18
|
+
# @return [Hash]
|
|
19
|
+
def call(path:, content:)
|
|
20
|
+
File.open(path, "w") { _1.write(content) }
|
|
21
|
+
{ok: true}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/llm/tools.rb
ADDED
data/lib/llm/version.rb
CHANGED
data/lib/llm.rb
CHANGED
|
@@ -180,6 +180,15 @@ module LLM
|
|
|
180
180
|
LLM::XAI.new(**)
|
|
181
181
|
end
|
|
182
182
|
|
|
183
|
+
##
|
|
184
|
+
# @param key (see LLM::Mistral#initialize)
|
|
185
|
+
# @param host (see LLM::Mistral#initialize)
|
|
186
|
+
# @return (see LLM::Mistral#initialize)
|
|
187
|
+
def mistral(**)
|
|
188
|
+
lock(:require) { require_relative "llm/providers/mistral" unless defined?(LLM::Mistral) }
|
|
189
|
+
LLM::Mistral.new(**)
|
|
190
|
+
end
|
|
191
|
+
|
|
183
192
|
##
|
|
184
193
|
# @param key (see LLM::ZAI#initialize)
|
|
185
194
|
# @param host (see LLM::ZAI#initialize)
|
data/llm.gemspec
CHANGED
|
@@ -5,7 +5,7 @@ require_relative "lib/llm/version"
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "llm.rb"
|
|
7
7
|
spec.version = LLM::VERSION
|
|
8
|
-
spec.authors = ["
|
|
8
|
+
spec.authors = ["robert", "Antar Azri", "Rodrigo Serrano"]
|
|
9
9
|
spec.email = ["robert@r.uby.dev"]
|
|
10
10
|
|
|
11
11
|
spec.summary = "Ruby's capable AI runtime"
|
data/resources/deepdive.md
CHANGED
|
@@ -54,6 +54,8 @@ features that didn't make it into the homepage documentation.
|
|
|
54
54
|
- [Tracer](#tracer)
|
|
55
55
|
- [Provider-wide tracer](#provider-wide-tracer)
|
|
56
56
|
- [Agent-local tracer](#agent-local-tracer)
|
|
57
|
+
- [REPL](#repl)
|
|
58
|
+
- [LLM::Agent](#llmagent)
|
|
57
59
|
- [Images](#images)
|
|
58
60
|
- [Generation](#generation)
|
|
59
61
|
- [Edits](#edits)
|
|
@@ -802,6 +804,36 @@ agent = LLM::Agent.new(llm, tracer: LLM::Tracer::Logger.new(llm, path: "deepseek
|
|
|
802
804
|
|
|
803
805
|
[Back to top](#table-of-contents)
|
|
804
806
|
|
|
807
|
+
## REPL
|
|
808
|
+
|
|
809
|
+
During the development and operation of agents it can often
|
|
810
|
+
be helpful to drop into a read-eval-print loop. This gives
|
|
811
|
+
you a simple way to confirm the work was successful, inspect
|
|
812
|
+
anything that went wrong (for example, tool call errors), and
|
|
813
|
+
keep talking to the same agent so you can learn about its
|
|
814
|
+
decision-making process and make improvements for future runs.
|
|
815
|
+
It can also be used to ask the agent to correct any errors
|
|
816
|
+
that might have made.
|
|
817
|
+
|
|
818
|
+
##### LLM::Agent
|
|
819
|
+
|
|
820
|
+
The [LLM::Agent#repl](https://r.uby.dev/api-docs/llm.rb/LLM/Agent.html#repl-instance_method)
|
|
821
|
+
method requires the [curses](https://github.com/ruby/curses)
|
|
822
|
+
gem to be installed and available for require. It is an
|
|
823
|
+
optional dependency that only becomes required when you
|
|
824
|
+
call the [LLM::Agent#repl](https://r.uby.dev/api-docs/llm.rb/LLM/Agent.html#repl-instance_method)
|
|
825
|
+
method.
|
|
826
|
+
|
|
827
|
+
```ruby
|
|
828
|
+
require "llm"
|
|
829
|
+
|
|
830
|
+
llm = LLM.deepseek(key: ENV["KEY"])
|
|
831
|
+
agent = LLM::Agent.new(llm)
|
|
832
|
+
agent.repl
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
[Back to top](#table-of-contents)
|
|
836
|
+
|
|
805
837
|
## Images
|
|
806
838
|
|
|
807
839
|
The OpenAI, Google, xAI, DeepInfra, and DeepSeek providers have
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 12.
|
|
4
|
+
version: 12.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- robert
|
|
8
8
|
- Antar Azri
|
|
9
9
|
- Rodrigo Serrano
|
|
10
10
|
bindir: bin
|
|
@@ -293,6 +293,7 @@ files:
|
|
|
293
293
|
- data/deepinfra.json
|
|
294
294
|
- data/deepseek.json
|
|
295
295
|
- data/google.json
|
|
296
|
+
- data/mistral.json
|
|
296
297
|
- data/openai.json
|
|
297
298
|
- data/xai.json
|
|
298
299
|
- data/zai.json
|
|
@@ -419,6 +420,9 @@ files:
|
|
|
419
420
|
- lib/llm/providers/google/stream_parser.rb
|
|
420
421
|
- lib/llm/providers/google/utils.rb
|
|
421
422
|
- lib/llm/providers/llamacpp.rb
|
|
423
|
+
- lib/llm/providers/mistral.rb
|
|
424
|
+
- lib/llm/providers/mistral/request_adapter.rb
|
|
425
|
+
- lib/llm/providers/mistral/request_adapter/completion.rb
|
|
422
426
|
- lib/llm/providers/ollama.rb
|
|
423
427
|
- lib/llm/providers/ollama/error_handler.rb
|
|
424
428
|
- lib/llm/providers/ollama/models.rb
|
|
@@ -459,6 +463,12 @@ files:
|
|
|
459
463
|
- lib/llm/providers/xai/images.rb
|
|
460
464
|
- lib/llm/providers/zai.rb
|
|
461
465
|
- lib/llm/registry.rb
|
|
466
|
+
- lib/llm/repl.rb
|
|
467
|
+
- lib/llm/repl/input.rb
|
|
468
|
+
- lib/llm/repl/status.rb
|
|
469
|
+
- lib/llm/repl/stream.rb
|
|
470
|
+
- lib/llm/repl/transcript.rb
|
|
471
|
+
- lib/llm/repl/window.rb
|
|
462
472
|
- lib/llm/response.rb
|
|
463
473
|
- lib/llm/schema.rb
|
|
464
474
|
- lib/llm/schema/all_of.rb
|
|
@@ -485,6 +495,16 @@ files:
|
|
|
485
495
|
- lib/llm/stream/queue.rb
|
|
486
496
|
- lib/llm/tool.rb
|
|
487
497
|
- lib/llm/tool/param.rb
|
|
498
|
+
- lib/llm/tools.rb
|
|
499
|
+
- lib/llm/tools/chdir.rb
|
|
500
|
+
- lib/llm/tools/git.rb
|
|
501
|
+
- lib/llm/tools/mkdir.rb
|
|
502
|
+
- lib/llm/tools/pwd.rb
|
|
503
|
+
- lib/llm/tools/read_file.rb
|
|
504
|
+
- lib/llm/tools/rg.rb
|
|
505
|
+
- lib/llm/tools/shell.rb
|
|
506
|
+
- lib/llm/tools/swap_text.rb
|
|
507
|
+
- lib/llm/tools/write_file.rb
|
|
488
508
|
- lib/llm/tracer.rb
|
|
489
509
|
- lib/llm/tracer/logger.rb
|
|
490
510
|
- lib/llm/tracer/null.rb
|