combs_formats/lib.rs
1//! # combs-formats
2//!
3//! File-format adapter layer. The runtime and model crates never touch file
4//! formats directly; they go through the [`ModelSource`] trait (the
5//! LiteRT-LM `ModelResources` equivalent). Phase 1 ships the
6//! [`safetensors`] adapter (HuggingFace `config.json` + `model.safetensors`,
7//! mmap-backed, zero-copy views). GGUF / ONNX / litertlm adapters plug in
8//! here later by implementing the same trait.
9
10mod gguf;
11mod metadata;
12mod safetensors;
13mod source;
14mod tokenizer;
15
16pub use gguf::GgufSource;
17pub use metadata::{ModelMetadata, VisionConfig};
18pub use safetensors::SafetensorsSource;
19pub use source::{ModelSource, SamplerConfig, TensorDtype, TensorReader};
20pub use tokenizer::TokenizerSpec;
21
22use std::path::Path;
23
24/// Opens any supported model path: a `.gguf` file, or a directory in the
25/// HuggingFace safetensors layout. This is the single entry point the CLI,
26/// FFI and server use — format detection lives here.
27pub fn open_model_source(path: impl AsRef<Path>) -> Result<Box<dyn ModelSource>> {
28 let path = path.as_ref();
29 if path.is_file() && path.extension().is_some_and(|e| e == "gguf") {
30 return Ok(Box::new(GgufSource::load(path)?));
31 }
32 if path.is_dir() {
33 return Ok(Box::new(SafetensorsSource::load(path)?));
34 }
35 Err(FormatError::MissingFile(path.display().to_string()))
36}
37
38/// Errors produced by format adapters.
39#[derive(Debug, thiserror::Error)]
40pub enum FormatError {
41 /// An I/O error while reading model files.
42 #[error("io error: {0}")]
43 Io(#[from] std::io::Error),
44
45 /// A JSON parse error (config.json, generation_config.json, …).
46 #[error("json error in {context}: {source}")]
47 Json {
48 /// Which file/section failed to parse.
49 context: String,
50 /// The underlying serde error.
51 source: serde_json::Error,
52 },
53
54 /// The safetensors container is malformed.
55 #[error("safetensors error: {0}")]
56 Safetensors(String),
57
58 /// A requested tensor does not exist in the source.
59 #[error("tensor not found: {0}")]
60 TensorNotFound(String),
61
62 /// A tensor has an unsupported dtype for this build.
63 #[error("unsupported dtype for tensor {tensor}: {dtype}")]
64 UnsupportedDtype {
65 /// Tensor name.
66 tensor: String,
67 /// Dtype string from the container.
68 dtype: String,
69 },
70
71 /// The model directory is missing a required file.
72 #[error("missing file: {0}")]
73 MissingFile(String),
74
75 /// The config is missing a required field.
76 #[error("missing config field: {0}")]
77 MissingField(String),
78}
79
80/// Convenient result alias for this crate.
81pub type Result<T> = std::result::Result<T, FormatError>;