raif 1.2.2 → 1.4.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 +6 -5
- data/app/assets/builds/raif.css +4 -1
- data/app/assets/builds/raif_admin.css +13 -1
- data/app/assets/javascript/raif/controllers/conversations_controller.js +1 -1
- data/app/assets/stylesheets/raif/admin/conversation.scss +16 -0
- data/app/assets/stylesheets/raif/conversations.scss +3 -0
- data/app/assets/stylesheets/raif.scss +2 -1
- data/app/controllers/raif/admin/application_controller.rb +16 -0
- data/app/controllers/raif/admin/configs_controller.rb +94 -0
- data/app/controllers/raif/admin/model_completions_controller.rb +18 -1
- data/app/controllers/raif/admin/model_tool_invocations_controller.rb +7 -1
- data/app/controllers/raif/admin/stats/model_tool_invocations_controller.rb +21 -0
- data/app/controllers/raif/admin/stats/tasks_controller.rb +15 -6
- data/app/controllers/raif/admin/stats_controller.rb +32 -3
- data/app/controllers/raif/conversation_entries_controller.rb +1 -0
- data/app/controllers/raif/conversations_controller.rb +10 -2
- data/app/jobs/raif/conversation_entry_job.rb +8 -6
- data/app/models/raif/admin/task_stat.rb +7 -0
- data/app/models/raif/agent.rb +63 -2
- data/app/models/raif/agents/native_tool_calling_agent.rb +101 -56
- data/app/models/raif/application_record.rb +18 -0
- data/app/models/raif/concerns/agent_inference_stats.rb +35 -0
- data/app/models/raif/concerns/has_llm.rb +1 -1
- data/app/models/raif/concerns/json_schema_definition.rb +40 -5
- data/app/models/raif/concerns/llms/anthropic/message_formatting.rb +28 -0
- data/app/models/raif/concerns/llms/anthropic/response_tool_calls.rb +24 -0
- data/app/models/raif/concerns/llms/anthropic/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/bedrock/message_formatting.rb +36 -0
- data/app/models/raif/concerns/llms/bedrock/response_tool_calls.rb +26 -0
- data/app/models/raif/concerns/llms/bedrock/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/google/message_formatting.rb +109 -0
- data/app/models/raif/concerns/llms/google/response_tool_calls.rb +32 -0
- data/app/models/raif/concerns/llms/google/tool_formatting.rb +72 -0
- data/app/models/raif/concerns/llms/message_formatting.rb +11 -5
- data/app/models/raif/concerns/llms/open_ai/json_schema_validation.rb +3 -3
- data/app/models/raif/concerns/llms/open_ai_completions/message_formatting.rb +22 -0
- data/app/models/raif/concerns/llms/open_ai_completions/response_tool_calls.rb +22 -0
- data/app/models/raif/concerns/llms/open_ai_completions/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/llms/open_ai_responses/message_formatting.rb +17 -0
- data/app/models/raif/concerns/llms/open_ai_responses/response_tool_calls.rb +26 -0
- data/app/models/raif/concerns/llms/open_ai_responses/tool_formatting.rb +4 -0
- data/app/models/raif/concerns/run_with.rb +127 -0
- data/app/models/raif/conversation.rb +96 -9
- data/app/models/raif/conversation_entry.rb +37 -8
- data/app/models/raif/embedding_model.rb +2 -1
- data/app/models/raif/embedding_models/open_ai.rb +1 -1
- data/app/models/raif/llm.rb +28 -3
- data/app/models/raif/llms/anthropic.rb +7 -19
- data/app/models/raif/llms/bedrock.rb +6 -20
- data/app/models/raif/llms/google.rb +140 -0
- data/app/models/raif/llms/open_ai_base.rb +19 -5
- data/app/models/raif/llms/open_ai_completions.rb +6 -11
- data/app/models/raif/llms/open_ai_responses.rb +6 -16
- data/app/models/raif/llms/open_router.rb +10 -14
- data/app/models/raif/model_completion.rb +61 -0
- data/app/models/raif/model_tool.rb +10 -2
- data/app/models/raif/model_tool_invocation.rb +38 -6
- data/app/models/raif/model_tools/agent_final_answer.rb +2 -7
- data/app/models/raif/model_tools/provider_managed/code_execution.rb +4 -0
- data/app/models/raif/model_tools/provider_managed/image_generation.rb +4 -0
- data/app/models/raif/model_tools/provider_managed/web_search.rb +4 -0
- data/app/models/raif/streaming_responses/google.rb +71 -0
- data/app/models/raif/task.rb +74 -18
- data/app/models/raif/user_tool_invocation.rb +19 -0
- data/app/views/layouts/raif/admin.html.erb +12 -1
- data/app/views/raif/admin/agents/_agent.html.erb +8 -0
- data/app/views/raif/admin/agents/_conversation_message.html.erb +28 -6
- data/app/views/raif/admin/agents/index.html.erb +2 -0
- data/app/views/raif/admin/agents/show.html.erb +46 -1
- data/app/views/raif/admin/configs/show.html.erb +117 -0
- data/app/views/raif/admin/conversations/_conversation_entry.html.erb +29 -34
- data/app/views/raif/admin/conversations/show.html.erb +2 -0
- data/app/views/raif/admin/model_completions/_model_completion.html.erb +9 -0
- data/app/views/raif/admin/model_completions/index.html.erb +26 -0
- data/app/views/raif/admin/model_completions/show.html.erb +124 -61
- data/app/views/raif/admin/model_tool_invocations/index.html.erb +22 -1
- data/app/views/raif/admin/model_tools/_list.html.erb +16 -0
- data/app/views/raif/admin/model_tools/_model_tool.html.erb +36 -0
- data/app/views/raif/admin/stats/_stats_tile.html.erb +34 -0
- data/app/views/raif/admin/stats/index.html.erb +71 -88
- data/app/views/raif/admin/stats/model_tool_invocations/index.html.erb +43 -0
- data/app/views/raif/admin/stats/tasks/index.html.erb +20 -6
- data/app/views/raif/admin/tasks/index.html.erb +6 -1
- data/app/views/raif/admin/tasks/show.html.erb +36 -3
- data/app/views/raif/conversation_entries/_form.html.erb +4 -1
- data/app/views/raif/conversations/_conversation.html.erb +10 -0
- data/app/views/raif/conversations/_entry_processed.turbo_stream.erb +12 -0
- data/app/views/raif/conversations/_full_conversation.html.erb +3 -6
- data/app/views/raif/conversations/_initial_chat_message.html.erb +5 -0
- data/app/views/raif/conversations/index.html.erb +23 -0
- data/config/locales/admin.en.yml +33 -1
- data/config/locales/en.yml +41 -4
- data/config/routes.rb +2 -0
- data/db/migrate/20250804013843_add_task_run_args_to_raif_tasks.rb +13 -0
- data/db/migrate/20250811171150_make_raif_task_creator_optional.rb +8 -0
- data/db/migrate/20250904194456_add_generating_entry_response_to_raif_conversations.rb +7 -0
- data/db/migrate/20250911125234_add_source_to_raif_tasks.rb +7 -0
- data/db/migrate/20251020005853_add_source_to_raif_agents.rb +7 -0
- data/db/migrate/20251020011346_rename_task_run_args_to_run_with.rb +7 -0
- data/db/migrate/20251020011405_add_run_with_to_raif_agents.rb +13 -0
- data/db/migrate/20251024160119_add_llm_messages_max_length_to_raif_conversations.rb +14 -0
- data/db/migrate/20251124185033_add_provider_tool_call_id_to_raif_model_tool_invocations.rb +7 -0
- data/db/migrate/20251128202941_add_tool_choice_to_raif_model_completions.rb +7 -0
- data/db/migrate/20260118144846_add_source_to_raif_conversations.rb +7 -0
- data/db/migrate/20260119000000_add_failure_tracking_to_raif_model_completions.rb +10 -0
- data/db/migrate/20260119000001_add_completed_at_to_raif_model_completions.rb +8 -0
- data/db/migrate/20260119000002_add_started_at_to_raif_model_completions.rb +8 -0
- data/exe/raif +7 -0
- data/lib/generators/raif/agent/agent_generator.rb +22 -7
- data/lib/generators/raif/agent/templates/agent.rb.tt +20 -24
- data/lib/generators/raif/agent/templates/agent_eval_set.rb.tt +48 -0
- data/lib/generators/raif/agent/templates/application_agent.rb.tt +1 -3
- data/lib/generators/raif/base_generator.rb +19 -0
- data/lib/generators/raif/conversation/conversation_generator.rb +21 -2
- data/lib/generators/raif/conversation/templates/application_conversation.rb.tt +0 -2
- data/lib/generators/raif/conversation/templates/conversation.rb.tt +34 -32
- data/lib/generators/raif/conversation/templates/conversation_eval_set.rb.tt +70 -0
- data/lib/generators/raif/eval_set/eval_set_generator.rb +28 -0
- data/lib/generators/raif/eval_set/templates/eval_set.rb.tt +21 -0
- data/lib/generators/raif/evals/setup/setup_generator.rb +47 -0
- data/lib/generators/raif/install/install_generator.rb +15 -0
- data/lib/generators/raif/install/templates/initializer.rb +89 -10
- data/lib/generators/raif/model_tool/model_tool_generator.rb +5 -5
- data/lib/generators/raif/model_tool/templates/model_tool.rb.tt +78 -78
- data/lib/generators/raif/model_tool/templates/model_tool_invocation_partial.html.erb.tt +1 -1
- data/lib/generators/raif/task/task_generator.rb +22 -3
- data/lib/generators/raif/task/templates/application_task.rb.tt +0 -2
- data/lib/generators/raif/task/templates/task.rb.tt +55 -59
- data/lib/generators/raif/task/templates/task_eval_set.rb.tt +54 -0
- data/lib/raif/cli/base.rb +39 -0
- data/lib/raif/cli/evals.rb +47 -0
- data/lib/raif/cli/evals_setup.rb +27 -0
- data/lib/raif/cli.rb +67 -0
- data/lib/raif/configuration.rb +57 -8
- data/lib/raif/engine.rb +8 -0
- data/lib/raif/errors/instance_dependent_schema_error.rb +8 -0
- data/lib/raif/errors/streaming_error.rb +6 -3
- data/lib/raif/errors.rb +1 -0
- data/lib/raif/evals/eval.rb +30 -0
- data/lib/raif/evals/eval_set.rb +111 -0
- data/lib/raif/evals/eval_sets/expectations.rb +53 -0
- data/lib/raif/evals/eval_sets/llm_judge_expectations.rb +255 -0
- data/lib/raif/evals/expectation_result.rb +39 -0
- data/lib/raif/evals/llm_judge.rb +32 -0
- data/lib/raif/evals/llm_judges/binary.rb +94 -0
- data/lib/raif/evals/llm_judges/comparative.rb +89 -0
- data/lib/raif/evals/llm_judges/scored.rb +63 -0
- data/lib/raif/evals/llm_judges/summarization.rb +166 -0
- data/lib/raif/evals/run.rb +202 -0
- data/lib/raif/evals/scoring_rubric.rb +174 -0
- data/lib/raif/evals.rb +26 -0
- data/lib/raif/json_schema_builder.rb +14 -0
- data/lib/raif/llm_registry.rb +218 -15
- data/lib/raif/messages.rb +180 -0
- data/lib/raif/migration_checker.rb +3 -3
- data/lib/raif/utils/colors.rb +23 -0
- data/lib/raif/utils.rb +1 -0
- data/lib/raif/version.rb +1 -1
- data/lib/raif.rb +13 -0
- data/lib/tasks/annotate_rb.rake +10 -0
- data/spec/support/current_temperature_test_tool.rb +34 -0
- data/spec/support/rspec_helpers.rb +8 -8
- data/spec/support/test_conversation.rb +1 -1
- metadata +77 -10
- data/app/models/raif/agents/re_act_agent.rb +0 -127
- data/app/models/raif/agents/re_act_step.rb +0 -33
data/config/locales/en.yml
CHANGED
|
@@ -6,10 +6,7 @@ en:
|
|
|
6
6
|
errors:
|
|
7
7
|
available_model_tools:
|
|
8
8
|
too_short: must have at least 1 tool in addition to the agent_final_answer tool
|
|
9
|
-
|
|
10
|
-
errors:
|
|
11
|
-
available_model_tools:
|
|
12
|
-
too_short: must have at least 1 tool
|
|
9
|
+
final_answer_warning: 'Warning: This is your final iteration. You must provide your final answer using the agent_final_answer tool.'
|
|
13
10
|
common:
|
|
14
11
|
send: Send
|
|
15
12
|
sources: Sources
|
|
@@ -18,6 +15,14 @@ en:
|
|
|
18
15
|
type_your_message: Type your message...
|
|
19
16
|
conversation:
|
|
20
17
|
initial_chat_message: Hello, how can I help you today?
|
|
18
|
+
conversations:
|
|
19
|
+
index:
|
|
20
|
+
no_conversations: No conversations found.
|
|
21
|
+
table:
|
|
22
|
+
actions: Actions
|
|
23
|
+
started: Started
|
|
24
|
+
view: View
|
|
25
|
+
title: Past Conversations
|
|
21
26
|
embedding_model_names:
|
|
22
27
|
bedrock_titan_embed_text_v2: AWS Bedrock Titan Text Embeddings v2
|
|
23
28
|
open_ai_text_embedding_3_large: OpenAI Text Embedding 3 Large
|
|
@@ -51,6 +56,9 @@ en:
|
|
|
51
56
|
anthropic_claude_3_5_sonnet: Anthropic Claude 3.5 Sonnet
|
|
52
57
|
anthropic_claude_3_7_sonnet: Anthropic Claude 3.7 Sonnet
|
|
53
58
|
anthropic_claude_3_opus: Anthropic Claude 3 Opus
|
|
59
|
+
anthropic_claude_4_1_opus: Anthropic Claude 4.1 Opus
|
|
60
|
+
anthropic_claude_4_5_haiku: Anthropic Claude 4.5 Haiku
|
|
61
|
+
anthropic_claude_4_5_sonnet: Anthropic Claude 4.5 Sonnet
|
|
54
62
|
anthropic_claude_4_opus: Anthropic Claude 4 Opus
|
|
55
63
|
anthropic_claude_4_sonnet: Anthropic Claude 4 Sonnet
|
|
56
64
|
bedrock_amazon_nova_lite: Amazon Nova Lite (via AWS Bedrock)
|
|
@@ -60,14 +68,26 @@ en:
|
|
|
60
68
|
bedrock_claude_3_5_sonnet: Anthropic Claude 3.5 Sonnet (via AWS Bedrock)
|
|
61
69
|
bedrock_claude_3_7_sonnet: Anthropic Claude 3.7 Sonnet (via AWS Bedrock)
|
|
62
70
|
bedrock_claude_3_opus: Anthropic Claude 3 Opus (via AWS Bedrock)
|
|
71
|
+
bedrock_claude_4_1_opus: Claude 4.1 Opus (via AWS Bedrock)
|
|
72
|
+
bedrock_claude_4_5_haiku: Anthropic Claude 4.5 Haiku (via AWS Bedrock)
|
|
73
|
+
bedrock_claude_4_5_sonnet: Anthropic Claude 4.5 Sonnet (via AWS Bedrock)
|
|
63
74
|
bedrock_claude_4_opus: Anthropic Claude 4 Opus (via AWS Bedrock)
|
|
64
75
|
bedrock_claude_4_sonnet: Anthropic Claude 4 Sonnet (via AWS Bedrock)
|
|
76
|
+
google_gemini_2_5_flash: Google Gemini 2.5 Flash
|
|
77
|
+
google_gemini_2_5_pro: Google Gemini 2.5 Pro
|
|
78
|
+
google_gemini_3_0_flash: Google Gemini 3.0 Flash
|
|
79
|
+
google_gemini_3_0_pro: Google Gemini 3.0 Pro
|
|
65
80
|
open_ai_gpt_3_5_turbo: OpenAI GPT-3.5 Turbo
|
|
66
81
|
open_ai_gpt_4_1: OpenAI GPT-4.1
|
|
67
82
|
open_ai_gpt_4_1_mini: OpenAI GPT-4.1 Mini
|
|
68
83
|
open_ai_gpt_4_1_nano: OpenAI GPT-4.1 Nano
|
|
69
84
|
open_ai_gpt_4o: OpenAI GPT-4o
|
|
70
85
|
open_ai_gpt_4o_mini: OpenAI GPT-4o Mini
|
|
86
|
+
open_ai_gpt_5: OpenAI GPT-5
|
|
87
|
+
open_ai_gpt_5_1: OpenAI GPT-5.1
|
|
88
|
+
open_ai_gpt_5_2: OpenAI GPT-5.2
|
|
89
|
+
open_ai_gpt_5_mini: OpenAI GPT-5 Mini
|
|
90
|
+
open_ai_gpt_5_nano: OpenAI GPT-5 Nano
|
|
71
91
|
open_ai_o1: OpenAI o1
|
|
72
92
|
open_ai_o1_mini: OpenAI o1 Mini
|
|
73
93
|
open_ai_o3: OpenAI o3
|
|
@@ -79,6 +99,11 @@ en:
|
|
|
79
99
|
open_ai_responses_gpt_4_1_nano: OpenAI GPT-4.1 Nano (Responses API)
|
|
80
100
|
open_ai_responses_gpt_4o: OpenAI GPT-4o (Responses API)
|
|
81
101
|
open_ai_responses_gpt_4o_mini: OpenAI GPT-4o Mini (Responses API)
|
|
102
|
+
open_ai_responses_gpt_5: OpenAI GPT-5 (Responses API)
|
|
103
|
+
open_ai_responses_gpt_5_1: OpenAI GPT-5.1 (Responses API)
|
|
104
|
+
open_ai_responses_gpt_5_2: OpenAI GPT-5.2 (Responses API)
|
|
105
|
+
open_ai_responses_gpt_5_mini: OpenAI GPT-5 Mini (Responses API)
|
|
106
|
+
open_ai_responses_gpt_5_nano: OpenAI GPT-5 Nano (Responses API)
|
|
82
107
|
open_ai_responses_o1: OpenAI o1 (Responses API)
|
|
83
108
|
open_ai_responses_o1_mini: OpenAI o1 Mini (Responses API)
|
|
84
109
|
open_ai_responses_o1_pro: OpenAI o1 Pro (Responses API)
|
|
@@ -88,9 +113,21 @@ en:
|
|
|
88
113
|
open_ai_responses_o4_mini: OpenAI o4 Mini (Responses API)
|
|
89
114
|
open_router_claude_3_7_sonnet: Anthropic Claude 3.7 Sonnet (via OpenRouter)
|
|
90
115
|
open_router_deepseek_chat_v3: DeepSeek Chat v3 (via OpenRouter)
|
|
116
|
+
open_router_deepseek_v3_1: DeepSeek v3.1 (via OpenRouter)
|
|
91
117
|
open_router_gemini_2_0_flash: Google Gemini 2.0 Flash (via OpenRouter)
|
|
118
|
+
open_router_gemini_2_5_flash: Gemini 2.5 Flash (via OpenRouter)
|
|
119
|
+
open_router_gemini_2_5_pro: Gemini 2.5 Pro (via OpenRouter)
|
|
120
|
+
open_router_gemini_3_pro_preview: Gemini 3 Pro Preview (via OpenRouter)
|
|
121
|
+
open_router_grok_4: Grok 4 (via OpenRouter)
|
|
122
|
+
open_router_grok_4_1_fast: Grok 4.1 Fast (via OpenRouter)
|
|
123
|
+
open_router_kimi_k2_thinking: Kimi K2 Thinking (via OpenRouter)
|
|
92
124
|
open_router_llama_3_1_8b_instruct: Meta Llama 3.1 8B Instruct (via OpenRouter)
|
|
93
125
|
open_router_llama_3_3_70b_instruct: Meta Llama 3.3 70B Instruct (via OpenRouter)
|
|
94
126
|
open_router_llama_4_maverick: Meta Llama 4 Maverick (via OpenRouter)
|
|
95
127
|
open_router_llama_4_scout: Meta Llama 4 Scout (via OpenRouter)
|
|
128
|
+
open_router_minimax_m2: Minimax M2 (via OpenRouter)
|
|
129
|
+
open_router_mistral_large_3_2512: Mistral Large 3 (via OpenRouter)
|
|
130
|
+
open_router_mistral_small_3_2_24b: Mistral Small 3.2 24B (via OpenRouter)
|
|
131
|
+
open_router_open_ai_gpt_oss_120b: OpenAI GPT-OSS 120B (via OpenRouter)
|
|
132
|
+
open_router_open_ai_gpt_oss_20b: OpenAI GPT-OSS 20B (via OpenRouter)
|
|
96
133
|
raif_test_llm: Raif Test LLM
|
data/config/routes.rb
CHANGED
|
@@ -17,6 +17,7 @@ Raif::Engine.routes.draw do
|
|
|
17
17
|
|
|
18
18
|
namespace :stats do
|
|
19
19
|
resources :tasks, only: [:index]
|
|
20
|
+
resources :model_tool_invocations, only: [:index]
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
resources :tasks, only: [:index, :show]
|
|
@@ -24,5 +25,6 @@ Raif::Engine.routes.draw do
|
|
|
24
25
|
resources :model_completions, only: [:index, :show]
|
|
25
26
|
resources :agents, only: [:index, :show]
|
|
26
27
|
resources :model_tool_invocations, only: [:index, :show]
|
|
28
|
+
resource :config, only: [:show]
|
|
27
29
|
end
|
|
28
30
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddTaskRunArgsToRaifTasks < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
json_column_type = if connection.adapter_name.downcase.include?("postgresql")
|
|
6
|
+
:jsonb
|
|
7
|
+
else
|
|
8
|
+
:json
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_column :raif_tasks, :task_run_args, json_column_type
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddRunWithToRaifAgents < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
json_column_type = if connection.adapter_name.downcase.include?("postgresql")
|
|
6
|
+
:jsonb
|
|
7
|
+
else
|
|
8
|
+
:json
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_column :raif_agents, :run_with, json_column_type
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddLlmMessagesMaxLengthToRaifConversations < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
add_column :raif_conversations, :llm_messages_max_length, :integer
|
|
6
|
+
|
|
7
|
+
reversible do |dir|
|
|
8
|
+
dir.up do
|
|
9
|
+
# Set default value for existing conversations
|
|
10
|
+
execute "UPDATE raif_conversations SET llm_messages_max_length = 50 WHERE llm_messages_max_length IS NULL"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddFailureTrackingToRaifModelCompletions < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
add_column :raif_model_completions, :failed_at, :datetime
|
|
6
|
+
add_column :raif_model_completions, :failure_error, :string
|
|
7
|
+
add_column :raif_model_completions, :failure_reason, :text
|
|
8
|
+
add_index :raif_model_completions, :failed_at
|
|
9
|
+
end
|
|
10
|
+
end
|
data/exe/raif
ADDED
|
@@ -1,32 +1,47 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../base_generator"
|
|
4
|
+
|
|
3
5
|
module Raif
|
|
4
6
|
module Generators
|
|
5
|
-
class AgentGenerator <
|
|
7
|
+
class AgentGenerator < BaseGenerator
|
|
6
8
|
source_root File.expand_path("templates", __dir__)
|
|
7
9
|
desc "Creates a new Raif::Agent subclass in app/models/raif/agents"
|
|
8
10
|
|
|
11
|
+
class_option :skip_eval_set,
|
|
12
|
+
type: :boolean,
|
|
13
|
+
default: false,
|
|
14
|
+
desc: "Skip generating the corresponding eval set"
|
|
15
|
+
|
|
9
16
|
def create_application_agent
|
|
10
17
|
template "application_agent.rb.tt", "app/models/raif/application_agent.rb" unless File.exist?("app/models/raif/application_agent.rb")
|
|
11
18
|
end
|
|
12
19
|
|
|
13
20
|
def create_agent
|
|
14
|
-
template "agent.rb.tt", "app/models/raif/agents
|
|
21
|
+
template "agent.rb.tt", File.join("app/models/raif/agents", class_path, "#{file_name}.rb")
|
|
15
22
|
end
|
|
16
23
|
|
|
17
24
|
def create_directory
|
|
18
25
|
empty_directory "app/models/raif/agents" unless File.directory?("app/models/raif/agents")
|
|
19
26
|
end
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
def create_eval_set
|
|
29
|
+
return if options[:skip_eval_set]
|
|
30
|
+
|
|
31
|
+
template "agent_eval_set.rb.tt", eval_set_file_path
|
|
32
|
+
end
|
|
22
33
|
|
|
23
|
-
def
|
|
24
|
-
|
|
34
|
+
def show_instructions
|
|
35
|
+
say "\nAgent created!"
|
|
36
|
+
say ""
|
|
25
37
|
end
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def eval_set_file_path
|
|
42
|
+
File.join("raif_evals", "eval_sets", "agents", class_path, "#{file_name}_eval_set.rb")
|
|
29
43
|
end
|
|
44
|
+
|
|
30
45
|
end
|
|
31
46
|
end
|
|
32
47
|
end
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
<% raif_module_namespacing(["Agents"]) do -%>
|
|
2
|
+
class <%= class_name.demodulize %> < Raif::ApplicationAgent
|
|
3
|
+
# If you want to always include a certain set of model tools with this agent type,
|
|
4
|
+
# uncomment this callback to populate the available_model_tools attribute with your desired model tools.
|
|
5
|
+
# def populate_default_model_tools
|
|
6
|
+
# self.available_model_tools = [
|
|
7
|
+
# Raif::ModelTools::WikipediaSearch,
|
|
8
|
+
# Raif::ModelTools::FetchUrl
|
|
9
|
+
# ]
|
|
10
|
+
# end
|
|
2
11
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
# def populate_default_model_tools
|
|
9
|
-
# self.available_model_tools ||= [
|
|
10
|
-
# Raif::ModelTools::WikipediaSearchTool,
|
|
11
|
-
# Raif::ModelTools::FetchUrlTool
|
|
12
|
-
# ]
|
|
13
|
-
# end
|
|
14
|
-
|
|
15
|
-
# Enter your agent's system prompt here. Alternatively, you can change your agent's superclass
|
|
16
|
-
# to an existing agent types (like Raif::Agents::ReActAgent) to utilize an existing system prompt.
|
|
17
|
-
def build_system_prompt
|
|
18
|
-
# TODO: Implement your system prompt here
|
|
19
|
-
end
|
|
12
|
+
# Enter your agent's system prompt here. Alternatively, you can change your agent's superclass
|
|
13
|
+
# to an existing agent types (like Raif::Agents::NativeToolCallingAgent) to utilize an existing system prompt.
|
|
14
|
+
def build_system_prompt
|
|
15
|
+
# TODO: Implement your system prompt here
|
|
16
|
+
end
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
end
|
|
18
|
+
# Each iteration of the agent loop will generate a new Raif::ModelCompletion record and
|
|
19
|
+
# then call this method with it as an argument.
|
|
20
|
+
def process_iteration_model_completion(model_completion)
|
|
21
|
+
# TODO: Implement your iteration processing here
|
|
26
22
|
end
|
|
27
23
|
end
|
|
28
|
-
end
|
|
24
|
+
<% end -%>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<% raif_module_namespacing(["Evals", "Agents"]) do -%>
|
|
2
|
+
class <%= class_name.demodulize %>EvalSet < Raif::Evals::EvalSet
|
|
3
|
+
# Run this eval set with:
|
|
4
|
+
# bundle exec raif evals ./<%= eval_set_file_path %>
|
|
5
|
+
|
|
6
|
+
# Setup method runs before each eval
|
|
7
|
+
setup do
|
|
8
|
+
# Common setup code
|
|
9
|
+
# @user = User.create!(email: "test@example.com")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Teardown runs after each eval
|
|
13
|
+
teardown do
|
|
14
|
+
# Cleanup code
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
eval "<%= class_name %> completes task successfully" do
|
|
18
|
+
# agent = Raif::Agents::<%= class_name %>.create!(
|
|
19
|
+
# creator: @user,
|
|
20
|
+
# task: "Your specific task here",
|
|
21
|
+
# available_model_tools: [] # Add your tools here if needed
|
|
22
|
+
# )
|
|
23
|
+
|
|
24
|
+
# agent.run!
|
|
25
|
+
|
|
26
|
+
# expect "agent completes successfully" do
|
|
27
|
+
# agent.completed?
|
|
28
|
+
# end
|
|
29
|
+
|
|
30
|
+
# expect "produces expected output" do
|
|
31
|
+
# agent.final_answer.include?("expected content")
|
|
32
|
+
# end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
eval "<%= class_name %> uses tools correctly" do
|
|
36
|
+
# agent = Raif::Agents::<%= class_name %>.create!(
|
|
37
|
+
# creator: @user,
|
|
38
|
+
# task: "A task that requires tool usage",
|
|
39
|
+
# available_model_tools: ["expected_tool_name"]
|
|
40
|
+
# )
|
|
41
|
+
|
|
42
|
+
# agent.run!
|
|
43
|
+
|
|
44
|
+
# expect_tool_invocation(agent, "expected_tool_name")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
<% end -%>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Raif
|
|
4
|
+
class BaseGenerator < Rails::Generators::NamedBase
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def raif_module_namespacing(intermediate_modules = [], &block)
|
|
8
|
+
content = capture(&block).rstrip
|
|
9
|
+
|
|
10
|
+
modules_names = intermediate_modules + class_path.map(&:camelize)
|
|
11
|
+
modules_names.reverse.each do |module_name|
|
|
12
|
+
content = indent "module #{module_name}\n#{content}\nend", 2
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
concat("module Raif\n#{content}\nend\n")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../base_generator"
|
|
4
|
+
|
|
3
5
|
module Raif
|
|
4
6
|
module Generators
|
|
5
|
-
class ConversationGenerator <
|
|
7
|
+
class ConversationGenerator < BaseGenerator
|
|
6
8
|
source_root File.expand_path("templates", __dir__)
|
|
7
9
|
|
|
8
10
|
desc "Creates a new conversation type in the app/models/raif/conversations directory"
|
|
@@ -12,19 +14,30 @@ module Raif
|
|
|
12
14
|
default: "text",
|
|
13
15
|
desc: "Response format for the task (text, html, or json)"
|
|
14
16
|
|
|
17
|
+
class_option :skip_eval_set,
|
|
18
|
+
type: :boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
desc: "Skip generating the corresponding eval set"
|
|
21
|
+
|
|
15
22
|
def create_application_conversation
|
|
16
23
|
template "application_conversation.rb.tt",
|
|
17
24
|
"app/models/raif/application_conversation.rb" unless File.exist?("app/models/raif/application_conversation.rb")
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
def create_conversation_file
|
|
21
|
-
template "conversation.rb.tt", File.join("app/models/raif/conversations", "#{file_name}.rb")
|
|
28
|
+
template "conversation.rb.tt", File.join("app/models/raif/conversations", class_path, "#{file_name}.rb")
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
def create_directory
|
|
25
32
|
empty_directory "app/models/raif/conversations" unless File.directory?("app/models/raif/conversations")
|
|
26
33
|
end
|
|
27
34
|
|
|
35
|
+
def create_eval_set
|
|
36
|
+
return if options[:skip_eval_set]
|
|
37
|
+
|
|
38
|
+
template "conversation_eval_set.rb.tt", eval_set_file_path
|
|
39
|
+
end
|
|
40
|
+
|
|
28
41
|
def success_message
|
|
29
42
|
say_status :success, "Conversation type created successfully", :green
|
|
30
43
|
say "\nYou can now implement your conversation type in:"
|
|
@@ -32,6 +45,12 @@ module Raif
|
|
|
32
45
|
say "\nDon't forget to add it to the config.conversation_types in your Raif configuration"
|
|
33
46
|
say "For example: config.conversation_types += ['Raif::Conversations::#{class_name}']\n\n"
|
|
34
47
|
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def eval_set_file_path
|
|
52
|
+
File.join("raif_evals", "eval_sets", "conversations", class_path, "#{file_name}_eval_set.rb")
|
|
53
|
+
end
|
|
35
54
|
end
|
|
36
55
|
end
|
|
37
56
|
end
|
|
@@ -1,39 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
<% raif_module_namespacing(["Conversations"]) do -%>
|
|
2
|
+
class <%= class_name.demodulize %> < Raif::ApplicationConversation
|
|
3
|
+
# Set the response format for the conversation. Options are :html, :text, or :json.
|
|
4
|
+
# If you set this to something other than :text, make sure to include instructions to the model in your system prompt
|
|
5
|
+
llm_response_format :<%= options[:response_format] %>
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# Set the response format for the task. Options are :html, :text, or :json.
|
|
7
|
-
# If you set this to something other than :text, make sure to include instructions to the model in your system prompt
|
|
8
|
-
llm_response_format :<%= options[:response_format] %>
|
|
7
|
+
# If you want to always include a certain set of model tools with this conversation type,
|
|
8
|
+
# uncomment this callback to populate the available_model_tools attribute with your desired model tools.
|
|
9
|
+
# before_create -> { self.available_model_tools = ["Raif::ModelTools::Example"] }
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
# Use this callback to run custom logic before prompting the model for an entry response.
|
|
12
|
+
# The block receives the entry as an argument, and `self` is the conversation instance.
|
|
13
|
+
# before_prompt_model_for_entry_response do |entry|
|
|
14
|
+
# # Custom logic here
|
|
15
|
+
# end
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
# Override the methods below to customize the system prompt for this conversation type.
|
|
18
|
+
# def system_prompt_intro
|
|
19
|
+
# Raif.config.conversation_system_prompt_intro
|
|
20
|
+
# end
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
# def build_system_prompt
|
|
23
|
+
# <<~PROMPT
|
|
24
|
+
# #{system_prompt_intro}
|
|
25
|
+
# #{system_prompt_language_preference}
|
|
26
|
+
# PROMPT
|
|
27
|
+
# end
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
# Override this method to set the initial message shown to the user.
|
|
30
|
+
# def initial_chat_message
|
|
31
|
+
# I18n.t("#{self.class.name.underscore.gsub("/", ".")}.initial_chat_message")
|
|
32
|
+
# end
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
34
|
+
# This method will be called when receing a model response to a Raif::ConversationEntry
|
|
35
|
+
# By default, it just passes the model response message through, but you can override
|
|
36
|
+
# for custom response message processing
|
|
37
|
+
# def process_model_response_message(message:, entry:)
|
|
38
|
+
# message
|
|
39
|
+
# end
|
|
38
40
|
end
|
|
39
|
-
end
|
|
41
|
+
<% end -%>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<% raif_module_namespacing(["Evals", "Conversations"]) do -%>
|
|
2
|
+
class <%= class_name.demodulize %>EvalSet < Raif::Evals::EvalSet
|
|
3
|
+
# Run this eval set with:
|
|
4
|
+
# bundle exec raif evals ./<%= eval_set_file_path %>
|
|
5
|
+
|
|
6
|
+
# Setup method runs before each eval
|
|
7
|
+
setup do
|
|
8
|
+
# Common setup code
|
|
9
|
+
# @user = User.create!(email: "test@example.com")
|
|
10
|
+
# @conversation = Raif::Conversations::<%= class_name %>.create!(creator: @user)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Teardown runs after each eval
|
|
14
|
+
teardown do
|
|
15
|
+
# Cleanup code
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
eval "<%= class_name %> responds appropriately to user greeting" do
|
|
19
|
+
# entry = @conversation.entries.create!(
|
|
20
|
+
# user_message: "Hello, how are you?",
|
|
21
|
+
# creator: @user
|
|
22
|
+
# )
|
|
23
|
+
|
|
24
|
+
# entry.process_entry!
|
|
25
|
+
|
|
26
|
+
# expect "generates a response" do
|
|
27
|
+
# entry.model_response_message.present?
|
|
28
|
+
# end
|
|
29
|
+
|
|
30
|
+
# expect "response is friendly" do
|
|
31
|
+
# entry.model_response_message.match?(/hello|hi|greetings/i)
|
|
32
|
+
# end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
eval "<%= class_name %> maintains conversation context" do
|
|
36
|
+
# First message establishes context
|
|
37
|
+
# first_entry = @conversation.entries.create!(
|
|
38
|
+
# user_message: "My name is Alice",
|
|
39
|
+
# creator: @user
|
|
40
|
+
# )
|
|
41
|
+
# first_entry.process_entry!
|
|
42
|
+
|
|
43
|
+
# Second message references context
|
|
44
|
+
# second_entry = @conversation.entries.create!(
|
|
45
|
+
# user_message: "What's my name?",
|
|
46
|
+
# creator: @user
|
|
47
|
+
# )
|
|
48
|
+
# second_entry.process_entry!
|
|
49
|
+
|
|
50
|
+
# expect "remembers the user's name" do
|
|
51
|
+
# second_entry.model_response_message.include?("Alice")
|
|
52
|
+
# end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
eval "<%= class_name %> handles tool invocations correctly" do
|
|
56
|
+
# Test if your conversation uses tools
|
|
57
|
+
# @conversation.update!(available_model_tools: [ "Raif::ModelTools::FetchUrl" ])
|
|
58
|
+
|
|
59
|
+
# entry = @conversation.entries.create!(
|
|
60
|
+
# user_message: "What can you tell me about the content of https://en.wikipedia.org/wiki/Moon",
|
|
61
|
+
# creator: @user
|
|
62
|
+
# )
|
|
63
|
+
|
|
64
|
+
# entry.process_entry!
|
|
65
|
+
|
|
66
|
+
# expect_tool_invocation(entry, "Raif::ModelTools::FetchUrl", with: { url: "https://en.wikipedia.org/wiki/Moon" })
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
<% end -%>
|