From 4e384b982e52423ce8e8409def7130c32ff88e58 Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:19:39 +0800 Subject: [PATCH] chore: pass chat metadata (#789) * chore: pass chat metadata * chore: clippy --- ...c89d4df0d2b5daf485a9957e71112d2682f9a.json | 22 --------------- ...e338a8c001ea30b722d3a6a1a60259d47913c.json | 28 +++++++++++++++++++ libs/appflowy-ai-client/src/client.rs | 6 ++++ libs/appflowy-ai-client/src/dto.rs | 2 ++ .../tests/chat_test/context_test.rs | 2 +- .../tests/chat_test/qa_test.rs | 6 ++-- libs/database/src/chat/chat_ops.rs | 6 ++-- src/api/chat.rs | 10 ++++--- src/biz/chat/ops.rs | 12 ++++---- 9 files changed, 56 insertions(+), 38 deletions(-) delete mode 100644 .sqlx/query-5fd78d55ed9c4b866f1ce883c5cc89d4df0d2b5daf485a9957e71112d2682f9a.json create mode 100644 .sqlx/query-6f5d6d79587d7f7a52c920acccfe338a8c001ea30b722d3a6a1a60259d47913c.json diff --git a/.sqlx/query-5fd78d55ed9c4b866f1ce883c5cc89d4df0d2b5daf485a9957e71112d2682f9a.json b/.sqlx/query-5fd78d55ed9c4b866f1ce883c5cc89d4df0d2b5daf485a9957e71112d2682f9a.json deleted file mode 100644 index 7b27f114..00000000 --- a/.sqlx/query-5fd78d55ed9c4b866f1ce883c5cc89d4df0d2b5daf485a9957e71112d2682f9a.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT content\n FROM af_chat_messages\n WHERE message_id = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "content", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false - ] - }, - "hash": "5fd78d55ed9c4b866f1ce883c5cc89d4df0d2b5daf485a9957e71112d2682f9a" -} diff --git a/.sqlx/query-6f5d6d79587d7f7a52c920acccfe338a8c001ea30b722d3a6a1a60259d47913c.json b/.sqlx/query-6f5d6d79587d7f7a52c920acccfe338a8c001ea30b722d3a6a1a60259d47913c.json new file mode 100644 index 00000000..63715021 --- /dev/null +++ b/.sqlx/query-6f5d6d79587d7f7a52c920acccfe338a8c001ea30b722d3a6a1a60259d47913c.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT content,meta_data\n FROM af_chat_messages\n WHERE message_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "content", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "meta_data", + "type_info": "Jsonb" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "6f5d6d79587d7f7a52c920acccfe338a8c001ea30b722d3a6a1a60259d47913c" +} diff --git a/libs/appflowy-ai-client/src/client.rs b/libs/appflowy-ai-client/src/client.rs index 4dc43650..8622cc45 100644 --- a/libs/appflowy-ai-client/src/client.rs +++ b/libs/appflowy-ai-client/src/client.rs @@ -201,11 +201,13 @@ impl AppFlowyAIClient { chat_id: &str, content: &str, model: &AIModel, + metadata: Option, ) -> Result { let json = ChatQuestion { chat_id: chat_id.to_string(), data: MessageData { content: content.to_string(), + metadata, }, }; let url = format!("{}/chat/message", self.url); @@ -224,12 +226,14 @@ impl AppFlowyAIClient { &self, chat_id: &str, content: &str, + metadata: Option, model: &AIModel, ) -> Result>, AIError> { let json = ChatQuestion { chat_id: chat_id.to_string(), data: MessageData { content: content.to_string(), + metadata, }, }; let url = format!("{}/chat/message/stream", self.url); @@ -247,12 +251,14 @@ impl AppFlowyAIClient { &self, chat_id: &str, content: &str, + metadata: Option, model: &AIModel, ) -> Result>, AIError> { let json = ChatQuestion { chat_id: chat_id.to_string(), data: MessageData { content: content.to_string(), + metadata, }, }; let url = format!("{}/v2/chat/message/stream", self.url); diff --git a/libs/appflowy-ai-client/src/dto.rs b/libs/appflowy-ai-client/src/dto.rs index bf5d5499..408bbcbe 100644 --- a/libs/appflowy-ai-client/src/dto.rs +++ b/libs/appflowy-ai-client/src/dto.rs @@ -20,6 +20,8 @@ pub struct ChatQuestion { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MessageData { pub content: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/libs/appflowy-ai-client/tests/chat_test/context_test.rs b/libs/appflowy-ai-client/tests/chat_test/context_test.rs index 1e3f0613..e82cda1c 100644 --- a/libs/appflowy-ai-client/tests/chat_test/context_test.rs +++ b/libs/appflowy-ai-client/tests/chat_test/context_test.rs @@ -14,7 +14,7 @@ async fn create_chat_context_test() { }; client.create_chat_text_context(context).await.unwrap(); let resp = client - .send_question(&chat_id, "Where I live?", &AIModel::GPT35) + .send_question(&chat_id, "Where I live?", &AIModel::GPT35, None) .await .unwrap(); // response will be something like: diff --git a/libs/appflowy-ai-client/tests/chat_test/qa_test.rs b/libs/appflowy-ai-client/tests/chat_test/qa_test.rs index a9bf1f6b..54a400e0 100644 --- a/libs/appflowy-ai-client/tests/chat_test/qa_test.rs +++ b/libs/appflowy-ai-client/tests/chat_test/qa_test.rs @@ -10,7 +10,7 @@ async fn qa_test() { client.health_check().await.unwrap(); let chat_id = uuid::Uuid::new_v4().to_string(); let resp = client - .send_question(&chat_id, "I feel hungry", &AIModel::GPT35) + .send_question(&chat_id, "I feel hungry", &AIModel::GPT35, None) .await .unwrap(); assert!(!resp.content.is_empty()); @@ -29,7 +29,7 @@ async fn stop_stream_test() { client.health_check().await.unwrap(); let chat_id = uuid::Uuid::new_v4().to_string(); let mut stream = client - .stream_question(&chat_id, "I feel hungry", &AIModel::GPT35) + .stream_question(&chat_id, "I feel hungry", None, &AIModel::GPT35) .await .unwrap(); @@ -51,7 +51,7 @@ async fn stream_test() { client.health_check().await.unwrap(); let chat_id = uuid::Uuid::new_v4().to_string(); let stream = client - .stream_question_v2(&chat_id, "I feel hungry", &AIModel::GPT35) + .stream_question_v2(&chat_id, "I feel hungry", None, &AIModel::GPT35) .await .unwrap(); let json_stream = JsonStream::::new(stream); diff --git a/libs/database/src/chat/chat_ops.rs b/libs/database/src/chat/chat_ops.rs index fe0a6009..59e9a1df 100644 --- a/libs/database/src/chat/chat_ops.rs +++ b/libs/database/src/chat/chat_ops.rs @@ -608,10 +608,10 @@ pub async fn update_chat_message_meta( pub async fn select_chat_message_content<'a, E: Executor<'a, Database = Postgres>>( executor: E, message_id: i64, -) -> Result { +) -> Result<(String, serde_json::Value), AppError> { let row = sqlx::query!( r#" - SELECT content + SELECT content,meta_data FROM af_chat_messages WHERE message_id = $1 "#, @@ -619,5 +619,5 @@ pub async fn select_chat_message_content<'a, E: Executor<'a, Database = Postgres ) .fetch_one(executor) .await?; - Ok(row.content) + Ok((row.content, row.meta_data)) } diff --git a/src/api/chat.rs b/src/api/chat.rs index b7351dc9..af06835c 100644 --- a/src/api/chat.rs +++ b/src/api/chat.rs @@ -258,11 +258,12 @@ async fn answer_stream_handler( req: HttpRequest, ) -> actix_web::Result { let (_workspace_id, chat_id, question_id) = path.into_inner(); - let content = chat::chat_ops::select_chat_message_content(&state.pg_pool, question_id).await?; + let (content, metadata) = + chat::chat_ops::select_chat_message_content(&state.pg_pool, question_id).await?; let ai_model = ai_model_from_header(&req); match state .ai_client - .stream_question(&chat_id, &content, &ai_model) + .stream_question(&chat_id, &content, Some(metadata), &ai_model) .await { Ok(answer_stream) => { @@ -290,11 +291,12 @@ async fn answer_stream_v2_handler( req: HttpRequest, ) -> actix_web::Result { let (_workspace_id, chat_id, question_id) = path.into_inner(); - let content = chat::chat_ops::select_chat_message_content(&state.pg_pool, question_id).await?; + let (content, metadata) = + chat::chat_ops::select_chat_message_content(&state.pg_pool, question_id).await?; let ai_model = ai_model_from_header(&req); match state .ai_client - .stream_question_v2(&chat_id, &content, &ai_model) + .stream_question_v2(&chat_id, &content, Some(metadata), &ai_model) .await { Ok(answer_stream) => { diff --git a/src/biz/chat/ops.rs b/src/biz/chat/ops.rs index 94bf22ec..f352ecb6 100644 --- a/src/biz/chat/ops.rs +++ b/src/biz/chat/ops.rs @@ -60,8 +60,9 @@ pub async fn update_chat_message( )) })?; + // TODO(nathan): query the metadata from the database let new_answer = ai_client - .send_question(¶ms.chat_id, ¶ms.content, &ai_model) + .send_question(¶ms.chat_id, ¶ms.content, &ai_model, None) .await?; let _answer = insert_answer_message( pg_pool, @@ -83,9 +84,10 @@ pub async fn generate_chat_message_answer( chat_id: &str, ai_model: AIModel, ) -> Result { - let content = chat::chat_ops::select_chat_message_content(pg_pool, question_message_id).await?; + let (content, metadata) = + chat::chat_ops::select_chat_message_content(pg_pool, question_message_id).await?; let new_answer = ai_client - .send_question(chat_id, &content, &ai_model) + .send_question(chat_id, &content, &ai_model, Some(metadata)) .await?; info!("new_answer: {:?}", new_answer); @@ -210,7 +212,7 @@ pub async fn create_chat_message_stream( ChatAuthor::new(uid, ChatAuthorType::Human), &chat_id, params.content.clone(), - params.metadata, + params.metadata.clone(), ).await { Ok(question) => question, Err(err) => { @@ -236,7 +238,7 @@ pub async fn create_chat_message_stream( match params.message_type { ChatMessageType::System => {} ChatMessageType::User => { - let answer = match ai_client.send_question(&chat_id, ¶ms.content, &ai_model).await { + let answer = match ai_client.send_question(&chat_id, ¶ms.content, &ai_model, params.metadata).await { Ok(response) => response, Err(err) => { error!("Failed to send question to AI: {}", err);