mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-28 19:21:16 +00:00
Switch to new Chat completion API + Add Tags completion
This commit is contained in:
parent
c36b9083ce
commit
93d9ded447
22 changed files with 93 additions and 32 deletions
|
@ -423,6 +423,8 @@
|
|||
"status.draft.delete" = "Выдаліць чарнавік";
|
||||
"status.draft.save" = "Захаваць чарнавік";
|
||||
"status.editor.ai-prompt.correct" = "Выправіць тэкст";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Вылучыць тэкст";
|
||||
"status.editor.ai-prompt.fit" = "Скараціць тэкст";
|
||||
"status.editor.description.add" = "Дадаць апісанне";
|
||||
|
|
|
@ -417,6 +417,8 @@
|
|||
"status.draft.delete" = "Elimina l'esborrany";
|
||||
"status.draft.save" = "Desa l'esborrany";
|
||||
"status.editor.ai-prompt.correct" = "Corregeix el text";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Amplia text";
|
||||
"status.editor.ai-prompt.fit" = "Acurta el text";
|
||||
"status.editor.description.add" = "Afegeix una descripció";
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"status.draft.delete" = "Entwurf löschen";
|
||||
"status.draft.save" = "Entwurf sichern";
|
||||
"status.editor.ai-prompt.correct" = "Text korrigieren";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Text hervorheben";
|
||||
"status.editor.ai-prompt.fit" = "Text kürzen";
|
||||
"status.editor.description.add" = "Beschreibung hinzufügen";
|
||||
|
|
|
@ -418,6 +418,8 @@
|
|||
"status.draft.delete" = "Delete Draft";
|
||||
"status.draft.save" = "Save Draft";
|
||||
"status.editor.ai-prompt.correct" = "Correct text";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Emphasise text";
|
||||
"status.editor.ai-prompt.fit" = "Shorten text";
|
||||
"status.editor.description.add" = "Add description";
|
||||
|
|
|
@ -419,6 +419,8 @@
|
|||
"status.draft.delete" = "Delete Draft";
|
||||
"status.draft.save" = "Save Draft";
|
||||
"status.editor.ai-prompt.correct" = "Correct text";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Emphasize text";
|
||||
"status.editor.ai-prompt.fit" = "Shorten text";
|
||||
"status.editor.description.add" = "Add description";
|
||||
|
|
|
@ -419,6 +419,8 @@
|
|||
"status.draft.delete" = "Eliminar borrador";
|
||||
"status.draft.save" = "Guardar borrador";
|
||||
"status.editor.ai-prompt.correct" = "Corregir texto";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Enfatizar texto";
|
||||
"status.editor.ai-prompt.fit" = "Acortar texto";
|
||||
"status.editor.description.add" = "Añadir descripción";
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
"status.draft.delete" = "Ezabatu zirriborroa";
|
||||
"status.draft.save" = "Gorde zirriborroa";
|
||||
"status.editor.ai-prompt.correct" = "Zuzendu testua";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Azpimarratu testua";
|
||||
"status.editor.ai-prompt.fit" = "Laburtu testua";
|
||||
"status.editor.description.add" = "Gehitu deskribapena";
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"status.draft.delete" = "Supprimer le brouillon";
|
||||
"status.draft.save" = "Enregistrer le brouillon";
|
||||
"status.editor.ai-prompt.correct" = "Corriger le texte";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Mettre en évidence le texte";
|
||||
"status.editor.ai-prompt.fit" = "Raccourcir le texte";
|
||||
"status.editor.description.add" = "Ajouter une description";
|
||||
|
|
|
@ -419,6 +419,8 @@
|
|||
"status.draft.delete" = "Cancella la bozza";
|
||||
"status.draft.save" = "Salva la bozza";
|
||||
"status.editor.ai-prompt.correct" = "Correggi il testo";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Enfatizza il testo";
|
||||
"status.editor.ai-prompt.fit" = "Accorcia il testo";
|
||||
"status.editor.description.add" = "Aggiungi la descrizione";
|
||||
|
|
|
@ -418,6 +418,8 @@
|
|||
"status.draft.delete" = "下書きを削除";
|
||||
"status.draft.save" = "下書きを保存";
|
||||
"status.editor.ai-prompt.correct" = "テキストを修正する";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "テキストを強調表示する";
|
||||
"status.editor.ai-prompt.fit" = "テキストを短くする";
|
||||
"status.editor.description.add" = "説明文を追加";
|
||||
|
|
|
@ -420,6 +420,8 @@
|
|||
"status.draft.delete" = "삭제";
|
||||
"status.draft.save" = "임시 보관함에 저장";
|
||||
"status.editor.ai-prompt.correct" = "맞게 고치기";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "내용 강조하기";
|
||||
"status.editor.ai-prompt.fit" = "간결하게 바꾸기";
|
||||
"status.editor.description.add" = "설명 추가";
|
||||
|
|
|
@ -418,6 +418,8 @@
|
|||
"status.draft.delete" = "Slett utkast";
|
||||
"status.draft.save" = "Arkiver utkast";
|
||||
"status.editor.ai-prompt.correct" = "Korrekt tekst";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Fremhev tekst";
|
||||
"status.editor.ai-prompt.fit" = "Forkort tekst";
|
||||
"status.editor.description.add" = "Legg til beskrivelse";
|
||||
|
|
|
@ -412,6 +412,8 @@
|
|||
"status.draft.delete" = "Verwijder concept";
|
||||
"status.draft.save" = "Bewaar concept";
|
||||
"status.editor.ai-prompt.correct" = "Corrigeer tekst";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Benadruk tekst";
|
||||
"status.editor.ai-prompt.fit" = "Kort tekst in";
|
||||
"status.editor.description.add" = "Voeg omschrijving toe";
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"status.draft.delete" = "Usuń wersję roboczą";
|
||||
"status.draft.save" = "Zachowaj wersję roboczą";
|
||||
"status.editor.ai-prompt.correct" = "Popraw tekst";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Wyróżnij tekst";
|
||||
"status.editor.ai-prompt.fit" = "Skróć tekst";
|
||||
"status.editor.description.add" = "Dodaj opis";
|
||||
|
|
|
@ -418,6 +418,8 @@
|
|||
"status.draft.delete" = "Excluir Rascunho";
|
||||
"status.draft.save" = "Salvar Rascunho";
|
||||
"status.editor.ai-prompt.correct" = "Corrigir texto";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Enfatizar texto";
|
||||
"status.editor.ai-prompt.fit" = "Diminuir texto";
|
||||
"status.editor.description.add" = "Adicionar descrição";
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"status.draft.delete" = "Taslağı Sil";
|
||||
"status.draft.save" = "Taslağı Kaydet";
|
||||
"status.editor.ai-prompt.correct" = "Yazıyı Düzelt";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Yazıyı Vurgula";
|
||||
"status.editor.ai-prompt.fit" = "Yazıyı Kısalt";
|
||||
"status.editor.description.add" = "Açıklama Ekle";
|
||||
|
|
|
@ -419,6 +419,8 @@
|
|||
"status.draft.delete" = "Видалити чернетку";
|
||||
"status.draft.save" = "Зберегти чернетку";
|
||||
"status.editor.ai-prompt.correct" = "Виправити текст";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "Надавати виразності";
|
||||
"status.editor.ai-prompt.fit" = "Підігнати текст";
|
||||
"status.editor.description.add" = "Додати опис";
|
||||
|
|
|
@ -417,6 +417,8 @@
|
|||
"status.draft.delete" = "删除草稿";
|
||||
"status.draft.save" = "保存草稿";
|
||||
"status.editor.ai-prompt.correct" = "检查拼写和语法";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "使用强调语气";
|
||||
"status.editor.ai-prompt.fit" = "精简文字";
|
||||
"status.editor.description.add" = "添加描述";
|
||||
|
|
|
@ -419,6 +419,8 @@
|
|||
"status.draft.delete" = "刪除草稿";
|
||||
"status.draft.save" = "儲存草稿";
|
||||
"status.editor.ai-prompt.correct" = "更正";
|
||||
"status.editor.ai-prompt.add-tags" = "Add #Tags in place";
|
||||
"status.editor.ai-prompt.insert-tags" = "Add #Tags after my text";
|
||||
"status.editor.ai-prompt.emphasize" = "強調";
|
||||
"status.editor.ai-prompt.fit" = "精簡";
|
||||
"status.editor.description.add" = "新增描述";
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
IceCubesApp does not collect or process any personal information from its users. The app is used to connect to third-party Mastodon servers that may or may not collect personal information and are not covered by this privacy policy. Each third-party Mastodon server comes equipped with its own privacy policy that can be viewed through the app or through that server's website.
|
||||
|
||||
When you use the OpenAI feature in the composer, please be aware that your input will be sent to the OpenAI server in order to generate a response. Please refer to the [OpenAI Privacy Policy](https://openai.com/policies/privacy-policy) if you want to know more. Nothing is sent to OpenAI if you don't use this feature. You can also completely disable this button in the app settings.
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import Foundation
|
||||
|
||||
protocol OpenAIRequest: Encodable {
|
||||
var path: String { get }
|
||||
}
|
||||
|
||||
public struct OpenAIClient {
|
||||
private let endpoint: URL = .init(string: "https://api.openai.com/v1/completions")!
|
||||
private let endpoint: URL = .init(string: "https://api.openai.com/v1/")!
|
||||
|
||||
private var APIKey: String {
|
||||
if let path = Bundle.main.path(forResource: "Secret", ofType: "plist") {
|
||||
|
@ -27,19 +31,24 @@ public struct OpenAIClient {
|
|||
return decoder
|
||||
}
|
||||
|
||||
public struct Request: Encodable {
|
||||
let model = "text-davinci-003"
|
||||
let topP: Int = 1
|
||||
let frequencyPenalty: Int = 0
|
||||
let presencePenalty: Int = 0
|
||||
let prompt: String
|
||||
let temperature: Double
|
||||
let maxTokens: Int
|
||||
public struct ChatRequest: OpenAIRequest {
|
||||
public struct Message: Encodable {
|
||||
public let role = "user"
|
||||
public let content: String
|
||||
}
|
||||
|
||||
public init(prompt: String, temperature: Double, maxTokens: Int) {
|
||||
self.prompt = prompt
|
||||
let model = "gpt-3.5-turbo"
|
||||
let messages: [Message]
|
||||
|
||||
let temperature: CGFloat
|
||||
|
||||
var path: String {
|
||||
"chat/completions"
|
||||
}
|
||||
|
||||
public init(content: String, temperature: CGFloat) {
|
||||
self.messages = [.init(content: content)]
|
||||
self.temperature = temperature
|
||||
self.maxTokens = maxTokens
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,37 +56,39 @@ public struct OpenAIClient {
|
|||
case correct(input: String)
|
||||
case shorten(input: String)
|
||||
case emphasize(input: String)
|
||||
case addTags(input: String)
|
||||
case insertTags(input: String)
|
||||
|
||||
var request: Request {
|
||||
var request: OpenAIRequest {
|
||||
switch self {
|
||||
case let .correct(input):
|
||||
return Request(prompt: "Correct this to standard English:\(input)",
|
||||
temperature: 0,
|
||||
maxTokens: 500)
|
||||
return ChatRequest(content: "Fix the spelling and grammar mistakes in the following text: \(input)", temperature: 0.2)
|
||||
case let .addTags(input):
|
||||
return ChatRequest(content: "Replace relevant words with Twitter hashtags in the following text while keeping the input same. Maximum of 5 hashtags: \(input)", temperature: 0.1)
|
||||
case let .insertTags(input):
|
||||
return ChatRequest(content: "Return the input with added Twitter hashtags at the end of the input with a maximum of 5 hashtags: \(input)", temperature: 0.2)
|
||||
case let .shorten(input):
|
||||
return Request(prompt: "Make a summary of this paragraph:\(input)",
|
||||
temperature: 0.7,
|
||||
maxTokens: 100)
|
||||
return ChatRequest(content: "Make a shorter version of this text: \(input)", temperature: 0.5)
|
||||
case let .emphasize(input):
|
||||
return Request(prompt: "Make this paragraph catchy, more fun:\(input)",
|
||||
temperature: 0.8,
|
||||
maxTokens: 500)
|
||||
return ChatRequest(content: "Make this text catchy, more fun: \(input)", temperature: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Response: Decodable {
|
||||
public struct Choice: Decodable {
|
||||
public let text: String
|
||||
public struct Message: Decodable {
|
||||
public let role: String
|
||||
public let content: String
|
||||
}
|
||||
|
||||
public let message: Message?
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public let object: String
|
||||
public let model: String
|
||||
public let choices: [Choice]
|
||||
|
||||
public var trimmedText: String {
|
||||
guard var text = choices.first?.text else {
|
||||
guard var text = choices.first?.message?.content else {
|
||||
return ""
|
||||
}
|
||||
while text.first?.isNewline == true || text.first?.isWhitespace == true {
|
||||
|
@ -92,7 +103,7 @@ public struct OpenAIClient {
|
|||
public func request(_ prompt: Prompt) async throws -> Response {
|
||||
do {
|
||||
let jsonData = try encoder.encode(prompt.request)
|
||||
var request = URLRequest(url: endpoint)
|
||||
var request = URLRequest(url: endpoint.appending(path: prompt.request.path))
|
||||
request.httpMethod = "POST"
|
||||
request.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
|
@ -108,6 +119,8 @@ public struct OpenAIClient {
|
|||
|
||||
extension OpenAIClient: Sendable {}
|
||||
extension OpenAIClient.Prompt: Sendable {}
|
||||
extension OpenAIClient.Request: Sendable {}
|
||||
extension OpenAIClient.ChatRequest: Sendable {}
|
||||
extension OpenAIClient.ChatRequest.Message: Sendable {}
|
||||
extension OpenAIClient.Response: Sendable {}
|
||||
extension OpenAIClient.Response.Choice: Sendable {}
|
||||
extension OpenAIClient.Response.Choice.Message: Sendable {}
|
||||
|
|
|
@ -3,13 +3,17 @@ import Network
|
|||
import SwiftUI
|
||||
|
||||
enum StatusEditorAIPrompt: CaseIterable {
|
||||
case correct, fit, emphasize
|
||||
case correct, fit, emphasize, addTags, insertTags
|
||||
|
||||
@ViewBuilder
|
||||
var label: some View {
|
||||
switch self {
|
||||
case .correct:
|
||||
Label("status.editor.ai-prompt.correct", systemImage: "text.badge.checkmark")
|
||||
case .addTags:
|
||||
Label("status.editor.ai-prompt.add-tags", systemImage: "number")
|
||||
case .insertTags:
|
||||
Label("status.editor.ai-prompt.insert-tags", systemImage: "number")
|
||||
case .fit:
|
||||
Label("status.editor.ai-prompt.fit", systemImage: "text.badge.minus")
|
||||
case .emphasize:
|
||||
|
@ -21,6 +25,10 @@ enum StatusEditorAIPrompt: CaseIterable {
|
|||
switch self {
|
||||
case .correct:
|
||||
return .correct(input: text)
|
||||
case .addTags:
|
||||
return .addTags(input: text)
|
||||
case .insertTags:
|
||||
return .insertTags(input: text)
|
||||
case .fit:
|
||||
return .shorten(input: text)
|
||||
case .emphasize:
|
||||
|
|
Loading…
Reference in a new issue