raif 1.2.1 → 1.3.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 +29 -935
- data/app/assets/builds/raif_admin.css +5 -1
- data/app/assets/images/raif-logo-white.svg +8 -0
- data/app/assets/stylesheets/raif_admin.scss +4 -0
- data/app/jobs/raif/conversation_entry_job.rb +1 -1
- data/app/models/raif/agents/re_act_step.rb +1 -2
- data/app/models/raif/concerns/has_llm.rb +1 -1
- data/app/models/raif/concerns/task_run_args.rb +62 -0
- data/app/models/raif/conversation.rb +8 -0
- data/app/models/raif/conversation_entry.rb +6 -9
- data/app/models/raif/llm.rb +1 -1
- data/app/models/raif/llms/open_router.rb +47 -4
- data/app/models/raif/task.rb +22 -9
- data/app/views/layouts/raif/admin.html.erb +3 -1
- data/app/views/raif/conversation_entries/_form.html.erb +1 -1
- data/app/views/raif/conversations/_full_conversation.html.erb +3 -6
- data/app/views/raif/conversations/_initial_chat_message.html.erb +5 -0
- data/config/locales/en.yml +8 -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/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 +0 -2
- 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 +29 -33
- 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 +14 -3
- data/lib/generators/raif/model_tool/model_tool_generator.rb +5 -2
- data/lib/generators/raif/model_tool/templates/model_tool.rb.tt +78 -76
- data/lib/generators/raif/model_tool/templates/model_tool_invocation_partial.html.erb.tt +10 -0
- 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 +23 -9
- data/lib/raif/engine.rb +2 -1
- 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 +201 -0
- data/lib/raif/evals/scoring_rubric.rb +174 -0
- data/lib/raif/evals.rb +26 -0
- data/lib/raif/llm_registry.rb +33 -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 +4 -0
- data/spec/support/current_temperature_test_tool.rb +34 -0
- data/spec/support/test_conversation.rb +1 -1
- metadata +37 -3
@@ -57,6 +57,9 @@ body.raif-admin {
|
|
57
57
|
font-size: 0.9375rem;
|
58
58
|
}
|
59
59
|
|
60
|
+
.raif-admin .navbar-brand-logo {
|
61
|
+
width: 100px;
|
62
|
+
}
|
60
63
|
.raif-admin h1,
|
61
64
|
.raif-admin h2,
|
62
65
|
.raif-admin h3,
|
@@ -89,6 +92,7 @@ body.raif-admin {
|
|
89
92
|
box-shadow: inset -1px 0 0 #e2e8f0;
|
90
93
|
background-color: white !important;
|
91
94
|
padding-top: 1rem;
|
95
|
+
height: 100vh;
|
92
96
|
}
|
93
97
|
.raif-admin .sidebar .nav-link {
|
94
98
|
color: #525f7f;
|
@@ -263,4 +267,4 @@ body.raif-admin {
|
|
263
267
|
}
|
264
268
|
}
|
265
269
|
|
266
|
-
/*# sourceMappingURL=data:application/json;base64,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ZCxxQkFBcUI7QUFDdkI7QUFDQTtFQUNFLHlCQUF5QjtFQUN6QixrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLGdCQUFnQjtFQUNoQixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLHlCQUF5QjtBQUMzQjtBQUNBO0VBQ0UscUJBQXFCO0FBQ3ZCO0FBQ0E7RUFDRSxxQkFBcUI7RUFDckIsYUFBYTtBQUNmO0FBQ0E7RUFDRSwyQkFBMkI7RUFDM0IsNEJBQTRCO0FBQzlCO0FBQ0E7RUFDRSw4QkFBOEI7RUFDOUIsK0JBQStCO0FBQ2pDO0FBQ0E7RUFDRSxjQUFjO0VBQ2QscUJBQXFCO0VBQ3JCLHVCQUF1QjtBQUN6QjtBQUNBO0VBQ0UseUJBQXlCO0VBQ3pCLHFCQUFxQjtFQUNyQixjQUFjO0FBQ2hCO0FBQ0E7RUFDRSx5QkFBeUI7RUFDekIscUJBQXFCO0FBQ3ZCO0FBQ0E7RUFDRSxjQUFjO0FBQ2hCO0FBQ0E7RUFDRSxZQUFZO0VBQ1osa0JBQWtCO0VBQ2xCLDJFQUEyRTtBQUM3RTtBQUNBO0VBQ0UseUNBQXlDO0VBQ3pDLGNBQWM7QUFDaEI7QUFDQTtFQUNFLHlCQUF5QjtBQUMzQjtBQUNBO0VBQ0U7SUFDRSxnQkFBZ0I7SUFDaEIsWUFBWTtJQUNaLGNBQWM7RUFDaEI7RUFDQTtJQUNFLFNBQVM7SUFDVCxnQkFBZ0I7RUFDbEI7RUFDQTtJQUNFLGlCQUFpQjtFQUNuQjtBQUNGIiwiZmlsZSI6InJhaWZfYWRtaW4uY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmNvbnZlcnNhdGlvbi1jYXJkIC5jYXJkLWJvZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmOWZhO1xufVxuXG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2Uge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2U6bGFzdC1jaGlsZCB7XG4gIG1hcmdpbi1ib3R0b206IDA7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UudXNlciB7XG4gIGJvcmRlci1sZWZ0OiAzcHggc29saWQgIzNiODJmNjtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZS51c2VyIC5tZXNzYWdlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xufVxuLmNvbnZlcnNhdGlvbi1oaXN0b3J5IC5tZXNzYWdlLmFzc2lzdGFudCB7XG4gIGJvcmRlci1sZWZ0OiAzcHggc29saWQgcmdiKDI1LCAxMzUsIDg0KTtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZS5hc3Npc3RhbnQgLm1lc3NhZ2UtY29udGVudCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYigyMzIsIDI1NSwgMjQ0KTtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZSAubWVzc2FnZS1jb250ZW50IHtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICBib3gtc2hhZG93OiAwIDFweCAycHggcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgY29sb3I6ICMxZTNhOGE7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UgLm1lc3NhZ2UtY29udGVudCBjb2RlIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIGZvbnQtZmFtaWx5OiBTRk1vbm8tUmVndWxhciwgTWVubG8sIE1vbmFjbywgQ29uc29sYXMsIFwiTGliZXJhdGlvbiBNb25vXCIsIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlO1xuICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG4gIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XG4gIGJhY2tncm91bmQ6IG5vbmU7XG4gIGJvcmRlcjogbm9uZTtcbiAgcGFkZGluZzogMDtcbiAgY29sb3I6IGluaGVyaXQ7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UgLm1lc3NhZ2UtY29udGVudDpsYXN0LWNoaWxkIHtcbiAgbWFyZ2luLWJvdHRvbTogMDtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZSAubWVzc2FnZS1jb250ZW50IC5tZXNzYWdlLWxhYmVsIHtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICBmb250LXNpemU6IDAuNzVyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7XG4gIGxldHRlci1zcGFjaW5nOiAwLjVweDtcbn1cblxuYm9keS5yYWlmLWFkbWluIHtcbiAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIEJsaW5rTWFjU3lzdGVtRm9udCwgXCJTZWdvZSBVSVwiLCBSb2JvdG8sIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7XG4gIGNvbG9yOiAjNTI1ZjdmO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmYWZjO1xuICBsaW5lLWhlaWdodDogMS41O1xuICBmb250LXNpemU6IDAuOTM3NXJlbTtcbn1cblxuLnJhaWYtYWRtaW4gaDEsXG4ucmFpZi1hZG1pbiBoMixcbi5yYWlmLWFkbWluIGgzLFxuLnJhaWYtYWRtaW4gaDQsXG4ucmFpZi1hZG1pbiBoNSxcbi5yYWlmLWFkbWluIGg2IHtcbiAgY29sb3I6ICMxZTNhOGE7XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG59XG4ucmFpZi1hZG1pbiBhIHtcbiAgY29sb3I6ICMzYjgyZjY7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTtcbn1cbi5yYWlmLWFkbWluIGE6aG92ZXIge1xuICBjb2xvcjogcmdiKDExLjE1MTIxOTUxMjIsIDk5LjEyMTk1MTIxOTUsIDI0Mi44NDg3ODA0ODc4KTtcbn1cbi5yYWlmLWFkbWluIC5uYXZiYXIge1xuICBib3gtc2hhZG93OiAwIDJweCA1cHggMCByZ2JhKDUwLCA1MCwgOTMsIDAuMSk7XG4gIHBhZGRpbmc6IDAuNzVyZW0gMS41cmVtO1xufVxuLnJhaWYtYWRtaW4gLm5hdmJhci5uYXZiYXItZGFyayB7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMxZTNhOGEsIHJnYigyMC44OTI4NTcxNDI5LCA0MC4zOTI4NTcxNDI5LCA5Ni4xMDcxNDI4NTcxKSkgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5uYXZiYXIgLm5hdmJhci1icmFuZCB7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7XG4gIGxldHRlci1zcGFjaW5nOiAwLjVweDtcbn1cbi5yYWlmLWFkbWluIC5zaWRlYmFyIHtcbiAgYm94LXNoYWRvdzogaW5zZXQgLTFweCAwIDAgI2UyZThmMDtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGUgIWltcG9ydGFudDtcbiAgcGFkZGluZy10b3A6IDFyZW07XG59XG4ucmFpZi1hZG1pbiAuc2lkZWJhciAubmF2LWxpbmsge1xuICBjb2xvcjogIzUyNWY3ZjtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBtYXJnaW46IDAuMjVyZW0gMC43NXJlbTtcbiAgcGFkZGluZzogMC41cmVtIDAuNzVyZW07XG59XG4ucmFpZi1hZG1pbiAuc2lkZWJhciAubmF2LWxpbms6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xufVxuLnJhaWYtYWRtaW4gLnNpZGViYXIgLm5hdi1saW5rLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjEpO1xuICBjb2xvcjogIzNiODJmNjtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbn1cbi5yYWlmLWFkbWluIG1haW4ge1xuICBwYWRkaW5nLXRvcDogMS41cmVtO1xuICBwYWRkaW5nLWJvdHRvbTogM3JlbTtcbn1cbi5yYWlmLWFkbWluIC5jYXJkIHtcbiAgYm9yZGVyOiBub25lO1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGJveC1zaGFkb3c6IDAgNHB4IDZweCByZ2JhKDUwLCA1MCwgOTMsIDAuMTEpLCAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjA4KTtcbiAgbWFyZ2luLWJvdHRvbTogMS41cmVtO1xuICBvdmVyZmxvdzogaGlkZGVuO1xufVxuLnJhaWYtYWRtaW4gLmNhcmQgLmNhcmQtaGVhZGVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZTJlOGYwO1xuICBwYWRkaW5nOiAxcmVtIDEuMjVyZW07XG59XG4ucmFpZi1hZG1pbiAuY2FyZCAuY2FyZC1oZWFkZXIgaDUge1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBmb250LXNpemU6IDFyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG59XG4ucmFpZi1hZG1pbiAuY2FyZCAuY2FyZC1ib2R5IHtcbiAgcGFkZGluZzogMS4yNXJlbTtcbn1cbi5yYWlmLWFkbWluIC5jYXJkLmNvbnZlcnNhdGlvbi1jYXJkIC5jYXJkLWJvZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmOWZhO1xufVxuLnJhaWYtYWRtaW4gLnRhYmxlIHtcbiAgbWFyZ2luLWJvdHRvbTogMDtcbn1cbi5yYWlmLWFkbWluIC50YWJsZSB0aCB7XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIGNvbG9yOiAjMWUzYThhO1xuICBib3JkZXItdG9wOiBub25lO1xuICBwYWRkaW5nOiAxcmVtIDAuNzVyZW07XG4gIGZvbnQtc2l6ZTogMC44MTI1cmVtO1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBsZXR0ZXItc3BhY2luZzogMC41cHg7XG59XG4ucmFpZi1hZG1pbiAudGFibGUgdGQge1xuICBwYWRkaW5nOiAxcmVtIDAuNzVyZW07XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG4gIGJvcmRlci1jb2xvcjogI2UyZThmMDtcbn1cbi5yYWlmLWFkbWluIC50YWJsZS50YWJsZS1ob3ZlciB0Ym9keSB0cjpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmMGY5ZmY7XG59XG4ucmFpZi1hZG1pbiAudGFibGUudGFibGUtc3RyaXBlZCB0Ym9keSB0cjpudGgtb2YtdHlwZShvZGQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0OSwgMjU1LCAwLjUpO1xufVxuLnJhaWYtYWRtaW4gLnRhYmxlLXJlc3BvbnNpdmUge1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGJveC1zaGFkb3c6IDAgNHB4IDZweCByZ2JhKDUwLCA1MCwgOTMsIDAuMTEpLCAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjA4KTtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG4ucmFpZi1hZG1pbiAuYmFkZ2Uge1xuICBmb250LXdlaWdodDogNTAwO1xuICBwYWRkaW5nOiAwLjRlbSAwLjY1ZW07XG4gIGZvbnQtc2l6ZTogMC43NWVtO1xuICBib3JkZXItcmFkaXVzOiA1MHJlbTtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy1zdWNjZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzBlYTVlOSAhaW1wb3J0YW50O1xufVxuLnJhaWYtYWRtaW4gLmJhZGdlLmJnLWRhbmdlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZjQ0NDQgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy13YXJuaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2Y1OWUwYiAhaW1wb3J0YW50O1xuICBjb2xvcjogd2hpdGUgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy1zZWNvbmRhcnkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjODg5OGFhICFpbXBvcnRhbnQ7XG59XG4ucmFpZi1hZG1pbiAuYnRuIHtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTtcbiAgYm94LXNoYWRvdzogMCA0cHggNnB4IHJnYmEoNTAsIDUwLCA5MywgMC4xMSksIDAgMXB4IDNweCByZ2JhKDAsIDAsIDAsIDAuMDgpO1xufVxuLnJhaWYtYWRtaW4gLmJ0bi5idG4tb3V0bGluZS1zZWNvbmRhcnkge1xuICBjb2xvcjogIzUyNWY3ZjtcbiAgYm9yZGVyLWNvbG9yOiAjZTJlOGYwO1xufVxuLnJhaWYtYWRtaW4gLmJ0bi5idG4tb3V0bGluZS1zZWNvbmRhcnk6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xuICBjb2xvcjogIzFlM2E4YTtcbiAgYm9yZGVyLWNvbG9yOiAjZTJlOGYwO1xufVxuLnJhaWYtYWRtaW4gcHJlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YwZjlmZjtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBwYWRkaW5nOiAxcmVtO1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBmb250LXNpemU6IDAuODc1cmVtO1xuICBjb2xvcjogIzFlM2E4YTtcbiAgYm9yZGVyOiAxcHggc29saWQgI2UyZThmMDtcbn1cbi5yYWlmLWFkbWluIC5wcmUtd3JhcCB7XG4gIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcbn1cbi5yYWlmLWFkbWluIC5saXN0LWdyb3VwLWl0ZW0ge1xuICBib3JkZXItY29sb3I6ICNlMmU4ZjA7XG4gIHBhZGRpbmc6IDFyZW07XG59XG4ucmFpZi1hZG1pbiAubGlzdC1ncm91cC1pdGVtOmZpcnN0LWNoaWxkIHtcbiAgYm9yZGVyLXRvcC1sZWZ0LXJhZGl1czogNHB4O1xuICBib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogNHB4O1xufVxuLnJhaWYtYWRtaW4gLmxpc3QtZ3JvdXAtaXRlbTpsYXN0LWNoaWxkIHtcbiAgYm9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czogNHB4O1xuICBib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czogNHB4O1xufVxuLnJhaWYtYWRtaW4gLnBhZ2luYXRpb24gLnBhZ2UtbGluayB7XG4gIGNvbG9yOiAjNTI1ZjdmO1xuICBib3JkZXItY29sb3I6ICNlMmU4ZjA7XG4gIHBhZGRpbmc6IDAuNXJlbSAwLjc1cmVtO1xufVxuLnJhaWYtYWRtaW4gLnBhZ2luYXRpb24gLnBhZ2UtbGluazpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmMGY5ZmY7XG4gIGJvcmRlci1jb2xvcjogI2UyZThmMDtcbiAgY29sb3I6ICMxZTNhOGE7XG59XG4ucmFpZi1hZG1pbiAucGFnaW5hdGlvbiAucGFnZS1pdGVtLmFjdGl2ZSAucGFnZS1saW5rIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzNiODJmNjtcbiAgYm9yZGVyLWNvbG9yOiAjM2I4MmY2O1xufVxuLnJhaWYtYWRtaW4gLnJvdy5tYi0zIC5jb2wtbWQtMyBzdHJvbmcge1xuICBjb2xvcjogIzFlM2E4YTtcbn1cbi5yYWlmLWFkbWluIC5hbGVydCB7XG4gIGJvcmRlcjogbm9uZTtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBib3gtc2hhZG93OiAwIDRweCA2cHggcmdiYSg1MCwgNTAsIDkzLCAwLjExKSwgMCAxcHggM3B4IHJnYmEoMCwgMCwgMCwgMC4wOCk7XG59XG4ucmFpZi1hZG1pbiAuYWxlcnQuYWxlcnQtaW5mbyB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjEpO1xuICBjb2xvcjogIzNiODJmNjtcbn1cbi5yYWlmLWFkbWluIC50ZXh0LW11dGVkIHtcbiAgY29sb3I6ICM4ODk4YWEgIWltcG9ydGFudDtcbn1cbkBtZWRpYSAobWF4LXdpZHRoOiA3NjcuOThweCkge1xuICAucmFpZi1hZG1pbiAuc2lkZWJhciB7XG4gICAgcG9zaXRpb246IHN0YXRpYztcbiAgICBoZWlnaHQ6IGF1dG87XG4gICAgcGFkZGluZy10b3A6IDA7XG4gIH1cbiAgLnJhaWYtYWRtaW4gLnNpZGViYXIgLm5hdi1saW5rIHtcbiAgICBtYXJnaW46IDA7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbiAgfVxuICAucmFpZi1hZG1pbiBtYWluIHtcbiAgICBwYWRkaW5nLXRvcDogMXJlbTtcbiAgfVxufVxuIl19 */
|
270
|
+
/*# sourceMappingURL=data:application/json;base64,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QUNBO0VBQ0UseUJBQXlCO0VBQ3pCLGNBQWM7RUFDZCxxQkFBcUI7QUFDdkI7QUFDQTtFQUNFLHlCQUF5QjtFQUN6QixrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLGdCQUFnQjtFQUNoQixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLHlCQUF5QjtBQUMzQjtBQUNBO0VBQ0UscUJBQXFCO0FBQ3ZCO0FBQ0E7RUFDRSxxQkFBcUI7RUFDckIsYUFBYTtBQUNmO0FBQ0E7RUFDRSwyQkFBMkI7RUFDM0IsNEJBQTRCO0FBQzlCO0FBQ0E7RUFDRSw4QkFBOEI7RUFDOUIsK0JBQStCO0FBQ2pDO0FBQ0E7RUFDRSxjQUFjO0VBQ2QscUJBQXFCO0VBQ3JCLHVCQUF1QjtBQUN6QjtBQUNBO0VBQ0UseUJBQXlCO0VBQ3pCLHFCQUFxQjtFQUNyQixjQUFjO0FBQ2hCO0FBQ0E7RUFDRSx5QkFBeUI7RUFDekIscUJBQXFCO0FBQ3ZCO0FBQ0E7RUFDRSxjQUFjO0FBQ2hCO0FBQ0E7RUFDRSxZQUFZO0VBQ1osa0JBQWtCO0VBQ2xCLDJFQUEyRTtBQUM3RTtBQUNBO0VBQ0UseUNBQXlDO0VBQ3pDLGNBQWM7QUFDaEI7QUFDQTtFQUNFLHlCQUF5QjtBQUMzQjtBQUNBO0VBQ0U7SUFDRSxnQkFBZ0I7SUFDaEIsWUFBWTtJQUNaLGNBQWM7RUFDaEI7RUFDQTtJQUNFLFNBQVM7SUFDVCxnQkFBZ0I7RUFDbEI7RUFDQTtJQUNFLGlCQUFpQjtFQUNuQjtBQUNGIiwiZmlsZSI6InJhaWZfYWRtaW4uY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmNvbnZlcnNhdGlvbi1jYXJkIC5jYXJkLWJvZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmOWZhO1xufVxuXG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2Uge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2U6bGFzdC1jaGlsZCB7XG4gIG1hcmdpbi1ib3R0b206IDA7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UudXNlciB7XG4gIGJvcmRlci1sZWZ0OiAzcHggc29saWQgIzNiODJmNjtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZS51c2VyIC5tZXNzYWdlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xufVxuLmNvbnZlcnNhdGlvbi1oaXN0b3J5IC5tZXNzYWdlLmFzc2lzdGFudCB7XG4gIGJvcmRlci1sZWZ0OiAzcHggc29saWQgcmdiKDI1LCAxMzUsIDg0KTtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZS5hc3Npc3RhbnQgLm1lc3NhZ2UtY29udGVudCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYigyMzIsIDI1NSwgMjQ0KTtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZSAubWVzc2FnZS1jb250ZW50IHtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICBib3gtc2hhZG93OiAwIDFweCAycHggcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgY29sb3I6ICMxZTNhOGE7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UgLm1lc3NhZ2UtY29udGVudCBjb2RlIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIGZvbnQtZmFtaWx5OiBTRk1vbm8tUmVndWxhciwgTWVubG8sIE1vbmFjbywgQ29uc29sYXMsIFwiTGliZXJhdGlvbiBNb25vXCIsIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlO1xuICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG4gIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XG4gIGJhY2tncm91bmQ6IG5vbmU7XG4gIGJvcmRlcjogbm9uZTtcbiAgcGFkZGluZzogMDtcbiAgY29sb3I6IGluaGVyaXQ7XG59XG4uY29udmVyc2F0aW9uLWhpc3RvcnkgLm1lc3NhZ2UgLm1lc3NhZ2UtY29udGVudDpsYXN0LWNoaWxkIHtcbiAgbWFyZ2luLWJvdHRvbTogMDtcbn1cbi5jb252ZXJzYXRpb24taGlzdG9yeSAubWVzc2FnZSAubWVzc2FnZS1jb250ZW50IC5tZXNzYWdlLWxhYmVsIHtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICBmb250LXNpemU6IDAuNzVyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7XG4gIGxldHRlci1zcGFjaW5nOiAwLjVweDtcbn1cblxuYm9keS5yYWlmLWFkbWluIHtcbiAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIEJsaW5rTWFjU3lzdGVtRm9udCwgXCJTZWdvZSBVSVwiLCBSb2JvdG8sIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7XG4gIGNvbG9yOiAjNTI1ZjdmO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmYWZjO1xuICBsaW5lLWhlaWdodDogMS41O1xuICBmb250LXNpemU6IDAuOTM3NXJlbTtcbn1cblxuLnJhaWYtYWRtaW4gLm5hdmJhci1icmFuZC1sb2dvIHtcbiAgd2lkdGg6IDEwMHB4O1xufVxuLnJhaWYtYWRtaW4gaDEsXG4ucmFpZi1hZG1pbiBoMixcbi5yYWlmLWFkbWluIGgzLFxuLnJhaWYtYWRtaW4gaDQsXG4ucmFpZi1hZG1pbiBoNSxcbi5yYWlmLWFkbWluIGg2IHtcbiAgY29sb3I6ICMxZTNhOGE7XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG59XG4ucmFpZi1hZG1pbiBhIHtcbiAgY29sb3I6ICMzYjgyZjY7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTtcbn1cbi5yYWlmLWFkbWluIGE6aG92ZXIge1xuICBjb2xvcjogcmdiKDExLjE1MTIxOTUxMjIsIDk5LjEyMTk1MTIxOTUsIDI0Mi44NDg3ODA0ODc4KTtcbn1cbi5yYWlmLWFkbWluIC5uYXZiYXIge1xuICBib3gtc2hhZG93OiAwIDJweCA1cHggMCByZ2JhKDUwLCA1MCwgOTMsIDAuMSk7XG4gIHBhZGRpbmc6IDAuNzVyZW0gMS41cmVtO1xufVxuLnJhaWYtYWRtaW4gLm5hdmJhci5uYXZiYXItZGFyayB7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMxZTNhOGEsIHJnYigyMC44OTI4NTcxNDI5LCA0MC4zOTI4NTcxNDI5LCA5Ni4xMDcxNDI4NTcxKSkgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5uYXZiYXIgLm5hdmJhci1icmFuZCB7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7XG4gIGxldHRlci1zcGFjaW5nOiAwLjVweDtcbn1cbi5yYWlmLWFkbWluIC5zaWRlYmFyIHtcbiAgYm94LXNoYWRvdzogaW5zZXQgLTFweCAwIDAgI2UyZThmMDtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGUgIWltcG9ydGFudDtcbiAgcGFkZGluZy10b3A6IDFyZW07XG4gIGhlaWdodDogMTAwdmg7XG59XG4ucmFpZi1hZG1pbiAuc2lkZWJhciAubmF2LWxpbmsge1xuICBjb2xvcjogIzUyNWY3ZjtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBtYXJnaW46IDAuMjVyZW0gMC43NXJlbTtcbiAgcGFkZGluZzogMC41cmVtIDAuNzVyZW07XG59XG4ucmFpZi1hZG1pbiAuc2lkZWJhciAubmF2LWxpbms6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xufVxuLnJhaWYtYWRtaW4gLnNpZGViYXIgLm5hdi1saW5rLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjEpO1xuICBjb2xvcjogIzNiODJmNjtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbn1cbi5yYWlmLWFkbWluIG1haW4ge1xuICBwYWRkaW5nLXRvcDogMS41cmVtO1xuICBwYWRkaW5nLWJvdHRvbTogM3JlbTtcbn1cbi5yYWlmLWFkbWluIC5jYXJkIHtcbiAgYm9yZGVyOiBub25lO1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGJveC1zaGFkb3c6IDAgNHB4IDZweCByZ2JhKDUwLCA1MCwgOTMsIDAuMTEpLCAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjA4KTtcbiAgbWFyZ2luLWJvdHRvbTogMS41cmVtO1xuICBvdmVyZmxvdzogaGlkZGVuO1xufVxuLnJhaWYtYWRtaW4gLmNhcmQgLmNhcmQtaGVhZGVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZTJlOGYwO1xuICBwYWRkaW5nOiAxcmVtIDEuMjVyZW07XG59XG4ucmFpZi1hZG1pbiAuY2FyZCAuY2FyZC1oZWFkZXIgaDUge1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBmb250LXNpemU6IDFyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG59XG4ucmFpZi1hZG1pbiAuY2FyZCAuY2FyZC1ib2R5IHtcbiAgcGFkZGluZzogMS4yNXJlbTtcbn1cbi5yYWlmLWFkbWluIC5jYXJkLmNvbnZlcnNhdGlvbi1jYXJkIC5jYXJkLWJvZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmOWZhO1xufVxuLnJhaWYtYWRtaW4gLnRhYmxlIHtcbiAgbWFyZ2luLWJvdHRvbTogMDtcbn1cbi5yYWlmLWFkbWluIC50YWJsZSB0aCB7XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIGNvbG9yOiAjMWUzYThhO1xuICBib3JkZXItdG9wOiBub25lO1xuICBwYWRkaW5nOiAxcmVtIDAuNzVyZW07XG4gIGZvbnQtc2l6ZTogMC44MTI1cmVtO1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBsZXR0ZXItc3BhY2luZzogMC41cHg7XG59XG4ucmFpZi1hZG1pbiAudGFibGUgdGQge1xuICBwYWRkaW5nOiAxcmVtIDAuNzVyZW07XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG4gIGJvcmRlci1jb2xvcjogI2UyZThmMDtcbn1cbi5yYWlmLWFkbWluIC50YWJsZS50YWJsZS1ob3ZlciB0Ym9keSB0cjpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmMGY5ZmY7XG59XG4ucmFpZi1hZG1pbiAudGFibGUudGFibGUtc3RyaXBlZCB0Ym9keSB0cjpudGgtb2YtdHlwZShvZGQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0OSwgMjU1LCAwLjUpO1xufVxuLnJhaWYtYWRtaW4gLnRhYmxlLXJlc3BvbnNpdmUge1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGJveC1zaGFkb3c6IDAgNHB4IDZweCByZ2JhKDUwLCA1MCwgOTMsIDAuMTEpLCAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjA4KTtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG4ucmFpZi1hZG1pbiAuYmFkZ2Uge1xuICBmb250LXdlaWdodDogNTAwO1xuICBwYWRkaW5nOiAwLjRlbSAwLjY1ZW07XG4gIGZvbnQtc2l6ZTogMC43NWVtO1xuICBib3JkZXItcmFkaXVzOiA1MHJlbTtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy1zdWNjZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzBlYTVlOSAhaW1wb3J0YW50O1xufVxuLnJhaWYtYWRtaW4gLmJhZGdlLmJnLWRhbmdlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZjQ0NDQgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy13YXJuaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2Y1OWUwYiAhaW1wb3J0YW50O1xuICBjb2xvcjogd2hpdGUgIWltcG9ydGFudDtcbn1cbi5yYWlmLWFkbWluIC5iYWRnZS5iZy1zZWNvbmRhcnkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjODg5OGFhICFpbXBvcnRhbnQ7XG59XG4ucmFpZi1hZG1pbiAuYnRuIHtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTtcbiAgYm94LXNoYWRvdzogMCA0cHggNnB4IHJnYmEoNTAsIDUwLCA5MywgMC4xMSksIDAgMXB4IDNweCByZ2JhKDAsIDAsIDAsIDAuMDgpO1xufVxuLnJhaWYtYWRtaW4gLmJ0bi5idG4tb3V0bGluZS1zZWNvbmRhcnkge1xuICBjb2xvcjogIzUyNWY3ZjtcbiAgYm9yZGVyLWNvbG9yOiAjZTJlOGYwO1xufVxuLnJhaWYtYWRtaW4gLmJ0bi5idG4tb3V0bGluZS1zZWNvbmRhcnk6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmOWZmO1xuICBjb2xvcjogIzFlM2E4YTtcbiAgYm9yZGVyLWNvbG9yOiAjZTJlOGYwO1xufVxuLnJhaWYtYWRtaW4gcHJlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YwZjlmZjtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBwYWRkaW5nOiAxcmVtO1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBmb250LXNpemU6IDAuODc1cmVtO1xuICBjb2xvcjogIzFlM2E4YTtcbiAgYm9yZGVyOiAxcHggc29saWQgI2UyZThmMDtcbn1cbi5yYWlmLWFkbWluIC5wcmUtd3JhcCB7XG4gIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcbn1cbi5yYWlmLWFkbWluIC5saXN0LWdyb3VwLWl0ZW0ge1xuICBib3JkZXItY29sb3I6ICNlMmU4ZjA7XG4gIHBhZGRpbmc6IDFyZW07XG59XG4ucmFpZi1hZG1pbiAubGlzdC1ncm91cC1pdGVtOmZpcnN0LWNoaWxkIHtcbiAgYm9yZGVyLXRvcC1sZWZ0LXJhZGl1czogNHB4O1xuICBib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogNHB4O1xufVxuLnJhaWYtYWRtaW4gLmxpc3QtZ3JvdXAtaXRlbTpsYXN0LWNoaWxkIHtcbiAgYm9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czogNHB4O1xuICBib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czogNHB4O1xufVxuLnJhaWYtYWRtaW4gLnBhZ2luYXRpb24gLnBhZ2UtbGluayB7XG4gIGNvbG9yOiAjNTI1ZjdmO1xuICBib3JkZXItY29sb3I6ICNlMmU4ZjA7XG4gIHBhZGRpbmc6IDAuNXJlbSAwLjc1cmVtO1xufVxuLnJhaWYtYWRtaW4gLnBhZ2luYXRpb24gLnBhZ2UtbGluazpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmMGY5ZmY7XG4gIGJvcmRlci1jb2xvcjogI2UyZThmMDtcbiAgY29sb3I6ICMxZTNhOGE7XG59XG4ucmFpZi1hZG1pbiAucGFnaW5hdGlvbiAucGFnZS1pdGVtLmFjdGl2ZSAucGFnZS1saW5rIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzNiODJmNjtcbiAgYm9yZGVyLWNvbG9yOiAjM2I4MmY2O1xufVxuLnJhaWYtYWRtaW4gLnJvdy5tYi0zIC5jb2wtbWQtMyBzdHJvbmcge1xuICBjb2xvcjogIzFlM2E4YTtcbn1cbi5yYWlmLWFkbWluIC5hbGVydCB7XG4gIGJvcmRlcjogbm9uZTtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBib3gtc2hhZG93OiAwIDRweCA2cHggcmdiYSg1MCwgNTAsIDkzLCAwLjExKSwgMCAxcHggM3B4IHJnYmEoMCwgMCwgMCwgMC4wOCk7XG59XG4ucmFpZi1hZG1pbiAuYWxlcnQuYWxlcnQtaW5mbyB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjEpO1xuICBjb2xvcjogIzNiODJmNjtcbn1cbi5yYWlmLWFkbWluIC50ZXh0LW11dGVkIHtcbiAgY29sb3I6ICM4ODk4YWEgIWltcG9ydGFudDtcbn1cbkBtZWRpYSAobWF4LXdpZHRoOiA3NjcuOThweCkge1xuICAucmFpZi1hZG1pbiAuc2lkZWJhciB7XG4gICAgcG9zaXRpb246IHN0YXRpYztcbiAgICBoZWlnaHQ6IGF1dG87XG4gICAgcGFkZGluZy10b3A6IDA7XG4gIH1cbiAgLnJhaWYtYWRtaW4gLnNpZGViYXIgLm5hdi1saW5rIHtcbiAgICBtYXJnaW46IDA7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbiAgfVxuICAucmFpZi1hZG1pbiBtYWluIHtcbiAgICBwYWRkaW5nLXRvcDogMXJlbTtcbiAgfVxufVxuIl19 */
|
@@ -0,0 +1,8 @@
|
|
1
|
+
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="3187.5" height="1328.6164850518683" viewBox="0 -93.75 3187.5 1328.6164850518683">
|
3
|
+
|
4
|
+
<g transform="scale(9.375) translate(10, 10)">
|
5
|
+
<defs id="SvgjsDefs4139"/><g id="SvgjsG4140" featureKey="5TMTKC-0" transform="matrix(-0.5092531442642212,0,0,0.5092531442642212,79.9527359008789,-10.000000953674316)" fill="#fff"><defs xmlns="http://www.w3.org/2000/svg"/><g xmlns="http://www.w3.org/2000/svg"><path d="M7 122c-8,20 -10,46 -2,81 1,-27 4,-54 2,-81z" style="fill: #3b82f6;"/><path d="M56 70c-10,5 -19,12 -27,19 3,40 -9,73 -18,110 4,-7 8,-15 12,-22 16,-32 33,-63 33,-107z" style="fill: #3b82f6;"/><path d="M114 36c-7,5 -14,9 -21,13 -6,60 -37,89 -68,134 40,-51 80,-74 89,-147z" style="fill: #3b82f6;"/><path d="M157 60c-2,-21 -6,-42 -12,-60 -5,88 -40,112 -97,166 44,-34 84,-51 109,-106z" style="fill: #3b82f6;"/><path d="M150 150c3,-11 6,-23 7,-36 -39,39 -94,49 -135,85 41,-25 86,-28 128,-49z" style="fill: #3b82f6;"/><path d="M105 208c10,-5 18,-13 26,-21 -38,5 -73,5 -110,19 29,-4 55,-1 84,2z" style="fill: #3b82f6;"/><path d="M9 213c25,6 46,8 64,5 -12,-5 -53,-10 -64,-5z" style="fill: #3b82f6;"/></g></g><g id="SvgjsG4141" featureKey="7UBp9i-0" transform="matrix(6.225240707397461,0,0,6.225240707397461,92.90322369982673,-21.50368198162188)" fill="#fff"><path d="M4.14 10.58 l0 2.92 l2.8 0 c0.92 0 1.46 -0.54 1.46 -1.46 s-0.54 -1.46 -1.46 -1.46 l-2.8 0 z M8.68 15.48 c0.56 0.76 1.12 1.52 1.7 2.26 c0.56 0.74 1.12 1.5 1.68 2.26 l-3.66 0 c-0.72 -0.96 -1.42 -1.92 -2.12 -2.88 c-0.7 -0.94 -1.42 -1.9 -2.14 -2.86 l0 5.74 l-3 0 l0 -12.24 l5.8 0 c2.28 0 4.22 1.74 4.22 4.04 c0 1.62 -1 3.04 -2.48 3.68 z M20.2 15 c-0.08 -1.46 -0.74 -2.32 -2.26 -2.32 c-0.42 0 -0.78 0.06 -1.08 0.18 c-0.92 0.42 -1.26 1.2 -1.26 2.16 c0 0.32 0.04 0.62 0.14 0.88 c0.3 1.04 1.2 1.42 2.2 1.42 c1.52 0 2.26 -0.82 2.26 -2.32 z M24 20 l-3 0 c-0.2 -0.5 -0.38 -1 -0.5 -1.52 c-0.68 1.12 -1.72 1.62 -3 1.62 c-2.86 0 -4.9 -2.4 -4.9 -5.14 c0 -3.16 2.36 -5.06 5.34 -5.06 c3.18 0 5.18 2.04 5.26 5.1 c0.02 0.26 0.02 0.56 0.02 0.92 c0 1.4 0.22 2.8 0.78 4.08 z M25.099999999999998 10 l3 0 l0 10 l-3 0 l0 -10 z M26.599999999999998 9.06 c-1.02 0 -1.74 -0.72 -1.74 -1.74 c0 -1.04 0.72 -1.72 1.74 -1.72 c1.04 0 1.72 0.68 1.72 1.72 c0 1.06 -0.66 1.74 -1.72 1.74 z M35.6 10.34 l0 2.78 l-2.46 0 l0 6.88 l-3 0 l0 -9.98 c0 -3.32 2.44 -5.12 5.52 -5.12 c0.1 0 0.24 0 0.38 0.02 s0.3 0.06 0.44 0.08 l0 2.9 c-0.1 -0.02 -0.22 -0.04 -0.36 -0.06 s-0.26 -0.04 -0.36 -0.04 c-0.5 0 -0.9 0.06 -1.24 0.16 c-0.56 0.2 -1.06 0.58 -1.24 1.18 c-0.1 0.26 -0.14 0.56 -0.14 0.86 l0 0.34 l2.46 0 z"/></g>
|
6
|
+
</g>
|
7
|
+
</svg>
|
8
|
+
|
@@ -25,6 +25,9 @@ body.raif-admin {
|
|
25
25
|
}
|
26
26
|
|
27
27
|
.raif-admin {
|
28
|
+
.navbar-brand-logo {
|
29
|
+
width: 100px;
|
30
|
+
}
|
28
31
|
|
29
32
|
h1,
|
30
33
|
h2,
|
@@ -65,6 +68,7 @@ body.raif-admin {
|
|
65
68
|
box-shadow: inset -1px 0 0 $border-color;
|
66
69
|
background-color: white !important;
|
67
70
|
padding-top: 1rem;
|
71
|
+
height: 100vh;
|
68
72
|
|
69
73
|
.nav-link {
|
70
74
|
color: $text-color;
|
@@ -16,7 +16,7 @@ module Raif
|
|
16
16
|
Turbo::StreamsChannel.broadcast_action_to(
|
17
17
|
conversation,
|
18
18
|
action: :raif_scroll_to_bottom,
|
19
|
-
target: dom_id(conversation, :entries)
|
19
|
+
target: ActionView::RecordIdentifier.dom_id(conversation, :entries)
|
20
20
|
)
|
21
21
|
rescue StandardError => e
|
22
22
|
logger.error "Error processing conversation entry: #{e.message}"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Raif::Concerns::TaskRunArgs
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :_task_run_args, instance_writer: false, default: []
|
8
|
+
end
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
# DSL for declaring persistent task arguments that will be serialized to the database
|
12
|
+
# @param name [Symbol] The name of the argument
|
13
|
+
def task_run_arg(name)
|
14
|
+
# Ensure each class has its own array copy
|
15
|
+
self._task_run_args = _task_run_args.dup
|
16
|
+
_task_run_args << name.to_sym
|
17
|
+
|
18
|
+
# Define getter that pulls from task_run_args JSON
|
19
|
+
define_method(name) do
|
20
|
+
return instance_variable_get("@#{name}") if instance_variable_defined?("@#{name}")
|
21
|
+
|
22
|
+
value = task_run_args&.dig(name.to_s)
|
23
|
+
return unless value
|
24
|
+
|
25
|
+
# Deserialize GID if it's a string starting with gid://
|
26
|
+
deserialized = if value.is_a?(String) && value.start_with?("gid://")
|
27
|
+
begin
|
28
|
+
GlobalID::Locator.locate(value)
|
29
|
+
rescue ActiveRecord::RecordNotFound
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
else
|
33
|
+
value
|
34
|
+
end
|
35
|
+
|
36
|
+
instance_variable_set("@#{name}", deserialized)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Define setter that stores in memory (for use during run)
|
40
|
+
define_method("#{name}=") do |value|
|
41
|
+
instance_variable_set("@#{name}", value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Transform run args into a hash that can be stored in the task_run_args database column
|
46
|
+
def serialize_task_run_args(args)
|
47
|
+
serialized_args = {}
|
48
|
+
_task_run_args.each do |arg_name|
|
49
|
+
next unless args.key?(arg_name)
|
50
|
+
|
51
|
+
value = args[arg_name]
|
52
|
+
serialized_args[arg_name.to_s] = if value.respond_to?(:to_global_id)
|
53
|
+
value.to_global_id.to_s
|
54
|
+
else
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
serialized_args
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -34,6 +34,10 @@ class Raif::Conversation < Raif::ApplicationRecord
|
|
34
34
|
I18n.t("#{self.class.name.underscore.gsub("/", ".")}.initial_chat_message")
|
35
35
|
end
|
36
36
|
|
37
|
+
def initial_chat_message_partial_path
|
38
|
+
"raif/conversations/initial_chat_message"
|
39
|
+
end
|
40
|
+
|
37
41
|
def prompt_model_for_entry_response(entry:, &block)
|
38
42
|
update(system_prompt: build_system_prompt)
|
39
43
|
|
@@ -47,6 +51,8 @@ class Raif::Conversation < Raif::ApplicationRecord
|
|
47
51
|
)
|
48
52
|
rescue StandardError => e
|
49
53
|
Rails.logger.error("Error processing conversation entry ##{entry.id}. #{e.message}")
|
54
|
+
Rails.logger.error(e.backtrace.join("\n"))
|
55
|
+
|
50
56
|
entry.failed!
|
51
57
|
|
52
58
|
if defined?(Airbrake)
|
@@ -56,6 +62,8 @@ class Raif::Conversation < Raif::ApplicationRecord
|
|
56
62
|
|
57
63
|
Airbrake.notify(notice)
|
58
64
|
end
|
65
|
+
|
66
|
+
nil
|
59
67
|
end
|
60
68
|
|
61
69
|
def process_model_response_message(message:, entry:)
|
@@ -17,7 +17,6 @@ class Raif::ConversationEntry < Raif::ApplicationRecord
|
|
17
17
|
|
18
18
|
delegate :available_model_tools, to: :raif_conversation
|
19
19
|
delegate :system_prompt, :llm_model_key, :citations, to: :raif_model_completion, allow_nil: true
|
20
|
-
delegate :json_response_schema, to: :class
|
21
20
|
|
22
21
|
accepts_nested_attributes_for :raif_user_tool_invocation
|
23
22
|
|
@@ -64,7 +63,7 @@ class Raif::ConversationEntry < Raif::ApplicationRecord
|
|
64
63
|
broadcast_replace_to raif_conversation
|
65
64
|
end
|
66
65
|
|
67
|
-
if raif_model_completion.parsed_response.present? || raif_model_completion.response_tool_calls.present?
|
66
|
+
if raif_model_completion.present? && (raif_model_completion.parsed_response.present? || raif_model_completion.response_tool_calls.present?)
|
68
67
|
extract_message_and_invoke_tools!
|
69
68
|
create_entry_for_observation! if triggers_observation_to_model?
|
70
69
|
else
|
@@ -84,7 +83,7 @@ class Raif::ConversationEntry < Raif::ApplicationRecord
|
|
84
83
|
def create_entry_for_observation!
|
85
84
|
follow_up_entry = raif_conversation.entries.create!(creator: creator)
|
86
85
|
Raif::ConversationEntryJob.perform_later(conversation_entry: follow_up_entry)
|
87
|
-
follow_up_entry.broadcast_append_to raif_conversation, target: dom_id(raif_conversation, :entries)
|
86
|
+
follow_up_entry.broadcast_append_to raif_conversation, target: ActionView::RecordIdentifier.dom_id(raif_conversation, :entries)
|
88
87
|
end
|
89
88
|
|
90
89
|
private
|
@@ -95,13 +94,11 @@ private
|
|
95
94
|
self.model_response_message = raif_conversation.process_model_response_message(message: raif_model_completion.parsed_response, entry: self)
|
96
95
|
save!
|
97
96
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
next if tool_klass.nil?
|
97
|
+
raif_model_completion.response_tool_calls&.each do |tool_call|
|
98
|
+
tool_klass = available_model_tools_map[tool_call["name"]]
|
99
|
+
next if tool_klass.nil?
|
102
100
|
|
103
|
-
|
104
|
-
end
|
101
|
+
tool_klass.invoke_tool(tool_arguments: tool_call["arguments"], source: self)
|
105
102
|
end
|
106
103
|
|
107
104
|
completed!
|
data/app/models/raif/llm.rb
CHANGED
@@ -77,7 +77,7 @@ module Raif
|
|
77
77
|
temperature ||= default_temperature
|
78
78
|
max_completion_tokens ||= default_max_completion_tokens
|
79
79
|
|
80
|
-
model_completion = Raif::ModelCompletion.
|
80
|
+
model_completion = Raif::ModelCompletion.create!(
|
81
81
|
messages: format_messages(messages),
|
82
82
|
system_prompt: system_prompt,
|
83
83
|
response_format: response_format,
|
@@ -38,9 +38,16 @@ private
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def update_model_completion(model_completion, response_json)
|
41
|
+
raw_response = if model_completion.response_format_json?
|
42
|
+
extract_json_response(response_json)
|
43
|
+
else
|
44
|
+
extract_text_response(response_json)
|
45
|
+
end
|
46
|
+
|
41
47
|
model_completion.update!(
|
48
|
+
response_id: response_json["id"],
|
42
49
|
response_tool_calls: extract_response_tool_calls(response_json),
|
43
|
-
raw_response:
|
50
|
+
raw_response: raw_response,
|
44
51
|
response_array: response_json["choices"],
|
45
52
|
completion_tokens: response_json.dig("usage", "completion_tokens"),
|
46
53
|
prompt_tokens: response_json.dig("usage", "prompt_tokens"),
|
@@ -63,6 +70,20 @@ private
|
|
63
70
|
|
64
71
|
if supports_native_tool_use?
|
65
72
|
tools = build_tools_parameter(model_completion)
|
73
|
+
|
74
|
+
if model_completion.json_response_schema.present?
|
75
|
+
validate_json_schema!(model_completion.json_response_schema)
|
76
|
+
|
77
|
+
tools << {
|
78
|
+
type: "function",
|
79
|
+
function: {
|
80
|
+
name: "json_response",
|
81
|
+
description: "Generate a structured JSON response based on the provided schema.",
|
82
|
+
parameters: model_completion.json_response_schema
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
66
87
|
params[:tools] = tools unless tools.blank?
|
67
88
|
end
|
68
89
|
|
@@ -72,7 +93,9 @@ private
|
|
72
93
|
params[:stream_options] = { include_usage: true }
|
73
94
|
end
|
74
95
|
|
75
|
-
|
96
|
+
# OpenRouter will sometimes complain about combining response_format json and tool calling.
|
97
|
+
# If we're telling it to use the json_response tool, then the json_object response_format should be irrelevant.
|
98
|
+
if model_completion.response_format_json? && params[:tools].blank?
|
76
99
|
params[:response_format] = { type: "json_object" }
|
77
100
|
model_completion.response_format_parameter = "json_object"
|
78
101
|
end
|
@@ -80,10 +103,30 @@ private
|
|
80
103
|
params
|
81
104
|
end
|
82
105
|
|
106
|
+
def extract_text_response(resp)
|
107
|
+
resp&.dig("choices", 0, "message", "content")
|
108
|
+
end
|
109
|
+
|
110
|
+
def extract_json_response(resp)
|
111
|
+
tool_calls = resp.dig("choices", 0, "message", "tool_calls")
|
112
|
+
return extract_text_response(resp) if tool_calls.blank?
|
113
|
+
|
114
|
+
tool_response = tool_calls.find do |tool_call|
|
115
|
+
tool_call["function"]["name"] == "json_response"
|
116
|
+
end
|
117
|
+
|
118
|
+
if tool_response&.dig("function", "arguments")
|
119
|
+
tool_response["function"]["arguments"]
|
120
|
+
else
|
121
|
+
extract_text_response(resp)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
83
125
|
def extract_response_tool_calls(resp)
|
84
|
-
|
126
|
+
tool_calls = resp.dig("choices", 0, "message", "tool_calls")
|
127
|
+
return if tool_calls.blank?
|
85
128
|
|
86
|
-
|
129
|
+
tool_calls.map do |tool_call|
|
87
130
|
{
|
88
131
|
"name" => tool_call["function"]["name"],
|
89
132
|
"arguments" => JSON.parse(tool_call["function"]["arguments"])
|
data/app/models/raif/task.rb
CHANGED
@@ -9,10 +9,13 @@ module Raif
|
|
9
9
|
include Raif::Concerns::LlmResponseParsing
|
10
10
|
include Raif::Concerns::LlmTemperature
|
11
11
|
include Raif::Concerns::JsonSchemaDefinition
|
12
|
+
include Raif::Concerns::TaskRunArgs
|
12
13
|
|
13
14
|
llm_temperature 0.7
|
14
15
|
|
15
|
-
belongs_to :creator, polymorphic: true
|
16
|
+
belongs_to :creator, polymorphic: true, optional: true
|
17
|
+
|
18
|
+
validates :creator, presence: true, unless: -> { Raif.config.task_creator_optional }
|
16
19
|
|
17
20
|
has_one :raif_model_completion, as: :source, dependent: :destroy, class_name: "Raif::ModelCompletion"
|
18
21
|
|
@@ -32,6 +35,7 @@ module Raif
|
|
32
35
|
attr_accessor :files, :images
|
33
36
|
|
34
37
|
after_initialize -> { self.available_model_tools ||= [] }
|
38
|
+
after_initialize -> { self.task_run_args ||= {} }
|
35
39
|
|
36
40
|
def status
|
37
41
|
if completed_at?
|
@@ -48,15 +52,24 @@ module Raif
|
|
48
52
|
# The primary interface for running a task. It will hit the LLM with the task's prompt and system prompt and return a Raif::Task object.
|
49
53
|
# It will also create a new Raif::ModelCompletion record.
|
50
54
|
#
|
51
|
-
# @param creator [Object] The creator of the task (polymorphic association)
|
55
|
+
# @param creator [Object, nil] The creator of the task (polymorphic association), optional
|
52
56
|
# @param available_model_tools [Array<Class>] Optional array of model tool classes that will be provided to the LLM for it to invoke.
|
53
57
|
# @param llm_model_key [Symbol, String] Optional key for the LLM model to use. If blank, Raif.config.default_llm_model_key will be used.
|
54
58
|
# @param images [Array] Optional array of Raif::ModelImageInput objects to include with the prompt.
|
55
59
|
# @param files [Array] Optional array of Raif::ModelFileInput objects to include with the prompt.
|
56
60
|
# @param args [Hash] Additional arguments to pass to the instance of the task that is created.
|
57
61
|
# @return [Raif::Task, nil] The task instance that was created and run.
|
58
|
-
def self.run(creator
|
59
|
-
task = new(
|
62
|
+
def self.run(creator: nil, available_model_tools: [], llm_model_key: nil, images: [], files: [], **args)
|
63
|
+
task = new(
|
64
|
+
creator: creator,
|
65
|
+
llm_model_key: llm_model_key,
|
66
|
+
available_model_tools: available_model_tools,
|
67
|
+
started_at: Time.current,
|
68
|
+
images: images,
|
69
|
+
files: files,
|
70
|
+
task_run_args: serialize_task_run_args(args),
|
71
|
+
**args
|
72
|
+
)
|
60
73
|
|
61
74
|
task.save!
|
62
75
|
task.run
|
@@ -109,19 +122,19 @@ module Raif
|
|
109
122
|
|
110
123
|
# Returns the LLM prompt for the task.
|
111
124
|
#
|
112
|
-
# @param creator [Object] The creator of the task (polymorphic association)
|
125
|
+
# @param creator [Object, nil] The creator of the task (polymorphic association), optional
|
113
126
|
# @param args [Hash] Additional arguments to pass to the instance of the task that is created.
|
114
127
|
# @return [String] The LLM prompt for the task.
|
115
|
-
def self.prompt(creator
|
128
|
+
def self.prompt(creator: nil, **args)
|
116
129
|
new(creator:, **args).build_prompt
|
117
130
|
end
|
118
131
|
|
119
132
|
# Returns the LLM system prompt for the task.
|
120
133
|
#
|
121
|
-
# @param creator [Object] The creator of the task (polymorphic association)
|
134
|
+
# @param creator [Object, nil] The creator of the task (polymorphic association), optional
|
122
135
|
# @param args [Hash] Additional arguments to pass to the instance of the task that is created.
|
123
136
|
# @return [String] The LLM system prompt for the task.
|
124
|
-
def self.system_prompt(creator
|
137
|
+
def self.system_prompt(creator: nil, **args)
|
125
138
|
new(creator:, **args).build_system_prompt
|
126
139
|
end
|
127
140
|
|
@@ -170,7 +183,7 @@ module Raif
|
|
170
183
|
end
|
171
184
|
|
172
185
|
def populate_prompts
|
173
|
-
self.requested_language_key ||= creator
|
186
|
+
self.requested_language_key ||= creator&.preferred_language_key if creator&.respond_to?(:preferred_language_key)
|
174
187
|
self.prompt = build_prompt
|
175
188
|
self.system_prompt = build_system_prompt
|
176
189
|
end
|
@@ -15,7 +15,9 @@
|
|
15
15
|
<body class="raif-admin">
|
16
16
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
|
17
17
|
<div class="container-fluid">
|
18
|
-
<a class="navbar-brand fw-bold" href="<%= raif.admin_tasks_path %>"
|
18
|
+
<a class="navbar-brand fw-bold" href="<%= raif.admin_tasks_path %>">
|
19
|
+
<%= image_tag "raif-logo-white.svg", class: "navbar-brand-logo" %>
|
20
|
+
</a>
|
19
21
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
20
22
|
<span class="navbar-toggler-icon"></span>
|
21
23
|
</button>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<% end %>
|
11
11
|
<% end %>
|
12
12
|
|
13
|
-
<div class="d-flex px-2">
|
13
|
+
<div class="d-flex px-2 align-items-center">
|
14
14
|
<%= f.text_field :user_message,
|
15
15
|
class: "form-control me-2",
|
16
16
|
placeholder: conversation_entry.raif_user_tool_invocation&.message_input_placeholder.presence || t("raif.common.type_your_message"),
|
@@ -1,14 +1,11 @@
|
|
1
1
|
<%= turbo_stream_from conversation %>
|
2
2
|
|
3
|
-
<div id="<%= dom_id(conversation, :entries) %>" class="flex-grow-1 overflow-auto" data-controller="raif--conversations">
|
4
|
-
<%= render
|
5
|
-
content: conversation.initial_chat_message,
|
6
|
-
message_type: :model_response %>
|
7
|
-
|
3
|
+
<div id="<%= dom_id(conversation, :entries) %>" class="flex-grow-1 overflow-auto raif-conversation-entries-container" data-controller="raif--conversations">
|
4
|
+
<%= render conversation.initial_chat_message_partial_path, conversation: conversation %>
|
8
5
|
<%= render conversation.entries.oldest_first %>
|
9
6
|
</div>
|
10
7
|
|
11
|
-
<div id="<%= dom_id(conversation, :entry_input) %>">
|
8
|
+
<div id="<%= dom_id(conversation, :entry_input) %>" class="raif-conversation-entry-input-container">
|
12
9
|
<%= render "raif/conversation_entries/form_with_available_tools",
|
13
10
|
conversation: conversation,
|
14
11
|
conversation_entry: Raif::ConversationEntry.new %>
|
data/config/locales/en.yml
CHANGED
@@ -68,6 +68,9 @@ en:
|
|
68
68
|
open_ai_gpt_4_1_nano: OpenAI GPT-4.1 Nano
|
69
69
|
open_ai_gpt_4o: OpenAI GPT-4o
|
70
70
|
open_ai_gpt_4o_mini: OpenAI GPT-4o Mini
|
71
|
+
open_ai_gpt_5: OpenAI GPT-5
|
72
|
+
open_ai_gpt_5_mini: OpenAI GPT-5 Mini
|
73
|
+
open_ai_gpt_5_nano: OpenAI GPT-5 Nano
|
71
74
|
open_ai_o1: OpenAI o1
|
72
75
|
open_ai_o1_mini: OpenAI o1 Mini
|
73
76
|
open_ai_o3: OpenAI o3
|
@@ -79,6 +82,9 @@ en:
|
|
79
82
|
open_ai_responses_gpt_4_1_nano: OpenAI GPT-4.1 Nano (Responses API)
|
80
83
|
open_ai_responses_gpt_4o: OpenAI GPT-4o (Responses API)
|
81
84
|
open_ai_responses_gpt_4o_mini: OpenAI GPT-4o Mini (Responses API)
|
85
|
+
open_ai_responses_gpt_5: OpenAI GPT-5 (Responses API)
|
86
|
+
open_ai_responses_gpt_5_mini: OpenAI GPT-5 Mini (Responses API)
|
87
|
+
open_ai_responses_gpt_5_nano: OpenAI GPT-5 Nano (Responses API)
|
82
88
|
open_ai_responses_o1: OpenAI o1 (Responses API)
|
83
89
|
open_ai_responses_o1_mini: OpenAI o1 Mini (Responses API)
|
84
90
|
open_ai_responses_o1_pro: OpenAI o1 Pro (Responses API)
|
@@ -93,4 +99,6 @@ en:
|
|
93
99
|
open_router_llama_3_3_70b_instruct: Meta Llama 3.3 70B Instruct (via OpenRouter)
|
94
100
|
open_router_llama_4_maverick: Meta Llama 4 Maverick (via OpenRouter)
|
95
101
|
open_router_llama_4_scout: Meta Llama 4 Scout (via OpenRouter)
|
102
|
+
open_router_open_ai_gpt_oss_120b: OpenAI GPT-OSS 120B (via OpenRouter)
|
103
|
+
open_router_open_ai_gpt_oss_20b: OpenAI GPT-OSS 20B (via OpenRouter)
|
96
104
|
raif_test_llm: Raif Test LLM
|
@@ -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
|
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
|