ruby_llm 1.6.4 → 1.7.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 +6 -3
- data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +115 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +39 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +24 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +14 -0
- data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +12 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +29 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt +11 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +23 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt +21 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt +10 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +9 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +30 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +18 -0
- data/lib/generators/ruby_llm/install/templates/chat_model.rb.tt +2 -2
- data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +4 -4
- data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +8 -7
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +43 -0
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +6 -5
- data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +10 -4
- data/lib/generators/ruby_llm/install/templates/message_model.rb.tt +4 -3
- data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +2 -2
- data/lib/generators/ruby_llm/install_generator.rb +129 -33
- data/lib/generators/ruby_llm/upgrade_to_v1_7/templates/migration.rb.tt +137 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_7_generator.rb +160 -0
- data/lib/ruby_llm/active_record/acts_as.rb +111 -327
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +398 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +336 -0
- data/lib/ruby_llm/active_record/message_methods.rb +72 -0
- data/lib/ruby_llm/active_record/model_methods.rb +84 -0
- data/lib/ruby_llm/aliases.json +54 -13
- data/lib/ruby_llm/attachment.rb +20 -0
- data/lib/ruby_llm/chat.rb +5 -5
- data/lib/ruby_llm/configuration.rb +9 -0
- data/lib/ruby_llm/connection.rb +4 -4
- data/lib/ruby_llm/model/info.rb +12 -0
- data/lib/ruby_llm/models.json +3579 -2029
- data/lib/ruby_llm/models.rb +51 -22
- data/lib/ruby_llm/provider.rb +3 -3
- data/lib/ruby_llm/providers/anthropic/chat.rb +2 -2
- data/lib/ruby_llm/providers/anthropic/media.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/chat.rb +2 -2
- data/lib/ruby_llm/providers/bedrock/models.rb +19 -1
- data/lib/ruby_llm/providers/gemini/chat.rb +1 -1
- data/lib/ruby_llm/providers/gemini/media.rb +1 -1
- data/lib/ruby_llm/providers/gpustack/chat.rb +11 -0
- data/lib/ruby_llm/providers/gpustack/media.rb +45 -0
- data/lib/ruby_llm/providers/gpustack/models.rb +44 -8
- data/lib/ruby_llm/providers/gpustack.rb +1 -0
- data/lib/ruby_llm/providers/ollama/media.rb +2 -6
- data/lib/ruby_llm/providers/ollama/models.rb +36 -0
- data/lib/ruby_llm/providers/ollama.rb +1 -0
- data/lib/ruby_llm/providers/openai/chat.rb +1 -1
- data/lib/ruby_llm/providers/openai/media.rb +4 -4
- data/lib/ruby_llm/providers/openai/tools.rb +11 -6
- data/lib/ruby_llm/providers/openai.rb +2 -2
- data/lib/ruby_llm/providers/vertexai/chat.rb +14 -0
- data/lib/ruby_llm/providers/vertexai/embeddings.rb +32 -0
- data/lib/ruby_llm/providers/vertexai/models.rb +130 -0
- data/lib/ruby_llm/providers/vertexai/streaming.rb +14 -0
- data/lib/ruby_llm/providers/vertexai.rb +55 -0
- data/lib/ruby_llm/railtie.rb +20 -3
- data/lib/ruby_llm/streaming.rb +1 -1
- data/lib/ruby_llm/utils.rb +5 -9
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/ruby_llm.rb +4 -3
- data/lib/tasks/models.rake +39 -28
- data/lib/tasks/ruby_llm.rake +15 -0
- data/lib/tasks/vcr.rake +2 -2
- metadata +36 -2
- data/lib/generators/ruby_llm/install/templates/INSTALL_INFO.md.tt +0 -108
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a7c8f498c7fee7618711944119c65a33f8a2236a87cbd55d51b5e5a5d25000f
|
4
|
+
data.tar.gz: 2bb4675e6bcad95099330783697c87c7d6eade98c159a6b00247c7e179f7bd9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06e41bd54bcf1c7c094750b67c494decf50e9db53a250d4732455742d688aa08c72669ba64f4cc771fa3a1ad5197f646ce58308be1f3fd7db84b21282180135b
|
7
|
+
data.tar.gz: '08c739bbdb44380720e817704d9f980b49b6a7bafd80d890a3207531afe746d9039e2e3e0d6adf82e496b8ce16d68fa0ee8359ccf63cecf08de778e07fe6b632'
|
data/README.md
CHANGED
@@ -9,14 +9,17 @@
|
|
9
9
|
|
10
10
|
Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="https://chatwithwork.com/logotype-dark.svg"><img src="https://chatwithwork.com/logotype.svg" alt="Chat with Work" height="30" align="absmiddle"></picture>](https://chatwithwork.com) — *Claude Code for your documents*
|
11
11
|
|
12
|
-
[](https://badge.fury.io/rb/ruby_llm)
|
13
13
|
[](https://github.com/testdouble/standard)
|
14
14
|
[](https://rubygems.org/gems/ruby_llm)
|
15
|
-
[](https://codecov.io/gh/crmne/ruby_llm)
|
16
16
|
|
17
17
|
<a href="https://trendshift.io/repositories/13640" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13640" alt="crmne%2Fruby_llm | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
18
18
|
</div>
|
19
19
|
|
20
|
+
> [!NOTE]
|
21
|
+
> Using RubyLLM in production? [Share your story](https://tally.so/r/3Na02p)! Takes 5 minutes.
|
22
|
+
|
20
23
|
---
|
21
24
|
|
22
25
|
Build chatbots, AI agents, RAG applications. Works with OpenAI, Anthropic, Google, AWS, local models, and any OpenAI-compatible API.
|
@@ -108,7 +111,7 @@ response = chat.with_schema(ProductSchema).ask "Analyze this product", with: "pr
|
|
108
111
|
* **Rails:** ActiveRecord integration with `acts_as_chat`
|
109
112
|
* **Async:** Fiber-based concurrency
|
110
113
|
* **Model registry:** 500+ models with capability detection and pricing
|
111
|
-
* **Providers:** OpenAI, Anthropic, Gemini, Bedrock, DeepSeek, Mistral, Ollama, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API
|
114
|
+
* **Providers:** OpenAI, Anthropic, Gemini, VertexAI, Bedrock, DeepSeek, Mistral, Ollama, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API
|
112
115
|
|
113
116
|
## Installation
|
114
117
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
|
5
|
+
module RubyLLM
|
6
|
+
module Generators
|
7
|
+
# Generates a simple chat UI scaffold for RubyLLM
|
8
|
+
class ChatUIGenerator < Rails::Generators::Base
|
9
|
+
source_root File.expand_path('templates', __dir__)
|
10
|
+
|
11
|
+
namespace 'ruby_llm:chat_ui'
|
12
|
+
|
13
|
+
argument :model_mappings, type: :array, default: [], banner: 'chat:ChatName message:MessageName ...'
|
14
|
+
|
15
|
+
desc 'Creates a chat UI scaffold with Turbo streaming\n' \
|
16
|
+
'Usage: rails g ruby_llm:chat_ui [chat:ChatName] [message:MessageName] ...'
|
17
|
+
|
18
|
+
def parse_model_mappings
|
19
|
+
@model_names = {
|
20
|
+
chat: 'Chat',
|
21
|
+
message: 'Message',
|
22
|
+
tool_call: 'ToolCall',
|
23
|
+
model: 'Model'
|
24
|
+
}
|
25
|
+
|
26
|
+
model_mappings.each do |mapping|
|
27
|
+
if mapping.include?(':')
|
28
|
+
key, value = mapping.split(':', 2)
|
29
|
+
@model_names[key.to_sym] = value.classify
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@model_names
|
34
|
+
end
|
35
|
+
|
36
|
+
%i[chat message model].each do |type|
|
37
|
+
define_method("#{type}_model_name") do
|
38
|
+
@model_names ||= parse_model_mappings
|
39
|
+
@model_names[type]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_views
|
44
|
+
# Chat views
|
45
|
+
template 'views/chats/index.html.erb', "app/views/#{chat_model_name.tableize}/index.html.erb"
|
46
|
+
template 'views/chats/new.html.erb', "app/views/#{chat_model_name.tableize}/new.html.erb"
|
47
|
+
template 'views/chats/show.html.erb', "app/views/#{chat_model_name.tableize}/show.html.erb"
|
48
|
+
template 'views/chats/_chat.html.erb',
|
49
|
+
"app/views/#{chat_model_name.tableize}/_#{chat_model_name.underscore}.html.erb"
|
50
|
+
template 'views/chats/_form.html.erb', "app/views/#{chat_model_name.tableize}/_form.html.erb"
|
51
|
+
|
52
|
+
# Message views
|
53
|
+
template 'views/messages/_message.html.erb',
|
54
|
+
"app/views/#{message_model_name.tableize}/_#{message_model_name.underscore}.html.erb"
|
55
|
+
template 'views/messages/_form.html.erb', "app/views/#{message_model_name.tableize}/_form.html.erb"
|
56
|
+
template 'views/messages/create.turbo_stream.erb',
|
57
|
+
"app/views/#{message_model_name.tableize}/create.turbo_stream.erb"
|
58
|
+
|
59
|
+
# Model views
|
60
|
+
template 'views/models/index.html.erb', "app/views/#{model_model_name.tableize}/index.html.erb"
|
61
|
+
template 'views/models/show.html.erb', "app/views/#{model_model_name.tableize}/show.html.erb"
|
62
|
+
template 'views/models/_model.html.erb',
|
63
|
+
"app/views/#{model_model_name.tableize}/_#{model_model_name.underscore}.html.erb"
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_controllers
|
67
|
+
template 'controllers/chats_controller.rb', "app/controllers/#{chat_model_name.tableize}_controller.rb"
|
68
|
+
template 'controllers/messages_controller.rb', "app/controllers/#{message_model_name.tableize}_controller.rb"
|
69
|
+
template 'controllers/models_controller.rb', "app/controllers/#{model_model_name.tableize}_controller.rb"
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_jobs
|
73
|
+
template 'jobs/chat_response_job.rb', "app/jobs/#{chat_model_name.underscore}_response_job.rb"
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_routes
|
77
|
+
model_routes = <<~ROUTES.strip
|
78
|
+
resources :#{model_model_name.tableize}, only: [:index, :show] do
|
79
|
+
collection do
|
80
|
+
post :refresh
|
81
|
+
end
|
82
|
+
end
|
83
|
+
ROUTES
|
84
|
+
route model_routes
|
85
|
+
chat_routes = <<~ROUTES.strip
|
86
|
+
resources :#{chat_model_name.tableize} do
|
87
|
+
resources :#{message_model_name.tableize}, only: [:create]
|
88
|
+
end
|
89
|
+
ROUTES
|
90
|
+
route chat_routes
|
91
|
+
end
|
92
|
+
|
93
|
+
def add_broadcasting_to_message_model
|
94
|
+
msg_var = message_model_name.underscore
|
95
|
+
chat_var = chat_model_name.underscore
|
96
|
+
broadcasting_code = "broadcasts_to ->(#{msg_var}) { \"#{chat_var}_\#{#{msg_var}.#{chat_var}_id}\" }"
|
97
|
+
|
98
|
+
inject_into_class "app/models/#{msg_var}.rb", message_model_name do
|
99
|
+
"\n #{broadcasting_code}\n"
|
100
|
+
end
|
101
|
+
rescue Errno::ENOENT
|
102
|
+
say "#{message_model_name} model not found. Add broadcasting code to your model.", :yellow
|
103
|
+
say " #{broadcasting_code}", :yellow
|
104
|
+
end
|
105
|
+
|
106
|
+
def display_post_install_message
|
107
|
+
return unless behavior == :invoke
|
108
|
+
|
109
|
+
say "\n ✅ Chat UI installed!", :green
|
110
|
+
say "\n Start your server and visit http://localhost:3000/#{chat_model_name.tableize}", :cyan
|
111
|
+
say "\n"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class <%= chat_model_name.pluralize %>Controller < ApplicationController
|
2
|
+
before_action :set_<%= chat_model_name.underscore %>, only: [:show]
|
3
|
+
|
4
|
+
def index
|
5
|
+
@<%= chat_model_name.tableize %> = <%= chat_model_name %>.order(created_at: :desc)
|
6
|
+
end
|
7
|
+
|
8
|
+
def new
|
9
|
+
@<%= chat_model_name.underscore %> = <%= chat_model_name %>.new
|
10
|
+
@selected_model = params[:model]
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
return unless prompt.present?
|
15
|
+
|
16
|
+
@<%= chat_model_name.underscore %> = <%= chat_model_name %>.create!(model: model)
|
17
|
+
<%= chat_model_name %>ResponseJob.perform_later(@<%= chat_model_name.underscore %>.id, prompt)
|
18
|
+
|
19
|
+
redirect_to @<%= chat_model_name.underscore %>, notice: '<%= chat_model_name.humanize %> was successfully created.'
|
20
|
+
end
|
21
|
+
|
22
|
+
def show
|
23
|
+
@<%= message_model_name.underscore %> = @<%= chat_model_name.underscore %>.<%= message_model_name.tableize %>.build
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def set_<%= chat_model_name.underscore %>
|
29
|
+
@<%= chat_model_name.underscore %> = <%= chat_model_name %>.find(params[:id])
|
30
|
+
end
|
31
|
+
|
32
|
+
def model
|
33
|
+
params[:<%= chat_model_name.underscore %>][:model].presence
|
34
|
+
end
|
35
|
+
|
36
|
+
def prompt
|
37
|
+
params[:<%= chat_model_name.underscore %>][:prompt]
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class <%= message_model_name.pluralize %>Controller < ApplicationController
|
2
|
+
before_action :set_<%= chat_model_name.underscore %>
|
3
|
+
|
4
|
+
def create
|
5
|
+
return unless content.present?
|
6
|
+
|
7
|
+
<%= chat_model_name %>ResponseJob.perform_later(@<%= chat_model_name.underscore %>.id, content)
|
8
|
+
|
9
|
+
respond_to do |format|
|
10
|
+
format.turbo_stream
|
11
|
+
format.html { redirect_to @<%= chat_model_name.underscore %> }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_<%= chat_model_name.underscore %>
|
18
|
+
@<%= chat_model_name.underscore %> = <%= chat_model_name %>.find(params[:<%= chat_model_name.underscore %>_id])
|
19
|
+
end
|
20
|
+
|
21
|
+
def content
|
22
|
+
params[:<%= message_model_name.underscore %>][:content]
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class <%= model_model_name.pluralize %>Controller < ApplicationController
|
2
|
+
def index
|
3
|
+
@<%= model_model_name.tableize %> = <%= model_model_name %>.all.group_by(&:provider)
|
4
|
+
end
|
5
|
+
|
6
|
+
def show
|
7
|
+
@<%= model_model_name.underscore %> = <%= model_model_name %>.find(params[:id])
|
8
|
+
end
|
9
|
+
|
10
|
+
def refresh
|
11
|
+
<%= model_model_name %>.refresh!
|
12
|
+
redirect_to <%= model_model_name.tableize %>_path, notice: "<%= model_model_name.pluralize %> refreshed successfully"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class <%= chat_model_name %>ResponseJob < ApplicationJob
|
2
|
+
def perform(<%= chat_model_name.underscore %>_id, content)
|
3
|
+
<%= chat_model_name.underscore %> = <%= chat_model_name %>.find(<%= chat_model_name.underscore %>_id)
|
4
|
+
|
5
|
+
<%= chat_model_name.underscore %>.ask(content) do |chunk|
|
6
|
+
if chunk.content && !chunk.content.blank?
|
7
|
+
<%= message_model_name.underscore %> = <%= chat_model_name.underscore %>.<%= message_model_name.tableize %>.last
|
8
|
+
<%= message_model_name.underscore %>.update!(content: <%= message_model_name.underscore %>.content + chunk.content)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div id="<%%= dom_id <%= chat_model_name.underscore %> %>">
|
2
|
+
<div>
|
3
|
+
<strong>Model:</strong>
|
4
|
+
<%%= <%= chat_model_name.underscore %>.model_association.name %>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div>
|
8
|
+
<strong>Messages:</strong>
|
9
|
+
<%%= <%= chat_model_name.underscore %>.messages_association.count %>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div>
|
13
|
+
<strong>Created:</strong>
|
14
|
+
<%%= <%= chat_model_name.underscore %>.created_at.strftime("%B %d, %Y at %I:%M %p") %>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<%%= form_with(model: <%= chat_model_name.underscore %>, url: <%= chat_model_name.tableize %>_path) do |form| %>
|
2
|
+
<%% if <%= chat_model_name.underscore %>.errors.any? %>
|
3
|
+
<div style="color: red">
|
4
|
+
<h2><%%= pluralize(<%= chat_model_name.underscore %>.errors.count, "error") %> prohibited this <%= chat_model_name.underscore.humanize.downcase %> from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<%% <%= chat_model_name.underscore %>.errors.each do |error| %>
|
8
|
+
<li><%%= error.full_message %></li>
|
9
|
+
<%% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<%% end %>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%%= form.label :model, "Select AI model:", style: "display: block" %>
|
16
|
+
<%%= form.select :model,
|
17
|
+
options_for_select(<%= model_model_name %>.pluck(:name, :model_id).unshift(["Default (#{RubyLLM.config.default_model})", nil]), @selected_model),
|
18
|
+
{},
|
19
|
+
style: "width: 100%; max-width: 600px; padding: 5px;" %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div style="margin-top: 15px;">
|
23
|
+
<%%= form.text_field :prompt, style: "width: 100%; max-width: 600px;", placeholder: "What would you like to discuss?", autofocus: true %>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<div>
|
27
|
+
<%%= form.submit "Start new <%= chat_model_name.underscore.humanize.downcase %>" %>
|
28
|
+
</div>
|
29
|
+
<%% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<p style="color: green"><%%= notice %></p>
|
2
|
+
|
3
|
+
<%% content_for :title, "<%= chat_model_name.pluralize %>" %>
|
4
|
+
|
5
|
+
<h1><%= chat_model_name.pluralize %></h1>
|
6
|
+
|
7
|
+
<div id="<%= chat_model_name.tableize %>">
|
8
|
+
<%% @<%= chat_model_name.tableize %>.each do |<%= chat_model_name.underscore %>| %>
|
9
|
+
<%%= render <%= chat_model_name.underscore %> %>
|
10
|
+
<p>
|
11
|
+
<%%= link_to "Show this <%= chat_model_name.underscore.humanize.downcase %>", <%= chat_model_name.underscore %> %>
|
12
|
+
</p>
|
13
|
+
<%% end %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<%%= link_to "New <%= chat_model_name.underscore.humanize.downcase %>", new_<%= chat_model_name.underscore %>_path %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%% content_for :title, "New <%= chat_model_name.underscore.humanize.downcase %>" %>
|
2
|
+
|
3
|
+
<h1>New <%= chat_model_name.underscore.humanize.downcase %></h1>
|
4
|
+
|
5
|
+
<%%= render "form", <%= chat_model_name.underscore %>: @<%= chat_model_name.underscore %> %>
|
6
|
+
|
7
|
+
<br>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%%= link_to "Back to <%= chat_model_name.tableize.humanize.downcase %>", <%= chat_model_name.tableize %>_path %>
|
11
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<p style="color: green"><%%= notice %></p>
|
2
|
+
|
3
|
+
<%%= turbo_stream_from "<%= chat_model_name.underscore %>_#{@<%= chat_model_name.underscore %>.id}" %>
|
4
|
+
|
5
|
+
<%% content_for :title, "<%= chat_model_name %>" %>
|
6
|
+
|
7
|
+
<h1><%= chat_model_name %> <%%= @<%= chat_model_name.underscore %>.id %></h1>
|
8
|
+
|
9
|
+
<p>Using <strong><%%= @<%= chat_model_name.underscore %>.model_association.name %></strong></p>
|
10
|
+
|
11
|
+
<div id="<%= message_model_name.tableize %>">
|
12
|
+
<%% @<%= chat_model_name.underscore %>.messages_association.where.not(id: nil).each do |<%= message_model_name.underscore %>| %>
|
13
|
+
<%%= render "<%= message_model_name.tableize %>/<%= message_model_name.underscore %>", <%= message_model_name.underscore %>: <%= message_model_name.underscore %> %>
|
14
|
+
<%% end %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div style="margin-top: 30px;">
|
18
|
+
<%%= render "<%= message_model_name.tableize %>/form", <%= chat_model_name.underscore %>: @<%= chat_model_name.underscore %>, <%= message_model_name.underscore %>: @<%= message_model_name.underscore %> %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div style="margin-top: 20px;">
|
22
|
+
<%%= link_to "Back to <%= chat_model_name.tableize.humanize.downcase %>", <%= chat_model_name.tableize %>_path %>
|
23
|
+
</div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<%%= form_with(model: [<%= chat_model_name.underscore %>, <%= message_model_name.underscore %>], id: "new_<%= message_model_name.underscore %>") do |form| %>
|
2
|
+
<%% if <%= message_model_name.underscore %>.errors.any? %>
|
3
|
+
<div style="color: red">
|
4
|
+
<h2><%%= pluralize(<%= message_model_name.underscore %>.errors.count, "error") %> prohibited this <%= message_model_name.underscore.humanize.downcase %> from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<%% <%= message_model_name.underscore %>.errors.each do |error| %>
|
8
|
+
<li><%%= error.full_message %></li>
|
9
|
+
<%% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<%% end %>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%%= form.text_field :content, style: "width: 100%; max-width: 600px;", placeholder: "Message...", autofocus: true %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div>
|
19
|
+
<%%= form.submit "Send <%= message_model_name.underscore.humanize.downcase %>" %>
|
20
|
+
</div>
|
21
|
+
<%% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%%= tag.div id: dom_id(<%= message_model_name.underscore %>), class: "<%= message_model_name.underscore %>",
|
2
|
+
style: "margin-bottom: 20px; padding: 10px; border-left: 3px solid #{<%= message_model_name.underscore %>.role == 'user' ? '#007bff' : '#28a745'};" do %>
|
3
|
+
<div style="font-weight: bold; margin-bottom: 5px;">
|
4
|
+
<%%= <%= message_model_name.underscore %>.role&.capitalize %>
|
5
|
+
</div>
|
6
|
+
<div style="white-space: pre-wrap;"><%%= <%= message_model_name.underscore %>.content %></div>
|
7
|
+
<div style="font-size: 0.85em; color: #666; margin-top: 5px;">
|
8
|
+
<%%= <%= message_model_name.underscore %>.created_at&.strftime("%I:%M %p") %>
|
9
|
+
</div>
|
10
|
+
<%% end %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%%= turbo_stream.append "<%= message_model_name.tableize %>" do %>
|
2
|
+
<%% @<%= chat_model_name.underscore %>.messages_association.last(2).each do |<%= message_model_name.underscore %>| %>
|
3
|
+
<%%= render "<%= message_model_name.tableize %>/<%= message_model_name.underscore %>", <%= message_model_name.underscore %>: <%= message_model_name.underscore %> %>
|
4
|
+
<%% end %>
|
5
|
+
<%% end %>
|
6
|
+
|
7
|
+
<%%= turbo_stream.replace "new_<%= message_model_name.underscore %>" do %>
|
8
|
+
<%%= render "<%= message_model_name.tableize %>/form", <%= chat_model_name.underscore %>: @<%= chat_model_name.underscore %>, <%= message_model_name.underscore %>: @<%= chat_model_name.underscore %>.messages_association.build %>
|
9
|
+
<%% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<tr id="<%%= dom_id <%= model_model_name.underscore %> %>">
|
2
|
+
<td><%%= <%= model_model_name.underscore %>.provider %></td>
|
3
|
+
<td><%%= <%= model_model_name.underscore %>.name %></td>
|
4
|
+
<td><%%= number_with_delimiter(<%= model_model_name.underscore %>.context_window) if <%= model_model_name.underscore %>.context_window %></td>
|
5
|
+
<td>
|
6
|
+
<%% if <%= model_model_name.underscore %>.pricing && <%= model_model_name.underscore %>.pricing['text_tokens'] && <%= model_model_name.underscore %>.pricing['text_tokens']['standard'] %>
|
7
|
+
<%% input = <%= model_model_name.underscore %>.pricing['text_tokens']['standard']['input_per_million'] %>
|
8
|
+
<%% output = <%= model_model_name.underscore %>.pricing['text_tokens']['standard']['output_per_million'] %>
|
9
|
+
<%% if input && output %>
|
10
|
+
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
11
|
+
<%% end %>
|
12
|
+
<%% end %>
|
13
|
+
</td>
|
14
|
+
<td><%%= link_to "Show", <%= model_model_name.underscore %> %></td>
|
15
|
+
<td><%%= link_to "Start <%= chat_model_name.underscore.humanize.downcase %>", new_<%= chat_model_name.underscore %>_path(model: <%= model_model_name.underscore %>.model_id) %></td>
|
16
|
+
</tr>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<p style="color: green"><%%= notice %></p>
|
2
|
+
|
3
|
+
<%% content_for :title, "<%= model_model_name.pluralize %>" %>
|
4
|
+
|
5
|
+
<h1><%= model_model_name.pluralize %></h1>
|
6
|
+
|
7
|
+
<p>
|
8
|
+
<%%= button_to "Refresh <%= model_model_name.pluralize %>", refresh_<%= model_model_name.tableize %>_path, method: :post %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<div id="<%= model_model_name.tableize %>">
|
12
|
+
<table>
|
13
|
+
<thead>
|
14
|
+
<tr>
|
15
|
+
<th>Provider</th>
|
16
|
+
<th>Model</th>
|
17
|
+
<th>Context Window</th>
|
18
|
+
<th>$/1M tokens (In/Out)</th>
|
19
|
+
<th colspan="2"></th>
|
20
|
+
</tr>
|
21
|
+
</thead>
|
22
|
+
<tbody>
|
23
|
+
<%% @<%= model_model_name.tableize %>.values.flatten.each do |<%= model_model_name.underscore %>| %>
|
24
|
+
<%%= render <%= model_model_name.underscore %> %>
|
25
|
+
<%% end %>
|
26
|
+
</tbody>
|
27
|
+
</table>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<%%= link_to "Back to <%= chat_model_name.tableize.humanize.downcase %>", <%= chat_model_name.tableize %>_path %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%% content_for :title, @model.name %>
|
2
|
+
|
3
|
+
<h1><%%= @model.name %></h1>
|
4
|
+
|
5
|
+
<p><strong>ID:</strong> <%%= @model.model_id %></p>
|
6
|
+
<p><strong>Provider:</strong> <%%= @model.provider %></p>
|
7
|
+
<p><strong>Context Window:</strong> <%%= number_with_delimiter(@model.context_window) %> tokens</p>
|
8
|
+
<p><strong>Max Output:</strong> <%%= number_with_delimiter(@model.max_output_tokens) %> tokens</p>
|
9
|
+
|
10
|
+
<%% if @model.capabilities.any? %>
|
11
|
+
<p><strong>Capabilities:</strong> <%%= @model.capabilities.join(", ") %></p>
|
12
|
+
<%% end %>
|
13
|
+
|
14
|
+
<p>
|
15
|
+
<%%= link_to "Start chat with this model", new_chat_path(model: @model.model_id) %> |
|
16
|
+
<%%= link_to "All models", models_path %> |
|
17
|
+
<%%= link_to "Back to chats", chats_path %>
|
18
|
+
</p>
|
@@ -1,3 +1,3 @@
|
|
1
|
-
class <%=
|
1
|
+
class <%= chat_model_name %> < ApplicationRecord
|
2
2
|
<%= acts_as_chat_declaration %>
|
3
|
-
end
|
3
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
class Create<%=
|
1
|
+
class Create<%= chat_model_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
create_table :<%=
|
4
|
-
t.
|
3
|
+
create_table :<%= chat_model_name.tableize %> do |t|
|
4
|
+
t.references :<%= model_model_name.tableize.singularize %>, foreign_key: true
|
5
5
|
t.timestamps
|
6
6
|
end
|
7
7
|
end
|
8
|
-
end
|
8
|
+
end
|
@@ -1,15 +1,16 @@
|
|
1
|
-
|
2
|
-
class Create<%= options[:message_model_name].pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
1
|
+
class Create<%= message_model_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
3
2
|
def change
|
4
|
-
create_table :<%=
|
5
|
-
t.references :<%=
|
6
|
-
t.string :role
|
3
|
+
create_table :<%= message_model_name.tableize %> do |t|
|
4
|
+
t.references :<%= chat_model_name.tableize.singularize %>, null: false, foreign_key: true
|
5
|
+
t.string :role, null: false
|
7
6
|
t.text :content
|
8
|
-
t.
|
7
|
+
t.references :<%= model_model_name.tableize.singularize %>, foreign_key: true
|
9
8
|
t.integer :input_tokens
|
10
9
|
t.integer :output_tokens
|
11
|
-
t.references :<%=
|
10
|
+
t.references :<%= tool_call_model_name.tableize.singularize %>, foreign_key: true
|
12
11
|
t.timestamps
|
13
12
|
end
|
13
|
+
|
14
|
+
add_index :<%= message_model_name.tableize %>, :role
|
14
15
|
end
|
15
16
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Create<%= model_model_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
create_table :<%= model_model_name.tableize %> do |t|
|
4
|
+
t.string :model_id, null: false
|
5
|
+
t.string :name, null: false
|
6
|
+
t.string :provider, null: false
|
7
|
+
t.string :family
|
8
|
+
t.datetime :model_created_at
|
9
|
+
t.integer :context_window
|
10
|
+
t.integer :max_output_tokens
|
11
|
+
t.date :knowledge_cutoff
|
12
|
+
<% if postgresql? %>
|
13
|
+
t.jsonb :modalities, default: {}
|
14
|
+
t.jsonb :capabilities, default: []
|
15
|
+
t.jsonb :pricing, default: {}
|
16
|
+
t.jsonb :metadata, default: {}
|
17
|
+
<% else %>
|
18
|
+
t.json :modalities, default: {}
|
19
|
+
t.json :capabilities, default: []
|
20
|
+
t.json :pricing, default: {}
|
21
|
+
t.json :metadata, default: {}
|
22
|
+
<% end %>
|
23
|
+
t.timestamps
|
24
|
+
|
25
|
+
t.index [:provider, :model_id], unique: true
|
26
|
+
t.index :provider
|
27
|
+
t.index :family
|
28
|
+
<% if postgresql? %>
|
29
|
+
t.index :capabilities, using: :gin
|
30
|
+
t.index :modalities, using: :gin
|
31
|
+
<% end %>
|
32
|
+
end
|
33
|
+
|
34
|
+
# Load models from JSON
|
35
|
+
say_with_time "Loading models from models.json" do
|
36
|
+
RubyLLM.models.load_from_json!
|
37
|
+
model_class = '<%= model_model_name %>'.constantize
|
38
|
+
model_class.save_to_database
|
39
|
+
|
40
|
+
"Loaded #{model_class.count} models"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
<%#- # Migration for creating tool_calls table with database-specific JSON handling -%>
|
2
|
-
class Create<%=
|
2
|
+
class Create<%= tool_call_model_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
3
3
|
def change
|
4
|
-
create_table :<%=
|
5
|
-
t.references :<%=
|
4
|
+
create_table :<%= tool_call_model_name.tableize %> do |t|
|
5
|
+
t.references :<%= message_model_name.tableize.singularize %>, null: false, foreign_key: true
|
6
6
|
t.string :tool_call_id, null: false
|
7
7
|
t.string :name, null: false
|
8
8
|
t.<%= postgresql? ? 'jsonb' : 'json' %> :arguments, default: {}
|
9
9
|
t.timestamps
|
10
10
|
end
|
11
11
|
|
12
|
-
add_index :<%=
|
12
|
+
add_index :<%= tool_call_model_name.tableize %>, :tool_call_id, unique: true
|
13
|
+
add_index :<%= tool_call_model_name.tableize %>, :name
|
13
14
|
end
|
14
|
-
end
|
15
|
+
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
RubyLLM.configure do |config|
|
2
|
-
config.openai_api_key =
|
3
|
-
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
4
|
-
|
2
|
+
config.openai_api_key = Rails.application.credentials.dig(:openai_api_key)
|
5
3
|
# config.default_model = "gpt-4.1-nano"
|
6
|
-
|
4
|
+
|
5
|
+
# Use the new association-based acts_as API (recommended)
|
6
|
+
config.use_new_acts_as = true
|
7
|
+
<% if model_model_name != 'Model' -%>
|
8
|
+
|
9
|
+
# Custom model registry class name
|
10
|
+
config.model_registry_class = "<%= model_model_name %>"
|
11
|
+
<% end -%>
|
12
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
-
class <%=
|
2
|
-
<%= acts_as_message_declaration %>
|
3
|
-
end
|
1
|
+
class <%= message_model_name %> < ApplicationRecord
|
2
|
+
<%= acts_as_message_declaration %><% unless options[:skip_active_storage] %>
|
3
|
+
has_many_attached :attachments<% end %>
|
4
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
class <%=
|
1
|
+
class <%= tool_call_model_name %> < ApplicationRecord
|
2
2
|
<%= acts_as_tool_call_declaration %>
|
3
|
-
end
|
3
|
+
end
|