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
@@ -12,6 +12,7 @@ module Raif
12
12
  :aws_bedrock_region,
13
13
  :bedrock_embedding_models_enabled,
14
14
  :conversation_entries_controller,
15
+ :conversation_llm_messages_max_length_default,
15
16
  :conversation_system_prompt_intro,
16
17
  :conversation_types,
17
18
  :conversations_controller,
@@ -20,19 +21,30 @@ module Raif
20
21
  :default_llm_model_key,
21
22
  :evals_default_llm_judge_model_key,
22
23
  :evals_verbose_output,
24
+ :google_api_key,
25
+ :google_embedding_models_enabled,
26
+ :google_models_enabled,
23
27
  :llm_api_requests_enabled,
24
28
  :llm_request_max_retries,
25
29
  :llm_request_retriable_exceptions,
26
30
  :model_superclass,
27
31
  :open_ai_api_key,
32
+ :open_ai_api_version,
33
+ :open_ai_auth_header_style,
34
+ :open_ai_base_url,
35
+ :open_ai_embedding_base_url,
28
36
  :open_ai_embedding_models_enabled,
29
37
  :open_ai_models_enabled,
30
38
  :open_router_api_key,
31
39
  :open_router_models_enabled,
32
40
  :open_router_app_name,
33
41
  :open_router_site_url,
42
+ :request_open_timeout,
43
+ :request_read_timeout,
44
+ :request_write_timeout,
34
45
  :streaming_update_chunk_size_threshold,
35
46
  :task_creator_optional,
47
+ :prompt_studio_runs_enabled,
36
48
  :task_system_prompt_intro,
37
49
  :user_tool_types
38
50
 
@@ -43,7 +55,7 @@ module Raif
43
55
  alias_method :aws_bedrock_titan_embedding_models_enabled=, :bedrock_embedding_models_enabled=
44
56
 
45
57
  def initialize
46
- @agent_types = Set.new(["Raif::Agents::ReActAgent", "Raif::Agents::NativeToolCallingAgent"])
58
+ @agent_types = Set.new(["Raif::Agents::NativeToolCallingAgent"])
47
59
  @anthropic_api_key = default_disable_llm_api_requests? ? "placeholder-anthropic-api-key" : ENV["ANTHROPIC_API_KEY"]
48
60
  @bedrock_models_enabled = false
49
61
  @anthropic_models_enabled = ENV["ANTHROPIC_API_KEY"].present?
@@ -54,6 +66,7 @@ module Raif
54
66
  @bedrock_embedding_models_enabled = false
55
67
  @task_system_prompt_intro = "You are a helpful assistant."
56
68
  @conversation_entries_controller = "Raif::ConversationEntriesController"
69
+ @conversation_llm_messages_max_length_default = 50
57
70
  @conversation_system_prompt_intro = "You are a helpful assistant who is collaborating with a teammate."
58
71
  @conversation_types = Set.new(["Raif::Conversation"])
59
72
  @conversations_controller = "Raif::ConversationsController"
@@ -62,22 +75,37 @@ module Raif
62
75
  @default_llm_model_key = default_disable_llm_api_requests? ? :raif_test_llm : (ENV["RAIF_DEFAULT_LLM_MODEL_KEY"].presence || "open_ai_gpt_4o")
63
76
  @evals_default_llm_judge_model_key = ENV["RAIF_EVALS_DEFAULT_LLM_JUDGE_MODEL_KEY"].presence
64
77
  @evals_verbose_output = false
78
+ google_api_key = ENV["GOOGLE_AI_API_KEY"].presence || ENV["GOOGLE_API_KEY"]
79
+ @google_api_key = default_disable_llm_api_requests? ? "placeholder-google-api-key" : google_api_key
80
+ @google_embedding_models_enabled = false
81
+ @google_models_enabled = @google_api_key.present?
65
82
  @llm_api_requests_enabled = !default_disable_llm_api_requests?
66
83
  @llm_request_max_retries = 2
67
84
  @llm_request_retriable_exceptions = [
68
85
  Faraday::ConnectionFailed,
69
86
  Faraday::TimeoutError,
70
87
  Faraday::ServerError,
88
+ Net::ReadTimeout,
89
+ Net::OpenTimeout,
90
+ Raif::Errors::BlankResponseError,
71
91
  ]
72
92
  @model_superclass = "ApplicationRecord"
73
93
  @open_ai_api_key = default_disable_llm_api_requests? ? "placeholder-open-ai-api-key" : ENV["OPENAI_API_KEY"]
94
+ @open_ai_api_version = nil
95
+ @open_ai_auth_header_style = :bearer
96
+ @open_ai_base_url = "https://api.openai.com/v1"
97
+ @open_ai_embedding_base_url = "https://api.openai.com/v1"
74
98
  @open_ai_embedding_models_enabled = ENV["OPENAI_API_KEY"].present?
75
99
  @open_ai_models_enabled = ENV["OPENAI_API_KEY"].present?
76
100
  open_router_api_key = ENV["OPEN_ROUTER_API_KEY"].presence || ENV["OPENROUTER_API_KEY"]
77
101
  @open_router_api_key = default_disable_llm_api_requests? ? "placeholder-open-router-api-key" : open_router_api_key
78
102
  @open_router_models_enabled = @open_router_api_key.present?
103
+ @prompt_studio_runs_enabled = Rails.env.development?
79
104
  @open_router_app_name = nil
80
105
  @open_router_site_url = nil
106
+ @request_open_timeout = nil
107
+ @request_read_timeout = nil
108
+ @request_write_timeout = nil
81
109
  @streaming_update_chunk_size_threshold = 25
82
110
  @task_creator_optional = true
83
111
  @user_tool_types = []
@@ -103,7 +131,9 @@ module Raif
103
131
  "Raif.config.default_llm_model_key was set to #{default_llm_model_key}, but must be one of: #{Raif.available_llm_keys.join(", ")}"
104
132
  end
105
133
 
106
- if Raif.embedding_model_registry.present? && !Raif.available_embedding_model_keys.include?(default_embedding_model_key.to_sym)
134
+ if default_embedding_model_key.present? &&
135
+ Raif.embedding_model_registry.present? &&
136
+ !Raif.available_embedding_model_keys.include?(default_embedding_model_key.to_sym)
107
137
  raise Raif::Errors::InvalidConfigError,
108
138
  "Raif.config.default_embedding_model_key was set to #{default_embedding_model_key}, but must be one of: #{Raif.available_embedding_model_keys.join(", ")}" # rubocop:disable Layout/LineLength
109
139
  end
@@ -127,6 +157,11 @@ module Raif
127
157
  "Raif.config.open_ai_api_key is required when Raif.config.open_ai_models_enabled is true. Set it via Raif.config.open_ai_api_key or ENV[\"OPENAI_API_KEY\"]" # rubocop:disable Layout/LineLength
128
158
  end
129
159
 
160
+ if open_ai_models_enabled && ![:bearer, :api_key].include?(open_ai_auth_header_style)
161
+ raise Raif::Errors::InvalidConfigError,
162
+ "Raif.config.open_ai_auth_header_style must be either :bearer or :api_key"
163
+ end
164
+
130
165
  if open_ai_embedding_models_enabled && open_ai_api_key.blank?
131
166
  raise Raif::Errors::InvalidConfigError,
132
167
  "Raif.config.open_ai_api_key is required when Raif.config.open_ai_embedding_models_enabled is true. Set it via Raif.config.open_ai_api_key or ENV[\"OPENAI_API_KEY\"]" # rubocop:disable Layout/LineLength
@@ -141,6 +176,16 @@ module Raif
141
176
  raise Raif::Errors::InvalidConfigError,
142
177
  "Raif.config.open_router_api_key is required when Raif.config.open_router_models_enabled is true. Set it via Raif.config.open_router_api_key or ENV['OPEN_ROUTER_API_KEY']" # rubocop:disable Layout/LineLength
143
178
  end
179
+
180
+ if google_models_enabled && google_api_key.blank?
181
+ raise Raif::Errors::InvalidConfigError,
182
+ "Raif.config.google_api_key is required when Raif.config.google_models_enabled is true. Set it via Raif.config.google_api_key or ENV['GOOGLE_API_KEY']" # rubocop:disable Layout/LineLength
183
+ end
184
+
185
+ if google_embedding_models_enabled && google_api_key.blank?
186
+ raise Raif::Errors::InvalidConfigError,
187
+ "Raif.config.google_api_key is required when Raif.config.google_embedding_models_enabled is true. Set it via Raif.config.google_api_key or ENV['GOOGLE_API_KEY']" # rubocop:disable Layout/LineLength
188
+ end
144
189
  end
145
190
 
146
191
  private
@@ -77,6 +77,14 @@ module Raif
77
77
  input_token_cost: 0.01 / 1_000_000,
78
78
  default_output_vector_size: 1024,
79
79
  },
80
+ ],
81
+ Raif::EmbeddingModels::Google => [
82
+ {
83
+ key: :google_gemini_embedding_2,
84
+ api_name: "gemini-embedding-2-preview",
85
+ input_token_cost: 0.20 / 1_000_000,
86
+ default_output_vector_size: 3072,
87
+ },
80
88
  ]
81
89
  }
82
90
  end
data/lib/raif/engine.rb CHANGED
@@ -9,6 +9,11 @@ module Raif
9
9
  class Engine < ::Rails::Engine
10
10
  isolate_namespace Raif
11
11
 
12
+ initializer "raif.prompt_template_formats", before: :add_view_paths do
13
+ Mime::Type.register "text/plain", :prompt unless Mime::Type.lookup_by_extension(:prompt)
14
+ Mime::Type.register "text/plain", :system_prompt unless Mime::Type.lookup_by_extension(:system_prompt)
15
+ end
16
+
12
17
  # If the host app is using FactoryBot, add the factories to the host app so they can be used in host apptests
13
18
  if defined?(FactoryBotRails)
14
19
  config.factory_bot.definition_file_paths += [File.expand_path("../../../spec/factories/shared", __FILE__)]
@@ -72,6 +77,22 @@ module Raif
72
77
  end
73
78
  end
74
79
 
80
+ config.after_initialize do
81
+ next unless Raif.config.google_models_enabled
82
+
83
+ Raif.default_llms[Raif::Llms::Google].each do |llm_config|
84
+ Raif.register_llm(Raif::Llms::Google, **llm_config)
85
+ end
86
+ end
87
+
88
+ config.after_initialize do
89
+ next unless Raif.config.google_embedding_models_enabled
90
+
91
+ Raif.default_embedding_models[Raif::EmbeddingModels::Google].each do |embedding_model_config|
92
+ Raif.register_embedding_model(Raif::EmbeddingModels::Google, **embedding_model_config)
93
+ end
94
+ end
95
+
75
96
  config.after_initialize do
76
97
  next unless Raif.config.bedrock_embedding_models_enabled
77
98
 
@@ -85,7 +106,8 @@ module Raif
85
106
  config.after_initialize do
86
107
  next unless Rails.env.test?
87
108
 
88
- Raif.config.conversation_types += ["Raif::TestConversation"]
109
+ Raif.config.conversation_types += ["Raif::TestConversation", "Raif::TestTemplateConversation"]
110
+ Raif.config.agent_types += ["Raif::TestTemplateAgent"]
89
111
 
90
112
  require "#{Raif::Engine.root}/spec/support/test_llm"
91
113
  Raif.register_llm(Raif::Llms::TestLlm, key: :raif_test_llm, api_name: "raif-test-llm")
@@ -120,6 +142,7 @@ module Raif
120
142
  Rails.application.config.assets.precompile += [
121
143
  "raif.js",
122
144
  "raif.css",
145
+ "raif_admin_sprockets.js",
123
146
  "raif_admin.css",
124
147
  "raif-logo-white.svg"
125
148
  ]
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Raif
4
+ module Errors
5
+ class BlankResponseError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Raif
4
+ module Errors
5
+ class InstanceDependentSchemaError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Raif
4
+ module Errors
5
+ class PromptTemplateError < StandardError
6
+ attr_reader :template_path, :original_error
7
+
8
+ def initialize(template_path:, original_error:)
9
+ @template_path = template_path
10
+ @original_error = original_error
11
+ super("Error rendering prompt template '#{template_path}': #{original_error.class}: #{original_error.message}")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -3,16 +3,19 @@
3
3
  module Raif
4
4
  module Errors
5
5
  class StreamingError < StandardError
6
- attr_reader :message, :type, :code, :event
6
+ attr_reader :type, :code, :event
7
7
 
8
8
  def initialize(message:, type:, event:, code: nil)
9
- super
9
+ super(message)
10
10
 
11
- @message = message
12
11
  @type = type
13
12
  @code = code
14
13
  @event = event
15
14
  end
15
+
16
+ def to_s
17
+ "[#{type}] #{super} (code=#{code}, event=#{event})"
18
+ end
16
19
  end
17
20
  end
18
21
  end
data/lib/raif/errors.rb CHANGED
@@ -9,3 +9,6 @@ require "raif/errors/invalid_model_image_input_error"
9
9
  require "raif/errors/invalid_model_file_input_error"
10
10
  require "raif/errors/unsupported_feature_error"
11
11
  require "raif/errors/streaming_error"
12
+ require "raif/errors/instance_dependent_schema_error"
13
+ require "raif/errors/prompt_template_error"
14
+ require "raif/errors/blank_response_error"
@@ -33,6 +33,7 @@ module Raif
33
33
  output.puts "\nStarting Raif Eval Run"
34
34
  output.puts ""
35
35
  output.puts "Raif.config.default_llm_model_key: #{Raif.config.default_llm_model_key}"
36
+ output.puts "Raif.config.evals_default_llm_judge_model_key: #{Raif.config.evals_default_llm_judge_model_key}"
36
37
  output.puts ""
37
38
  output.puts "=" * 50
38
39
 
data/lib/raif/evals.rb CHANGED
@@ -4,12 +4,6 @@ require "raif/evals/expectation_result"
4
4
  require "raif/evals/eval"
5
5
  require "raif/evals/eval_set"
6
6
  require "raif/evals/run"
7
- require "raif/evals/llm_judge"
8
- require "raif/evals/llm_judges/binary"
9
- require "raif/evals/llm_judges/comparative"
10
- require "raif/evals/llm_judges/scored"
11
- require "raif/evals/llm_judges/summarization"
12
- require "raif/evals/scoring_rubric"
13
7
 
14
8
  module Raif
15
9
  module Evals
@@ -10,6 +10,20 @@ module Raif
10
10
  @items_schema = nil
11
11
  end
12
12
 
13
+ # Build schema with instance context for instance-dependent schemas
14
+ # The block receives the instance as a parameter and has access to the builder methods
15
+ #
16
+ # @param instance [Object] The instance to use as context
17
+ # @param block [Proc] The block to evaluate with instance context
18
+ # @return [JsonSchemaBuilder] self for chaining
19
+ def build_with_instance(instance, &block)
20
+ # Evaluate the block in the context of the builder, passing the instance as parameter
21
+ # This allows the block to use both builder methods (string, integer, etc.)
22
+ # and access the instance parameter for conditional logic
23
+ instance_exec(instance, &block)
24
+ self
25
+ end
26
+
13
27
  def string(name, options = {})
14
28
  add_property(name, "string", options)
15
29
  end