feat: openai and stabilityai integration (#3439)

* chore: create trait

* test: add tests

* chore: remove log

* chore: disable log
This commit is contained in:
Nathan.fooo 2023-09-21 12:41:52 +08:00 committed by GitHub
parent 37a5054ebd
commit 6ba7fc0317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 475 additions and 224 deletions

View File

@ -34,7 +34,7 @@ class TransactionAdapter {
final DocumentService documentService;
final String documentId;
final bool _enableDebug = true;
final bool _enableDebug = false;
Future<void> apply(Transaction transaction, EditorState editorState) async {
final stopwatch = Stopwatch()..start();

View File

@ -150,7 +150,6 @@ Future<AppTheme> appTheme(String themeName) async {
try {
return await AppTheme.fromName(themeName);
} catch (e) {
Log.error(e);
return AppTheme.fallback;
}
}

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
@ -17,10 +16,7 @@ class UserBackendService {
static Future<Either<FlowyError, UserProfilePB>>
getCurrentUserProfile() async {
final result = await UserEventGetUserProfile().send().then((value) {
value.fold((l) => null, (r) => Log.info(r));
return value;
});
final result = await UserEventGetUserProfile().send();
return result.swap();
}

View File

@ -104,7 +104,7 @@ class SplashScreen extends StatelessWidget {
}
void _handleUnauthenticated(BuildContext context, Unauthenticated result) {
Log.debug(
Log.trace(
'_handleUnauthenticated -> Supabase is enabled: $isSupabaseEnabled',
);
// if the env is not configured, we will skip to the 'skip login screen'.

View File

@ -21,6 +21,7 @@ class Log {
printEmojis: true, // Print an emoji for each log message
printTime: false // Should each log print contain a timestamp
),
level: kDebugMode ? Level.verbose : Level.info,
);
}

View File

@ -172,6 +172,38 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "async-convert"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d416feee97712e43152cd42874de162b8f9b77295b1c85e5d92725cc8310bae"
dependencies = [
"async-trait",
]
[[package]]
name = "async-openai"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7150fb5d9cc4eb0184af43ce75a89620dc3747d3c816e8b0ba200682d0155c05"
dependencies = [
"async-convert",
"backoff",
"base64 0.21.2",
"derive_builder",
"futures",
"rand 0.8.5",
"reqwest",
"reqwest-eventsource",
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio-stream",
"tokio-util",
"tracing",
]
[[package]]
name = "async-stream"
version = "0.3.5"
@ -250,6 +282,20 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backoff"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1"
dependencies = [
"futures-core",
"getrandom 0.2.10",
"instant",
"pin-project-lite",
"rand 0.8.5",
"tokio",
]
[[package]]
name = "backtrace"
version = "0.3.67"
@ -362,7 +408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
"hashbrown 0.12.3",
"hashbrown 0.13.2",
]
[[package]]
@ -1215,14 +1261,38 @@ dependencies = [
"cipher",
]
[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core 0.14.4",
"darling_macro 0.14.4",
]
[[package]]
name = "darling"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944"
dependencies = [
"darling_core",
"darling_macro",
"darling_core 0.20.1",
"darling_macro 0.20.1",
]
[[package]]
name = "darling_core"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
]
[[package]]
@ -1239,13 +1309,24 @@ dependencies = [
"syn 2.0.29",
]
[[package]]
name = "darling_macro"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core 0.14.4",
"quote",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
dependencies = [
"darling_core",
"darling_core 0.20.1",
"quote",
"syn 2.0.29",
]
@ -1274,6 +1355,37 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "derive_builder"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
dependencies = [
"darling 0.14.4",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "derive_builder_macro"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
dependencies = [
"derive_builder_core",
"syn 1.0.109",
]
[[package]]
name = "derive_more"
version = "0.99.17"
@ -1364,6 +1476,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "dotenvy"
version = "0.15.7"
@ -1482,6 +1600,17 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "eventsource-stream"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab"
dependencies = [
"futures-core",
"nom 7.1.3",
"pin-project-lite",
]
[[package]]
name = "faccess"
version = "0.2.4"
@ -1573,17 +1702,14 @@ dependencies = [
name = "flowy-ai"
version = "0.1.0"
dependencies = [
"bytes",
"flowy-derive",
"flowy-error",
"flowy-notification",
"lib-dispatch",
"anyhow",
"async-openai",
"dotenv",
"lib-infra",
"protobuf",
"reqwest",
"serde",
"serde_json",
"strum_macros 0.21.1",
"tokio",
]
[[package]]
@ -2160,6 +2286,12 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-timer"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
version = "0.3.28"
@ -4515,6 +4647,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"serde",
"serde_json",
@ -4533,6 +4666,22 @@ dependencies = [
"winreg 0.50.0",
]
[[package]]
name = "reqwest-eventsource"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f03f570355882dd8d15acc3a313841e6e90eddbc76a93c748fd82cc13ba9f51"
dependencies = [
"eventsource-stream",
"futures-core",
"futures-timer",
"mime",
"nom 7.1.3",
"pin-project-lite",
"reqwest",
"thiserror",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -4661,6 +4810,18 @@ dependencies = [
"sct",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
dependencies = [
"openssl-probe",
"rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.2"
@ -4911,7 +5072,7 @@ version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070"
dependencies = [
"darling",
"darling 0.20.1",
"proc-macro2",
"quote",
"syn 2.0.29",

View File

@ -152,6 +152,38 @@ dependencies = [
"serde_json",
]
[[package]]
name = "async-convert"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d416feee97712e43152cd42874de162b8f9b77295b1c85e5d92725cc8310bae"
dependencies = [
"async-trait",
]
[[package]]
name = "async-openai"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7150fb5d9cc4eb0184af43ce75a89620dc3747d3c816e8b0ba200682d0155c05"
dependencies = [
"async-convert",
"backoff",
"base64 0.21.3",
"derive_builder",
"futures",
"rand 0.8.5",
"reqwest",
"reqwest-eventsource",
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio-stream",
"tokio-util",
"tracing",
]
[[package]]
name = "async-stream"
version = "0.3.5"
@ -257,6 +289,20 @@ dependencies = [
"tower-service",
]
[[package]]
name = "backoff"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1"
dependencies = [
"futures-core",
"getrandom 0.2.10",
"instant",
"pin-project-lite",
"rand 0.8.5",
"tokio",
]
[[package]]
name = "backtrace"
version = "0.3.69"
@ -375,7 +421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
"hashbrown 0.12.3",
"hashbrown 0.13.2",
]
[[package]]
@ -1048,6 +1094,41 @@ dependencies = [
"cipher",
]
[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core",
"quote",
"syn 1.0.109",
]
[[package]]
name = "dart-ffi"
version = "0.1.0"
@ -1104,6 +1185,37 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "derive_builder"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "derive_builder_macro"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
dependencies = [
"derive_builder_core",
"syn 1.0.109",
]
[[package]]
name = "deunicode"
version = "0.4.4"
@ -1248,6 +1360,17 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "eventsource-stream"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab"
dependencies = [
"futures-core",
"nom 7.1.3",
"pin-project-lite",
]
[[package]]
name = "faccess"
version = "0.2.4"
@ -1321,17 +1444,14 @@ dependencies = [
name = "flowy-ai"
version = "0.1.0"
dependencies = [
"bytes",
"flowy-derive",
"flowy-error",
"flowy-notification",
"lib-dispatch",
"anyhow",
"async-openai",
"dotenv",
"lib-infra",
"protobuf",
"reqwest",
"serde",
"serde_json",
"strum_macros 0.21.1",
"tokio",
]
[[package]]
@ -1971,6 +2091,12 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-timer"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
version = "0.3.28"
@ -2340,6 +2466,12 @@ dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.4.0"
@ -2403,6 +2535,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "ipnet"
version = "2.8.0"
@ -3737,6 +3878,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"serde",
"serde_json",
@ -3755,6 +3897,22 @@ dependencies = [
"winreg",
]
[[package]]
name = "reqwest-eventsource"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f03f570355882dd8d15acc3a313841e6e90eddbc76a93c748fd82cc13ba9f51"
dependencies = [
"eventsource-stream",
"futures-core",
"futures-timer",
"mime",
"nom 7.1.3",
"pin-project-lite",
"reqwest",
"thiserror",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -3871,6 +4029,18 @@ dependencies = [
"sct",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
dependencies = [
"openssl-probe",
"rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.3"
@ -4323,6 +4493,12 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.25.0"

View File

@ -6,15 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
flowy-derive = { path = "../../../shared-lib/flowy-derive" }
flowy-notification = { path = "../flowy-notification" }
flowy-error = { path = "../flowy-error", features = ["impl_from_serde", "impl_from_dispatch_error"] }
lib-dispatch = { path = "../lib-dispatch" }
lib-infra = { path = "../../../shared-lib/lib-infra" }
protobuf = {version = "2.28.0"}
bytes = { version = "1.4" }
strum_macros = "0.21"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0.75"
lib-infra = { path = "../../../shared-lib/lib-infra" }
async-openai = "0.14.2"
tokio = { version = "1.12", features = ["rt", "sync"] }
dotenv = "0.15.0"

View File

@ -0,0 +1,16 @@
use anyhow::{anyhow, Error};
pub struct OpenAISetting {
pub openai_api_key: String,
}
const OPENAI_API_KEY: &str = "OPENAI_API_KEY";
impl OpenAISetting {
pub fn from_env() -> Result<Self, Error> {
let openai_api_key =
std::env::var(OPENAI_API_KEY).map_err(|_| anyhow!("Missing OPENAI_API_KEY"))?;
Ok(Self { openai_api_key })
}
}

View File

@ -1,71 +0,0 @@
use flowy_error::ErrorCode;
/*
model="text-davinci-003",
prompt="Write a tagline for an ice cream shop."
*/
#[derive(Default)]
pub struct TextCompletionPayloadPB {
pub request_id: String,
// Model: Either text-davinci-003 or gpt-3.5-turbo
pub model: String,
// Prompt to query gpt
pub prompt: String,
// User open_ai_key for authentication
pub open_ai_key: String,
}
pub struct TextCompletionParams {
pub request_id: String,
pub model: String,
pub prompt: String,
pub open_ai_key: String,
}
impl TryInto<TextCompletionParams> for TextCompletionPayloadPB {
type Error = ErrorCode;
fn try_into(self) -> Result<TextCompletionParams, Self::Error> {
Ok(TextCompletionParams {
request_id: self.request_id,
model: self.model,
prompt: self.prompt,
open_ai_key: self.open_ai_key,
})
}
}
/*
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-3.5-turbo-0613",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nHello there, how may I assist you today?",
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21
}
}
*/
#[derive(Default)]
pub struct TextCompletionDataPB {
pub request_id: String,
pub model: String,
pub index: i32,
pub content: String,
}

View File

@ -1,71 +0,0 @@
use crate::entities::{TextCompletionDataPB, TextCompletionParams, TextCompletionPayloadPB};
use flowy_error::FlowyError;
use lib_dispatch::prelude::{data_result_ok, AFPluginData, DataResult};
use reqwest;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Message {
role: String,
content: String,
}
#[derive(Serialize)]
struct RequestBody {
model: String,
messages: Vec<Message>,
}
#[derive(Deserialize)]
struct ResponseChoice {
index: i32,
message: Message,
}
#[derive(Deserialize)]
struct ApiResponse {
choices: Vec<ResponseChoice>,
}
pub(crate) async fn request_text_completion(
data: AFPluginData<TextCompletionPayloadPB>,
) -> DataResult<TextCompletionDataPB, FlowyError> {
// Set up the request body
let body = RequestBody {
model: "gpt-3.5-turbo".to_string(),
messages: vec![
Message {
role: "system".to_string(),
content: "You are a helpful assistant.".to_string(),
},
Message {
role: "user".to_string(),
content: data.prompt.to_string(),
},
],
};
// Make the API call
let client = reqwest::Client::new();
let response: ApiResponse = client
.post("https://api.openai.com/v1/chat/completions")
.header("Content-Type", "application/json")
.header("Authorization", format!("Bearer {}", data.open_ai_key))
.json(&body)
.send()
.await?
.json()
.await?;
// Extract index and content
let _choice = &response.choices[0];
let params: TextCompletionParams = data.into_inner().try_into()?;
data_result_ok(TextCompletionDataPB {
request_id: params.request_id,
model: params.model,
index: response.choices[0].index,
content: response.choices[0].message.content.to_string(),
})
}

View File

@ -1,18 +0,0 @@
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
use lib_dispatch::prelude::AFPlugin;
use strum_macros::Display;
use crate::event_handler::request_text_completion;
pub fn init() -> AFPlugin {
AFPlugin::new()
.name(env!("CARGO_PKG_NAME"))
.event(OpenAIEvent::RequestTextCompletion, request_text_completion)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, ProtoBuf_Enum, Flowy_Event)]
#[event_err = "FlowyError"]
pub enum OpenAIEvent {
#[event(input = "TextCompletionPayloadPB", output = "TextCompletionDataPB")]
RequestTextCompletion = 0,
}

View File

@ -1,4 +1,2 @@
// pub mod entities;
// pub mod event_handler;
// pub mod event_map;
// pub mod notification;
pub mod config;
pub mod text;

View File

@ -1,21 +0,0 @@
use flowy_derive::ProtoBuf_Enum;
use flowy_notification::NotificationBuilder;
const OPEN_AI_NOTIFICATION: &str = "OpenAI";
#[derive(ProtoBuf_Enum, Debug, Default)]
pub(crate) enum OpenAINotification {
#[default]
Unknown = 0,
}
impl std::convert::From<OpenAINotification> for i32 {
fn from(notification: OpenAINotification) -> Self {
notification as i32
}
}
#[allow(dead_code)]
pub(crate) fn send_notification(id: &str, ty: OpenAINotification) -> NotificationBuilder {
NotificationBuilder::new(id, ty, OPEN_AI_NOTIFICATION)
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,14 @@
use anyhow::Error;
use lib_infra::async_trait::async_trait;
mod entities;
pub mod open_ai;
pub mod stability_ai;
#[async_trait]
pub trait TextCompletion: Send + Sync {
type Input: Send + 'static;
type Output;
async fn text_completion(&self, params: Self::Input) -> Result<Self::Output, Error>;
}

View File

@ -0,0 +1,30 @@
use crate::text::TextCompletion;
use anyhow::Error;
use async_openai::config::OpenAIConfig;
use async_openai::types::{CreateCompletionRequest, CreateCompletionResponse};
use async_openai::Client;
use lib_infra::async_trait::async_trait;
pub struct OpenAITextCompletion {
client: Client<OpenAIConfig>,
}
impl OpenAITextCompletion {
pub fn new(api_key: &str) -> Self {
// https://docs.rs/async-openai/latest/async_openai/struct.Completions.html
let config = OpenAIConfig::new().with_api_key(api_key);
let client = Client::with_config(config);
Self { client }
}
}
#[async_trait]
impl TextCompletion for OpenAITextCompletion {
type Input = CreateCompletionRequest;
type Output = CreateCompletionResponse;
async fn text_completion(&self, params: Self::Input) -> Result<Self::Output, Error> {
let response = self.client.completions().create(params).await?;
Ok(response)
}
}

View File

@ -0,0 +1,15 @@
use crate::text::TextCompletion;
use anyhow::Error;
use lib_infra::async_trait::async_trait;
pub struct StabilityAITextCompletion {}
#[async_trait]
impl TextCompletion for StabilityAITextCompletion {
type Input = ();
type Output = ();
async fn text_completion(&self, _params: Self::Input) -> Result<Self::Output, Error> {
todo!()
}
}

View File

@ -0,0 +1,2 @@
mod text;
mod util;

View File

@ -0,0 +1,18 @@
use crate::util::get_openai_config;
use async_openai::types::CreateCompletionRequestArgs;
use flowy_ai::text::open_ai::OpenAITextCompletion;
use flowy_ai::text::TextCompletion;
#[tokio::test]
async fn text_completion_test() {
if let Some(config) = get_openai_config() {
let client = OpenAITextCompletion::new(&config.openai_api_key);
let params = CreateCompletionRequestArgs::default()
.model("text-davinci-003")
.prompt("Write a rust function to calculate the sum of two numbers")
.build()
.unwrap();
let resp = client.text_completion(params).await.unwrap();
dbg!("{:?}", resp);
}
}

View File

@ -0,0 +1 @@
mod completion_test;

View File

@ -0,0 +1,8 @@
use flowy_ai::config::OpenAISetting;
// To run the OpenAI test, you need to create a .env file in the flowy-ai folder.
// Use the format: OPENAI_API_KEY=your_api_key
pub fn get_openai_config() -> Option<OpenAISetting> {
dotenv::from_filename(".env").ok()?;
OpenAISetting::from_env().ok()
}

View File

@ -24,7 +24,7 @@ impl BoxAny {
pub fn unbox_or_error<T>(self) -> Result<T>
where
T: Default + 'static,
T: 'static,
{
match self.0.downcast::<T>() {
Ok(value) => Ok(*value),
@ -38,7 +38,7 @@ impl BoxAny {
pub fn unbox_or_none<T>(self) -> Option<T>
where
T: Default + 'static,
T: 'static,
{
match self.0.downcast::<T>() {
Ok(value) => Some(*value),