FIX: Use XML tags in generate_titles prompt. (#322)

We must ensure we can isolate titles, and the models sometimes ignore the example we give them.

Additionally, anons can generate HyDE posts, so we need to check if user is nil when attempting to log requests.
This commit is contained in:
Roman Rizzi 2023-11-28 12:52:22 -03:00 committed by GitHub
parent 11e531b099
commit f26adf2cf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 48 additions and 31 deletions

View File

@ -5,7 +5,7 @@ class CompletionPrompt < ActiveRecord::Base
self.ignored_columns = ["provider"]
TRANSLATE = -301
GENERATE_TITLES = -302
GENERATE_TITLES = -307
PROOFREAD = -303
MARKDOWN_TABLE = -304
CUSTOM_PROMPT = -305

View File

@ -16,28 +16,6 @@ CompletionPrompt.seed do |cp|
TEXT
end
CompletionPrompt.seed do |cp|
cp.id = -302
cp.name = "generate_titles"
cp.prompt_type = CompletionPrompt.prompt_types[:list]
cp.messages = {
insts: <<~TEXT,
I want you to act as a title generator for written pieces. I will provide you with a text,
and you will generate five attention-grabbing titles. Please keep the title concise and under 20 words,
and ensure that the meaning is maintained. Replies will utilize the language type of the topic.
I want you to only reply the list of options and nothing else, do not write explanations.
Each title you generate must be separated by *.
You will find the text between <input></input> XML tags.
TEXT
examples: [
[
"<input>In the labyrinth of time, a solitary horse, etched in gold by the setting sun, embarked on an infinite journey.</input>",
"The solitary horse*The horse etched in gold*A horse's infinite journey*A horse lost in time*A horse's last ride",
],
],
}
end
CompletionPrompt.seed do |cp|
cp.id = -303
cp.name = "proofread"
@ -172,3 +150,26 @@ CompletionPrompt.seed do |cp|
nothing more.
TEXT
end
CompletionPrompt.seed do |cp|
cp.id = -307
cp.name = "generate_titles"
cp.prompt_type = CompletionPrompt.prompt_types[:list]
cp.messages = {
insts: <<~TEXT,
I want you to act as a title generator for written pieces. I will provide you with a text,
and you will generate five attention-grabbing titles. Please keep the title concise and under 20 words,
and ensure that the meaning is maintained. Replies will utilize the language type of the topic.
I want you to only reply the list of options and nothing else, do not write explanations.
Each title you generate must be separated by *.
You will find the text between <input></input> XML tags.
TEXT
examples: [
[
"<input>In the labyrinth of time, a solitary horse, etched in gold by the setting sun, embarked on an infinite journey.</input>",
"<item>The solitary horse</item><item>The horse etched in gold</item><item>A horse's infinite journey</item><item>A horse lost in time</item><item>A horse's last ride</item>",
],
],
post_insts: "Wrap each title between <item></item> XML tags.",
}
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class RecreateGenerateTitlesPrompt < ActiveRecord::Migration[7.0]
def up
DB.exec("DELETE FROM completion_prompts WHERE id = -302")
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View File

@ -57,7 +57,7 @@ module DiscourseAi
log =
AiApiAuditLog.new(
provider_id: provider_id,
user_id: user.id,
user_id: user&.id,
raw_request_payload: request_body,
request_tokens: prompt_size(prompt),
)

View File

@ -103,7 +103,7 @@ module DiscourseAi
end
def parse_list(list)
list.split("*")
Nokogiri::HTML5.fragment(list).css("item").map(&:text)
end
end
end

View File

@ -34,11 +34,17 @@ RSpec.describe DiscourseAi::AiHelper::Assistant do
let(:mode) { CompletionPrompt::GENERATE_TITLES }
let(:titles) do
"The solitary horse*The horse etched in gold*A horse's infinite journey*A horse lost in time*A horse's last ride"
"<item>The solitary horse</item><item>The horse etched in gold</item><item>A horse's infinite journey</item><item>A horse lost in time</item><item>A horse's last ride</item>"
end
it "returns an array with each title" do
expected = titles.split("*")
expected = [
"The solitary horse",
"The horse etched in gold",
"A horse's infinite journey",
"A horse lost in time",
"A horse's last ride",
]
response =
DiscourseAi::Completions::LLM.with_prepared_responses([titles]) do

View File

@ -9,9 +9,8 @@ RSpec.describe DiscourseAi::AiHelper::ChatThreadTitler do
describe "#suggested_title" do
it "suggest the first option from the generate_titles prompt" do
titles =
"The solitary horse*The horse etched in gold*A horse's infinite journey*A horse lost in time*A horse's last ride"
expected_title = titles.split("*").first
"<item>The solitary horse</item><item>The horse etched in gold</item><item>A horse's infinite journey</item><item>A horse lost in time</item><item>A horse's last ride</item>"
expected_title = "The solitary horse"
result =
DiscourseAi::Completions::LLM.with_prepared_responses([titles]) { titler.suggested_title }

View File

@ -265,7 +265,7 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
let(:mode) { CompletionPrompt::GENERATE_TITLES }
let(:titles) do
"Rainy Spain*Plane-Bound Delights*Mysterious Spain*Plane-Rain Chronicles*Unveiling Spain"
"<item>Rainy Spain</item><item>Plane-Bound Delights</item><item>Mysterious Spain</item><item>Plane-Rain Chronicles</item><item>Unveiling Spain</item>"
end
it "opens a menu with title suggestions" do