diff --git a/Cargo.lock b/Cargo.lock
index 6aa29a4..bb4c4e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -610,9 +610,9 @@ checksum = "8c98b077c7463d01d22dde8a24378ddf1ca7263dc687cffbed38819ea6c21131"
[[package]]
name = "duckduckgo"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d2f5930dc4e7056b3e8dfc80ede384c5589759f97673df8ec1c17a5aa07a106"
+checksum = "3e844e28d1de0538ae3d851c46a4b9c532ba6b4f63acd4ac1d96fce90c5f79ca"
dependencies = [
"anyhow",
"chrono",
diff --git a/Cargo.toml b/Cargo.toml
index 86bce6e..6ce1ff6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,7 +30,7 @@ chrono = { version = "0.4.44", features = ["serde"] }
uuid = { version = "1.23.1", features = ["v4"] }
derivative = "2.2.0"
clap = { version = "4.6.1", features = ["derive"] }
-duckduckgo = "0.3.1"
+duckduckgo = "0.3.2"
lopdf = { version = "0.40.0" }
reqwest = { version = "0.12", features = ["json"] }
pyo3 = { version = "0.28.3", features = ["extension-module"] }
diff --git a/examples/chat/Cargo.lock b/examples/chat/Cargo.lock
index 93b6497..19a31ef 100644
--- a/examples/chat/Cargo.lock
+++ b/examples/chat/Cargo.lock
@@ -95,9 +95,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
-version = "1.2.60"
+version = "1.2.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
+checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -105,12 +105,6 @@ dependencies = [
"shlex",
]
-[[package]]
-name = "cesu8"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
-
[[package]]
name = "cfg-if"
version = "1.0.4"
@@ -344,9 +338,9 @@ dependencies = [
[[package]]
name = "duckduckgo"
-version = "0.2.3"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c636351c9be07452ad1cb2be62e33bf187b00db469588313bf37261fd430b48"
+checksum = "3e844e28d1de0538ae3d851c46a4b9c532ba6b4f63acd4ac1d96fce90c5f79ca"
dependencies = [
"anyhow",
"chrono",
@@ -736,9 +730,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
+checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
dependencies = [
"atomic-waker",
"bytes",
@@ -1026,9 +1020,9 @@ dependencies = [
[[package]]
name = "idna_adapter"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
dependencies = [
"icu_normalizer",
"icu_properties",
@@ -1082,16 +1076,6 @@ version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
-[[package]]
-name = "iri-string"
-version = "0.7.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
-dependencies = [
- "memchr",
- "serde",
-]
-
[[package]]
name = "itoa"
version = "1.0.18"
@@ -1100,27 +1084,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "jni"
-version = "0.21.1"
+version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
+checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
dependencies = [
- "cesu8",
"cfg-if",
"combine",
- "jni-sys 0.3.1",
+ "jni-macros",
+ "jni-sys",
"log",
- "thiserror 1.0.69",
+ "simd_cesu8",
+ "thiserror 2.0.18",
"walkdir",
- "windows-sys 0.45.0",
+ "windows-link",
]
[[package]]
-name = "jni-sys"
-version = "0.3.1"
+name = "jni-macros"
+version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258"
+checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
- "jni-sys 0.4.1",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "simd_cesu8",
+ "syn 2.0.117",
]
[[package]]
@@ -1154,9 +1143,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.95"
+version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
+checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -1172,9 +1161,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
-version = "0.2.185"
+version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "litemap"
@@ -1190,16 +1179,17 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "lmm"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09bb00ebb454566a4492aac75ddd06e8761799c6dcfe51ab67a1a77c42cc9f4"
+version = "0.2.7"
dependencies = [
"anyhow",
"duckduckgo",
"getrandom 0.4.2",
+ "phf 0.13.1",
"rand 0.10.1",
"serde",
"serde_json",
+ "strum",
+ "strum_macros",
"thiserror 2.0.18",
"tracing",
]
@@ -1429,18 +1419,18 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.1.11"
+version = "1.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517"
+checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.11"
+version = "1.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6"
+checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389"
dependencies = [
"proc-macro2",
"quote",
@@ -1726,9 +1716,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
-version = "0.13.2"
+version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801"
+checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
dependencies = [
"base64",
"bytes",
@@ -1798,9 +1788,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.38"
+version = "0.23.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21"
+checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
dependencies = [
"aws-lc-rs",
"once_cell",
@@ -1824,9 +1814,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.14.0"
+version = "1.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
+checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
dependencies = [
"web-time",
"zeroize",
@@ -1834,9 +1824,9 @@ dependencies = [
[[package]]
name = "rustls-platform-verifier"
-version = "0.6.2"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
+checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
@@ -1861,9 +1851,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
-version = "0.103.12"
+version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06"
+checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [
"aws-lc-rs",
"ring",
@@ -2051,11 +2041,27 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+[[package]]
+name = "simd_cesu8"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
+dependencies = [
+ "rustc_version",
+ "simdutf8",
+]
+
+[[package]]
+name = "simdutf8"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+
[[package]]
name = "siphasher"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
+checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -2109,6 +2115,27 @@ dependencies = [
"quote",
]
+[[package]]
+name = "strum"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "subtle"
version = "2.6.1"
@@ -2285,9 +2312,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.52.1"
+version = "1.52.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
+checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386"
dependencies = [
"bytes",
"libc",
@@ -2394,20 +2421,20 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.6.8"
+version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
+checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
dependencies = [
"bitflags",
"bytes",
"futures-util",
"http 1.4.0",
"http-body",
- "iri-string",
"pin-project-lite",
"tower",
"tower-layer",
"tower-service",
+ "url",
]
[[package]]
@@ -2564,9 +2591,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
+checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -2577,9 +2604,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.68"
+version = "0.4.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
+checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2587,9 +2614,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
+checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2597,9 +2624,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
+checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -2610,9 +2637,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
+checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -2653,9 +2680,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.95"
+version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
+checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2673,9 +2700,9 @@ dependencies = [
[[package]]
name = "web_atoms"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a9779e9f04d2ac1ce317aee707aa2f6b773afba7b931222bff6983843b1576"
+checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538"
dependencies = [
"phf 0.13.1",
"phf_codegen",
@@ -2771,15 +2798,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
[[package]]
name = "windows-sys"
version = "0.52.0"
@@ -2807,21 +2825,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
-]
-
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -2855,12 +2858,6 @@ dependencies = [
"windows_x86_64_msvc 0.53.1",
]
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
@@ -2873,12 +2870,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
@@ -2891,12 +2882,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@@ -2921,12 +2906,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
-[[package]]
-name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
@@ -2939,12 +2918,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
@@ -2957,12 +2930,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
@@ -2975,12 +2942,6 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
-
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
diff --git a/examples/chat/Cargo.toml b/examples/chat/Cargo.toml
index dea4dab..b21030f 100644
--- a/examples/chat/Cargo.toml
+++ b/examples/chat/Cargo.toml
@@ -9,7 +9,7 @@ path = "src/main.rs"
[dependencies]
input-rs = { version = "0.2.6", features = ["yew"] }
-lmm = { version = "0.1.11", features = ["wasm-net"] }
+lmm = { version = "0.2.8", features = ["wasm-net"] }
serde = { version = "1.0.228", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.104", default-features = false }
wasm-bindgen = { version = "0.2.87", default-features = false }
diff --git a/examples/chat/README.md b/examples/chat/README.md
index 3180a12..49381e2 100644
--- a/examples/chat/README.md
+++ b/examples/chat/README.md
@@ -31,3 +31,14 @@ trunk serve --port 3000
trunk build
# Output in dist/
```
+
+### DuckDuckGo CORS Proxy
+
+By default, the **Ask** feature falls back to **Wikipedia** in production to bypass browser CORS restrictions. To enable full DuckDuckGo search:
+
+1. Set the URL in `.cargo/config.toml`:
+ ```toml
+ [env]
+ DDG_CORS_PROXY_URL = "https://your-proxy.workers.dev"
+ ```
+1. Rebuild: `trunk build`
diff --git a/examples/chat/index.html b/examples/chat/index.html
index 15cc306..c9e67a9 100644
--- a/examples/chat/index.html
+++ b/examples/chat/index.html
@@ -7,7 +7,7 @@
name="description"
content="VECT: Variable Equation Computation Technology. A chat interface powered by the LMM framework demonstrating deterministic and stochastic text generation."
/>
-
+
+
VECT | Variable Equation Computation Technology
diff --git a/examples/chat/src/app.rs b/examples/chat/src/app.rs
index c450207..582fa6b 100644
--- a/examples/chat/src/app.rs
+++ b/examples/chat/src/app.rs
@@ -181,11 +181,7 @@ pub fn app() -> Html {
aria-label="Toggle configuration panel"
aria-expanded={(*sidebar_open).to_string()}
>
-
-
-
-
+
{"Configure"}
diff --git a/examples/chat/src/components/chat_window.rs b/examples/chat/src/components/chat_window.rs
index a2636d4..c56d72c 100644
--- a/examples/chat/src/components/chat_window.rs
+++ b/examples/chat/src/components/chat_window.rs
@@ -32,17 +32,9 @@ pub fn chat_window(props: &ChatWindowProps) -> Html {
if props.messages.is_empty() {
-
-
-
-
-
-
-
-
-
-
-
+
+
+
{"Welcome to VECT"}
{"Select a generation mode from the sidebar, then type any text below to begin."}
@@ -52,11 +44,11 @@ pub fn chat_window(props: &ChatWindowProps) -> Html {
{for GenerationMode::all().into_iter().map(|m| html! {
-
{m.icon()}
-
{m.label()}
+
+
{m.label()}
{m.description()}
})}
@@ -69,15 +61,15 @@ pub fn chat_window(props: &ChatWindowProps) -> Html {
})}
if props.is_loading {
-
-
{"V"}
+
+
{"Searching & generating"}
-
-
-
+
+
+
diff --git a/examples/chat/src/components/header.rs b/examples/chat/src/components/header.rs
index 4a99bc8..2c54d59 100644
--- a/examples/chat/src/components/header.rs
+++ b/examples/chat/src/components/header.rs
@@ -8,19 +8,9 @@ pub fn header() -> Html {
role="banner"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/examples/chat/src/components/input_bar.rs b/examples/chat/src/components/input_bar.rs
index ae3f422..230f08b 100644
--- a/examples/chat/src/components/input_bar.rs
+++ b/examples/chat/src/components/input_bar.rs
@@ -64,7 +64,7 @@ pub fn input_bar(props: &InputBarProps) -> Html {
handle={input_handle}
name={"message"}
r#ref={input_ref}
- placeholder={"Type a seed, text or question... (Enter=send, Shift+Enter=newline)"}
+ placeholder={"Ask anything..."}
input_class={"vect-textarea"}
field_class={"w-full"}
error_class={""}
@@ -74,7 +74,7 @@ pub fn input_bar(props: &InputBarProps) -> Html {
/>
Html {
type="button"
>
if props.is_loading {
-
-
-
-
+
} else {
-
-
-
+
}
diff --git a/examples/chat/src/components/message_bubble.rs b/examples/chat/src/components/message_bubble.rs
index e331f1f..dfef44f 100644
--- a/examples/chat/src/components/message_bubble.rs
+++ b/examples/chat/src/components/message_bubble.rs
@@ -20,10 +20,10 @@ pub fn message_bubble(props: &MessageBubbleProps) -> Html {
- {"U"}
+
}
@@ -31,10 +31,10 @@ pub fn message_bubble(props: &MessageBubbleProps) -> Html {
html! {
- {"V"}
+
{if let Some(mode) = &props.message.mode {
@@ -60,14 +60,12 @@ pub fn message_bubble(props: &MessageBubbleProps) -> Html {
href={url}
target="_blank"
rel="noopener noreferrer"
- class="inline-flex items-center gap-1 text-xs px-2 py-1 rounded-full \
- bg-vect-violet/10 text-vect-violet-light border border-vect-violet/20 \
- hover:bg-vect-violet/20 hover:border-vect-violet/40 \
+ class="inline-flex items-center gap-1 text-xs px-2 py-1 rounded-md \
+ bg-vect-elevated text-vect-muted border border-vect-border \
+ hover:bg-vect-border hover:text-vect-text \
transition-all duration-150 max-w-[180px] truncate"
>
-
-
-
+
{title}
}
diff --git a/examples/chat/src/components/mode_badge.rs b/examples/chat/src/components/mode_badge.rs
index e235c07..3aa8dc8 100644
--- a/examples/chat/src/components/mode_badge.rs
+++ b/examples/chat/src/components/mode_badge.rs
@@ -10,7 +10,7 @@ pub struct ModeBadgeProps {
pub fn mode_badge(props: &ModeBadgeProps) -> Html {
html! {
- {props.mode.icon()}
+
{" "}{props.mode.label()}
}
diff --git a/examples/chat/src/components/sidebar.rs b/examples/chat/src/components/sidebar.rs
index 7c9bc27..5260068 100644
--- a/examples/chat/src/components/sidebar.rs
+++ b/examples/chat/src/components/sidebar.rs
@@ -76,7 +76,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
id={format!("mode-{}", m.label().to_lowercase())}
title={m.description()}
>
-
{m.icon()}
+
{m.label()}
{m.description()}
@@ -106,7 +106,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
class={classes!(
"toggle-track",
"shrink-0",
- if props.stochastic { "bg-vect-violet" } else { "bg-vect-border" }
+ if props.stochastic { "bg-vect-accent" } else { "bg-vect-border" }
)}
>
Html {
{"Probability"}
-
+
{format!("{}%", props.probability)}
@@ -129,7 +129,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
min="1"
max="100"
value={props.probability.to_string()}
- class="w-full h-1.5 rounded-full cursor-pointer accent-vect-violet bg-vect-border"
+ class="w-full h-1.5 rounded-full cursor-pointer accent-vect-accent bg-vect-border"
oninput={on_prob}
aria-label="Synonym replacement probability"
aria-valuemin="1"
@@ -167,7 +167,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
class={classes!(
"toggle-track",
"shrink-0",
- if props.web_search { "bg-vect-cyan" } else { "bg-vect-border" }
+ if props.web_search { "bg-vect-accent" } else { "bg-vect-border" }
)}
>
Html {
if props.web_search {
-
- {"🌐 DuckDuckGo search fetches live context for your query."}
+
+
+ {"DuckDuckGo search fetches live context for your query."}
} else {
@@ -251,7 +252,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
{"Powered by "}
- {"LMM"}
+ {"LMM"}
{" - Large Mathematical Model. All text generation runs locally in your browser via WebAssembly."}
diff --git a/examples/chat/src/lmm_bridge.rs b/examples/chat/src/lmm_bridge.rs
index 5b4f388..70628bd 100644
--- a/examples/chat/src/lmm_bridge.rs
+++ b/examples/chat/src/lmm_bridge.rs
@@ -1,7 +1,5 @@
use crate::types::SearchLink;
-use lmm::net::{
- SearchAggregator, corpus_from_response, corpus_from_results, corpus_from_results_raw,
-};
+use lmm::net::{SearchAggregator, corpus_from_response};
use lmm::predict::TextPredictor;
use lmm::stochastic::StochasticEnhancer;
use lmm::text::{EssayGenerator, ParagraphGenerator, SentenceGenerator, TextSummarizer};
@@ -14,6 +12,20 @@ fn enhance(text: &str, stochastic: bool, prob: f64) -> String {
}
}
+fn local_fallback(prompt: &str, sentences: usize, stochastic: bool, prob: f64) -> String {
+ match ParagraphGenerator::new(sentences.max(2), 50, 5).generate(prompt) {
+ Ok(p) => enhance(&p, stochastic, prob),
+ Err(_) => match SentenceGenerator::new(50, 5).generate(prompt) {
+ Ok(s) => enhance(&s, stochastic, prob),
+ Err(_) => format!(
+ "I could not retrieve web results for \"{prompt}\" \
+ and the local model lacks enough context to generate a meaningful response. \
+ Please try a more descriptive query."
+ ),
+ },
+ }
+}
+
pub fn generate_sentence(seed: &str, stochastic: bool, prob: f64) -> String {
match SentenceGenerator::new(50, 5).generate(seed) {
Ok(s) => enhance(&s, stochastic, prob),
@@ -77,7 +89,9 @@ pub async fn ask(
stochastic: bool,
prob: f64,
) -> (String, Vec) {
+ let prompt = prompt.trim();
let aggregator = SearchAggregator::new();
+
let api_result = aggregator.get_response(prompt).await;
let corpus = api_result
@@ -85,7 +99,7 @@ pub async fn ask(
.map(corpus_from_response)
.unwrap_or_default();
- let mut links: Vec = api_result
+ let links: Vec = api_result
.as_ref()
.map(|resp| {
resp.related_topics
@@ -116,19 +130,9 @@ pub async fn ask(
let final_corpus = if corpus.trim().is_empty() {
#[cfg(not(target_arch = "wasm32"))]
{
+ use lmm::net::{corpus_from_results, corpus_from_results_raw};
match aggregator.fetch(prompt, 6).await {
Ok(results) => {
- if links.is_empty() {
- links = results
- .iter()
- .filter(|r| !r.url.is_empty())
- .map(|r| SearchLink {
- title: r.title.clone(),
- url: r.url.clone(),
- })
- .take(10)
- .collect();
- }
let quality = corpus_from_results(&results);
if quality.trim().is_empty() {
corpus_from_results_raw(&results)
@@ -148,12 +152,7 @@ pub async fn ask(
};
if final_corpus.trim().is_empty() {
- return (
- "The DuckDuckGo Instant Answer API returned no content for this query. \
- Try a more specific well-known topic."
- .to_string(),
- links,
- );
+ return (local_fallback(prompt, sentences, stochastic, prob), links);
}
let summary = match TextSummarizer::new(sentences.max(2), 50, 5)
@@ -164,7 +163,7 @@ pub async fn ask(
.map(|s| enhance(s, stochastic, prob))
.collect::>()
.join(" "),
- Err(_) => "Could not summarize search results.".to_string(),
+ Err(_) => local_fallback(prompt, sentences, stochastic, prob),
};
(summary, links)
diff --git a/examples/chat/src/tailwind.css b/examples/chat/src/tailwind.css
index f108ce7..315f098 100644
--- a/examples/chat/src/tailwind.css
+++ b/examples/chat/src/tailwind.css
@@ -29,7 +29,7 @@
}
::-webkit-scrollbar-track {
- @apply bg-vect-surface;
+ @apply bg-transparent;
}
::-webkit-scrollbar-thumb {
@@ -38,11 +38,11 @@
}
::-webkit-scrollbar-thumb:hover {
- @apply bg-vect-violet;
+ @apply bg-vect-subtle;
}
::selection {
- @apply bg-vect-violet text-white;
+ @apply bg-vect-accent text-white;
}
}
@@ -52,41 +52,41 @@
}
.vect-btn-primary {
- @apply inline-flex items-center justify-center gap-2 bg-vect-violet hover:bg-vect-violet-hover
- text-white font-semibold px-4 py-2 rounded-xl transition-all duration-200
- focus:outline-none focus:ring-2 focus:ring-vect-violet focus:ring-offset-2 focus:ring-offset-vect-bg
- active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed;
+ @apply inline-flex items-center justify-center gap-2 bg-vect-accent hover:bg-vect-accent-hover
+ text-white font-medium px-4 py-2 rounded-full transition-all duration-200
+ focus:outline-none focus:ring-2 focus:ring-vect-accent focus:ring-offset-2 focus:ring-offset-vect-bg
+ active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed;
}
.vect-btn-ghost {
@apply inline-flex items-center justify-center gap-2 bg-transparent hover:bg-vect-elevated
- text-vect-muted hover:text-vect-text font-medium px-3 py-2 rounded-xl transition-all duration-200
- focus:outline-none focus:ring-2 focus:ring-vect-violet;
+ text-vect-muted hover:text-vect-text font-medium px-3 py-2 rounded-lg transition-all duration-200
+ focus:outline-none focus:ring-2 focus:ring-vect-accent;
}
.vect-input {
- @apply bg-vect-elevated border border-vect-border text-vect-text rounded-xl px-4 py-3
- focus:outline-none focus:ring-2 focus:ring-vect-violet focus:border-vect-violet
+ @apply bg-vect-elevated border border-vect-border text-vect-text rounded-lg px-4 py-3
+ focus:outline-none focus:ring-2 focus:ring-vect-accent focus:border-vect-accent
transition-all duration-200 placeholder-vect-subtle w-full;
}
.vect-textarea {
@apply bg-vect-elevated border border-vect-border text-vect-text rounded-xl px-4 py-3
- focus:outline-none focus:ring-2 focus:ring-vect-violet focus:border-vect-violet
+ focus:outline-none focus:ring-2 focus:ring-vect-accent focus:border-vect-accent
transition-all duration-200 placeholder-vect-subtle w-full resize-none;
- min-height: 80px;
+ min-height: 52px;
max-height: 200px;
overflow-y: auto;
field-sizing: content;
}
.mode-btn {
- @apply flex items-center gap-2.5 w-full text-left px-3 py-2.5 rounded-xl text-sm font-medium
+ @apply flex items-center gap-2.5 w-full text-left px-3 py-2.5 rounded-lg text-sm font-medium
transition-all duration-150 cursor-pointer select-none;
}
.mode-btn-active {
- @apply bg-vect-violet text-white shadow-glow-violet;
+ @apply bg-vect-elevated text-vect-text;
}
.mode-btn-inactive {
@@ -102,17 +102,17 @@
}
.message-user {
- @apply self-end max-w-[85%] md:max-w-[70%] bg-gradient-to-br from-violet-700 to-vect-violet
- text-white rounded-2xl rounded-br-sm px-5 py-3 shadow-glow-violet animate-fade-in;
+ @apply self-end max-w-[85%] md:max-w-[70%] bg-vect-elevated
+ text-vect-text rounded-2xl rounded-br-sm px-5 py-3 animate-fade-in;
}
.message-ai {
- @apply self-start max-w-[85%] md:max-w-[70%] bg-vect-elevated border border-vect-border
+ @apply self-start max-w-[85%] md:max-w-[70%]
text-vect-text rounded-2xl rounded-bl-sm px-5 py-3 animate-fade-in;
}
.badge {
- @apply inline-flex items-center gap-1 text-xs font-semibold px-2 py-0.5 rounded-full;
+ @apply inline-flex items-center gap-1.5 text-xs font-medium px-2.5 py-1 rounded-md;
}
.sidebar-label {
diff --git a/examples/chat/src/types.rs b/examples/chat/src/types.rs
index bdd1d9c..1c7fd46 100644
--- a/examples/chat/src/types.rs
+++ b/examples/chat/src/types.rs
@@ -20,14 +20,14 @@ impl GenerationMode {
}
}
- pub fn icon(&self) -> &'static str {
+ pub fn icon_class(&self) -> &'static str {
match self {
- Self::Sentence => "✍️",
- Self::Paragraph => "📄",
- Self::Essay => "📖",
- Self::Summarize => "✂️",
- Self::Predict => "🔮",
- Self::Ask => "🌐",
+ Self::Sentence => "fa-solid fa-pen-nib",
+ Self::Paragraph => "fa-solid fa-align-left",
+ Self::Essay => "fa-solid fa-book-open",
+ Self::Summarize => "fa-solid fa-scissors",
+ Self::Predict => "fa-solid fa-wand-magic-sparkles",
+ Self::Ask => "fa-solid fa-globe",
}
}
@@ -44,12 +44,12 @@ impl GenerationMode {
pub fn color_class(&self) -> &'static str {
match self {
- Self::Sentence => "bg-vect-violet text-white",
- Self::Paragraph => "bg-violet-700 text-white",
- Self::Essay => "bg-violet-600 text-white",
- Self::Summarize => "bg-vect-cyan text-vect-bg",
- Self::Predict => "bg-indigo-600 text-white",
- Self::Ask => "bg-teal-600 text-white",
+ Self::Sentence => "bg-vect-elevated text-vect-text",
+ Self::Paragraph => "bg-vect-elevated text-vect-text",
+ Self::Essay => "bg-vect-elevated text-vect-text",
+ Self::Summarize => "bg-vect-elevated text-vect-text",
+ Self::Predict => "bg-vect-elevated text-vect-text",
+ Self::Ask => "bg-vect-accent/20 text-vect-accent",
}
}
diff --git a/examples/chat/tailwind.config.js b/examples/chat/tailwind.config.js
index 4b02518..3d612f4 100644
--- a/examples/chat/tailwind.config.js
+++ b/examples/chat/tailwind.config.js
@@ -5,19 +5,15 @@ module.exports = {
extend: {
colors: {
vect: {
- bg: "#07071a",
- surface: "#0d0d24",
- elevated: "#12122e",
- border: "#1e1e4a",
- violet: "#7c3aed",
- "violet-hover": "#6d28d9",
- "violet-light": "#a78bfa",
- cyan: "#06b6d4",
- "cyan-hover": "#0891b2",
- "cyan-light": "#67e8f9",
- text: "#e2e8f0",
- muted: "#94a3b8",
- subtle: "#475569",
+ bg: "#212121",
+ surface: "#171717",
+ elevated: "#2f2f2f",
+ border: "#424242",
+ accent: "#10a37f",
+ "accent-hover": "#0d8a6a",
+ text: "#ececec",
+ muted: "#b4b4b4",
+ subtle: "#6e6e6e",
},
},
fontFamily: {
@@ -25,27 +21,18 @@ module.exports = {
mono: ["JetBrains Mono", "monospace"],
},
animation: {
- "fade-in": "fadeIn 0.35s ease-out",
- "slide-up": "slideUp 0.3s ease-out",
- "pulse-glow": "pulseGlow 2s ease-in-out infinite",
+ "fade-in": "fadeIn 0.3s ease-out",
+ "slide-up": "slideUp 0.25s ease-out",
},
keyframes: {
fadeIn: {
- "0%": { opacity: "0", transform: "translateY(6px)" },
+ "0%": { opacity: "0", transform: "translateY(4px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
slideUp: {
- "0%": { opacity: "0", transform: "translateY(10px)" },
+ "0%": { opacity: "0", transform: "translateY(8px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
- pulseGlow: {
- "0%, 100%": { boxShadow: "0 0 0 0 rgba(124,58,237,0)" },
- "50%": { boxShadow: "0 0 16px 4px rgba(124,58,237,0.35)" },
- },
- },
- boxShadow: {
- "glow-violet": "0 0 24px rgba(124,58,237,0.4)",
- "glow-cyan": "0 0 24px rgba(6,182,212,0.35)",
},
},
},
diff --git a/lmm/src/imagen.rs b/lmm/src/imagen.rs
index c792ec7..adfac42 100644
--- a/lmm/src/imagen.rs
+++ b/lmm/src/imagen.rs
@@ -35,7 +35,7 @@
//! println!("Saved to {path}");
//! ```
-#![cfg_attr(target_arch = "wasm32", allow(dead_code))]
+#![cfg_attr(target_arch = "wasm32", allow(unused_imports), allow(dead_code))]
use crate::error::{LmmError, Result};
use phf::{Map, phf_map};
use strum_macros::{AsRefStr, Display, EnumIter, EnumString};