-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #170 from commercetools/category-recommendations
Support for CategoryRecommendations ML Endpoint
- Loading branch information
Showing
5 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// | ||
// Copyright (c) 2018 Commercetools. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/** | ||
Provides a set of methods used for category recommendations machine learning endpoint. | ||
*/ | ||
public struct CategoryRecommendations: MLEndpoint, Codable { | ||
|
||
public typealias ResponseType = PagedQueryResult<ProjectCategoryRecommendation, ProjectCategoryRecommendationMeta> | ||
|
||
public static let path = "recommendations/project-categories" | ||
|
||
/** | ||
Queries for best-fitting / recommended categories for the specified product. | ||
|
||
- parameter productId: Specific product ID to be used for searching for the best-fitting categories. | ||
- parameter staged: Flag to target either the staged or the current version of a product. | ||
- parameter confidenceMin: An Optional min value for confidence bounds on the returned predictions. | ||
- parameter confidenceMax: An Optional max value for confidence bounds on the returned predictions. | ||
- parameter limit: An optional parameter to limit the number of returned results. | ||
- parameter offset: An optional parameter to set the offset of the first returned result. | ||
- parameter result: The code to be executed after processing the response. | ||
*/ | ||
public static func query(productId: String, staged: Bool? = nil, confidenceMin: Double? = nil, confidenceMax: Double? = nil, limit: Int? = nil, offset: Int? = nil, result: @escaping (Result<ResponseType>) -> Void) { | ||
requestWithTokenAndPath(result, { token, path in | ||
var urlParameters = [String: String]() | ||
|
||
if let staged = staged { | ||
urlParameters["staged"] = staged ? "true" : "false" | ||
} | ||
if let confidenceMin = confidenceMin { | ||
urlParameters["confidenceMin"] = "\(confidenceMin)" | ||
} | ||
if let confidenceMax = confidenceMax { | ||
urlParameters["confidenceMax"] = "\(confidenceMax)" | ||
} | ||
if let limit = limit { | ||
urlParameters["limit"] = "\(limit)" | ||
} | ||
if let offset = offset { | ||
urlParameters["offset"] = "\(offset)" | ||
} | ||
|
||
let request = self.request(url: "\(path)/\(productId)", urlParameters: urlParameters, headers: self.headers(token)) | ||
|
||
perform(request: request) { (response: Result<ResponseType>) in | ||
result(response) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
Tests/MachineLearningEndpoints/CategoryRecommendationsTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// Copyright (c) 2018 Commercetools. All rights reserved. | ||
// | ||
|
||
import XCTest | ||
@testable import Commercetools | ||
|
||
class CategoryRecommendationsTests: XCTestCase { | ||
|
||
override func setUp() { | ||
super.setUp() | ||
|
||
setupTestConfiguration() | ||
} | ||
|
||
override func tearDown() { | ||
cleanPersistedTokens() | ||
super.tearDown() | ||
} | ||
|
||
func testCategoryRecommendationsForProject() { | ||
let categoryRecommendationsExpectation = expectation(description: "category recommendations expectation") | ||
|
||
sampleProduct { product in | ||
CategoryRecommendations.query(productId: product.id) { result in | ||
XCTAssert(result.isSuccess) | ||
XCTAssertNotNil(result.model) | ||
categoryRecommendationsExpectation.fulfill() | ||
} | ||
} | ||
|
||
waitForExpectations(timeout: 30, handler: nil) | ||
} | ||
|
||
func testRecommendationsInConfidenceRange() { | ||
let categoryRecommendationsExpectation = expectation(description: "category recommendations expectation") | ||
|
||
sampleProduct { product in | ||
CategoryRecommendations.query(productId: product.id, confidenceMin: 0.3, confidenceMax: 0.8, limit: 20) { result in | ||
XCTAssert(result.isSuccess) | ||
XCTAssertNotNil(result.model) | ||
let results = result.model!.results | ||
XCTAssertEqual(results.filter({ $0.confidence < 0.3 || $0.confidence > 0.8 }).count, 0) | ||
categoryRecommendationsExpectation.fulfill() | ||
} | ||
} | ||
|
||
waitForExpectations(timeout: 30, handler: nil) | ||
} | ||
|
||
private func sampleProduct(_ completion: @escaping (ProductProjection) -> Void) { | ||
ProductProjection.query(limit: 1, result: { result in | ||
if let product = result.model?.results.first, result.isSuccess { | ||
completion(product) | ||
} | ||
}) | ||
} | ||
} |