raif 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/app/assets/builds/raif_admin.css +40 -2
- data/app/assets/builds/raif_admin_sprockets.js +2709 -0
- data/app/assets/javascript/raif/admin/copy_to_clipboard_controller.js +132 -0
- data/app/assets/javascript/raif/admin/cost_estimate_controller.js +80 -0
- data/app/assets/javascript/raif/admin/judge_config_controller.js +23 -0
- data/app/assets/javascript/raif/admin/select_all_checkboxes_controller.js +33 -0
- data/app/assets/javascript/raif/admin/sortable_table_controller.js +51 -0
- data/app/assets/javascript/raif/admin/table_search_controller.js +15 -0
- data/app/assets/javascript/raif/admin/tom_select_controller.js +33 -0
- data/app/assets/javascript/raif_admin.js +23 -0
- data/app/assets/javascript/raif_admin_sprockets.js +24 -0
- data/app/assets/stylesheets/raif_admin.scss +50 -1
- data/app/controllers/raif/admin/agents_controller.rb +27 -1
- data/app/controllers/raif/admin/configs_controller.rb +1 -0
- data/app/controllers/raif/admin/llms_controller.rb +27 -0
- data/app/controllers/raif/admin/model_completions_controller.rb +6 -0
- data/app/controllers/raif/admin/prompt_studio/agents_controller.rb +25 -0
- data/app/controllers/raif/admin/prompt_studio/base_controller.rb +32 -0
- data/app/controllers/raif/admin/prompt_studio/batch_runs_controller.rb +102 -0
- data/app/controllers/raif/admin/prompt_studio/conversations_controller.rb +25 -0
- data/app/controllers/raif/admin/prompt_studio/tasks_controller.rb +64 -0
- data/app/controllers/raif/admin/tasks_controller.rb +5 -0
- data/app/helpers/raif/application_helper.rb +40 -0
- data/app/jobs/raif/prompt_studio_batch_run_item_job.rb +11 -0
- data/app/jobs/raif/prompt_studio_batch_run_job.rb +15 -0
- data/app/jobs/raif/prompt_studio_task_run_job.rb +36 -0
- data/app/models/raif/agent.rb +36 -5
- data/app/models/raif/agents/native_tool_calling_agent.rb +101 -19
- data/app/models/raif/concerns/has_prompt_templates.rb +88 -0
- data/app/models/raif/concerns/has_runtime_duration.rb +41 -0
- data/app/models/raif/concerns/json_schema_definition.rb +16 -3
- data/app/models/raif/concerns/llm_prompt_caching.rb +20 -0
- data/app/models/raif/concerns/llms/anthropic/message_formatting.rb +6 -0
- data/app/models/raif/concerns/llms/anthropic/tool_formatting.rb +5 -1
- data/app/models/raif/concerns/llms/bedrock/message_formatting.rb +7 -0
- data/app/models/raif/concerns/llms/bedrock/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/google/message_formatting.rb +5 -2
- data/app/models/raif/concerns/llms/google/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/message_formatting.rb +30 -0
- data/app/models/raif/concerns/llms/open_ai_completions/response_tool_calls.rb +1 -1
- data/app/models/raif/concerns/llms/open_ai_completions/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/open_ai_responses/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/provider_managed_tool_calls.rb +162 -0
- data/app/models/raif/conversation.rb +24 -3
- data/app/models/raif/conversation_entry.rb +6 -3
- data/app/models/raif/embedding_models/bedrock.rb +10 -1
- data/app/models/raif/embedding_models/google.rb +37 -0
- data/app/models/raif/evals/llm_judge.rb +70 -0
- data/{lib → app/models}/raif/evals/llm_judges/binary.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/comparative.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/scored.rb +38 -0
- data/{lib → app/models}/raif/evals/llm_judges/summarization.rb +38 -0
- data/app/models/raif/llm.rb +82 -7
- data/app/models/raif/llms/anthropic.rb +26 -4
- data/app/models/raif/llms/bedrock.rb +59 -5
- data/app/models/raif/llms/google.rb +28 -2
- data/app/models/raif/llms/open_ai_base.rb +4 -0
- data/app/models/raif/llms/open_ai_completions.rb +9 -2
- data/app/models/raif/llms/open_ai_responses.rb +9 -2
- data/app/models/raif/llms/open_router.rb +10 -3
- data/app/models/raif/model_completion.rb +75 -34
- data/app/models/raif/model_tool.rb +45 -3
- data/app/models/raif/model_tool_invocation.rb +31 -1
- data/app/models/raif/prompt_studio_batch_run.rb +155 -0
- data/app/models/raif/prompt_studio_batch_run_item.rb +220 -0
- data/app/models/raif/streaming_responses/bedrock.rb +60 -1
- data/app/models/raif/task.rb +30 -6
- data/app/views/layouts/raif/admin.html.erb +31 -1
- data/app/views/raif/admin/agents/_agent.html.erb +1 -0
- data/app/views/raif/admin/agents/index.html.erb +48 -0
- data/app/views/raif/admin/agents/show.html.erb +4 -0
- data/app/views/raif/admin/llms/index.html.erb +110 -0
- data/app/views/raif/admin/model_completions/_model_completion.html.erb +3 -7
- data/app/views/raif/admin/model_completions/index.html.erb +14 -1
- data/app/views/raif/admin/model_completions/show.html.erb +164 -55
- data/app/views/raif/admin/model_tool_invocations/index.html.erb +1 -1
- data/app/views/raif/admin/model_tool_invocations/show.html.erb +18 -0
- data/app/views/raif/admin/prompt_studio/agents/index.html.erb +56 -0
- data/app/views/raif/admin/prompt_studio/agents/show.html.erb +57 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_batch_run_item.html.erb +54 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_judge_config_fields.html.erb +76 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_judge_detail_modal.html.erb +27 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_modal.html.erb +35 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/_progress.html.erb +78 -0
- data/app/views/raif/admin/prompt_studio/batch_runs/show.html.erb +49 -0
- data/app/views/raif/admin/prompt_studio/conversations/index.html.erb +48 -0
- data/app/views/raif/admin/prompt_studio/conversations/show.html.erb +36 -0
- data/app/views/raif/admin/prompt_studio/shared/_nav_tabs.html.erb +17 -0
- data/app/views/raif/admin/prompt_studio/shared/_prompt_comparison.html.erb +87 -0
- data/app/views/raif/admin/prompt_studio/shared/_type_filter.html.erb +54 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_result.html.erb +145 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_row.html.erb +12 -0
- data/app/views/raif/admin/prompt_studio/tasks/_task_type_filter.html.erb +58 -0
- data/app/views/raif/admin/prompt_studio/tasks/_tasks_table.html.erb +22 -0
- data/app/views/raif/admin/prompt_studio/tasks/index.html.erb +35 -0
- data/app/views/raif/admin/prompt_studio/tasks/show.html.erb +19 -0
- data/app/views/raif/admin/tasks/_task.html.erb +1 -0
- data/app/views/raif/admin/tasks/index.html.erb +17 -5
- data/app/views/raif/admin/tasks/show.html.erb +20 -0
- data/app/views/raif/conversation_entries/_message.html.erb +10 -6
- data/config/importmap.rb +8 -0
- data/config/locales/admin.en.yml +128 -0
- data/config/locales/en.yml +36 -2
- data/config/routes.rb +8 -0
- data/db/migrate/20260307000000_add_prompt_studio_run_to_raif_tasks.rb +7 -0
- data/db/migrate/20260308000000_create_raif_prompt_studio_batch_runs.rb +27 -0
- data/db/migrate/20260308000001_create_raif_prompt_studio_batch_run_items.rb +24 -0
- data/db/migrate/20260407000000_add_cache_token_columns_to_raif_model_completions.rb +8 -0
- data/lib/generators/raif/agent/agent_generator.rb +18 -0
- data/lib/generators/raif/agent/templates/agent.rb.tt +7 -5
- data/lib/generators/raif/agent/templates/system_prompt.erb.tt +3 -0
- data/lib/generators/raif/conversation/conversation_generator.rb +19 -1
- data/lib/generators/raif/conversation/templates/system_prompt.erb.tt +4 -0
- data/lib/generators/raif/install/templates/initializer.rb +68 -27
- data/lib/generators/raif/task/task_generator.rb +18 -0
- data/lib/generators/raif/task/templates/prompt.erb.tt +4 -0
- data/lib/generators/raif/task/templates/task.rb.tt +9 -8
- data/lib/raif/configuration.rb +10 -0
- data/lib/raif/embedding_model_registry.rb +8 -0
- data/lib/raif/engine.rb +16 -1
- data/lib/raif/errors/blank_response_error.rb +8 -0
- data/lib/raif/errors/prompt_template_error.rb +15 -0
- data/lib/raif/errors.rb +2 -0
- data/lib/raif/evals.rb +0 -6
- data/lib/raif/llm_registry.rb +230 -9
- data/lib/raif/prompt_studio_comparison_builder.rb +138 -0
- data/lib/raif/token_estimator.rb +28 -0
- data/lib/raif/version.rb +1 -1
- data/lib/raif.rb +2 -0
- data/spec/support/rspec_helpers.rb +7 -1
- data/spec/support/test_task.rb +9 -0
- data/spec/support/test_template_task.rb +41 -0
- metadata +65 -7
- data/lib/raif/evals/llm_judge.rb +0 -32
- /data/{lib → app/models}/raif/evals/scoring_rubric.rb +0 -0
|
@@ -19,6 +19,11 @@ module Raif
|
|
|
19
19
|
default: false,
|
|
20
20
|
desc: "Skip generating the corresponding eval set"
|
|
21
21
|
|
|
22
|
+
class_option :skip_prompt_template,
|
|
23
|
+
type: :boolean,
|
|
24
|
+
default: false,
|
|
25
|
+
desc: "Skip generating the system prompt template file"
|
|
26
|
+
|
|
22
27
|
def create_application_conversation
|
|
23
28
|
template "application_conversation.rb.tt",
|
|
24
29
|
"app/models/raif/application_conversation.rb" unless File.exist?("app/models/raif/application_conversation.rb")
|
|
@@ -28,6 +33,12 @@ module Raif
|
|
|
28
33
|
template "conversation.rb.tt", File.join("app/models/raif/conversations", class_path, "#{file_name}.rb")
|
|
29
34
|
end
|
|
30
35
|
|
|
36
|
+
def create_system_prompt_template
|
|
37
|
+
return if options[:skip_prompt_template]
|
|
38
|
+
|
|
39
|
+
template "system_prompt.erb.tt", system_prompt_template_file_path
|
|
40
|
+
end
|
|
41
|
+
|
|
31
42
|
def create_directory
|
|
32
43
|
empty_directory "app/models/raif/conversations" unless File.directory?("app/models/raif/conversations")
|
|
33
44
|
end
|
|
@@ -41,7 +52,10 @@ module Raif
|
|
|
41
52
|
def success_message
|
|
42
53
|
say_status :success, "Conversation type created successfully", :green
|
|
43
54
|
say "\nYou can now implement your conversation type in:"
|
|
44
|
-
say " app/models/raif/conversations/#{file_name}.rb
|
|
55
|
+
say " app/models/raif/conversations/#{file_name}.rb"
|
|
56
|
+
unless options[:skip_prompt_template]
|
|
57
|
+
say " System prompt template: #{system_prompt_template_file_path}"
|
|
58
|
+
end
|
|
45
59
|
say "\nDon't forget to add it to the config.conversation_types in your Raif configuration"
|
|
46
60
|
say "For example: config.conversation_types += ['Raif::Conversations::#{class_name}']\n\n"
|
|
47
61
|
end
|
|
@@ -51,6 +65,10 @@ module Raif
|
|
|
51
65
|
def eval_set_file_path
|
|
52
66
|
File.join("raif_evals", "eval_sets", "conversations", class_path, "#{file_name}_eval_set.rb")
|
|
53
67
|
end
|
|
68
|
+
|
|
69
|
+
def system_prompt_template_file_path
|
|
70
|
+
File.join("app/views/raif/conversations", class_path, "#{file_name}.system_prompt.erb")
|
|
71
|
+
end
|
|
54
72
|
end
|
|
55
73
|
end
|
|
56
74
|
end
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<%% # Define the system prompt for Raif::Conversations::<%= class_name %> here. %>
|
|
2
|
+
<%% # All instance methods are available in this template. %>
|
|
3
|
+
<%% # You can also use Rails view helpers and render partials. %>
|
|
4
|
+
<%% # If this file is removed, the default system prompt from Raif.config.conversation_system_prompt_intro will be used. %>
|
|
@@ -60,75 +60,115 @@ Raif.configure do |config|
|
|
|
60
60
|
# config.google_api_key = ENV["GOOGLE_AI_API_KEY"].presence || ENV["GOOGLE_API_KEY"]
|
|
61
61
|
|
|
62
62
|
# Whether Google models are enabled.
|
|
63
|
-
# config.google_models_enabled = ENV["GOOGLE_API_KEY"].present?
|
|
63
|
+
# config.google_models_enabled = ENV["GOOGLE_AI_API_KEY"].present? || ENV["GOOGLE_API_KEY"].present?
|
|
64
|
+
|
|
65
|
+
# Whether Google embedding models are enabled. Defaults to false
|
|
66
|
+
# config.google_embedding_models_enabled = false
|
|
64
67
|
|
|
65
68
|
# The default LLM model to use. Defaults to "open_ai_gpt_4o"
|
|
66
69
|
# Available keys:
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
+
# open_ai_gpt_5_4
|
|
71
|
+
# open_ai_gpt_5_2
|
|
72
|
+
# open_ai_gpt_5_1
|
|
73
|
+
# open_ai_gpt_5
|
|
74
|
+
# open_ai_gpt_5_mini
|
|
75
|
+
# open_ai_gpt_5_nano
|
|
70
76
|
# open_ai_gpt_4_1
|
|
71
77
|
# open_ai_gpt_4_1_mini
|
|
72
78
|
# open_ai_gpt_4_1_nano
|
|
73
|
-
#
|
|
74
|
-
#
|
|
79
|
+
# open_ai_gpt_4o
|
|
80
|
+
# open_ai_gpt_4o_mini
|
|
81
|
+
# open_ai_gpt_3_5_turbo
|
|
82
|
+
# open_ai_o4_mini
|
|
75
83
|
# open_ai_o3
|
|
76
84
|
# open_ai_o3_mini
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
85
|
+
# open_ai_o1
|
|
86
|
+
# open_ai_o1_mini
|
|
87
|
+
# open_ai_responses_gpt_5_4
|
|
88
|
+
# open_ai_responses_gpt_5_4_pro
|
|
89
|
+
# open_ai_responses_gpt_5_2
|
|
90
|
+
# open_ai_responses_gpt_5_2_pro
|
|
91
|
+
# open_ai_responses_gpt_5_1
|
|
92
|
+
# open_ai_responses_gpt_5
|
|
93
|
+
# open_ai_responses_gpt_5_pro
|
|
94
|
+
# open_ai_responses_gpt_5_mini
|
|
95
|
+
# open_ai_responses_gpt_5_nano
|
|
84
96
|
# open_ai_responses_gpt_4_1
|
|
85
97
|
# open_ai_responses_gpt_4_1_mini
|
|
86
98
|
# open_ai_responses_gpt_4_1_nano
|
|
87
|
-
#
|
|
88
|
-
#
|
|
99
|
+
# open_ai_responses_gpt_4o
|
|
100
|
+
# open_ai_responses_gpt_4o_mini
|
|
101
|
+
# open_ai_responses_gpt_3_5_turbo
|
|
102
|
+
# open_ai_responses_o4_mini
|
|
89
103
|
# open_ai_responses_o3
|
|
104
|
+
# open_ai_responses_o3_pro
|
|
90
105
|
# open_ai_responses_o3_mini
|
|
91
|
-
#
|
|
92
|
-
# open_ai_responses_gpt_5
|
|
93
|
-
# open_ai_responses_gpt_5_mini
|
|
94
|
-
# open_ai_responses_gpt_5_nano
|
|
106
|
+
# open_ai_responses_o1
|
|
95
107
|
# open_ai_responses_o1_pro
|
|
96
|
-
#
|
|
97
|
-
#
|
|
108
|
+
# anthropic_claude_4_7_opus
|
|
109
|
+
# anthropic_claude_4_6_opus
|
|
110
|
+
# anthropic_claude_4_6_sonnet
|
|
111
|
+
# anthropic_claude_4_5_opus
|
|
98
112
|
# anthropic_claude_4_5_sonnet
|
|
99
|
-
#
|
|
113
|
+
# anthropic_claude_4_5_haiku
|
|
100
114
|
# anthropic_claude_4_1_opus
|
|
115
|
+
# anthropic_claude_4_opus
|
|
116
|
+
# anthropic_claude_4_sonnet
|
|
101
117
|
# anthropic_claude_3_7_sonnet
|
|
102
118
|
# anthropic_claude_3_5_sonnet
|
|
103
119
|
# anthropic_claude_3_5_haiku
|
|
104
120
|
# anthropic_claude_3_opus
|
|
105
|
-
#
|
|
121
|
+
# bedrock_claude_4_7_opus
|
|
122
|
+
# bedrock_claude_4_6_opus
|
|
123
|
+
# bedrock_claude_4_6_sonnet
|
|
124
|
+
# bedrock_claude_4_5_opus
|
|
106
125
|
# bedrock_claude_4_5_sonnet
|
|
107
|
-
#
|
|
126
|
+
# bedrock_claude_4_5_haiku
|
|
108
127
|
# bedrock_claude_4_1_opus
|
|
109
|
-
#
|
|
128
|
+
# bedrock_claude_4_opus
|
|
129
|
+
# bedrock_claude_4_sonnet
|
|
110
130
|
# bedrock_claude_3_7_sonnet
|
|
131
|
+
# bedrock_claude_3_5_sonnet
|
|
111
132
|
# bedrock_claude_3_5_haiku
|
|
112
133
|
# bedrock_claude_3_opus
|
|
113
134
|
# bedrock_amazon_nova_micro
|
|
114
135
|
# bedrock_amazon_nova_lite
|
|
115
136
|
# bedrock_amazon_nova_pro
|
|
137
|
+
# bedrock_deepseek_v3_2
|
|
138
|
+
# bedrock_deepseek_r1
|
|
139
|
+
# bedrock_gpt_oss_120b
|
|
140
|
+
# bedrock_gpt_oss_20b
|
|
116
141
|
# open_router_claude_3_7_sonnet
|
|
117
142
|
# open_router_deepseek_chat_v3
|
|
118
143
|
# open_router_deepseek_v3_1
|
|
144
|
+
# open_router_deepseek_v3_2
|
|
119
145
|
# open_router_gemini_2_0_flash
|
|
146
|
+
# open_router_gemini_2_5_flash
|
|
120
147
|
# open_router_gemini_2_5_pro
|
|
148
|
+
# open_router_gemini_3_pro_preview
|
|
121
149
|
# open_router_grok_4
|
|
150
|
+
# open_router_grok_4_1_fast
|
|
151
|
+
# open_router_kimi_k2_thinking
|
|
152
|
+
# open_router_kimi_k2_5
|
|
122
153
|
# open_router_llama_3_1_8b_instruct
|
|
123
154
|
# open_router_llama_3_3_70b_instruct
|
|
124
155
|
# open_router_llama_4_maverick
|
|
125
156
|
# open_router_llama_4_scout
|
|
157
|
+
# open_router_minimax_m2
|
|
158
|
+
# open_router_minimax_m2_1
|
|
159
|
+
# open_router_minimax_m2_5
|
|
160
|
+
# open_router_mistral_large_3_2512
|
|
161
|
+
# open_router_mistral_small_3_2_24b
|
|
162
|
+
# open_router_gemini_3_1_pro_preview
|
|
163
|
+
# open_router_gemini_3_1_flash_lite_preview
|
|
126
164
|
# open_router_open_ai_gpt_oss_120b
|
|
127
165
|
# open_router_open_ai_gpt_oss_20b
|
|
128
|
-
#
|
|
129
|
-
#
|
|
166
|
+
# google_gemini_3_1_pro
|
|
167
|
+
# google_gemini_3_1_flash_lite
|
|
130
168
|
# google_gemini_3_0_pro
|
|
131
169
|
# google_gemini_3_0_flash
|
|
170
|
+
# google_gemini_2_5_pro
|
|
171
|
+
# google_gemini_2_5_flash
|
|
132
172
|
#
|
|
133
173
|
# config.default_llm_model_key = "open_ai_gpt_4o"
|
|
134
174
|
|
|
@@ -139,6 +179,7 @@ Raif.configure do |config|
|
|
|
139
179
|
# open_ai_text_embedding_3_large
|
|
140
180
|
# open_ai_text_embedding_ada_002
|
|
141
181
|
# bedrock_titan_embed_text_v2
|
|
182
|
+
# google_gemini_embedding_2
|
|
142
183
|
#
|
|
143
184
|
# config.default_embedding_model_key = "open_ai_text_embedding_3_small"
|
|
144
185
|
|
|
@@ -17,6 +17,11 @@ module Raif
|
|
|
17
17
|
default: false,
|
|
18
18
|
desc: "Skip generating the corresponding eval set"
|
|
19
19
|
|
|
20
|
+
class_option :skip_prompt_template,
|
|
21
|
+
type: :boolean,
|
|
22
|
+
default: false,
|
|
23
|
+
desc: "Skip generating the prompt template file"
|
|
24
|
+
|
|
20
25
|
def create_application_task
|
|
21
26
|
template "application_task.rb.tt", "app/models/raif/application_task.rb" unless File.exist?("app/models/raif/application_task.rb")
|
|
22
27
|
end
|
|
@@ -25,6 +30,12 @@ module Raif
|
|
|
25
30
|
template "task.rb.tt", File.join("app/models/raif/tasks", class_path, "#{file_name}.rb")
|
|
26
31
|
end
|
|
27
32
|
|
|
33
|
+
def create_prompt_template
|
|
34
|
+
return if options[:skip_prompt_template]
|
|
35
|
+
|
|
36
|
+
template "prompt.erb.tt", prompt_template_file_path
|
|
37
|
+
end
|
|
38
|
+
|
|
28
39
|
def create_eval_set
|
|
29
40
|
return if options[:skip_eval_set]
|
|
30
41
|
|
|
@@ -33,6 +44,9 @@ module Raif
|
|
|
33
44
|
|
|
34
45
|
def show_instructions
|
|
35
46
|
say "\nTask created!"
|
|
47
|
+
unless options[:skip_prompt_template]
|
|
48
|
+
say " Prompt template: #{prompt_template_file_path}"
|
|
49
|
+
end
|
|
36
50
|
say ""
|
|
37
51
|
end
|
|
38
52
|
|
|
@@ -42,6 +56,10 @@ module Raif
|
|
|
42
56
|
File.join("raif_evals", "eval_sets", "tasks", class_path, "#{file_name}_eval_set.rb")
|
|
43
57
|
end
|
|
44
58
|
|
|
59
|
+
def prompt_template_file_path
|
|
60
|
+
File.join("app/views/raif/tasks", class_path, "#{file_name}.prompt.erb")
|
|
61
|
+
end
|
|
62
|
+
|
|
45
63
|
end
|
|
46
64
|
end
|
|
47
65
|
end
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<%% # Implement the LLM prompt for Raif::Tasks::<%= class_name %> here. %>
|
|
2
|
+
<%% # All instance methods and run_with attributes are available in this template. %>
|
|
3
|
+
<%% # You can also use Rails view helpers (content_tag, strip_tags, truncate, etc.) %>
|
|
4
|
+
<%% # and render partials with: <%%= render partial: "raif/shared/my_partial" %> %>
|
|
@@ -44,14 +44,15 @@
|
|
|
44
44
|
end
|
|
45
45
|
<%- end -%>
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
47
|
+
# Prompt is defined in app/views/raif/tasks/<%= class_path.any? ? class_path.join("/") + "/" : "" %><%= file_name %>.prompt.erb
|
|
48
|
+
# You can also define a system prompt template at:
|
|
49
|
+
# app/views/raif/tasks/<%= class_path.any? ? class_path.join("/") + "/" : "" %><%= file_name %>.system_prompt.erb
|
|
50
|
+
#
|
|
51
|
+
# Alternatively, override build_prompt and/or build_system_prompt methods directly:
|
|
52
|
+
# def build_prompt
|
|
53
|
+
# "Your prompt here"
|
|
54
|
+
# end
|
|
55
|
+
#
|
|
55
56
|
# def build_system_prompt
|
|
56
57
|
# super + "\nAdditional system instructions..."
|
|
57
58
|
# end
|
data/lib/raif/configuration.rb
CHANGED
|
@@ -22,6 +22,7 @@ module Raif
|
|
|
22
22
|
:evals_default_llm_judge_model_key,
|
|
23
23
|
:evals_verbose_output,
|
|
24
24
|
:google_api_key,
|
|
25
|
+
:google_embedding_models_enabled,
|
|
25
26
|
:google_models_enabled,
|
|
26
27
|
:llm_api_requests_enabled,
|
|
27
28
|
:llm_request_max_retries,
|
|
@@ -43,6 +44,7 @@ module Raif
|
|
|
43
44
|
:request_write_timeout,
|
|
44
45
|
:streaming_update_chunk_size_threshold,
|
|
45
46
|
:task_creator_optional,
|
|
47
|
+
:prompt_studio_runs_enabled,
|
|
46
48
|
:task_system_prompt_intro,
|
|
47
49
|
:user_tool_types
|
|
48
50
|
|
|
@@ -75,6 +77,7 @@ module Raif
|
|
|
75
77
|
@evals_verbose_output = false
|
|
76
78
|
google_api_key = ENV["GOOGLE_AI_API_KEY"].presence || ENV["GOOGLE_API_KEY"]
|
|
77
79
|
@google_api_key = default_disable_llm_api_requests? ? "placeholder-google-api-key" : google_api_key
|
|
80
|
+
@google_embedding_models_enabled = false
|
|
78
81
|
@google_models_enabled = @google_api_key.present?
|
|
79
82
|
@llm_api_requests_enabled = !default_disable_llm_api_requests?
|
|
80
83
|
@llm_request_max_retries = 2
|
|
@@ -84,6 +87,7 @@ module Raif
|
|
|
84
87
|
Faraday::ServerError,
|
|
85
88
|
Net::ReadTimeout,
|
|
86
89
|
Net::OpenTimeout,
|
|
90
|
+
Raif::Errors::BlankResponseError,
|
|
87
91
|
]
|
|
88
92
|
@model_superclass = "ApplicationRecord"
|
|
89
93
|
@open_ai_api_key = default_disable_llm_api_requests? ? "placeholder-open-ai-api-key" : ENV["OPENAI_API_KEY"]
|
|
@@ -96,6 +100,7 @@ module Raif
|
|
|
96
100
|
open_router_api_key = ENV["OPEN_ROUTER_API_KEY"].presence || ENV["OPENROUTER_API_KEY"]
|
|
97
101
|
@open_router_api_key = default_disable_llm_api_requests? ? "placeholder-open-router-api-key" : open_router_api_key
|
|
98
102
|
@open_router_models_enabled = @open_router_api_key.present?
|
|
103
|
+
@prompt_studio_runs_enabled = Rails.env.development?
|
|
99
104
|
@open_router_app_name = nil
|
|
100
105
|
@open_router_site_url = nil
|
|
101
106
|
@request_open_timeout = nil
|
|
@@ -176,6 +181,11 @@ module Raif
|
|
|
176
181
|
raise Raif::Errors::InvalidConfigError,
|
|
177
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
|
|
178
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
|
|
179
189
|
end
|
|
180
190
|
|
|
181
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__)]
|
|
@@ -80,6 +85,14 @@ module Raif
|
|
|
80
85
|
end
|
|
81
86
|
end
|
|
82
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
|
+
|
|
83
96
|
config.after_initialize do
|
|
84
97
|
next unless Raif.config.bedrock_embedding_models_enabled
|
|
85
98
|
|
|
@@ -93,7 +106,8 @@ module Raif
|
|
|
93
106
|
config.after_initialize do
|
|
94
107
|
next unless Rails.env.test?
|
|
95
108
|
|
|
96
|
-
Raif.config.conversation_types += ["Raif::TestConversation"]
|
|
109
|
+
Raif.config.conversation_types += ["Raif::TestConversation", "Raif::TestTemplateConversation"]
|
|
110
|
+
Raif.config.agent_types += ["Raif::TestTemplateAgent"]
|
|
97
111
|
|
|
98
112
|
require "#{Raif::Engine.root}/spec/support/test_llm"
|
|
99
113
|
Raif.register_llm(Raif::Llms::TestLlm, key: :raif_test_llm, api_name: "raif-test-llm")
|
|
@@ -128,6 +142,7 @@ module Raif
|
|
|
128
142
|
Rails.application.config.assets.precompile += [
|
|
129
143
|
"raif.js",
|
|
130
144
|
"raif.css",
|
|
145
|
+
"raif_admin_sprockets.js",
|
|
131
146
|
"raif_admin.css",
|
|
132
147
|
"raif-logo-white.svg"
|
|
133
148
|
]
|
|
@@ -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
|
data/lib/raif/errors.rb
CHANGED
|
@@ -10,3 +10,5 @@ require "raif/errors/invalid_model_file_input_error"
|
|
|
10
10
|
require "raif/errors/unsupported_feature_error"
|
|
11
11
|
require "raif/errors/streaming_error"
|
|
12
12
|
require "raif/errors/instance_dependent_schema_error"
|
|
13
|
+
require "raif/errors/prompt_template_error"
|
|
14
|
+
require "raif/errors/blank_response_error"
|
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
|