From 1b568f2391dff8656ad75032f60a29557e21da74 Mon Sep 17 00:00:00 2001 From: Roman Rizzi Date: Tue, 27 Jun 2023 14:42:33 -0300 Subject: [PATCH] FIX: Claude's max_tookens_to_sample is a required field (#97) --- lib/shared/inference/anthropic_completions.rb | 4 ++-- .../jobs/regular/create_ai_reply_spec.rb | 2 +- .../summarization/models/anthropic_spec.rb | 16 +++++++--------- .../summarization/models/discourse_spec.rb | 18 ++++++++---------- .../summarization/models/open_ai_spec.rb | 16 +++++++--------- .../strategies/fold_content_spec.rb | 8 ++++---- .../strategies/truncate_content_spec.rb | 6 +++--- .../inference/anthropic_completions_spec.rb | 2 +- spec/support/anthropic_completion_stubs.rb | 6 +++++- 9 files changed, 38 insertions(+), 40 deletions(-) diff --git a/lib/shared/inference/anthropic_completions.rb b/lib/shared/inference/anthropic_completions.rb index 18fd4418..36b0522e 100644 --- a/lib/shared/inference/anthropic_completions.rb +++ b/lib/shared/inference/anthropic_completions.rb @@ -22,9 +22,9 @@ module ::DiscourseAi payload = { model: model, prompt: prompt } - payload[:temperature] = temperature if temperature payload[:top_p] = top_p if top_p - payload[:max_tokens_to_sample] = max_tokens if max_tokens + payload[:max_tokens_to_sample] = max_tokens || 2000 + payload[:temperature] = temperature if temperature payload[:stream] = true if block_given? Net::HTTP.start( diff --git a/spec/lib/modules/ai_bot/jobs/regular/create_ai_reply_spec.rb b/spec/lib/modules/ai_bot/jobs/regular/create_ai_reply_spec.rb index 122eb2ea..95f9d243 100644 --- a/spec/lib/modules/ai_bot/jobs/regular/create_ai_reply_spec.rb +++ b/spec/lib/modules/ai_bot/jobs/regular/create_ai_reply_spec.rb @@ -85,8 +85,8 @@ RSpec.describe Jobs::CreateAiReply do deltas, model: "claude-v1.3", req_opts: { - temperature: 0.4, max_tokens_to_sample: 3000, + temperature: 0.4, stream: true, }, ) diff --git a/spec/lib/modules/summarization/models/anthropic_spec.rb b/spec/lib/modules/summarization/models/anthropic_spec.rb index 2ce99a3a..f3c985e2 100644 --- a/spec/lib/modules/summarization/models/anthropic_spec.rb +++ b/spec/lib/modules/summarization/models/anthropic_spec.rb @@ -3,10 +3,10 @@ require_relative "../../../../support/anthropic_completion_stubs" RSpec.describe DiscourseAi::Summarization::Models::Anthropic do - let(:model) { "claude-v1" } - let(:max_tokens) { 720 } + subject(:model) { described_class.new(model_name, max_tokens: max_tokens) } - subject { described_class.new(model, max_tokens: max_tokens) } + let(:model_name) { "claude-v1" } + let(:max_tokens) { 720 } let(:content) do { @@ -44,7 +44,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Anthropic do ) summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1") end @@ -67,7 +67,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Anthropic do end summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1", "This is summary 2") end @@ -86,9 +86,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Anthropic do AnthropicCompletionStubs.stub_response(messages, "concatenated summary") - expect(subject.concatenate_summaries(["summary 1", "summary 2"])).to eq( - "concatenated summary", - ) + expect(model.concatenate_summaries(["summary 1", "summary 2"])).to eq("concatenated summary") end end @@ -110,7 +108,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Anthropic do AnthropicCompletionStubs.stub_response(instructions, "truncated summary") - expect(subject.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") + expect(model.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") end end end diff --git a/spec/lib/modules/summarization/models/discourse_spec.rb b/spec/lib/modules/summarization/models/discourse_spec.rb index c505da1c..3f0d6bdd 100644 --- a/spec/lib/modules/summarization/models/discourse_spec.rb +++ b/spec/lib/modules/summarization/models/discourse_spec.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true RSpec.describe DiscourseAi::Summarization::Models::Discourse do - let(:model) { "bart-large-cnn-samsum" } - let(:max_tokens) { 20 } + subject(:model) { described_class.new(model_name, max_tokens: max_tokens) } - subject { described_class.new(model, max_tokens: max_tokens) } + let(:model_name) { "bart-large-cnn-samsum" } + let(:max_tokens) { 20 } let(:content) do { @@ -22,7 +22,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Discourse do :post, "#{SiteSetting.ai_summarization_discourse_service_api_endpoint}/api/v1/classify", ) - .with(body: JSON.dump(model: model, content: prompt)) + .with(body: JSON.dump(model: model_name, content: prompt)) .to_return(status: 200, body: JSON.dump(summary_text: response)) end @@ -40,7 +40,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Discourse do stub_request(expected_messages(content[:contents], opts), "This is summary 1") summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1") end @@ -60,7 +60,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Discourse do end summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1", "This is summary 2") end @@ -73,9 +73,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Discourse do stub_request(messages, "concatenated summary") - expect(subject.concatenate_summaries(["summary 1", "summary 2"])).to eq( - "concatenated summary", - ) + expect(model.concatenate_summaries(["summary 1", "summary 2"])).to eq("concatenated summary") end end @@ -87,7 +85,7 @@ RSpec.describe DiscourseAi::Summarization::Models::Discourse do stub_request("( 1 asd said : this is", "truncated summary") - expect(subject.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") + expect(model.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") end end end diff --git a/spec/lib/modules/summarization/models/open_ai_spec.rb b/spec/lib/modules/summarization/models/open_ai_spec.rb index d01fd287..7e1a24f5 100644 --- a/spec/lib/modules/summarization/models/open_ai_spec.rb +++ b/spec/lib/modules/summarization/models/open_ai_spec.rb @@ -3,10 +3,10 @@ require_relative "../../../../support/openai_completions_inference_stubs" RSpec.describe DiscourseAi::Summarization::Models::OpenAi do - let(:model) { "gpt-3.5-turbo" } - let(:max_tokens) { 720 } + subject(:model) { described_class.new(model_name, max_tokens: max_tokens) } - subject { described_class.new(model, max_tokens: max_tokens) } + let(:model_name) { "gpt-3.5-turbo" } + let(:max_tokens) { 720 } let(:content) do { @@ -47,7 +47,7 @@ RSpec.describe DiscourseAi::Summarization::Models::OpenAi do ) summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1") end @@ -70,7 +70,7 @@ RSpec.describe DiscourseAi::Summarization::Models::OpenAi do end summarized_chunks = - subject.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } + model.summarize_in_chunks(content[:contents], opts).map { |c| c[:summary] } expect(summarized_chunks).to contain_exactly("This is summary 1", "This is summary 2") end @@ -90,9 +90,7 @@ RSpec.describe DiscourseAi::Summarization::Models::OpenAi do OpenAiCompletionsInferenceStubs.stub_response(messages, "concatenated summary") - expect(subject.concatenate_summaries(["summary 1", "summary 2"])).to eq( - "concatenated summary", - ) + expect(model.concatenate_summaries(["summary 1", "summary 2"])).to eq("concatenated summary") end end @@ -110,7 +108,7 @@ RSpec.describe DiscourseAi::Summarization::Models::OpenAi do OpenAiCompletionsInferenceStubs.stub_response(truncated_version, "truncated summary") - expect(subject.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") + expect(model.summarize_with_truncation(content[:contents], opts)).to eq("truncated summary") end end end diff --git a/spec/lib/modules/summarization/strategies/fold_content_spec.rb b/spec/lib/modules/summarization/strategies/fold_content_spec.rb index 655a7855..a414d25d 100644 --- a/spec/lib/modules/summarization/strategies/fold_content_spec.rb +++ b/spec/lib/modules/summarization/strategies/fold_content_spec.rb @@ -4,6 +4,8 @@ require_relative "../../../../support/summarization/dummy_completion_model" RSpec.describe DiscourseAi::Summarization::Strategies::FoldContent do describe "#summarize" do + subject(:strategy) { described_class.new(model) } + let(:summarize_text) { "This is a text" } let(:model) { DummyCompletionModel.new(model_tokens) } let(:model_tokens) do @@ -11,13 +13,11 @@ RSpec.describe DiscourseAi::Summarization::Strategies::FoldContent do DiscourseAi::Tokenizer::BertTokenizer.size("(1 asd said: This is a text ") + 3 end - subject { described_class.new(model) } - let(:content) { { contents: [{ poster: "asd", id: 1, text: summarize_text }] } } context "when the content to summarize fits in a single call" do it "does one call to summarize content" do - result = subject.summarize(content) + result = strategy.summarize(content) expect(model.summarization_calls).to eq(1) expect(result[:summary]).to eq(DummyCompletionModel::SINGLE_SUMMARY) @@ -28,7 +28,7 @@ RSpec.describe DiscourseAi::Summarization::Strategies::FoldContent do it "summarizes each chunk and then concatenates them" do content[:contents] << { poster: "asd2", id: 2, text: summarize_text } - result = subject.summarize(content) + result = strategy.summarize(content) expect(model.summarization_calls).to eq(3) expect(result[:summary]).to eq(DummyCompletionModel::CONCATENATED_SUMMARIES) diff --git a/spec/lib/modules/summarization/strategies/truncate_content_spec.rb b/spec/lib/modules/summarization/strategies/truncate_content_spec.rb index 4b6f1584..4f4bbee4 100644 --- a/spec/lib/modules/summarization/strategies/truncate_content_spec.rb +++ b/spec/lib/modules/summarization/strategies/truncate_content_spec.rb @@ -4,19 +4,19 @@ require_relative "../../../../support/summarization/dummy_completion_model" RSpec.describe DiscourseAi::Summarization::Strategies::TruncateContent do describe "#summarize" do + subject(:strategy) { described_class.new(model) } + let(:summarize_text) { "This is a text" } let(:model_tokens) { summarize_text.length } let(:model) { DummyCompletionModel.new(model_tokens) } - subject { described_class.new(model) } - let(:content) { { contents: [{ poster: "asd", id: 1, text: summarize_text }] } } context "when the content to summarize doesn't fit in a single call" do it "summarizes a truncated version" do content[:contents] << { poster: "asd2", id: 2, text: summarize_text } - result = subject.summarize(content) + result = strategy.summarize(content) expect(model.summarization_calls).to eq(1) expect(result[:summary]).to eq(DummyCompletionModel::SINGLE_SUMMARY) diff --git a/spec/shared/inference/anthropic_completions_spec.rb b/spec/shared/inference/anthropic_completions_spec.rb index 6ab081a7..27cb2d52 100644 --- a/spec/shared/inference/anthropic_completions_spec.rb +++ b/spec/shared/inference/anthropic_completions_spec.rb @@ -9,7 +9,7 @@ RSpec.describe DiscourseAi::Inference::AnthropicCompletions do response_text = "1. Serenity\\n2. Laughter\\n3. Adventure" prompt = "Human: write 3 words\n\n" user_id = 183 - req_opts = { temperature: 0.5, max_tokens_to_sample: 700 } + req_opts = { max_tokens_to_sample: 700, temperature: 0.5 } AnthropicCompletionStubs.stub_response(prompt, response_text, req_opts: req_opts) diff --git a/spec/support/anthropic_completion_stubs.rb b/spec/support/anthropic_completion_stubs.rb index 6ea2bbd7..6e61e5df 100644 --- a/spec/support/anthropic_completion_stubs.rb +++ b/spec/support/anthropic_completion_stubs.rb @@ -17,7 +17,11 @@ class AnthropicCompletionStubs def stub_response(prompt, response_text, req_opts: {}) WebMock .stub_request(:post, "https://api.anthropic.com/v1/complete") - .with(body: { model: "claude-v1", prompt: prompt }.merge(req_opts).to_json) + .with( + body: { model: "claude-v1", prompt: prompt, max_tokens_to_sample: 2000 }.merge( + req_opts, + ).to_json, + ) .to_return(status: 200, body: JSON.dump(response(response_text))) end