lex-llm 0.1.2 → 0.1.3

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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +7 -1
  4. data/Gemfile +1 -19
  5. data/README.md +22 -25
  6. data/lex-llm.gemspec +2 -2
  7. data/lib/legion/extensions/llm/agent.rb +366 -0
  8. data/lib/legion/extensions/llm/aliases.rb +42 -0
  9. data/lib/legion/extensions/llm/attachment.rb +229 -0
  10. data/lib/legion/extensions/llm/chat.rb +355 -0
  11. data/lib/legion/extensions/llm/chunk.rb +10 -0
  12. data/lib/legion/extensions/llm/configuration.rb +82 -0
  13. data/lib/legion/extensions/llm/connection.rb +134 -0
  14. data/lib/legion/extensions/llm/content.rb +81 -0
  15. data/lib/legion/extensions/llm/context.rb +33 -0
  16. data/lib/legion/extensions/llm/embedding.rb +33 -0
  17. data/lib/legion/extensions/llm/error.rb +116 -0
  18. data/lib/legion/extensions/llm/image.rb +109 -0
  19. data/lib/legion/extensions/llm/message.rb +111 -0
  20. data/lib/legion/extensions/llm/mime_type.rb +75 -0
  21. data/lib/legion/extensions/llm/model/info.rb +117 -0
  22. data/lib/legion/extensions/llm/model/modalities.rb +26 -0
  23. data/lib/legion/extensions/llm/model/pricing.rb +52 -0
  24. data/lib/legion/extensions/llm/model/pricing_category.rb +50 -0
  25. data/lib/legion/extensions/llm/model/pricing_tier.rb +37 -0
  26. data/lib/legion/extensions/llm/model.rb +11 -0
  27. data/lib/legion/extensions/llm/models.rb +514 -0
  28. data/lib/{lex_llm → legion/extensions/llm}/models_schema.json +1 -1
  29. data/lib/legion/extensions/llm/moderation.rb +60 -0
  30. data/lib/legion/extensions/llm/provider/open_ai_compatible.rb +240 -0
  31. data/lib/legion/extensions/llm/provider.rb +282 -0
  32. data/lib/legion/extensions/llm/routing/lane_key.rb +57 -0
  33. data/lib/legion/extensions/llm/routing/model_offering.rb +173 -0
  34. data/lib/legion/extensions/llm/routing.rb +11 -0
  35. data/lib/legion/extensions/llm/stream_accumulator.rb +209 -0
  36. data/lib/legion/extensions/llm/streaming.rb +181 -0
  37. data/lib/legion/extensions/llm/thinking.rb +53 -0
  38. data/lib/legion/extensions/llm/tokens.rb +51 -0
  39. data/lib/legion/extensions/llm/tool.rb +258 -0
  40. data/lib/legion/extensions/llm/tool_call.rb +29 -0
  41. data/lib/legion/extensions/llm/transcription.rb +39 -0
  42. data/lib/legion/extensions/llm/utils.rb +95 -0
  43. data/lib/legion/extensions/llm/version.rb +9 -0
  44. data/lib/legion/extensions/llm.rb +85 -6
  45. metadata +40 -122
  46. data/lib/generators/lex_llm/agent/agent_generator.rb +0 -36
  47. data/lib/generators/lex_llm/agent/templates/agent.rb.tt +0 -6
  48. data/lib/generators/lex_llm/agent/templates/instructions.txt.erb.tt +0 -0
  49. data/lib/generators/lex_llm/chat_ui/chat_ui_generator.rb +0 -256
  50. data/lib/generators/lex_llm/chat_ui/templates/controllers/chats_controller.rb.tt +0 -38
  51. data/lib/generators/lex_llm/chat_ui/templates/controllers/messages_controller.rb.tt +0 -21
  52. data/lib/generators/lex_llm/chat_ui/templates/controllers/models_controller.rb.tt +0 -14
  53. data/lib/generators/lex_llm/chat_ui/templates/helpers/messages_helper.rb.tt +0 -25
  54. data/lib/generators/lex_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +0 -12
  55. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +0 -16
  56. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +0 -31
  57. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +0 -31
  58. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/new.html.erb.tt +0 -9
  59. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +0 -27
  60. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +0 -14
  61. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_content.html.erb.tt +0 -1
  62. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_error.html.erb.tt +0 -13
  63. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_form.html.erb.tt +0 -23
  64. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +0 -10
  65. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +0 -2
  66. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +0 -4
  67. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +0 -14
  68. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +0 -13
  69. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/tool_results/_default.html.erb.tt +0 -21
  70. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +0 -17
  71. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +0 -40
  72. data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +0 -27
  73. data/lib/generators/lex_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +0 -16
  74. data/lib/generators/lex_llm/chat_ui/templates/views/chats/_form.html.erb.tt +0 -29
  75. data/lib/generators/lex_llm/chat_ui/templates/views/chats/index.html.erb.tt +0 -28
  76. data/lib/generators/lex_llm/chat_ui/templates/views/chats/new.html.erb.tt +0 -11
  77. data/lib/generators/lex_llm/chat_ui/templates/views/chats/show.html.erb.tt +0 -25
  78. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +0 -9
  79. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_content.html.erb.tt +0 -1
  80. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_error.html.erb.tt +0 -8
  81. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_form.html.erb.tt +0 -21
  82. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_system.html.erb.tt +0 -6
  83. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +0 -2
  84. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +0 -4
  85. data/lib/generators/lex_llm/chat_ui/templates/views/messages/_user.html.erb.tt +0 -9
  86. data/lib/generators/lex_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +0 -7
  87. data/lib/generators/lex_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +0 -8
  88. data/lib/generators/lex_llm/chat_ui/templates/views/messages/tool_results/_default.html.erb.tt +0 -16
  89. data/lib/generators/lex_llm/chat_ui/templates/views/models/_model.html.erb.tt +0 -15
  90. data/lib/generators/lex_llm/chat_ui/templates/views/models/index.html.erb.tt +0 -38
  91. data/lib/generators/lex_llm/chat_ui/templates/views/models/show.html.erb.tt +0 -17
  92. data/lib/generators/lex_llm/generator_helpers.rb +0 -214
  93. data/lib/generators/lex_llm/install/install_generator.rb +0 -109
  94. data/lib/generators/lex_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt +0 -9
  95. data/lib/generators/lex_llm/install/templates/chat_model.rb.tt +0 -3
  96. data/lib/generators/lex_llm/install/templates/create_chats_migration.rb.tt +0 -7
  97. data/lib/generators/lex_llm/install/templates/create_messages_migration.rb.tt +0 -19
  98. data/lib/generators/lex_llm/install/templates/create_models_migration.rb.tt +0 -39
  99. data/lib/generators/lex_llm/install/templates/create_tool_calls_migration.rb.tt +0 -21
  100. data/lib/generators/lex_llm/install/templates/initializer.rb.tt +0 -20
  101. data/lib/generators/lex_llm/install/templates/message_model.rb.tt +0 -4
  102. data/lib/generators/lex_llm/install/templates/model_model.rb.tt +0 -3
  103. data/lib/generators/lex_llm/install/templates/tool_call_model.rb.tt +0 -3
  104. data/lib/generators/lex_llm/schema/schema_generator.rb +0 -26
  105. data/lib/generators/lex_llm/schema/templates/schema.rb.tt +0 -2
  106. data/lib/generators/lex_llm/tool/templates/tool.rb.tt +0 -9
  107. data/lib/generators/lex_llm/tool/templates/tool_call.html.erb.tt +0 -13
  108. data/lib/generators/lex_llm/tool/templates/tool_result.html.erb.tt +0 -13
  109. data/lib/generators/lex_llm/tool/tool_generator.rb +0 -96
  110. data/lib/generators/lex_llm/upgrade_to_v1_10/templates/add_v1_10_message_columns.rb.tt +0 -19
  111. data/lib/generators/lex_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +0 -50
  112. data/lib/generators/lex_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +0 -7
  113. data/lib/generators/lex_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +0 -49
  114. data/lib/generators/lex_llm/upgrade_to_v1_7/templates/migration.rb.tt +0 -145
  115. data/lib/generators/lex_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +0 -122
  116. data/lib/generators/lex_llm/upgrade_to_v1_9/templates/add_v1_9_message_columns.rb.tt +0 -15
  117. data/lib/generators/lex_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +0 -49
  118. data/lib/lex_llm/active_record/acts_as.rb +0 -180
  119. data/lib/lex_llm/active_record/acts_as_legacy.rb +0 -503
  120. data/lib/lex_llm/active_record/chat_methods.rb +0 -468
  121. data/lib/lex_llm/active_record/message_methods.rb +0 -131
  122. data/lib/lex_llm/active_record/model_methods.rb +0 -76
  123. data/lib/lex_llm/active_record/payload_helpers.rb +0 -26
  124. data/lib/lex_llm/active_record/tool_call_methods.rb +0 -15
  125. data/lib/lex_llm/agent.rb +0 -365
  126. data/lib/lex_llm/aliases.rb +0 -38
  127. data/lib/lex_llm/attachment.rb +0 -223
  128. data/lib/lex_llm/chat.rb +0 -351
  129. data/lib/lex_llm/chunk.rb +0 -6
  130. data/lib/lex_llm/configuration.rb +0 -81
  131. data/lib/lex_llm/connection.rb +0 -130
  132. data/lib/lex_llm/content.rb +0 -77
  133. data/lib/lex_llm/context.rb +0 -29
  134. data/lib/lex_llm/embedding.rb +0 -29
  135. data/lib/lex_llm/error.rb +0 -112
  136. data/lib/lex_llm/image.rb +0 -105
  137. data/lib/lex_llm/message.rb +0 -107
  138. data/lib/lex_llm/mime_type.rb +0 -71
  139. data/lib/lex_llm/model/info.rb +0 -113
  140. data/lib/lex_llm/model/modalities.rb +0 -22
  141. data/lib/lex_llm/model/pricing.rb +0 -48
  142. data/lib/lex_llm/model/pricing_category.rb +0 -46
  143. data/lib/lex_llm/model/pricing_tier.rb +0 -33
  144. data/lib/lex_llm/model.rb +0 -7
  145. data/lib/lex_llm/models.rb +0 -506
  146. data/lib/lex_llm/moderation.rb +0 -56
  147. data/lib/lex_llm/provider/open_ai_compatible.rb +0 -219
  148. data/lib/lex_llm/provider.rb +0 -278
  149. data/lib/lex_llm/railtie.rb +0 -35
  150. data/lib/lex_llm/routing/lane_key.rb +0 -51
  151. data/lib/lex_llm/routing/model_offering.rb +0 -169
  152. data/lib/lex_llm/routing.rb +0 -7
  153. data/lib/lex_llm/stream_accumulator.rb +0 -203
  154. data/lib/lex_llm/streaming.rb +0 -175
  155. data/lib/lex_llm/thinking.rb +0 -49
  156. data/lib/lex_llm/tokens.rb +0 -47
  157. data/lib/lex_llm/tool.rb +0 -254
  158. data/lib/lex_llm/tool_call.rb +0 -25
  159. data/lib/lex_llm/transcription.rb +0 -35
  160. data/lib/lex_llm/utils.rb +0 -91
  161. data/lib/lex_llm/version.rb +0 -5
  162. data/lib/lex_llm.rb +0 -96
  163. data/lib/tasks/lex_llm.rake +0 -23
  164. /data/lib/{lex_llm → legion/extensions/llm}/aliases.json +0 -0
  165. /data/lib/{lex_llm → legion/extensions/llm}/models.json +0 -0
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ module Model
7
+ # Information about an AI model's capabilities, pricing, and metadata.
8
+ class Info
9
+ attr_reader :id, :name, :provider, :family, :created_at, :context_window, :max_output_tokens,
10
+ :knowledge_cutoff, :modalities, :capabilities, :pricing, :metadata
11
+
12
+ # Create a default model with assumed capabilities
13
+ def self.default(model_id, provider)
14
+ new(
15
+ id: model_id,
16
+ name: model_id.tr('-', ' ').capitalize,
17
+ provider: provider,
18
+ capabilities: %w[function_calling streaming vision structured_output],
19
+ modalities: { input: %w[text image], output: %w[text] },
20
+ metadata: { warning: 'Assuming model exists, capabilities may not be accurate' }
21
+ )
22
+ end
23
+
24
+ def initialize(data)
25
+ @id = data[:id]
26
+ @name = data[:name]
27
+ @provider = data[:provider]
28
+ @family = data[:family]
29
+ @created_at = Utils.to_time(data[:created_at])&.utc
30
+ @context_window = data[:context_window]
31
+ @max_output_tokens = data[:max_output_tokens]
32
+ @knowledge_cutoff = Utils.to_date(data[:knowledge_cutoff])
33
+ @modalities = Modalities.new(data[:modalities] || {})
34
+ @capabilities = data[:capabilities] || []
35
+ @pricing = Pricing.new(data[:pricing] || {})
36
+ @metadata = data[:metadata] || {}
37
+ end
38
+
39
+ def supports?(capability)
40
+ capabilities.include?(capability.to_s)
41
+ end
42
+
43
+ %w[function_calling structured_output batch reasoning citations streaming].each do |cap|
44
+ define_method "#{cap}?" do
45
+ supports?(cap)
46
+ end
47
+ end
48
+
49
+ def display_name
50
+ name
51
+ end
52
+
53
+ def label
54
+ provider_name = provider_class&.name || provider
55
+ "#{provider_name} - #{display_name}"
56
+ end
57
+
58
+ def max_tokens
59
+ max_output_tokens
60
+ end
61
+
62
+ def supports_vision?
63
+ modalities.input.include?('image')
64
+ end
65
+
66
+ def supports_video?
67
+ modalities.input.include?('video')
68
+ end
69
+
70
+ def supports_functions?
71
+ function_calling?
72
+ end
73
+
74
+ def input_price_per_million
75
+ pricing.text_tokens.input
76
+ end
77
+
78
+ def output_price_per_million
79
+ pricing.text_tokens.output
80
+ end
81
+
82
+ def provider_class
83
+ Legion::Extensions::Llm::Provider.resolve provider
84
+ end
85
+
86
+ def type
87
+ output = modalities.output
88
+ return 'embedding' if output.include?('embeddings')
89
+ return 'moderation' if output.include?('moderation')
90
+ return 'image' if output.include?('image')
91
+ return 'audio' if output.include?('audio')
92
+ return 'video' if output.include?('video')
93
+
94
+ 'chat'
95
+ end
96
+
97
+ def to_h
98
+ {
99
+ id: id,
100
+ name: name,
101
+ provider: provider,
102
+ family: family,
103
+ created_at: created_at,
104
+ context_window: context_window,
105
+ max_output_tokens: max_output_tokens,
106
+ knowledge_cutoff: knowledge_cutoff,
107
+ modalities: modalities.to_h,
108
+ capabilities: capabilities,
109
+ pricing: pricing.to_h,
110
+ metadata: metadata
111
+ }
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ module Model
7
+ # Holds and manages input and output modalities for a language model
8
+ class Modalities
9
+ attr_reader :input, :output
10
+
11
+ def initialize(data)
12
+ @input = Array(data[:input]).map(&:to_s)
13
+ @output = Array(data[:output]).map(&:to_s)
14
+ end
15
+
16
+ def to_h
17
+ {
18
+ input: input,
19
+ output: output
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ module Model
7
+ # A collection that manages and provides access to different categories of pricing information
8
+ class Pricing
9
+ def initialize(data)
10
+ @data = {}
11
+
12
+ %i[text_tokens images audio_tokens embeddings].each do |category|
13
+ @data[category] = PricingCategory.new(data[category]) if data[category] && !empty_pricing?(data[category])
14
+ end
15
+ end
16
+
17
+ def method_missing(method, *args)
18
+ if respond_to_missing?(method)
19
+ @data[method.to_sym] || PricingCategory.new
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ def respond_to_missing?(method, include_private = false)
26
+ %i[text_tokens images audio_tokens embeddings].include?(method.to_sym) || super
27
+ end
28
+
29
+ def to_h
30
+ @data.transform_values(&:to_h)
31
+ end
32
+
33
+ private
34
+
35
+ def empty_pricing?(data)
36
+ return true unless data
37
+
38
+ %i[standard batch].each do |tier|
39
+ next unless data[tier]
40
+
41
+ data[tier].each_value do |value|
42
+ return false if value && value != 0.0
43
+ end
44
+ end
45
+
46
+ true
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ module Model
7
+ # Represents pricing tiers for different usage categories (standard and batch)
8
+ class PricingCategory
9
+ attr_reader :standard, :batch
10
+
11
+ def initialize(data = {})
12
+ @standard = PricingTier.new(data[:standard] || {}) unless empty_tier?(data[:standard])
13
+ @batch = PricingTier.new(data[:batch] || {}) unless empty_tier?(data[:batch])
14
+ end
15
+
16
+ def input
17
+ standard&.input_per_million
18
+ end
19
+
20
+ def output
21
+ standard&.output_per_million
22
+ end
23
+
24
+ def cached_input
25
+ standard&.cached_input_per_million
26
+ end
27
+
28
+ def [](key)
29
+ key == :batch ? batch : standard
30
+ end
31
+
32
+ def to_h
33
+ result = {}
34
+ result[:standard] = standard.to_h if standard
35
+ result[:batch] = batch.to_h if batch
36
+ result
37
+ end
38
+
39
+ private
40
+
41
+ def empty_tier?(tier_data)
42
+ return true unless tier_data
43
+
44
+ tier_data.values.all? { |v| v.nil? || v == 0.0 }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ module Model
7
+ # A dynamic class for storing non-zero pricing values with flexible attribute access
8
+ class PricingTier
9
+ def initialize(data = {})
10
+ @values = {}
11
+
12
+ data.each do |key, value|
13
+ @values[key.to_sym] = value if value && value != 0.0
14
+ end
15
+ end
16
+
17
+ def method_missing(method, *args)
18
+ if method.to_s.end_with?('=')
19
+ key = method.to_s.chomp('=').to_sym
20
+ @values[key] = args.first if args.first && args.first != 0.0
21
+ elsif @values.key?(method)
22
+ @values[method]
23
+ end
24
+ end
25
+
26
+ def respond_to_missing?(method, include_private = false)
27
+ method.to_s.end_with?('=') || @values.key?(method.to_sym) || super
28
+ end
29
+
30
+ def to_h
31
+ @values
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Llm
6
+ # Model-related classes for working with LLM models
7
+ module Model
8
+ end
9
+ end
10
+ end
11
+ end