leva 0.1.9 → 0.1.10
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 +20 -3
- data/app/controllers/leva/application_controller.rb +1 -1
- data/app/controllers/leva/dataset_records_controller.rb +1 -1
- data/app/controllers/leva/datasets_controller.rb +6 -6
- data/app/controllers/leva/experiments_controller.rb +8 -8
- data/app/controllers/leva/runner_results_controller.rb +1 -1
- data/app/controllers/leva/workbench_controller.rb +26 -15
- data/app/helpers/leva/application_helper.rb +7 -7
- data/app/jobs/leva/experiment_job.rb +1 -1
- data/app/jobs/leva/run_eval_job.rb +1 -1
- data/app/models/concerns/leva/recordable.rb +5 -5
- data/app/models/leva/dataset.rb +1 -1
- data/app/models/leva/evaluation_result.rb +1 -1
- data/app/models/leva/experiment.rb +1 -1
- data/app/models/leva/prompt.rb +1 -1
- data/app/views/layouts/leva/application.html.erb +0 -1
- data/app/views/leva/dataset_records/index.html.erb +56 -31
- data/app/views/leva/experiments/new.html.erb +28 -1
- data/app/views/leva/workbench/_prompt_content.html.erb +60 -14
- data/config/routes.rb +9 -9
- data/db/migrate/20240813173033_create_leva_dataset_records.rb +1 -0
- data/db/migrate/20240813173035_create_leva_experiments.rb +2 -0
- data/db/migrate/{20240816201419_create_leva_runner_results.rb → 20240813173040_create_leva_runner_results.rb} +4 -1
- data/db/migrate/20240813173050_create_leva_evaluation_results.rb +3 -3
- data/lib/generators/leva/eval_generator.rb +4 -4
- data/lib/generators/leva/runner_generator.rb +4 -4
- data/lib/generators/leva/templates/runner.rb.erb +20 -0
- data/lib/leva/version.rb +1 -1
- data/lib/leva.rb +24 -2
- metadata +3 -11
- data/db/migrate/20240816201433_update_leva_evaluation_results.rb +0 -8
- data/db/migrate/20240821163608_make_experiment_optional_for_runner_results.rb +0 -6
- data/db/migrate/20240821181934_add_prompt_to_leva_runner_results.rb +0 -5
- data/db/migrate/20240821183153_add_runner_and_evaluator_to_leva_experiments.rb +0 -6
- data/db/migrate/20240821191713_add_actual_result_to_leva_dataset_records.rb +0 -5
- data/db/migrate/20240822143201_remove_actual_result_from_leva_runner_results.rb +0 -5
- data/db/migrate/20240912183556_add_runner_class_to_leva_runner_results.rb +0 -5
- data/lib/tasks/auto_annotate_models.rake +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63fc046c15809b57e461d3c7b8a35635b6a32c439b58d916e4d41e33e0f72827
|
4
|
+
data.tar.gz: 0e7f080fcb722d9f9539a139fecc7e0692a202e4e0bc8266f7f4b637750b2942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa195af952f524ff1d3b33106dc9dae8a58a9f24afeb658395ca255b485ccbcfb6cb78e48f00dbbba0f40e467afe8553ed795f1e3c67391e1b0cf2eebbf65a5c
|
7
|
+
data.tar.gz: 2da6f65c79f5e46f70033c24a3f7b30b1a873bd986bcefc556186ffc2b3dd38aae9036a9cb1ec375c480c06233f2fb99b713af6afdc0a4d0d12db0034196362e
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Leva - Flexible Evaluation Framework for Language Models
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/leva)
|
4
|
+
[](https://github.com/kieranklaassen/leva/actions/workflows/ci.yml)
|
4
5
|
|
5
6
|
Leva is a Ruby on Rails framework for evaluating Language Models (LLMs) using ActiveRecord datasets on production models. It provides a flexible structure for creating experiments, managing datasets, and implementing various evaluation logic on production data with security in mind.
|
6
7
|
|
@@ -28,13 +29,25 @@ rails leva:install:migrations
|
|
28
29
|
rails db:migrate
|
29
30
|
```
|
30
31
|
|
32
|
+
Mount the Leva engine in your application's routes file:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# config/routes.rb
|
36
|
+
Rails.application.routes.draw do
|
37
|
+
mount Leva::Engine => "/leva"
|
38
|
+
# your other routes...
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
The Leva UI will then be available at `/leva` in your application.
|
43
|
+
|
31
44
|
## Usage
|
32
45
|
|
33
46
|
### 1. Setting up Datasets
|
34
47
|
|
35
48
|
First, create a dataset and add any ActiveRecord records you want to evaluate against. To make your models compatible with Leva, include the `Leva::Recordable` concern in your model:
|
36
49
|
|
37
|
-
|
50
|
+
```ruby
|
38
51
|
class TextContent < ApplicationRecord
|
39
52
|
include Leva::Recordable
|
40
53
|
|
@@ -71,7 +84,11 @@ class TextContent < ApplicationRecord
|
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
74
|
-
dataset = Leva::Dataset.create(name: "Sentiment Analysis Dataset")
|
87
|
+
dataset = Leva::Dataset.create(name: "Sentiment Analysis Dataset")
|
88
|
+
dataset.add_record TextContent.create(text: "I love this product!", expected_label: "Positive")
|
89
|
+
dataset.add_record TextContent.create(text: "Terrible experience", expected_label: "Negative")
|
90
|
+
dataset.add_record TextContent.create(text: "It's ok", expected_label: "Neutral")
|
91
|
+
```
|
75
92
|
|
76
93
|
### 2. Implementing Runs
|
77
94
|
|
@@ -79,7 +96,7 @@ Create a run class to handle the execution of your inference logic:
|
|
79
96
|
|
80
97
|
```bash
|
81
98
|
rails generate leva:runner sentiment
|
82
|
-
|
99
|
+
```
|
83
100
|
|
84
101
|
```ruby
|
85
102
|
class SentimentRun < Leva::BaseRun
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Leva
|
4
4
|
class DatasetsController < ApplicationController
|
5
|
-
before_action :set_dataset, only: [:show, :edit, :update, :destroy]
|
5
|
+
before_action :set_dataset, only: [ :show, :edit, :update, :destroy ]
|
6
6
|
|
7
7
|
# GET /datasets
|
8
8
|
# @return [void]
|
@@ -35,7 +35,7 @@ module Leva
|
|
35
35
|
@dataset = Dataset.new(dataset_params)
|
36
36
|
|
37
37
|
if @dataset.save
|
38
|
-
redirect_to @dataset, notice:
|
38
|
+
redirect_to @dataset, notice: "Dataset was successfully created."
|
39
39
|
else
|
40
40
|
render :new
|
41
41
|
end
|
@@ -45,7 +45,7 @@ module Leva
|
|
45
45
|
# @return [void]
|
46
46
|
def update
|
47
47
|
if @dataset.update(dataset_params)
|
48
|
-
redirect_to @dataset, notice:
|
48
|
+
redirect_to @dataset, notice: "Dataset was successfully updated."
|
49
49
|
else
|
50
50
|
render :edit
|
51
51
|
end
|
@@ -55,10 +55,10 @@ module Leva
|
|
55
55
|
# @return [void]
|
56
56
|
def destroy
|
57
57
|
if @dataset.dataset_records.any?
|
58
|
-
redirect_to @dataset, alert:
|
58
|
+
redirect_to @dataset, alert: "Cannot delete dataset with existing records."
|
59
59
|
else
|
60
60
|
@dataset.destroy
|
61
|
-
redirect_to datasets_url, notice:
|
61
|
+
redirect_to datasets_url, notice: "Dataset was successfully destroyed."
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -76,4 +76,4 @@ module Leva
|
|
76
76
|
params.require(:dataset).permit(:name, :description)
|
77
77
|
end
|
78
78
|
end
|
79
|
-
end
|
79
|
+
end
|
@@ -4,9 +4,9 @@ module Leva
|
|
4
4
|
class ExperimentsController < ApplicationController
|
5
5
|
include ApplicationHelper
|
6
6
|
|
7
|
-
before_action :set_experiment, only: [:show, :edit, :update]
|
8
|
-
before_action :check_editable, only: [:edit, :update]
|
9
|
-
before_action :load_runners_and_evaluators, only: [:new, :edit, :create, :update]
|
7
|
+
before_action :set_experiment, only: [ :show, :edit, :update ]
|
8
|
+
before_action :check_editable, only: [ :edit, :update ]
|
9
|
+
before_action :load_runners_and_evaluators, only: [ :new, :edit, :create, :update ]
|
10
10
|
|
11
11
|
# GET /experiments
|
12
12
|
# @return [void]
|
@@ -39,7 +39,7 @@ module Leva
|
|
39
39
|
|
40
40
|
if @experiment.save
|
41
41
|
ExperimentJob.perform_later(@experiment) unless @experiment.completed?
|
42
|
-
redirect_to @experiment, notice:
|
42
|
+
redirect_to @experiment, notice: "Experiment was successfully created and is now running."
|
43
43
|
else
|
44
44
|
render :new
|
45
45
|
end
|
@@ -49,7 +49,7 @@ module Leva
|
|
49
49
|
# @return [void]
|
50
50
|
def update
|
51
51
|
if @experiment.update(experiment_params)
|
52
|
-
redirect_to @experiment, notice:
|
52
|
+
redirect_to @experiment, notice: "Experiment was successfully updated."
|
53
53
|
else
|
54
54
|
render :edit
|
55
55
|
end
|
@@ -69,7 +69,7 @@ module Leva
|
|
69
69
|
# Queue the job again
|
70
70
|
ExperimentJob.perform_later(@experiment)
|
71
71
|
|
72
|
-
redirect_to @experiment, notice:
|
72
|
+
redirect_to @experiment, notice: "Experiment has been reset and is now running again."
|
73
73
|
end
|
74
74
|
|
75
75
|
private
|
@@ -92,7 +92,7 @@ module Leva
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def check_editable
|
95
|
-
redirect_to @experiment, alert:
|
95
|
+
redirect_to @experiment, alert: "Completed experiments cannot be edited." if @experiment.completed?
|
96
96
|
end
|
97
97
|
end
|
98
|
-
end
|
98
|
+
end
|
@@ -4,9 +4,9 @@ module Leva
|
|
4
4
|
class WorkbenchController < ApplicationController
|
5
5
|
include ApplicationHelper
|
6
6
|
|
7
|
-
before_action :set_prompt, only: [:index, :edit, :update, :run, :run_all_evals, :run_evaluator]
|
8
|
-
before_action :set_dataset_record, only: [:index, :run, :run_all_evals, :run_evaluator]
|
9
|
-
before_action :set_runner_result, only: [:index, :run_all_evals, :run_evaluator]
|
7
|
+
before_action :set_prompt, only: [ :index, :edit, :update, :run, :run_all_evals, :run_evaluator ]
|
8
|
+
before_action :set_dataset_record, only: [ :index, :run, :run_all_evals, :run_evaluator ]
|
9
|
+
before_action :set_runner_result, only: [ :index, :run_all_evals, :run_evaluator ]
|
10
10
|
|
11
11
|
# GET /workbench
|
12
12
|
# @return [void]
|
@@ -17,6 +17,17 @@ module Leva
|
|
17
17
|
@runners = load_runners
|
18
18
|
@selected_runner = params[:runner] || @runners.first&.name
|
19
19
|
@selected_dataset_record = params[:dataset_record_id] || DatasetRecord.first&.id
|
20
|
+
|
21
|
+
# Get merged context if runner and dataset record are available
|
22
|
+
if @selected_runner && @dataset_record
|
23
|
+
runner_class = @selected_runner.constantize rescue nil
|
24
|
+
if runner_class && runner_class < Leva::BaseRun
|
25
|
+
runner = runner_class.new
|
26
|
+
@record_context = @dataset_record.recordable.to_llm_context
|
27
|
+
@runner_context = runner.to_llm_context(@dataset_record.recordable)
|
28
|
+
@merged_context = @record_context.merge(@runner_context)
|
29
|
+
end
|
30
|
+
end
|
20
31
|
end
|
21
32
|
|
22
33
|
# GET /workbench/new
|
@@ -31,7 +42,7 @@ module Leva
|
|
31
42
|
def create
|
32
43
|
@prompt = Prompt.new(prompt_params)
|
33
44
|
if @prompt.save
|
34
|
-
redirect_to workbench_index_path(prompt_id: @prompt.id), notice:
|
45
|
+
redirect_to workbench_index_path(prompt_id: @prompt.id), notice: "Prompt was successfully created."
|
35
46
|
else
|
36
47
|
render :new
|
37
48
|
end
|
@@ -47,45 +58,45 @@ module Leva
|
|
47
58
|
def update
|
48
59
|
@prompt = Prompt.find(params[:id])
|
49
60
|
if @prompt.update(prompt_params)
|
50
|
-
render json: { status:
|
61
|
+
render json: { status: "success", message: "Prompt updated successfully" }
|
51
62
|
else
|
52
|
-
render json: { status:
|
63
|
+
render json: { status: "error", errors: @prompt.errors.full_messages }, status: :unprocessable_entity
|
53
64
|
end
|
54
65
|
end
|
55
66
|
|
56
67
|
def run
|
57
|
-
return redirect_to workbench_index_path, alert:
|
68
|
+
return redirect_to workbench_index_path, alert: "Please select a record and a runner" unless @dataset_record && run_params[:runner]
|
58
69
|
|
59
70
|
runner_class = run_params[:runner].constantize
|
60
|
-
return redirect_to workbench_index_path, alert:
|
71
|
+
return redirect_to workbench_index_path, alert: "Invalid runner selected" unless runner_class < Leva::BaseRun
|
61
72
|
|
62
73
|
runner = runner_class.new
|
63
74
|
runner_result = runner.execute_and_store(nil, @dataset_record, @prompt)
|
64
75
|
|
65
|
-
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: run_params[:runner]), notice:
|
76
|
+
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: run_params[:runner]), notice: "Run completed successfully"
|
66
77
|
end
|
67
78
|
|
68
79
|
def run_all_evals
|
69
|
-
return redirect_to workbench_index_path, alert:
|
80
|
+
return redirect_to workbench_index_path, alert: "No runner result available" unless @runner_result
|
70
81
|
|
71
82
|
load_evaluators.each do |evaluator_class|
|
72
83
|
evaluator = evaluator_class.new
|
73
84
|
evaluator.evaluate_and_store(nil, @runner_result)
|
74
85
|
end
|
75
86
|
|
76
|
-
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: params[:runner]), notice:
|
87
|
+
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: params[:runner]), notice: "All evaluations completed successfully"
|
77
88
|
end
|
78
89
|
|
79
90
|
def run_evaluator
|
80
|
-
return redirect_to workbench_index_path, alert:
|
91
|
+
return redirect_to workbench_index_path, alert: "No runner result available" unless @runner_result
|
81
92
|
|
82
93
|
evaluator_class = params[:evaluator].constantize
|
83
|
-
return redirect_to workbench_index_path, alert:
|
94
|
+
return redirect_to workbench_index_path, alert: "Invalid evaluator selected" unless evaluator_class < Leva::BaseEval
|
84
95
|
|
85
96
|
evaluator = evaluator_class.new
|
86
97
|
evaluator.evaluate_and_store(nil, @runner_result)
|
87
98
|
|
88
|
-
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: params[:runner]), notice:
|
99
|
+
redirect_to workbench_index_path(prompt_id: @prompt.id, dataset_record_id: @dataset_record.id, runner: params[:runner]), notice: "Evaluator run successfully"
|
89
100
|
end
|
90
101
|
|
91
102
|
private
|
@@ -110,4 +121,4 @@ module Leva
|
|
110
121
|
@runner_result = @dataset_record.runner_results.last if @dataset_record
|
111
122
|
end
|
112
123
|
end
|
113
|
-
end
|
124
|
+
end
|
@@ -4,24 +4,24 @@ module Leva
|
|
4
4
|
#
|
5
5
|
# @return [Array<Class>] An array of evaluator classes
|
6
6
|
def load_evaluators
|
7
|
-
load_classes_from_directory(
|
7
|
+
load_classes_from_directory("app/evals", Leva::BaseEval) || []
|
8
8
|
end
|
9
9
|
|
10
10
|
# Loads all runner classes that inherit from Leva::BaseRun
|
11
11
|
#
|
12
12
|
# @return [Array<Class>] An array of runner classes
|
13
13
|
def load_runners
|
14
|
-
load_classes_from_directory(
|
14
|
+
load_classes_from_directory("app/runners", Leva::BaseRun) || []
|
15
15
|
end
|
16
16
|
|
17
17
|
# Loads predefined prompts from markdown files
|
18
18
|
#
|
19
19
|
# @return [Array<Array<String, String>>] An array of prompt name and content pairs
|
20
20
|
def load_predefined_prompts
|
21
|
-
prompts = Dir.glob(Rails.root.join(
|
22
|
-
name = File.basename(file,
|
21
|
+
prompts = Dir.glob(Rails.root.join("app", "prompts", "*.md")).map do |file|
|
22
|
+
name = File.basename(file, ".md").titleize
|
23
23
|
content = File.read(file)
|
24
|
-
[name, content]
|
24
|
+
[ name, content ]
|
25
25
|
end
|
26
26
|
prompts
|
27
27
|
end
|
@@ -34,8 +34,8 @@ module Leva
|
|
34
34
|
# @param base_class [Class] The base class that loaded classes should inherit from
|
35
35
|
# @return [Array<Class>] An array of loaded classes
|
36
36
|
def load_classes_from_directory(directory, base_class)
|
37
|
-
classes = Dir[Rails.root.join(directory,
|
38
|
-
File.basename(file,
|
37
|
+
classes = Dir[Rails.root.join(directory, "*.rb")].map do |file|
|
38
|
+
File.basename(file, ".rb").camelize.constantize
|
39
39
|
end.select { |klass| klass < base_class }
|
40
40
|
classes.empty? ? [] : classes
|
41
41
|
end
|
@@ -3,10 +3,10 @@ module Leva
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
has_many :dataset_records, as: :recordable, class_name:
|
7
|
-
has_many :datasets, through: :dataset_records, class_name:
|
8
|
-
has_many :runner_results, through: :dataset_records, class_name:
|
9
|
-
has_many :evaluation_results, through: :runner_results, class_name:
|
6
|
+
has_many :dataset_records, as: :recordable, class_name: "Leva::DatasetRecord", dependent: :destroy
|
7
|
+
has_many :datasets, through: :dataset_records, class_name: "Leva::Dataset"
|
8
|
+
has_many :runner_results, through: :dataset_records, class_name: "Leva::RunnerResult"
|
9
|
+
has_many :evaluation_results, through: :runner_results, class_name: "Leva::EvaluationResult"
|
10
10
|
end
|
11
11
|
|
12
12
|
# @return [String] The ground truth label for the record
|
@@ -34,4 +34,4 @@ module Leva
|
|
34
34
|
false
|
35
35
|
end
|
36
36
|
end
|
37
|
-
end
|
37
|
+
end
|
data/app/models/leva/dataset.rb
CHANGED
data/app/models/leva/prompt.rb
CHANGED
@@ -8,7 +8,6 @@
|
|
8
8
|
<%= csp_meta_tag %>
|
9
9
|
<script src="https://cdn.tailwindcss.com"></script>
|
10
10
|
<script src="https://cdn.jsdelivr.net/npm/stimulus@3.2.2/dist/stimulus.umd.min.js"></script>
|
11
|
-
<script src="<%= asset_path 'custom/prompt_preview.js' %>"></script>
|
12
11
|
<%= yield(:head) %>
|
13
12
|
</head>
|
14
13
|
<body class="bg-gray-950 text-white">
|
@@ -12,38 +12,63 @@
|
|
12
12
|
</div>
|
13
13
|
</div>
|
14
14
|
|
15
|
-
|
16
|
-
<
|
17
|
-
<
|
18
|
-
<
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
<th scope="col" class="relative px-6 py-3">
|
25
|
-
<span class="sr-only">Actions</span>
|
26
|
-
</th>
|
27
|
-
</tr>
|
28
|
-
</thead>
|
29
|
-
<tbody class="bg-gray-800 divide-y divide-gray-700">
|
30
|
-
<% @records.each do |record| %>
|
31
|
-
<tr class="hover:bg-gray-700 transition-colors duration-200">
|
32
|
-
<% record.index_attributes.values.each do |value| %>
|
33
|
-
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-300">
|
34
|
-
<%= value %>
|
35
|
-
</td>
|
15
|
+
<% if @records.any? %>
|
16
|
+
<div class="bg-gray-800 rounded-lg shadow-lg overflow-hidden">
|
17
|
+
<table class="min-w-full divide-y divide-gray-700">
|
18
|
+
<thead class="bg-gray-700">
|
19
|
+
<tr>
|
20
|
+
<% @records.first.index_attributes.keys.each do |key| %>
|
21
|
+
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">
|
22
|
+
<%= key.to_s.humanize %>
|
23
|
+
</th>
|
36
24
|
<% end %>
|
37
|
-
<
|
38
|
-
|
39
|
-
</
|
25
|
+
<th scope="col" class="relative px-6 py-3">
|
26
|
+
<span class="sr-only">Actions</span>
|
27
|
+
</th>
|
40
28
|
</tr>
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
29
|
+
</thead>
|
30
|
+
<tbody class="bg-gray-800 divide-y divide-gray-700">
|
31
|
+
<% @records.each do |record| %>
|
32
|
+
<tr class="hover:bg-gray-700 transition-colors duration-200">
|
33
|
+
<% record.index_attributes.values.each do |value| %>
|
34
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-300">
|
35
|
+
<%= value %>
|
36
|
+
</td>
|
37
|
+
<% end %>
|
38
|
+
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
39
|
+
<%= link_to 'View', dataset_dataset_record_path(@dataset, record), class: 'text-indigo-400 hover:text-indigo-300 transition-colors duration-200' %>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
<% end %>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
45
|
+
</div>
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
<div class="mt-4 text-gray-400 text-sm">
|
48
|
+
Total records: <%= @records.count %>
|
49
|
+
</div>
|
50
|
+
<% else %>
|
51
|
+
<div class="bg-gray-800 rounded-lg shadow-lg p-12 text-center">
|
52
|
+
<svg class="mx-auto h-12 w-12 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
53
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
54
|
+
</svg>
|
55
|
+
<h3 class="mt-2 text-xl font-medium text-indigo-300">No records yet</h3>
|
56
|
+
<p class="mt-1 text-gray-400">This dataset doesn't contain any records yet.</p>
|
57
|
+
<div class="mt-4 text-sm text-gray-500">
|
58
|
+
<p>To add records to this dataset, use the Rails console or create them programmatically:</p>
|
59
|
+
<div class="mt-2 bg-gray-900 rounded px-3 py-2 text-left font-mono text-xs text-gray-300">
|
60
|
+
<p>dataset = Leva::Dataset.find(<%= @dataset.id %>)</p>
|
61
|
+
<p>dataset.add_record(your_model_instance)</p>
|
62
|
+
</div>
|
63
|
+
</div>
|
64
|
+
<div class="mt-6">
|
65
|
+
<%= link_to dataset_path(@dataset), class: "btn btn-secondary inline-flex items-center" do %>
|
66
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
67
|
+
<path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd" />
|
68
|
+
</svg>
|
69
|
+
Back to Dataset
|
70
|
+
<% end %>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
<% end %>
|
49
74
|
</div>
|
@@ -1,5 +1,32 @@
|
|
1
1
|
<% content_for :title, 'New Experiment' %>
|
2
2
|
<div class="container mx-auto px-4 py-8 bg-gray-950 text-white">
|
3
3
|
<h1 class="text-3xl font-bold text-indigo-400 mb-6">New Experiment</h1>
|
4
|
-
|
4
|
+
<% if @runners.present? %>
|
5
|
+
<%= render 'form', experiment: @experiment %>
|
6
|
+
<% else %>
|
7
|
+
<div class="bg-gray-800 rounded-lg shadow-lg p-12 text-center">
|
8
|
+
<svg class="mx-auto h-12 w-12 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
9
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
10
|
+
</svg>
|
11
|
+
<h3 class="mt-2 text-xl font-medium text-yellow-300">No runners available</h3>
|
12
|
+
<p class="mt-1 text-gray-400">You need at least one runner to create an experiment.</p>
|
13
|
+
<div class="mt-6 text-left bg-gray-900 rounded-lg p-6">
|
14
|
+
<h4 class="text-lg font-semibold text-indigo-300 mb-3">What are runners?</h4>
|
15
|
+
<p class="text-gray-300 mb-4">Runners define how your model processes dataset records. They contain the execution logic that takes a dataset record and returns a prediction.</p>
|
16
|
+
<h4 class="text-lg font-semibold text-indigo-300 mb-3">Create your first runner:</h4>
|
17
|
+
<div class="bg-gray-800 rounded p-3 mb-4">
|
18
|
+
<code class="text-green-400">rails generate leva:runner sentiment</code>
|
19
|
+
</div>
|
20
|
+
<p class="text-gray-400 text-sm">This will create <code class="text-gray-300">app/runners/sentiment_run.rb</code> with a template to implement your model logic.</p>
|
21
|
+
</div>
|
22
|
+
<div class="mt-6">
|
23
|
+
<%= link_to experiments_path, class: "btn btn-secondary inline-flex items-center" do %>
|
24
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
25
|
+
<path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd" />
|
26
|
+
</svg>
|
27
|
+
Back to Experiments
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
5
32
|
</div>
|
@@ -48,19 +48,65 @@
|
|
48
48
|
</svg>
|
49
49
|
</h2>
|
50
50
|
<div class="bg-gray-800 p-3 rounded-lg text-sm hidden" data-collapsible-target="content">
|
51
|
-
<%
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
51
|
+
<% # Use merged context if available, otherwise just record context %>
|
52
|
+
<% context_to_display = @merged_context || @dataset_record.recordable.to_llm_context %>
|
53
|
+
|
54
|
+
<% if @record_context && @runner_context %>
|
55
|
+
<!-- Record Context -->
|
56
|
+
<div class="mb-4">
|
57
|
+
<h3 class="text-xs font-semibold text-gray-400 mb-2">FROM RECORD:</h3>
|
58
|
+
<% @record_context.each do |key, value| %>
|
59
|
+
<details class="mb-2">
|
60
|
+
<summary class="text-green-400 cursor-pointer flex items-center justify-between">
|
61
|
+
<span>{{ <%= key %> }}</span>
|
62
|
+
<button class="btn btn-small text-blue-400 hover:text-blue-300 flex items-center" data-action="clipboard#copy" data-clipboard-source="liquidTag<%= key %>">
|
63
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
64
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
|
65
|
+
</svg>
|
66
|
+
Copy
|
67
|
+
</button>
|
68
|
+
</summary>
|
69
|
+
<pre class="text-xs text-gray-300 mt-1 whitespace-pre-wrap break-words overflow-x-auto max-w-full" id="liquidTag<%= key %>"><%= value.to_s %></pre>
|
70
|
+
</details>
|
71
|
+
<% end %>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<!-- Runner Context -->
|
75
|
+
<% if @runner_context.any? %>
|
76
|
+
<div class="mb-4">
|
77
|
+
<h3 class="text-xs font-semibold text-gray-400 mb-2">FROM RUNNER:</h3>
|
78
|
+
<% @runner_context.each do |key, value| %>
|
79
|
+
<details class="mb-2">
|
80
|
+
<summary class="text-yellow-400 cursor-pointer flex items-center justify-between">
|
81
|
+
<span>{{ <%= key %> }}</span>
|
82
|
+
<button class="btn btn-small text-blue-400 hover:text-blue-300 flex items-center" data-action="clipboard#copy" data-clipboard-source="liquidTag<%= key %>">
|
83
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
84
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
|
85
|
+
</svg>
|
86
|
+
Copy
|
87
|
+
</button>
|
88
|
+
</summary>
|
89
|
+
<pre class="text-xs text-gray-300 mt-1 whitespace-pre-wrap break-words overflow-x-auto max-w-full" id="liquidTag<%= key %>"><%= value.to_s %></pre>
|
90
|
+
</details>
|
91
|
+
<% end %>
|
92
|
+
</div>
|
93
|
+
<% end %>
|
94
|
+
<% else %>
|
95
|
+
<!-- Fallback to original display -->
|
96
|
+
<% context_to_display.each do |key, value| %>
|
97
|
+
<details class="mb-2">
|
98
|
+
<summary class="text-green-400 cursor-pointer flex items-center justify-between">
|
99
|
+
<span>{{ <%= key %> }}</span>
|
100
|
+
<button class="btn btn-small text-blue-400 hover:text-blue-300 flex items-center" data-action="clipboard#copy" data-clipboard-source="liquidTag<%= key %>">
|
101
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
102
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
|
103
|
+
</svg>
|
104
|
+
Copy
|
105
|
+
</button>
|
106
|
+
</summary>
|
107
|
+
<pre class="text-xs text-gray-300 mt-1 whitespace-pre-wrap break-words overflow-x-auto max-w-full" id="liquidTag<%= key %>"><%= value.to_s %></pre>
|
108
|
+
</details>
|
109
|
+
<% end %>
|
64
110
|
<% end %>
|
65
111
|
</div>
|
66
112
|
</div>
|
@@ -77,7 +123,7 @@
|
|
77
123
|
Copy
|
78
124
|
</button>
|
79
125
|
</div>
|
80
|
-
<pre class="w-full bg-gray-800 text-white p-3 rounded-lg text-sm whitespace-pre-wrap overflow-x-auto break-words max-w-full" id="fullPrompt"><%= Liquid::Template.parse(@selected_prompt.user_prompt).render(@dataset_record.recordable.to_llm_context.stringify_keys) %></pre>
|
126
|
+
<pre class="w-full bg-gray-800 text-white p-3 rounded-lg text-sm whitespace-pre-wrap overflow-x-auto break-words max-w-full" id="fullPrompt"><%= Liquid::Template.parse(@selected_prompt.user_prompt).render((@merged_context || @dataset_record.recordable.to_llm_context).stringify_keys) %></pre>
|
81
127
|
</div>
|
82
128
|
<% end %>
|
83
129
|
<div class="text-sm text-center" data-prompt-autosave-target="status"></div>
|
data/config/routes.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
Leva::Engine.routes.draw do
|
2
|
-
root
|
2
|
+
root "workbench#index"
|
3
3
|
|
4
4
|
resources :datasets do
|
5
|
-
resources :dataset_records, path:
|
5
|
+
resources :dataset_records, path: "records", only: [ :index, :show ]
|
6
6
|
end
|
7
|
-
resources :experiments, except: [:destroy] do
|
7
|
+
resources :experiments, except: [ :destroy ] do
|
8
8
|
member do
|
9
9
|
post :rerun
|
10
10
|
end
|
11
|
-
resources :runner_results, only: [:show]
|
11
|
+
resources :runner_results, only: [ :show ]
|
12
12
|
end
|
13
13
|
resources :prompts
|
14
|
-
resources :workbench, only: [:index, :new, :create, :edit, :update] do
|
14
|
+
resources :workbench, only: [ :index, :new, :create, :edit, :update ] do
|
15
15
|
collection do
|
16
|
-
post
|
17
|
-
post
|
18
|
-
post
|
16
|
+
post "run"
|
17
|
+
post "run_all_evals"
|
18
|
+
post "run_evaluator"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
@@ -3,6 +3,7 @@ class CreateLevaDatasetRecords < ActiveRecord::Migration[7.2]
|
|
3
3
|
create_table :leva_dataset_records do |t|
|
4
4
|
t.references :dataset, null: false, foreign_key: { to_table: :leva_datasets }
|
5
5
|
t.references :recordable, polymorphic: true, null: false
|
6
|
+
t.text :actual_result
|
6
7
|
|
7
8
|
t.timestamps
|
8
9
|
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
class CreateLevaRunnerResults < ActiveRecord::Migration[7.2]
|
2
2
|
def change
|
3
3
|
create_table :leva_runner_results do |t|
|
4
|
-
t.references :experiment, null:
|
4
|
+
t.references :experiment, null: true, foreign_key: { to_table: :leva_experiments }
|
5
5
|
t.references :dataset_record, null: false, foreign_key: { to_table: :leva_dataset_records }
|
6
|
+
t.references :prompt, null: false, foreign_key: { to_table: :leva_prompts }
|
7
|
+
t.integer :prompt_version
|
6
8
|
t.text :prediction
|
9
|
+
t.string :runner_class
|
7
10
|
|
8
11
|
t.timestamps
|
9
12
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class CreateLevaEvaluationResults < ActiveRecord::Migration[7.2]
|
2
2
|
def change
|
3
3
|
create_table :leva_evaluation_results do |t|
|
4
|
-
t.references :experiment, null:
|
4
|
+
t.references :experiment, null: true, foreign_key: { to_table: :leva_experiments }
|
5
5
|
t.references :dataset_record, null: false, foreign_key: { to_table: :leva_dataset_records }
|
6
|
-
t.
|
6
|
+
t.references :runner_result, null: false, foreign_key: { to_table: :leva_runner_results }
|
7
|
+
t.string :evaluator_class, null: false
|
7
8
|
t.float :score
|
8
|
-
t.string :label
|
9
9
|
|
10
10
|
t.timestamps
|
11
11
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module Leva
|
4
4
|
module Generators
|
5
5
|
class EvalGenerator < Rails::Generators::NamedBase
|
6
|
-
source_root File.expand_path(
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
7
|
|
8
8
|
def create_eval_file
|
9
|
-
template
|
9
|
+
template "eval.rb.erb", File.join("app/evals", class_path, "#{file_name}_eval.rb")
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -16,8 +16,8 @@ module Leva
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def remove_possible_suffix(name)
|
19
|
-
name.sub(/_?eval$/i,
|
19
|
+
name.sub(/_?eval$/i, "")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module Leva
|
4
4
|
module Generators
|
5
5
|
class RunnerGenerator < Rails::Generators::NamedBase
|
6
|
-
source_root File.expand_path(
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
7
|
|
8
8
|
def create_runner_file
|
9
|
-
template
|
9
|
+
template "runner.rb.erb", File.join("app/runners", class_path, "#{file_name}_run.rb")
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -16,8 +16,8 @@ module Leva
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def remove_possible_suffix(name)
|
19
|
-
name.sub(/_?runner$/i,
|
19
|
+
name.sub(/_?runner$/i, "")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end
|
@@ -33,4 +33,24 @@ class <%= class_name %>Run < Leva::BaseRun
|
|
33
33
|
# # For example:
|
34
34
|
# # /\<result\>(.*?)\<\/result\>/
|
35
35
|
# end
|
36
|
+
|
37
|
+
# Override this method to provide additional context for LLM prompts
|
38
|
+
# This is useful for expensive operations or runner-specific data
|
39
|
+
# that you don't want to compute in the record's to_llm_context
|
40
|
+
#
|
41
|
+
# @param record [YourRecordClass] The record to generate context for
|
42
|
+
# @return [Hash] Additional context to merge with the record's context
|
43
|
+
# def to_llm_context(record)
|
44
|
+
# # Example: Add runner-specific expensive computations
|
45
|
+
# {
|
46
|
+
# # Count of similar records (expensive database query)
|
47
|
+
# similar_<%= singular_name %>_count: record.class.where(
|
48
|
+
# "some_field LIKE ?", "%#{record.some_field.split.first}%"
|
49
|
+
# ).count,
|
50
|
+
#
|
51
|
+
# # Runner-specific configuration
|
52
|
+
# model_version: "v1.2.3",
|
53
|
+
# temperature: 0.7
|
54
|
+
# }
|
55
|
+
# end
|
36
56
|
end
|
data/lib/leva/version.rb
CHANGED
data/lib/leva.rb
CHANGED
@@ -65,6 +65,7 @@ module Leva
|
|
65
65
|
# Expose these to the subclass execution
|
66
66
|
@experiment = experiment
|
67
67
|
@prompt = prompt
|
68
|
+
@dataset_record = dataset_record
|
68
69
|
|
69
70
|
result = execute(dataset_record.recordable)
|
70
71
|
RunnerResult.create!(
|
@@ -76,13 +77,25 @@ module Leva
|
|
76
77
|
)
|
77
78
|
end
|
78
79
|
|
80
|
+
# Gets the merged LLM context for the current execution.
|
81
|
+
# Combines the record's context with the runner's additional context.
|
82
|
+
#
|
83
|
+
# @return [Hash] The merged context for LLM prompt rendering
|
84
|
+
def merged_llm_context
|
85
|
+
return {} unless @dataset_record
|
86
|
+
|
87
|
+
record_context = @dataset_record.recordable.to_llm_context
|
88
|
+
runner_context = to_llm_context(@dataset_record.recordable)
|
89
|
+
record_context.merge(runner_context)
|
90
|
+
end
|
91
|
+
|
79
92
|
# @param runner_result [Leva::RunnerResult] The runner result to parse
|
80
93
|
# @return [Array<String>] The parsed predictions
|
81
94
|
def parsed_predictions(runner_result)
|
82
95
|
if extract_regex_pattern(runner_result)
|
83
96
|
runner_result.prediction.scan(extract_regex_pattern(runner_result)).map { |match| match.first&.strip }.compact
|
84
97
|
else
|
85
|
-
[runner_result.prediction]
|
98
|
+
[ runner_result.prediction ]
|
86
99
|
end
|
87
100
|
end
|
88
101
|
|
@@ -97,6 +110,15 @@ module Leva
|
|
97
110
|
def ground_truth(runner_result)
|
98
111
|
runner_result.dataset_record.ground_truth
|
99
112
|
end
|
113
|
+
|
114
|
+
# Provides additional LLM context specific to this runner.
|
115
|
+
# Override in subclasses to add expensive or runner-specific context.
|
116
|
+
#
|
117
|
+
# @param record [Object] The recordable object to generate context for
|
118
|
+
# @return [Hash] Additional context to merge with the record's context
|
119
|
+
def to_llm_context(record)
|
120
|
+
{}
|
121
|
+
end
|
100
122
|
end
|
101
123
|
|
102
124
|
# Base class for all evaluation implementations in Leva.
|
@@ -134,4 +156,4 @@ module Leva
|
|
134
156
|
)
|
135
157
|
end
|
136
158
|
end
|
137
|
-
end
|
159
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leva
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kieran Klaassen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -103,15 +103,8 @@ files:
|
|
103
103
|
- db/migrate/20240813173033_create_leva_dataset_records.rb
|
104
104
|
- db/migrate/20240813173034_create_leva_prompts.rb
|
105
105
|
- db/migrate/20240813173035_create_leva_experiments.rb
|
106
|
+
- db/migrate/20240813173040_create_leva_runner_results.rb
|
106
107
|
- db/migrate/20240813173050_create_leva_evaluation_results.rb
|
107
|
-
- db/migrate/20240816201419_create_leva_runner_results.rb
|
108
|
-
- db/migrate/20240816201433_update_leva_evaluation_results.rb
|
109
|
-
- db/migrate/20240821163608_make_experiment_optional_for_runner_results.rb
|
110
|
-
- db/migrate/20240821181934_add_prompt_to_leva_runner_results.rb
|
111
|
-
- db/migrate/20240821183153_add_runner_and_evaluator_to_leva_experiments.rb
|
112
|
-
- db/migrate/20240821191713_add_actual_result_to_leva_dataset_records.rb
|
113
|
-
- db/migrate/20240822143201_remove_actual_result_from_leva_runner_results.rb
|
114
|
-
- db/migrate/20240912183556_add_runner_class_to_leva_runner_results.rb
|
115
108
|
- lib/generators/leva/eval_generator.rb
|
116
109
|
- lib/generators/leva/runner_generator.rb
|
117
110
|
- lib/generators/leva/templates/eval.rb.erb
|
@@ -119,7 +112,6 @@ files:
|
|
119
112
|
- lib/leva.rb
|
120
113
|
- lib/leva/engine.rb
|
121
114
|
- lib/leva/version.rb
|
122
|
-
- lib/tasks/auto_annotate_models.rake
|
123
115
|
- lib/tasks/leva_tasks.rake
|
124
116
|
homepage: https://github.com/kieranklaassen/leva
|
125
117
|
licenses:
|
@@ -1,8 +0,0 @@
|
|
1
|
-
class UpdateLevaEvaluationResults < ActiveRecord::Migration[7.2]
|
2
|
-
def change
|
3
|
-
add_reference :leva_evaluation_results, :runner_result, null: false, foreign_key: { to_table: :leva_runner_results }
|
4
|
-
add_column :leva_evaluation_results, :evaluator_class, :string, null: false
|
5
|
-
remove_column :leva_evaluation_results, :prediction, :string
|
6
|
-
remove_column :leva_evaluation_results, :label, :string
|
7
|
-
end
|
8
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# NOTE: only doing this in development as some production environments (Heroku)
|
2
|
-
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
|
3
|
-
# NOTE: to have a dev-mode tool do its thing in production.
|
4
|
-
if Rails.env.development?
|
5
|
-
require 'annotate'
|
6
|
-
task :set_annotation_options do
|
7
|
-
# You can override any of these by setting an environment variable of the
|
8
|
-
# same name.
|
9
|
-
Annotate.set_defaults(
|
10
|
-
'active_admin' => 'false',
|
11
|
-
'additional_file_patterns' => [],
|
12
|
-
'routes' => 'false',
|
13
|
-
'models' => 'true',
|
14
|
-
'position_in_routes' => 'before',
|
15
|
-
'position_in_class' => 'before',
|
16
|
-
'position_in_test' => 'before',
|
17
|
-
'position_in_fixture' => 'before',
|
18
|
-
'position_in_factory' => 'before',
|
19
|
-
'position_in_serializer' => 'before',
|
20
|
-
'show_foreign_keys' => 'true',
|
21
|
-
'show_complete_foreign_keys' => 'false',
|
22
|
-
'show_indexes' => 'true',
|
23
|
-
'simple_indexes' => 'false',
|
24
|
-
'model_dir' => 'app/models',
|
25
|
-
'root_dir' => '',
|
26
|
-
'include_version' => 'false',
|
27
|
-
'require' => '',
|
28
|
-
'exclude_tests' => 'false',
|
29
|
-
'exclude_fixtures' => 'false',
|
30
|
-
'exclude_factories' => 'false',
|
31
|
-
'exclude_serializers' => 'false',
|
32
|
-
'exclude_scaffolds' => 'true',
|
33
|
-
'exclude_controllers' => 'true',
|
34
|
-
'exclude_helpers' => 'true',
|
35
|
-
'exclude_sti_subclasses' => 'false',
|
36
|
-
'ignore_model_sub_dir' => 'false',
|
37
|
-
'ignore_columns' => nil,
|
38
|
-
'ignore_routes' => nil,
|
39
|
-
'ignore_unknown_models' => 'false',
|
40
|
-
'hide_limit_column_types' => 'integer,bigint,boolean',
|
41
|
-
'hide_default_column_types' => 'json,jsonb,hstore',
|
42
|
-
'skip_on_db_migrate' => 'false',
|
43
|
-
'format_bare' => 'true',
|
44
|
-
'format_rdoc' => 'false',
|
45
|
-
'format_yard' => 'false',
|
46
|
-
'format_markdown' => 'false',
|
47
|
-
'sort' => 'false',
|
48
|
-
'force' => 'false',
|
49
|
-
'frozen' => 'false',
|
50
|
-
'classified_sort' => 'true',
|
51
|
-
'trace' => 'false',
|
52
|
-
'wrapper_open' => nil,
|
53
|
-
'wrapper_close' => nil,
|
54
|
-
'with_comment' => 'true'
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
|
-
Annotate.load_tasks
|
59
|
-
end
|