chore: pass chat metadata (#789)
* chore: pass chat metadata * chore: clippy
This commit is contained in:
parent
2b57fb7125
commit
4e384b982e
|
|
@ -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"
|
|
||||||
}
|
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -201,11 +201,13 @@ impl AppFlowyAIClient {
|
||||||
chat_id: &str,
|
chat_id: &str,
|
||||||
content: &str,
|
content: &str,
|
||||||
model: &AIModel,
|
model: &AIModel,
|
||||||
|
metadata: Option<serde_json::Value>,
|
||||||
) -> Result<ChatAnswer, AIError> {
|
) -> Result<ChatAnswer, AIError> {
|
||||||
let json = ChatQuestion {
|
let json = ChatQuestion {
|
||||||
chat_id: chat_id.to_string(),
|
chat_id: chat_id.to_string(),
|
||||||
data: MessageData {
|
data: MessageData {
|
||||||
content: content.to_string(),
|
content: content.to_string(),
|
||||||
|
metadata,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let url = format!("{}/chat/message", self.url);
|
let url = format!("{}/chat/message", self.url);
|
||||||
|
|
@ -224,12 +226,14 @@ impl AppFlowyAIClient {
|
||||||
&self,
|
&self,
|
||||||
chat_id: &str,
|
chat_id: &str,
|
||||||
content: &str,
|
content: &str,
|
||||||
|
metadata: Option<serde_json::Value>,
|
||||||
model: &AIModel,
|
model: &AIModel,
|
||||||
) -> Result<impl Stream<Item = Result<Bytes, AIError>>, AIError> {
|
) -> Result<impl Stream<Item = Result<Bytes, AIError>>, AIError> {
|
||||||
let json = ChatQuestion {
|
let json = ChatQuestion {
|
||||||
chat_id: chat_id.to_string(),
|
chat_id: chat_id.to_string(),
|
||||||
data: MessageData {
|
data: MessageData {
|
||||||
content: content.to_string(),
|
content: content.to_string(),
|
||||||
|
metadata,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let url = format!("{}/chat/message/stream", self.url);
|
let url = format!("{}/chat/message/stream", self.url);
|
||||||
|
|
@ -247,12 +251,14 @@ impl AppFlowyAIClient {
|
||||||
&self,
|
&self,
|
||||||
chat_id: &str,
|
chat_id: &str,
|
||||||
content: &str,
|
content: &str,
|
||||||
|
metadata: Option<serde_json::Value>,
|
||||||
model: &AIModel,
|
model: &AIModel,
|
||||||
) -> Result<impl Stream<Item = Result<Bytes, AIError>>, AIError> {
|
) -> Result<impl Stream<Item = Result<Bytes, AIError>>, AIError> {
|
||||||
let json = ChatQuestion {
|
let json = ChatQuestion {
|
||||||
chat_id: chat_id.to_string(),
|
chat_id: chat_id.to_string(),
|
||||||
data: MessageData {
|
data: MessageData {
|
||||||
content: content.to_string(),
|
content: content.to_string(),
|
||||||
|
metadata,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let url = format!("{}/v2/chat/message/stream", self.url);
|
let url = format!("{}/v2/chat/message/stream", self.url);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ pub struct ChatQuestion {
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct MessageData {
|
pub struct MessageData {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metadata: Option<serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ async fn create_chat_context_test() {
|
||||||
};
|
};
|
||||||
client.create_chat_text_context(context).await.unwrap();
|
client.create_chat_text_context(context).await.unwrap();
|
||||||
let resp = client
|
let resp = client
|
||||||
.send_question(&chat_id, "Where I live?", &AIModel::GPT35)
|
.send_question(&chat_id, "Where I live?", &AIModel::GPT35, None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// response will be something like:
|
// response will be something like:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ async fn qa_test() {
|
||||||
client.health_check().await.unwrap();
|
client.health_check().await.unwrap();
|
||||||
let chat_id = uuid::Uuid::new_v4().to_string();
|
let chat_id = uuid::Uuid::new_v4().to_string();
|
||||||
let resp = client
|
let resp = client
|
||||||
.send_question(&chat_id, "I feel hungry", &AIModel::GPT35)
|
.send_question(&chat_id, "I feel hungry", &AIModel::GPT35, None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(!resp.content.is_empty());
|
assert!(!resp.content.is_empty());
|
||||||
|
|
@ -29,7 +29,7 @@ async fn stop_stream_test() {
|
||||||
client.health_check().await.unwrap();
|
client.health_check().await.unwrap();
|
||||||
let chat_id = uuid::Uuid::new_v4().to_string();
|
let chat_id = uuid::Uuid::new_v4().to_string();
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_question(&chat_id, "I feel hungry", &AIModel::GPT35)
|
.stream_question(&chat_id, "I feel hungry", None, &AIModel::GPT35)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ async fn stream_test() {
|
||||||
client.health_check().await.unwrap();
|
client.health_check().await.unwrap();
|
||||||
let chat_id = uuid::Uuid::new_v4().to_string();
|
let chat_id = uuid::Uuid::new_v4().to_string();
|
||||||
let stream = client
|
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
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let json_stream = JsonStream::<serde_json::Value>::new(stream);
|
let json_stream = JsonStream::<serde_json::Value>::new(stream);
|
||||||
|
|
|
||||||
|
|
@ -608,10 +608,10 @@ pub async fn update_chat_message_meta(
|
||||||
pub async fn select_chat_message_content<'a, E: Executor<'a, Database = Postgres>>(
|
pub async fn select_chat_message_content<'a, E: Executor<'a, Database = Postgres>>(
|
||||||
executor: E,
|
executor: E,
|
||||||
message_id: i64,
|
message_id: i64,
|
||||||
) -> Result<String, AppError> {
|
) -> Result<(String, serde_json::Value), AppError> {
|
||||||
let row = sqlx::query!(
|
let row = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
SELECT content
|
SELECT content,meta_data
|
||||||
FROM af_chat_messages
|
FROM af_chat_messages
|
||||||
WHERE message_id = $1
|
WHERE message_id = $1
|
||||||
"#,
|
"#,
|
||||||
|
|
@ -619,5 +619,5 @@ pub async fn select_chat_message_content<'a, E: Executor<'a, Database = Postgres
|
||||||
)
|
)
|
||||||
.fetch_one(executor)
|
.fetch_one(executor)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(row.content)
|
Ok((row.content, row.meta_data))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,11 +258,12 @@ async fn answer_stream_handler(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
) -> actix_web::Result<HttpResponse> {
|
) -> actix_web::Result<HttpResponse> {
|
||||||
let (_workspace_id, chat_id, question_id) = path.into_inner();
|
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);
|
let ai_model = ai_model_from_header(&req);
|
||||||
match state
|
match state
|
||||||
.ai_client
|
.ai_client
|
||||||
.stream_question(&chat_id, &content, &ai_model)
|
.stream_question(&chat_id, &content, Some(metadata), &ai_model)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(answer_stream) => {
|
Ok(answer_stream) => {
|
||||||
|
|
@ -290,11 +291,12 @@ async fn answer_stream_v2_handler(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
) -> actix_web::Result<HttpResponse> {
|
) -> actix_web::Result<HttpResponse> {
|
||||||
let (_workspace_id, chat_id, question_id) = path.into_inner();
|
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);
|
let ai_model = ai_model_from_header(&req);
|
||||||
match state
|
match state
|
||||||
.ai_client
|
.ai_client
|
||||||
.stream_question_v2(&chat_id, &content, &ai_model)
|
.stream_question_v2(&chat_id, &content, Some(metadata), &ai_model)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(answer_stream) => {
|
Ok(answer_stream) => {
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,9 @@ pub async fn update_chat_message(
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// TODO(nathan): query the metadata from the database
|
||||||
let new_answer = ai_client
|
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?;
|
.await?;
|
||||||
let _answer = insert_answer_message(
|
let _answer = insert_answer_message(
|
||||||
pg_pool,
|
pg_pool,
|
||||||
|
|
@ -83,9 +84,10 @@ pub async fn generate_chat_message_answer(
|
||||||
chat_id: &str,
|
chat_id: &str,
|
||||||
ai_model: AIModel,
|
ai_model: AIModel,
|
||||||
) -> Result<ChatMessage, AppError> {
|
) -> Result<ChatMessage, AppError> {
|
||||||
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
|
let new_answer = ai_client
|
||||||
.send_question(chat_id, &content, &ai_model)
|
.send_question(chat_id, &content, &ai_model, Some(metadata))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
info!("new_answer: {:?}", new_answer);
|
info!("new_answer: {:?}", new_answer);
|
||||||
|
|
@ -210,7 +212,7 @@ pub async fn create_chat_message_stream(
|
||||||
ChatAuthor::new(uid, ChatAuthorType::Human),
|
ChatAuthor::new(uid, ChatAuthorType::Human),
|
||||||
&chat_id,
|
&chat_id,
|
||||||
params.content.clone(),
|
params.content.clone(),
|
||||||
params.metadata,
|
params.metadata.clone(),
|
||||||
).await {
|
).await {
|
||||||
Ok(question) => question,
|
Ok(question) => question,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
@ -236,7 +238,7 @@ pub async fn create_chat_message_stream(
|
||||||
match params.message_type {
|
match params.message_type {
|
||||||
ChatMessageType::System => {}
|
ChatMessageType::System => {}
|
||||||
ChatMessageType::User => {
|
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,
|
Ok(response) => response,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to send question to AI: {}", err);
|
error!("Failed to send question to AI: {}", err);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue