llm.rb 11.3.0 → 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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +270 -1
  3. data/LICENSE +92 -17
  4. data/README.md +209 -647
  5. data/data/anthropic.json +433 -249
  6. data/data/bedrock.json +2097 -1055
  7. data/data/deepinfra.json +993 -0
  8. data/data/deepseek.json +53 -28
  9. data/data/google.json +389 -771
  10. data/data/openai.json +1053 -771
  11. data/data/xai.json +133 -292
  12. data/data/zai.json +249 -141
  13. data/lib/llm/a2a.rb +2 -2
  14. data/lib/llm/active_record/acts_as_agent.rb +10 -41
  15. data/lib/llm/active_record/acts_as_llm.rb +25 -0
  16. data/lib/llm/active_record.rb +3 -3
  17. data/lib/llm/agent.rb +1 -1
  18. data/lib/llm/context.rb +9 -5
  19. data/lib/llm/contract/completion.rb +2 -2
  20. data/lib/llm/cost.rb +1 -1
  21. data/lib/llm/function/fiber_group.rb +2 -2
  22. data/lib/llm/function/task_group.rb +2 -2
  23. data/lib/llm/function/thread_group.rb +3 -3
  24. data/lib/llm/pipe.rb +1 -1
  25. data/lib/llm/provider.rb +2 -2
  26. data/lib/llm/providers/anthropic/request_adapter.rb +1 -1
  27. data/lib/llm/providers/bedrock/request_adapter/completion.rb +5 -5
  28. data/lib/llm/providers/bedrock/request_adapter.rb +3 -3
  29. data/lib/llm/providers/bedrock/response_adapter/completion.rb +2 -2
  30. data/lib/llm/providers/bedrock/response_adapter.rb +2 -2
  31. data/lib/llm/providers/deepinfra/audio.rb +66 -0
  32. data/lib/llm/providers/deepinfra/images.rb +90 -0
  33. data/lib/llm/providers/deepinfra/response_adapter.rb +36 -0
  34. data/lib/llm/providers/deepinfra.rb +100 -0
  35. data/lib/llm/providers/deepseek/images.rb +109 -0
  36. data/lib/llm/providers/deepseek/request_adapter.rb +32 -0
  37. data/lib/llm/providers/deepseek/response_adapter/image.rb +9 -0
  38. data/lib/llm/providers/deepseek/response_adapter.rb +29 -0
  39. data/lib/llm/providers/deepseek.rb +4 -2
  40. data/lib/llm/providers/google/request_adapter.rb +23 -6
  41. data/lib/llm/providers/google.rb +4 -4
  42. data/lib/llm/providers/ollama/request_adapter.rb +1 -1
  43. data/lib/llm/providers/openai/audio.rb +6 -2
  44. data/lib/llm/providers/openai/images.rb +9 -50
  45. data/lib/llm/providers/openai/request_adapter/respond.rb +38 -4
  46. data/lib/llm/providers/openai/request_adapter.rb +1 -1
  47. data/lib/llm/providers/openai/response_adapter/audio.rb +5 -1
  48. data/lib/llm/providers/openai/response_adapter/completion.rb +1 -1
  49. data/lib/llm/providers/openai/response_adapter/image.rb +0 -4
  50. data/lib/llm/providers/openai/responses.rb +1 -0
  51. data/lib/llm/providers/openai/stream_parser.rb +5 -6
  52. data/lib/llm/providers/openai.rb +2 -2
  53. data/lib/llm/providers/xai/images.rb +49 -26
  54. data/lib/llm/providers/xai.rb +2 -2
  55. data/lib/llm/registry.rb +2 -2
  56. data/lib/llm/response.rb +11 -1
  57. data/lib/llm/schema/leaf.rb +7 -1
  58. data/lib/llm/schema/object.rb +1 -1
  59. data/lib/llm/schema/renderer.rb +121 -0
  60. data/lib/llm/schema.rb +30 -0
  61. data/lib/llm/sequel/agent.rb +2 -43
  62. data/lib/llm/sequel/plugin.rb +25 -7
  63. data/lib/llm/stream.rb +1 -1
  64. data/lib/llm/tool.rb +2 -2
  65. data/lib/llm/tracer/telemetry.rb +4 -6
  66. data/lib/llm/tracer.rb +9 -21
  67. data/lib/llm/transport/execution.rb +16 -1
  68. data/lib/llm/transport/http.rb +2 -2
  69. data/lib/llm/transport/net_http_adapter.rb +1 -1
  70. data/lib/llm/transport/persistent_http.rb +1 -1
  71. data/lib/llm/transport/response/http.rb +1 -1
  72. data/lib/llm/uridata.rb +16 -0
  73. data/lib/llm/utils.rb +1 -1
  74. data/lib/llm/version.rb +1 -1
  75. data/lib/llm.rb +20 -8
  76. data/llm.gemspec +14 -26
  77. data/resources/deepdive.md +966 -0
  78. metadata +26 -29
  79. data/lib/llm/tracer/langsmith.rb +0 -144
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.3.0
4
+ version: 12.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - 0x1eef (Robert)
7
+ - bsdrobert
8
8
  - Antar Azri
9
9
  - Rodrigo Serrano
10
- - Christos Maris
11
10
  bindir: bin
12
11
  cert_chain: []
13
12
  date: 1980-01-02 00:00:00.000000000 Z
@@ -41,19 +40,19 @@ dependencies:
41
40
  - !ruby/object:Gem::Version
42
41
  version: 0.9.37
43
42
  - !ruby/object:Gem::Dependency
44
- name: kramdown
43
+ name: redcarpet
45
44
  requirement: !ruby/object:Gem::Requirement
46
45
  requirements:
47
46
  - - "~>"
48
47
  - !ruby/object:Gem::Version
49
- version: '2.4'
48
+ version: '3.6'
50
49
  type: :development
51
50
  prerelease: false
52
51
  version_requirements: !ruby/object:Gem::Requirement
53
52
  requirements:
54
53
  - - "~>"
55
54
  - !ruby/object:Gem::Version
56
- version: '2.4'
55
+ version: '3.6'
57
56
  - !ruby/object:Gem::Dependency
58
57
  name: webrick
59
58
  requirement: !ruby/object:Gem::Requirement
@@ -278,22 +277,10 @@ dependencies:
278
277
  - - "~>"
279
278
  - !ruby/object:Gem::Version
280
279
  version: '1.18'
281
- description: |
282
- llm.rb is Ruby's most capable AI runtime.
283
-
284
- It runs on Ruby's standard library by default. loads optional pieces
285
- only when needed, and offers a single runtime for providers, agents,
286
- tools, skills, MCP, A2A (Agent2Agent), RAG (vector stores & embeddings),
287
- streaming, files, and persisted state. As a bonus, llm.rb is also available
288
- for mruby.
289
-
290
- It supports OpenAI, OpenAI-compatible endpoints, Anthropic, Google
291
- Gemini, DeepSeek, xAI, Z.ai, AWS Bedrock, Ollama, and llama.cpp. It
292
- also includes built-in ActiveRecord and Sequel support, plus concurrent
293
- tool execution through threads, tasks (via async gem), fibers, ractors,
294
- 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.
295
282
  email:
296
- - robert@4.4bsd.dev
283
+ - robert@r.uby.dev
297
284
  executables: []
298
285
  extensions: []
299
286
  extra_rdoc_files: []
@@ -303,6 +290,7 @@ files:
303
290
  - README.md
304
291
  - data/anthropic.json
305
292
  - data/bedrock.json
293
+ - data/deepinfra.json
306
294
  - data/deepseek.json
307
295
  - data/google.json
308
296
  - data/openai.json
@@ -402,9 +390,16 @@ files:
402
390
  - lib/llm/providers/bedrock/signature.rb
403
391
  - lib/llm/providers/bedrock/stream_decoder.rb
404
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
405
397
  - lib/llm/providers/deepseek.rb
398
+ - lib/llm/providers/deepseek/images.rb
406
399
  - lib/llm/providers/deepseek/request_adapter.rb
407
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
408
403
  - lib/llm/providers/google.rb
409
404
  - lib/llm/providers/google/audio.rb
410
405
  - lib/llm/providers/google/error_handler.rb
@@ -478,6 +473,7 @@ files:
478
473
  - lib/llm/schema/object.rb
479
474
  - lib/llm/schema/one_of.rb
480
475
  - lib/llm/schema/parser.rb
476
+ - lib/llm/schema/renderer.rb
481
477
  - lib/llm/schema/string.rb
482
478
  - lib/llm/schema/version.rb
483
479
  - lib/llm/sequel/agent.rb
@@ -490,7 +486,6 @@ files:
490
486
  - lib/llm/tool.rb
491
487
  - lib/llm/tool/param.rb
492
488
  - lib/llm/tracer.rb
493
- - lib/llm/tracer/langsmith.rb
494
489
  - lib/llm/tracer/logger.rb
495
490
  - lib/llm/tracer/null.rb
496
491
  - lib/llm/tracer/telemetry.rb
@@ -506,20 +501,22 @@ files:
506
501
  - lib/llm/transport/response/http.rb
507
502
  - lib/llm/transport/stream_decoder.rb
508
503
  - lib/llm/transport/utils.rb
504
+ - lib/llm/uridata.rb
509
505
  - lib/llm/usage.rb
510
506
  - lib/llm/utils.rb
511
507
  - lib/llm/version.rb
512
508
  - lib/sequel/plugins/agent.rb
513
509
  - lib/sequel/plugins/llm.rb
514
510
  - llm.gemspec
515
- homepage: https://llmrb.github.io
511
+ - resources/deepdive.md
512
+ homepage: https://r.uby.dev/llm/
516
513
  licenses:
517
- - 0BSD
514
+ - BUSL-1.1
518
515
  metadata:
519
- homepage_uri: https://llmrb.github.io
520
- source_code_uri: https://github.com/llmrb/llm.rb
521
- documentation_uri: https://llmrb.github.io/llm.rb
522
- changelog_uri: https://0x1eef.github.io/x/llm.rb/file.CHANGELOG.html
516
+ homepage_uri: https://r.uby.dev/llm/
517
+ source_code_uri: https://github.com/r-uby-dev/llm.rb
518
+ documentation_uri: https://r.uby.dev/llm/
519
+ changelog_uri: https://r.uby.dev/api-docs/llm.rb/file.CHANGELOG.html
523
520
  rdoc_options: []
524
521
  require_paths:
525
522
  - lib
@@ -536,5 +533,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
536
533
  requirements: []
537
534
  rubygems_version: 4.0.6
538
535
  specification_version: 4
539
- summary: Ruby's most capable AI runtime
536
+ summary: Ruby's capable AI runtime
540
537
  test_files: []
@@ -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