in Sources/Hub/Hub.swift [170:240]
func loadConfig(
modelFolder: URL,
hubApi: HubApi = .shared
) async throws -> Configurations {
do {
// Load required configurations
let modelConfigURL = modelFolder.appending(path: "config.json")
guard FileManager.default.fileExists(atPath: modelConfigURL.path) else {
throw Hub.HubClientError.configurationMissing("config.json")
}
let modelConfig = try hubApi.configuration(fileURL: modelConfigURL)
let tokenizerDataURL = modelFolder.appending(path: "tokenizer.json")
guard FileManager.default.fileExists(atPath: tokenizerDataURL.path) else {
throw Hub.HubClientError.configurationMissing("tokenizer.json")
}
let tokenizerData = try hubApi.configuration(fileURL: tokenizerDataURL)
// Load tokenizer config (optional)
var tokenizerConfig: Config? = nil
let tokenizerConfigURL = modelFolder.appending(path: "tokenizer_config.json")
if FileManager.default.fileExists(atPath: tokenizerConfigURL.path) {
tokenizerConfig = try hubApi.configuration(fileURL: tokenizerConfigURL)
}
// Check for chat template and merge if available
// Prefer .jinja template over .json template
var chatTemplate: String? = nil
let chatTemplateJinjaURL = modelFolder.appending(path: "chat_template.jinja")
let chatTemplateJsonURL = modelFolder.appending(path: "chat_template.json")
if FileManager.default.fileExists(atPath: chatTemplateJinjaURL.path) {
// Try to load .jinja template as plain text
chatTemplate = try? String(contentsOf: chatTemplateJinjaURL, encoding: .utf8)
} else if FileManager.default.fileExists(atPath: chatTemplateJsonURL.path),
let chatTemplateConfig = try? hubApi.configuration(fileURL: chatTemplateJsonURL)
{
// Fall back to .json template
chatTemplate = chatTemplateConfig.chatTemplate.string()
}
if let chatTemplate {
// Create or update tokenizer config with chat template
if var configDict = tokenizerConfig?.dictionary() {
configDict["chat_template"] = .init(chatTemplate)
tokenizerConfig = Config(configDict)
} else {
tokenizerConfig = Config(["chat_template": chatTemplate])
}
}
return Configurations(
modelConfig: modelConfig,
tokenizerConfig: tokenizerConfig,
tokenizerData: tokenizerData
)
} catch let error as Hub.HubClientError {
throw error
} catch {
if let nsError = error as NSError? {
if nsError.domain == NSCocoaErrorDomain, nsError.code == NSFileReadNoSuchFileError {
throw Hub.HubClientError.fileSystemError(error)
} else if nsError.domain == "NSJSONSerialization" {
throw Hub.HubClientError.parseError("Invalid JSON format: \(nsError.localizedDescription)")
}
}
throw Hub.HubClientError.fileSystemError(error)
}
}