You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In {{ 05-many-futures pr }}, your colleague modified the Chatbot API to support retrieval-augmented generation (RAG), a cutting-edge chatbot technique. To use RAG, when a user provides a set of input messages, you should first call Chatbot::retrieval_documents to generate a set of paths to documents that the model thinks are relevant to the query. Then you should read those files from disk, and pass their contents in the new docs parameter of Chatbot::query_chat.
Performance
All documents should be retrieved from disk in parallel. No additional tasks should be spawned.
Background
Async I/O
Rust's standard I/O functions like std::fs::read_to_string are blocking, meaning they do not have optimal performance when used with async. Therefore, async libraries like Tokio provide utilities for asynchronous I/O such as the tokio::fs module. For example, you can read a file to a string using tokio::fs::read_to_string like this:
let contents = tokio::fs::read_to_string("some_file.txt").await.unwrap();
Note that at the time of writing, Tokio's async I/O is a simple wrapper over std::fs that launches I/O on a new thread to avoid blocking. See the tokio::fs module documentation for details.
Async closures
Unlike top-level functions, Rust does not yet have a dedicated syntax for using async in a closure. Instead, you can use async block syntax like this:
asyncfnincr(n:usize) -> usize{ n + 1}asyncfncompute(){let f = |i:usize| asyncmove{incr(i).await};let n = f(1).await;println!("1 + 1 = {n}");}
Waiting on many futures
As discussed in {{ 02-join issue }}, if you need to wait on many futures, it's bad practice to .await in a sequence, and you should prefer to join! the futures instead. join! works well for a fixed number of futures, but you need different primitives for a variable number of futures.
There are a few different approaches depending on your goal. The most straightforward is to use a function like futures::future::join_all in the futures utility crate. For example:
Task
Functionality
In {{ 05-many-futures pr }}, your colleague modified the
Chatbot
API to support retrieval-augmented generation (RAG), a cutting-edge chatbot technique. To use RAG, when a user provides a set of input messages, you should first callChatbot::retrieval_documents
to generate a set of paths to documents that the model thinks are relevant to the query. Then you should read those files from disk, and pass their contents in the newdocs
parameter ofChatbot::query_chat
.Performance
All documents should be retrieved from disk in parallel. No additional tasks should be spawned.
Background
Async I/O
Rust's standard I/O functions like
std::fs::read_to_string
are blocking, meaning they do not have optimal performance when used with async. Therefore, async libraries like Tokio provide utilities for asynchronous I/O such as thetokio::fs
module. For example, you can read a file to a string usingtokio::fs::read_to_string
like this:Note that at the time of writing, Tokio's async I/O is a simple wrapper over
std::fs
that launches I/O on a new thread to avoid blocking. See thetokio::fs
module documentation for details.Async closures
Unlike top-level functions, Rust does not yet have a dedicated syntax for using
async
in a closure. Instead, you can use async block syntax like this:Waiting on many futures
As discussed in {{ 02-join issue }}, if you need to wait on many futures, it's bad practice to
.await
in a sequence, and you should prefer tojoin!
the futures instead.join!
works well for a fixed number of futures, but you need different primitives for a variable number of futures.There are a few different approaches depending on your goal. The most straightforward is to use a function like
futures::future::join_all
in thefutures
utility crate. For example:Tokio provides a more complex data structure for this purpose, the
JoinSet
. For example:JoinSet
is useful if you need more advanced capabilities like aborting tasks (which we will discuss further in a later chapter).The text was updated successfully, but these errors were encountered: