-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
96 additions
and
5 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,7 +38,7 @@ _None._ | |
|
||
### New Features | ||
|
||
_None._ | ||
- Add `JetpackAIServiceRemote` | ||
|
||
### Bug Fixes | ||
|
||
|
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
78 changes: 78 additions & 0 deletions
78
Sources/WordPressKit/Services/JetpackAIServiceRemote.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,78 @@ | ||
import Foundation | ||
|
||
public final class JetpackAIServiceRemote: SiteServiceRemoteWordPressComREST { | ||
/// Returns short-lived JWT token (lifetime is in minutes). | ||
public func getAuthorizationToken() async throws -> String { | ||
struct Response: Decodable { | ||
let token: String | ||
} | ||
let path = path(forEndpoint: "sites/\(siteID)/jetpack-openai-query/jwt", withVersion: ._2_0) | ||
let response = await wordPressComRestApi.perform(.post, URLString: path, type: Response.self) | ||
return try response.get().body.token | ||
} | ||
|
||
/// - parameter token: Token retrieved using ``JetpackAIServiceRemote/getAuthorizationToken``. | ||
public func transcribeAudio(from fileURL: URL, token: String) async throws -> String { | ||
let path = path(forEndpoint: "jetpack-ai-transcription?feature=voice-to-content", withVersion: ._2_0) | ||
let file = FilePart(parameterName: "audio_file", url: fileURL, fileName: "voice_recording", mimeType: "audio/m4a") | ||
let result = await wordPressComRestApi.upload(URLString: path, httpHeaders: [ | ||
"Authorization": "Bearer \(token)" | ||
], fileParts: [file]) | ||
guard let body = try result.get().body as? [String: Any], | ||
let text = body["text"] as? String else { | ||
throw URLError(.unknown) | ||
} | ||
return text | ||
} | ||
|
||
/// - parameter token: Token retrieved using ``JetpackAIServiceRemote/getAuthorizationToken``. | ||
public func makePostContent(fromPlainText plainText: String, token: String) async throws -> String { | ||
let path = path(forEndpoint: "jetpack-ai-query", withVersion: ._2_0) | ||
let request = JetpackAIQueryRequest(messages: [ | ||
.init(role: "jetpack-ai", context: .init(type: "voice-to-content-simple-draft", content: plainText)) | ||
], feature: "voice-to-content", stream: false) | ||
let builder = try wordPressComRestApi.requestBuilder(URLString: path) | ||
.method(.post) | ||
.headers(["Authorization": "Bearer \(token)"]) | ||
.body(json: request, jsonEncoder: JSONEncoder()) | ||
let result = await wordPressComRestApi.perform(request: builder) { data in | ||
try JSONDecoder().decode(JetpackAIQueryResponse.self, from: data) | ||
} | ||
let response = try result.get().body | ||
guard let content = response.choices.first?.message.content else { | ||
throw URLError(.unknown) | ||
} | ||
return content | ||
} | ||
} | ||
|
||
private struct JetpackAIQueryRequest: Encodable { | ||
let messages: [Message] | ||
let feature: String | ||
let stream: Bool | ||
|
||
struct Message: Encodable { | ||
let role: String | ||
let context: Context | ||
} | ||
|
||
struct Context: Codable { | ||
let type: String | ||
let content: String | ||
} | ||
} | ||
|
||
private struct JetpackAIQueryResponse: Decodable { | ||
let model: String? | ||
let choices: [Choice] | ||
|
||
struct Choice: Codable { | ||
let index: Int | ||
let message: Message | ||
} | ||
|
||
struct Message: Codable { | ||
let role: String? | ||
let content: String | ||
} | ||
} |
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