mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-02-06 15:10:20 +00:00
feat: [rust] add Opus-MT
This commit is contained in:
546
rust/Cargo.lock
generated
546
rust/Cargo.lock
generated
@@ -316,12 +316,24 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
@@ -630,6 +642,16 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
@@ -655,14 +677,38 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core 0.20.11",
|
||||
"darling_macro 0.20.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
"darling_core 0.21.3",
|
||||
"darling_macro 0.21.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -679,13 +725,24 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core 0.20.11",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_core 0.21.3",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
@@ -729,6 +786,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||
dependencies = [
|
||||
"pem-rfc7468",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.4"
|
||||
@@ -739,6 +806,37 @@ dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||
dependencies = [
|
||||
"derive_builder_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||
dependencies = [
|
||||
"darling 0.20.11",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_macro"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@@ -865,6 +963,12 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "esaxx-rs"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6"
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "5.4.1"
|
||||
@@ -902,6 +1006,18 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"libredox",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.4"
|
||||
@@ -1206,7 +1322,7 @@ dependencies = [
|
||||
"idna",
|
||||
"ipnet",
|
||||
"once_cell",
|
||||
"rand",
|
||||
"rand 0.9.2",
|
||||
"ring",
|
||||
"thiserror 2.0.17",
|
||||
"tinyvec",
|
||||
@@ -1228,9 +1344,9 @@ dependencies = [
|
||||
"moka",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rand",
|
||||
"rand 0.9.2",
|
||||
"resolv-conf",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -1293,7 +1409,7 @@ dependencies = [
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"tokio",
|
||||
"want",
|
||||
]
|
||||
@@ -1337,7 +1453,7 @@ version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -1418,7 +1534,7 @@ dependencies = [
|
||||
"icu_normalizer_data",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
@@ -1480,7 +1596,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
|
||||
dependencies = [
|
||||
"idna_adapter",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"utf8_iter",
|
||||
]
|
||||
|
||||
@@ -1575,6 +1691,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
@@ -1603,6 +1728,17 @@ version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
@@ -1654,6 +1790,32 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520"
|
||||
dependencies = [
|
||||
"macro_rules_attribute-proc_macro",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro_rules_attribute-proc_macro"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
@@ -1725,11 +1887,33 @@ dependencies = [
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"tagptr",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monostate"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67"
|
||||
dependencies = [
|
||||
"monostate-impl",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monostate-impl"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.14"
|
||||
@@ -1747,6 +1931,21 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
@@ -1784,12 +1983,30 @@ dependencies = [
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
@@ -1873,6 +2090,28 @@ version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "onig"
|
||||
version = "6.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"onig_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onig_sys"
|
||||
version = "69.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.74"
|
||||
@@ -1927,6 +2166,31 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ort"
|
||||
version = "2.0.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa7e49bd669d32d7bc2a15ec540a527e7764aec722a45467814005725bcd721"
|
||||
dependencies = [
|
||||
"ndarray",
|
||||
"ort-sys",
|
||||
"smallvec 2.0.0-alpha.10",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ort-sys"
|
||||
version = "2.0.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2aba9f5c7c479925205799216e7e5d07cc1d4fa76ea8058c60a9a30f6a4e890"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"pkg-config",
|
||||
"sha2",
|
||||
"tar",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oslog"
|
||||
version = "0.2.0"
|
||||
@@ -1969,10 +2233,25 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"smallvec 1.15.1",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.2"
|
||||
@@ -2037,6 +2316,15 @@ version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic-util"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.3"
|
||||
@@ -2133,7 +2421,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.4",
|
||||
"lru-slab",
|
||||
"rand",
|
||||
"rand 0.9.2",
|
||||
"ring",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
@@ -2174,14 +2462,35 @@ version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.1",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2191,7 +2500,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2203,6 +2521,43 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-cond"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9"
|
||||
dependencies = [
|
||||
"either",
|
||||
"itertools 0.11.0",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.18"
|
||||
@@ -2268,7 +2623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"cookie",
|
||||
"cookie_store",
|
||||
@@ -2340,10 +2695,14 @@ dependencies = [
|
||||
"flutter_rust_bridge",
|
||||
"futures",
|
||||
"hickory-resolver",
|
||||
"ndarray",
|
||||
"notify-rust",
|
||||
"once_cell",
|
||||
"ort",
|
||||
"reqwest",
|
||||
"scopeguard",
|
||||
"serde_json",
|
||||
"tokenizers",
|
||||
"tokio",
|
||||
"url",
|
||||
"walkdir",
|
||||
@@ -2581,7 +2940,7 @@ version = "3.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa66c845eee442168b2c8134fec70ac50dc20e760769c8ba0ad1319ca1959b04"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
@@ -2600,7 +2959,7 @@ version = "3.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b91a903660542fced4e99881aa481bdbaec1634568ee02e0b8bd57c64cb38955"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"darling 0.21.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -2659,6 +3018,12 @@ version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "2.0.0-alpha.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d44cfb396c3caf6fbfd0ab422af02631b69ddd96d2eff0b0f0724f9024051b"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.10"
|
||||
@@ -2679,6 +3044,29 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socks"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spm_precompiled"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"nom",
|
||||
"serde",
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
@@ -2761,6 +3149,17 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-winrt-notification"
|
||||
version = "0.7.2"
|
||||
@@ -2900,6 +3299,37 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokenizers"
|
||||
version = "0.20.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b08cc37428a476fc9e20ac850132a513a2e1ce32b6a31addf2b74fa7033b905"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"derive_builder",
|
||||
"esaxx-rs",
|
||||
"getrandom 0.2.16",
|
||||
"itertools 0.12.1",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"macro_rules_attribute",
|
||||
"monostate",
|
||||
"onig",
|
||||
"paste",
|
||||
"rand 0.8.5",
|
||||
"rayon",
|
||||
"rayon-cond",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"spm_precompiled",
|
||||
"thiserror 1.0.69",
|
||||
"unicode-normalization-alignments",
|
||||
"unicode-segmentation",
|
||||
"unicode_categories",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.48.0"
|
||||
@@ -3117,18 +3547,69 @@ version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization-alignments"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de"
|
||||
dependencies = [
|
||||
"smallvec 1.15.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_categories"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "3.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"der",
|
||||
"log",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"rustls-pki-types",
|
||||
"socks",
|
||||
"ureq-proto",
|
||||
"utf-8",
|
||||
"webpki-root-certs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.7"
|
||||
@@ -3141,6 +3622,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
@@ -3309,7 +3796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d12a78aa0bab22d2f26ed1a96df7ab58e8a93506a3e20adb47c51a93b4e1357"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"itertools",
|
||||
"itertools 0.11.0",
|
||||
"nom",
|
||||
"pori",
|
||||
"regex",
|
||||
@@ -3337,6 +3824,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-root-certs"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.3"
|
||||
@@ -3865,6 +4361,16 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -23,6 +23,10 @@ scopeguard = "1.2"
|
||||
notify-rust = "4"
|
||||
asar = "0.3.0"
|
||||
walkdir = "2.5.0"
|
||||
ort = { version = "2.0.0-rc.10", features = ["xnnpack", "download-binaries", "ndarray"] }
|
||||
tokenizers = { version = "0.20", default-features = false, features = ["onig"] }
|
||||
ndarray = "0.16"
|
||||
serde_json = "1.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.62.2", features = ["Win32_UI_WindowsAndMessaging"] }
|
||||
|
||||
@@ -5,3 +5,4 @@ pub mod http_api;
|
||||
pub mod rs_process;
|
||||
pub mod win32_api;
|
||||
pub mod asar_api;
|
||||
pub mod ort_api;
|
||||
|
||||
107
rust/src/api/ort_api.rs
Normal file
107
rust/src/api/ort_api.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
use anyhow::Result;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::ort_models::opus_mt::OpusMtModel;
|
||||
|
||||
/// 全局模型缓存
|
||||
static MODEL_CACHE: Lazy<Mutex<HashMap<String, OpusMtModel>>> =
|
||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
/// 加载 ONNX 翻译模型
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `model_path` - 模型文件夹路径
|
||||
/// * `model_key` - 模型缓存键(用于标识模型,如 "zh-en")
|
||||
/// * `quantization_suffix` - 量化后缀(如 "_q4", "_q8",空字符串表示使用默认模型)
|
||||
///
|
||||
pub fn load_translation_model(
|
||||
model_path: String,
|
||||
model_key: String,
|
||||
quantization_suffix: String,
|
||||
) -> Result<()> {
|
||||
let model = OpusMtModel::new(&model_path, &quantization_suffix)?;
|
||||
|
||||
let mut cache = MODEL_CACHE
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to lock model cache: {}", e))?;
|
||||
|
||||
cache.insert(model_key, model);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 翻译文本
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `model_key` - 模型缓存键(如 "zh-en")
|
||||
/// * `text` - 要翻译的文本
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<String>` - 翻译后的文本
|
||||
pub fn translate_text(model_key: String, text: String) -> Result<String> {
|
||||
let cache = MODEL_CACHE
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to lock model cache: {}", e))?;
|
||||
|
||||
let model = cache.get(&model_key).ok_or_else(|| {
|
||||
anyhow::anyhow!(
|
||||
"Model not found: {}. Please load the model first.",
|
||||
model_key
|
||||
)
|
||||
})?;
|
||||
|
||||
model.translate(&text)
|
||||
}
|
||||
|
||||
/// 批量翻译文本
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `model_key` - 模型缓存键(如 "zh-en")
|
||||
/// * `texts` - 要翻译的文本列表
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<Vec<String>>` - 翻译后的文本列表
|
||||
pub fn translate_text_batch(model_key: String, texts: Vec<String>) -> Result<Vec<String>> {
|
||||
let cache = MODEL_CACHE
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to lock model cache: {}", e))?;
|
||||
|
||||
let model = cache.get(&model_key).ok_or_else(|| {
|
||||
anyhow::anyhow!(
|
||||
"Model not found: {}. Please load the model first.",
|
||||
model_key
|
||||
)
|
||||
})?;
|
||||
|
||||
model.translate_batch(&texts)
|
||||
}
|
||||
|
||||
/// 卸载模型
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `model_key` - 模型缓存键(如 "zh-en")
|
||||
///
|
||||
pub fn unload_translation_model(model_key: String) -> Result<()> {
|
||||
let mut cache = MODEL_CACHE
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to lock model cache: {}", e))?;
|
||||
|
||||
cache.remove(&model_key);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 清空所有已加载的模型
|
||||
///
|
||||
/// # Returns
|
||||
pub fn clear_all_models() -> Result<()> {
|
||||
let mut cache = MODEL_CACHE
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to lock model cache: {}", e))?;
|
||||
|
||||
cache.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -37,7 +37,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
||||
default_rust_auto_opaque = RustAutoOpaqueNom,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1832496273;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -706588047;
|
||||
|
||||
// Section: executor
|
||||
|
||||
@@ -45,6 +45,27 @@ flutter_rust_bridge::frb_generated_default_handler!();
|
||||
|
||||
// Section: wire_funcs
|
||||
|
||||
fn wire__crate__api__ort_api__clear_all_models_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "clear_all_models",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::ort_api::clear_all_models()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__http_api__dns_lookup_ips_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
host: impl CstDecode<String>,
|
||||
@@ -161,6 +182,37 @@ fn wire__crate__api__asar_api__get_rsi_launcher_asar_data_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__load_translation_model_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_path: impl CstDecode<String>,
|
||||
model_key: impl CstDecode<String>,
|
||||
quantization_suffix: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "load_translation_model",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_model_path = model_path.cst_decode();
|
||||
let api_model_key = model_key.cst_decode();
|
||||
let api_quantization_suffix = quantization_suffix.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::ort_api::load_translation_model(
|
||||
api_model_path,
|
||||
api_model_key,
|
||||
api_quantization_suffix,
|
||||
)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
that: impl CstDecode<crate::api::asar_api::RsiLauncherAsarData>,
|
||||
@@ -315,6 +367,82 @@ fn wire__crate__api__rs_process__start_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__translate_text_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_key: impl CstDecode<String>,
|
||||
text: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "translate_text",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_model_key = model_key.cst_decode();
|
||||
let api_text = text.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::ort_api::translate_text(api_model_key, api_text)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__translate_text_batch_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_key: impl CstDecode<String>,
|
||||
texts: impl CstDecode<Vec<String>>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "translate_text_batch",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_model_key = model_key.cst_decode();
|
||||
let api_texts = texts.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::ort_api::translate_text_batch(api_model_key, api_texts)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__unload_translation_model_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_key: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "unload_translation_model",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_model_key = model_key.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::ort_api::unload_translation_model(api_model_key)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__rs_process__write_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
rs_pid: impl CstDecode<u32>,
|
||||
@@ -1361,6 +1489,13 @@ mod io {
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__clear_all_models(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__ort_api__clear_all_models_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__http_api__dns_lookup_ips(
|
||||
port_: i64,
|
||||
@@ -1406,6 +1541,21 @@ mod io {
|
||||
wire__crate__api__asar_api__get_rsi_launcher_asar_data_impl(port_, asar_path)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__load_translation_model(
|
||||
port_: i64,
|
||||
model_path: *mut wire_cst_list_prim_u_8_strict,
|
||||
model_key: *mut wire_cst_list_prim_u_8_strict,
|
||||
quantization_suffix: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__ort_api__load_translation_model_impl(
|
||||
port_,
|
||||
model_path,
|
||||
model_key,
|
||||
quantization_suffix,
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js(
|
||||
port_: i64,
|
||||
@@ -1459,6 +1609,32 @@ mod io {
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__translate_text(
|
||||
port_: i64,
|
||||
model_key: *mut wire_cst_list_prim_u_8_strict,
|
||||
text: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__ort_api__translate_text_impl(port_, model_key, text)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__translate_text_batch(
|
||||
port_: i64,
|
||||
model_key: *mut wire_cst_list_prim_u_8_strict,
|
||||
texts: *mut wire_cst_list_String,
|
||||
) {
|
||||
wire__crate__api__ort_api__translate_text_batch_impl(port_, model_key, texts)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__unload_translation_model(
|
||||
port_: i64,
|
||||
model_key: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__ort_api__unload_translation_model_impl(port_, model_key)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__rs_process__write(
|
||||
port_: i64,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod api;
|
||||
mod frb_generated;
|
||||
pub mod http_package;
|
||||
pub mod ort_models;
|
||||
|
||||
1
rust/src/ort_models/mod.rs
Normal file
1
rust/src/ort_models/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod opus_mt;
|
||||
388
rust/src/ort_models/opus_mt.rs
Normal file
388
rust/src/ort_models/opus_mt.rs
Normal file
@@ -0,0 +1,388 @@
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use ndarray::{Array2, ArrayD};
|
||||
use ort::{
|
||||
execution_providers::XNNPACKExecutionProvider, session::builder::GraphOptimizationLevel,
|
||||
session::Session, value::Value,
|
||||
};
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
use tokenizers::Tokenizer;
|
||||
|
||||
/// Opus-MT 翻译模型的推理结构
|
||||
pub struct OpusMtModel {
|
||||
encoder_session: Mutex<Session>,
|
||||
decoder_session: Mutex<Session>,
|
||||
tokenizer: Tokenizer,
|
||||
config: ModelConfig,
|
||||
}
|
||||
|
||||
/// 模型配置
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModelConfig {
|
||||
pub max_length: usize,
|
||||
pub num_beams: usize,
|
||||
pub decoder_start_token_id: i64,
|
||||
pub eos_token_id: i64,
|
||||
pub pad_token_id: i64,
|
||||
}
|
||||
|
||||
impl Default for ModelConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_length: 512,
|
||||
num_beams: 1,
|
||||
decoder_start_token_id: 0,
|
||||
eos_token_id: 0,
|
||||
pad_token_id: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpusMtModel {
|
||||
/// 从模型路径创建新的 OpusMT 模型实例
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `model_path` - 模型文件夹路径(应包含 onnx 子文件夹)
|
||||
/// * `quantization_suffix` - 量化后缀,如 "_q4", "_q8",为空字符串则使用默认模型
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<Self>` - 成功返回模型实例,失败返回错误
|
||||
pub fn new<P: AsRef<Path>>(model_path: P, quantization_suffix: &str) -> Result<Self> {
|
||||
let model_path = model_path.as_ref();
|
||||
|
||||
// onnx-community 标准:模型在 onnx 子文件夹中
|
||||
let onnx_dir = model_path.join("onnx");
|
||||
|
||||
// 加载 tokenizer(在根目录)
|
||||
let tokenizer_path = model_path.join("tokenizer.json");
|
||||
|
||||
// 动态加载并修复 tokenizer
|
||||
let tokenizer =
|
||||
Self::load_tokenizer(&tokenizer_path).context("Failed to load tokenizer")?;
|
||||
|
||||
// 构建模型文件名
|
||||
let encoder_filename = if quantization_suffix.is_empty() {
|
||||
"encoder_model.onnx".to_string()
|
||||
} else {
|
||||
format!("encoder_model{}.onnx", quantization_suffix)
|
||||
};
|
||||
|
||||
let decoder_filename = if quantization_suffix.is_empty() {
|
||||
"decoder_model.onnx".to_string()
|
||||
} else {
|
||||
format!("decoder_model{}.onnx", quantization_suffix)
|
||||
};
|
||||
|
||||
// 加载 encoder 模型(在 onnx 子目录)
|
||||
let encoder_path = onnx_dir.join(&encoder_filename);
|
||||
if !encoder_path.exists() {
|
||||
return Err(anyhow!(
|
||||
"Encoder model not found: {}",
|
||||
encoder_path.display()
|
||||
));
|
||||
}
|
||||
|
||||
let encoder_session = Session::builder()
|
||||
.context("Failed to create encoder session builder")?
|
||||
.with_optimization_level(GraphOptimizationLevel::Level3)
|
||||
.context("Failed to set optimization level")?
|
||||
.with_intra_threads(4)
|
||||
.context("Failed to set intra threads")?
|
||||
.with_execution_providers([XNNPACKExecutionProvider::default().build()])
|
||||
.context("Failed to register XNNPACK execution provider")?
|
||||
.commit_from_file(&encoder_path)
|
||||
.context(format!(
|
||||
"Failed to load encoder model: {}",
|
||||
encoder_filename
|
||||
))?;
|
||||
|
||||
// 加载 decoder 模型(在 onnx 子目录)
|
||||
let decoder_path = onnx_dir.join(&decoder_filename);
|
||||
if !decoder_path.exists() {
|
||||
return Err(anyhow!(
|
||||
"Decoder model not found: {}",
|
||||
decoder_path.display()
|
||||
));
|
||||
}
|
||||
|
||||
let decoder_session = Session::builder()
|
||||
.context("Failed to create decoder session builder")?
|
||||
.with_optimization_level(GraphOptimizationLevel::Level3)
|
||||
.context("Failed to set optimization level")?
|
||||
.with_intra_threads(4)
|
||||
.context("Failed to set intra threads")?
|
||||
.with_execution_providers([XNNPACKExecutionProvider::default().build()])
|
||||
.context("Failed to register XNNPACK execution provider")?
|
||||
.commit_from_file(&decoder_path)
|
||||
.context(format!(
|
||||
"Failed to load decoder model: {}",
|
||||
decoder_filename
|
||||
))?;
|
||||
|
||||
// 加载配置(如果存在,在根目录)
|
||||
let config = Self::load_config(model_path)?;
|
||||
|
||||
Ok(Self {
|
||||
encoder_session: Mutex::new(encoder_session),
|
||||
decoder_session: Mutex::new(decoder_session),
|
||||
tokenizer,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
/// 动态加载 tokenizer,自动修复常见问题
|
||||
fn load_tokenizer(tokenizer_path: &Path) -> Result<Tokenizer> {
|
||||
use std::fs;
|
||||
|
||||
// 读取原始文件
|
||||
let content =
|
||||
fs::read_to_string(tokenizer_path).context("Failed to read tokenizer.json")?;
|
||||
|
||||
// 解析为 JSON
|
||||
let mut json: serde_json::Value =
|
||||
serde_json::from_str(&content).context("Failed to parse tokenizer.json")?;
|
||||
|
||||
let mut needs_fix = false;
|
||||
|
||||
// 修复 normalizer 中的问题
|
||||
if let Some(obj) = json.as_object_mut() {
|
||||
if let Some(normalizer) = obj.get("normalizer") {
|
||||
let mut should_remove_normalizer = false;
|
||||
|
||||
if normalizer.is_null() {
|
||||
// normalizer 是 null,需要移除
|
||||
should_remove_normalizer = true;
|
||||
} else if let Some(norm_obj) = normalizer.as_object() {
|
||||
// 检查是否是有问题的 Precompiled 类型
|
||||
if let Some(type_val) = norm_obj.get("type") {
|
||||
if type_val.as_str() == Some("Precompiled") {
|
||||
// 检查 precompiled_charsmap 字段
|
||||
if let Some(precompiled) = norm_obj.get("precompiled_charsmap") {
|
||||
if precompiled.is_null() {
|
||||
// precompiled_charsmap 是 null,移除整个 normalizer
|
||||
should_remove_normalizer = true;
|
||||
}
|
||||
} else {
|
||||
// 缺少 precompiled_charsmap 字段,移除整个 normalizer
|
||||
should_remove_normalizer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if should_remove_normalizer {
|
||||
obj.remove("normalizer");
|
||||
needs_fix = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从修复后的 JSON 字符串加载 tokenizer
|
||||
let json_str = if needs_fix {
|
||||
serde_json::to_string(&json).context("Failed to serialize fixed tokenizer")?
|
||||
} else {
|
||||
content
|
||||
};
|
||||
|
||||
// 从字节数组加载 tokenizer
|
||||
Tokenizer::from_bytes(json_str.as_bytes())
|
||||
.map_err(|e| anyhow!("Failed to load tokenizer: {}", e))
|
||||
}
|
||||
|
||||
/// 从配置文件加载模型配置
|
||||
fn load_config(model_path: &Path) -> Result<ModelConfig> {
|
||||
let config_path = model_path.join("config.json");
|
||||
|
||||
if config_path.exists() {
|
||||
let config_str =
|
||||
std::fs::read_to_string(config_path).context("Failed to read config.json")?;
|
||||
let config_json: serde_json::Value =
|
||||
serde_json::from_str(&config_str).context("Failed to parse config.json")?;
|
||||
|
||||
Ok(ModelConfig {
|
||||
max_length: config_json["max_length"].as_u64().unwrap_or(512) as usize,
|
||||
num_beams: config_json["num_beams"].as_u64().unwrap_or(1) as usize,
|
||||
decoder_start_token_id: config_json["decoder_start_token_id"].as_i64().unwrap_or(0),
|
||||
eos_token_id: config_json["eos_token_id"].as_i64().unwrap_or(0),
|
||||
pad_token_id: config_json["pad_token_id"].as_i64().unwrap_or(0),
|
||||
})
|
||||
} else {
|
||||
Ok(ModelConfig::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// 翻译文本
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `text` - 要翻译的文本
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<String>` - 翻译后的文本
|
||||
pub fn translate(&self, text: &str) -> Result<String> {
|
||||
// 1. Tokenize 输入文本
|
||||
let encoding = self
|
||||
.tokenizer
|
||||
.encode(text, true)
|
||||
.map_err(|e| anyhow!("Failed to encode text: {}", e))?;
|
||||
|
||||
let input_ids = encoding.get_ids();
|
||||
let attention_mask = encoding.get_attention_mask();
|
||||
|
||||
// 2. 准备 encoder 输入
|
||||
let batch_size = 1;
|
||||
let seq_len = input_ids.len();
|
||||
|
||||
let input_ids_array: Array2<i64> = Array2::from_shape_vec(
|
||||
(batch_size, seq_len),
|
||||
input_ids.iter().map(|&id| id as i64).collect(),
|
||||
)
|
||||
.context("Failed to create input_ids array")?;
|
||||
|
||||
let attention_mask_array: Array2<i64> = Array2::from_shape_vec(
|
||||
(batch_size, seq_len),
|
||||
attention_mask.iter().map(|&mask| mask as i64).collect(),
|
||||
)
|
||||
.context("Failed to create attention_mask array")?;
|
||||
|
||||
// 3. 运行 encoder
|
||||
let input_ids_value =
|
||||
Value::from_array(input_ids_array).context("Failed to create input_ids value")?;
|
||||
let attention_mask_value = Value::from_array(attention_mask_array.clone())
|
||||
.context("Failed to create attention_mask value")?;
|
||||
|
||||
let encoder_inputs = ort::inputs![
|
||||
"input_ids" => input_ids_value,
|
||||
"attention_mask" => attention_mask_value,
|
||||
];
|
||||
|
||||
let mut encoder_session = self
|
||||
.encoder_session
|
||||
.lock()
|
||||
.map_err(|e| anyhow!("Failed to lock encoder session: {}", e))?;
|
||||
let encoder_outputs = encoder_session
|
||||
.run(encoder_inputs)
|
||||
.context("Failed to run encoder")?;
|
||||
|
||||
let encoder_hidden_states = encoder_outputs["last_hidden_state"]
|
||||
.try_extract_tensor::<f32>()
|
||||
.context("Failed to extract encoder hidden states")?;
|
||||
|
||||
// 将 tensor 转换为 ArrayD
|
||||
let (shape, data) = encoder_hidden_states;
|
||||
let shape_vec: Vec<usize> = shape.iter().map(|&x| x as usize).collect();
|
||||
let encoder_array = ArrayD::from_shape_vec(shape_vec, data.to_vec())
|
||||
.context("Failed to create encoder array")?;
|
||||
|
||||
// 4. 贪婪解码生成输出
|
||||
let output_ids = self.greedy_decode(encoder_array, &attention_mask_array)?;
|
||||
|
||||
// 5. Decode 输出 token IDs
|
||||
let output_tokens: Vec<u32> = output_ids.iter().map(|&id| id as u32).collect();
|
||||
let decoded = self
|
||||
.tokenizer
|
||||
.decode(&output_tokens, true)
|
||||
.map_err(|e| anyhow!("Failed to decode output: {}", e))?;
|
||||
|
||||
Ok(decoded)
|
||||
}
|
||||
|
||||
/// 贪婪解码
|
||||
fn greedy_decode(
|
||||
&self,
|
||||
encoder_hidden_states: ArrayD<f32>,
|
||||
encoder_attention_mask: &Array2<i64>,
|
||||
) -> Result<Vec<i64>> {
|
||||
let batch_size = 1;
|
||||
let mut generated_ids = vec![self.config.decoder_start_token_id];
|
||||
|
||||
for _ in 0..self.config.max_length {
|
||||
// 准备 decoder 输入
|
||||
let decoder_input_len = generated_ids.len();
|
||||
let decoder_input_ids: Array2<i64> =
|
||||
Array2::from_shape_vec((batch_size, decoder_input_len), generated_ids.clone())
|
||||
.context("Failed to create decoder input_ids")?;
|
||||
|
||||
// 创建 ORT Value
|
||||
let decoder_input_value = Value::from_array(decoder_input_ids)
|
||||
.context("Failed to create decoder input value")?;
|
||||
let encoder_hidden_value = Value::from_array(encoder_hidden_states.clone())
|
||||
.context("Failed to create encoder hidden value")?;
|
||||
let encoder_mask_value = Value::from_array(encoder_attention_mask.clone())
|
||||
.context("Failed to create encoder mask value")?;
|
||||
|
||||
// 运行 decoder
|
||||
let decoder_inputs = ort::inputs![
|
||||
"input_ids" => decoder_input_value,
|
||||
"encoder_hidden_states" => encoder_hidden_value,
|
||||
"encoder_attention_mask" => encoder_mask_value,
|
||||
];
|
||||
|
||||
let mut decoder_session = self
|
||||
.decoder_session
|
||||
.lock()
|
||||
.map_err(|e| anyhow!("Failed to lock decoder session: {}", e))?;
|
||||
let decoder_outputs = decoder_session
|
||||
.run(decoder_inputs)
|
||||
.context("Failed to run decoder")?;
|
||||
|
||||
// 获取 logits
|
||||
let logits_tensor = decoder_outputs["logits"]
|
||||
.try_extract_tensor::<f32>()
|
||||
.context("Failed to extract logits")?;
|
||||
|
||||
let (logits_shape, logits_data) = logits_tensor;
|
||||
let vocab_size = logits_shape[2] as usize;
|
||||
|
||||
// 获取最后一个 token 的 logits
|
||||
let last_token_idx = decoder_input_len - 1;
|
||||
let last_logits_start = last_token_idx * vocab_size;
|
||||
let last_logits_end = last_logits_start + vocab_size;
|
||||
|
||||
let last_logits_slice = &logits_data[last_logits_start..last_logits_end];
|
||||
|
||||
// 找到最大概率的 token
|
||||
let next_token_id = last_logits_slice
|
||||
.iter()
|
||||
.enumerate()
|
||||
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
|
||||
.map(|(idx, _)| idx as i64)
|
||||
.context("Failed to find max token")?;
|
||||
|
||||
// 检查是否到达结束 token
|
||||
if next_token_id == self.config.eos_token_id {
|
||||
break;
|
||||
}
|
||||
|
||||
generated_ids.push(next_token_id);
|
||||
}
|
||||
|
||||
Ok(generated_ids)
|
||||
}
|
||||
|
||||
/// 批量翻译文本
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `texts` - 要翻译的文本列表
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<Vec<String>>` - 翻译后的文本列表
|
||||
pub fn translate_batch(&self, texts: &[String]) -> Result<Vec<String>> {
|
||||
texts.iter().map(|text| self.translate(text)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_translation() {
|
||||
let model = OpusMtModel::new(
|
||||
"C:\\Users\\xkeyc\\Downloads\\onnx_models\\opus-mt-zh-en",
|
||||
"_q4f16",
|
||||
)
|
||||
.unwrap();
|
||||
let result = model.translate("你好世界").unwrap();
|
||||
println!("Translation: {}", result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user