Spaces:
Runtime error
Runtime error
fix: change table schemas to match submission requirements and migrate some module names
Browse files- Cargo.lock +65 -0
- Cargo.toml +1 -0
- migrations/2025-08-19-034235_create_videos/up.sql +2 -4
- migrations/2025-08-19-041510_create_keyframes/up.sql +4 -3
- src/constants/mod.rs +0 -2
- src/controllers/v1/mod.rs +2 -2
- src/controllers/v1/{vectors → queries}/keyframes/mod.rs +1 -1
- src/controllers/v1/{vectors → queries}/mod.rs +0 -0
- src/models/dtos/keyframes/mod.rs +8 -9
- src/models/dtos/vectors/keyframes/requests/mod.rs +5 -0
- src/models/entities/keyframes/mod.rs +15 -6
- src/models/entities/videos/mod.rs +5 -10
- src/models/states/mod.rs +7 -0
- src/schema.rs +5 -8
- src/services/mod.rs +1 -1
- src/services/{vector_queries → queries}/keyframes/mod.rs +9 -8
- src/services/{vector_queries → queries}/mod.rs +0 -0
Cargo.lock
CHANGED
|
@@ -63,6 +63,7 @@ dependencies = [
|
|
| 63 |
"tower-http",
|
| 64 |
"tracing",
|
| 65 |
"tracing-subscriber",
|
|
|
|
| 66 |
"utoipa",
|
| 67 |
"utoipa-axum",
|
| 68 |
"utoipa-swagger-ui",
|
|
@@ -941,6 +942,15 @@ dependencies = [
|
|
| 941 |
"windows-sys 0.60.2",
|
| 942 |
]
|
| 943 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 944 |
[[package]]
|
| 945 |
name = "http"
|
| 946 |
version = "1.3.1"
|
|
@@ -1336,6 +1346,33 @@ version = "0.1.2"
|
|
| 1336 |
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 1337 |
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
| 1338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1339 |
[[package]]
|
| 1340 |
name = "macro_rules_attribute"
|
| 1341 |
version = "0.2.2"
|
|
@@ -2058,6 +2095,7 @@ dependencies = [
|
|
| 2058 |
"base64 0.22.1",
|
| 2059 |
"bytes",
|
| 2060 |
"encoding_rs",
|
|
|
|
| 2061 |
"futures-core",
|
| 2062 |
"futures-util",
|
| 2063 |
"h2",
|
|
@@ -2943,6 +2981,21 @@ dependencies = [
|
|
| 2943 |
"tracing-log",
|
| 2944 |
]
|
| 2945 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2946 |
[[package]]
|
| 2947 |
name = "try-lock"
|
| 2948 |
version = "0.2.5"
|
|
@@ -3031,6 +3084,18 @@ dependencies = [
|
|
| 3031 |
"percent-encoding",
|
| 3032 |
]
|
| 3033 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3034 |
[[package]]
|
| 3035 |
name = "utf8_iter"
|
| 3036 |
version = "1.0.4"
|
|
|
|
| 63 |
"tower-http",
|
| 64 |
"tracing",
|
| 65 |
"tracing-subscriber",
|
| 66 |
+
"translators",
|
| 67 |
"utoipa",
|
| 68 |
"utoipa-axum",
|
| 69 |
"utoipa-swagger-ui",
|
|
|
|
| 942 |
"windows-sys 0.60.2",
|
| 943 |
]
|
| 944 |
|
| 945 |
+
[[package]]
|
| 946 |
+
name = "html-escape"
|
| 947 |
+
version = "0.2.13"
|
| 948 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 949 |
+
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
| 950 |
+
dependencies = [
|
| 951 |
+
"utf8-width",
|
| 952 |
+
]
|
| 953 |
+
|
| 954 |
[[package]]
|
| 955 |
name = "http"
|
| 956 |
version = "1.3.1"
|
|
|
|
| 1346 |
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 1347 |
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
| 1348 |
|
| 1349 |
+
[[package]]
|
| 1350 |
+
name = "macon"
|
| 1351 |
+
version = "1.3.0"
|
| 1352 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 1353 |
+
checksum = "4e2360fdc60235ad3db2d65bb74539e0813c20a626f7e330ce9a64b2d4e513f0"
|
| 1354 |
+
dependencies = [
|
| 1355 |
+
"macon_api",
|
| 1356 |
+
"macon_derive",
|
| 1357 |
+
]
|
| 1358 |
+
|
| 1359 |
+
[[package]]
|
| 1360 |
+
name = "macon_api"
|
| 1361 |
+
version = "1.3.0"
|
| 1362 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 1363 |
+
checksum = "2330ee9375fc537d78cc438ed16695a5d0201f0be9d977bf6bc4ac11e5b4e177"
|
| 1364 |
+
|
| 1365 |
+
[[package]]
|
| 1366 |
+
name = "macon_derive"
|
| 1367 |
+
version = "1.3.0"
|
| 1368 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 1369 |
+
checksum = "ccd7e1436ba066ad10c8b43ac4a00d304322831b90f039f1d83815f846fee024"
|
| 1370 |
+
dependencies = [
|
| 1371 |
+
"proc-macro2",
|
| 1372 |
+
"quote",
|
| 1373 |
+
"syn",
|
| 1374 |
+
]
|
| 1375 |
+
|
| 1376 |
[[package]]
|
| 1377 |
name = "macro_rules_attribute"
|
| 1378 |
version = "0.2.2"
|
|
|
|
| 2095 |
"base64 0.22.1",
|
| 2096 |
"bytes",
|
| 2097 |
"encoding_rs",
|
| 2098 |
+
"futures-channel",
|
| 2099 |
"futures-core",
|
| 2100 |
"futures-util",
|
| 2101 |
"h2",
|
|
|
|
| 2981 |
"tracing-log",
|
| 2982 |
]
|
| 2983 |
|
| 2984 |
+
[[package]]
|
| 2985 |
+
name = "translators"
|
| 2986 |
+
version = "0.1.5"
|
| 2987 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 2988 |
+
checksum = "2957ae11f61a19fdc8c93cef9e0af3e8638c4672dce5f8d578e6232f55220873"
|
| 2989 |
+
dependencies = [
|
| 2990 |
+
"futures",
|
| 2991 |
+
"html-escape",
|
| 2992 |
+
"macon",
|
| 2993 |
+
"regex",
|
| 2994 |
+
"reqwest",
|
| 2995 |
+
"tokio",
|
| 2996 |
+
"urlencoding",
|
| 2997 |
+
]
|
| 2998 |
+
|
| 2999 |
[[package]]
|
| 3000 |
name = "try-lock"
|
| 3001 |
version = "0.2.5"
|
|
|
|
| 3084 |
"percent-encoding",
|
| 3085 |
]
|
| 3086 |
|
| 3087 |
+
[[package]]
|
| 3088 |
+
name = "urlencoding"
|
| 3089 |
+
version = "2.1.3"
|
| 3090 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 3091 |
+
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
| 3092 |
+
|
| 3093 |
+
[[package]]
|
| 3094 |
+
name = "utf8-width"
|
| 3095 |
+
version = "0.1.7"
|
| 3096 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 3097 |
+
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
| 3098 |
+
|
| 3099 |
[[package]]
|
| 3100 |
name = "utf8_iter"
|
| 3101 |
version = "1.0.4"
|
Cargo.toml
CHANGED
|
@@ -22,6 +22,7 @@ tower = "0.5.2"
|
|
| 22 |
tower-http = { version = "0.6.6", features = ["cors", "trace"] }
|
| 23 |
tracing = "0.1.41"
|
| 24 |
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
|
|
|
| 25 |
utoipa = "5.4.0"
|
| 26 |
utoipa-axum = "0.2.0"
|
| 27 |
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
|
|
|
|
| 22 |
tower-http = { version = "0.6.6", features = ["cors", "trace"] }
|
| 23 |
tracing = "0.1.41"
|
| 24 |
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
| 25 |
+
translators = { version = "0.1.5", features = ["google", "tokio-async"] }
|
| 26 |
utoipa = "5.4.0"
|
| 27 |
utoipa-axum = "0.2.0"
|
| 28 |
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
|
migrations/2025-08-19-034235_create_videos/up.sql
CHANGED
|
@@ -1,7 +1,5 @@
|
|
| 1 |
CREATE TABLE videos (
|
| 2 |
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
watch_url TEXT NOT NULL,
|
| 6 |
-
UNIQUE (l, v)
|
| 7 |
)
|
|
|
|
| 1 |
CREATE TABLE videos (
|
| 2 |
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
| 3 |
+
name TEXT NOT NULL UNIQUE,
|
| 4 |
+
watch_url TEXT NOT NULL
|
|
|
|
|
|
|
| 5 |
)
|
migrations/2025-08-19-041510_create_keyframes/up.sql
CHANGED
|
@@ -1,7 +1,8 @@
|
|
| 1 |
CREATE TABLE keyframes (
|
| 2 |
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
|
|
|
|
|
|
|
|
| 3 |
video_id BIGINT NOT NULL REFERENCES videos (id),
|
| 4 |
-
|
| 5 |
-
video_related_frame_timestamp REAL NOT NULL,
|
| 6 |
-
UNIQUE (video_id, video_related_frame_id)
|
| 7 |
)
|
|
|
|
| 1 |
CREATE TABLE keyframes (
|
| 2 |
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
| 3 |
+
name TEXT NOT NULL,
|
| 4 |
+
frame_index BIGINT NOT NULL,
|
| 5 |
+
frame_timestamp REAL NOT NULL,
|
| 6 |
video_id BIGINT NOT NULL REFERENCES videos (id),
|
| 7 |
+
UNIQUE (video_id, frame_index)
|
|
|
|
|
|
|
| 8 |
)
|
src/constants/mod.rs
CHANGED
|
@@ -1,4 +1,2 @@
|
|
| 1 |
pub const QDRANT_KEYFRAME_COLLECTION_NAME: &str = "keyframes";
|
| 2 |
-
pub const QDRANT_KEYFRAME_COLLECTION_IMAGE_VECTOR_NAME: &str = "images";
|
| 3 |
-
pub const QDRANT_KEYFRAME_COLLECTION_OBJECT_VECTOR_NAME: &str = "objects";
|
| 4 |
pub const OPENAPI_TAG: &str = "AIC Server";
|
|
|
|
| 1 |
pub const QDRANT_KEYFRAME_COLLECTION_NAME: &str = "keyframes";
|
|
|
|
|
|
|
| 2 |
pub const OPENAPI_TAG: &str = "AIC Server";
|
src/controllers/v1/mod.rs
CHANGED
|
@@ -3,12 +3,12 @@ use utoipa_axum::router::OpenApiRouter;
|
|
| 3 |
use crate::models::states::AppState;
|
| 4 |
|
| 5 |
mod keyframes;
|
| 6 |
-
mod
|
| 7 |
mod videos;
|
| 8 |
|
| 9 |
pub fn router() -> OpenApiRouter<AppState> {
|
| 10 |
OpenApiRouter::new()
|
| 11 |
.nest("/keyframes", keyframes::router())
|
| 12 |
.nest("/videos", videos::router())
|
| 13 |
-
.nest("/vectors",
|
| 14 |
}
|
|
|
|
| 3 |
use crate::models::states::AppState;
|
| 4 |
|
| 5 |
mod keyframes;
|
| 6 |
+
mod queries;
|
| 7 |
mod videos;
|
| 8 |
|
| 9 |
pub fn router() -> OpenApiRouter<AppState> {
|
| 10 |
OpenApiRouter::new()
|
| 11 |
.nest("/keyframes", keyframes::router())
|
| 12 |
.nest("/videos", videos::router())
|
| 13 |
+
.nest("/vectors", queries::router())
|
| 14 |
}
|
src/controllers/v1/{vectors → queries}/keyframes/mod.rs
RENAMED
|
@@ -7,7 +7,7 @@ use crate::{
|
|
| 7 |
dtos::vectors::keyframes::{VectorizedKeyframeDto, VectorizedKeyframeRequestDto},
|
| 8 |
states::AppState,
|
| 9 |
},
|
| 10 |
-
services::
|
| 11 |
};
|
| 12 |
|
| 13 |
pub fn router() -> OpenApiRouter<AppState> {
|
|
|
|
| 7 |
dtos::vectors::keyframes::{VectorizedKeyframeDto, VectorizedKeyframeRequestDto},
|
| 8 |
states::AppState,
|
| 9 |
},
|
| 10 |
+
services::queries::keyframes::VectorizedKeyframeService,
|
| 11 |
};
|
| 12 |
|
| 13 |
pub fn router() -> OpenApiRouter<AppState> {
|
src/controllers/v1/{vectors → queries}/mod.rs
RENAMED
|
File without changes
|
src/models/dtos/keyframes/mod.rs
CHANGED
|
@@ -4,23 +4,22 @@ use crate::models::entities::{keyframes::KeyframeEntity, videos::VideoEntity};
|
|
| 4 |
pub struct KeyframeDto {
|
| 5 |
id: i64,
|
| 6 |
path: String,
|
| 7 |
-
|
|
|
|
| 8 |
}
|
| 9 |
|
| 10 |
impl From<(KeyframeEntity, VideoEntity)> for KeyframeDto {
|
| 11 |
fn from((keyframe, video): (KeyframeEntity, VideoEntity)) -> Self {
|
| 12 |
let id = keyframe.id();
|
| 13 |
-
let
|
| 14 |
-
let
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
video.v(),
|
| 18 |
-
keyframe.video_related_frame_id()
|
| 19 |
-
);
|
| 20 |
Self {
|
| 21 |
id,
|
| 22 |
path,
|
| 23 |
-
|
|
|
|
| 24 |
}
|
| 25 |
}
|
| 26 |
}
|
|
|
|
| 4 |
pub struct KeyframeDto {
|
| 5 |
id: i64,
|
| 6 |
path: String,
|
| 7 |
+
frame_index: i64,
|
| 8 |
+
frame_timestamp: f32,
|
| 9 |
}
|
| 10 |
|
| 11 |
impl From<(KeyframeEntity, VideoEntity)> for KeyframeDto {
|
| 12 |
fn from((keyframe, video): (KeyframeEntity, VideoEntity)) -> Self {
|
| 13 |
let id = keyframe.id();
|
| 14 |
+
let frame_index = keyframe.frame_index();
|
| 15 |
+
let frame_timestamp = keyframe.frame_timestamp();
|
| 16 |
+
let video_id = video.id();
|
| 17 |
+
let path = format!("/static/keyframes/{}/{:0>3}.jpg", video_id, keyframe.name());
|
|
|
|
|
|
|
|
|
|
| 18 |
Self {
|
| 19 |
id,
|
| 20 |
path,
|
| 21 |
+
frame_index,
|
| 22 |
+
frame_timestamp,
|
| 23 |
}
|
| 24 |
}
|
| 25 |
}
|
src/models/dtos/vectors/keyframes/requests/mod.rs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
pub struct VectorizedKeyframeRequestDto {
|
| 3 |
prompt: String,
|
| 4 |
top_k: u64,
|
|
|
|
| 5 |
}
|
| 6 |
|
| 7 |
impl VectorizedKeyframeRequestDto {
|
|
@@ -12,4 +13,8 @@ impl VectorizedKeyframeRequestDto {
|
|
| 12 |
pub fn top_k(&self) -> u64 {
|
| 13 |
self.top_k
|
| 14 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
|
|
|
| 2 |
pub struct VectorizedKeyframeRequestDto {
|
| 3 |
prompt: String,
|
| 4 |
top_k: u64,
|
| 5 |
+
object_threshold: f64,
|
| 6 |
}
|
| 7 |
|
| 8 |
impl VectorizedKeyframeRequestDto {
|
|
|
|
| 13 |
pub fn top_k(&self) -> u64 {
|
| 14 |
self.top_k
|
| 15 |
}
|
| 16 |
+
|
| 17 |
+
pub fn object_threshold(&self) -> f64 {
|
| 18 |
+
self.object_threshold
|
| 19 |
+
}
|
| 20 |
}
|
src/models/entities/keyframes/mod.rs
CHANGED
|
@@ -3,8 +3,9 @@
|
|
| 3 |
#[diesel(check_for_backend(diesel::pg::Pg))]
|
| 4 |
pub struct KeyframeEntity {
|
| 5 |
id: i64,
|
| 6 |
-
|
| 7 |
-
|
|
|
|
| 8 |
}
|
| 9 |
|
| 10 |
impl KeyframeEntity {
|
|
@@ -12,11 +13,19 @@ impl KeyframeEntity {
|
|
| 12 |
self.id
|
| 13 |
}
|
| 14 |
|
| 15 |
-
pub fn
|
| 16 |
-
self.
|
| 17 |
}
|
| 18 |
|
| 19 |
-
pub fn
|
| 20 |
-
self.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
}
|
| 22 |
}
|
|
|
|
| 3 |
#[diesel(check_for_backend(diesel::pg::Pg))]
|
| 4 |
pub struct KeyframeEntity {
|
| 5 |
id: i64,
|
| 6 |
+
name: String,
|
| 7 |
+
frame_index: i64,
|
| 8 |
+
frame_timestamp: f32,
|
| 9 |
}
|
| 10 |
|
| 11 |
impl KeyframeEntity {
|
|
|
|
| 13 |
self.id
|
| 14 |
}
|
| 15 |
|
| 16 |
+
pub fn name(&self) -> &str {
|
| 17 |
+
&self.name
|
| 18 |
}
|
| 19 |
|
| 20 |
+
pub fn frame_index(&self) -> i64 {
|
| 21 |
+
self.frame_index
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
pub fn frame_timestamp(&self) -> f32 {
|
| 25 |
+
self.frame_timestamp
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
pub fn name_mut(&mut self) -> &mut String {
|
| 29 |
+
&mut self.name
|
| 30 |
}
|
| 31 |
}
|
src/models/entities/videos/mod.rs
CHANGED
|
@@ -3,8 +3,7 @@
|
|
| 3 |
#[diesel(check_for_backend(diesel::pg::Pg))]
|
| 4 |
pub struct VideoEntity {
|
| 5 |
id: i64,
|
| 6 |
-
|
| 7 |
-
v: i16,
|
| 8 |
watch_url: String,
|
| 9 |
}
|
| 10 |
|
|
@@ -13,15 +12,11 @@ impl VideoEntity {
|
|
| 13 |
self.id
|
| 14 |
}
|
| 15 |
|
| 16 |
-
pub fn l(&self) -> i16 {
|
| 17 |
-
self.l
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
pub fn v(&self) -> i16 {
|
| 21 |
-
self.v
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
pub fn watch_url_mut(&mut self) -> &mut String {
|
| 25 |
&mut self.watch_url
|
| 26 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
}
|
|
|
|
| 3 |
#[diesel(check_for_backend(diesel::pg::Pg))]
|
| 4 |
pub struct VideoEntity {
|
| 5 |
id: i64,
|
| 6 |
+
name: String,
|
|
|
|
| 7 |
watch_url: String,
|
| 8 |
}
|
| 9 |
|
|
|
|
| 12 |
self.id
|
| 13 |
}
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
pub fn watch_url_mut(&mut self) -> &mut String {
|
| 16 |
&mut self.watch_url
|
| 17 |
}
|
| 18 |
+
|
| 19 |
+
pub fn name_mut(&mut self) -> &mut String {
|
| 20 |
+
&mut self.name
|
| 21 |
+
}
|
| 22 |
}
|
src/models/states/mod.rs
CHANGED
|
@@ -5,11 +5,13 @@ use deadpool_diesel::{
|
|
| 5 |
postgres::{Manager, Pool},
|
| 6 |
};
|
| 7 |
use qdrant_client::Qdrant;
|
|
|
|
| 8 |
|
| 9 |
#[derive(Clone)]
|
| 10 |
pub struct AppState {
|
| 11 |
diesel_pool: Pool,
|
| 12 |
qdrant_client: Arc<Qdrant>,
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
impl AppState {
|
|
@@ -17,6 +19,7 @@ impl AppState {
|
|
| 17 |
Ok(Self {
|
| 18 |
diesel_pool: Self::diesel_pool_helper()?,
|
| 19 |
qdrant_client: Self::qdrant_client_helper().await?,
|
|
|
|
| 20 |
})
|
| 21 |
}
|
| 22 |
|
|
@@ -45,4 +48,8 @@ impl AppState {
|
|
| 45 |
pub fn qdrant_client(&self) -> &Qdrant {
|
| 46 |
&self.qdrant_client
|
| 47 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
|
|
|
| 5 |
postgres::{Manager, Pool},
|
| 6 |
};
|
| 7 |
use qdrant_client::Qdrant;
|
| 8 |
+
use translators::GoogleTranslator;
|
| 9 |
|
| 10 |
#[derive(Clone)]
|
| 11 |
pub struct AppState {
|
| 12 |
diesel_pool: Pool,
|
| 13 |
qdrant_client: Arc<Qdrant>,
|
| 14 |
+
translator: GoogleTranslator,
|
| 15 |
}
|
| 16 |
|
| 17 |
impl AppState {
|
|
|
|
| 19 |
Ok(Self {
|
| 20 |
diesel_pool: Self::diesel_pool_helper()?,
|
| 21 |
qdrant_client: Self::qdrant_client_helper().await?,
|
| 22 |
+
translator: GoogleTranslator::default(),
|
| 23 |
})
|
| 24 |
}
|
| 25 |
|
|
|
|
| 48 |
pub fn qdrant_client(&self) -> &Qdrant {
|
| 49 |
&self.qdrant_client
|
| 50 |
}
|
| 51 |
+
|
| 52 |
+
pub fn translator(&self) -> &GoogleTranslator {
|
| 53 |
+
&self.translator
|
| 54 |
+
}
|
| 55 |
}
|
src/schema.rs
CHANGED
|
@@ -3,24 +3,21 @@
|
|
| 3 |
diesel::table! {
|
| 4 |
keyframes (id) {
|
| 5 |
id -> Int8,
|
|
|
|
| 6 |
video_id -> Int8,
|
| 7 |
-
|
| 8 |
-
|
| 9 |
}
|
| 10 |
}
|
| 11 |
|
| 12 |
diesel::table! {
|
| 13 |
videos (id) {
|
| 14 |
id -> Int8,
|
| 15 |
-
|
| 16 |
-
v -> Int2,
|
| 17 |
watch_url -> Text,
|
| 18 |
}
|
| 19 |
}
|
| 20 |
|
| 21 |
diesel::joinable!(keyframes -> videos (video_id));
|
| 22 |
|
| 23 |
-
diesel::allow_tables_to_appear_in_same_query!(
|
| 24 |
-
keyframes,
|
| 25 |
-
videos,
|
| 26 |
-
);
|
|
|
|
| 3 |
diesel::table! {
|
| 4 |
keyframes (id) {
|
| 5 |
id -> Int8,
|
| 6 |
+
name -> Text,
|
| 7 |
video_id -> Int8,
|
| 8 |
+
frame_index -> Int8,
|
| 9 |
+
frame_timestamp -> Float4,
|
| 10 |
}
|
| 11 |
}
|
| 12 |
|
| 13 |
diesel::table! {
|
| 14 |
videos (id) {
|
| 15 |
id -> Int8,
|
| 16 |
+
name -> Text,
|
|
|
|
| 17 |
watch_url -> Text,
|
| 18 |
}
|
| 19 |
}
|
| 20 |
|
| 21 |
diesel::joinable!(keyframes -> videos (video_id));
|
| 22 |
|
| 23 |
+
diesel::allow_tables_to_appear_in_same_query!(keyframes, videos,);
|
|
|
|
|
|
|
|
|
src/services/mod.rs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
pub mod embeddings;
|
| 2 |
pub mod keyframes;
|
| 3 |
-
pub mod
|
| 4 |
pub mod videos;
|
|
|
|
| 1 |
pub mod embeddings;
|
| 2 |
pub mod keyframes;
|
| 3 |
+
pub mod queries;
|
| 4 |
pub mod videos;
|
src/services/{vector_queries → queries}/keyframes/mod.rs
RENAMED
|
@@ -3,12 +3,10 @@ use qdrant_client::{
|
|
| 3 |
qdrant::{PrefetchQueryBuilder, Query, QueryPointsBuilder},
|
| 4 |
};
|
| 5 |
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
|
|
|
| 6 |
|
| 7 |
use crate::{
|
| 8 |
-
constants::
|
| 9 |
-
QDRANT_KEYFRAME_COLLECTION_IMAGE_VECTOR_NAME, QDRANT_KEYFRAME_COLLECTION_NAME,
|
| 10 |
-
QDRANT_KEYFRAME_COLLECTION_OBJECT_VECTOR_NAME,
|
| 11 |
-
},
|
| 12 |
models::{dtos::vectors::keyframes::VectorizedKeyframeDto, states::AppState},
|
| 13 |
services::embeddings::texts::TextEmbeddingService,
|
| 14 |
};
|
|
@@ -16,12 +14,14 @@ use crate::{
|
|
| 16 |
#[derive(Clone, Copy)]
|
| 17 |
pub struct VectorizedKeyframeService<'a> {
|
| 18 |
client: &'a Qdrant,
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
impl<'a> From<&'a AppState> for VectorizedKeyframeService<'a> {
|
| 22 |
fn from(value: &'a AppState) -> Self {
|
| 23 |
Self {
|
| 24 |
client: value.qdrant_client(),
|
|
|
|
| 25 |
}
|
| 26 |
}
|
| 27 |
}
|
|
@@ -37,7 +37,8 @@ impl<'a> VectorizedKeyframeService<'a> {
|
|
| 37 |
text: &str,
|
| 38 |
top_k: u64,
|
| 39 |
) -> anyhow::Result<Vec<VectorizedKeyframeDto>> {
|
| 40 |
-
let
|
|
|
|
| 41 |
|
| 42 |
let query_result = self
|
| 43 |
.client
|
|
@@ -46,11 +47,11 @@ impl<'a> VectorizedKeyframeService<'a> {
|
|
| 46 |
.add_prefetch(
|
| 47 |
PrefetchQueryBuilder::default()
|
| 48 |
.query(Query::new_nearest(embeddings.clone()))
|
| 49 |
-
.using(
|
| 50 |
-
.limit(
|
| 51 |
)
|
| 52 |
.query(Query::new_nearest(embeddings))
|
| 53 |
-
.using(
|
| 54 |
.limit(top_k),
|
| 55 |
)
|
| 56 |
.await?
|
|
|
|
| 3 |
qdrant::{PrefetchQueryBuilder, Query, QueryPointsBuilder},
|
| 4 |
};
|
| 5 |
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
| 6 |
+
use translators::{GoogleTranslator, Translator};
|
| 7 |
|
| 8 |
use crate::{
|
| 9 |
+
constants::QDRANT_KEYFRAME_COLLECTION_NAME,
|
|
|
|
|
|
|
|
|
|
| 10 |
models::{dtos::vectors::keyframes::VectorizedKeyframeDto, states::AppState},
|
| 11 |
services::embeddings::texts::TextEmbeddingService,
|
| 12 |
};
|
|
|
|
| 14 |
#[derive(Clone, Copy)]
|
| 15 |
pub struct VectorizedKeyframeService<'a> {
|
| 16 |
client: &'a Qdrant,
|
| 17 |
+
translator: &'a GoogleTranslator,
|
| 18 |
}
|
| 19 |
|
| 20 |
impl<'a> From<&'a AppState> for VectorizedKeyframeService<'a> {
|
| 21 |
fn from(value: &'a AppState) -> Self {
|
| 22 |
Self {
|
| 23 |
client: value.qdrant_client(),
|
| 24 |
+
translator: value.translator(),
|
| 25 |
}
|
| 26 |
}
|
| 27 |
}
|
|
|
|
| 37 |
text: &str,
|
| 38 |
top_k: u64,
|
| 39 |
) -> anyhow::Result<Vec<VectorizedKeyframeDto>> {
|
| 40 |
+
let translated_text = self.translator.translate_async(text, "vi", "en").await?;
|
| 41 |
+
let embeddings = self.embed_text(&translated_text).await?;
|
| 42 |
|
| 43 |
let query_result = self
|
| 44 |
.client
|
|
|
|
| 47 |
.add_prefetch(
|
| 48 |
PrefetchQueryBuilder::default()
|
| 49 |
.query(Query::new_nearest(embeddings.clone()))
|
| 50 |
+
.using("images")
|
| 51 |
+
.limit(top_k * 10),
|
| 52 |
)
|
| 53 |
.query(Query::new_nearest(embeddings))
|
| 54 |
+
.using("objects")
|
| 55 |
.limit(top_k),
|
| 56 |
)
|
| 57 |
.await?
|
src/services/{vector_queries → queries}/mod.rs
RENAMED
|
File without changes
|