Improve CLI
This commit is contained in:
parent
6aa1026478
commit
f67a9a2de7
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"contentDirectory": "../Public",
|
"folder": "../Public",
|
||||||
"trainingIterations": 20,
|
"iterations": 20,
|
||||||
"serverPath": "https://mydomain.com/caps",
|
"server": "https://mydomain.com/caps",
|
||||||
"authenticationToken": "mysecretkey",
|
"authentication": "mysecretkey",
|
||||||
}
|
}
|
||||||
|
@ -4,49 +4,54 @@ import Foundation
|
|||||||
@main
|
@main
|
||||||
struct CapTrain: AsyncParsableCommand {
|
struct CapTrain: AsyncParsableCommand {
|
||||||
|
|
||||||
|
private static let defaultIterations = 10
|
||||||
|
|
||||||
@Flag(name: .shortAndLong, help: "Resume the previous training session (default: false)")
|
@Flag(name: .shortAndLong, help: "Resume the previous training session (default: false)")
|
||||||
var resume: Bool = false
|
var resume: Bool = false
|
||||||
|
|
||||||
@Argument(help: "The path to the configuration file")
|
@Option(name: .shortAndLong, help: "The path to the configuration file. The file must be a json object containing command line arguments. Command line options take precedence over configuration file options")
|
||||||
var configPath: String?
|
var configuration: String?
|
||||||
|
|
||||||
@Option(name: .shortAndLong, help: "The number of iterations to train")
|
@Option(name: .shortAndLong, help: "The number of iterations to train (default: 10)")
|
||||||
var iterations: Int?
|
var iterations: Int?
|
||||||
|
|
||||||
@Option(name: .shortAndLong, help: "The url of the caps server")
|
@Option(name: .shortAndLong, help: "The url of the caps server to retrieve images and upload the classifier")
|
||||||
var serverPath: String?
|
var server: String?
|
||||||
|
|
||||||
@Option(name: .shortAndLong, help: "The authentication token for the server")
|
@Option(name: .shortAndLong, help: "The authentication token for the server")
|
||||||
var authentication: String?
|
var authentication: String?
|
||||||
|
|
||||||
@Option(name: .shortAndLong, help: "The folder where the content (images, classifier, thumbnails) is stored")
|
@Option(name: .shortAndLong, help: "The path to the folder where the content (images, classifier, thumbnails) is stored")
|
||||||
var folder: String?
|
var folder: String?
|
||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
let configurationFile = try configurationFile()
|
let configurationFile = try configurationFile()
|
||||||
guard let contentFolder = folder ?? configurationFile?.contentFolder,
|
let iterations = iterations ?? configurationFile?.iterations ?? CapTrain.defaultIterations
|
||||||
let trainingIterations = iterations ?? configurationFile?.trainingIterations,
|
guard let contentFolder = folder ?? configurationFile?.folder else {
|
||||||
let serverPath = serverPath ?? configurationFile?.serverPath,
|
throw TrainingError.missingArguments("folder")
|
||||||
let authenticationToken = authentication ?? configurationFile?.authenticationToken
|
}
|
||||||
else {
|
guard let serverPath = server ?? configurationFile?.server else {
|
||||||
throw TrainingError.missingArguments
|
throw TrainingError.missingArguments("server")
|
||||||
|
}
|
||||||
|
guard let authentication = authentication ?? configurationFile?.authentication else {
|
||||||
|
throw TrainingError.missingArguments("authentication")
|
||||||
}
|
}
|
||||||
|
|
||||||
let configuration = Configuration(
|
let configuration = Configuration(
|
||||||
contentFolder: contentFolder,
|
contentFolder: contentFolder,
|
||||||
trainingIterations: trainingIterations,
|
trainingIterations: iterations,
|
||||||
serverPath: serverPath,
|
serverPath: serverPath,
|
||||||
authenticationToken: authenticationToken)
|
authenticationToken: authentication)
|
||||||
|
|
||||||
let creator = try ClassifierCreator(configuration: configuration, resume: resume)
|
let creator = try ClassifierCreator(configuration: configuration, resume: resume)
|
||||||
try await creator.run()
|
try await creator.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func configurationFile() throws -> ConfigurationFile? {
|
private func configurationFile() throws -> ConfigurationFile? {
|
||||||
guard let configPath else {
|
guard let configuration else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let configurationFileUrl = URL(fileURLWithPath: configPath)
|
let configurationFileUrl = URL(fileURLWithPath: configuration)
|
||||||
return try ConfigurationFile(at: configurationFileUrl)
|
return try ConfigurationFile(at: configurationFileUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,13 @@ import Foundation
|
|||||||
|
|
||||||
struct ConfigurationFile {
|
struct ConfigurationFile {
|
||||||
|
|
||||||
let contentFolder: String?
|
let folder: String?
|
||||||
|
|
||||||
let trainingIterations: Int?
|
let iterations: Int?
|
||||||
|
|
||||||
let serverPath: String?
|
let server: String?
|
||||||
|
|
||||||
let authenticationToken: String?
|
let authentication: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConfigurationFile: Decodable {
|
extension ConfigurationFile: Decodable {
|
||||||
|
@ -4,7 +4,7 @@ enum TrainingError: Error {
|
|||||||
case invalidGetResponseData(Int)
|
case invalidGetResponseData(Int)
|
||||||
case invalidResponse(URL, Int)
|
case invalidResponse(URL, Int)
|
||||||
|
|
||||||
case missingArguments
|
case missingArguments(String)
|
||||||
|
|
||||||
case configurationFileMissing(URL)
|
case configurationFileMissing(URL)
|
||||||
case configurationFileUnreadable(URL, Error)
|
case configurationFileUnreadable(URL, Error)
|
||||||
@ -54,8 +54,8 @@ extension TrainingError: CustomStringConvertible {
|
|||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .missingArguments:
|
case .missingArguments(let argument):
|
||||||
return "Missing arguments"
|
return "Missing argument '\(argument)'"
|
||||||
case .configurationFileMissing(let url):
|
case .configurationFileMissing(let url):
|
||||||
return "No configuration at \(url.absoluteURL.path)"
|
return "No configuration at \(url.absoluteURL.path)"
|
||||||
case .configurationFileUnreadable(let url, let error):
|
case .configurationFileUnreadable(let url, let error):
|
||||||
|
Loading…
Reference in New Issue
Block a user