ruby_llm 1.13.2 → 1.14.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/README.md +5 -5
- data/lib/generators/ruby_llm/agent/agent_generator.rb +36 -0
- data/lib/generators/ruby_llm/agent/templates/agent.rb.tt +6 -0
- data/lib/generators/ruby_llm/agent/templates/instructions.txt.erb.tt +0 -0
- data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +110 -41
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +14 -15
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +8 -11
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/helpers/messages_helper.rb.tt +25 -0
- data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +31 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +31 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/new.html.erb.tt +9 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +27 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +14 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_content.html.erb.tt +1 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_error.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_form.html.erb.tt +23 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +10 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +2 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +4 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +14 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_results/_default.html.erb.tt +21 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +17 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +40 -0
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +27 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +19 -7
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +5 -3
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +9 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_content.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_error.html.erb.tt +8 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_system.html.erb.tt +6 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +2 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +4 -7
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_user.html.erb.tt +9 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +5 -7
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +8 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_results/_default.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +11 -12
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +27 -17
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +3 -4
- data/lib/generators/ruby_llm/generator_helpers.rb +33 -17
- data/lib/generators/ruby_llm/install/install_generator.rb +21 -18
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +3 -4
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +1 -1
- data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +2 -2
- data/lib/generators/ruby_llm/schema/schema_generator.rb +26 -0
- data/lib/generators/ruby_llm/schema/templates/schema.rb.tt +2 -0
- data/lib/generators/ruby_llm/tool/templates/tool.rb.tt +9 -0
- data/lib/generators/ruby_llm/tool/templates/tool_call.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/tool/templates/tool_result.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/tool/tool_generator.rb +96 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +1 -1
- data/lib/generators/ruby_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +7 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +49 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +2 -4
- data/lib/generators/ruby_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +1 -1
- data/lib/ruby_llm/active_record/acts_as.rb +2 -0
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +2 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +1 -1
- data/lib/ruby_llm/active_record/message_methods.rb +28 -0
- data/lib/ruby_llm/active_record/model_methods.rb +1 -1
- data/lib/ruby_llm/active_record/tool_call_methods.rb +28 -0
- data/lib/ruby_llm/agent.rb +11 -0
- data/lib/ruby_llm/aliases.json +15 -5
- data/lib/ruby_llm/attachment.rb +3 -0
- data/lib/ruby_llm/configuration.rb +54 -73
- data/lib/ruby_llm/connection.rb +1 -3
- data/lib/ruby_llm/error.rb +5 -0
- data/lib/ruby_llm/model/info.rb +14 -12
- data/lib/ruby_llm/models.json +2693 -2160
- data/lib/ruby_llm/models.rb +10 -3
- data/lib/ruby_llm/provider.rb +5 -0
- data/lib/ruby_llm/providers/anthropic.rb +4 -0
- data/lib/ruby_llm/providers/azure.rb +4 -0
- data/lib/ruby_llm/providers/bedrock.rb +4 -0
- data/lib/ruby_llm/providers/deepseek.rb +4 -0
- data/lib/ruby_llm/providers/gemini.rb +4 -0
- data/lib/ruby_llm/providers/gpustack.rb +4 -0
- data/lib/ruby_llm/providers/mistral.rb +4 -0
- data/lib/ruby_llm/providers/ollama.rb +4 -0
- data/lib/ruby_llm/providers/openai.rb +10 -0
- data/lib/ruby_llm/providers/openrouter/images.rb +1 -1
- data/lib/ruby_llm/providers/openrouter.rb +4 -0
- data/lib/ruby_llm/providers/perplexity.rb +4 -0
- data/lib/ruby_llm/providers/vertexai.rb +4 -0
- data/lib/ruby_llm/providers/xai.rb +4 -0
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/tasks/release.rake +1 -1
- data/lib/tasks/ruby_llm.rake +6 -5
- data/lib/tasks/vcr.rake +1 -1
- metadata +47 -10
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt +0 -13
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%% system ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= system.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
3
|
+
<div>
|
|
4
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
5
|
+
System
|
|
6
|
+
</span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="whitespace-pre-wrap text-gray-700"><%%= system.content %></div>
|
|
10
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%% user ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-blue-50">
|
|
3
|
+
<div>
|
|
4
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-blue-100 text-blue-700">
|
|
5
|
+
User
|
|
6
|
+
</span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>_content" class="whitespace-pre-wrap"><%%= user.content %></div>
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<span class="text-sm text-gray-600"><%%= user.created_at&.strftime("%I:%M %p") %></span>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div id="<%= message_variable_name %>_<%%= tool_calls.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
2
|
+
<div>
|
|
3
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
4
|
+
Tool Call
|
|
5
|
+
</span>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<pre class="whitespace-pre-wrap text-gray-700 text-sm overflow-x-auto"><%%= tool_call.name %>(<%%= tool_call.arguments.map { |k, v| "#{k}: #{v.inspect}" }.join(", ") %>)</pre>
|
|
9
|
+
|
|
10
|
+
<div>
|
|
11
|
+
<span class="text-sm text-gray-600"><%%= tool_calls.created_at&.strftime("%I:%M %p") %></span>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%% error_message = tool.tool_error_message %>
|
|
2
|
+
<%% if error_message.present? %>
|
|
3
|
+
<%%= render "<%= message_model_name.underscore.pluralize %>/error",
|
|
4
|
+
<%= message_model_name.demodulize.underscore %>: tool,
|
|
5
|
+
title: "Tool Result Error",
|
|
6
|
+
error_message: error_message %>
|
|
7
|
+
<%% else %>
|
|
8
|
+
<div id="<%= message_variable_name %>_<%%= tool.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
9
|
+
<div>
|
|
10
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
11
|
+
Tool
|
|
12
|
+
</span>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<pre class="whitespace-pre-wrap text-gray-700 text-sm overflow-x-auto"><%%= tool.content.presence || "(no output)" %></pre>
|
|
16
|
+
|
|
17
|
+
<div>
|
|
18
|
+
<span class="text-sm text-gray-600"><%%= tool.created_at&.strftime("%I:%M %p") %></span>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<%% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%% model_id = <%= model_model_name.demodulize.underscore %>.respond_to?(:model_id) ? <%= model_model_name.demodulize.underscore %>.model_id : <%= model_model_name.demodulize.underscore %>.id %>
|
|
2
|
+
<%% row_id = [<%= model_model_name.demodulize.underscore %>.provider, model_id].join("_").parameterize(separator: "_") %>
|
|
3
|
+
<tr id="model_<%%= row_id %>">
|
|
4
|
+
<td class="px-3 py-2 text-sm text-gray-700"><%%= <%= model_model_name.demodulize.underscore %>.provider_class&.name || <%= model_model_name.demodulize.underscore %>.provider %></td>
|
|
5
|
+
<td class="px-3 py-2 text-sm text-gray-900"><%%= <%= model_model_name.demodulize.underscore %>.respond_to?(:display_name) ? <%= model_model_name.demodulize.underscore %>.display_name : <%= model_model_name.demodulize.underscore %>.name %></td>
|
|
6
|
+
<td class="px-3 py-2 text-sm text-gray-700"><%%= number_with_delimiter(<%= model_model_name.demodulize.underscore %>.context_window) if <%= model_model_name.demodulize.underscore %>.context_window %></td>
|
|
7
|
+
<td class="px-3 py-2 text-sm text-gray-700">
|
|
8
|
+
<%% input = <%= model_model_name.demodulize.underscore %>.input_price_per_million %>
|
|
9
|
+
<%% output = <%= model_model_name.demodulize.underscore %>.output_price_per_million %>
|
|
10
|
+
<%% if input && output %>
|
|
11
|
+
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
</td>
|
|
14
|
+
<td class="px-3 py-2 text-sm">
|
|
15
|
+
<%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path(model: model_id), class: "text-blue-600 hover:text-blue-500" %>
|
|
16
|
+
</td>
|
|
17
|
+
</tr>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<%% content_for :title, "<%= model_model_name.pluralize %>" %>
|
|
2
|
+
|
|
3
|
+
<div class="w-full">
|
|
4
|
+
<%% if notice.present? %>
|
|
5
|
+
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md inline-block" id="notice"><%%= notice %></p>
|
|
6
|
+
<%% end %>
|
|
7
|
+
|
|
8
|
+
<div class="flex justify-between items-center">
|
|
9
|
+
<h1 class="font-bold text-4xl"><%= model_model_name.pluralize %></h1>
|
|
10
|
+
<div class="flex items-center gap-2">
|
|
11
|
+
<%%= link_to "<%= chat_model_name.pluralize %>", <%= chat_table_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 text-gray-900 block font-medium" %>
|
|
12
|
+
<%%= button_to "Refresh <%= model_model_name.pluralize %>", refresh_<%= model_table_name %>_path, method: :post, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium cursor-pointer" %>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div id="<%= model_table_name %>" class="mt-5 overflow-x-auto">
|
|
17
|
+
<%% if @<%= model_variable_name.pluralize %>.any? %>
|
|
18
|
+
<table class="min-w-full divide-y divide-gray-300 border border-gray-300">
|
|
19
|
+
<thead class="bg-gray-50">
|
|
20
|
+
<tr>
|
|
21
|
+
<th class="px-3 py-2 text-left text-sm font-semibold text-gray-900">Provider</th>
|
|
22
|
+
<th class="px-3 py-2 text-left text-sm font-semibold text-gray-900">Model</th>
|
|
23
|
+
<th class="px-3 py-2 text-left text-sm font-semibold text-gray-900">Context Window</th>
|
|
24
|
+
<th class="px-3 py-2 text-left text-sm font-semibold text-gray-900">$/1M tokens (In/Out)</th>
|
|
25
|
+
<th class="px-3 py-2 text-left text-sm font-semibold text-gray-900"></th>
|
|
26
|
+
</tr>
|
|
27
|
+
</thead>
|
|
28
|
+
<tbody class="divide-y divide-gray-200 bg-white">
|
|
29
|
+
<%% @<%= model_variable_name.pluralize %>.each do |model_info| %>
|
|
30
|
+
<%%= render "<%= model_model_name.underscore.pluralize %>/<%= model_model_name.demodulize.underscore %>",
|
|
31
|
+
<%= model_model_name.demodulize.underscore %>: model_info %>
|
|
32
|
+
<%% end %>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
<%% else %>
|
|
36
|
+
<p class="text-center my-10">No chat models found.</p>
|
|
37
|
+
<%% end %>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%% content_for :title, "Showing <%= model_table_name.singularize.humanize.downcase %>" %>
|
|
2
|
+
|
|
3
|
+
<div class="md:w-2/3 w-full">
|
|
4
|
+
<%% if notice.present? %>
|
|
5
|
+
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md inline-block" id="notice"><%%= notice %></p>
|
|
6
|
+
<%% end %>
|
|
7
|
+
|
|
8
|
+
<h1 class="font-bold text-4xl">Showing <%= model_table_name.singularize.humanize.downcase %></h1>
|
|
9
|
+
|
|
10
|
+
<div class="my-5 space-y-3">
|
|
11
|
+
<p><strong class="block font-medium mb-1">Provider:</strong> <%%= @<%= model_variable_name %>.provider_class&.name || @<%= model_variable_name %>.provider %></p>
|
|
12
|
+
<p><strong class="block font-medium mb-1">Model:</strong> <%%= @<%= model_variable_name %>.name %></p>
|
|
13
|
+
<p><strong class="block font-medium mb-1">ID:</strong> <%%= @<%= model_variable_name %>.model_id %></p>
|
|
14
|
+
<p><strong class="block font-medium mb-1">Context Window:</strong> <%%= number_with_delimiter(@<%= model_variable_name %>.context_window) if @<%= model_variable_name %>.context_window %></p>
|
|
15
|
+
<p><strong class="block font-medium mb-1">Max Output Tokens:</strong> <%%= number_with_delimiter(@<%= model_variable_name %>.max_output_tokens) if @<%= model_variable_name %>.max_output_tokens %></p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<%% if @<%= model_variable_name %>.capabilities.any? %>
|
|
19
|
+
<div class="my-5">
|
|
20
|
+
<strong class="block font-medium mb-1">Capabilities:</strong>
|
|
21
|
+
<%%= @<%= model_variable_name %>.capabilities.join(", ") %>
|
|
22
|
+
</div>
|
|
23
|
+
<%% end %>
|
|
24
|
+
|
|
25
|
+
<%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %> with this model", new_<%= chat_variable_name %>_path(model: @<%= model_variable_name %>.model_id), class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
|
|
26
|
+
<%%= link_to "All <%= model_table_name.humanize.downcase %>", <%= model_table_name %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
|
|
27
|
+
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div id="<%%= dom_id <%= chat_model_name.demodulize.underscore %> %>">
|
|
2
2
|
<div>
|
|
3
3
|
<strong>Model:</strong>
|
|
4
|
-
<%%= <%= chat_model_name.demodulize.underscore %>.<%= model_table_name.singularize %>&.
|
|
4
|
+
<%%= <%= chat_model_name.demodulize.underscore %>.<%= model_table_name.singularize %>&.label || default_model_display_name %>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
7
|
<div>
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
<strong>Created:</strong>
|
|
14
14
|
<%%= <%= chat_model_name.demodulize.underscore %>.created_at.strftime("%B %d, %Y at %I:%M %p") %>
|
|
15
15
|
</div>
|
|
16
|
-
</div>
|
|
16
|
+
</div>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<div>
|
|
15
15
|
<%%= form.label :model, "Select AI model:", style: "display: block" %>
|
|
16
16
|
<%%= form.select :model,
|
|
17
|
-
options_for_select(
|
|
17
|
+
options_for_select(@chat_models.map { |model| [model.label, model.id] }.unshift([default_model_display_name, nil]), @selected_model),
|
|
18
18
|
{},
|
|
19
19
|
style: "width: 100%; max-width: 600px; padding: 5px;" %>
|
|
20
20
|
</div>
|
|
@@ -26,4 +26,4 @@
|
|
|
26
26
|
<div>
|
|
27
27
|
<%%= form.submit "Start new <%= chat_table_name.singularize.humanize.downcase %>" %>
|
|
28
28
|
</div>
|
|
29
|
-
<%% end %>
|
|
29
|
+
<%% end %>
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
<%% if notice.present? %>
|
|
2
|
+
<p style="color: green"><%%= notice %></p>
|
|
3
|
+
<%% end %>
|
|
2
4
|
|
|
3
5
|
<%% content_for :title, "<%= chat_model_name.pluralize %>" %>
|
|
4
6
|
|
|
5
7
|
<h1><%= chat_model_name.pluralize %></h1>
|
|
8
|
+
<p>
|
|
9
|
+
<%%= link_to "<%= model_model_name.pluralize %>", <%= model_table_name %>_path %>
|
|
10
|
+
</p>
|
|
6
11
|
|
|
7
12
|
<div id="<%= chat_table_name %>">
|
|
8
|
-
<%% @<%= chat_table_name %>.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
<%% if @<%= chat_table_name %>.any? %>
|
|
14
|
+
<%% @<%= chat_table_name %>.each do |<%= chat_variable_name %>| %>
|
|
15
|
+
<%%= render <%= chat_variable_name %> %>
|
|
16
|
+
<p>
|
|
17
|
+
<%%= link_to "Show this <%= chat_table_name.singularize.humanize.downcase %>", <%= chat_variable_name %> %>
|
|
18
|
+
</p>
|
|
19
|
+
<p>
|
|
20
|
+
<%%= link_to "Destroy this <%= chat_table_name.singularize.humanize.downcase %>", <%= chat_variable_name %>, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
|
|
21
|
+
</p>
|
|
22
|
+
<%% end %>
|
|
23
|
+
<%% else %>
|
|
24
|
+
<p>No <%= chat_table_name.humanize.downcase %> found.</p>
|
|
13
25
|
<%% end %>
|
|
14
26
|
</div>
|
|
15
27
|
|
|
16
|
-
<%%= link_to "New <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path %>
|
|
28
|
+
<%%= link_to "New <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path %>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<%% if notice.present? %>
|
|
2
|
+
<p style="color: green"><%%= notice %></p>
|
|
3
|
+
<%% end %>
|
|
2
4
|
|
|
3
5
|
<%%= turbo_stream_from "<%= chat_variable_name %>_#{@<%= chat_variable_name %>.id}" %>
|
|
4
6
|
|
|
@@ -6,7 +8,7 @@
|
|
|
6
8
|
|
|
7
9
|
<h1><%= chat_model_name %> <%%= @<%= chat_variable_name %>.id %></h1>
|
|
8
10
|
|
|
9
|
-
<p>Using <strong><%%= @<%= chat_variable_name %>.<%= model_table_name.singularize
|
|
11
|
+
<p>Using <strong><%%= @<%= chat_variable_name %>.<%= model_table_name.singularize %>&.label || default_model_display_name %></strong></p>
|
|
10
12
|
|
|
11
13
|
<div id="<%= message_table_name %>">
|
|
12
14
|
<%% @<%= chat_variable_name %>.<%= message_table_name %>.where.not(id: nil).each do |<%= message_variable_name %>| %>
|
|
@@ -20,4 +22,4 @@
|
|
|
20
22
|
|
|
21
23
|
<div style="margin-top: 20px;">
|
|
22
24
|
<%%= link_to "Back to <%= chat_table_name.humanize.downcase %>", <%= chat_table_name %>_path %>
|
|
23
|
-
</div>
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%% assistant ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= assistant.id %>" class="<%= message_variable_name %>"
|
|
3
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #28a745;">
|
|
4
|
+
<div style="font-weight: bold; margin-bottom: 5px;">Assistant</div>
|
|
5
|
+
<div id="<%= message_variable_name %>_<%%= assistant.id %>_content" style="white-space: pre-wrap;"><%%= assistant.content %></div>
|
|
6
|
+
<div style="font-size: 0.85em; color: #666; margin-top: 5px;">
|
|
7
|
+
<%%= assistant.created_at&.strftime("%I:%M %p") %>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<%%= content
|
|
1
|
+
<%%= content -%>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<div id="<%= message_variable_name %>_<%%= <%= message_model_name.demodulize.underscore %>.id %>" class="<%= message_variable_name %>"
|
|
2
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #dc2626; background: #fef2f2;">
|
|
3
|
+
<div style="font-weight: bold; margin-bottom: 5px; color: #b91c1c;"><%%= title.presence || "Error" %></div>
|
|
4
|
+
<pre style="white-space: pre-wrap; margin: 0; color: #7f1d1d;"><%%= error_message %></pre>
|
|
5
|
+
<div style="font-size: 0.85em; color: #7f1d1d; margin-top: 5px;">
|
|
6
|
+
<%%= <%= message_model_name.demodulize.underscore %>.created_at&.strftime("%I:%M %p") %>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<%% system ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= system.id %>" class="<%= message_variable_name %>"
|
|
3
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #6b7280; background: #f9fafb;">
|
|
4
|
+
<div style="font-weight: bold; margin-bottom: 5px; color: #374151;">System</div>
|
|
5
|
+
<div style="white-space: pre-wrap; color: #4b5563;"><%%= system.content %></div>
|
|
6
|
+
</div>
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
</div>
|
|
6
|
-
<%% end %>
|
|
7
|
-
</div>
|
|
1
|
+
<%% tool_calls ||= local_assigns[:message] %>
|
|
2
|
+
<%% tool_calls.<%= tool_call_variable_name.pluralize %>.each do |tool_call| %>
|
|
3
|
+
<%%= render tool_call_partial(tool_call), tool_calls: tool_calls, tool_call: tool_call %>
|
|
4
|
+
<%% end %>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%% user ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>" class="<%= message_variable_name %>"
|
|
3
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #007bff;">
|
|
4
|
+
<div style="font-weight: bold; margin-bottom: 5px;">User</div>
|
|
5
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>_content" style="white-space: pre-wrap;"><%%= user.content %></div>
|
|
6
|
+
<div style="font-size: 0.85em; color: #666; margin-top: 5px;">
|
|
7
|
+
<%%= user.created_at&.strftime("%I:%M %p") %>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<%%= render <%=
|
|
1
|
+
<%% if defined?(@<%= chat_variable_name %>) && @<%= chat_variable_name %>.present? %>
|
|
2
|
+
<%%= turbo_stream.replace "new_<%= message_variable_name %>" do %>
|
|
3
|
+
<%%= render "<%= message_model_name.underscore.pluralize %>/form",
|
|
4
|
+
<%= chat_variable_name %>: @<%= chat_variable_name %>,
|
|
5
|
+
<%= message_variable_name %>: @<%= chat_variable_name %>.<%= message_table_name %>.build %>
|
|
4
6
|
<%% end %>
|
|
5
7
|
<%% end %>
|
|
6
|
-
|
|
7
|
-
<%%= turbo_stream.replace "new_<%= message_variable_name %>" do %>
|
|
8
|
-
<%%= render "<%= message_model_name.underscore.pluralize %>/form", <%= chat_variable_name %>: @<%= chat_variable_name %>, <%= message_variable_name %>: @<%= chat_variable_name %>.<%= message_table_name %>.build %>
|
|
9
|
-
<%% end %>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<div id="<%= message_variable_name %>_<%%= tool_calls.id %>" class="<%= message_variable_name %>"
|
|
2
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #6b7280; background: #f9fafb;">
|
|
3
|
+
<div style="font-weight: bold; margin-bottom: 5px;">Tool Call</div>
|
|
4
|
+
<pre style="white-space: pre-wrap; margin: 0;"><%%= tool_call.name %>(<%%= tool_call.arguments.map { |k, v| "#{k}: #{v.inspect}" }.join(", ") %>)</pre>
|
|
5
|
+
<div style="font-size: 0.85em; color: #666; margin-top: 5px;">
|
|
6
|
+
<%%= tool_calls.created_at&.strftime("%I:%M %p") %>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_results/_default.html.erb.tt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%% error_message = tool.tool_error_message %>
|
|
2
|
+
<%% if error_message.present? %>
|
|
3
|
+
<%%= render "<%= message_model_name.underscore.pluralize %>/error",
|
|
4
|
+
<%= message_model_name.demodulize.underscore %>: tool,
|
|
5
|
+
title: "Tool Result Error",
|
|
6
|
+
error_message: error_message %>
|
|
7
|
+
<%% else %>
|
|
8
|
+
<div id="<%= message_variable_name %>_<%%= tool.id %>" class="<%= message_variable_name %>"
|
|
9
|
+
style="margin-bottom: 20px; padding: 10px; border-left: 3px solid #6b7280; background: #f9fafb;">
|
|
10
|
+
<div style="font-weight: bold; margin-bottom: 5px;">Tool</div>
|
|
11
|
+
<pre style="white-space: pre-wrap; margin: 0;"><%%= tool.content.presence || "(no output)" %></pre>
|
|
12
|
+
<div style="font-size: 0.85em; color: #666; margin-top: 5px;">
|
|
13
|
+
<%%= tool.created_at&.strftime("%I:%M %p") %>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<%% end %>
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<%% model_id = <%= model_model_name.demodulize.underscore %>.respond_to?(:model_id) ? <%= model_model_name.demodulize.underscore %>.model_id : <%= model_model_name.demodulize.underscore %>.id %>
|
|
2
|
+
<%% row_id = [<%= model_model_name.demodulize.underscore %>.provider, model_id].join("_").parameterize(separator: "_") %>
|
|
3
|
+
<tr id="model_<%%= row_id %>">
|
|
4
|
+
<td><%%= <%= model_model_name.demodulize.underscore %>.provider_class&.name || <%= model_model_name.demodulize.underscore %>.provider %></td>
|
|
5
|
+
<td><%%= <%= model_model_name.demodulize.underscore %>.respond_to?(:display_name) ? <%= model_model_name.demodulize.underscore %>.display_name : <%= model_model_name.demodulize.underscore %>.name %></td>
|
|
4
6
|
<td><%%= number_with_delimiter(<%= model_model_name.demodulize.underscore %>.context_window) if <%= model_model_name.demodulize.underscore %>.context_window %></td>
|
|
5
7
|
<td>
|
|
6
|
-
<%%
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
|
11
|
-
<%% end %>
|
|
8
|
+
<%% input = <%= model_model_name.demodulize.underscore %>.input_price_per_million %>
|
|
9
|
+
<%% output = <%= model_model_name.demodulize.underscore %>.output_price_per_million %>
|
|
10
|
+
<%% if input && output %>
|
|
11
|
+
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
|
12
12
|
<%% end %>
|
|
13
13
|
</td>
|
|
14
|
-
<td><%%= link_to "
|
|
15
|
-
|
|
16
|
-
</tr>
|
|
14
|
+
<td><%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path(model: model_id) %></td>
|
|
15
|
+
</tr>
|
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
<%% if notice.present? %>
|
|
2
|
+
<p style="color: green"><%%= notice %></p>
|
|
3
|
+
<%% end %>
|
|
2
4
|
|
|
3
5
|
<%% content_for :title, "<%= model_model_name.pluralize %>" %>
|
|
4
6
|
|
|
5
7
|
<h1><%= model_model_name.pluralize %></h1>
|
|
8
|
+
<p>
|
|
9
|
+
<%%= link_to "<%= chat_model_name.pluralize %>", <%= chat_table_name %>_path %>
|
|
10
|
+
</p>
|
|
6
11
|
|
|
7
12
|
<p>
|
|
8
13
|
<%%= button_to "Refresh <%= model_model_name.pluralize %>", refresh_<%= model_table_name %>_path, method: :post %>
|
|
9
14
|
</p>
|
|
10
15
|
|
|
11
16
|
<div id="<%= model_table_name %>">
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
<%% if @<%= model_variable_name.pluralize %>.any? %>
|
|
18
|
+
<table>
|
|
19
|
+
<thead>
|
|
20
|
+
<tr>
|
|
21
|
+
<th>Provider</th>
|
|
22
|
+
<th>Model</th>
|
|
23
|
+
<th>Context Window</th>
|
|
24
|
+
<th>$/1M tokens (In/Out)</th>
|
|
25
|
+
<th></th>
|
|
26
|
+
</tr>
|
|
27
|
+
</thead>
|
|
28
|
+
<tbody>
|
|
29
|
+
<%% @<%= model_variable_name.pluralize %>.each do |model_info| %>
|
|
30
|
+
<%%= render "<%= model_model_name.underscore.pluralize %>/<%= model_model_name.demodulize.underscore %>",
|
|
31
|
+
<%= model_model_name.demodulize.underscore %>: model_info %>
|
|
32
|
+
<%% end %>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
<%% else %>
|
|
36
|
+
<p>No chat models found.</p>
|
|
37
|
+
<%% end %>
|
|
26
38
|
</div>
|
|
27
|
-
|
|
28
|
-
<%%= link_to "Back to <%= chat_table_name.humanize.downcase %>", <%= chat_table_name %>_path %>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<h1><%%= @<%= model_variable_name %>.name %></h1>
|
|
4
4
|
|
|
5
5
|
<p><strong>ID:</strong> <%%= @<%= model_variable_name %>.model_id %></p>
|
|
6
|
-
<p><strong>Provider:</strong> <%%= @<%= model_variable_name %>.provider %></p>
|
|
6
|
+
<p><strong>Provider:</strong> <%%= @<%= model_variable_name %>.provider_class&.name || @<%= model_variable_name %>.provider %></p>
|
|
7
7
|
<p><strong>Context Window:</strong> <%%= number_with_delimiter(@<%= model_variable_name %>.context_window) %> tokens</p>
|
|
8
8
|
<p><strong>Max Output:</strong> <%%= number_with_delimiter(@<%= model_variable_name %>.max_output_tokens) %> tokens</p>
|
|
9
9
|
|
|
@@ -13,6 +13,5 @@
|
|
|
13
13
|
|
|
14
14
|
<p>
|
|
15
15
|
<%%= link_to "Start chat with this model", new_<%= chat_variable_name %>_path(model: @<%= model_variable_name %>.model_id) %> |
|
|
16
|
-
<%%= link_to "All models", <%= model_table_name %>_path %>
|
|
17
|
-
|
|
18
|
-
</p>
|
|
16
|
+
<%%= link_to "All models", <%= model_table_name %>_path %>
|
|
17
|
+
</p>
|
|
@@ -53,9 +53,9 @@ module RubyLLM
|
|
|
53
53
|
params = []
|
|
54
54
|
|
|
55
55
|
add_association_params(params, :messages, message_table_name, message_model_name,
|
|
56
|
-
owner_table: chat_table_name, plural: true)
|
|
56
|
+
owner_table: chat_table_name, owner_model_name: chat_model_name, plural: true)
|
|
57
57
|
add_association_params(params, :model, model_table_name, model_model_name,
|
|
58
|
-
owner_table: chat_table_name)
|
|
58
|
+
owner_table: chat_table_name, owner_model_name: chat_model_name)
|
|
59
59
|
|
|
60
60
|
"acts_as_chat#{" #{params.join(', ')}" if params.any?}"
|
|
61
61
|
end
|
|
@@ -64,11 +64,11 @@ module RubyLLM
|
|
|
64
64
|
params = []
|
|
65
65
|
|
|
66
66
|
add_association_params(params, :chat, chat_table_name, chat_model_name,
|
|
67
|
-
owner_table: message_table_name)
|
|
67
|
+
owner_table: message_table_name, owner_model_name: message_model_name)
|
|
68
68
|
add_association_params(params, :tool_calls, tool_call_table_name, tool_call_model_name,
|
|
69
|
-
owner_table: message_table_name, plural: true)
|
|
69
|
+
owner_table: message_table_name, owner_model_name: message_model_name, plural: true)
|
|
70
70
|
add_association_params(params, :model, model_table_name, model_model_name,
|
|
71
|
-
owner_table: message_table_name)
|
|
71
|
+
owner_table: message_table_name, owner_model_name: message_model_name)
|
|
72
72
|
|
|
73
73
|
"acts_as_message#{" #{params.join(', ')}" if params.any?}"
|
|
74
74
|
end
|
|
@@ -77,7 +77,7 @@ module RubyLLM
|
|
|
77
77
|
params = []
|
|
78
78
|
|
|
79
79
|
add_association_params(params, :chats, chat_table_name, chat_model_name,
|
|
80
|
-
owner_table: model_table_name, plural: true)
|
|
80
|
+
owner_table: model_table_name, owner_model_name: model_model_name, plural: true)
|
|
81
81
|
|
|
82
82
|
"acts_as_model#{" #{params.join(', ')}" if params.any?}"
|
|
83
83
|
end
|
|
@@ -86,7 +86,7 @@ module RubyLLM
|
|
|
86
86
|
params = []
|
|
87
87
|
|
|
88
88
|
add_association_params(params, :message, message_table_name, message_model_name,
|
|
89
|
-
owner_table: tool_call_table_name)
|
|
89
|
+
owner_table: tool_call_table_name, owner_model_name: tool_call_model_name)
|
|
90
90
|
|
|
91
91
|
"acts_as_tool_call#{" #{params.join(', ')}" if params.any?}"
|
|
92
92
|
end
|
|
@@ -145,22 +145,38 @@ module RubyLLM
|
|
|
145
145
|
|
|
146
146
|
private
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
# rubocop:disable Metrics/ParameterLists
|
|
149
|
+
def add_association_params(params, default_assoc, table_name, model_name,
|
|
150
|
+
owner_table:, owner_model_name:, plural: false)
|
|
149
151
|
assoc = plural ? table_name.to_sym : table_name.singularize.to_sym
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# belongs_to: foreign key is on the owner table pointing to associated table
|
|
154
|
-
foreign_key = if plural || default_assoc.to_s.pluralize == default_assoc.to_s # has_many or has_one
|
|
155
|
-
"#{owner_table.singularize}_id"
|
|
156
|
-
else # belongs_to
|
|
157
|
-
"#{table_name.singularize}_id"
|
|
158
|
-
end
|
|
152
|
+
collection_association = collection_association?(default_assoc, plural)
|
|
153
|
+
foreign_key = inferred_foreign_key(table_name, owner_table, collection_association)
|
|
154
|
+
default_foreign_key = default_inferred_foreign_key(assoc, owner_model_name, collection_association)
|
|
159
155
|
|
|
160
156
|
params << "#{default_assoc}: :#{assoc}" if assoc != default_assoc
|
|
161
157
|
params << "#{default_assoc.to_s.singularize}_class: '#{model_name}'" if model_name != assoc.to_s.classify
|
|
162
158
|
params << "#{default_assoc}_foreign_key: :#{foreign_key}" if foreign_key != default_foreign_key
|
|
163
159
|
end
|
|
160
|
+
# rubocop:enable Metrics/ParameterLists
|
|
161
|
+
|
|
162
|
+
def collection_association?(default_assoc, plural)
|
|
163
|
+
plural || default_assoc.to_s.pluralize == default_assoc.to_s
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def inferred_foreign_key(table_name, owner_table, collection_association)
|
|
167
|
+
return "#{table_name.singularize}_id" unless collection_association
|
|
168
|
+
|
|
169
|
+
"#{owner_table.singularize}_id"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Rails default inference:
|
|
173
|
+
# belongs_to :assoc -> assoc_id
|
|
174
|
+
# has_many/has_one -> owner demodulized model name + _id
|
|
175
|
+
def default_inferred_foreign_key(association_name, owner_model_name, collection_association)
|
|
176
|
+
return "#{association_name}_id" unless collection_association
|
|
177
|
+
|
|
178
|
+
"#{owner_model_name.demodulize.underscore}_id"
|
|
179
|
+
end
|
|
164
180
|
|
|
165
181
|
# Convert namespaced model names to proper table names
|
|
166
182
|
# e.g., "Assistant::Chat" -> "assistant_chats" (not "assistant/chats")
|