llm.rb 11.3.1 → 12.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 +242 -1
- data/LICENSE +92 -17
- data/README.md +204 -623
- data/data/anthropic.json +433 -249
- data/data/bedrock.json +2097 -1055
- data/data/deepinfra.json +993 -0
- data/data/deepseek.json +53 -28
- data/data/google.json +389 -771
- data/data/openai.json +1053 -771
- data/data/xai.json +133 -292
- data/data/zai.json +249 -141
- data/lib/llm/active_record/acts_as_agent.rb +3 -41
- data/lib/llm/active_record/acts_as_llm.rb +18 -0
- data/lib/llm/active_record.rb +3 -3
- data/lib/llm/context.rb +9 -5
- data/lib/llm/contract/completion.rb +2 -2
- data/lib/llm/provider.rb +2 -2
- data/lib/llm/providers/deepinfra/audio.rb +66 -0
- data/lib/llm/providers/deepinfra/images.rb +90 -0
- data/lib/llm/providers/deepinfra/response_adapter.rb +36 -0
- data/lib/llm/providers/deepinfra.rb +100 -0
- data/lib/llm/providers/deepseek/images.rb +109 -0
- data/lib/llm/providers/deepseek/request_adapter.rb +32 -0
- data/lib/llm/providers/deepseek/response_adapter/image.rb +9 -0
- data/lib/llm/providers/deepseek/response_adapter.rb +29 -0
- data/lib/llm/providers/deepseek.rb +4 -2
- data/lib/llm/providers/google/request_adapter.rb +22 -5
- data/lib/llm/providers/google.rb +4 -4
- data/lib/llm/providers/openai/audio.rb +6 -2
- data/lib/llm/providers/openai/images.rb +9 -50
- data/lib/llm/providers/openai/request_adapter/respond.rb +38 -4
- data/lib/llm/providers/openai/response_adapter/audio.rb +5 -1
- data/lib/llm/providers/openai/response_adapter/completion.rb +1 -1
- data/lib/llm/providers/openai/response_adapter/image.rb +0 -4
- data/lib/llm/providers/openai/responses.rb +1 -0
- data/lib/llm/providers/openai/stream_parser.rb +5 -6
- data/lib/llm/providers/openai.rb +2 -2
- data/lib/llm/providers/xai/images.rb +49 -26
- data/lib/llm/providers/xai.rb +2 -2
- data/lib/llm/response.rb +10 -0
- data/lib/llm/schema/leaf.rb +7 -1
- data/lib/llm/schema/renderer.rb +121 -0
- data/lib/llm/schema.rb +30 -0
- data/lib/llm/sequel/agent.rb +2 -43
- data/lib/llm/sequel/plugin.rb +25 -7
- data/lib/llm/tracer/telemetry.rb +4 -6
- data/lib/llm/tracer.rb +9 -21
- data/lib/llm/transport/execution.rb +16 -1
- data/lib/llm/transport/net_http_adapter.rb +1 -1
- data/lib/llm/uridata.rb +16 -0
- data/lib/llm/version.rb +1 -1
- data/lib/llm.rb +9 -0
- data/llm.gemspec +5 -18
- data/resources/deepdive.md +798 -264
- metadata +15 -18
- data/lib/llm/tracer/langsmith.rb +0 -144
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:
|
|
4
|
+
version: 12.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- bsdrobert
|
|
8
8
|
- Antar Azri
|
|
9
9
|
- Rodrigo Serrano
|
|
10
10
|
bindir: bin
|
|
@@ -277,20 +277,8 @@ dependencies:
|
|
|
277
277
|
- - "~>"
|
|
278
278
|
- !ruby/object:Gem::Version
|
|
279
279
|
version: '1.18'
|
|
280
|
-
description:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
It runs on Ruby's standard library by default. loads optional pieces
|
|
284
|
-
only when needed, and offers a single runtime for providers, agents,
|
|
285
|
-
tools, skills, MCP, A2A (Agent2Agent), RAG (vector stores & embeddings),
|
|
286
|
-
streaming, files, and persisted state. As a bonus, llm.rb is also available
|
|
287
|
-
for mruby.
|
|
288
|
-
|
|
289
|
-
It supports OpenAI, OpenAI-compatible endpoints, Anthropic, Google
|
|
290
|
-
Gemini, DeepSeek, xAI, Z.ai, AWS Bedrock, Ollama, and llama.cpp. It
|
|
291
|
-
also includes built-in ActiveRecord and Sequel support, plus concurrent
|
|
292
|
-
tool execution through threads, tasks (via async gem), fibers, ractors,
|
|
293
|
-
and fork (via xchan.rb gem).
|
|
280
|
+
description: llm.rb is not a library, framework or toolkit but an advanced runtime
|
|
281
|
+
for building highly capable AI applications on CRuby.
|
|
294
282
|
email:
|
|
295
283
|
- robert@r.uby.dev
|
|
296
284
|
executables: []
|
|
@@ -302,6 +290,7 @@ files:
|
|
|
302
290
|
- README.md
|
|
303
291
|
- data/anthropic.json
|
|
304
292
|
- data/bedrock.json
|
|
293
|
+
- data/deepinfra.json
|
|
305
294
|
- data/deepseek.json
|
|
306
295
|
- data/google.json
|
|
307
296
|
- data/openai.json
|
|
@@ -401,9 +390,16 @@ files:
|
|
|
401
390
|
- lib/llm/providers/bedrock/signature.rb
|
|
402
391
|
- lib/llm/providers/bedrock/stream_decoder.rb
|
|
403
392
|
- lib/llm/providers/bedrock/stream_parser.rb
|
|
393
|
+
- lib/llm/providers/deepinfra.rb
|
|
394
|
+
- lib/llm/providers/deepinfra/audio.rb
|
|
395
|
+
- lib/llm/providers/deepinfra/images.rb
|
|
396
|
+
- lib/llm/providers/deepinfra/response_adapter.rb
|
|
404
397
|
- lib/llm/providers/deepseek.rb
|
|
398
|
+
- lib/llm/providers/deepseek/images.rb
|
|
405
399
|
- lib/llm/providers/deepseek/request_adapter.rb
|
|
406
400
|
- lib/llm/providers/deepseek/request_adapter/completion.rb
|
|
401
|
+
- lib/llm/providers/deepseek/response_adapter.rb
|
|
402
|
+
- lib/llm/providers/deepseek/response_adapter/image.rb
|
|
407
403
|
- lib/llm/providers/google.rb
|
|
408
404
|
- lib/llm/providers/google/audio.rb
|
|
409
405
|
- lib/llm/providers/google/error_handler.rb
|
|
@@ -477,6 +473,7 @@ files:
|
|
|
477
473
|
- lib/llm/schema/object.rb
|
|
478
474
|
- lib/llm/schema/one_of.rb
|
|
479
475
|
- lib/llm/schema/parser.rb
|
|
476
|
+
- lib/llm/schema/renderer.rb
|
|
480
477
|
- lib/llm/schema/string.rb
|
|
481
478
|
- lib/llm/schema/version.rb
|
|
482
479
|
- lib/llm/sequel/agent.rb
|
|
@@ -489,7 +486,6 @@ files:
|
|
|
489
486
|
- lib/llm/tool.rb
|
|
490
487
|
- lib/llm/tool/param.rb
|
|
491
488
|
- lib/llm/tracer.rb
|
|
492
|
-
- lib/llm/tracer/langsmith.rb
|
|
493
489
|
- lib/llm/tracer/logger.rb
|
|
494
490
|
- lib/llm/tracer/null.rb
|
|
495
491
|
- lib/llm/tracer/telemetry.rb
|
|
@@ -505,6 +501,7 @@ files:
|
|
|
505
501
|
- lib/llm/transport/response/http.rb
|
|
506
502
|
- lib/llm/transport/stream_decoder.rb
|
|
507
503
|
- lib/llm/transport/utils.rb
|
|
504
|
+
- lib/llm/uridata.rb
|
|
508
505
|
- lib/llm/usage.rb
|
|
509
506
|
- lib/llm/utils.rb
|
|
510
507
|
- lib/llm/version.rb
|
|
@@ -514,7 +511,7 @@ files:
|
|
|
514
511
|
- resources/deepdive.md
|
|
515
512
|
homepage: https://r.uby.dev/llm/
|
|
516
513
|
licenses:
|
|
517
|
-
-
|
|
514
|
+
- BUSL-1.1
|
|
518
515
|
metadata:
|
|
519
516
|
homepage_uri: https://r.uby.dev/llm/
|
|
520
517
|
source_code_uri: https://github.com/r-uby-dev/llm.rb
|
data/lib/llm/tracer/langsmith.rb
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module LLM
|
|
4
|
-
##
|
|
5
|
-
# LangSmith-specific tracer built on top of Telemetry. Supports extra
|
|
6
|
-
# inputs/outputs and metadata on traces and spans via {#merge_extra} and
|
|
7
|
-
# {#start_trace}(metadata:).
|
|
8
|
-
#
|
|
9
|
-
# @example Constructor metadata and tags
|
|
10
|
-
# llm.tracer = LLM::Tracer::Langsmith.new(
|
|
11
|
-
# llm,
|
|
12
|
-
# session_id: "123e4567-e89b-12d3-a456-426614174000",
|
|
13
|
-
# metadata: {env: "dev"},
|
|
14
|
-
# tags: ["changelog"]
|
|
15
|
-
# )
|
|
16
|
-
#
|
|
17
|
-
# @example Per-request extra metadata and inputs (e.g. from chatbot)
|
|
18
|
-
# tracer.merge_extra(
|
|
19
|
-
# metadata: { turn_id: turn.id, component: "chatbot_message_stream" },
|
|
20
|
-
# inputs: { "gen_ai.input.messages" => messages_json }
|
|
21
|
-
# )
|
|
22
|
-
# bot.chat(prompt)
|
|
23
|
-
#
|
|
24
|
-
# @example Trace-level metadata via start_trace
|
|
25
|
-
# tracer.start_trace(trace_group_id: turn.id, name: "chatbot.turn", metadata: { turn_id: turn.id })
|
|
26
|
-
class Tracer::Langsmith < Tracer::Telemetry
|
|
27
|
-
THREAD_EXTRA_KEY = :llm_langsmith_extra
|
|
28
|
-
|
|
29
|
-
UUID = /\A
|
|
30
|
-
[0-9a-f]{8}-
|
|
31
|
-
[0-9a-f]{4}-
|
|
32
|
-
[1-5][0-9a-f]{3}-
|
|
33
|
-
[89ab][0-9a-f]{3}-
|
|
34
|
-
[0-9a-f]{12}
|
|
35
|
-
\z/ix
|
|
36
|
-
|
|
37
|
-
def initialize(provider, options = {})
|
|
38
|
-
super
|
|
39
|
-
setup_langsmith!(options)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def start_trace(trace_group_id: nil, name: "llm", attributes: {}, metadata: nil)
|
|
43
|
-
merge_extra(metadata: metadata) if metadata && !metadata.empty?
|
|
44
|
-
super
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def stop_trace
|
|
48
|
-
clear_thread_extra!
|
|
49
|
-
super
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def merge_extra(metadata: nil, inputs: nil, outputs: nil)
|
|
53
|
-
store = thread_extra
|
|
54
|
-
store[:metadata].merge!(metadata) if metadata && !metadata.empty?
|
|
55
|
-
store[:inputs].merge!(inputs) if inputs && !inputs.empty?
|
|
56
|
-
store[:outputs].merge!(outputs) if outputs && !outputs.empty?
|
|
57
|
-
self
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def current_extra
|
|
61
|
-
store = thread_extra
|
|
62
|
-
{
|
|
63
|
-
metadata: store[:metadata].dup,
|
|
64
|
-
inputs: store[:inputs].dup,
|
|
65
|
-
outputs: store[:outputs].dup
|
|
66
|
-
}
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def consume_extra_inputs
|
|
70
|
-
thread_extra[:inputs].tap { thread_extra[:inputs] = {} }
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def consume_extra_outputs
|
|
74
|
-
thread_extra[:outputs].tap { thread_extra[:outputs] = {} }
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
private
|
|
78
|
-
|
|
79
|
-
def trace_attributes(span_kind:)
|
|
80
|
-
attributes = {}
|
|
81
|
-
unless @langsmith_session_id.to_s.empty?
|
|
82
|
-
attributes["langsmith.trace.session_id"] = @langsmith_session_id
|
|
83
|
-
end
|
|
84
|
-
merged_metadata = @langsmith_metadata.merge(thread_extra[:metadata])
|
|
85
|
-
merged_metadata.each do |key, value|
|
|
86
|
-
next if value.nil?
|
|
87
|
-
|
|
88
|
-
attr_key = key.to_s.start_with?("langsmith.metadata.") ? key.to_s : "langsmith.metadata.#{key}"
|
|
89
|
-
attributes[attr_key] = serialize_langsmith_value(value)
|
|
90
|
-
end
|
|
91
|
-
unless @langsmith_tags.empty?
|
|
92
|
-
attributes["langsmith.span.tags"] = @langsmith_tags.map(&:to_s).join(",")
|
|
93
|
-
end
|
|
94
|
-
attributes["langsmith.span.kind"] = span_kind
|
|
95
|
-
attributes
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def thread_extra
|
|
99
|
-
Thread.current[THREAD_EXTRA_KEY] ||= {
|
|
100
|
-
metadata: {},
|
|
101
|
-
inputs: {},
|
|
102
|
-
outputs: {}
|
|
103
|
-
}
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def clear_thread_extra!
|
|
107
|
-
Thread.current[THREAD_EXTRA_KEY] = nil
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def setup_langsmith!(options)
|
|
111
|
-
options ||= {}
|
|
112
|
-
@langsmith_metadata = options[:metadata] || {}
|
|
113
|
-
@langsmith_session_id = normalize_langsmith_session_id(
|
|
114
|
-
options[:session_id],
|
|
115
|
-
metadata: @langsmith_metadata
|
|
116
|
-
)
|
|
117
|
-
@langsmith_tags = options[:tags] || []
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def serialize_langsmith_value(value)
|
|
121
|
-
case value
|
|
122
|
-
when String, Numeric, TrueClass, FalseClass
|
|
123
|
-
value
|
|
124
|
-
else
|
|
125
|
-
LLM.json.dump(value)
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def normalize_langsmith_session_id(session_id, metadata:)
|
|
130
|
-
raw = session_id&.to_s
|
|
131
|
-
return nil if raw.to_s.empty?
|
|
132
|
-
return raw if uuid?(raw)
|
|
133
|
-
|
|
134
|
-
# Keep arbitrary identifiers in metadata instead of forcing
|
|
135
|
-
# them into langsmith.trace.session_id, which expects a UUID.
|
|
136
|
-
metadata[:session_id] ||= raw
|
|
137
|
-
nil
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def uuid?(value)
|
|
141
|
-
value.match?(UUID)
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|