///|
/// A Chroma collection as returned by the server.
pub(all) struct Collection {
id : String
name : String
metadata : Metadata
configuration : Json
log_position : Int32
version : Int32
} derive(Eq, Debug)
///|
/// Decodes a collection from a server response object.
///
/// `id` and `name` are required: a response without them is not a
/// collection, and silently defaulting a name to `""` would only push the
/// failure further down the line. The remaining fields are optional and
/// default to empty so that responses from older servers still decode.
pub fn Collection::from_json(json : Json) -> Collection raise ChromaError {
let log_position = with_default(optional_int(json, "log_position"), 0)
let version = with_default(optional_int(json, "version"), 0)
{
id: required_string(json, "id"),
name: required_string(json, "name"),
metadata: metadata_from_json(optional_object(json, "metadata")),
configuration: optional_object(json, "configuration"),
log_position,
version,
}
}
///|
fn with_default(value : Int32?, fallback : Int32) -> Int32 {
match value {
Some(v) => v
None => fallback
}
}
///|
/// Reads an optional integer field.
fn optional_int(json : Json, key : String) -> Int32? {
match json {
Json::Object(fields) =>
match fields.get(key) {
Some(Json::Number(n, ..)) => Some(n.to_int())
_ => None
}
_ => None
}
}
///|
/// Parameters for `get_or_create_collection` and `create_collection`.
///
/// `configuration` is sent verbatim, so index options the server knows about
/// (for example `{"hnsw": {"space": "cosine"}}`) can be set without waiting
/// for this client to model them. When it is unset a default L2 HNSW
/// configuration is sent.
pub(all) struct CollectionConfig {
metadata : Metadata
configuration : Json?
} derive(Eq, Debug)
///|
/// Builds a `CollectionConfig` with all options unset.
pub fn CollectionConfig::new(
metadata~ : Metadata = [],
configuration~ : Json? = None,
) -> CollectionConfig {
{ metadata, configuration, }
}
///|
/// Builds the request body for creating a collection.
///
/// Chroma's `CreateCollection` model takes `name`, `configuration`,
/// `metadata` and `get_or_create`. There is no top-level
/// `embedding_function` field: a collection's embedding function is
/// configured through `configuration`, so `CollectionConfig`'s name is not
/// sent on its own.
fn create_body(
name : String,
config : CollectionConfig,
get_or_create~ : Bool,
) -> Json {
let body : Map[String, Json] = Map([])
body["name"] = Json::string(name)
body["get_or_create"] = Json::boolean(get_or_create)
match config.configuration {
Some(configuration) => body["configuration"] = configuration
None => {
let hnsw : Map[String, Json] = Map([])
hnsw["space"] = Json::string("l2")
body["configuration"] = Json::object({ "hnsw": Json::object(hnsw) })
}
}
if config.metadata.length() > 0 {
body["metadata"] = metadata_to_json(config.metadata)
}
Json::object(body)
}
///|
pub extend Collection with Eq::{not_equal, equal}
///|
pub extend Collection with @debug.Debug::{to_repr}
///|
pub extend CollectionConfig with Eq::{not_equal, equal}
///|
pub extend CollectionConfig with @debug.Debug::{to_repr}
///|
/// Serializes a collection configuration, useful for logging and for
/// building custom requests.
///
/// Same value as `CollectionConfig::to_json`; the name is kept because the
/// logging use case reads better with it.
pub fn debug_collection_config(config : CollectionConfig) -> Json {
config.to_json()
}
///|
/// Serializes the collection configuration for a create request.
///
/// This is the body `create_collection` sends, with `get_or_create` set to
/// `false`.
pub fn CollectionConfig::to_json(config : CollectionConfig) -> Json {
create_body("", config, get_or_create=false)
}