raif 1.4.0 → 1.5.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 +2 -2
- data/app/assets/builds/raif_admin.css +40 -2
- data/app/assets/builds/raif_admin_sprockets.js +2709 -0
- data/app/assets/javascript/raif/admin/copy_to_clipboard_controller.js +132 -0
- data/app/assets/javascript/raif/admin/cost_estimate_controller.js +80 -0
- data/app/assets/javascript/raif/admin/judge_config_controller.js +23 -0
- data/app/assets/javascript/raif/admin/select_all_checkboxes_controller.js +33 -0
- data/app/assets/javascript/raif/admin/sortable_table_controller.js +51 -0
- data/app/assets/javascript/raif/admin/table_search_controller.js +15 -0
- data/app/assets/javascript/raif/admin/tom_select_controller.js +33 -0
- data/app/assets/javascript/raif_admin.js +23 -0
- data/app/assets/javascript/raif_admin_sprockets.js +24 -0
- data/app/assets/stylesheets/raif_admin.scss +50 -1
- data/app/controllers/raif/admin/agents_controller.rb +27 -1
- data/app/controllers/raif/admin/configs_controller.rb +1 -0
- data/app/controllers/raif/admin/llms_controller.rb +27 -0
- data/app/controllers/raif/admin/model_completions_controller.rb +6 -0
- data/app/controllers/raif/admin/prompt_studio/agents_controller.rb +25 -0
- data/app/controllers/raif/admin/prompt_studio/base_controller.rb +32 -0
- data/app/controllers/raif/admin/prompt_studio/batch_runs_controller.rb +102 -0
- data/app/controllers/raif/admin/prompt_studio/conversations_controller.rb +25 -0
- data/app/controllers/raif/admin/prompt_studio/tasks_controller.rb +64 -0
- data/app/controllers/raif/admin/tasks_controller.rb +5 -0
- data/app/helpers/raif/application_helper.rb +40 -0
- data/app/jobs/raif/prompt_studio_batch_run_item_job.rb +11 -0
- data/app/jobs/raif/prompt_studio_batch_run_job.rb +15 -0
- data/app/jobs/raif/prompt_studio_task_run_job.rb +36 -0
- data/app/models/raif/agent.rb +36 -5
- data/app/models/raif/agents/native_tool_calling_agent.rb +101 -19
- data/app/models/raif/concerns/has_prompt_templates.rb +88 -0
- data/app/models/raif/concerns/has_runtime_duration.rb +41 -0
- data/app/models/raif/concerns/json_schema_definition.rb +16 -3
- data/app/models/raif/concerns/llm_prompt_caching.rb +20 -0
- data/app/models/raif/concerns/llms/anthropic/message_formatting.rb +6 -0
- data/app/models/raif/concerns/llms/anthropic/tool_formatting.rb +5 -1
- data/app/models/raif/concerns/llms/bedrock/message_formatting.rb +7 -0
- data/app/models/raif/concerns/llms/bedrock/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/google/message_formatting.rb +5 -2
- data/app/models/raif/concerns/llms/google/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/message_formatting.rb +30 -0
- data/app/models/raif/concerns/llms/open_ai_completions/response_tool_calls.rb +1 -1
- data/app/models/raif/concerns/llms/open_ai_completions/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/open_ai_responses/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/provider_managed_tool_calls.rb +162 -0
- data/app/models/raif/conversation.rb +24 -3
- data/app/models/raif/conversation_entry.rb +6 -3
- data/app/models/raif/embedding_models/bedrock.rb +10 -1
- data/app/models/raif/embedding_models/google.rb +37 -0
- data/app/models/raif/evals/llm_judge.rb +70 -0
- data/{lib → app/models}/raif/evals/llm_judges/binary.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/comparative.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/scored.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/summarization.rb +38 -0
- data/app/models/raif/llm.rb +82 -7
- data/app/models/raif/llms/anthropic.rb +26 -4
- data/app/models/raif/llms/bedrock.rb +59 -5
- data/app/models/raif/llms/google.rb +28 -2
- data/app/models/raif/llms/open_ai_base.rb +4 -0
- data/app/models/raif/llms/open_ai_completions.rb +9 -2
- data/app/models/raif/llms/open_ai_responses.rb +9 -2
- data/app/models/raif/llms/open_router.rb +10 -3
- data/app/models/raif/model_completion.rb +75 -34
- data/app/models/raif/model_tool.rb +45 -3
- data/app/models/raif/model_tool_invocation.rb +31 -1
- data/app/models/raif/prompt_studio_batch_run.rb +155 -0
- data/app/models/raif/prompt_studio_batch_run_item.rb +220 -0
- data/app/models/raif/streaming_responses/bedrock.rb +60 -1
- data/app/models/raif/task.rb +30 -6
- data/app/views/layouts/raif/admin.html.erb +31 -1
- data/app/views/raif/admin/agents/_agent.html.erb +1 -0
- data/app/views/raif/admin/agents/index.html.erb +48 -0
- data/app/views/raif/admin/agents/show.html.erb +4 -0
- data/app/views/raif/admin/llms/index.html.erb +110 -0
- data/app/views/raif/admin/model_completions/_model_completion.html.erb +3 -7
- data/app/views/raif/admin/model_completions/index.html.erb +14 -1
- data/app/views/raif/admin/model_completions/show.html.erb +164 -55
- data/app/views/raif/admin/model_tool_invocations/index.html.erb +1 -1
- data/app/views/raif/admin/model_tool_invocations/show.html.erb +18 -0
- data/app/views/raif/admin/prompt_studio/agents/index.html.erb +56 -0
- data/app/views/raif/admin/prompt_studio/agents/show.html.erb +57 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_batch_run_item.html.erb +54 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_judge_config_fields.html.erb +76 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_judge_detail_modal.html.erb +27 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_modal.html.erb +35 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_progress.html.erb +78 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/show.html.erb +49 -0
- data/app/views/raif/admin/prompt_studio/conversations/index.html.erb +48 -0
- data/app/views/raif/admin/prompt_studio/conversations/show.html.erb +36 -0
- data/app/views/raif/admin/prompt_studio/shared/_nav_tabs.html.erb +17 -0
- data/app/views/raif/admin/prompt_studio/shared/_prompt_comparison.html.erb +87 -0
- data/app/views/raif/admin/prompt_studio/shared/_type_filter.html.erb +54 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_result.html.erb +145 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_row.html.erb +12 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_type_filter.html.erb +58 -0
- data/app/views/raif/admin/prompt_studio/tasks/_tasks_table.html.erb +22 -0
- data/app/views/raif/admin/prompt_studio/tasks/index.html.erb +35 -0
- data/app/views/raif/admin/prompt_studio/tasks/show.html.erb +19 -0
- data/app/views/raif/admin/tasks/_task.html.erb +1 -0
- data/app/views/raif/admin/tasks/index.html.erb +17 -5
- data/app/views/raif/admin/tasks/show.html.erb +20 -0
- data/app/views/raif/conversation_entries/_message.html.erb +10 -6
- data/config/importmap.rb +8 -0
- data/config/locales/admin.en.yml +128 -0
- data/config/locales/en.yml +36 -2
- data/config/routes.rb +8 -0
- data/db/migrate/20260307000000_add_prompt_studio_run_to_raif_tasks.rb +7 -0
- data/db/migrate/20260308000000_create_raif_prompt_studio_batch_runs.rb +27 -0
- data/db/migrate/20260308000001_create_raif_prompt_studio_batch_run_items.rb +24 -0
- data/db/migrate/20260407000000_add_cache_token_columns_to_raif_model_completions.rb +8 -0
- data/lib/generators/raif/agent/agent_generator.rb +18 -0
- data/lib/generators/raif/agent/templates/agent.rb.tt +7 -5
- data/lib/generators/raif/agent/templates/system_prompt.erb.tt +3 -0
- data/lib/generators/raif/conversation/conversation_generator.rb +19 -1
- data/lib/generators/raif/conversation/templates/system_prompt.erb.tt +4 -0
- data/lib/generators/raif/install/templates/initializer.rb +68 -27
- data/lib/generators/raif/task/task_generator.rb +18 -0
- data/lib/generators/raif/task/templates/prompt.erb.tt +4 -0
- data/lib/generators/raif/task/templates/task.rb.tt +9 -8
- data/lib/raif/configuration.rb +10 -0
- data/lib/raif/embedding_model_registry.rb +8 -0
- data/lib/raif/engine.rb +16 -1
- data/lib/raif/errors/blank_response_error.rb +8 -0
- data/lib/raif/errors/prompt_template_error.rb +15 -0
- data/lib/raif/errors.rb +2 -0
- data/lib/raif/evals.rb +0 -6
- data/lib/raif/llm_registry.rb +230 -9
- data/lib/raif/prompt_studio_comparison_builder.rb +138 -0
- data/lib/raif/token_estimator.rb +28 -0
- data/lib/raif/version.rb +1 -1
- data/lib/raif.rb +2 -0
- data/spec/support/rspec_helpers.rb +7 -1
- data/spec/support/test_task.rb +9 -0
- data/spec/support/test_template_task.rb +41 -0
- metadata +65 -7
- data/lib/raif/evals/llm_judge.rb +0 -32
- /data/{lib → app/models}/raif/evals/scoring_rubric.rb +0 -0
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
class Raif::StreamingResponses::Bedrock
|
|
4
4
|
|
|
5
5
|
def initialize_new_message
|
|
6
|
+
@reasoning_content_blocks = {}
|
|
7
|
+
|
|
6
8
|
# Initialize empty AWS response object
|
|
7
9
|
@message = Aws::BedrockRuntime::Types::Message.new(
|
|
8
10
|
role: "assistant",
|
|
@@ -62,9 +64,12 @@ class Raif::StreamingResponses::Bedrock
|
|
|
62
64
|
)
|
|
63
65
|
|
|
64
66
|
@message.content[index].tool_use.input += event.delta.tool_use.input
|
|
67
|
+
elsif event.delta.is_a?(Aws::BedrockRuntime::Types::ContentBlockDelta::ReasoningContent)
|
|
68
|
+
accumulate_reasoning_content(index, event.delta.reasoning_content)
|
|
65
69
|
end
|
|
66
70
|
when :content_block_stop
|
|
67
|
-
|
|
71
|
+
index = event.content_block_index
|
|
72
|
+
content_block = @message.content[index]
|
|
68
73
|
|
|
69
74
|
if content_block&.tool_use&.input.is_a?(String)
|
|
70
75
|
begin
|
|
@@ -73,6 +78,8 @@ class Raif::StreamingResponses::Bedrock
|
|
|
73
78
|
# If parsing fails, leave as a string
|
|
74
79
|
end
|
|
75
80
|
end
|
|
81
|
+
|
|
82
|
+
finalize_reasoning_content(index)
|
|
76
83
|
when :message_stop
|
|
77
84
|
@response.stop_reason = event.stop_reason
|
|
78
85
|
when :metadata
|
|
@@ -86,4 +93,56 @@ class Raif::StreamingResponses::Bedrock
|
|
|
86
93
|
@response
|
|
87
94
|
end
|
|
88
95
|
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def accumulate_reasoning_content(index, reasoning_delta)
|
|
99
|
+
reasoning_content = reasoning_content_for(index)
|
|
100
|
+
reasoning_content[:seen] = true
|
|
101
|
+
|
|
102
|
+
case reasoning_delta
|
|
103
|
+
when Aws::BedrockRuntime::Types::ReasoningContentBlockDelta::Text
|
|
104
|
+
reasoning_content[:text] << reasoning_delta.text.to_s
|
|
105
|
+
when Aws::BedrockRuntime::Types::ReasoningContentBlockDelta::Signature
|
|
106
|
+
reasoning_content[:signature] = reasoning_delta.signature
|
|
107
|
+
when Aws::BedrockRuntime::Types::ReasoningContentBlockDelta::RedactedContent
|
|
108
|
+
reasoning_content[:redacted_content] << reasoning_delta.redacted_content.to_s
|
|
109
|
+
else
|
|
110
|
+
reasoning_content[:unknown] = true
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def finalize_reasoning_content(index)
|
|
115
|
+
reasoning_content = @reasoning_content_blocks.delete(index)
|
|
116
|
+
return unless reasoning_content&.dig(:seen)
|
|
117
|
+
|
|
118
|
+
@message.content[index] = Aws::BedrockRuntime::Types::ContentBlock::ReasoningContent.new(
|
|
119
|
+
reasoning_content: build_reasoning_content(reasoning_content)
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def build_reasoning_content(reasoning_content)
|
|
124
|
+
if reasoning_content[:text].blank? && reasoning_content[:signature].blank? && reasoning_content[:redacted_content].present?
|
|
125
|
+
return Aws::BedrockRuntime::Types::ReasoningContentBlock::RedactedContent.new(
|
|
126
|
+
redacted_content: reasoning_content[:redacted_content]
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
Aws::BedrockRuntime::Types::ReasoningContentBlock::ReasoningText.new(
|
|
131
|
+
reasoning_text: Aws::BedrockRuntime::Types::ReasoningTextBlock.new(
|
|
132
|
+
text: reasoning_content[:text],
|
|
133
|
+
signature: reasoning_content[:signature]
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def reasoning_content_for(index)
|
|
139
|
+
@reasoning_content_blocks[index] ||= {
|
|
140
|
+
seen: false,
|
|
141
|
+
text: +"",
|
|
142
|
+
signature: nil,
|
|
143
|
+
redacted_content: +"",
|
|
144
|
+
unknown: false
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
89
148
|
end
|
data/app/models/raif/task.rb
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# failed_at :datetime
|
|
12
12
|
# llm_model_key :string not null
|
|
13
13
|
# prompt :text
|
|
14
|
+
# prompt_studio_run :boolean default(FALSE), not null
|
|
14
15
|
# raw_response :text
|
|
15
16
|
# requested_language_key :string
|
|
16
17
|
# response_format :integer default("text"), not null
|
|
@@ -39,12 +40,16 @@
|
|
|
39
40
|
#
|
|
40
41
|
module Raif
|
|
41
42
|
class Task < Raif::ApplicationRecord
|
|
43
|
+
prepend Raif::Concerns::HasPromptTemplates
|
|
44
|
+
|
|
42
45
|
include Raif::Concerns::HasLlm
|
|
43
46
|
include Raif::Concerns::HasRequestedLanguage
|
|
44
47
|
include Raif::Concerns::HasAvailableModelTools
|
|
48
|
+
include Raif::Concerns::HasRuntimeDuration
|
|
45
49
|
include Raif::Concerns::InvokesModelTools
|
|
46
50
|
include Raif::Concerns::LlmResponseParsing
|
|
47
51
|
include Raif::Concerns::LlmTemperature
|
|
52
|
+
include Raif::Concerns::LlmPromptCaching
|
|
48
53
|
include Raif::Concerns::JsonSchemaDefinition
|
|
49
54
|
include Raif::Concerns::RunWith
|
|
50
55
|
|
|
@@ -95,7 +100,7 @@ module Raif
|
|
|
95
100
|
# @param files [Array] Optional array of Raif::ModelFileInput objects to include with the prompt.
|
|
96
101
|
# @param args [Hash] Additional arguments to pass to the instance of the task that is created.
|
|
97
102
|
# @return [Raif::Task, nil] The task instance that was created and run.
|
|
98
|
-
def self.run(creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args)
|
|
103
|
+
def self.run(creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args, &block)
|
|
99
104
|
task = new(
|
|
100
105
|
creator: creator,
|
|
101
106
|
llm_model_key: llm_model_key,
|
|
@@ -107,7 +112,7 @@ module Raif
|
|
|
107
112
|
)
|
|
108
113
|
|
|
109
114
|
task.save!
|
|
110
|
-
task.run
|
|
115
|
+
task.run(&block)
|
|
111
116
|
task
|
|
112
117
|
rescue StandardError => e
|
|
113
118
|
task&.failed!
|
|
@@ -126,18 +131,28 @@ module Raif
|
|
|
126
131
|
task
|
|
127
132
|
end
|
|
128
133
|
|
|
129
|
-
def run(skip_prompt_population: false)
|
|
134
|
+
def run(skip_prompt_population: false, &block)
|
|
130
135
|
update_columns(started_at: Time.current) if started_at.nil?
|
|
131
136
|
|
|
132
137
|
populate_prompts unless skip_prompt_population
|
|
133
138
|
|
|
139
|
+
streaming_block = if block_given?
|
|
140
|
+
proc do |model_completion, delta, sse_event|
|
|
141
|
+
update_columns(raw_response: model_completion.raw_response, updated_at: Time.current)
|
|
142
|
+
block.call(model_completion, delta, sse_event)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
134
146
|
mc = llm.chat(
|
|
135
147
|
messages: messages,
|
|
136
148
|
source: self,
|
|
137
149
|
system_prompt: system_prompt,
|
|
138
150
|
response_format: response_format.to_sym,
|
|
139
151
|
available_model_tools: available_model_tools,
|
|
140
|
-
temperature: self.class.temperature
|
|
152
|
+
temperature: self.class.temperature,
|
|
153
|
+
anthropic_prompt_caching_enabled: self.class.anthropic_prompt_caching_enabled,
|
|
154
|
+
bedrock_prompt_caching_enabled: self.class.bedrock_prompt_caching_enabled,
|
|
155
|
+
&streaming_block
|
|
141
156
|
)
|
|
142
157
|
|
|
143
158
|
self.raif_model_completion = mc.becomes(Raif::ModelCompletion)
|
|
@@ -149,9 +164,9 @@ module Raif
|
|
|
149
164
|
self
|
|
150
165
|
end
|
|
151
166
|
|
|
152
|
-
def re_run
|
|
167
|
+
def re_run(&block)
|
|
153
168
|
update_columns(started_at: Time.current)
|
|
154
|
-
run(skip_prompt_population: true)
|
|
169
|
+
run(skip_prompt_population: true, &block)
|
|
155
170
|
end
|
|
156
171
|
|
|
157
172
|
def messages
|
|
@@ -191,6 +206,15 @@ module Raif
|
|
|
191
206
|
schema_for_instance(:json_response)
|
|
192
207
|
end
|
|
193
208
|
|
|
209
|
+
# Returns additional attributes to assign when creating tasks in Prompt Studio
|
|
210
|
+
# (reruns, batch runs, and judge tasks). Override in your ApplicationTask or
|
|
211
|
+
# task subclass to include app-specific attributes.
|
|
212
|
+
#
|
|
213
|
+
# @return [Hash] additional attributes to assign to the new task
|
|
214
|
+
def prompt_studio_task_attributes
|
|
215
|
+
{}
|
|
216
|
+
end
|
|
217
|
+
|
|
194
218
|
def build_prompt
|
|
195
219
|
raise NotImplementedError, "Raif::Task subclasses must implement #build_prompt"
|
|
196
220
|
end
|
|
@@ -5,14 +5,23 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
6
|
<%= csrf_meta_tags %>
|
|
7
7
|
<%= csp_meta_tag %>
|
|
8
|
+
<%= action_cable_meta_tag if respond_to?(:action_cable_meta_tag) %>
|
|
8
9
|
|
|
9
10
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
|
10
11
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous" nonce="<%= request.content_security_policy_nonce %>"></script>
|
|
11
12
|
|
|
13
|
+
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.4.3/dist/css/tom-select.bootstrap5.min.css" rel="stylesheet">
|
|
14
|
+
<script src="https://cdn.jsdelivr.net/npm/tom-select@2.4.3/dist/js/tom-select.complete.min.js" nonce="<%= request.content_security_policy_nonce %>"></script>
|
|
15
|
+
|
|
16
|
+
<% if respond_to?(:javascript_importmap_tags) %>
|
|
17
|
+
<%= javascript_importmap_tags "raif_admin" %>
|
|
18
|
+
<% else %>
|
|
19
|
+
<%= javascript_include_tag "raif_admin_sprockets", nonce: true %>
|
|
20
|
+
<% end %>
|
|
12
21
|
<%= stylesheet_link_tag "raif_admin" %>
|
|
13
22
|
</head>
|
|
14
23
|
|
|
15
|
-
<body class="raif-admin">
|
|
24
|
+
<body class="raif-admin" data-controller="raif--copy-to-clipboard">
|
|
16
25
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
|
|
17
26
|
<div class="container-fluid">
|
|
18
27
|
<a class="navbar-brand fw-bold" href="<%= raif.admin_tasks_path %>">
|
|
@@ -96,6 +105,27 @@
|
|
|
96
105
|
<%= t("raif.admin.common.agents") %>
|
|
97
106
|
</a>
|
|
98
107
|
</li>
|
|
108
|
+
<li class="nav-item">
|
|
109
|
+
<a class="nav-link <%= current_page?(raif.admin_llms_path) ? "active" : "" %>" href="<%= raif.admin_llms_path %>">
|
|
110
|
+
<span class="d-inline-block me-2">
|
|
111
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-currency-dollar" viewBox="0 0 16 16">
|
|
112
|
+
<path d="M4 10.781c.148 1.667 1.513 2.85 3.591 3.003V15h1.043v-1.216c2.27-.179 3.678-1.438 3.678-3.3 0-1.59-.947-2.51-2.956-3.028l-.722-.187V3.467c1.122.11 1.879.714 2.07 1.616h1.47c-.166-1.6-1.54-2.748-3.54-2.875V1H7.591v1.233c-1.939.23-3.27 1.472-3.27 3.156 0 1.454.966 2.483 2.661 2.917l.61.162v4.031c-1.149-.17-1.94-.8-2.131-1.718H4zm3.391-3.836c-1.043-.263-1.6-.825-1.6-1.616 0-.944.704-1.641 1.8-1.828v3.495l-.2-.05zm1.591 1.872c1.287.323 1.852.859 1.852 1.769 0 1.097-.826 1.828-2.2 1.939V8.73l.348.086z" />
|
|
113
|
+
</svg>
|
|
114
|
+
</span>
|
|
115
|
+
<%= t("raif.admin.common.llms") %>
|
|
116
|
+
</a>
|
|
117
|
+
</li>
|
|
118
|
+
<li class="nav-item">
|
|
119
|
+
<a class="nav-link <%= params[:controller].start_with?("raif/admin/prompt_studio") ? "active" : "" %>" href="<%= raif.admin_prompt_studio_tasks_path %>">
|
|
120
|
+
<span class="d-inline-block me-2">
|
|
121
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil-square" viewBox="0 0 16 16">
|
|
122
|
+
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" />
|
|
123
|
+
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z" />
|
|
124
|
+
</svg>
|
|
125
|
+
</span>
|
|
126
|
+
<%= t("raif.admin.prompt_studio.common.prompt_studio") %>
|
|
127
|
+
</a>
|
|
128
|
+
</li>
|
|
99
129
|
<li class="nav-item">
|
|
100
130
|
<a class="nav-link <%= current_page?(raif.admin_config_path) ? "active" : "" %>" href="<%= raif.admin_config_path %>">
|
|
101
131
|
<span class="d-inline-block me-2">
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
<span class="badge bg-secondary"><%= t("raif.admin.common.pending") %></span>
|
|
15
15
|
<% end %>
|
|
16
16
|
</td>
|
|
17
|
+
<td><small class="text-muted"><%= agent.runtime_duration %></small></td>
|
|
17
18
|
<td><%= agent.iteration_count %> / <%= agent.max_iterations %></td>
|
|
18
19
|
<td>
|
|
19
20
|
<% if agent.total_cost && agent.total_cost > 0 %>
|
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
<div class="row">
|
|
4
4
|
<div class="col-12">
|
|
5
|
+
<%= form_tag raif.admin_agents_path, method: :get, class: "mb-4" do %>
|
|
6
|
+
<div class="row align-items-end">
|
|
7
|
+
<div class="col-md-3">
|
|
8
|
+
<div class="form-group">
|
|
9
|
+
<label for="agent_type"><%= t("raif.admin.common.type") %></label>
|
|
10
|
+
<%= select_tag :agent_type,
|
|
11
|
+
options_for_select(
|
|
12
|
+
[[t("raif.admin.common.all"), "all"]] + @agent_types.map { |type| [type, type] },
|
|
13
|
+
@selected_type
|
|
14
|
+
),
|
|
15
|
+
{ class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="col-md-3">
|
|
19
|
+
<div class="form-group">
|
|
20
|
+
<label for="status"><%= t("raif.admin.common.status") %></label>
|
|
21
|
+
<%= select_tag :status,
|
|
22
|
+
options_for_select(
|
|
23
|
+
[
|
|
24
|
+
[t("raif.admin.common.all"), :all],
|
|
25
|
+
[t("raif.admin.common.completed"), :completed],
|
|
26
|
+
[t("raif.admin.common.failed"), :failed],
|
|
27
|
+
[t("raif.admin.common.running"), :running],
|
|
28
|
+
[t("raif.admin.common.pending"), :pending]
|
|
29
|
+
],
|
|
30
|
+
@selected_status
|
|
31
|
+
),
|
|
32
|
+
{ class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="col-md-3">
|
|
36
|
+
<div class="form-group">
|
|
37
|
+
<label for="llm_model_key"><%= t("raif.admin.common.model") %></label>
|
|
38
|
+
<%= select_tag :llm_model_key,
|
|
39
|
+
options_for_select(
|
|
40
|
+
[[t("raif.admin.common.all"), ""]] + @llm_model_keys.map { |key| [key, key] },
|
|
41
|
+
@selected_llm_model_key
|
|
42
|
+
),
|
|
43
|
+
{ class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="col-md-2">
|
|
47
|
+
<%= submit_tag t("raif.admin.common.filter"), class: "btn btn-primary" %>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<% end %>
|
|
51
|
+
|
|
5
52
|
<% if @agents.any? %>
|
|
6
53
|
<div class="table-responsive">
|
|
7
54
|
<table class="table table-striped table-hover">
|
|
@@ -12,6 +59,7 @@
|
|
|
12
59
|
<th><%= t("raif.admin.common.created_at") %></th>
|
|
13
60
|
<th><%= t("raif.admin.common.task") %></th>
|
|
14
61
|
<th><%= t("raif.admin.common.status") %></th>
|
|
62
|
+
<th><%= t("raif.admin.common.duration") %></th>
|
|
15
63
|
<th><%= t("raif.admin.common.iterations") %></th>
|
|
16
64
|
<th><%= t("raif.admin.common.total_cost") %></th>
|
|
17
65
|
<th><%= t("raif.admin.common.final_answer") %></th>
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
<% end %>
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
39
|
+
<div class="row mb-3">
|
|
40
|
+
<div class="col-md-3"><strong><%= t("raif.admin.common.duration") %>:</strong></div>
|
|
41
|
+
<div class="col-md-9"><%= @agent.runtime_duration %></div>
|
|
42
|
+
</div>
|
|
39
43
|
<div class="row mb-3">
|
|
40
44
|
<div class="col-md-3"><strong><%= t("raif.admin.common.iterations") %>:</strong></div>
|
|
41
45
|
<div class="col-md-9"><%= @agent.iteration_count %> / <%= @agent.max_iterations %></div>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<h1 class="my-4"><%= t("raif.admin.llms.index.title") %></h1>
|
|
2
|
+
|
|
3
|
+
<div class="row">
|
|
4
|
+
<div class="col-12">
|
|
5
|
+
<%= form_tag raif.admin_llms_path, method: :get, class: "mb-4" do %>
|
|
6
|
+
<div class="row align-items-end">
|
|
7
|
+
<div class="col-md-4">
|
|
8
|
+
<div class="form-group">
|
|
9
|
+
<label for="names"><%= t("raif.admin.llms.index.name") %></label>
|
|
10
|
+
<%= select_tag "names[]",
|
|
11
|
+
options_for_select(
|
|
12
|
+
@llm_names.map { |n| [n, n] },
|
|
13
|
+
@selected_names
|
|
14
|
+
),
|
|
15
|
+
{ id: "names", multiple: true, class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="col-md-4">
|
|
19
|
+
<div class="form-group">
|
|
20
|
+
<label for="providers"><%= t("raif.admin.llms.index.provider") %></label>
|
|
21
|
+
<%= select_tag "providers[]",
|
|
22
|
+
options_for_select(
|
|
23
|
+
@provider_names.map { |p| [p, p] },
|
|
24
|
+
@selected_providers
|
|
25
|
+
),
|
|
26
|
+
{ id: "providers", multiple: true, class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="col-md-2">
|
|
30
|
+
<%= submit_tag t("raif.admin.common.filter"), class: "btn btn-primary" %>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<% end %>
|
|
34
|
+
|
|
35
|
+
<div class="card" data-controller="raif--table-search raif--sortable-table">
|
|
36
|
+
<div class="card-header bg-light">
|
|
37
|
+
<input type="text"
|
|
38
|
+
class="form-control form-control-sm"
|
|
39
|
+
placeholder="<%= t("raif.admin.llms.index.search_placeholder") %>"
|
|
40
|
+
data-raif--table-search-target="input"
|
|
41
|
+
autocomplete="off"
|
|
42
|
+
data-action="input->raif--table-search#filter">
|
|
43
|
+
</div>
|
|
44
|
+
<div class="card-body">
|
|
45
|
+
<% if @llms.any? %>
|
|
46
|
+
<table class="table table-sm table-hover mb-0">
|
|
47
|
+
<thead>
|
|
48
|
+
<tr>
|
|
49
|
+
<th role="button" data-action="click->raif--sortable-table#sort" data-raif--sortable-table-target="header" data-col-index="0" data-sort-type="string" style="cursor: pointer;">
|
|
50
|
+
<%= t("raif.admin.llms.index.name") %>
|
|
51
|
+
</th>
|
|
52
|
+
<th role="button" data-action="click->raif--sortable-table#sort" data-raif--sortable-table-target="header" data-col-index="1" data-sort-type="string" style="cursor: pointer;">
|
|
53
|
+
<%= t("raif.admin.llms.index.provider") %>
|
|
54
|
+
</th>
|
|
55
|
+
<th role="button" data-action="click->raif--sortable-table#sort" data-raif--sortable-table-target="header" data-col-index="2" data-sort-type="string" style="cursor: pointer;">
|
|
56
|
+
<%= t("raif.admin.llms.index.api_name") %>
|
|
57
|
+
</th>
|
|
58
|
+
<th role="button" class="text-end" data-action="click->raif--sortable-table#sort" data-raif--sortable-table-target="header" data-col-index="3" data-sort-type="number" style="cursor: pointer;">
|
|
59
|
+
<%= t("raif.admin.llms.index.input_cost") %>
|
|
60
|
+
</th>
|
|
61
|
+
<th role="button" class="text-end" data-action="click->raif--sortable-table#sort" data-raif--sortable-table-target="header" data-col-index="4" data-sort-type="number" style="cursor: pointer;">
|
|
62
|
+
<%= t("raif.admin.llms.index.output_cost") %>
|
|
63
|
+
</th>
|
|
64
|
+
<th class="text-center"><%= t("raif.admin.common.default") %></th>
|
|
65
|
+
</tr>
|
|
66
|
+
</thead>
|
|
67
|
+
<tbody data-raif--sortable-table-target="body">
|
|
68
|
+
<% @llms.each do |llm| %>
|
|
69
|
+
<% input_cost = llm.input_token_cost.present? && llm.input_token_cost > 0 ? llm.input_token_cost * 1_000_000 : 0 %>
|
|
70
|
+
<% output_cost = llm.output_token_cost.present? && llm.output_token_cost > 0 ? llm.output_token_cost * 1_000_000 : 0 %>
|
|
71
|
+
<tr data-raif--table-search-target="row"
|
|
72
|
+
data-searchable="<%= "#{llm.name} #{llm.class.name.demodulize} #{llm.api_name}".downcase %>">
|
|
73
|
+
<td><%= llm.name %></td>
|
|
74
|
+
<td><code><%= llm.class.name.demodulize %></code></td>
|
|
75
|
+
<td><code><%= llm.api_name %></code></td>
|
|
76
|
+
<td class="text-end" data-sort-value="<%= input_cost %>">
|
|
77
|
+
<% if input_cost > 0 %>
|
|
78
|
+
$<%= format("%.2f", input_cost) %>
|
|
79
|
+
<% else %>
|
|
80
|
+
<span class="text-muted">-</span>
|
|
81
|
+
<% end %>
|
|
82
|
+
</td>
|
|
83
|
+
<td class="text-end" data-sort-value="<%= output_cost %>">
|
|
84
|
+
<% if output_cost > 0 %>
|
|
85
|
+
$<%= format("%.2f", output_cost) %>
|
|
86
|
+
<% else %>
|
|
87
|
+
<span class="text-muted">-</span>
|
|
88
|
+
<% end %>
|
|
89
|
+
</td>
|
|
90
|
+
<td class="text-center">
|
|
91
|
+
<% if llm.key.to_s == Raif.config.default_llm_model_key.to_s %>
|
|
92
|
+
<span class="badge bg-primary"><%= t("raif.admin.llms.index.default_badge") %></span>
|
|
93
|
+
<% end %>
|
|
94
|
+
</td>
|
|
95
|
+
</tr>
|
|
96
|
+
<% end %>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
99
|
+
<p class="text-muted mt-3 mb-0">
|
|
100
|
+
<small><%= t("raif.admin.llms.index.cost_note") %></small>
|
|
101
|
+
</p>
|
|
102
|
+
<% else %>
|
|
103
|
+
<div class="alert alert-warning mb-0">
|
|
104
|
+
<%= t("raif.admin.llms.index.no_llms") %>
|
|
105
|
+
</div>
|
|
106
|
+
<% end %>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
@@ -13,14 +13,10 @@
|
|
|
13
13
|
<span class="badge bg-secondary"><%= t("raif.admin.common.pending") %></span>
|
|
14
14
|
<% end %>
|
|
15
15
|
</td>
|
|
16
|
+
<td><small class="text-muted"><%= model_completion.runtime_duration %></small></td>
|
|
17
|
+
<td><%= model_completion.cache_read_input_tokens.to_i > 0 ? number_with_delimiter(model_completion.cache_read_input_tokens) : "-" %></td>
|
|
18
|
+
<td><%= model_completion.cache_creation_input_tokens.to_i > 0 ? number_with_delimiter(model_completion.cache_creation_input_tokens) : "-" %></td>
|
|
16
19
|
<td><%= model_completion.total_tokens ? number_with_delimiter(model_completion.total_tokens) : "-" %></td>
|
|
17
20
|
<td><%= model_completion.total_cost ? number_to_currency(model_completion.total_cost, precision: 6) : "-" %></td>
|
|
18
|
-
<td>
|
|
19
|
-
<% if model_completion.citations.present? %>
|
|
20
|
-
<span class="badge bg-info"><%= model_completion.citations.length %></span>
|
|
21
|
-
<% else %>
|
|
22
|
-
<span class="text-muted">-</span>
|
|
23
|
-
<% end %>
|
|
24
|
-
</td>
|
|
25
21
|
<td><small class="text-muted"><%= truncate(model_completion.raw_response, length: 100) %></small></td>
|
|
26
22
|
</tr>
|
|
@@ -21,6 +21,17 @@
|
|
|
21
21
|
{ class: "form-select" } %>
|
|
22
22
|
</div>
|
|
23
23
|
</div>
|
|
24
|
+
<div class="col-md-4">
|
|
25
|
+
<div class="form-group">
|
|
26
|
+
<label for="llm_model_key"><%= t("raif.admin.common.model") %></label>
|
|
27
|
+
<%= select_tag :llm_model_key,
|
|
28
|
+
options_for_select(
|
|
29
|
+
[[t("raif.admin.common.all"), ""]] + @llm_model_keys.map { |key| [key, key] },
|
|
30
|
+
@selected_llm_model_key
|
|
31
|
+
),
|
|
32
|
+
{ class: "form-select", data: { controller: "raif--tom-select" } } %>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
24
35
|
<div class="col-md-2">
|
|
25
36
|
<%= submit_tag t("raif.admin.common.filter"), class: "btn btn-primary" %>
|
|
26
37
|
</div>
|
|
@@ -38,9 +49,11 @@
|
|
|
38
49
|
<th><%= t("raif.admin.common.model") %></th>
|
|
39
50
|
<th><%= t("raif.admin.common.response_format") %></th>
|
|
40
51
|
<th><%= t("raif.admin.common.status") %></th>
|
|
52
|
+
<th><%= t("raif.admin.common.duration") %></th>
|
|
53
|
+
<th><%= t("raif.admin.common.cache_read_input_tokens") %></th>
|
|
54
|
+
<th><%= t("raif.admin.common.cache_creation_input_tokens") %></th>
|
|
41
55
|
<th><%= t("raif.admin.common.total_tokens") %></th>
|
|
42
56
|
<th><%= t("raif.admin.common.total_cost") %></th>
|
|
43
|
-
<th><%= t("raif.admin.common.citations") %></th>
|
|
44
57
|
<th><%= t("raif.admin.common.response") %></th>
|
|
45
58
|
</tr>
|
|
46
59
|
</thead>
|