2022-10-18 13:19:03 +00:00
|
|
|
//! Text Generation gRPC client library
|
2022-10-08 10:30:12 +00:00
|
|
|
|
|
|
|
mod client;
|
2022-10-18 13:19:03 +00:00
|
|
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
2022-10-08 10:30:12 +00:00
|
|
|
mod pb;
|
|
|
|
mod sharded_client;
|
|
|
|
|
2024-06-03 07:27:22 +00:00
|
|
|
use base64::{engine::general_purpose::STANDARD, Engine};
|
2022-10-08 10:30:12 +00:00
|
|
|
pub use client::Client;
|
2024-06-03 07:27:22 +00:00
|
|
|
pub use pb::generate::v2::input_chunk::Chunk;
|
2023-12-11 11:46:30 +00:00
|
|
|
pub use pb::generate::v2::HealthResponse;
|
2024-06-03 07:27:22 +00:00
|
|
|
pub use pb::generate::v2::Image;
|
2023-12-11 11:46:30 +00:00
|
|
|
pub use pb::generate::v2::InfoResponse as ShardInfo;
|
|
|
|
pub use pb::generate::v2::{
|
2024-06-03 07:27:22 +00:00
|
|
|
Batch, CachedBatch, FinishReason, GeneratedText, Generation, GrammarType, Input, InputChunk,
|
2024-02-15 09:28:10 +00:00
|
|
|
NextTokenChooserParameters, Request, StoppingCriteriaParameters, Tokens,
|
2022-12-12 17:25:22 +00:00
|
|
|
};
|
2022-10-08 10:30:12 +00:00
|
|
|
pub use sharded_client::ShardedClient;
|
|
|
|
use thiserror::Error;
|
2022-10-18 13:19:03 +00:00
|
|
|
use tonic::transport;
|
2022-10-08 10:30:12 +00:00
|
|
|
use tonic::Status;
|
|
|
|
|
|
|
|
#[derive(Error, Debug, Clone)]
|
2022-10-17 12:59:00 +00:00
|
|
|
pub enum ClientError {
|
2023-02-13 12:02:45 +00:00
|
|
|
#[error("Could not connect to Text Generation server: {0}")]
|
2022-10-17 12:59:00 +00:00
|
|
|
Connection(String),
|
2023-02-13 12:02:45 +00:00
|
|
|
#[error("Server error: {0}")]
|
2022-10-17 12:59:00 +00:00
|
|
|
Generation(String),
|
2023-05-10 13:48:21 +00:00
|
|
|
#[error("Sharded results are empty")]
|
|
|
|
EmptyResults,
|
2022-10-08 10:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Status> for ClientError {
|
|
|
|
fn from(err: Status) -> Self {
|
2023-02-13 12:02:45 +00:00
|
|
|
let err = Self::Generation(err.message().to_string());
|
|
|
|
tracing::error!("{err}");
|
|
|
|
err
|
2022-10-17 12:59:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<transport::Error> for ClientError {
|
|
|
|
fn from(err: transport::Error) -> Self {
|
2023-02-13 12:02:45 +00:00
|
|
|
let err = Self::Connection(err.to_string());
|
|
|
|
tracing::error!("{err}");
|
|
|
|
err
|
2022-10-08 10:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type Result<T> = std::result::Result<T, ClientError>;
|
2024-06-03 07:27:22 +00:00
|
|
|
|
|
|
|
// Small convenience re-wrapping of `Chunk`.
|
|
|
|
impl From<Chunk> for InputChunk {
|
|
|
|
fn from(chunk: Chunk) -> Self {
|
|
|
|
InputChunk { chunk: Some(chunk) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert input chunks to a stringly-typed input for backwards
|
|
|
|
/// compat for backends that haven't implemented chunked inputs.
|
|
|
|
pub trait ChunksToString {
|
|
|
|
/// Convert chunks to string.
|
|
|
|
fn chunks_to_string(&self) -> String;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ChunksToString for Vec<InputChunk> {
|
|
|
|
fn chunks_to_string(&self) -> String {
|
|
|
|
let mut output = String::new();
|
|
|
|
self.iter().for_each(|c| match &c.chunk {
|
|
|
|
Some(Chunk::Text(text)) => output.push_str(text),
|
|
|
|
Some(Chunk::Image(Image { data, mimetype })) => {
|
|
|
|
let encoded = STANDARD.encode(data);
|
|
|
|
output.push_str(&format!("", mimetype, encoded))
|
|
|
|
}
|
|
|
|
// We don't create empty chunks, so this should be unreachable.
|
|
|
|
None => unreachable!("Chunks should never be empty"),
|
|
|
|
});
|
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|