feat: translate api endpoint (#612)

* chore: support translate

* chore: support translate

* chore: update endpoint structs
This commit is contained in:
Nathan.fooo 2024-06-12 12:37:11 +08:00 committed by GitHub
parent d0467e7e2e
commit ff4384fbd0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 104 additions and 10 deletions

View File

@ -1,6 +1,7 @@
use crate::dto::{
ChatAnswer, ChatQuestion, CompleteTextResponse, CompletionType, Document, MessageData,
RepeatedRelatedQuestion, SearchDocumentsRequest, SummarizeRowResponse, TranslateRowResponse,
RepeatedRelatedQuestion, SearchDocumentsRequest, SummarizeRowResponse, TranslateRowData,
TranslateRowResponse,
};
use crate::error::AIError;
@ -81,12 +82,14 @@ impl AppFlowyAIClient {
.into_data()
}
pub async fn translate_row(&self, json: Value) -> Result<TranslateRowResponse, AIError> {
pub async fn translate_row(
&self,
data: TranslateRowData,
) -> Result<TranslateRowResponse, AIError> {
let url = format!("{}/translate_row", self.url);
trace!("translate_row url: {}", url);
let resp = self
.http_client(Method::POST, &url)?
.json(&json)
.json(&data)
.send()
.await?;
AIResponse::<TranslateRowResponse>::from_response(resp)

View File

@ -1,16 +1,12 @@
use serde::{Deserialize, Serialize, Serializer};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::collections::HashMap;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SummarizeRowResponse {
pub text: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TranslateRowResponse {
text: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChatQuestion {
pub chat_id: String,
@ -94,3 +90,27 @@ pub enum CollabType {
UserAwareness = 5,
Unknown = 6,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TranslateRowParams {
pub workspace_id: String,
pub data: TranslateRowData,
}
/// Represents different types of content that can be used to summarize a database row.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TranslateRowData {
pub cells: Vec<TranslateItem>,
pub language: String,
pub include_header: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TranslateItem {
pub title: String,
pub content: String,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct TranslateRowResponse {
pub items: Vec<HashMap<String, String>>,
}

View File

@ -1 +1,2 @@
mod summarize_test;
mod translate_test;

View File

@ -0,0 +1,25 @@
use crate::appflowy_ai_client;
use appflowy_ai_client::dto::{TranslateItem, TranslateRowData};
#[tokio::test]
async fn translate_row_test() {
let client = appflowy_ai_client();
let mut cells = Vec::new();
for (key, value) in [("book name", "Atomic Habits"), ("author", "James Clear")].iter() {
cells.push(TranslateItem {
title: key.to_string(),
content: value.to_string(),
});
}
let data = TranslateRowData {
cells,
language: "Chinese".to_string(),
include_header: false,
};
let result = client.translate_row(data).await.unwrap();
assert_eq!(result.items.len(), 2);
}

View File

@ -3,6 +3,7 @@ use crate::Client;
use reqwest::Method;
use shared_entity::dto::ai_dto::{
CompleteTextParams, CompleteTextResponse, SummarizeRowParams, SummarizeRowResponse,
TranslateRowParams, TranslateRowResponse,
};
use shared_entity::response::{AppResponse, AppResponseError};
use tracing::instrument;
@ -31,6 +32,29 @@ impl Client {
.into_data()
}
#[instrument(level = "info", skip_all)]
pub async fn translate_row(
&self,
params: TranslateRowParams,
) -> Result<TranslateRowResponse, AppResponseError> {
let url = format!(
"{}/api/ai/{}/translate_row",
self.base_url, params.workspace_id
);
let resp = self
.http_client_with_auth(Method::POST, &url)
.await?
.json(&params)
.send()
.await?;
log_request_id(&resp);
AppResponse::<TranslateRowResponse>::from_response(resp)
.await?
.into_data()
}
#[instrument(level = "info", skip_all)]
pub async fn completion_text(
&self,

View File

@ -2,7 +2,7 @@ use crate::state::AppState;
use actix_web::web::{Data, Json};
use actix_web::{web, Scope};
use app_error::AppError;
use appflowy_ai_client::dto::CompleteTextResponse;
use appflowy_ai_client::dto::{CompleteTextResponse, TranslateRowParams, TranslateRowResponse};
use shared_entity::dto::ai_dto::{
CompleteTextParams, SummarizeRowData, SummarizeRowParams, SummarizeRowResponse,
};
@ -13,6 +13,7 @@ pub fn ai_completion_scope() -> Scope {
web::scope("/api/ai/{workspace_id}")
.service(web::resource("/complete_text").route(web::post().to(complete_text_handler)))
.service(web::resource("/summarize_row").route(web::post().to(summarize_row_handler)))
.service(web::resource("/translate_row").route(web::post().to(translate_row_handler)))
}
async fn complete_text_handler(
@ -64,3 +65,23 @@ async fn summarize_row_handler(
},
}
}
#[instrument(level = "debug", skip(state, payload), err)]
async fn translate_row_handler(
state: web::Data<AppState>,
payload: web::Json<TranslateRowParams>,
) -> actix_web::Result<Json<AppResponse<TranslateRowResponse>>> {
let params = payload.into_inner();
match state.ai_client.translate_row(params.data).await {
Ok(resp) => Ok(AppResponse::Ok().with_data(resp).into()),
Err(err) => {
error!("Failed to translate row: {:?}", err);
Ok(
AppResponse::Ok()
.with_data(TranslateRowResponse::default())
.into(),
)
},
}
}