completion-kit 0.27.0 → 0.27.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0fa2b7edcc463d34ce7dbed34a522119f840778bd75fa9912124069564420dd
4
- data.tar.gz: 16e1aa2310b4efd26c67fcf70ac55dedb0bd760e97201f41bdb9c73f98247070
3
+ metadata.gz: 7f8fdeef847d7243a665b86e111343d0255ac2eb56ba6538c56c21871de04d1c
4
+ data.tar.gz: 58911d7d679a943284eacaaca586c6ad375efdf674aa1604f9895ca971f80c2e
5
5
  SHA512:
6
- metadata.gz: '0572479a9194f494f34f4982c563dc5b3ffae3c1e430c0b39786ea05a6eac15359d7f51946810c8208bf60eb43274554b152d981b492d9fe9a04a01c7c8cb23b'
7
- data.tar.gz: 931853452dac7e901d2e8eed066011c7f428aed7290d68d86787b0c029a9d4f7e0e1b0888ed2adefe015093a6f423487b433731e6a4826ac9dcf5ca255943e62
6
+ metadata.gz: fd44b864ef07239759b9211cf24dac1aad601d30bd1b92068e5e2952571e338decb85be400464c1c3a947f40040c14aeea74384512594290f79dbfddbed19555
7
+ data.tar.gz: ad879e8ebc9f77dab47592f23b3bf0a6ae7eb101e11dc07e43a1ed7b67caa19fde109b3dcc20ab445c3a0c4daebb843b442b1de69ec9e433a3fe5da9d7d5c661
@@ -25,10 +25,16 @@ module CompletionKit
25
25
 
26
26
  def update
27
27
  if @prompt.runs.exists?
28
- new_prompt = @prompt.clone_as_new_version(prompt_params.except(:tag_names).to_h)
29
- new_prompt.publish!
30
- new_prompt.update!(tag_names: prompt_params[:tag_names]) if prompt_params.key?(:tag_names)
31
- render json: new_prompt.reload
28
+ new_prompt = @prompt.build_next_version(prompt_params.to_h)
29
+ if new_prompt.valid?
30
+ CompletionKit::ApplicationRecord.transaction do
31
+ new_prompt.save!
32
+ new_prompt.publish!
33
+ end
34
+ render json: new_prompt.reload
35
+ else
36
+ render_validation_errors(new_prompt)
37
+ end
32
38
  elsif @prompt.update(prompt_params)
33
39
  render json: @prompt
34
40
  else
@@ -33,10 +33,18 @@ module CompletionKit
33
33
 
34
34
  def update
35
35
  if @prompt.runs.exists?
36
- new_prompt = @prompt.clone_as_new_version(prompt_params.except(:tag_names).to_h)
37
- new_prompt.publish!
38
- new_prompt.update!(tag_names: prompt_params[:tag_names]) if prompt_params.key?(:tag_names)
39
- redirect_to prompt_path(new_prompt), notice: "Saved as #{new_prompt.version_label}."
36
+ new_prompt = @prompt.build_next_version(prompt_params.to_h)
37
+ if new_prompt.valid?
38
+ CompletionKit::ApplicationRecord.transaction do
39
+ new_prompt.save!
40
+ new_prompt.publish!
41
+ end
42
+ redirect_to prompt_path(new_prompt), notice: "Saved as #{new_prompt.version_label}."
43
+ else
44
+ @prompt.assign_attributes(prompt_params.to_h)
45
+ @prompt.errors.merge!(new_prompt.errors)
46
+ render :edit, status: :unprocessable_entity
47
+ end
40
48
  elsif @prompt.update(prompt_params)
41
49
  redirect_to prompt_path(@prompt), notice: "Prompt saved."
42
50
  else
@@ -5,10 +5,12 @@ module CompletionKit
5
5
  has_many :runs, dependent: :destroy
6
6
  has_many :responses, through: :runs
7
7
 
8
+ attr_accessor :cloned_from_llm_model
9
+
8
10
  validates :name, presence: true
9
11
  validates :template, presence: true
10
12
  validates :llm_model, presence: true
11
- validate :llm_model_usable_for_generation, if: :llm_model_changed?
13
+ validate :llm_model_usable_for_generation, if: :llm_model_newly_selected?
12
14
  validates :family_key, presence: true
13
15
  validates :version_number, presence: true, numericality: { only_integer: true, greater_than: 0 }
14
16
 
@@ -53,8 +55,8 @@ module CompletionKit
53
55
  self.class.where(family_key: family_key).order(version_number: :desc, created_at: :desc)
54
56
  end
55
57
 
56
- def clone_as_new_version(overrides = {})
57
- self.class.create!(
58
+ def build_next_version(overrides = {})
59
+ version = self.class.new(
58
60
  {
59
61
  name: name,
60
62
  description: description,
@@ -66,6 +68,14 @@ module CompletionKit
66
68
  published_at: nil
67
69
  }.merge(overrides.compact)
68
70
  )
71
+ version.cloned_from_llm_model = llm_model
72
+ version
73
+ end
74
+
75
+ def clone_as_new_version(overrides = {})
76
+ version = build_next_version(overrides)
77
+ version.save!
78
+ version
69
79
  end
70
80
 
71
81
  def publish!
@@ -87,9 +97,14 @@ module CompletionKit
87
97
 
88
98
  private
89
99
 
90
- def llm_model_usable_for_generation
91
- return if llm_model.blank?
100
+ def llm_model_newly_selected?
101
+ return false if llm_model.blank?
102
+ return llm_model != cloned_from_llm_model if new_record? && cloned_from_llm_model.present?
103
+
104
+ llm_model_changed?
105
+ end
92
106
 
107
+ def llm_model_usable_for_generation
93
108
  rows = Model.where(model_id: llm_model)
94
109
  return if rows.empty?
95
110
  return if rows.where(supports_generation: true, status: "active").exists?
@@ -7,18 +7,42 @@ module CompletionKit
7
7
  class_name: "CompletionKit::Tagging",
8
8
  dependent: :destroy
9
9
  has_many :tags, through: :taggings, class_name: "CompletionKit::Tag"
10
+
11
+ validate :assigned_tag_names_are_valid, if: -> { @tag_names_assigned }
12
+ after_save :sync_assigned_tags, if: -> { @tag_names_assigned }
10
13
  end
11
14
 
12
15
  def tag_names
16
+ return @assigned_tag_names if @tag_names_assigned
17
+
13
18
  tags.pluck(:name)
14
19
  end
15
20
 
16
21
  def tag_names=(names)
17
- resolved = Array(names)
22
+ @tag_names_assigned = true
23
+ @assigned_tag_names = Array(names)
18
24
  .map { |n| n.to_s.strip.downcase }
19
25
  .reject(&:blank?)
20
26
  .uniq
21
- self.tags = resolved.map { |name| CompletionKit::Tag.find_or_create_by!(name: name) }
27
+ end
28
+
29
+ private
30
+
31
+ def assigned_tag_names_are_valid
32
+ @assigned_tag_names.each do |name|
33
+ next if CompletionKit::Tag.exists?(name: name)
34
+
35
+ probe = CompletionKit::Tag.new(name: name)
36
+ next if probe.valid?
37
+
38
+ errors.add(:base, "Tag \"#{name}\" is not allowed: #{probe.errors[:name].to_sentence}")
39
+ end
40
+ end
41
+
42
+ def sync_assigned_tags
43
+ self.tags = @assigned_tag_names.map { |name| CompletionKit::Tag.find_or_create_by!(name: name) }
44
+ @tag_names_assigned = false
45
+ @assigned_tag_names = nil
22
46
  end
23
47
  end
24
48
  end
@@ -27,6 +27,8 @@ module CompletionKit
27
27
  metrics = import_metrics(config)
28
28
  Result.new(ok: true, error: nil, prompts: prompts, dataset: dataset, metrics: metrics, providers: providers)
29
29
  end
30
+ rescue ActiveRecord::RecordInvalid => e
31
+ failure(e.record.errors.full_messages.to_sentence.presence || e.message)
30
32
  end
31
33
 
32
34
  private
@@ -79,7 +79,9 @@
79
79
  </div>
80
80
  <% if @response.status == "failed" %>
81
81
  <% err = @response.error_payload || {} %>
82
- <div class="ck-code-scroll-wrap"><pre class="ck-code ck-code--error"><%= err[:provider]&.titleize %><%= " #{err[:status]}" if err[:status].present? %><%= "\n\n" if err[:provider].present? || err[:status].present? %><%= err[:message] %></pre></div>
82
+ <% head = [err[:provider]&.titleize, err[:status].presence].compact.join(" ").presence %>
83
+ <% error_text = [head, @response.error_message.presence].compact.join("\n\n").presence || "The provider returned no error detail." %>
84
+ <div class="ck-code-scroll-wrap"><pre class="ck-code ck-code--error"><%= error_text %></pre></div>
83
85
  <% else %>
84
86
  <div class="ck-code-scroll-wrap"><pre class="ck-code"><%= ck_format_maybe_json(@response.response_text) %></pre></div>
85
87
  <% end %>
@@ -2,15 +2,21 @@
2
2
  <% label_text = local_assigns[:label].presence || "#{param_namespace.to_s.titleize} tags" %>
3
3
  <%= label_tag "#{param_namespace}_tags", label_text, class: "ck-label" %>
4
4
  <% all_tags = CompletionKit::Tag.order(:name) %>
5
- <% selected_ids = (record.persisted? || record.tags.loaded?) ? record.tags.map(&:id) : [] %>
5
+ <% selected_names = record.tag_names %>
6
6
  <div class="ck-tag-picker">
7
7
  <% all_tags.each do |tag| %>
8
- <% checked = selected_ids.include?(tag.id) %>
8
+ <% checked = selected_names.include?(tag.name) %>
9
9
  <label class="tag-mark" style="--mark-color: var(--tag-<%= tag.color %>);">
10
10
  <%= check_box_tag "#{param_namespace}[tag_names][]", tag.name, checked, class: "ck-visually-hidden", "aria-label": "Tag: #{tag.name}" %>
11
11
  <span aria-hidden="true"><%= tag.name %></span>
12
12
  </label>
13
13
  <% end %>
14
+ <% (selected_names - all_tags.map(&:name)).each do |pending_name| %>
15
+ <label class="tag-mark" style="--mark-color: var(--ck-muted);">
16
+ <%= check_box_tag "#{param_namespace}[tag_names][]", pending_name, true, class: "ck-visually-hidden", "aria-label": "Tag: #{pending_name}" %>
17
+ <span aria-hidden="true"><%= pending_name %></span>
18
+ </label>
19
+ <% end %>
14
20
  <%= text_field_tag "#{param_namespace}[tag_names][]", "",
15
21
  id: "#{param_namespace}_tags",
16
22
  class: "ck-tag-picker__input",
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.27.0"
2
+ VERSION = "0.27.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completion-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.27.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin