From 4bfd1724ecc36f347e001afbcc94bc47c055949d Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Tue, 10 Dec 2024 10:51:50 -0500
Subject: [PATCH 01/14] Add test language model button
---
.../settings/language_models_controller.rb | 8 ++++++-
app/models/language_model.rb | 4 ++++
app/services/ai_backend.rb | 1 +
app/services/ai_backend/anthropic.rb | 12 +++++++++++
app/services/ai_backend/open_ai.rb | 14 +++++++++++++
.../settings/language_models/_form.html.erb | 21 ++++++++++++++++++-
6 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index 5c99396f..89b564c3 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -27,7 +27,13 @@ def create
end
def update
- if @language_model.update(language_model_params)
+ if params[:test_language_model]
+ answer = @language_model.test_api
+ # TODO: Remove this and add testing route and turbo stream update
+ redirect_to settings_language_models_path, notice: "Test result: #{answer}", status: :see_other
+ #flash.now[:notice] = "Test result: #{answer}"
+ #render :edit, status: :unprocessable_entity
+ elsif @language_model.update(language_model_params)
redirect_to settings_language_models_path, notice: "Saved", status: :see_other
else
render :edit, status: :unprocessable_entity
diff --git a/app/models/language_model.rb b/app/models/language_model.rb
index a0e48e8d..4fb758b5 100644
--- a/app/models/language_model.rb
+++ b/app/models/language_model.rb
@@ -31,6 +31,10 @@ def supports_tools?
api_service.name != "Groq" # TODO: Remove this short circuit once I can debug tool use with Groq
end
+ def test_api
+ ai_backend.test_language_model(self)
+ end
+
private
def populate_position
diff --git a/app/services/ai_backend.rb b/app/services/ai_backend.rb
index d4204f08..f92142da 100644
--- a/app/services/ai_backend.rb
+++ b/app/services/ai_backend.rb
@@ -2,6 +2,7 @@ class AIBackend
include Utilities, Tools
attr :client
+ attr :test_language_model
def initialize(user, assistant, conversation = nil, message = nil)
@user = user
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index f8a4d5d9..6709e034 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -25,6 +25,18 @@ def initialize(user, assistant, conversation = nil, message = nil)
end
end
+ def self.test_language_model(language_model)
+ client = ::Anthropic::Client.new(uri_base: language_model.api_service.url, access_token: language_model.api_service.effective_token)
+
+ # client.messages(parameters: {
+ # model: language_model.api_name,
+ # messages: [{ role: "user", content: "Hello!" }],
+ # }).dig("content", 0, "text")
+ "Not Implemented"
+ rescue ::Faraday::Error => e
+ e.message
+ end
+
private
def client_method_name
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index aa8bd600..37f85d2f 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -25,6 +25,20 @@ def initialize(user, assistant, conversation = nil, message = nil)
end
end
+ def self.test_language_model(language_model)
+ client = ::OpenAI::Client.new(
+ access_token: language_model.api_service.effective_token,
+ uri_base: language_model.api_service.url
+ )
+
+ client.chat(parameters: {
+ model: language_model.api_name,
+ messages: [{ role: "user", content: "Hello!" }],
+ }).dig("choices", 0, "message", "content")
+ rescue ::Faraday::Error => e
+ e.message
+ end
+
private
def client_method_name
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index d8ee22f2..248cd936 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -57,7 +57,26 @@
<%= form.check_box :supports_system_message %>
<%= form.label :supports_system_message, "Supports System Message (Instructions)?" %>
-
+
+ <%= form.submit "Test",
+ name: "test_language_model",
+ class: %|
+ inline-block font-bold
+ bg-gray-200 dark:bg-gray-900
+ border border-gray-400
+ rounded-lg py-3 px-5
+ cursor-pointer
+ |,
+ data: { turbo_submits_with: "Testing..." }
+ %>
+
+
+
+ (Untested).
+
+
+
+
<%= form.submit "Save",
class: %|
inline-block font-bold
From 461a1230a73f8d651b82a3ee2d958527289a4611 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Wed, 11 Dec 2024 11:56:29 -0500
Subject: [PATCH 02/14] Test using form
---
.../settings/language_models_controller.rb | 14 +++----
app/models/language_model.rb | 2 +-
.../settings/language_models/_form.html.erb | 41 ++++++++++---------
config/routes.rb | 4 +-
4 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index 89b564c3..28bb3c1e 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -27,19 +27,19 @@ def create
end
def update
- if params[:test_language_model]
- answer = @language_model.test_api
- # TODO: Remove this and add testing route and turbo stream update
- redirect_to settings_language_models_path, notice: "Test result: #{answer}", status: :see_other
- #flash.now[:notice] = "Test result: #{answer}"
- #render :edit, status: :unprocessable_entity
- elsif @language_model.update(language_model_params)
+ if @language_model.update(language_model_params)
redirect_to settings_language_models_path, notice: "Saved", status: :see_other
else
render :edit, status: :unprocessable_entity
end
end
+ def test
+ @language_model = Current.user.language_models.find_by(id: params[:language_model_id])
+ @answer = @language_model.test
+ render :edit
+ end
+
def destroy
@language_model.deleted!
redirect_to settings_language_models_path, notice: "Deleted", status: :see_other
diff --git a/app/models/language_model.rb b/app/models/language_model.rb
index 4fb758b5..a1335842 100644
--- a/app/models/language_model.rb
+++ b/app/models/language_model.rb
@@ -31,7 +31,7 @@ def supports_tools?
api_service.name != "Groq" # TODO: Remove this short circuit once I can debug tool use with Groq
end
- def test_api
+ def test
ai_backend.test_language_model(self)
end
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 248cd936..a7081bf6 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -57,26 +57,6 @@
<%= form.check_box :supports_system_message %>
<%= form.label :supports_system_message, "Supports System Message (Instructions)?" %>
-
- <%= form.submit "Test",
- name: "test_language_model",
- class: %|
- inline-block font-bold
- bg-gray-200 dark:bg-gray-900
- border border-gray-400
- rounded-lg py-3 px-5
- cursor-pointer
- |,
- data: { turbo_submits_with: "Testing..." }
- %>
-
-
-
- (Untested).
-
-
-
-
<%= form.submit "Save",
class: %|
inline-block font-bold
@@ -87,4 +67,25 @@
|,
data: { turbo_submits_with: "Saving..." }
%>
+ <% if @answer %>
+ Tested <%= @answer %>
+ <% else %>
+ <%= form.label :test, "Test",
+ class: %|
+ inline-block font-medium
+ bg-gray-100 dark:bg-gray-900 dark:text-white
+ border border-gray-400
+ rounded-lg py-3 px-5
+ cursor-pointer
+ |
+ %>
+ <% end %>
<% end %>
+
+<%= button_to "Test",
+ settings_language_model_test_path(@language_model),
+ id: "language_model_test",
+ method: :get,
+ data: { turbo: false },
+ class: "hidden"
+%>
diff --git a/config/routes.rb b/config/routes.rb
index 73386abb..17a08926 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,7 +16,9 @@
namespace :settings do
resources :assistants, except: [:index, :show]
resource :person, only: [:edit, :update]
- resources :language_models
+ resources :language_models do
+ get :test, to: "language_models#test"
+ end
resources :api_services, except: [:show]
resources :memories, only: [:index, :destroy] do
delete :destroy, to: "memories#destroy_all", on: :collection
From cc5664953e6d38d5c481790b274c0dbe6a58ece5 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Wed, 11 Dec 2024 13:29:49 -0500
Subject: [PATCH 03/14] Switch to turbo frame
---
.../settings/language_models_controller.rb | 1 -
.../settings/language_models/_form.html.erb | 23 +------------------
.../settings/language_models/edit.html.erb | 4 ++++
.../settings/language_models/test.html.erb | 9 ++++++++
4 files changed, 14 insertions(+), 23 deletions(-)
create mode 100644 app/views/settings/language_models/test.html.erb
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index 28bb3c1e..0beaa7e8 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -37,7 +37,6 @@ def update
def test
@language_model = Current.user.language_models.find_by(id: params[:language_model_id])
@answer = @language_model.test
- render :edit
end
def destroy
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index a7081bf6..8494f87a 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -67,25 +67,4 @@
|,
data: { turbo_submits_with: "Saving..." }
%>
- <% if @answer %>
- Tested <%= @answer %>
- <% else %>
- <%= form.label :test, "Test",
- class: %|
- inline-block font-medium
- bg-gray-100 dark:bg-gray-900 dark:text-white
- border border-gray-400
- rounded-lg py-3 px-5
- cursor-pointer
- |
- %>
- <% end %>
-<% end %>
-
-<%= button_to "Test",
- settings_language_model_test_path(@language_model),
- id: "language_model_test",
- method: :get,
- data: { turbo: false },
- class: "hidden"
-%>
+<% end%>
diff --git a/app/views/settings/language_models/edit.html.erb b/app/views/settings/language_models/edit.html.erb
index 78d7a8b1..2e8eea8f 100644
--- a/app/views/settings/language_models/edit.html.erb
+++ b/app/views/settings/language_models/edit.html.erb
@@ -23,3 +23,7 @@
<%= link_to "Back", settings_language_models_path, class: "float-right inline-block ml-5 py-3" %>
+
+<%= link_to settings_language_model_test_path(@language_model), method: :get, data: { turbo_frame: :language_model_test } do %>
+ Test
+<% end %>
diff --git a/app/views/settings/language_models/test.html.erb b/app/views/settings/language_models/test.html.erb
new file mode 100644
index 00000000..74ff069b
--- /dev/null
+++ b/app/views/settings/language_models/test.html.erb
@@ -0,0 +1,9 @@
+ <%= turbo_frame_tag :language_model_test do %>
+
+ <% if @answer %>
+
Tested <%= @answer %>
+ <% else %>
+
Failed
+ <% end %>
+
+ <% end %>
From e887c0577c840ccae32dd69485aec62eb1741c12 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Wed, 11 Dec 2024 15:29:23 -0500
Subject: [PATCH 04/14] WIP. Finish test for openai
---
app/services/ai_backend/anthropic.rb | 13 +++++++++----
app/services/ai_backend/gemini.rb | 4 ++++
app/services/ai_backend/open_ai.rb | 1 +
app/views/settings/language_models/_form.html.erb | 4 ++++
app/views/settings/language_models/edit.html.erb | 4 ----
app/views/settings/language_models/test.html.erb | 4 ++--
6 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index 6709e034..7a0bcaf1 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -26,13 +26,18 @@ def initialize(user, assistant, conversation = nil, message = nil)
end
def self.test_language_model(language_model)
- client = ::Anthropic::Client.new(uri_base: language_model.api_service.url, access_token: language_model.api_service.effective_token)
+ client = ::Anthropic::Client.new(
+ uri_base: language_model.api_service.url,
+ access_token: language_model.api_service.effective_token
+ )
- # client.messages(parameters: {
+ # TODO: Implement this. Use get_oneoff_message?
+ # client.chat(parameters: {
# model: language_model.api_name,
# messages: [{ role: "user", content: "Hello!" }],
- # }).dig("content", 0, "text")
- "Not Implemented"
+ # }).dig("choices", 0, "message", "content")
+
+ "Testing Not Implemented Yet"
rescue ::Faraday::Error => e
e.message
end
diff --git a/app/services/ai_backend/gemini.rb b/app/services/ai_backend/gemini.rb
index f89447cf..e9ef49ae 100644
--- a/app/services/ai_backend/gemini.rb
+++ b/app/services/ai_backend/gemini.rb
@@ -87,6 +87,10 @@ def stream_next_conversation_message(&chunk_handler)
return nil
end
+ def self.test_language_model(language_model)
+ "Testing Not Implemented Yet"
+ end
+
private
def system_message(content)
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index 37f85d2f..1f36c56b 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -35,6 +35,7 @@ def self.test_language_model(language_model)
model: language_model.api_name,
messages: [{ role: "user", content: "Hello!" }],
}).dig("choices", 0, "message", "content")
+
rescue ::Faraday::Error => e
e.message
end
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 8494f87a..8f8905dc 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -18,6 +18,10 @@
<%= form.label :api_name %>
+ <%= turbo_frame_tag :language_model_test, class: "inline-block" do %>
+ <%= link_to "Test", settings_language_model_test_path(@language_model), class: "inline-block ml-5 py-3" %>
+ <%= render template: "settings/language_models/test" %>
+ <% end %>
<%= form.text_field :api_name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
As specified in the API docs
diff --git a/app/views/settings/language_models/edit.html.erb b/app/views/settings/language_models/edit.html.erb
index 2e8eea8f..78d7a8b1 100644
--- a/app/views/settings/language_models/edit.html.erb
+++ b/app/views/settings/language_models/edit.html.erb
@@ -23,7 +23,3 @@
<%= link_to "Back", settings_language_models_path, class: "float-right inline-block ml-5 py-3" %>
-
-<%= link_to settings_language_model_test_path(@language_model), method: :get, data: { turbo_frame: :language_model_test } do %>
- Test
-<% end %>
diff --git a/app/views/settings/language_models/test.html.erb b/app/views/settings/language_models/test.html.erb
index 74ff069b..4fba821f 100644
--- a/app/views/settings/language_models/test.html.erb
+++ b/app/views/settings/language_models/test.html.erb
@@ -1,9 +1,9 @@
<%= turbo_frame_tag :language_model_test do %>
<% if @answer %>
-
Tested <%= @answer %>
+
Result: <%= @answer %>
<% else %>
-
Failed
+
<% end %>
<% end %>
From 47a6093a9cef88b8966bb6f07fc2ca64bc7a9a9b Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Thu, 12 Dec 2024 15:38:17 -0500
Subject: [PATCH 05/14] Use turbo stream and fix for new form
---
.../settings/language_models_controller.rb | 7 ++++++-
app/models/language_model.rb | 4 ++--
app/services/ai_backend/anthropic.rb | 2 +-
app/services/ai_backend/open_ai.rb | 6 ++++--
app/views/settings/language_models/_form.html.erb | 13 ++++++++-----
app/views/settings/language_models/test.html.erb | 9 ---------
.../settings/language_models/test.turbo_stream.erb | 11 +++++++++++
7 files changed, 32 insertions(+), 20 deletions(-)
delete mode 100644 app/views/settings/language_models/test.html.erb
create mode 100644 app/views/settings/language_models/test.turbo_stream.erb
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index 0beaa7e8..0d730760 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -36,7 +36,12 @@ def update
def test
@language_model = Current.user.language_models.find_by(id: params[:language_model_id])
- @answer = @language_model.test
+ @answer = @language_model.test(params[:api_name])
+
+ respond_to do |format|
+ format.html { redirect_to settings_language_models_path, notice: "Tested", status: :see_other }
+ format.turbo_stream
+ end
end
def destroy
diff --git a/app/models/language_model.rb b/app/models/language_model.rb
index a1335842..ffd44bb0 100644
--- a/app/models/language_model.rb
+++ b/app/models/language_model.rb
@@ -31,8 +31,8 @@ def supports_tools?
api_service.name != "Groq" # TODO: Remove this short circuit once I can debug tool use with Groq
end
- def test
- ai_backend.test_language_model(self)
+ def test(api_name = nil)
+ ai_backend.test_language_model(self, api_name)
end
private
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index 7a0bcaf1..3e2da834 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -25,7 +25,7 @@ def initialize(user, assistant, conversation = nil, message = nil)
end
end
- def self.test_language_model(language_model)
+ def self.test_language_model(language_model, api_name = nil)
client = ::Anthropic::Client.new(
uri_base: language_model.api_service.url,
access_token: language_model.api_service.effective_token
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index 1f36c56b..4d38a2c1 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -25,14 +25,16 @@ def initialize(user, assistant, conversation = nil, message = nil)
end
end
- def self.test_language_model(language_model)
+ def self.test_language_model(language_model, api_name = nil)
+ api_name ||= language_model.api_name
+
client = ::OpenAI::Client.new(
access_token: language_model.api_service.effective_token,
uri_base: language_model.api_service.url
)
client.chat(parameters: {
- model: language_model.api_name,
+ model: api_name,
messages: [{ role: "user", content: "Hello!" }],
}).dig("choices", 0, "message", "content")
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 8f8905dc..0c5dde12 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -18,10 +18,12 @@
<%= form.label :api_name %>
- <%= turbo_frame_tag :language_model_test, class: "inline-block" do %>
- <%= link_to "Test", settings_language_model_test_path(@language_model), class: "inline-block ml-5 py-3" %>
- <%= render template: "settings/language_models/test" %>
- <% end %>
+
+ <% if language_model.persisted? %>
+ <%= link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
+ <%= link_to "Test", link_url, data: { turbo_stream: true }, class: "inline-block ml-5 py-3" %>
+ <% end %>
+
<%= form.text_field :api_name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
As specified in the API docs
@@ -61,6 +63,7 @@
<%= form.check_box :supports_system_message %>
<%= form.label :supports_system_message, "Supports System Message (Instructions)?" %>
+
<%= form.submit "Save",
class: %|
inline-block font-bold
@@ -71,4 +74,4 @@
|,
data: { turbo_submits_with: "Saving..." }
%>
-<% end%>
+<% end %>
diff --git a/app/views/settings/language_models/test.html.erb b/app/views/settings/language_models/test.html.erb
deleted file mode 100644
index 4fba821f..00000000
--- a/app/views/settings/language_models/test.html.erb
+++ /dev/null
@@ -1,9 +0,0 @@
- <%= turbo_frame_tag :language_model_test do %>
-
- <% if @answer %>
-
Result: <%= @answer %>
- <% else %>
-
- <% end %>
-
- <% end %>
diff --git a/app/views/settings/language_models/test.turbo_stream.erb b/app/views/settings/language_models/test.turbo_stream.erb
new file mode 100644
index 00000000..529ebdba
--- /dev/null
+++ b/app/views/settings/language_models/test.turbo_stream.erb
@@ -0,0 +1,11 @@
+
+
+
+ <% if @answer %>
+
Result: <%= @answer %>
+ <% else %>
+
No result
+ <% end %>
+
+
+
From 7701f0e6b95ada8a2d91bf5f0aaa0c1f77ac9907 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 06:26:23 -0500
Subject: [PATCH 06/14] Fix view and start adding update_url
---
app/controllers/settings/language_models_controller.rb | 6 ++++--
.../stimulus/language_model_test_controller.js | 10 ++++++++++
app/views/settings/language_models/_form.html.erb | 10 +++++-----
3 files changed, 19 insertions(+), 7 deletions(-)
create mode 100644 app/javascript/stimulus/language_model_test_controller.js
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index 0d730760..b024efeb 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -35,11 +35,13 @@ def update
end
def test
+ Rails.logger.info("TESTING LANGUAGE MODEL: #{params}")
+ Rails.logger.info("URL: #{request.fullpath}")
@language_model = Current.user.language_models.find_by(id: params[:language_model_id])
- @answer = @language_model.test(params[:api_name])
+ @answer = @language_model.test(params[:query])
respond_to do |format|
- format.html { redirect_to settings_language_models_path, notice: "Tested", status: :see_other }
+ format.html { redirect_to settings_language_models_path, notice: "Tested: #{@answer}", status: :see_other }
format.turbo_stream
end
end
diff --git a/app/javascript/stimulus/language_model_test_controller.js b/app/javascript/stimulus/language_model_test_controller.js
new file mode 100644
index 00000000..b77a3786
--- /dev/null
+++ b/app/javascript/stimulus/language_model_test_controller.js
@@ -0,0 +1,10 @@
+import { Controller } from "@hotwired/stimulus"
+static targets = ["input"]
+
+// Connects to data-controller="language-model"
+export default class extends Controller {
+ update_link(event) {
+ const link = document.getElementById("test_language_model")
+ link.href = link.href + "?query=" + event.target.value
+ }
+}
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 0c5dde12..a1b2cc72 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -16,15 +16,15 @@
<%= form.text_field :name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
-
+
<%= form.label :api_name %>
-
+
<% if language_model.persisted? %>
- <%= link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
- <%= link_to "Test", link_url, data: { turbo_stream: true }, class: "inline-block ml-5 py-3" %>
+ <% link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
+ <%= link_to "(Test)", link_url, id: "test_language_model", data: { turbo_stream: true, action: "click->test-language-model#update_link" }, class: "inline-block ml-5" %>
<% end %>
- <%= form.text_field :api_name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
+ <%= form.text_field :api_name, data-test-language-model-target: "input", class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
As specified in the API docs
From 26799e38d902d90bdbc96ea4e9a466145c496102 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 08:05:40 -0500
Subject: [PATCH 07/14] Fix stimulus target
---
app/views/settings/language_models/_form.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index a1b2cc72..31621614 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -24,7 +24,7 @@
<%= link_to "(Test)", link_url, id: "test_language_model", data: { turbo_stream: true, action: "click->test-language-model#update_link" }, class: "inline-block ml-5" %>
<% end %>
- <%= form.text_field :api_name, data-test-language-model-target: "input", class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
+ <%= form.text_field :api_name, data: { test_language_model_target: "input" }, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
As specified in the API docs
From 89123d1bf11b1c0f93019434c7fe6f2b7c7fbc3a Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 09:26:39 -0500
Subject: [PATCH 08/14] Cleanup. Still WIP.
---
app/services/ai_backend/anthropic.rb | 29 +++++++++++++---------------
app/services/ai_backend/gemini.rb | 29 ++++++++++++++++++++++++----
app/services/ai_backend/open_ai.rb | 22 ++++++++++-----------
3 files changed, 49 insertions(+), 31 deletions(-)
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index 3e2da834..49113fbf 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -14,34 +14,31 @@ def self.client
end
end
- def initialize(user, assistant, conversation = nil, message = nil)
- super(user, assistant, conversation, message)
- begin
- raise ::Anthropic::ConfigurationError if assistant.api_service.requires_token? && assistant.api_service.effective_token.blank?
- Rails.logger.info "Connecting to Anthropic API server at #{assistant.api_service.url} with access token of length #{assistant.api_service.effective_token.to_s.length}"
- @client = self.class.client.new(uri_base: assistant.api_service.url, access_token: assistant.api_service.effective_token)
- rescue ::Faraday::UnauthorizedError => e
- raise ::Anthropic::ConfigurationError
- end
- end
-
def self.test_language_model(language_model, api_name = nil)
client = ::Anthropic::Client.new(
uri_base: language_model.api_service.url,
access_token: language_model.api_service.effective_token
)
- # TODO: Implement this. Use get_oneoff_message?
- # client.chat(parameters: {
- # model: language_model.api_name,
- # messages: [{ role: "user", content: "Hello!" }],
- # }).dig("choices", 0, "message", "content")
+ # TODO: Implement this. Send: messages: [{ role: "user", content: "Hello!" }]
+ # and return the first message content.
"Testing Not Implemented Yet"
rescue ::Faraday::Error => e
e.message
end
+ def initialize(user, assistant, conversation = nil, message = nil)
+ super(user, assistant, conversation, message)
+ begin
+ raise ::Anthropic::ConfigurationError if assistant.api_service.requires_token? && assistant.api_service.effective_token.blank?
+ Rails.logger.info "Connecting to Anthropic API server at #{assistant.api_service.url} with access token of length #{assistant.api_service.effective_token.to_s.length}"
+ @client = self.class.client.new(uri_base: assistant.api_service.url, access_token: assistant.api_service.effective_token)
+ rescue ::Faraday::UnauthorizedError => e
+ raise ::Anthropic::ConfigurationError
+ end
+ end
+
private
def client_method_name
diff --git a/app/services/ai_backend/gemini.rb b/app/services/ai_backend/gemini.rb
index e9ef49ae..7072be9b 100644
--- a/app/services/ai_backend/gemini.rb
+++ b/app/services/ai_backend/gemini.rb
@@ -15,6 +15,31 @@ def self.client
end
end
+ def self.test_language_model(language_model, api_name = nil)
+ api_name ||= language_model.api_name
+
+ client = ::Gemini.new(
+ credentials: {
+ service: "generative-language-api",
+ api_key: language_model.api_service.effective_token,
+ version: "v1beta"
+ },
+ options: {
+ model: api_name,
+ server_sent_events: true
+ }
+ )
+
+ # TODO: Fix this. Response is 400 currently.
+ # response = client.generate_content({
+ # system_instruction: "Hello!",
+ # contents: { role: "user", parts: { text: "Hello!" }}
+ # })
+ # response.dig("candidates", 0, "content", "parts", 0, "text")
+
+ "Testing Not Implemented Yet"
+ end
+
def initialize(user, assistant, conversation = nil, message = nil)
super(user, assistant, conversation, message)
begin
@@ -87,10 +112,6 @@ def stream_next_conversation_message(&chunk_handler)
return nil
end
- def self.test_language_model(language_model)
- "Testing Not Implemented Yet"
- end
-
private
def system_message(content)
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index 4d38a2c1..0d773046 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -14,17 +14,6 @@ def self.client
end
end
- def initialize(user, assistant, conversation = nil, message = nil)
- super(user, assistant, conversation, message)
- begin
- raise ::OpenAI::ConfigurationError if assistant.api_service.requires_token? && assistant.api_service.effective_token.blank?
- Rails.logger.info "Connecting to OpenAI API server at #{assistant.api_service.url} with access token of length #{assistant.api_service.effective_token.to_s.length}"
- @client = self.class.client.new(uri_base: assistant.api_service.url, access_token: assistant.api_service.effective_token)
- rescue ::Faraday::UnauthorizedError => e
- raise ::OpenAI::ConfigurationError
- end
- end
-
def self.test_language_model(language_model, api_name = nil)
api_name ||= language_model.api_name
@@ -42,6 +31,17 @@ def self.test_language_model(language_model, api_name = nil)
e.message
end
+ def initialize(user, assistant, conversation = nil, message = nil)
+ super(user, assistant, conversation, message)
+ begin
+ raise ::OpenAI::ConfigurationError if assistant.api_service.requires_token? && assistant.api_service.effective_token.blank?
+ Rails.logger.info "Connecting to OpenAI API server at #{assistant.api_service.url} with access token of length #{assistant.api_service.effective_token.to_s.length}"
+ @client = self.class.client.new(uri_base: assistant.api_service.url, access_token: assistant.api_service.effective_token)
+ rescue ::Faraday::UnauthorizedError => e
+ raise ::OpenAI::ConfigurationError
+ end
+ end
+
private
def client_method_name
From d6c765ba4fdd09d49c285a2c44e2b4e1e4cbe467 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 12:54:09 -0500
Subject: [PATCH 09/14] Fix error message. Still WIP.
---
.../stimulus/language_model_test_controller.js | 10 ----------
app/javascript/stimulus/testing_controller.js | 10 ++++++++++
app/services/ai_backend/open_ai.rb | 2 +-
app/views/settings/language_models/_form.html.erb | 13 ++++++++++---
.../language_models/test.turbo_stream.erb | 15 ++++++++++-----
5 files changed, 31 insertions(+), 19 deletions(-)
delete mode 100644 app/javascript/stimulus/language_model_test_controller.js
create mode 100644 app/javascript/stimulus/testing_controller.js
diff --git a/app/javascript/stimulus/language_model_test_controller.js b/app/javascript/stimulus/language_model_test_controller.js
deleted file mode 100644
index b77a3786..00000000
--- a/app/javascript/stimulus/language_model_test_controller.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Controller } from "@hotwired/stimulus"
-static targets = ["input"]
-
-// Connects to data-controller="language-model"
-export default class extends Controller {
- update_link(event) {
- const link = document.getElementById("test_language_model")
- link.href = link.href + "?query=" + event.target.value
- }
-}
diff --git a/app/javascript/stimulus/testing_controller.js b/app/javascript/stimulus/testing_controller.js
new file mode 100644
index 00000000..dce3a5d4
--- /dev/null
+++ b/app/javascript/stimulus/testing_controller.js
@@ -0,0 +1,10 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = ["input"]
+
+ update_link(event) {
+ const link = event.currentTarget;
+ link.href = link.href + "?query=" + this.inputTarget.value
+ }
+}
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index 0d773046..1e8c5d82 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -28,7 +28,7 @@ def self.test_language_model(language_model, api_name = nil)
}).dig("choices", 0, "message", "content")
rescue ::Faraday::Error => e
- e.message
+ "Error: #{e.message}"
end
def initialize(user, assistant, conversation = nil, message = nil)
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 31621614..8bdea97e 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -16,15 +16,22 @@
<%= form.text_field :name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
-
+
<%= form.label :api_name %>
<% if language_model.persisted? %>
<% link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
- <%= link_to "(Test)", link_url, id: "test_language_model", data: { turbo_stream: true, action: "click->test-language-model#update_link" }, class: "inline-block ml-5" %>
+ <%= link_to "(Test)", link_url,
+ id: "test_result",
+ data: { turbo_stream: true, action: "click->testing#update_link" },
+ class: "inline-block ml-5"
+ %>
<% end %>
- <%= form.text_field :api_name, data: { test_language_model_target: "input" }, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
+ <%= form.text_field :api_name,
+ data: { testing_target: "input" },
+ class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black"
+ %>
As specified in the API docs
diff --git a/app/views/settings/language_models/test.turbo_stream.erb b/app/views/settings/language_models/test.turbo_stream.erb
index 529ebdba..114ac859 100644
--- a/app/views/settings/language_models/test.turbo_stream.erb
+++ b/app/views/settings/language_models/test.turbo_stream.erb
@@ -1,11 +1,16 @@
-
+
-
- <% if @answer %>
-
Result: <%= @answer %>
+
+ <% if @answer.start_with?("Error:") %>
+
<%= @answer %>
<% else %>
-
No result
+
Result: <%= @answer %>
<% end %>
+ <%= link_to "(Re-Test)",
+ settings_language_model_test_path(@language_model),
+ id: "test_result",
+ data: { turbo_stream: true, action: "click->testing#update_link" }
+ %>
From f02d7669913f85d390313f549a26afe56f9bafe1 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 17:04:55 -0500
Subject: [PATCH 10/14] Cleanup. Still WIP.
---
app/views/settings/language_models/_form.html.erb | 8 ++++----
.../language_models/test.turbo_stream.erb | 15 +++++++++------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 8bdea97e..b7f4debb 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -16,18 +16,18 @@
<%= form.text_field :name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
-
+
<%= form.label :api_name %>
-
+
<% if language_model.persisted? %>
<% link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
<%= link_to "(Test)", link_url,
id: "test_result",
data: { turbo_stream: true, action: "click->testing#update_link" },
- class: "inline-block ml-5"
+ class: "underline text-blue-600"
%>
<% end %>
-
+
<%= form.text_field :api_name,
data: { testing_target: "input" },
class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black"
diff --git a/app/views/settings/language_models/test.turbo_stream.erb b/app/views/settings/language_models/test.turbo_stream.erb
index 114ac859..ce79b122 100644
--- a/app/views/settings/language_models/test.turbo_stream.erb
+++ b/app/views/settings/language_models/test.turbo_stream.erb
@@ -1,16 +1,19 @@
-
+
+
+ <%= link_to "(Test)",
+ settings_language_model_test_path(@language_model),
+ id: "test_result",
+ data: { turbo_stream: true, action: "click->testing#update_link" },
+ class: "underline text-blue-600"
+ %>
+
<% if @answer.start_with?("Error:") %>
<%= @answer %>
<% else %>
Result: <%= @answer %>
<% end %>
- <%= link_to "(Re-Test)",
- settings_language_model_test_path(@language_model),
- id: "test_result",
- data: { turbo_stream: true, action: "click->testing#update_link" }
- %>
From 5e5b774253a4cbd0088cfa78c928f7ee4b03486c Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Fri, 13 Dec 2024 17:53:07 -0500
Subject: [PATCH 11/14] Implement for anthropic and gemini
---
.../settings/language_models_controller.rb | 2 --
app/services/ai_backend.rb | 1 -
app/services/ai_backend/anthropic.rb | 15 +++++++++++----
app/services/ai_backend/gemini.rb | 14 ++++++--------
app/views/settings/language_models/_form.html.erb | 4 ++--
5 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index b024efeb..abe323b7 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -35,8 +35,6 @@ def update
end
def test
- Rails.logger.info("TESTING LANGUAGE MODEL: #{params}")
- Rails.logger.info("URL: #{request.fullpath}")
@language_model = Current.user.language_models.find_by(id: params[:language_model_id])
@answer = @language_model.test(params[:query])
diff --git a/app/services/ai_backend.rb b/app/services/ai_backend.rb
index f92142da..d4204f08 100644
--- a/app/services/ai_backend.rb
+++ b/app/services/ai_backend.rb
@@ -2,7 +2,6 @@ class AIBackend
include Utilities, Tools
attr :client
- attr :test_language_model
def initialize(user, assistant, conversation = nil, message = nil)
@user = user
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index 49113fbf..43e669c6 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -15,16 +15,23 @@ def self.client
end
def self.test_language_model(language_model, api_name = nil)
+ api_name ||= language_model.api_name
+
client = ::Anthropic::Client.new(
uri_base: language_model.api_service.url,
access_token: language_model.api_service.effective_token
)
- # TODO: Implement this. Send: messages: [{ role: "user", content: "Hello!" }]
- # and return the first message content.
+ response = client.messages(
+ model: api_name,
+ messages: [
+ { "role": "user", "content": "Hello!" }
+ ],
+ system: "You are a helpful assistant.",
+ parameters: { max_tokens: 1000 }
+ ).dig("content", 0, "text")
- "Testing Not Implemented Yet"
- rescue ::Faraday::Error => e
+ rescue => e
e.message
end
diff --git a/app/services/ai_backend/gemini.rb b/app/services/ai_backend/gemini.rb
index 7072be9b..069d42d4 100644
--- a/app/services/ai_backend/gemini.rb
+++ b/app/services/ai_backend/gemini.rb
@@ -30,14 +30,12 @@ def self.test_language_model(language_model, api_name = nil)
}
)
- # TODO: Fix this. Response is 400 currently.
- # response = client.generate_content({
- # system_instruction: "Hello!",
- # contents: { role: "user", parts: { text: "Hello!" }}
- # })
- # response.dig("candidates", 0, "content", "parts", 0, "text")
-
- "Testing Not Implemented Yet"
+ client.generate_content({
+ contents: { role: "user", parts: { text: "Hello!" }}
+ }).dig("candidates", 0, "content", "parts", 0, "text")
+
+ rescue ::Faraday::Error => e
+ "Error: #{e.message}"
end
def initialize(user, assistant, conversation = nil, message = nil)
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index b7f4debb..4e19845f 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -16,7 +16,7 @@
<%= form.text_field :name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
-
+
<%= form.label :api_name %>
<% if language_model.persisted? %>
@@ -31,7 +31,7 @@
<%= form.text_field :api_name,
data: { testing_target: "input" },
class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black"
- %>
+ %>
As specified in the API docs
From 6b1cbad278c2dde601c42158f67fbb698eb8f21c Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Sat, 14 Dec 2024 08:04:24 -0500
Subject: [PATCH 12/14] Add controller test
---
.../settings/language_models_controller.rb | 2 +-
app/javascript/stimulus/testing_controller.js | 2 +-
app/services/ai_backend/anthropic.rb | 2 +-
app/services/ai_backend/open_ai.rb | 25 +++++++++++++------
.../language_models_controller_test.rb | 8 ++++++
5 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/app/controllers/settings/language_models_controller.rb b/app/controllers/settings/language_models_controller.rb
index abe323b7..70f6d3bf 100644
--- a/app/controllers/settings/language_models_controller.rb
+++ b/app/controllers/settings/language_models_controller.rb
@@ -36,7 +36,7 @@ def update
def test
@language_model = Current.user.language_models.find_by(id: params[:language_model_id])
- @answer = @language_model.test(params[:query])
+ @answer = @language_model.test(params[:model])
respond_to do |format|
format.html { redirect_to settings_language_models_path, notice: "Tested: #{@answer}", status: :see_other }
diff --git a/app/javascript/stimulus/testing_controller.js b/app/javascript/stimulus/testing_controller.js
index dce3a5d4..78b455a5 100644
--- a/app/javascript/stimulus/testing_controller.js
+++ b/app/javascript/stimulus/testing_controller.js
@@ -5,6 +5,6 @@ export default class extends Controller {
update_link(event) {
const link = event.currentTarget;
- link.href = link.href + "?query=" + this.inputTarget.value
+ link.href = link.href + "?model=" + this.inputTarget.value
}
}
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index 43e669c6..d1a5680b 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -32,7 +32,7 @@ def self.test_language_model(language_model, api_name = nil)
).dig("content", 0, "text")
rescue => e
- e.message
+ "Error: #{e.message}"
end
def initialize(user, assistant, conversation = nil, message = nil)
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index 1e8c5d82..b7d87bda 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -16,17 +16,26 @@ def self.client
def self.test_language_model(language_model, api_name = nil)
api_name ||= language_model.api_name
-
- client = ::OpenAI::Client.new(
- access_token: language_model.api_service.effective_token,
- uri_base: language_model.api_service.url
- )
-
- client.chat(parameters: {
+ params = {
model: api_name,
messages: [{ role: "user", content: "Hello!" }],
- }).dig("choices", 0, "message", "content")
+ }
+
+ if Rails.env.test?
+ client = ::TestClient::OpenAI.new(
+ access_token: language_model.api_service.effective_token,
+ uri_base: language_model.api_service.url
+ )
+ response = client.send(:chat, ** {parameters: params})
+ else
+ client = ::OpenAI::Client.new(
+ access_token: language_model.api_service.effective_token,
+ uri_base: language_model.api_service.url
+ )
+ response = client.chat(parameters: params)
+ end
+ response.dig("choices", 0, "message", "content")
rescue ::Faraday::Error => e
"Error: #{e.message}"
end
diff --git a/test/controllers/settings/language_models_controller_test.rb b/test/controllers/settings/language_models_controller_test.rb
index 1accfe13..f35b42a5 100644
--- a/test/controllers/settings/language_models_controller_test.rb
+++ b/test/controllers/settings/language_models_controller_test.rb
@@ -199,4 +199,12 @@ class Settings::LanguageModelsControllerTest < ActionDispatch::IntegrationTest
assert_select 'input[name="language_model[supports_system_message]"][checked="checked"]', false
end
end
+
+ test "test should return success and a message" do
+ TestClient::OpenAI.stub :text, "Success." do
+ get settings_language_model_test_url(format: :turbo_stream, language_model_id: language_models(:guanaco).id, model: "gpt-4o")
+ assert_response :success
+ assert_contains_text "div#test_result", "Success."
+ end
+ end
end
From 37fae04a7cc66b6ed7b6d9b19b39d5d6b254126c Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Mon, 23 Dec 2024 09:25:17 -0500
Subject: [PATCH 13/14] Add api test and anthropic and gemeni
---
.../settings/api_services_controller.rb | 10 ++++++
app/javascript/stimulus/testing_controller.js | 21 +++++++++++--
app/models/api_service.rb | 4 +++
app/services/ai_backend.rb | 21 +++++++++++++
app/services/ai_backend/anthropic.rb | 13 ++++----
app/services/ai_backend/gemini.rb | 8 ++---
app/services/ai_backend/open_ai.rb | 23 ++++++--------
.../settings/api_services/_form.html.erb | 31 ++++++++++++++++---
.../api_services/test.turbo_stream.erb | 11 +++++++
.../settings/language_models/_form.html.erb | 13 ++++----
.../language_models/test.turbo_stream.erb | 10 +-----
config/routes.rb | 4 ++-
12 files changed, 121 insertions(+), 48 deletions(-)
create mode 100644 app/views/settings/api_services/test.turbo_stream.erb
diff --git a/app/controllers/settings/api_services_controller.rb b/app/controllers/settings/api_services_controller.rb
index ce6a3831..5ac8251a 100644
--- a/app/controllers/settings/api_services_controller.rb
+++ b/app/controllers/settings/api_services_controller.rb
@@ -30,6 +30,16 @@ def update
end
end
+ def test
+ @api_service = Current.user.api_services.find_by(id: params[:api_service_id])
+ @answer = @api_service.test_api_service(params[:url], params[:token])
+
+ respond_to do |format|
+ format.html { redirect_to settings_api_services_path, notice: "Tested: #{@answer}", status: :see_other }
+ format.turbo_stream
+ end
+ end
+
def destroy
@api_service.deleted!
redirect_to settings_api_services_path, notice: "Deleted", status: :see_other
diff --git a/app/javascript/stimulus/testing_controller.js b/app/javascript/stimulus/testing_controller.js
index 78b455a5..c9fc27de 100644
--- a/app/javascript/stimulus/testing_controller.js
+++ b/app/javascript/stimulus/testing_controller.js
@@ -1,10 +1,25 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
- static targets = ["input"]
+ static targets = ["model", "test", "url","token"]
- update_link(event) {
+ update_link_language_model(event) {
const link = event.currentTarget;
- link.href = link.href + "?model=" + this.inputTarget.value
+ const href = link.href.split('?')[0];
+ link.href = href + "?model=" + this.modelTarget.value
+ }
+
+ update_link_api_service(event) {
+ const link = event.currentTarget;
+ const href = link.href.split('?')[0];
+ link.href = href + "?url=" + this.urlTarget.value + "&token=" + this.tokenTarget.value
+ console.log("Link: ", link)
+ }
+
+ disable_test_link() {
+ const link = this.testTarget;
+ link.addEventListener('click', function(event) {
+ event.preventDefault();
+ });
}
}
diff --git a/app/models/api_service.rb b/app/models/api_service.rb
index 9ad738fd..17798d05 100644
--- a/app/models/api_service.rb
+++ b/app/models/api_service.rb
@@ -39,6 +39,10 @@ def effective_token
token.presence || default_llm_key
end
+ def test_api_service(url = nil, token = nil)
+ ai_backend.test_api_service(self, url, token)
+ end
+
private
def default_llm_key
diff --git a/app/services/ai_backend.rb b/app/services/ai_backend.rb
index d4204f08..5f14342b 100644
--- a/app/services/ai_backend.rb
+++ b/app/services/ai_backend.rb
@@ -48,6 +48,27 @@ def stream_next_conversation_message(&chunk_handler)
end
end
+ def self.test_language_model(language_model, api_name = nil)
+ api_name ||= language_model.api_name
+ url = language_model.api_service.url
+ token = language_model.api_service.effective_token
+ return "Error: API key (token) is blank" if language_model.api_service.requires_token? && token.blank?
+
+ test_execute(url, token, api_name)
+ end
+
+ def self.test_api_service(api_service, url = nil, token = nil)
+ url ||= api_service.url
+ token ||= api_service.effective_token
+ language_model = LanguageModel.where(best: true, api_service: api_service).first
+ api_name = language_model.api_name unless language_model.nil?
+
+ return "Error: API key (token) is blank" if api_service.requires_token? && token.blank?
+ return "Error: API name is blank. Define a best Language Model for this API service." if api_name.blank?
+
+ test_execute(url, token, api_name)
+ end
+
private
def client_method_name
diff --git a/app/services/ai_backend/anthropic.rb b/app/services/ai_backend/anthropic.rb
index d1a5680b..638df9ea 100644
--- a/app/services/ai_backend/anthropic.rb
+++ b/app/services/ai_backend/anthropic.rb
@@ -14,15 +14,15 @@ def self.client
end
end
- def self.test_language_model(language_model, api_name = nil)
- api_name ||= language_model.api_name
-
+ def self.test_execute(url, token, api_name)
+ Rails.logger.info "Connecting to Anthropic API server at #{url} with access token of length #{token.to_s.length}"
client = ::Anthropic::Client.new(
- uri_base: language_model.api_service.url,
- access_token: language_model.api_service.effective_token
+ uri_base: url,
+ access_token: token
)
- response = client.messages(
+ Rails.logger.info "Testing using model #{api_name}"
+ client.messages(
model: api_name,
messages: [
{ "role": "user", "content": "Hello!" }
@@ -30,7 +30,6 @@ def self.test_language_model(language_model, api_name = nil)
system: "You are a helpful assistant.",
parameters: { max_tokens: 1000 }
).dig("content", 0, "text")
-
rescue => e
"Error: #{e.message}"
end
diff --git a/app/services/ai_backend/gemini.rb b/app/services/ai_backend/gemini.rb
index 069d42d4..d125fc68 100644
--- a/app/services/ai_backend/gemini.rb
+++ b/app/services/ai_backend/gemini.rb
@@ -15,13 +15,12 @@ def self.client
end
end
- def self.test_language_model(language_model, api_name = nil)
- api_name ||= language_model.api_name
-
+ def self.test_execute(url, token, api_name)
+ Rails.logger.info "Connecting to Gemini API server at #{url} with access token of length #{token.to_s.length}"
client = ::Gemini.new(
credentials: {
service: "generative-language-api",
- api_key: language_model.api_service.effective_token,
+ api_key: token,
version: "v1beta"
},
options: {
@@ -33,7 +32,6 @@ def self.test_language_model(language_model, api_name = nil)
client.generate_content({
contents: { role: "user", parts: { text: "Hello!" }}
}).dig("candidates", 0, "content", "parts", 0, "text")
-
rescue ::Faraday::Error => e
"Error: #{e.message}"
end
diff --git a/app/services/ai_backend/open_ai.rb b/app/services/ai_backend/open_ai.rb
index b7d87bda..f40c730f 100644
--- a/app/services/ai_backend/open_ai.rb
+++ b/app/services/ai_backend/open_ai.rb
@@ -14,25 +14,22 @@ def self.client
end
end
- def self.test_language_model(language_model, api_name = nil)
- api_name ||= language_model.api_name
- params = {
- model: api_name,
- messages: [{ role: "user", content: "Hello!" }],
- }
-
+ def self.test_execute(url, token, api_name)
if Rails.env.test?
client = ::TestClient::OpenAI.new(
- access_token: language_model.api_service.effective_token,
- uri_base: language_model.api_service.url
+ access_token: token,
+ uri_base: url
)
- response = client.send(:chat, ** {parameters: params})
+ response = client.send(:chat, ** {parameters: {model: api_name, messages: [{ role: "user", content: "Hello!" }]}})
else
+ Rails.logger.info "Connecting to OpenAI API server at #{url} with access token of length #{token.to_s.length}"
client = ::OpenAI::Client.new(
- access_token: language_model.api_service.effective_token,
- uri_base: language_model.api_service.url
+ access_token: token,
+ uri_base: url
)
- response = client.chat(parameters: params)
+
+ Rails.logger.info "Testing using model #{api_name}"
+ response = client.chat(parameters: {model: api_name, messages: [{ role: "user", content: "Hello!" }]})
end
response.dig("choices", 0, "message", "content")
diff --git a/app/views/settings/api_services/_form.html.erb b/app/views/settings/api_services/_form.html.erb
index a6c9d073..30e5e8b9 100644
--- a/app/views/settings/api_services/_form.html.erb
+++ b/app/views/settings/api_services/_form.html.erb
@@ -1,4 +1,4 @@
-<%= form_with(model: [:settings, api_service], class: "contents") do |form| %>
+<%= form_with(model: [:settings, api_service], class: "contents", data: {controller: "testing"}) do |form| %>
<% if api_service.errors.any? %>
<%= pluralize(api_service.errors.count, "error") %> prohibited this API service from being saved:
@@ -21,6 +21,7 @@
<%= form.select :driver,
APIService.drivers.keys,
{},
+ data: { action: "change->testing#disable_test_link" },
class: %|
block
border border-gray-200 outline-none
@@ -32,9 +33,22 @@
%>
-
+
<%= form.label :url %>
- <%= form.text_field :url, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
+
+ <% if api_service.persisted? %>
+ <% link_url = settings_api_services_path + "/" + api_service.id.to_s + "/test" %>
+ <%= link_to "Test", link_url,
+ data: { testing_target: "test", turbo_stream: true, action: "click->testing#update_link_api_service" },
+ class: "underline text-blue-600"
+ %>
+ <% end %>
+
+
+ <%= form.text_field :url,
+ data: { testing_target: "url" },
+ class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black"
+ %>
@@ -167,7 +181,16 @@
%>.
- <%= form.text_field :token, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black", autocomplete: "off" %>
+ <%= form.text_field :token,
+ class: %|
+ block shadow
+ rounded-md border border-gray-200 outline-none
+ px-3 py-2 mt-2 w-full dark:text-black
+ |,
+ autocomplete: "off",
+ id: "input_token",
+ data: { testing_target: "token" }
+ %>
<%= form.submit "Save",
diff --git a/app/views/settings/api_services/test.turbo_stream.erb b/app/views/settings/api_services/test.turbo_stream.erb
new file mode 100644
index 00000000..14155ff6
--- /dev/null
+++ b/app/views/settings/api_services/test.turbo_stream.erb
@@ -0,0 +1,11 @@
+
+
+
+ <% if @answer.start_with?("Error:") %>
+ <%= @answer %>
+ <% else %>
+ <%= @answer %>
+ <% end %>
+
+
+
diff --git a/app/views/settings/language_models/_form.html.erb b/app/views/settings/language_models/_form.html.erb
index 4e19845f..934961a7 100644
--- a/app/views/settings/language_models/_form.html.erb
+++ b/app/views/settings/language_models/_form.html.erb
@@ -1,4 +1,4 @@
-<%= form_with(model: [:settings, language_model], class: "contents") do |form| %>
+<%= form_with(model: [:settings, language_model], class: "contents", data: { controller: "testing" }) do |form| %>
<% if language_model.errors.any? %>
<%= pluralize(language_model.errors.count, "error") %> prohibited this language model from being saved:
@@ -16,20 +16,20 @@
<%= form.text_field :name, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black" %>
-
+
<%= form.label :api_name %>
<% if language_model.persisted? %>
<% link_url = settings_language_models_path + "/" + language_model.id.to_s + "/test" %>
- <%= link_to "(Test)", link_url,
- id: "test_result",
- data: { turbo_stream: true, action: "click->testing#update_link" },
+ <%= link_to "Test", link_url,
+ data: { testing_target: "test", turbo_stream: true, action: "click->testing#update_link_language_model" },
class: "underline text-blue-600"
%>
+
<% end %>
<%= form.text_field :api_name,
- data: { testing_target: "input" },
+ data: { testing_target: "model" },
class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full dark:text-black"
%>
As specified in the API docs
@@ -41,6 +41,7 @@
<%= form.select :api_service_id,
Current.user.api_services.ordered.pluck(:name, :id).reverse,
{},
+ data: { action: "change->testing#disable_test_link" },
class: %|
block
border border-gray-200 outline-none
diff --git a/app/views/settings/language_models/test.turbo_stream.erb b/app/views/settings/language_models/test.turbo_stream.erb
index ce79b122..14155ff6 100644
--- a/app/views/settings/language_models/test.turbo_stream.erb
+++ b/app/views/settings/language_models/test.turbo_stream.erb
@@ -1,18 +1,10 @@
-
- <%= link_to "(Test)",
- settings_language_model_test_path(@language_model),
- id: "test_result",
- data: { turbo_stream: true, action: "click->testing#update_link" },
- class: "underline text-blue-600"
- %>
-
<% if @answer.start_with?("Error:") %>
<%= @answer %>
<% else %>
- Result: <%= @answer %>
+ <%= @answer %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 17a08926..5f5a2fb3 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -19,7 +19,9 @@
resources :language_models do
get :test, to: "language_models#test"
end
- resources :api_services, except: [:show]
+ resources :api_services, except: [:show] do
+ get :test, to: "api_services#test"
+ end
resources :memories, only: [:index, :destroy] do
delete :destroy, to: "memories#destroy_all", on: :collection
end
From 7841dafea25a30f04d8aed04b03802ec7303f903 Mon Sep 17 00:00:00 2001
From: Matt Lindsey
Date: Mon, 23 Dec 2024 15:27:26 -0500
Subject: [PATCH 14/14] Add test for api service test controller
---
test/controllers/settings/api_services_controller_test.rb | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/test/controllers/settings/api_services_controller_test.rb b/test/controllers/settings/api_services_controller_test.rb
index 2e42e25f..7bb44c58 100644
--- a/test/controllers/settings/api_services_controller_test.rb
+++ b/test/controllers/settings/api_services_controller_test.rb
@@ -108,4 +108,12 @@ class Settings::APIServicesControllerTest < ActionDispatch::IntegrationTest
get edit_settings_api_service_url(api_services(:keith_other_service))
assert_select "button#instructions.hidden"
end
+
+ test "test should return success and a message" do
+ TestClient::OpenAI.stub :text, "Success." do
+ get settings_api_service_test_url(format: :turbo_stream, api_service_id: api_services(:keith_openai_service).id, url: "https://api.openai.com/v1", token: "abc-secret123")
+ assert_response :success
+ assert_contains_text "div#test_result", "Success."
+ end
+ end
end