Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions Modules/Sources/Networking/Remote/AIRequestPrompts.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

struct AIRequestPrompts {
// Prompt instructions
static let identifyLanguage = [
"What is the ISO language code of the language used in the below text?",
"Do not include any explanations and only provide the ISO language code in your response.",
"Text: ```%@"
].joined(separator: "\n")

static let inputComponents = [
"You are a WooCommerce SEO and marketing expert, perform in-depth research about the product " +
"using the provided name, keywords, and tone, and give your response in the below JSON format.",
"keywords: ```%@```",
"tone: ```%@```"
].joined(separator: "\n")

static let jsonFormatInstructions =
"Your response should be in JSON format and don't send anything extra. " +
"Don't include the word JSON in your response:" +
"\n%@"

// Product Generation
static let productNameTemplate = "name: ```%@```"

// Tags
static let defaultTagsPrompt = "Suggest an array of the best matching tags for this product."
static let existingTagsPrompt =
"Given the list of available tags ```%@```, " +
"suggest an array of the best matching tags for this product. You can suggest new tags as well."

// Categories
static let defaultCategoriesPrompt = "Suggest an array of the best matching categories for this product."
static let existingCategoriesPrompt =
"Given the list of available categories ```%@```, " +
"suggest an array of the best matching categories for this product. You can suggest new categories as well."

// Shipping
static let weightPrompt = "Guess and provide only the number in %@"
static let lengthPrompt = "Guess and provide only the number in %@"
static let widthPrompt = "Guess and provide only the number in %@"
static let heightPrompt = "Guess and provide only the number in %@"

//JSON Response Format
static let namesFormat = "An array of strings, containing three different names of the product, written in the language with ISO code ```%@```"
static let descriptionsFormat =
"An array of strings, each containing three different product descriptions of around 100 words long each in a ```%@``` tone, " +
"written in the language with ISO code ```%@```"
static let shortDescriptionsFormat =
"An array of strings, each containing three different short descriptions of the product in a ```%@``` tone, " +
"written in the language with ISO code ```%@```"
static let virtualFormat = "A boolean value that shows whether the product is virtual or physical"
static let priceFormat =
"Guess the price in %@, do not include the currency symbol, " +
"only provide the price as a number"
}
53 changes: 18 additions & 35 deletions Modules/Sources/Networking/Remote/GenerativeContentRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,7 @@ private extension GenerativeContentRemote {
string: String,
feature: GenerativeContentRemoteFeature,
token: JWToken) async throws -> String {
let prompt = [
"What is the ISO language code of the language used in the below text?" +
"Do not include any explanations and only provide the ISO language code in your response.",
"Text: ```\(string)```"
].joined(separator: "\n")
let prompt = String(format: AIRequestPrompts.identifyLanguage, string)
let parameters: [String: Any] = [ParameterKey.token: token.token,
ParameterKey.question: prompt,
ParameterKey.stream: ParameterValue.stream,
Expand All @@ -219,73 +215,60 @@ private extension GenerativeContentRemote {
categories: [ProductCategory],
tags: [ProductTag],
token: JWToken) async throws -> AIProduct {
var inputComponents = [
"You are a WooCommerce SEO and marketing expert, perform in-depth research about the product " +
"using the provided name, keywords and tone, and give your response in the below JSON format.",
"keywords: ```\(keywords)```",
"tone: ```\(tone)```",
]
var inputComponents = [String(format: AIRequestPrompts.inputComponents, keywords, tone)]

// Name will be added only if `productName` is available.
// TODO: this code related to `productName` can be removed after releasing the new product creation with AI flow. Github issue: 13108
if let productName = productName, !productName.isEmpty {
inputComponents.insert("name: ```\(productName)```", at: 1)
inputComponents.insert(String(format: AIRequestPrompts.productNameTemplate, productName), at: 1)
}

let input = inputComponents.joined(separator: "\n")

let jsonResponseFormatDict: [String: Any] = {
let tagsPrompt: String = {
guard !tags.isEmpty else {
return "Suggest an array of the best matching tags for this product."
return AIRequestPrompts.defaultTagsPrompt
}

return "Given the list of available tags ```\(tags.map { $0.name }.joined(separator: ", "))```, " +
"suggest an array of the best matching tags for this product. You can suggest new tags as well."
return String(format: AIRequestPrompts.existingTagsPrompt, tags.map { $0.name }.joined(separator: ", "))
}()

let categoriesPrompt: String = {
guard !categories.isEmpty else {
return "Suggest an array of the best matching categories for this product."
return AIRequestPrompts.defaultCategoriesPrompt
}

return "Given the list of available categories ```\(categories.map { $0.name }.joined(separator: ", "))```, " +
"suggest an array of the best matching categories for this product. You can suggest new categories as well."
return String(format: AIRequestPrompts.existingCategoriesPrompt, categories.map { $0.name }.joined(separator: ", "))
}()

let shippingPrompt = {
var dict = [String: String]()
if let weightUnit {
dict["weight"] = "Guess and provide only the number in \(weightUnit)"
dict["weight"] = String(format: AIRequestPrompts.weightPrompt, weightUnit)
}

if let dimensionUnit {
dict["length"] = "Guess and provide only the number in \(dimensionUnit)"
dict["width"] = "Guess and provide only the number in \(dimensionUnit)"
dict["height"] = "Guess and provide only the number in \(dimensionUnit)"
dict["length"] = String(format: AIRequestPrompts.lengthPrompt, dimensionUnit)
dict["width"] = String(format: AIRequestPrompts.widthPrompt, dimensionUnit)
dict["height"] = String(format: AIRequestPrompts.heightPrompt, dimensionUnit)
}
return dict
}()

// swiftlint:disable line_length
return ["names": "An array of strings, containing three different names of the product, written in the language with ISO code ```\(language)```",
"descriptions": "An array of strings, each containing three different product descriptions of around 100 words long each in a ```\(tone)``` tone, "
+ "written in the language with ISO code ```\(language)```",
"short_descriptions": "An array of strings, each containing three different short descriptions of the product in a ```\(tone)``` tone, "
+ "written in the language with ISO code ```\(language)```",
"virtual": "A boolean value that shows whether the product is virtual or physical",
return ["names": String(format: AIRequestPrompts.namesFormat, language),
"descriptions": String(format: AIRequestPrompts.descriptionsFormat, tone, language),
"short_descriptions": String(format: AIRequestPrompts.shortDescriptionsFormat, tone, language),
"virtual": AIRequestPrompts.virtualFormat,
"shipping": shippingPrompt,
"price": "Guess the price in \(currencySymbol), do not include the currency symbol, "
+ "only provide the price as a number",
"price": String(format: AIRequestPrompts.priceFormat, currencySymbol),
"tags": tagsPrompt,
"categories": categoriesPrompt]
}()

let expectedJsonFormat =
"Your response should be in JSON format and don't send anything extra. " +
"Don't include the word JSON in your response:" +
"\n" +
(jsonResponseFormatDict.toJSONEncoded() ?? "")
let expectedJsonFormat = String(format: AIRequestPrompts.jsonFormatInstructions,
jsonResponseFormatDict.toJSONEncoded() ?? "")

let prompt = input + "\n" + expectedJsonFormat

Expand Down
Loading