raif 1.0.0 → 1.2.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 +346 -43
- data/app/assets/builds/raif.css +26 -1
- data/app/assets/stylesheets/raif/admin/stats.scss +12 -0
- data/app/assets/stylesheets/raif/loader.scss +27 -1
- data/app/controllers/raif/admin/application_controller.rb +14 -0
- data/app/controllers/raif/admin/stats/tasks_controller.rb +25 -0
- data/app/controllers/raif/admin/stats_controller.rb +19 -0
- data/app/controllers/raif/admin/tasks_controller.rb +18 -2
- data/app/controllers/raif/conversations_controller.rb +5 -1
- data/app/models/raif/agent.rb +11 -9
- data/app/models/raif/agents/native_tool_calling_agent.rb +11 -1
- data/app/models/raif/agents/re_act_agent.rb +6 -0
- data/app/models/raif/concerns/has_available_model_tools.rb +1 -1
- data/app/models/raif/concerns/json_schema_definition.rb +28 -0
- data/app/models/raif/concerns/llm_response_parsing.rb +42 -14
- data/app/models/raif/concerns/llm_temperature.rb +17 -0
- data/app/models/raif/concerns/llms/anthropic/message_formatting.rb +51 -0
- data/app/models/raif/concerns/llms/anthropic/tool_formatting.rb +56 -0
- data/app/models/raif/concerns/llms/bedrock/message_formatting.rb +70 -0
- data/app/models/raif/concerns/llms/bedrock/tool_formatting.rb +37 -0
- data/app/models/raif/concerns/llms/message_formatting.rb +42 -0
- data/app/models/raif/concerns/llms/open_ai/json_schema_validation.rb +138 -0
- data/app/models/raif/concerns/llms/open_ai_completions/message_formatting.rb +41 -0
- data/app/models/raif/concerns/llms/open_ai_completions/tool_formatting.rb +26 -0
- data/app/models/raif/concerns/llms/open_ai_responses/message_formatting.rb +43 -0
- data/app/models/raif/concerns/llms/open_ai_responses/tool_formatting.rb +42 -0
- data/app/models/raif/conversation.rb +28 -7
- data/app/models/raif/conversation_entry.rb +40 -8
- data/app/models/raif/embedding_model.rb +22 -0
- data/app/models/raif/embedding_models/bedrock.rb +34 -0
- data/app/models/raif/embedding_models/open_ai.rb +40 -0
- data/app/models/raif/llm.rb +108 -9
- data/app/models/raif/llms/anthropic.rb +72 -57
- data/app/models/raif/llms/bedrock.rb +165 -0
- data/app/models/raif/llms/open_ai_base.rb +66 -0
- data/app/models/raif/llms/open_ai_completions.rb +100 -0
- data/app/models/raif/llms/open_ai_responses.rb +144 -0
- data/app/models/raif/llms/open_router.rb +88 -0
- data/app/models/raif/model_completion.rb +23 -2
- data/app/models/raif/model_file_input.rb +113 -0
- data/app/models/raif/model_image_input.rb +4 -0
- data/app/models/raif/model_tool.rb +82 -52
- data/app/models/raif/model_tool_invocation.rb +8 -6
- data/app/models/raif/model_tools/agent_final_answer.rb +18 -27
- data/app/models/raif/model_tools/fetch_url.rb +27 -36
- data/app/models/raif/model_tools/provider_managed/base.rb +9 -0
- data/app/models/raif/model_tools/provider_managed/code_execution.rb +5 -0
- data/app/models/raif/model_tools/provider_managed/image_generation.rb +5 -0
- data/app/models/raif/model_tools/provider_managed/web_search.rb +5 -0
- data/app/models/raif/model_tools/wikipedia_search.rb +46 -55
- data/app/models/raif/streaming_responses/anthropic.rb +63 -0
- data/app/models/raif/streaming_responses/bedrock.rb +89 -0
- data/app/models/raif/streaming_responses/open_ai_completions.rb +76 -0
- data/app/models/raif/streaming_responses/open_ai_responses.rb +54 -0
- data/app/models/raif/task.rb +71 -16
- data/app/views/layouts/raif/admin.html.erb +10 -0
- data/app/views/raif/admin/agents/show.html.erb +3 -1
- data/app/views/raif/admin/conversations/_conversation.html.erb +1 -1
- data/app/views/raif/admin/conversations/_conversation_entry.html.erb +48 -0
- data/app/views/raif/admin/conversations/show.html.erb +4 -2
- data/app/views/raif/admin/model_completions/_model_completion.html.erb +8 -0
- data/app/views/raif/admin/model_completions/index.html.erb +2 -0
- data/app/views/raif/admin/model_completions/show.html.erb +58 -3
- data/app/views/raif/admin/stats/index.html.erb +128 -0
- data/app/views/raif/admin/stats/tasks/index.html.erb +45 -0
- data/app/views/raif/admin/tasks/_task.html.erb +5 -4
- data/app/views/raif/admin/tasks/index.html.erb +20 -2
- data/app/views/raif/admin/tasks/show.html.erb +3 -1
- data/app/views/raif/conversation_entries/_citations.html.erb +9 -0
- data/app/views/raif/conversation_entries/_conversation_entry.html.erb +22 -14
- data/app/views/raif/conversation_entries/_form.html.erb +1 -1
- data/app/views/raif/conversation_entries/_form_with_available_tools.html.erb +4 -4
- data/app/views/raif/conversation_entries/_message.html.erb +14 -3
- data/config/locales/admin.en.yml +16 -0
- data/config/locales/en.yml +47 -3
- data/config/routes.rb +6 -0
- data/db/migrate/20250224234252_create_raif_tables.rb +1 -1
- data/db/migrate/20250421202149_add_response_format_to_raif_conversations.rb +7 -0
- data/db/migrate/20250424200755_add_cost_columns_to_raif_model_completions.rb +14 -0
- data/db/migrate/20250424232946_add_created_at_indexes.rb +11 -0
- data/db/migrate/20250502155330_add_status_indexes_to_raif_tasks.rb +14 -0
- data/db/migrate/20250507155314_add_retry_count_to_raif_model_completions.rb +7 -0
- data/db/migrate/20250527213016_add_response_id_and_response_array_to_model_completions.rb +14 -0
- data/db/migrate/20250603140622_add_citations_to_raif_model_completions.rb +13 -0
- data/db/migrate/20250603202013_add_stream_response_to_raif_model_completions.rb +7 -0
- data/lib/generators/raif/agent/agent_generator.rb +22 -12
- data/lib/generators/raif/agent/templates/agent.rb.tt +3 -3
- data/lib/generators/raif/agent/templates/application_agent.rb.tt +7 -0
- data/lib/generators/raif/conversation/conversation_generator.rb +10 -0
- data/lib/generators/raif/conversation/templates/application_conversation.rb.tt +7 -0
- data/lib/generators/raif/conversation/templates/conversation.rb.tt +16 -14
- data/lib/generators/raif/install/templates/initializer.rb +62 -6
- data/lib/generators/raif/model_tool/model_tool_generator.rb +0 -5
- data/lib/generators/raif/model_tool/templates/model_tool.rb.tt +69 -56
- data/lib/generators/raif/task/templates/task.rb.tt +34 -23
- data/lib/raif/configuration.rb +63 -4
- data/lib/raif/embedding_model_registry.rb +83 -0
- data/lib/raif/engine.rb +56 -7
- data/lib/raif/errors/{open_ai/api_error.rb → invalid_model_file_input_error.rb} +1 -3
- data/lib/raif/errors/{anthropic/api_error.rb → invalid_model_image_input_error.rb} +1 -3
- data/lib/raif/errors/streaming_error.rb +18 -0
- data/lib/raif/errors/unsupported_feature_error.rb +8 -0
- data/lib/raif/errors.rb +4 -2
- data/lib/raif/json_schema_builder.rb +104 -0
- data/lib/raif/llm_registry.rb +315 -0
- data/lib/raif/migration_checker.rb +74 -0
- data/lib/raif/utils/html_fragment_processor.rb +169 -0
- data/lib/raif/utils.rb +1 -0
- data/lib/raif/version.rb +1 -1
- data/lib/raif.rb +7 -32
- data/lib/tasks/raif_tasks.rake +9 -4
- metadata +62 -12
- data/app/models/raif/llms/bedrock_claude.rb +0 -134
- data/app/models/raif/llms/open_ai.rb +0 -259
- data/lib/raif/default_llms.rb +0 -37
@@ -32,6 +32,16 @@
|
|
32
32
|
<div class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
|
33
33
|
<div class="position-sticky pt-3">
|
34
34
|
<ul class="nav flex-column">
|
35
|
+
<li class="nav-item">
|
36
|
+
<a class="nav-link <%= current_page?(raif.admin_stats_path) ? "active" : "" %>" href="<%= raif.admin_stats_path %>">
|
37
|
+
<span class="d-inline-block me-2">
|
38
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
|
39
|
+
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z" />
|
40
|
+
</svg>
|
41
|
+
</span>
|
42
|
+
<%= t("raif.admin.common.stats") %>
|
43
|
+
</a>
|
44
|
+
</li>
|
35
45
|
<li class="nav-item">
|
36
46
|
<a class="nav-link <%= current_page?(raif.admin_tasks_path) ? "active" : "" %>" href="<%= raif.admin_tasks_path %>">
|
37
47
|
<span class="d-inline-block me-2">
|
@@ -18,7 +18,9 @@
|
|
18
18
|
</div>
|
19
19
|
<div class="row mb-3">
|
20
20
|
<div class="col-md-3"><strong><%= t("raif.admin.common.creator") %>:</strong></div>
|
21
|
-
<div class="col-md-9"
|
21
|
+
<div class="col-md-9">
|
22
|
+
<%= @agent.creator.try(:raif_display_name) || "#{@agent.creator_type} ##{@agent.creator_id}" %>
|
23
|
+
</div>
|
22
24
|
</div>
|
23
25
|
<div class="row mb-3">
|
24
26
|
<div class="col-md-3"><strong><%= t("raif.admin.common.status") %>:</strong></div>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<tr id="<%= dom_id(conversation) %>" class="raif-conversation">
|
2
2
|
<td><%= link_to "##{conversation.id}", raif.admin_conversation_path(conversation) %></td>
|
3
3
|
<td><small class="text-muted"><%= conversation.created_at.rfc822 %></small></td>
|
4
|
-
<td><%= conversation.
|
4
|
+
<td><%= conversation.creator.try(:raif_display_name) || "#{conversation.creator_type} ##{conversation.creator_id}" %></td>
|
5
5
|
<td><%= conversation.type %></td>
|
6
6
|
<td><%= conversation.conversation_entries_count %></td>
|
7
7
|
</tr>
|
@@ -21,6 +21,7 @@
|
|
21
21
|
<%= link_to t("raif.admin.common.model_completion"), raif.admin_model_completion_path(entry.raif_model_completion) %>
|
22
22
|
<% end %>
|
23
23
|
</div>
|
24
|
+
|
24
25
|
<div class="mb-3">
|
25
26
|
<strong><%= t("raif.admin.common.user_message") %>:</strong>
|
26
27
|
<pre class="mt-2"><%= entry.user_message %></pre>
|
@@ -31,4 +32,51 @@
|
|
31
32
|
<pre class="mt-2"><%= entry.model_response_message %></pre>
|
32
33
|
</div>
|
33
34
|
<% end %>
|
35
|
+
|
36
|
+
<% if entry.raif_model_tool_invocations.any? %>
|
37
|
+
<div class="mb-3">
|
38
|
+
<strong><%= t("raif.admin.common.model_tool_invocations") %>:</strong>
|
39
|
+
<div class="ms-3 mt-2">
|
40
|
+
<% entry.raif_model_tool_invocations.each do |invocation| %>
|
41
|
+
<div class="card mb-2">
|
42
|
+
<div class="card-body p-3">
|
43
|
+
<div class="d-flex w-100 justify-content-between align-items-start">
|
44
|
+
<div>
|
45
|
+
<h6 class="mb-1">
|
46
|
+
<%= link_to invocation.tool_name, raif.admin_model_tool_invocation_path(invocation) %>
|
47
|
+
</h6>
|
48
|
+
<% if invocation.completed_at? %>
|
49
|
+
<span class="badge bg-success"><%= t("raif.admin.common.completed") %></span>
|
50
|
+
<% elsif invocation.failed_at? %>
|
51
|
+
<span class="badge bg-danger"><%= t("raif.admin.common.failed") %></span>
|
52
|
+
<% else %>
|
53
|
+
<span class="badge bg-secondary"><%= t("raif.admin.common.pending") %></span>
|
54
|
+
<% end %>
|
55
|
+
</div>
|
56
|
+
<small class="text-muted"><%= invocation.created_at.rfc822 %></small>
|
57
|
+
</div>
|
58
|
+
<div class="mt-2">
|
59
|
+
<strong><%= t("raif.admin.common.arguments") %>:</strong>
|
60
|
+
<pre class="pre-wrap mt-1"><%= begin
|
61
|
+
JSON.pretty_generate(invocation.tool_arguments)
|
62
|
+
rescue StandardError
|
63
|
+
invocation.tool_arguments
|
64
|
+
end %></pre>
|
65
|
+
</div>
|
66
|
+
<% if invocation.result.present? %>
|
67
|
+
<div class="mt-2">
|
68
|
+
<strong><%= t("raif.admin.common.result") %>:</strong>
|
69
|
+
<pre class="pre-wrap mt-1"><%= begin
|
70
|
+
JSON.pretty_generate(invocation.result)
|
71
|
+
rescue StandardError
|
72
|
+
invocation.result
|
73
|
+
end %></pre>
|
74
|
+
</div>
|
75
|
+
<% end %>
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
<% end %>
|
34
82
|
</div>
|
@@ -14,7 +14,9 @@
|
|
14
14
|
</div>
|
15
15
|
<div class="row mb-3">
|
16
16
|
<div class="col-md-3"><strong><%= t("raif.admin.common.creator") %>:</strong></div>
|
17
|
-
<div class="col-md-9"
|
17
|
+
<div class="col-md-9">
|
18
|
+
<%= @conversation.creator.try(:raif_display_name) || "#{@conversation.creator_type} ##{@conversation.creator_id}" %>
|
19
|
+
</div>
|
18
20
|
</div>
|
19
21
|
<div class="row mb-3">
|
20
22
|
<div class="col-md-3"><strong><%= t("raif.admin.common.type") %>:</strong></div>
|
@@ -47,7 +49,7 @@
|
|
47
49
|
</div>
|
48
50
|
<div class="card-body">
|
49
51
|
<div class="list-group">
|
50
|
-
<%= render collection: @conversation.entries.order(created_at: :asc).includes(:raif_model_completion),
|
52
|
+
<%= render collection: @conversation.entries.order(created_at: :asc).includes(:raif_model_completion, :raif_model_tool_invocations),
|
51
53
|
partial: "raif/admin/conversations/conversation_entry",
|
52
54
|
as: :entry %>
|
53
55
|
</div>
|
@@ -5,5 +5,13 @@
|
|
5
5
|
<td><%= model_completion.llm_model_key %></td>
|
6
6
|
<td><%= model_completion.response_format %></td>
|
7
7
|
<td><%= model_completion.total_tokens ? number_with_delimiter(model_completion.total_tokens) : "-" %></td>
|
8
|
+
<td><%= model_completion.total_cost ? number_to_currency(model_completion.total_cost, precision: 6) : "-" %></td>
|
9
|
+
<td>
|
10
|
+
<% if model_completion.citations.present? %>
|
11
|
+
<span class="badge bg-info"><%= model_completion.citations.length %></span>
|
12
|
+
<% else %>
|
13
|
+
<span class="text-muted">-</span>
|
14
|
+
<% end %>
|
15
|
+
</td>
|
8
16
|
<td><small class="text-muted"><%= truncate(model_completion.raw_response, length: 100) %></small></td>
|
9
17
|
</tr>
|
@@ -13,6 +13,8 @@
|
|
13
13
|
<th><%= t("raif.admin.common.model") %></th>
|
14
14
|
<th><%= t("raif.admin.common.response_format") %></th>
|
15
15
|
<th><%= t("raif.admin.common.total_tokens") %></th>
|
16
|
+
<th><%= t("raif.admin.common.total_cost") %></th>
|
17
|
+
<th><%= t("raif.admin.common.citations") %></th>
|
16
18
|
<th><%= t("raif.admin.common.response") %></th>
|
17
19
|
</tr>
|
18
20
|
</thead>
|
@@ -34,15 +34,42 @@
|
|
34
34
|
</div>
|
35
35
|
<div class="row mb-3">
|
36
36
|
<div class="col-md-3"><strong><%= t("raif.admin.common.prompt_tokens") %>:</strong></div>
|
37
|
-
<div class="col-md-9"
|
37
|
+
<div class="col-md-9">
|
38
|
+
<% if @model_completion.prompt_tokens %>
|
39
|
+
<%= number_with_delimiter(@model_completion.prompt_tokens) %>
|
40
|
+
<% if @model_completion.prompt_token_cost %>
|
41
|
+
<small>(<%= t("raif.admin.common.est_cost") %>: <%= "$" %><%= number_with_precision(@model_completion.prompt_token_cost, precision: 6) %>)</small>
|
42
|
+
<% end %>
|
43
|
+
<% else %>
|
44
|
+
-
|
45
|
+
<% end %>
|
46
|
+
</div>
|
38
47
|
</div>
|
39
48
|
<div class="row mb-3">
|
40
49
|
<div class="col-md-3"><strong><%= t("raif.admin.common.completion_tokens") %>:</strong></div>
|
41
|
-
<div class="col-md-9"
|
50
|
+
<div class="col-md-9">
|
51
|
+
<% if @model_completion.completion_tokens %>
|
52
|
+
<%= number_with_delimiter(@model_completion.completion_tokens) %>
|
53
|
+
<% if @model_completion.output_token_cost %>
|
54
|
+
<small>(<%= t("raif.admin.common.est_cost") %>: <%= "$" %><%= number_with_precision(@model_completion.output_token_cost, precision: 6) %>)</small>
|
55
|
+
<% end %>
|
56
|
+
<% else %>
|
57
|
+
-
|
58
|
+
<% end %>
|
59
|
+
</div>
|
42
60
|
</div>
|
43
61
|
<div class="row mb-3">
|
44
62
|
<div class="col-md-3"><strong><%= t("raif.admin.common.total_tokens") %>:</strong></div>
|
45
|
-
<div class="col-md-9"
|
63
|
+
<div class="col-md-9">
|
64
|
+
<% if @model_completion.total_tokens %>
|
65
|
+
<%= number_with_delimiter(@model_completion.total_tokens) %>
|
66
|
+
<% if @model_completion.total_cost %>
|
67
|
+
<small>(<%= t("raif.admin.common.est_cost") %>: <%= "$" %><%= number_with_precision(@model_completion.total_cost, precision: 6) %>)</small>
|
68
|
+
<% end %>
|
69
|
+
<% else %>
|
70
|
+
-
|
71
|
+
<% end %>
|
72
|
+
</div>
|
46
73
|
</div>
|
47
74
|
</div>
|
48
75
|
</div>
|
@@ -115,3 +142,31 @@
|
|
115
142
|
<% end %>
|
116
143
|
</div>
|
117
144
|
</div>
|
145
|
+
|
146
|
+
<div class="card mb-4">
|
147
|
+
<div class="card-header">
|
148
|
+
<h5 class="mb-0"><%= t("raif.admin.common.citations") %></h5>
|
149
|
+
</div>
|
150
|
+
<div class="card-body">
|
151
|
+
<% if @model_completion.citations.present? %>
|
152
|
+
<% @model_completion.citations.each_with_index do |citation, index| %>
|
153
|
+
<div class="mb-3 p-3 border rounded">
|
154
|
+
<div class="d-flex align-items-start">
|
155
|
+
<span class="badge bg-primary me-3"><%= index + 1 %></span>
|
156
|
+
<div class="flex-grow-1">
|
157
|
+
<h6 class="mb-1">
|
158
|
+
<a href="<%= citation["url"] %>" target="_blank" rel="noopener" class="text-decoration-none">
|
159
|
+
<%= citation["title"] %>
|
160
|
+
<i class="bi bi-box-arrow-up-right ms-1" style="font-size: 0.8em;"></i>
|
161
|
+
</a>
|
162
|
+
</h6>
|
163
|
+
<small class="text-muted"><%= citation["url"] %></small>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
</div>
|
167
|
+
<% end %>
|
168
|
+
<% else %>
|
169
|
+
<p class="text-muted mb-0"><%= t("raif.admin.common.no_citations") %></p>
|
170
|
+
<% end %>
|
171
|
+
</div>
|
172
|
+
</div>
|
@@ -0,0 +1,128 @@
|
|
1
|
+
<div class="d-flex justify-content-between align-items-center my-4">
|
2
|
+
<h1 class="mb-0"><%= t("raif.admin.common.stats") %></h1>
|
3
|
+
|
4
|
+
<div class="period-filter">
|
5
|
+
<%= form_tag raif.admin_stats_path, method: :get, id: "period_filter_form", class: "d-flex align-items-center" do %>
|
6
|
+
<%= select_tag :period,
|
7
|
+
options_for_select(
|
8
|
+
[
|
9
|
+
[t("raif.admin.common.period_day"), "day"],
|
10
|
+
[t("raif.admin.common.period_week"), "week"],
|
11
|
+
[t("raif.admin.common.period_month"), "month"],
|
12
|
+
[t("raif.admin.common.period_all"), "all"]
|
13
|
+
],
|
14
|
+
@selected_period
|
15
|
+
),
|
16
|
+
class: "form-select form-select-sm me-2" %>
|
17
|
+
<%= submit_tag t("raif.admin.common.update"), class: "btn btn-sm btn-primary" %>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div class="row">
|
23
|
+
<div class="col-12">
|
24
|
+
<div class="card shadow-sm mb-4">
|
25
|
+
<div class="card-body">
|
26
|
+
<div class="row g-4">
|
27
|
+
<!-- Model Completions -->
|
28
|
+
<div class="col-md-4 col-lg-4">
|
29
|
+
<div class="stats-card p-3 border rounded shadow-sm h-100">
|
30
|
+
<div class="d-flex align-items-center mb-2">
|
31
|
+
<span class="stats-icon bg-primary-subtle text-primary rounded p-2 me-3">
|
32
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-robot" viewBox="0 0 16 16">
|
33
|
+
<path d="M6 12.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5ZM3 8.062C3 6.76 4.235 5.765 5.53 5.886a26.58 26.58 0 0 0 4.94 0C11.765 5.765 13 6.76 13 8.062v1.157a.933.933 0 0 1-.765.935c-.845.147-2.34.346-4.235.346-1.895 0-3.39-.2-4.235-.346A.933.933 0 0 1 3 9.219V8.062Zm4.542-.827a.25.25 0 0 0-.217.068l-.92.9a24.767 24.767 0 0 1-1.871-.183.25.25 0 0 0-.068.495c.55.076 1.232.149 2.02.193a.25.25 0 0 0 .189-.071l.754-.736.847 1.71a.25.25 0 0 0 .404.062l.932-.97a25.286 25.286 0 0 0 1.922-.188.25.25 0 0 0-.068-.495c-.538.074-1.207.145-1.98.189a.25.25 0 0 0-.166.076l-.754.785-.842-1.7a.25.25 0 0 0-.182-.135Z" />
|
34
|
+
<path d="M8.5 1.866a1 1 0 1 0-1 0V3h-2A4.5 4.5 0 0 0 1 7.5V8a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1v1a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v-.5A4.5 4.5 0 0 0 10.5 3h-2V1.866ZM14 7.5V13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5A3.5 3.5 0 0 1 5.5 4h5A3.5 3.5 0 0 1 14 7.5Z" />
|
35
|
+
</svg>
|
36
|
+
</span>
|
37
|
+
<div>
|
38
|
+
<h6 class="mb-0 text-muted"><%= t("raif.admin.common.model_completions") %></h6>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<div class="d-flex justify-content-between align-items-center">
|
42
|
+
<h3 class="fw-bold mb-0"><%= number_with_delimiter(@model_completion_count) %></h3>
|
43
|
+
<p class="text-muted mt-2 mb-0"><small><%= t("raif.admin.common.est_cost") %>: <%= number_to_currency(@model_completion_total_cost, precision: 6) %></small></p>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<!-- Tasks -->
|
49
|
+
<div class="col-md-4 col-lg-4">
|
50
|
+
<div class="stats-card p-3 border rounded shadow-sm h-100">
|
51
|
+
<div class="d-flex align-items-center mb-2">
|
52
|
+
<span class="stats-icon bg-success-subtle text-success rounded p-2 me-3">
|
53
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-list-check" viewBox="0 0 16 16">
|
54
|
+
<path fill-rule="evenodd" d="M5 11.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3.854 2.146a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708L2 3.293l1.146-1.147a.5.5 0 0 1 .708 0zm0 4a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708L2 7.293l1.146-1.147a.5.5 0 0 1 .708 0zm0 4a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 0 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0z" />
|
55
|
+
</svg>
|
56
|
+
</span>
|
57
|
+
<div>
|
58
|
+
<h6 class="mb-0 text-muted"><%= t("raif.admin.common.tasks") %></h6>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
<div class="d-flex justify-content-between align-items-center">
|
62
|
+
<h3 class="fw-bold mb-0"><%= number_with_delimiter(@task_count) %></h3>
|
63
|
+
<div class="mt-2">
|
64
|
+
<%= link_to raif.admin_stats_tasks_path(period: @selected_period) do %>
|
65
|
+
<%= t("raif.admin.common.details") %> »
|
66
|
+
<% end %>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
|
72
|
+
<!-- Agents -->
|
73
|
+
<div class="col-md-4 col-lg-4">
|
74
|
+
<div class="stats-card p-3 border rounded shadow-sm h-100">
|
75
|
+
<div class="d-flex align-items-center mb-2">
|
76
|
+
<span class="stats-icon bg-danger-subtle text-danger rounded p-2 me-3">
|
77
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cpu" viewBox="0 0 16 16">
|
78
|
+
<path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z" />
|
79
|
+
</svg>
|
80
|
+
</span>
|
81
|
+
<div>
|
82
|
+
<h6 class="mb-0 text-muted"><%= t("raif.admin.common.agents") %></h6>
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
<h3 class="fw-bold mb-0"><%= number_with_delimiter(@agent_count) %></h3>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
|
89
|
+
<!-- Conversations -->
|
90
|
+
<div class="col-md-4 col-lg-4">
|
91
|
+
<div class="stats-card p-3 border rounded shadow-sm h-100">
|
92
|
+
<div class="d-flex align-items-center mb-2">
|
93
|
+
<span class="stats-icon bg-info-subtle text-info rounded p-2 me-3">
|
94
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-chat-dots" viewBox="0 0 16 16">
|
95
|
+
<path d="M5 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm4 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />
|
96
|
+
<path d="m2.165 15.803.02-.004c1.83-.363 2.948-.842 3.468-1.105A9.06 9.06 0 0 0 8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6a10.437 10.437 0 0 1-.524 2.318l-.003.011a10.722 10.722 0 0 1-.244.637c-.079.186.074.394.273.362a21.673 21.673 0 0 0 .693-.125zm.8-3.108a1 1 0 0 0-.287-.801C1.618 10.83 1 9.468 1 8c0-3.192 3.004-6 7-6s7 2.808 7 6c0 3.193-3.004 6-7 6a8.06 8.06 0 0 1-2.088-.272a1 1 0 0 0-.711.074c-.387.196-1.24.57-2.634.893a10.97 10.97 0 0 0 .398-2z" />
|
97
|
+
</svg>
|
98
|
+
</span>
|
99
|
+
<div>
|
100
|
+
<h6 class="mb-0 text-muted"><%= t("raif.admin.common.conversations") %></h6>
|
101
|
+
</div>
|
102
|
+
</div>
|
103
|
+
<h3 class="fw-bold mb-0"><%= number_with_delimiter(@conversation_count) %></h3>
|
104
|
+
</div>
|
105
|
+
</div>
|
106
|
+
|
107
|
+
<!-- Conversation Entries -->
|
108
|
+
<div class="col-md-4 col-lg-4">
|
109
|
+
<div class="stats-card p-3 border rounded shadow-sm h-100">
|
110
|
+
<div class="d-flex align-items-center mb-2">
|
111
|
+
<span class="stats-icon bg-warning-subtle text-warning rounded p-2 me-3">
|
112
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-chat-text" viewBox="0 0 16 16">
|
113
|
+
<path d="M2.678 11.894a1 1 0 0 1 .287.801 10.97 10.97 0 0 1-.398 2c1.395-.323 2.247-.697 2.634-.893a1 1 0 0 1 .71-.074A8.06 8.06 0 0 0 8 14c3.996 0 7-2.807 7-6 0-3.192-3.004-6-7-6S1 4.808 1 8c0 1.468.617 2.83 1.678 3.894zm-.493 3.905a21.682 21.682 0 0 1-.713.129c-.2.032-.352-.176-.273-.362a9.68 9.68 0 0 0 .244-.637l.003-.01c.248-.72.45-1.548.524-2.319C.743 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.52.263-1.639.742-3.468 1.105z" />
|
114
|
+
<path d="M4 5.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zM4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8zm0 2.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5z" />
|
115
|
+
</svg>
|
116
|
+
</span>
|
117
|
+
<div>
|
118
|
+
<h6 class="mb-0 text-muted"><%= t("raif.admin.common.conversation_entries") %></h6>
|
119
|
+
</div>
|
120
|
+
</div>
|
121
|
+
<h3 class="fw-bold mb-0"><%= number_with_delimiter(@conversation_entry_count) %></h3>
|
122
|
+
</div>
|
123
|
+
</div>
|
124
|
+
</div>
|
125
|
+
</div>
|
126
|
+
</div>
|
127
|
+
</div>
|
128
|
+
</div>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<%= link_to raif.admin_stats_path do %>
|
2
|
+
« <%= t("raif.admin.stats.tasks.back_to_stats") %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<div class="d-flex justify-content-between align-items-center my-4">
|
6
|
+
<h1 class="mb-0"><%= t("raif.admin.stats.tasks.title") %></h1>
|
7
|
+
|
8
|
+
<div class="period-filter">
|
9
|
+
<%= form_tag raif.admin_stats_tasks_path, method: :get, id: "period_filter_form", class: "d-flex align-items-center" do %>
|
10
|
+
<%= select_tag :period,
|
11
|
+
options_for_select(
|
12
|
+
[
|
13
|
+
[t("raif.admin.common.period_day"), "day"],
|
14
|
+
[t("raif.admin.common.period_week"), "week"],
|
15
|
+
[t("raif.admin.common.period_month"), "month"],
|
16
|
+
[t("raif.admin.common.period_all"), "all"]
|
17
|
+
],
|
18
|
+
@selected_period
|
19
|
+
),
|
20
|
+
class: "form-select form-select-sm me-2" %>
|
21
|
+
<%= submit_tag t("raif.admin.common.update"), class: "btn btn-sm btn-primary" %>
|
22
|
+
<% end %>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<div class="table-responsive">
|
27
|
+
<table class="table table-striped table-hover">
|
28
|
+
<thead class="table-light">
|
29
|
+
<tr>
|
30
|
+
<th><%= t("raif.admin.common.type") %></th>
|
31
|
+
<th><%= t("raif.admin.common.count") %></th>
|
32
|
+
<th><%= t("raif.admin.common.est_cost") %></th>
|
33
|
+
</tr>
|
34
|
+
</thead>
|
35
|
+
<tbody>
|
36
|
+
<% @task_counts_by_type.each do |type, count| %>
|
37
|
+
<tr>
|
38
|
+
<td><%= type %></td>
|
39
|
+
<td><%= number_with_delimiter(count) %></td>
|
40
|
+
<td><%= number_to_currency(@task_costs_by_type[type] || 0, precision: 6) %></td>
|
41
|
+
</tr>
|
42
|
+
<% end %>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
45
|
+
</div>
|
@@ -2,14 +2,15 @@
|
|
2
2
|
<td><%= link_to "##{task.id}", raif.admin_task_path(task) %></td>
|
3
3
|
<td><%= task.type %></td>
|
4
4
|
<td><small class="text-muted"><%= task.created_at.rfc822 %></small></td>
|
5
|
-
<td><%= task.
|
5
|
+
<td><%= task.creator.try(:raif_display_name) || "#{task.creator_type} ##{task.creator_id}" %></td>
|
6
6
|
<td><%= task.llm_model_key %></td>
|
7
7
|
<td>
|
8
|
-
<%
|
8
|
+
<% case task.status %>
|
9
|
+
<% when :completed %>
|
9
10
|
<span class="badge bg-success"><%= t("raif.admin.common.completed") %></span>
|
10
|
-
<%
|
11
|
+
<% when :failed %>
|
11
12
|
<span class="badge bg-danger"><%= t("raif.admin.common.failed") %></span>
|
12
|
-
<%
|
13
|
+
<% when :in_progress %>
|
13
14
|
<span class="badge bg-warning text-dark"><%= t("raif.admin.common.in_progress") %></span>
|
14
15
|
<% else %>
|
15
16
|
<span class="badge bg-secondary"><%= t("raif.admin.common.pending") %></span>
|
@@ -4,10 +4,28 @@
|
|
4
4
|
<div class="col-12">
|
5
5
|
<%= form_tag raif.admin_tasks_path, method: :get, class: "mb-4" do %>
|
6
6
|
<div class="row align-items-end">
|
7
|
-
<div class="col-md-
|
7
|
+
<div class="col-md-4">
|
8
8
|
<div class="form-group">
|
9
|
+
<label for="task_types"><%= t("raif.admin.common.type") %></label>
|
9
10
|
<%= select_tag :task_types,
|
10
|
-
options_for_select(@task_types.map{|type| [type, type] }, @
|
11
|
+
options_for_select([["All", "all"]] + @task_types.map{|type| [type, type] }, @selected_type),
|
12
|
+
{ class: "form-select" } %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<div class="col-md-4">
|
16
|
+
<div class="form-group">
|
17
|
+
<label for="task_statuses"><%= t("raif.admin.common.status") %></label>
|
18
|
+
<%= select_tag :task_statuses,
|
19
|
+
options_for_select(
|
20
|
+
[
|
21
|
+
[t("raif.admin.common.all"), :all],
|
22
|
+
[t("raif.admin.common.completed"), :completed],
|
23
|
+
[t("raif.admin.common.failed"), :failed],
|
24
|
+
[t("raif.admin.common.in_progress"), :in_progress],
|
25
|
+
[t("raif.admin.common.pending"), :pending]
|
26
|
+
],
|
27
|
+
@selected_statuses
|
28
|
+
),
|
11
29
|
{ class: "form-select" } %>
|
12
30
|
</div>
|
13
31
|
</div>
|
@@ -14,7 +14,9 @@
|
|
14
14
|
</div>
|
15
15
|
<div class="row mb-3">
|
16
16
|
<div class="col-md-3"><strong><%= t("raif.admin.common.creator") %>:</strong></div>
|
17
|
-
<div class="col-md-9"
|
17
|
+
<div class="col-md-9">
|
18
|
+
<%= @task.creator.try(:raif_display_name) || "#{@task.creator_type} ##{@task.creator_id}" %>
|
19
|
+
</div>
|
18
20
|
</div>
|
19
21
|
<div class="row mb-3">
|
20
22
|
<div class="col-md-3"><strong><%= t("raif.admin.common.model") %>:</strong></div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="conversation-entry-citations">
|
2
|
+
<h6><%= t("raif.common.sources") %></h6>
|
3
|
+
<% conversation_entry.citations.each do |citation| %>
|
4
|
+
<%= link_to citation["url"], target: "_blank", rel: "noopener noreferrer", class: "d-flex align-items-center" do %>
|
5
|
+
<%= image_tag "https://www.google.com/s2/favicons?sz=16&domain=#{citation["url"]}", class: "me-1" %>
|
6
|
+
<%= citation["title"] %>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
@@ -1,26 +1,34 @@
|
|
1
|
-
<div id="<%= dom_id(conversation_entry) %>" class="my-2">
|
1
|
+
<div id="<%= dom_id(conversation_entry) %>" class="my-2 conversation-entry">
|
2
2
|
<%= render "raif/conversation_entries/message",
|
3
3
|
conversation_entry: conversation_entry,
|
4
4
|
content: conversation_entry.user_message,
|
5
|
-
message_type: :user %>
|
5
|
+
message_type: :user if conversation_entry.user_message.present? %>
|
6
6
|
|
7
|
-
<% if conversation_entry.
|
8
|
-
<%= render "raif/conversation_entries/message",
|
9
|
-
conversation_entry: conversation_entry,
|
10
|
-
content: conversation_entry.generating_response? ? content_tag(:span, "", class: "raif-loader") : conversation_entry.model_response_message,
|
11
|
-
message_type: :model_response %>
|
12
|
-
|
13
|
-
<% conversation_entry.raif_model_tool_invocations.select(&:renderable?).each do |ti| %>
|
14
|
-
<div class="mb-4 container">
|
15
|
-
<%= render ti, conversation_entry: conversation_entry %>
|
16
|
-
</div>
|
17
|
-
<% end %>
|
18
|
-
<% elsif conversation_entry.failed? %>
|
7
|
+
<% if conversation_entry.failed? %>
|
19
8
|
<div class="mb-4 container">
|
20
9
|
<%= render "raif/conversation_entries/message",
|
21
10
|
conversation_entry: conversation_entry,
|
22
11
|
content: t("raif.common.there_was_an_error_generating_this_response"),
|
23
12
|
message_type: :model_response %>
|
24
13
|
</div>
|
14
|
+
<% elsif conversation_entry.generating_response? %>
|
15
|
+
<%= render "raif/conversation_entries/message",
|
16
|
+
conversation_entry: conversation_entry,
|
17
|
+
content: if conversation_entry.model_response_message.present?
|
18
|
+
conversation_entry.model_response_message + content_tag(:span, "", class: "raif-streaming-cursor")
|
19
|
+
else
|
20
|
+
content_tag(:span, "", class: "raif-loader")
|
21
|
+
end,
|
22
|
+
message_type: :model_response %>
|
23
|
+
|
24
|
+
<% elsif conversation_entry.completed? %>
|
25
|
+
<%= render "raif/conversation_entries/message",
|
26
|
+
conversation_entry: conversation_entry,
|
27
|
+
content: conversation_entry.model_response_message,
|
28
|
+
message_type: :model_response if conversation_entry.model_response_message.present? %>
|
29
|
+
|
30
|
+
<% conversation_entry.raif_model_tool_invocations.select(&:renderable?).each do |ti| %>
|
31
|
+
<%= render ti, conversation_entry: conversation_entry %>
|
32
|
+
<% end %>
|
25
33
|
<% end %>
|
26
34
|
</div>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<% end %>
|
11
11
|
<% end %>
|
12
12
|
|
13
|
-
<div class="d-flex">
|
13
|
+
<div class="d-flex px-2">
|
14
14
|
<%= f.text_field :user_message,
|
15
15
|
class: "form-control me-2",
|
16
16
|
placeholder: conversation_entry.raif_user_tool_invocation&.message_input_placeholder.presence || t("raif.common.type_your_message"),
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
<%= render "raif/
|
4
|
-
|
1
|
+
<div class="border-top pt-2">
|
2
|
+
<%= render "raif/conversations/available_user_tools", conversation: conversation %>
|
3
|
+
<%= render "raif/conversation_entries/form", conversation: conversation, conversation_entry: conversation_entry %>
|
4
|
+
</div>
|
@@ -1,12 +1,23 @@
|
|
1
|
-
<div class="d-flex
|
2
|
-
<div class="d-flex
|
1
|
+
<div class="d-flex my-2 px-3 <%= "justify-content-end" if message_type == :user %>">
|
2
|
+
<div class="d-flex <%= "chat-message-content" if message_type == :user %> <%= "received-message-content" if message_type == :model_response %>">
|
3
3
|
<% if message_type == :model_response %>
|
4
4
|
<%= render "raif/conversation_entries/model_response_avatar", conversation_entry: local_assigns[:conversation_entry] %>
|
5
5
|
<% end %>
|
6
6
|
|
7
7
|
<% if content.present? %>
|
8
8
|
<div class="mb-1 rounded-2 p-3 <%= message_type == :user ? "bg-primary text-white" : "border" %>">
|
9
|
-
|
9
|
+
<% case local_assigns[:conversation_entry]&.response_format %>
|
10
|
+
<% when "text" %>
|
11
|
+
<%= simple_format content %>
|
12
|
+
<% when "html" %>
|
13
|
+
<%= sanitize content %>
|
14
|
+
<% else %>
|
15
|
+
<%= content %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if message_type == :model_response && local_assigns[:conversation_entry]&.citations.present? %>
|
19
|
+
<%= render "raif/conversation_entries/citations", conversation_entry: conversation_entry %>
|
20
|
+
<% end %>
|
10
21
|
</div>
|
11
22
|
<% end %>
|
12
23
|
|