raif 1.3.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.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -7
  3. data/app/assets/builds/raif.css +4 -1
  4. data/app/assets/builds/raif_admin.css +52 -2
  5. data/app/assets/builds/raif_admin_sprockets.js +2709 -0
  6. data/app/assets/javascript/raif/admin/copy_to_clipboard_controller.js +132 -0
  7. data/app/assets/javascript/raif/admin/cost_estimate_controller.js +80 -0
  8. data/app/assets/javascript/raif/admin/judge_config_controller.js +23 -0
  9. data/app/assets/javascript/raif/admin/select_all_checkboxes_controller.js +33 -0
  10. data/app/assets/javascript/raif/admin/sortable_table_controller.js +51 -0
  11. data/app/assets/javascript/raif/admin/table_search_controller.js +15 -0
  12. data/app/assets/javascript/raif/admin/tom_select_controller.js +33 -0
  13. data/app/assets/javascript/raif/controllers/conversations_controller.js +1 -1
  14. data/app/assets/javascript/raif_admin.js +23 -0
  15. data/app/assets/javascript/raif_admin_sprockets.js +24 -0
  16. data/app/assets/stylesheets/raif/admin/conversation.scss +16 -0
  17. data/app/assets/stylesheets/raif/conversations.scss +3 -0
  18. data/app/assets/stylesheets/raif.scss +2 -1
  19. data/app/assets/stylesheets/raif_admin.scss +50 -1
  20. data/app/controllers/raif/admin/agents_controller.rb +27 -1
  21. data/app/controllers/raif/admin/application_controller.rb +16 -0
  22. data/app/controllers/raif/admin/configs_controller.rb +95 -0
  23. data/app/controllers/raif/admin/llms_controller.rb +27 -0
  24. data/app/controllers/raif/admin/model_completions_controller.rb +24 -1
  25. data/app/controllers/raif/admin/model_tool_invocations_controller.rb +7 -1
  26. data/app/controllers/raif/admin/prompt_studio/agents_controller.rb +25 -0
  27. data/app/controllers/raif/admin/prompt_studio/base_controller.rb +32 -0
  28. data/app/controllers/raif/admin/prompt_studio/batch_runs_controller.rb +102 -0
  29. data/app/controllers/raif/admin/prompt_studio/conversations_controller.rb +25 -0
  30. data/app/controllers/raif/admin/prompt_studio/tasks_controller.rb +64 -0
  31. data/app/controllers/raif/admin/stats/model_tool_invocations_controller.rb +21 -0
  32. data/app/controllers/raif/admin/stats/tasks_controller.rb +15 -6
  33. data/app/controllers/raif/admin/stats_controller.rb +32 -3
  34. data/app/controllers/raif/admin/tasks_controller.rb +5 -0
  35. data/app/controllers/raif/conversation_entries_controller.rb +1 -0
  36. data/app/controllers/raif/conversations_controller.rb +10 -2
  37. data/app/helpers/raif/application_helper.rb +40 -0
  38. data/app/jobs/raif/conversation_entry_job.rb +8 -6
  39. data/app/jobs/raif/prompt_studio_batch_run_item_job.rb +11 -0
  40. data/app/jobs/raif/prompt_studio_batch_run_job.rb +15 -0
  41. data/app/jobs/raif/prompt_studio_task_run_job.rb +36 -0
  42. data/app/models/raif/admin/task_stat.rb +7 -0
  43. data/app/models/raif/agent.rb +98 -6
  44. data/app/models/raif/agents/native_tool_calling_agent.rb +179 -52
  45. data/app/models/raif/application_record.rb +18 -0
  46. data/app/models/raif/concerns/agent_inference_stats.rb +35 -0
  47. data/app/models/raif/concerns/has_prompt_templates.rb +88 -0
  48. data/app/models/raif/concerns/has_runtime_duration.rb +41 -0
  49. data/app/models/raif/concerns/json_schema_definition.rb +54 -6
  50. data/app/models/raif/concerns/llm_prompt_caching.rb +20 -0
  51. data/app/models/raif/concerns/llms/anthropic/message_formatting.rb +34 -0
  52. data/app/models/raif/concerns/llms/anthropic/response_tool_calls.rb +24 -0
  53. data/app/models/raif/concerns/llms/anthropic/tool_formatting.rb +8 -0
  54. data/app/models/raif/concerns/llms/bedrock/message_formatting.rb +43 -0
  55. data/app/models/raif/concerns/llms/bedrock/response_tool_calls.rb +26 -0
  56. data/app/models/raif/concerns/llms/bedrock/tool_formatting.rb +8 -0
  57. data/app/models/raif/concerns/llms/google/message_formatting.rb +112 -0
  58. data/app/models/raif/concerns/llms/google/response_tool_calls.rb +32 -0
  59. data/app/models/raif/concerns/llms/google/tool_formatting.rb +76 -0
  60. data/app/models/raif/concerns/llms/message_formatting.rb +41 -5
  61. data/app/models/raif/concerns/llms/open_ai/json_schema_validation.rb +3 -3
  62. data/app/models/raif/concerns/llms/open_ai_completions/message_formatting.rb +22 -0
  63. data/app/models/raif/concerns/llms/open_ai_completions/response_tool_calls.rb +22 -0
  64. data/app/models/raif/concerns/llms/open_ai_completions/tool_formatting.rb +8 -0
  65. data/app/models/raif/concerns/llms/open_ai_responses/message_formatting.rb +17 -0
  66. data/app/models/raif/concerns/llms/open_ai_responses/response_tool_calls.rb +26 -0
  67. data/app/models/raif/concerns/llms/open_ai_responses/tool_formatting.rb +8 -0
  68. data/app/models/raif/concerns/provider_managed_tool_calls.rb +162 -0
  69. data/app/models/raif/concerns/run_with.rb +127 -0
  70. data/app/models/raif/conversation.rb +112 -8
  71. data/app/models/raif/conversation_entry.rb +38 -4
  72. data/app/models/raif/embedding_model.rb +2 -1
  73. data/app/models/raif/embedding_models/bedrock.rb +10 -1
  74. data/app/models/raif/embedding_models/google.rb +37 -0
  75. data/app/models/raif/embedding_models/open_ai.rb +1 -1
  76. data/app/models/raif/evals/llm_judge.rb +70 -0
  77. data/{lib → app/models}/raif/evals/llm_judges/binary.rb +41 -3
  78. data/{lib → app/models}/raif/evals/llm_judges/comparative.rb +41 -3
  79. data/{lib → app/models}/raif/evals/llm_judges/scored.rb +39 -1
  80. data/{lib → app/models}/raif/evals/llm_judges/summarization.rb +40 -2
  81. data/app/models/raif/llm.rb +104 -4
  82. data/app/models/raif/llms/anthropic.rb +32 -22
  83. data/app/models/raif/llms/bedrock.rb +64 -24
  84. data/app/models/raif/llms/google.rb +166 -0
  85. data/app/models/raif/llms/open_ai_base.rb +23 -5
  86. data/app/models/raif/llms/open_ai_completions.rb +14 -12
  87. data/app/models/raif/llms/open_ai_responses.rb +14 -17
  88. data/app/models/raif/llms/open_router.rb +16 -15
  89. data/app/models/raif/model_completion.rb +103 -1
  90. data/app/models/raif/model_tool.rb +55 -5
  91. data/app/models/raif/model_tool_invocation.rb +68 -6
  92. data/app/models/raif/model_tools/agent_final_answer.rb +2 -7
  93. data/app/models/raif/model_tools/provider_managed/code_execution.rb +4 -0
  94. data/app/models/raif/model_tools/provider_managed/image_generation.rb +4 -0
  95. data/app/models/raif/model_tools/provider_managed/web_search.rb +4 -0
  96. data/app/models/raif/prompt_studio_batch_run.rb +155 -0
  97. data/app/models/raif/prompt_studio_batch_run_item.rb +220 -0
  98. data/app/models/raif/streaming_responses/bedrock.rb +60 -1
  99. data/app/models/raif/streaming_responses/google.rb +71 -0
  100. data/app/models/raif/task.rb +85 -18
  101. data/app/models/raif/user_tool_invocation.rb +19 -0
  102. data/app/views/layouts/raif/admin.html.erb +43 -2
  103. data/app/views/raif/admin/agents/_agent.html.erb +9 -0
  104. data/app/views/raif/admin/agents/_conversation_message.html.erb +28 -6
  105. data/app/views/raif/admin/agents/index.html.erb +50 -0
  106. data/app/views/raif/admin/agents/show.html.erb +50 -1
  107. data/app/views/raif/admin/configs/show.html.erb +117 -0
  108. data/app/views/raif/admin/conversations/_conversation_entry.html.erb +29 -34
  109. data/app/views/raif/admin/conversations/show.html.erb +2 -0
  110. data/app/views/raif/admin/llms/index.html.erb +110 -0
  111. data/app/views/raif/admin/model_completions/_model_completion.html.erb +10 -5
  112. data/app/views/raif/admin/model_completions/index.html.erb +40 -1
  113. data/app/views/raif/admin/model_completions/show.html.erb +256 -84
  114. data/app/views/raif/admin/model_tool_invocations/index.html.erb +22 -1
  115. data/app/views/raif/admin/model_tool_invocations/show.html.erb +18 -0
  116. data/app/views/raif/admin/model_tools/_list.html.erb +16 -0
  117. data/app/views/raif/admin/model_tools/_model_tool.html.erb +36 -0
  118. data/app/views/raif/admin/prompt_studio/agents/index.html.erb +56 -0
  119. data/app/views/raif/admin/prompt_studio/agents/show.html.erb +57 -0
  120. data/app/views/raif/admin/prompt_studio/batch_runs/_batch_run_item.html.erb +54 -0
  121. data/app/views/raif/admin/prompt_studio/batch_runs/_judge_config_fields.html.erb +76 -0
  122. data/app/views/raif/admin/prompt_studio/batch_runs/_judge_detail_modal.html.erb +27 -0
  123. data/app/views/raif/admin/prompt_studio/batch_runs/_modal.html.erb +35 -0
  124. data/app/views/raif/admin/prompt_studio/batch_runs/_progress.html.erb +78 -0
  125. data/app/views/raif/admin/prompt_studio/batch_runs/show.html.erb +49 -0
  126. data/app/views/raif/admin/prompt_studio/conversations/index.html.erb +48 -0
  127. data/app/views/raif/admin/prompt_studio/conversations/show.html.erb +36 -0
  128. data/app/views/raif/admin/prompt_studio/shared/_nav_tabs.html.erb +17 -0
  129. data/app/views/raif/admin/prompt_studio/shared/_prompt_comparison.html.erb +87 -0
  130. data/app/views/raif/admin/prompt_studio/shared/_type_filter.html.erb +54 -0
  131. data/app/views/raif/admin/prompt_studio/tasks/_task_result.html.erb +145 -0
  132. data/app/views/raif/admin/prompt_studio/tasks/_task_row.html.erb +12 -0
  133. data/app/views/raif/admin/prompt_studio/tasks/_task_type_filter.html.erb +58 -0
  134. data/app/views/raif/admin/prompt_studio/tasks/_tasks_table.html.erb +22 -0
  135. data/app/views/raif/admin/prompt_studio/tasks/index.html.erb +35 -0
  136. data/app/views/raif/admin/prompt_studio/tasks/show.html.erb +19 -0
  137. data/app/views/raif/admin/stats/_stats_tile.html.erb +34 -0
  138. data/app/views/raif/admin/stats/index.html.erb +71 -88
  139. data/app/views/raif/admin/stats/model_tool_invocations/index.html.erb +43 -0
  140. data/app/views/raif/admin/stats/tasks/index.html.erb +20 -6
  141. data/app/views/raif/admin/tasks/_task.html.erb +1 -0
  142. data/app/views/raif/admin/tasks/index.html.erb +23 -6
  143. data/app/views/raif/admin/tasks/show.html.erb +56 -3
  144. data/app/views/raif/conversation_entries/_form.html.erb +3 -0
  145. data/app/views/raif/conversation_entries/_message.html.erb +10 -6
  146. data/app/views/raif/conversations/_conversation.html.erb +10 -0
  147. data/app/views/raif/conversations/_entry_processed.turbo_stream.erb +12 -0
  148. data/app/views/raif/conversations/index.html.erb +23 -0
  149. data/config/importmap.rb +8 -0
  150. data/config/locales/admin.en.yml +161 -1
  151. data/config/locales/en.yml +67 -4
  152. data/config/routes.rb +10 -0
  153. data/db/migrate/20250904194456_add_generating_entry_response_to_raif_conversations.rb +7 -0
  154. data/db/migrate/20250911125234_add_source_to_raif_tasks.rb +7 -0
  155. data/db/migrate/20251020005853_add_source_to_raif_agents.rb +7 -0
  156. data/db/migrate/20251020011346_rename_task_run_args_to_run_with.rb +7 -0
  157. data/db/migrate/20251020011405_add_run_with_to_raif_agents.rb +13 -0
  158. data/db/migrate/20251024160119_add_llm_messages_max_length_to_raif_conversations.rb +14 -0
  159. data/db/migrate/20251124185033_add_provider_tool_call_id_to_raif_model_tool_invocations.rb +7 -0
  160. data/db/migrate/20251128202941_add_tool_choice_to_raif_model_completions.rb +7 -0
  161. data/db/migrate/20260118144846_add_source_to_raif_conversations.rb +7 -0
  162. data/db/migrate/20260119000000_add_failure_tracking_to_raif_model_completions.rb +10 -0
  163. data/db/migrate/20260119000001_add_completed_at_to_raif_model_completions.rb +8 -0
  164. data/db/migrate/20260119000002_add_started_at_to_raif_model_completions.rb +8 -0
  165. data/db/migrate/20260307000000_add_prompt_studio_run_to_raif_tasks.rb +7 -0
  166. data/db/migrate/20260308000000_create_raif_prompt_studio_batch_runs.rb +27 -0
  167. data/db/migrate/20260308000001_create_raif_prompt_studio_batch_run_items.rb +24 -0
  168. data/db/migrate/20260407000000_add_cache_token_columns_to_raif_model_completions.rb +8 -0
  169. data/lib/generators/raif/agent/agent_generator.rb +18 -0
  170. data/lib/generators/raif/agent/templates/agent.rb.tt +7 -5
  171. data/lib/generators/raif/agent/templates/application_agent.rb.tt +1 -1
  172. data/lib/generators/raif/agent/templates/system_prompt.erb.tt +3 -0
  173. data/lib/generators/raif/conversation/conversation_generator.rb +19 -1
  174. data/lib/generators/raif/conversation/templates/conversation.rb.tt +6 -0
  175. data/lib/generators/raif/conversation/templates/system_prompt.erb.tt +4 -0
  176. data/lib/generators/raif/install/templates/initializer.rb +117 -8
  177. data/lib/generators/raif/task/task_generator.rb +18 -0
  178. data/lib/generators/raif/task/templates/prompt.erb.tt +4 -0
  179. data/lib/generators/raif/task/templates/task.rb.tt +10 -9
  180. data/lib/raif/configuration.rb +47 -2
  181. data/lib/raif/embedding_model_registry.rb +8 -0
  182. data/lib/raif/engine.rb +24 -1
  183. data/lib/raif/errors/blank_response_error.rb +8 -0
  184. data/lib/raif/errors/instance_dependent_schema_error.rb +8 -0
  185. data/lib/raif/errors/prompt_template_error.rb +15 -0
  186. data/lib/raif/errors/streaming_error.rb +6 -3
  187. data/lib/raif/errors.rb +3 -0
  188. data/lib/raif/evals/run.rb +1 -0
  189. data/lib/raif/evals.rb +0 -6
  190. data/lib/raif/json_schema_builder.rb +14 -0
  191. data/lib/raif/llm_registry.rb +433 -42
  192. data/lib/raif/messages.rb +180 -0
  193. data/lib/raif/prompt_studio_comparison_builder.rb +138 -0
  194. data/lib/raif/token_estimator.rb +28 -0
  195. data/lib/raif/version.rb +1 -1
  196. data/lib/raif.rb +11 -0
  197. data/lib/tasks/annotate_rb.rake +10 -0
  198. data/spec/support/rspec_helpers.rb +15 -9
  199. data/spec/support/test_task.rb +9 -0
  200. data/spec/support/test_template_task.rb +41 -0
  201. metadata +108 -15
  202. data/app/models/raif/agents/re_act_agent.rb +0 -127
  203. data/app/models/raif/agents/re_act_step.rb +0 -32
  204. data/app/models/raif/concerns/task_run_args.rb +0 -62
  205. data/lib/raif/evals/llm_judge.rb +0 -32
  206. /data/{lib → app/models}/raif/evals/scoring_rubric.rb +0 -0
@@ -8,97 +8,181 @@
8
8
  <h5 class="mb-0"><%= t("raif.admin.common.details") %></h5>
9
9
  </div>
10
10
  <div class="card-body">
11
- <div class="row mb-3">
12
- <div class="col-md-3"><strong><%= t("raif.admin.common.id") %>:</strong></div>
13
- <div class="col-md-9"><%= @model_completion.id %></div>
14
- </div>
15
- <div class="row mb-3">
16
- <div class="col-md-3"><strong><%= t("raif.admin.common.source") %>:</strong></div>
17
- <div class="col-md-9"><%= @model_completion.source_type %> #<%= @model_completion.source_id %></div>
18
- </div>
19
- <div class="row mb-3">
20
- <div class="col-md-3"><strong><%= t("raif.admin.common.model") %>:</strong></div>
21
- <div class="col-md-9"><%= @model_completion.llm_model_key %></div>
22
- </div>
23
- <div class="row mb-3">
24
- <div class="col-md-3"><strong><%= t("raif.admin.common.response_format") %>:</strong></div>
25
- <div class="col-md-9"><%= @model_completion.response_format %></div>
26
- </div>
27
- <div class="row mb-3">
28
- <div class="col-md-3"><strong><%= t("raif.admin.common.response_format_parameter") %>:</strong></div>
29
- <div class="col-md-9"><%= @model_completion.response_format_parameter %></div>
30
- </div>
31
- <div class="row mb-3">
32
- <div class="col-md-3"><strong><%= t("raif.admin.common.created_at") %>:</strong></div>
33
- <div class="col-md-9"><%= @model_completion.created_at.rfc822 %></div>
34
- </div>
35
- <div class="row mb-3">
36
- <div class="col-md-3"><strong><%= t("raif.admin.common.prompt_tokens") %>:</strong></div>
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 %>
11
+ <div class="row">
12
+ <div class="col-md-6">
13
+ <div class="row mb-2">
14
+ <div class="col-5"><strong><%= t("raif.admin.common.id") %>:</strong></div>
15
+ <div class="col-7"><%= @model_completion.id %></div>
16
+ </div>
17
+ <div class="row mb-2">
18
+ <div class="col-5"><strong><%= t("raif.admin.common.source") %>:</strong></div>
19
+ <div class="col-7"><%= @model_completion.source_type %> #<%= @model_completion.source_id %></div>
20
+ </div>
21
+ <div class="row mb-2">
22
+ <div class="col-5"><strong><%= t("raif.admin.common.model") %>:</strong></div>
23
+ <div class="col-7"><%= @model_completion.llm_model_key %></div>
24
+ </div>
25
+ <div class="row mb-2">
26
+ <div class="col-5"><strong><%= t("raif.admin.common.response_format") %>:</strong></div>
27
+ <div class="col-7"><%= @model_completion.response_format %><%= " (#{@model_completion.response_format_parameter})" if @model_completion.response_format_parameter.present? %></div>
28
+ </div>
29
+ <div class="row mb-2">
30
+ <div class="col-5"><strong><%= t("raif.admin.common.status") %>:</strong></div>
31
+ <div class="col-7">
32
+ <% if @model_completion.failed? %>
33
+ <span class="badge bg-danger"><%= t("raif.admin.common.failed") %></span>
34
+ <% elsif @model_completion.completed? %>
35
+ <span class="badge bg-success"><%= t("raif.admin.common.completed") %></span>
36
+ <% elsif @model_completion.started? %>
37
+ <span class="badge bg-warning text-dark"><%= t("raif.admin.common.in_progress") %></span>
38
+ <% else %>
39
+ <span class="badge bg-secondary"><%= t("raif.admin.common.pending") %></span>
40
+ <% end %>
41
+ </div>
42
+ </div>
43
+ <div class="row mb-2">
44
+ <div class="col-5"><strong><%= t("raif.admin.common.retry_count") %>:</strong></div>
45
+ <div class="col-7"><%= @model_completion.retry_count %></div>
46
+ </div>
46
47
  </div>
47
- </div>
48
- <div class="row mb-3">
49
- <div class="col-md-3"><strong><%= t("raif.admin.common.completion_tokens") %>:</strong></div>
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 %>
48
+ <div class="col-md-6">
49
+ <div class="row mb-2">
50
+ <div class="col-5"><strong><%= t("raif.admin.common.created_at") %>:</strong></div>
51
+ <div class="col-7"><small><%= @model_completion.created_at.rfc822 %></small></div>
52
+ </div>
53
+ <div class="row mb-2">
54
+ <div class="col-5"><strong><%= t("raif.admin.common.started_at") %>:</strong></div>
55
+ <div class="col-7"><small><%= @model_completion.started_at&.rfc822 || "-" %></small></div>
56
+ </div>
57
+ <div class="row mb-2">
58
+ <div class="col-5"><strong><%= t("raif.admin.common.completed_at") %>:</strong></div>
59
+ <div class="col-7"><small><%= @model_completion.completed_at&.rfc822 || "-" %></small></div>
60
+ </div>
61
+ <div class="row mb-2">
62
+ <div class="col-5"><strong><%= t("raif.admin.common.duration") %>:</strong></div>
63
+ <div class="col-7"><small><%= @model_completion.runtime_duration %></small></div>
64
+ </div>
65
+ <div class="row mb-2">
66
+ <div class="col-5"><strong><%= t("raif.admin.common.prompt_tokens") %>:</strong></div>
67
+ <div class="col-7">
68
+ <% if @model_completion.prompt_tokens %>
69
+ <%= number_with_delimiter(@model_completion.prompt_tokens) %>
70
+ <% if @model_completion.prompt_token_cost %>
71
+ <small>(<%= t("raif.admin.common.est_cost") %>: <%= number_to_currency(@model_completion.prompt_token_cost, precision: 6) %>)</small>
72
+ <% end %>
73
+ <% else %>
74
+ -
75
+ <% end %>
76
+ </div>
77
+ </div>
78
+ <div class="row mb-2">
79
+ <div class="col-5"><strong><%= t("raif.admin.common.completion_tokens") %>:</strong></div>
80
+ <div class="col-7">
81
+ <% if @model_completion.completion_tokens %>
82
+ <%= number_with_delimiter(@model_completion.completion_tokens) %>
83
+ <% if @model_completion.output_token_cost %>
84
+ <small>(<%= t("raif.admin.common.est_cost") %>: <%= number_to_currency(@model_completion.output_token_cost, precision: 6) %>)</small>
85
+ <% end %>
86
+ <% else %>
87
+ -
88
+ <% end %>
89
+ </div>
90
+ </div>
91
+ <div class="row mb-2">
92
+ <div class="col-5"><strong><%= t("raif.admin.common.total_tokens") %>:</strong></div>
93
+ <div class="col-7">
94
+ <% if @model_completion.total_tokens %>
95
+ <%= number_with_delimiter(@model_completion.total_tokens) %>
96
+ <% if @model_completion.total_cost %>
97
+ <small>(<%= t("raif.admin.common.est_cost") %>: <%= "$" %><%= number_with_precision(@model_completion.total_cost, precision: 6) %>)</small>
98
+ <% end %>
99
+ <% else %>
100
+ -
101
+ <% end %>
102
+ </div>
103
+ </div>
104
+ <hr class="my-2">
105
+ <div class="row mb-2">
106
+ <div class="col-5"><strong><%= t("raif.admin.common.cache_read_input_tokens") %>:</strong></div>
107
+ <div class="col-7"><%= @model_completion.cache_read_input_tokens ? number_with_delimiter(@model_completion.cache_read_input_tokens) : "-" %></div>
108
+ </div>
109
+ <div class="row mb-2">
110
+ <div class="col-5"><strong><%= t("raif.admin.common.cache_creation_input_tokens") %>:</strong></div>
111
+ <div class="col-7"><%= @model_completion.cache_creation_input_tokens ? number_with_delimiter(@model_completion.cache_creation_input_tokens) : "-" %></div>
112
+ </div>
59
113
  </div>
60
114
  </div>
61
- <div class="row mb-3">
62
- <div class="col-md-3"><strong><%= t("raif.admin.common.total_tokens") %>:</strong></div>
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 %>
115
+ <% if @model_completion.failed? %>
116
+ <hr>
117
+ <div class="row mb-2">
118
+ <div class="col-md-2"><strong><%= t("raif.admin.common.failed_at") %>:</strong></div>
119
+ <div class="col-md-10"><small><%= @model_completion.failed_at&.rfc822 || "-" %></small></div>
72
120
  </div>
73
- </div>
121
+ <div class="row mb-2">
122
+ <div class="col-md-2"><strong><%= t("raif.admin.common.failure_error") %>:</strong></div>
123
+ <div class="col-md-10"><code><%= @model_completion.failure_error %></code></div>
124
+ </div>
125
+ <div class="row mb-2">
126
+ <div class="col-md-2"><strong><%= t("raif.admin.common.failure_reason") %>:</strong></div>
127
+ <div class="col-md-10"><%= @model_completion.failure_reason %></div>
128
+ </div>
129
+ <% end %>
74
130
  </div>
75
131
  </div>
76
132
 
77
133
  <% if @model_completion.messages.present? %>
78
- <div class="card mb-4">
79
- <div class="card-header">
80
- <h5 class="mb-0"><%= t("raif.admin.common.messages") %></h5>
81
- </div>
82
- <div class="card-body">
83
- <% @model_completion.messages.each do |message| %>
84
- <div class="mb-3">
85
- <strong><%= message["role"].titleize %>:</strong>
86
- <pre class="mt-2"><%= message["content"] %></pre>
87
- </div>
88
- <% end %>
134
+ <div class="card mb-4">
135
+ <div class="card-header">
136
+ <h5 class="mb-0"><%= t("raif.admin.common.messages") %></h5>
137
+ </div>
138
+ <div class="card-body">
139
+ <% @model_completion.messages.each do |message| %>
140
+ <div class="mb-3">
141
+ <% if message["type"] == "function_call" %>
142
+ <strong><%= t("raif.admin.common.tool_call") %>:</strong>
143
+ <div class="border rounded p-2 mt-2 bg-light">
144
+ <div><strong><%= t("raif.admin.common.tool_name") %>:</strong> <%= message["name"] %></div>
145
+ <div><strong><%= t("raif.admin.common.arguments") %>:</strong></div>
146
+ <pre class="mb-0 mt-1"><%= pretty_json(message["arguments"]) %></pre>
147
+ </div>
148
+ <% elsif message["type"] == "function_call_output" %>
149
+ <strong><%= t("raif.admin.common.tool_result") %>:</strong>
150
+ <pre class="mt-2"><%= pretty_json(message["output"]) %></pre>
151
+ <% else %>
152
+ <% if message["role"].present? %>
153
+ <strong><%= message["role"].titleize %>:</strong>
154
+ <% end %>
155
+ <% if message["content"].present? %>
156
+ <pre class="mt-2"><%= message["content"] %></pre>
157
+ <% end %>
158
+
159
+ <% if message["tool_calls"].present? %>
160
+ <div class="mt-2">
161
+ <% message["tool_calls"].each do |tool_call| %>
162
+ <div class="border rounded p-2 mb-2 bg-light">
163
+ <div><strong><%= t("raif.admin.common.tool_name") %>:</strong> <%= tool_call.dig("function", "name") %></div>
164
+ <div><strong><%= t("raif.admin.common.arguments") %>:</strong></div>
165
+ <pre class="mb-0 mt-1"><%= pretty_json(tool_call.dig("function", "arguments")) %></pre>
166
+ </div>
167
+ <% end %>
168
+ </div>
169
+ <% end %>
170
+ <% end %>
171
+ </div>
172
+ <% end %>
173
+ </div>
89
174
  </div>
90
- </div>
91
175
  <% end %>
92
176
 
93
177
  <% if @model_completion.system_prompt.present? %>
94
- <div class="card mb-4">
95
- <div class="card-header">
96
- <h5 class="mb-0"><%= t("raif.admin.common.system_prompt") %></h5>
97
- </div>
98
- <div class="card-body">
99
- <pre class="pre-wrap"><%= @model_completion.system_prompt %></pre>
178
+ <div class="card mb-4">
179
+ <div class="card-header">
180
+ <h5 class="mb-0"><%= t("raif.admin.common.system_prompt") %></h5>
181
+ </div>
182
+ <div class="card-body">
183
+ <pre class="pre-wrap"><%= @model_completion.system_prompt %></pre>
184
+ </div>
100
185
  </div>
101
- </div>
102
186
  <% end %>
103
187
 
104
188
  <div class="card mb-4">
@@ -113,7 +197,7 @@
113
197
  <h5 class="mb-0 mt-4"><%= t("raif.admin.common.prettified") %></h5>
114
198
  <% begin %>
115
199
  <pre class="pre-wrap"><%= JSON.pretty_generate(@model_completion.parsed_response) %></pre>
116
- <% rescue StandardError %>
200
+ <% rescue StandardError %>
117
201
  <%= t("raif.admin.common.invalid_json") %>
118
202
  <% end %>
119
203
  <% elsif @model_completion.response_format_html? %>
@@ -143,22 +227,95 @@
143
227
  </div>
144
228
  </div>
145
229
 
230
+ <% if @model_completion.provider_managed_tool_calls.present? %>
231
+ <div class="card mb-4">
232
+ <div class="card-header">
233
+ <h5 class="mb-0"><%= t("raif.admin.common.provider_managed_tool_calls") %></h5>
234
+ </div>
235
+ <div class="card-body">
236
+ <% @model_completion.provider_managed_tool_calls.each do |tool_call| %>
237
+ <div class="border rounded p-3 mb-3 bg-light">
238
+ <div class="d-flex justify-content-between align-items-start gap-3">
239
+ <div>
240
+ <div><strong><%= t("raif.admin.common.tool_name") %>:</strong> <%= tool_call["tool_name"].to_s.titleize %></div>
241
+ <% if tool_call["provider_tool_call_id"].present? %>
242
+ <div><strong><%= t("raif.admin.common.provider_tool_call_id") %>:</strong> <code><%= tool_call["provider_tool_call_id"] %></code></div>
243
+ <% end %>
244
+ <% if tool_call["inferred"] %>
245
+ <div><small class="text-muted"><%= t("raif.admin.common.inferred_from_citations") %></small></div>
246
+ <% end %>
247
+ </div>
248
+ <% if tool_call["status"].present? %>
249
+ <span class="badge bg-info text-dark"><%= tool_call["status"].to_s.titleize %></span>
250
+ <% end %>
251
+ </div>
252
+
253
+ <% if tool_call["arguments"].present? %>
254
+ <div class="mt-3"><strong><%= t("raif.admin.common.arguments") %>:</strong></div>
255
+ <pre class="mb-0 mt-1"><%= begin
256
+ JSON.pretty_generate(tool_call["arguments"])
257
+ rescue StandardError
258
+ tool_call["arguments"]
259
+ end %></pre>
260
+ <% end %>
261
+
262
+ <% if tool_call["sources"].present? %>
263
+ <div class="mt-3">
264
+ <strong><%= t("raif.admin.common.sources") %>:</strong>
265
+ <div class="mt-2">
266
+ <% tool_call["sources"].each do |source| %>
267
+ <div class="border rounded p-2 mb-2 bg-white">
268
+ <% if source["url"].present? %>
269
+ <div>
270
+ <a href="<%= source["url"] %>" target="_blank" rel="noopener" class="text-decoration-none">
271
+ <%= source["title"].presence || source["url"] %>
272
+ </a>
273
+ </div>
274
+ <small class="text-muted d-block"><%= source["url"] %></small>
275
+ <% else %>
276
+ <div><%= source["title"] %></div>
277
+ <% end %>
278
+ <% if source["page_age"].present? %>
279
+ <small class="text-muted d-block"><%= source["page_age"] %></small>
280
+ <% end %>
281
+ </div>
282
+ <% end %>
283
+ </div>
284
+ </div>
285
+ <% elsif tool_call["raw_result"].present? %>
286
+ <div class="mt-3"><strong><%= t("raif.admin.common.result") %>:</strong></div>
287
+ <pre class="mb-0 mt-1"><%= begin
288
+ JSON.pretty_generate(tool_call["raw_result"])
289
+ rescue StandardError
290
+ tool_call["raw_result"]
291
+ end %></pre>
292
+ <% end %>
293
+ </div>
294
+ <% end %>
295
+ </div>
296
+ </div>
297
+ <% end %>
298
+
146
299
  <div class="card mb-4">
147
300
  <div class="card-header">
148
301
  <h5 class="mb-0"><%= t("raif.admin.common.citations") %></h5>
149
302
  </div>
150
303
  <div class="card-body">
151
- <% if @model_completion.citations.present? %>
152
- <% @model_completion.citations.each_with_index do |citation, index| %>
304
+ <% if @model_completion.sanitized_citations.present? %>
305
+ <% @model_completion.sanitized_citations.each_with_index do |citation, index| %>
153
306
  <div class="mb-3 p-3 border rounded">
154
307
  <div class="d-flex align-items-start">
155
308
  <span class="badge bg-primary me-3"><%= index + 1 %></span>
156
309
  <div class="flex-grow-1">
157
310
  <h6 class="mb-1">
158
- <a href="<%= citation["url"] %>" target="_blank" rel="noopener" class="text-decoration-none">
311
+ <% if citation["url"].present? %>
312
+ <a href="<%= citation["url"] %>" target="_blank" rel="noopener" class="text-decoration-none">
313
+ <%= citation["title"] %>
314
+ <i class="bi bi-box-arrow-up-right ms-1" style="font-size: 0.8em;"></i>
315
+ </a>
316
+ <% else %>
159
317
  <%= citation["title"] %>
160
- <i class="bi bi-box-arrow-up-right ms-1" style="font-size: 0.8em;"></i>
161
- </a>
318
+ <% end %>
162
319
  </h6>
163
320
  <small class="text-muted"><%= citation["url"] %></small>
164
321
  </div>
@@ -170,3 +327,18 @@
170
327
  <% end %>
171
328
  </div>
172
329
  </div>
330
+
331
+ <% if @model_completion.response_array.present? %>
332
+ <div class="card mb-4">
333
+ <div class="card-header">
334
+ <h5 class="mb-0"><%= t("raif.admin.common.response_array") %></h5>
335
+ </div>
336
+ <div class="card-body">
337
+ <pre class="pre-wrap"><%= begin
338
+ JSON.pretty_generate(@model_completion.response_array)
339
+ rescue StandardError
340
+ @model_completion.response_array
341
+ end %></pre>
342
+ </div>
343
+ </div>
344
+ <% end %>
@@ -1,7 +1,28 @@
1
- <h1 class="my-4"><%= t("raif.admin.common.model_tool_invocations") %></h1>
1
+ <div class="d-flex justify-content-between align-items-center my-4">
2
+ <h1 class="mb-0"><%= t("raif.admin.common.model_tool_invocations") %></h1>
3
+ <%= link_to raif.admin_stats_model_tool_invocations_path, class: "btn btn-outline-primary" do %>
4
+ <%= t("raif.admin.common.stats") %> &raquo;
5
+ <% end %>
6
+ </div>
2
7
 
3
8
  <div class="row">
4
9
  <div class="col-12">
10
+ <%= form_tag raif.admin_model_tool_invocations_path, method: :get, class: "mb-4" do %>
11
+ <div class="row align-items-end">
12
+ <div class="col-md-4">
13
+ <div class="form-group">
14
+ <label for="tool_types"><%= t("raif.admin.common.tool_type") %></label>
15
+ <%= select_tag :tool_types,
16
+ options_for_select([[t("raif.admin.common.all"), "all"]] + @tool_types.map{|type| [type, type] }, @selected_type),
17
+ { class: "form-select", data: { controller: "raif--tom-select" } } %>
18
+ </div>
19
+ </div>
20
+ <div class="col-md-2">
21
+ <%= submit_tag t("raif.admin.common.filter"), class: "btn btn-primary" %>
22
+ </div>
23
+ </div>
24
+ <% end %>
25
+
5
26
  <% if @model_tool_invocations.any? %>
6
27
  <div class="table-responsive">
7
28
  <table class="table table-striped table-hover">
@@ -64,3 +64,21 @@
64
64
  </div>
65
65
  </div>
66
66
  <% end %>
67
+
68
+ <% if @model_tool_invocation.admin_observation_available? %>
69
+ <div class="card mb-4">
70
+ <div class="card-header">
71
+ <h5 class="mb-0"><%= t(".observation_sent_to_model") %></h5>
72
+ </div>
73
+ <% if @model_tool_invocation.admin_observation_error.present? %>
74
+ <div class="card-body text-muted">
75
+ <%= t(".observation_unavailable", error: @model_tool_invocation.admin_observation_error) %>
76
+ </div>
77
+ <% else %>
78
+ <div class="card-body">
79
+ <p class="text-muted small"><%= t(".observation_disclaimer") %></p>
80
+ <pre class="pre-wrap"><%= @model_tool_invocation.admin_observation %></pre>
81
+ </div>
82
+ <% end %>
83
+ </div>
84
+ <% end %>
@@ -0,0 +1,16 @@
1
+ <div class="card mb-4">
2
+ <div class="card-header">
3
+ <h5 class="mb-0"><%= t("raif.admin.common.available_tools") %></h5>
4
+ </div>
5
+ <div class="card-body">
6
+ <% if model_tools.blank? %>
7
+ <%= t("raif.admin.common.none") %>
8
+ <% else %>
9
+ <div class="accordion" id="modelToolsAccordion">
10
+ <% model_tools.each_with_index do |(tool_name, tool_class), index| %>
11
+ <%= render partial: "raif/admin/model_tools/model_tool", locals: { tool_name: tool_name, tool_class: tool_class, index: index } %>
12
+ <% end %>
13
+ </div>
14
+ <% end %>
15
+ </div>
16
+ </div>
@@ -0,0 +1,36 @@
1
+ <div class="accordion-item">
2
+ <h2 class="accordion-header" id="heading-<%= index %>">
3
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-<%= index %>" aria-expanded="false" aria-controls="collapse-<%= index %>">
4
+ <strong><%= tool_name %></strong>
5
+ </button>
6
+ </h2>
7
+ <div id="collapse-<%= index %>" class="accordion-collapse collapse" aria-labelledby="heading-<%= index %>" data-bs-parent="#modelToolsAccordion">
8
+ <div class="accordion-body">
9
+ <div class="row mb-3">
10
+ <div class="col-md-2"><strong><%= t("raif.admin.common.tool_name") %>:</strong></div>
11
+ <div class="col-md-10"><code><%= tool_class.tool_name %></code></div>
12
+ </div>
13
+ <div class="row mb-3">
14
+ <div class="col-md-2"><strong><%= t("raif.admin.common.description") %>:</strong></div>
15
+ <div class="col-md-10"><%= tool_class.tool_description %></div>
16
+ </div>
17
+ <% if tool_class.respond_to?(:tool_arguments_schema) %>
18
+ <% if tool_class.schema_defined?(:tool_arguments) %>
19
+ <div class="row mb-3">
20
+ <div class="col-md-2"><strong><%= t("raif.admin.common.arguments_schema") %>:</strong></div>
21
+ <div class="col-md-10">
22
+ <pre class="pre-wrap"><%= JSON.pretty_generate(tool_class.tool_arguments_schema) %></pre>
23
+ </div>
24
+ </div>
25
+ <% else %>
26
+ <div class="row mb-3">
27
+ <div class="col-md-2"><strong><%= t("raif.admin.common.arguments_schema") %>:</strong></div>
28
+ <div class="col-md-10">
29
+ <em><%= t("raif.admin.common.none") %></em>
30
+ </div>
31
+ </div>
32
+ <% end %>
33
+ <% end %>
34
+ </div>
35
+ </div>
36
+ </div>
@@ -0,0 +1,56 @@
1
+ <div class="d-flex justify-content-between align-items-center my-4">
2
+ <h1 class="mb-0"><%= t("raif.admin.prompt_studio.common.prompt_studio") %></h1>
3
+ </div>
4
+
5
+ <%= render "raif/admin/prompt_studio/shared/nav_tabs", active_tab: :agents %>
6
+
7
+ <%= render "raif/admin/prompt_studio/shared/type_filter",
8
+ filter_path: raif.admin_prompt_studio_agents_path,
9
+ param_name: :agent_type,
10
+ types: @agent_types,
11
+ selected_type: @selected_type,
12
+ llm_model_keys: @llm_model_keys %>
13
+
14
+ <% if @selected_type.present? && @agents.present? %>
15
+ <div class="table-responsive">
16
+ <table class="table table-striped">
17
+ <thead>
18
+ <tr>
19
+ <th><%= t("raif.admin.common.id") %></th>
20
+ <th><%= t("raif.admin.common.type") %></th>
21
+ <th><%= t("raif.admin.common.created_at") %></th>
22
+ <th><%= t("raif.admin.common.model") %></th>
23
+ <th><%= t("raif.admin.common.status") %></th>
24
+ <th></th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <% @agents.each do |agent| %>
29
+ <tr>
30
+ <td><%= agent.id %></td>
31
+ <td><%= agent.type %></td>
32
+ <td><%= agent.created_at.rfc822 %></td>
33
+ <td><%= agent.llm_model_key %></td>
34
+ <td>
35
+ <% if agent.completed_at? %>
36
+ <span class="badge bg-success"><%= t("raif.admin.common.completed") %></span>
37
+ <% elsif agent.failed_at? %>
38
+ <span class="badge bg-danger"><%= t("raif.admin.common.failed") %></span>
39
+ <% elsif agent.started_at? %>
40
+ <span class="badge bg-warning text-dark"><%= t("raif.admin.common.in_progress") %></span>
41
+ <% end %>
42
+ </td>
43
+ <td>
44
+ <%= link_to "View", raif.admin_prompt_studio_agent_path(agent), class: "btn btn-sm btn-outline-primary" %>
45
+ </td>
46
+ </tr>
47
+ <% end %>
48
+ </tbody>
49
+ </table>
50
+ </div>
51
+ <div class="mt-3"><%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %></div>
52
+ <% elsif @selected_type.present? %>
53
+ <div class="alert alert-info">
54
+ <%= t("raif.admin.prompt_studio.common.no_instances") %>
55
+ </div>
56
+ <% end %>
@@ -0,0 +1,57 @@
1
+ <div class="d-flex justify-content-between align-items-center my-4">
2
+ <h1 class="mb-0"><%= t("raif.admin.prompt_studio.agents.show.page_title", id: @agent.id) %></h1>
3
+ <%= link_to t("raif.admin.prompt_studio.common.back"),
4
+ raif.admin_prompt_studio_agents_path(agent_type: @agent.type),
5
+ class: "btn btn-outline-secondary" %>
6
+ </div>
7
+
8
+ <div class="card mb-4">
9
+ <div class="card-header">
10
+ <h5 class="mb-0"><%= t("raif.admin.prompt_studio.agents.show.agent_details") %></h5>
11
+ </div>
12
+ <div class="card-body">
13
+ <div class="row mb-3">
14
+ <div class="col-md-2"><strong><%= t("raif.admin.common.id") %>:</strong></div>
15
+ <div class="col-md-10"><%= @agent.id %></div>
16
+ </div>
17
+ <div class="row mb-3">
18
+ <div class="col-md-2"><strong><%= t("raif.admin.common.type") %>:</strong></div>
19
+ <div class="col-md-10"><%= @agent.type %></div>
20
+ </div>
21
+ <div class="row mb-3">
22
+ <div class="col-md-2"><strong><%= t("raif.admin.common.model") %>:</strong></div>
23
+ <div class="col-md-10"><%= @agent.llm_model_key %></div>
24
+ </div>
25
+ <div class="row mb-3">
26
+ <div class="col-md-2"><strong><%= t("raif.admin.common.created_at") %>:</strong></div>
27
+ <div class="col-md-10"><%= @agent.created_at.rfc822 %></div>
28
+ </div>
29
+ <% if @agent.task.present? %>
30
+ <div class="row mb-3">
31
+ <div class="col-md-2"><strong><%= t("raif.admin.common.task") %>:</strong></div>
32
+ <div class="col-md-10"><%= @agent.task %></div>
33
+ </div>
34
+ <% end %>
35
+ <% if @agent.run_with.present? %>
36
+ <div class="row mb-3">
37
+ <div class="col-md-2"><strong><%= t("raif.admin.common.run_with") %>:</strong></div>
38
+ <div class="col-md-10">
39
+ <pre class="pre-wrap mb-0"><%= JSON.pretty_generate(@agent.run_with) %></pre>
40
+ </div>
41
+ </div>
42
+ <% end %>
43
+ </div>
44
+ </div>
45
+
46
+ <%= render "raif/admin/prompt_studio/shared/prompt_comparison", comparison: @comparison %>
47
+
48
+ <% if @agent.final_answer.present? %>
49
+ <div class="card mb-4">
50
+ <div class="card-header">
51
+ <h5 class="mb-0"><%= t("raif.admin.common.final_answer") %></h5>
52
+ </div>
53
+ <div class="card-body">
54
+ <pre class="pre-wrap"><%= @agent.final_answer %></pre>
55
+ </div>
56
+ </div>
57
+ <% end %>