llm_meta_client 0.4.0 → 0.6.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/CHANGELOG.md +18 -0
- data/app/assets/stylesheets/llm_meta_client/generation_settings.css +90 -0
- data/lib/generators/llm_meta_client/scaffold/scaffold_generator.rb +4 -2
- data/lib/generators/llm_meta_client/scaffold/templates/app/controllers/chats_controller.rb +13 -3
- data/lib/generators/llm_meta_client/scaffold/templates/app/controllers/prompts_controller.rb +2 -2
- data/lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/generation_settings_controller.js +51 -0
- data/lib/generators/llm_meta_client/scaffold/templates/app/models/chat.rb +17 -21
- data/lib/generators/llm_meta_client/scaffold/templates/app/models/message.rb +2 -2
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/_message.html.erb +3 -3
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/create.turbo_stream.erb +2 -2
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/edit.html.erb +1 -0
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/new.html.erb +1 -0
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/update.turbo_stream.erb +2 -2
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/layouts/_sidebar.html.erb +1 -1
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/layouts/application.html.erb +1 -1
- data/lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_generation_settings_field.html.erb +87 -0
- data/lib/generators/llm_meta_client/scaffold/templates/db/migrate/create_messages.rb +1 -1
- data/lib/llm_meta_client/server_query.rb +4 -3
- data/lib/llm_meta_client/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e6f2472a161a70eb1e9aa1af8495c25a9a7229d0351663f2b8784759377e813
|
|
4
|
+
data.tar.gz: 7830a137d1a7751942a314e5271a98e5db27aa105aa36885f2a753b02f63f9a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b16d80ac8a8f96fbf3545688a8657ed12ad2ef298707ee6475789b9468399a314b494f7d01e829557039dc11985702fbf1b4a6f1f8f67dab8f9908395fdf1d0
|
|
7
|
+
data.tar.gz: c335cf07ce4e413b7251fdc75ea41d227b89e86ebca4f6e44a526cd8fbb6f44dc3185851d2b1055cf20ae86ee1658e1fd2138924da0370da2d33127699c18fb6
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.0] - 2026-03-18
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Rename `prompt_manager` references to `prompt_navigator` across all scaffold templates (models, controllers, views, migrations, generator config)
|
|
13
|
+
- Refactor chat template to use `PromptExecution#build_context` instead of manual message iteration
|
|
14
|
+
- Update `prompt_navigator` gem to 0.3.0
|
|
15
|
+
|
|
16
|
+
## [0.5.0] - 2026-03-17
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Generation settings support:
|
|
21
|
+
- `generation_settings` parameter in `ServerQuery` API layer for configuring LLM generation parameters
|
|
22
|
+
- `generation_settings` threading through `Chat` model
|
|
23
|
+
- `generation_settings` parameter extraction in `ChatsController`
|
|
24
|
+
- Generation settings UI components for configuring parameters in chat forms
|
|
25
|
+
|
|
8
26
|
## [0.4.0] - 2026-03-11
|
|
9
27
|
|
|
10
28
|
### Added
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* Generation Settings */
|
|
2
|
+
.generation-settings-field {
|
|
3
|
+
margin-bottom: 10px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.generation-settings-toggle-button {
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
gap: 6px;
|
|
10
|
+
background: none;
|
|
11
|
+
border: 1px solid #d1d5db;
|
|
12
|
+
border-radius: 6px;
|
|
13
|
+
padding: 6px 12px;
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
color: #374151;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
transition: border-color 0.2s, background-color 0.2s;
|
|
19
|
+
|
|
20
|
+
&:hover {
|
|
21
|
+
background-color: #f9fafb;
|
|
22
|
+
border-color: #9ca3af;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.generation-settings-panel {
|
|
27
|
+
margin-top: 8px;
|
|
28
|
+
border: 1px solid #e5e7eb;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
background-color: #f9fafb;
|
|
31
|
+
padding: 12px 16px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.generation-setting-item {
|
|
35
|
+
margin-bottom: 14px;
|
|
36
|
+
|
|
37
|
+
&:last-child {
|
|
38
|
+
margin-bottom: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
label {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 8px;
|
|
45
|
+
font-size: 13px;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
color: #374151;
|
|
48
|
+
margin-bottom: 4px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
input[type="range"] {
|
|
52
|
+
width: 100%;
|
|
53
|
+
accent-color: #3b82f6;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.max-tokens-input {
|
|
58
|
+
width: 100%;
|
|
59
|
+
padding: 6px 10px;
|
|
60
|
+
border: 1px solid #d1d5db;
|
|
61
|
+
border-radius: 6px;
|
|
62
|
+
font-size: 13px;
|
|
63
|
+
background-color: white;
|
|
64
|
+
transition: border-color 0.2s;
|
|
65
|
+
|
|
66
|
+
&:focus {
|
|
67
|
+
outline: none;
|
|
68
|
+
border-color: #3b82f6;
|
|
69
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&::placeholder {
|
|
73
|
+
color: #9ca3af;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.setting-value {
|
|
79
|
+
font-weight: 700;
|
|
80
|
+
color: #3b82f6;
|
|
81
|
+
font-size: 13px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.setting-range-labels {
|
|
85
|
+
display: flex;
|
|
86
|
+
justify-content: space-between;
|
|
87
|
+
font-size: 11px;
|
|
88
|
+
color: #9ca3af;
|
|
89
|
+
margin-top: 2px;
|
|
90
|
+
}
|
|
@@ -34,6 +34,7 @@ module LlmMetaClient
|
|
|
34
34
|
template "app/views/shared/_api_key_field.html.erb"
|
|
35
35
|
template "app/views/shared/_model_field.html.erb"
|
|
36
36
|
template "app/views/shared/_tool_selector_field.html.erb"
|
|
37
|
+
template "app/views/shared/_generation_settings_field.html.erb"
|
|
37
38
|
template "app/views/layouts/application.html.erb"
|
|
38
39
|
template "app/views/layouts/_header.html.erb"
|
|
39
40
|
template "app/views/layouts/_sidebar.html.erb"
|
|
@@ -44,6 +45,7 @@ module LlmMetaClient
|
|
|
44
45
|
template "app/javascript/controllers/chats_form_controller.js"
|
|
45
46
|
template "app/javascript/controllers/chat_title_edit_controller.js"
|
|
46
47
|
template "app/javascript/controllers/tool_selector_controller.js"
|
|
48
|
+
template "app/javascript/controllers/generation_settings_controller.js"
|
|
47
49
|
copy_file "app/javascript/popover.js"
|
|
48
50
|
end
|
|
49
51
|
|
|
@@ -95,8 +97,8 @@ module LlmMetaClient
|
|
|
95
97
|
|
|
96
98
|
def configure_asset_paths
|
|
97
99
|
inject_into_class "config/application.rb", "Application", <<-RUBY
|
|
98
|
-
# Add asset paths for
|
|
99
|
-
config.assets.paths << Rails.root.join("../
|
|
100
|
+
# Add asset paths for prompt_navigator gem
|
|
101
|
+
config.assets.paths << Rails.root.join("../prompt_navigator/app/assets/stylesheets")
|
|
100
102
|
# Add asset paths for chat_manager gem
|
|
101
103
|
config.assets.paths << Rails.root.join("../chat_manager/app/assets/stylesheets")
|
|
102
104
|
RUBY
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class ChatsController < ApplicationController
|
|
2
2
|
include ChatManager::ChatManageable
|
|
3
3
|
include ChatManager::CsvDownloadable
|
|
4
|
-
include
|
|
4
|
+
include PromptNavigator::HistoryManageable
|
|
5
5
|
# Allow access without login
|
|
6
6
|
skip_before_action :authenticate_user!, raise: false
|
|
7
7
|
before_action :authenticate_user!, only: [ :update_title, :download_csv, :download_all_csv ]
|
|
@@ -82,7 +82,7 @@ class ChatsController < ApplicationController
|
|
|
82
82
|
|
|
83
83
|
# Send to LLM and get assistant response
|
|
84
84
|
begin
|
|
85
|
-
@assistant_message = @chat.add_assistant_response(@prompt_execution, jwt_token, tool_ids: tool_ids_param)
|
|
85
|
+
@assistant_message = @chat.add_assistant_response(@prompt_execution, jwt_token, tool_ids: tool_ids_param, generation_settings: generation_settings_param)
|
|
86
86
|
# Generate chat title from the user's prompt (only if title is not yet set)
|
|
87
87
|
@chat.generate_title(params[:message], jwt_token)
|
|
88
88
|
rescue StandardError => e
|
|
@@ -172,7 +172,7 @@ class ChatsController < ApplicationController
|
|
|
172
172
|
|
|
173
173
|
# Send to LLM and get assistant response
|
|
174
174
|
begin
|
|
175
|
-
@assistant_message = @chat.add_assistant_response(@prompt_execution, jwt_token, tool_ids: tool_ids_param)
|
|
175
|
+
@assistant_message = @chat.add_assistant_response(@prompt_execution, jwt_token, tool_ids: tool_ids_param, generation_settings: generation_settings_param)
|
|
176
176
|
rescue StandardError => e
|
|
177
177
|
Rails.logger.error "Error in chat response: #{e.class} - #{e.message}\n#{e.backtrace&.join("\n")}"
|
|
178
178
|
@error_message = "An error occurred while getting the response. Please try again."
|
|
@@ -191,4 +191,14 @@ class ChatsController < ApplicationController
|
|
|
191
191
|
def tool_ids_param
|
|
192
192
|
params[:tool_ids].presence || []
|
|
193
193
|
end
|
|
194
|
+
|
|
195
|
+
def generation_settings_param
|
|
196
|
+
settings = {}
|
|
197
|
+
settings[:temperature] = params[:temperature].to_f if params[:temperature].present?
|
|
198
|
+
settings[:top_k] = params[:top_k].to_i if params[:top_k].present?
|
|
199
|
+
settings[:top_p] = params[:top_p].to_f if params[:top_p].present?
|
|
200
|
+
settings[:max_tokens] = params[:max_tokens].to_i if params[:max_tokens].present?
|
|
201
|
+
settings[:repeat_penalty] = params[:repeat_penalty].to_f if params[:repeat_penalty].present?
|
|
202
|
+
settings
|
|
203
|
+
end
|
|
194
204
|
end
|
data/lib/generators/llm_meta_client/scaffold/templates/app/controllers/prompts_controller.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
class PromptsController < ApplicationController
|
|
2
2
|
include ChatManager::ChatManageable
|
|
3
|
-
include
|
|
3
|
+
include PromptNavigator::HistoryManageable
|
|
4
4
|
skip_before_action :authenticate_user!, raise: false
|
|
5
5
|
|
|
6
6
|
def show
|
|
7
|
-
@prompt_execution =
|
|
7
|
+
@prompt_execution = PromptNavigator::PromptExecution.includes(:messages).find_by(execution_id: params[:id])
|
|
8
8
|
@message = @prompt_execution.messages.first
|
|
9
9
|
@chat = @message.chat
|
|
10
10
|
@messages = @chat.ordered_messages
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="generation-settings"
|
|
4
|
+
export default class extends Controller {
|
|
5
|
+
static targets = [
|
|
6
|
+
"toggleButton",
|
|
7
|
+
"toggleIcon",
|
|
8
|
+
"panel",
|
|
9
|
+
"temperatureRange",
|
|
10
|
+
"temperatureValue",
|
|
11
|
+
"topKRange",
|
|
12
|
+
"topKValue",
|
|
13
|
+
"topPRange",
|
|
14
|
+
"topPValue",
|
|
15
|
+
"maxTokensInput",
|
|
16
|
+
"repeatPenaltyRange",
|
|
17
|
+
"repeatPenaltyValue",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
connect() {
|
|
21
|
+
this.expanded = false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
toggle() {
|
|
25
|
+
if (!this.hasPanelTarget) return
|
|
26
|
+
|
|
27
|
+
this.expanded = !this.expanded
|
|
28
|
+
this.panelTarget.style.display = this.expanded ? "block" : "none"
|
|
29
|
+
|
|
30
|
+
if (this.hasToggleIconTarget) {
|
|
31
|
+
this.toggleIconTarget.classList.toggle("bi-chevron-down", !this.expanded)
|
|
32
|
+
this.toggleIconTarget.classList.toggle("bi-chevron-up", this.expanded)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
updateTemperature() {
|
|
37
|
+
this.temperatureValueTarget.textContent = this.temperatureRangeTarget.value
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
updateTopK() {
|
|
41
|
+
this.topKValueTarget.textContent = this.topKRangeTarget.value
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateTopP() {
|
|
45
|
+
this.topPValueTarget.textContent = this.topPRangeTarget.value
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
updateRepeatPenalty() {
|
|
49
|
+
this.repeatPenaltyValueTarget.textContent = this.repeatPenaltyRangeTarget.value
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -51,31 +51,31 @@ class Chat < ApplicationRecord
|
|
|
51
51
|
# Add a user message to the chat
|
|
52
52
|
def add_user_message(message, model, branch_from_uuid = nil)
|
|
53
53
|
parent_message = branch_from_uuid.present? ? messages.find_by(uuid: branch_from_uuid) : nil
|
|
54
|
-
prompt_execution =
|
|
54
|
+
prompt_execution = PromptNavigator::PromptExecution.create!(
|
|
55
55
|
prompt: message,
|
|
56
56
|
model: model,
|
|
57
57
|
configuration: "",
|
|
58
|
-
previous_id: parent_message&.
|
|
58
|
+
previous_id: parent_message&.prompt_navigator_prompt_execution_id
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
new_message = messages.create!(
|
|
62
62
|
role: "user",
|
|
63
|
-
|
|
63
|
+
prompt_navigator_prompt_execution: prompt_execution
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
[ prompt_execution, new_message ]
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
# Add assistant response by sending to LLM
|
|
70
|
-
def add_assistant_response(prompt_execution, jwt_token, tool_ids: [])
|
|
71
|
-
response_content = send_to_llm(jwt_token, tool_ids: tool_ids)
|
|
70
|
+
def add_assistant_response(prompt_execution, jwt_token, tool_ids: [], generation_settings: {})
|
|
71
|
+
response_content = send_to_llm(jwt_token, tool_ids: tool_ids, generation_settings: generation_settings)
|
|
72
72
|
prompt_execution.update!(
|
|
73
73
|
llm_platform: llm_type(jwt_token),
|
|
74
74
|
response: response_content
|
|
75
75
|
)
|
|
76
76
|
new_message = messages.create!(
|
|
77
77
|
role: "assistant",
|
|
78
|
-
|
|
78
|
+
prompt_navigator_prompt_execution: prompt_execution
|
|
79
79
|
)
|
|
80
80
|
|
|
81
81
|
new_message
|
|
@@ -84,18 +84,18 @@ class Chat < ApplicationRecord
|
|
|
84
84
|
# Get all messages in order
|
|
85
85
|
def ordered_messages
|
|
86
86
|
messages
|
|
87
|
-
.includes(:
|
|
87
|
+
.includes(:prompt_navigator_prompt_execution)
|
|
88
88
|
.order(:created_at)
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def ordered_by_descending_prompt_executions
|
|
92
92
|
messages
|
|
93
93
|
.where(role: "user")
|
|
94
|
-
.includes(:
|
|
94
|
+
.includes(:prompt_navigator_prompt_execution)
|
|
95
95
|
.order(created_at: :desc)
|
|
96
96
|
.to_a
|
|
97
|
-
.select { |msg| msg.
|
|
98
|
-
.map(&:
|
|
97
|
+
.select { |msg| msg.prompt_navigator_prompt_execution }
|
|
98
|
+
.map(&:prompt_navigator_prompt_execution)
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
# Check if chat needs to be reset due to LLM or model change
|
|
@@ -122,33 +122,29 @@ class Chat < ApplicationRecord
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
# Send messages to LLM and get response
|
|
125
|
-
def send_to_llm(jwt_token, tool_ids: [])
|
|
125
|
+
def send_to_llm(jwt_token, tool_ids: [], generation_settings: {})
|
|
126
126
|
# Get LLM options
|
|
127
127
|
llm_options = LlmMetaClient::ServerResource.available_llm_options(jwt_token)
|
|
128
128
|
|
|
129
129
|
# Error if no LLM is available
|
|
130
130
|
raise LlmMetaClient::Exceptions::OllamaUnavailableError, "No LLM available" if llm_options.empty?
|
|
131
131
|
|
|
132
|
-
#
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
# Build prompt and context from direct lineage via PromptExecution
|
|
133
|
+
last_msg = ordered_messages.last
|
|
134
|
+
pe = last_msg.prompt_manager_prompt_execution
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
context = all_messages[0...-1].last(Rails.configuration.summarize_conversation_count).map do |msg|
|
|
139
|
-
{ role: msg.role, prompt: msg.prompt_manager_prompt_execution.prompt, response: msg.prompt_manager_prompt_execution&.response }
|
|
140
|
-
end
|
|
136
|
+
prompt = { role: last_msg.role, prompt: pe.prompt }
|
|
137
|
+
context = pe.build_context(limit: Rails.configuration.summarize_conversation_count)
|
|
141
138
|
|
|
142
139
|
if context.empty?
|
|
143
140
|
summarized_context = "No context available."
|
|
144
141
|
else
|
|
145
|
-
# Summarize context
|
|
146
142
|
summarized_context = LlmMetaClient::ServerQuery.new.call(jwt_token, llm_uuid, model, context, "Please summarize the context")
|
|
147
143
|
end
|
|
148
144
|
|
|
149
145
|
summarized_context += "Additional prompt: Responses from the assistant must consist solely of the response body."
|
|
150
146
|
|
|
151
147
|
# Send chat request using LlmMetaClient::ServerQuery
|
|
152
|
-
LlmMetaClient::ServerQuery.new.call(jwt_token, llm_uuid, model, summarized_context, prompt, tool_ids: tool_ids)
|
|
148
|
+
LlmMetaClient::ServerQuery.new.call(jwt_token, llm_uuid, model, summarized_context, prompt, tool_ids: tool_ids, generation_settings: generation_settings)
|
|
153
149
|
end
|
|
154
150
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class Message < ApplicationRecord
|
|
2
2
|
belongs_to :chat
|
|
3
|
-
belongs_to :
|
|
4
|
-
class_name: "
|
|
3
|
+
belongs_to :prompt_navigator_prompt_execution,
|
|
4
|
+
class_name: "PromptNavigator::PromptExecution",
|
|
5
5
|
optional: false
|
|
6
6
|
|
|
7
7
|
validates :role, presence: true, inclusion: { in: %w[user assistant] }
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
<%% if message.role == 'user' %>
|
|
4
4
|
👤 You
|
|
5
5
|
<%% else %>
|
|
6
|
-
🤖 <%%= message.
|
|
6
|
+
🤖 <%%= message.prompt_navigator_prompt_execution.llm_platform&.capitalize || 'LLM' %>
|
|
7
7
|
<%% end %>
|
|
8
8
|
</div>
|
|
9
9
|
<div class="message-content">
|
|
10
10
|
<%% if message.role == 'user' %>
|
|
11
|
-
<%%= simple_format(message.
|
|
11
|
+
<%%= simple_format(message.prompt_navigator_prompt_execution&.prompt) %>
|
|
12
12
|
<%% else %>
|
|
13
|
-
<%%= simple_format(message.
|
|
13
|
+
<%%= simple_format(message.prompt_navigator_prompt_execution&.response) %>
|
|
14
14
|
<%% end %>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/create.turbo_stream.erb
CHANGED
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
<div id="history-content">
|
|
37
37
|
<h2>History</h2>
|
|
38
38
|
<div class="history-stack" id="history-stack" data-controller="history">
|
|
39
|
-
<%%= render '
|
|
39
|
+
<%%= render 'prompt_navigator/history_card', locals: {
|
|
40
40
|
ann: @prompt_execution,
|
|
41
41
|
next_ann: nil,
|
|
42
42
|
is_active: @prompt_execution.execution_id == @active_message_uuid,
|
|
43
43
|
card_path: ->(uuid) { prompt_path(uuid) }
|
|
44
44
|
} %>
|
|
45
45
|
<%% (@chat&.ordered_by_descending_prompt_executions || []).drop(1).each_with_index do |ann, idx| %>
|
|
46
|
-
<%%= render '
|
|
46
|
+
<%%= render 'prompt_navigator/history_card', locals: {
|
|
47
47
|
ann: ann,
|
|
48
48
|
next_ann: @chat.ordered_by_descending_prompt_executions[idx + 2],
|
|
49
49
|
is_active: ann.execution_id == @active_message_uuid,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
<%% if user_signed_in? %>
|
|
19
19
|
<%%= render "shared/tool_selector_field", stimulus_controller: "tool-selector" %>
|
|
20
20
|
<%% end %>
|
|
21
|
+
<%%= render "shared/generation_settings_field", stimulus_controller: "generation-settings" %>
|
|
21
22
|
<%% end %>
|
|
22
23
|
<div class="input-wrapper">
|
|
23
24
|
<%%= f.text_area :message,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
<%% if user_signed_in? %>
|
|
19
19
|
<%%= render "shared/tool_selector_field", stimulus_controller: "tool-selector" %>
|
|
20
20
|
<%% end %>
|
|
21
|
+
<%%= render "shared/generation_settings_field", stimulus_controller: "generation-settings" %>
|
|
21
22
|
<%% end %>
|
|
22
23
|
<div class="input-wrapper">
|
|
23
24
|
<%%= f.text_area :message,
|
data/lib/generators/llm_meta_client/scaffold/templates/app/views/chats/update.turbo_stream.erb
CHANGED
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
<div id="history-content">
|
|
31
31
|
<h2>History</h2>
|
|
32
32
|
<div class="history-stack" id="history-stack" data-controller="history">
|
|
33
|
-
<%%= render '
|
|
33
|
+
<%%= render 'prompt_navigator/history_card', locals: {
|
|
34
34
|
ann: @prompt_execution,
|
|
35
35
|
next_ann: nil,
|
|
36
36
|
is_active: @prompt_execution.execution_id == @active_message_uuid,
|
|
37
37
|
card_path: ->(uuid) { prompt_path(uuid) }
|
|
38
38
|
} %>
|
|
39
39
|
<%% (@chat&.ordered_by_descending_prompt_executions || []).drop(1).each_with_index do |ann, idx| %>
|
|
40
|
-
<%%= render '
|
|
40
|
+
<%%= render 'prompt_navigator/history_card', locals: {
|
|
41
41
|
ann: ann,
|
|
42
42
|
next_ann: @chat.ordered_by_descending_prompt_executions[idx + 2],
|
|
43
43
|
is_active: ann.execution_id == @active_message_uuid,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<%% if history.present? %>
|
|
13
13
|
<div class="history-stack" id="history-stack" data-controller="history">
|
|
14
14
|
<%% history.each_with_index do |ann, idx| %>
|
|
15
|
-
<%%= render '
|
|
15
|
+
<%%= render 'prompt_navigator/history_card', locals: {
|
|
16
16
|
ann: ann,
|
|
17
17
|
next_ann: history[idx + 1],
|
|
18
18
|
is_active: ann.uuid == active_uuid,
|
data/lib/generators/llm_meta_client/scaffold/templates/app/views/layouts/application.html.erb
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
<%% # Includes all stylesheet files in app/assets/stylesheets %>
|
|
22
22
|
<%%= stylesheet_link_tag :app %>
|
|
23
|
-
<%%= stylesheet_link_tag "
|
|
23
|
+
<%%= stylesheet_link_tag "prompt_navigator/history", "data-turbo-track": "reload" %>
|
|
24
24
|
<%%= stylesheet_link_tag "chat_manager/chat", "data-turbo-track": "reload" %>
|
|
25
25
|
<%%= javascript_importmap_tags %>
|
|
26
26
|
</head>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<%%
|
|
2
|
+
stimulus_controller = local_assigns[:stimulus_controller] || "generation-settings"
|
|
3
|
+
%>
|
|
4
|
+
<div class="generation-settings-field" data-controller="<%%= stimulus_controller %>">
|
|
5
|
+
<div class="generation-settings-toggle">
|
|
6
|
+
<button type="button"
|
|
7
|
+
class="generation-settings-toggle-button"
|
|
8
|
+
data-<%%= stimulus_controller %>-target="toggleButton"
|
|
9
|
+
data-action="click-><%%= stimulus_controller %>#toggle">
|
|
10
|
+
<i class="bi bi-sliders"></i>
|
|
11
|
+
Generation Settings
|
|
12
|
+
<i class="bi bi-chevron-down toggle-icon" data-<%%= stimulus_controller %>-target="toggleIcon"></i>
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="generation-settings-panel" data-<%%= stimulus_controller %>-target="panel" style="display: none;">
|
|
16
|
+
<div class="generation-setting-item">
|
|
17
|
+
<label for="temperature">
|
|
18
|
+
Temperature
|
|
19
|
+
<span class="setting-value" data-<%%= stimulus_controller %>-target="temperatureValue">0.7</span>
|
|
20
|
+
</label>
|
|
21
|
+
<input type="range" name="temperature" id="temperature"
|
|
22
|
+
min="0" max="2" step="0.1" value="0.7"
|
|
23
|
+
data-<%%= stimulus_controller %>-target="temperatureRange"
|
|
24
|
+
data-action="input-><%%= stimulus_controller %>#updateTemperature">
|
|
25
|
+
<div class="setting-range-labels">
|
|
26
|
+
<span>0 (deterministic)</span>
|
|
27
|
+
<span>2 (creative)</span>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="generation-setting-item">
|
|
32
|
+
<label for="top_k">
|
|
33
|
+
Top-K
|
|
34
|
+
<span class="setting-value" data-<%%= stimulus_controller %>-target="topKValue">40</span>
|
|
35
|
+
</label>
|
|
36
|
+
<input type="range" name="top_k" id="top_k"
|
|
37
|
+
min="1" max="100" step="1" value="40"
|
|
38
|
+
data-<%%= stimulus_controller %>-target="topKRange"
|
|
39
|
+
data-action="input-><%%= stimulus_controller %>#updateTopK">
|
|
40
|
+
<div class="setting-range-labels">
|
|
41
|
+
<span>1 (focused)</span>
|
|
42
|
+
<span>100 (diverse)</span>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="generation-setting-item">
|
|
47
|
+
<label for="top_p">
|
|
48
|
+
Top-P
|
|
49
|
+
<span class="setting-value" data-<%%= stimulus_controller %>-target="topPValue">0.9</span>
|
|
50
|
+
</label>
|
|
51
|
+
<input type="range" name="top_p" id="top_p"
|
|
52
|
+
min="0" max="1" step="0.05" value="0.9"
|
|
53
|
+
data-<%%= stimulus_controller %>-target="topPRange"
|
|
54
|
+
data-action="input-><%%= stimulus_controller %>#updateTopP">
|
|
55
|
+
<div class="setting-range-labels">
|
|
56
|
+
<span>0 (narrow)</span>
|
|
57
|
+
<span>1 (broad)</span>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="generation-setting-item">
|
|
62
|
+
<label for="max_tokens">
|
|
63
|
+
Max Tokens
|
|
64
|
+
</label>
|
|
65
|
+
<input type="number" name="max_tokens" id="max_tokens"
|
|
66
|
+
min="1" max="128000" step="1" value=""
|
|
67
|
+
placeholder="Default (model-dependent)"
|
|
68
|
+
class="max-tokens-input"
|
|
69
|
+
data-<%%= stimulus_controller %>-target="maxTokensInput">
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class="generation-setting-item">
|
|
73
|
+
<label for="repeat_penalty">
|
|
74
|
+
Repeat Penalty
|
|
75
|
+
<span class="setting-value" data-<%%= stimulus_controller %>-target="repeatPenaltyValue">1.1</span>
|
|
76
|
+
</label>
|
|
77
|
+
<input type="range" name="repeat_penalty" id="repeat_penalty"
|
|
78
|
+
min="1" max="2" step="0.05" value="1.1"
|
|
79
|
+
data-<%%= stimulus_controller %>-target="repeatPenaltyRange"
|
|
80
|
+
data-action="input-><%%= stimulus_controller %>#updateRepeatPenalty">
|
|
81
|
+
<div class="setting-range-labels">
|
|
82
|
+
<span>1.0 (no penalty)</span>
|
|
83
|
+
<span>2.0 (strong)</span>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
@@ -3,7 +3,7 @@ class CreateMessages < ActiveRecord::Migration[8.1]
|
|
|
3
3
|
create_table :messages do |t|
|
|
4
4
|
t.references :chat, null: false, foreign_key: true
|
|
5
5
|
# t.references :parent, foreign_key: { to_table: :messages }, index: true, null: true
|
|
6
|
-
t.references :
|
|
6
|
+
t.references :prompt_navigator_prompt_execution, null: true, foreign_key: { to_table: :prompt_navigator_prompt_executions }
|
|
7
7
|
t.string :role
|
|
8
8
|
|
|
9
9
|
t.timestamps
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module LlmMetaClient
|
|
2
2
|
class ServerQuery
|
|
3
|
-
def call(id_token, api_key_uuid, model_id, context, user_content, tool_ids: [])
|
|
3
|
+
def call(id_token, api_key_uuid, model_id, context, user_content, tool_ids: [], generation_settings: {})
|
|
4
4
|
debug_log "Context: #{context}"
|
|
5
5
|
context_and_user_content = "Context:#{context}, User Prompt: #{user_content}"
|
|
6
6
|
debug_log "Request to LLM: \n===>\n#{context_and_user_content}\n===>"
|
|
7
7
|
|
|
8
|
-
response = request(api_key_uuid, id_token, model_id, context_and_user_content, tool_ids)
|
|
8
|
+
response = request(api_key_uuid, id_token, model_id, context_and_user_content, tool_ids, generation_settings)
|
|
9
9
|
|
|
10
10
|
raise Exceptions::ServerError, "LLM server returned HTTP #{response.code}" unless response.success?
|
|
11
11
|
|
|
@@ -28,12 +28,13 @@ module LlmMetaClient
|
|
|
28
28
|
Rails.logger.info(message) if Rails.env.development?
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def request(api_key_uuid, id_token, model_id, user_content, tool_ids)
|
|
31
|
+
def request(api_key_uuid, id_token, model_id, user_content, tool_ids, generation_settings)
|
|
32
32
|
headers = { "Content-Type" => "application/json" }
|
|
33
33
|
headers["Authorization"] = "Bearer #{id_token}" if id_token.present?
|
|
34
34
|
|
|
35
35
|
body = { prompt: user_content.to_s }
|
|
36
36
|
body[:tool_ids] = tool_ids if tool_ids.present?
|
|
37
|
+
body[:generation_settings] = generation_settings if generation_settings.present?
|
|
37
38
|
|
|
38
39
|
HTTParty.post(
|
|
39
40
|
url(api_key_uuid, model_id),
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm_meta_client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dhq_boiler
|
|
@@ -85,6 +85,7 @@ files:
|
|
|
85
85
|
- README.md
|
|
86
86
|
- Rakefile
|
|
87
87
|
- app/assets/stylesheets/llm_meta_client/application.css
|
|
88
|
+
- app/assets/stylesheets/llm_meta_client/generation_settings.css
|
|
88
89
|
- app/controllers/llm_meta_client/application_controller.rb
|
|
89
90
|
- app/helpers/llm_meta_client/application_helper.rb
|
|
90
91
|
- app/jobs/llm_meta_client/application_job.rb
|
|
@@ -106,6 +107,7 @@ files:
|
|
|
106
107
|
- lib/generators/llm_meta_client/scaffold/templates/app/controllers/prompts_controller.rb
|
|
107
108
|
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/chat_title_edit_controller.js
|
|
108
109
|
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/chats_form_controller.js
|
|
110
|
+
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/generation_settings_controller.js
|
|
109
111
|
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/llm_selector_controller.js
|
|
110
112
|
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/controllers/tool_selector_controller.js
|
|
111
113
|
- lib/generators/llm_meta_client/scaffold/templates/app/javascript/popover.js
|
|
@@ -122,6 +124,7 @@ files:
|
|
|
122
124
|
- lib/generators/llm_meta_client/scaffold/templates/app/views/layouts/application.html.erb
|
|
123
125
|
- lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_api_key_field.html.erb
|
|
124
126
|
- lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_family_field.html.erb
|
|
127
|
+
- lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_generation_settings_field.html.erb
|
|
125
128
|
- lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_model_field.html.erb
|
|
126
129
|
- lib/generators/llm_meta_client/scaffold/templates/app/views/shared/_tool_selector_field.html.erb
|
|
127
130
|
- lib/generators/llm_meta_client/scaffold/templates/config/initializers/llm_service.rb
|