pyo3 update. (#2545)

* pyo3 update.

* Stub fix.
This commit is contained in:
Laurent Mazare
2024-10-06 10:09:38 +02:00
committed by GitHub
parent d2e432914e
commit f856b5c3a7
5 changed files with 22 additions and 27 deletions

View File

@ -27,7 +27,7 @@ intel-mkl-src = { workspace = true, optional = true }
num-traits = { workspace = true } num-traits = { workspace = true }
palette = { version = "0.7.6", optional = true } palette = { version = "0.7.6", optional = true }
enterpolation = { version = "0.2.1", optional = true} enterpolation = { version = "0.2.1", optional = true}
pyo3 = { version = "0.21.0", features = ["auto-initialize"], optional = true } pyo3 = { version = "0.22.0", features = ["auto-initialize"], optional = true }
rayon = { workspace = true } rayon = { workspace = true }
rubato = { version = "0.15.0", optional = true } rubato = { version = "0.15.0", optional = true }
safetensors = { workspace = true } safetensors = { workspace = true }

View File

@ -20,10 +20,10 @@ candle-nn = { workspace = true }
candle-onnx = { workspace = true, optional = true } candle-onnx = { workspace = true, optional = true }
half = { workspace = true } half = { workspace = true }
intel-mkl-src = { workspace = true, optional = true } intel-mkl-src = { workspace = true, optional = true }
pyo3 = { version = "0.21.0", features = ["extension-module", "abi3-py38"] } pyo3 = { version = "0.22.0", features = ["extension-module", "abi3-py38"] }
[build-dependencies] [build-dependencies]
pyo3-build-config = "0.21" pyo3-build-config = "0.22"
[features] [features]
default = [] default = []

View File

@ -33,9 +33,7 @@ def has_mkl() -> bool:
pass pass
@staticmethod @staticmethod
def load_ggml( def load_ggml(path, device=None) -> Tuple[Dict[str, QTensor], Dict[str, Any], List[str]]:
path: Union[str, PathLike], device: Optional[Device] = None
) -> Tuple[Dict[str, QTensor], Dict[str, Any], List[str]]:
""" """
Load a GGML file. Returns a tuple of three objects: a dictionary mapping tensor names to tensors, Load a GGML file. Returns a tuple of three objects: a dictionary mapping tensor names to tensors,
a dictionary mapping hyperparameter names to hyperparameter values, and a vocabulary. a dictionary mapping hyperparameter names to hyperparameter values, and a vocabulary.
@ -43,9 +41,7 @@ def load_ggml(
pass pass
@staticmethod @staticmethod
def load_gguf( def load_gguf(path, device=None) -> Tuple[Dict[str, QTensor], Dict[str, Any]]:
path: Union[str, PathLike], device: Optional[Device] = None
) -> Tuple[Dict[str, QTensor], Dict[str, Any]]:
""" """
Loads a GGUF file. Returns a tuple of two dictionaries: the first maps tensor names to tensors, Loads a GGUF file. Returns a tuple of two dictionaries: the first maps tensor names to tensors,
and the second maps metadata keys to metadata values. and the second maps metadata keys to metadata values.
@ -60,7 +56,7 @@ def load_safetensors(path: Union[str, PathLike]) -> Dict[str, Tensor]:
pass pass
@staticmethod @staticmethod
def save_gguf(path: Union[str, PathLike], tensors: Dict[str, QTensor], metadata: Dict[str, Any]): def save_gguf(path, tensors, metadata):
""" """
Save quanitzed tensors and metadata to a GGUF file. Save quanitzed tensors and metadata to a GGUF file.
""" """

View File

@ -6,7 +6,6 @@ use pyo3::types::{IntoPyDict, PyDict, PyTuple};
use pyo3::ToPyObject; use pyo3::ToPyObject;
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::os::raw::c_long;
use std::sync::Arc; use std::sync::Arc;
use half::{bf16, f16}; use half::{bf16, f16};
@ -115,7 +114,7 @@ impl PyDevice {
} }
impl<'source> FromPyObject<'source> for PyDevice { impl<'source> FromPyObject<'source> for PyDevice {
fn extract(ob: &'source PyAny) -> PyResult<Self> { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
let device: String = ob.extract()?; let device: String = ob.extract()?;
let device = match device.as_str() { let device = match device.as_str() {
"cpu" => PyDevice::Cpu, "cpu" => PyDevice::Cpu,
@ -217,11 +216,11 @@ enum Indexer {
IndexSelect(Tensor), IndexSelect(Tensor),
} }
#[derive(Clone, Debug)] #[derive(Debug)]
struct TorchTensor(PyObject); struct TorchTensor(PyObject);
impl<'source> pyo3::FromPyObject<'source> for TorchTensor { impl<'source> pyo3::FromPyObject<'source> for TorchTensor {
fn extract(ob: &'source PyAny) -> PyResult<Self> { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
let numpy_value: PyObject = ob.getattr("numpy")?.call0()?.extract()?; let numpy_value: PyObject = ob.getattr("numpy")?.call0()?.extract()?;
Ok(TorchTensor(numpy_value)) Ok(TorchTensor(numpy_value))
} }
@ -540,7 +539,7 @@ impl PyTensor {
)) ))
} else if let Ok(slice) = py_indexer.downcast::<pyo3::types::PySlice>() { } else if let Ok(slice) = py_indexer.downcast::<pyo3::types::PySlice>() {
// Handle a single slice e.g. tensor[0:1] or tensor[0:-1] // Handle a single slice e.g. tensor[0:1] or tensor[0:-1]
let index = slice.indices(dims[current_dim] as c_long)?; let index = slice.indices(dims[current_dim] as isize)?;
Ok(( Ok((
Indexer::Slice(index.start as usize, index.stop as usize), Indexer::Slice(index.start as usize, index.stop as usize),
current_dim + 1, current_dim + 1,
@ -1284,7 +1283,7 @@ fn save_safetensors(
} }
#[pyfunction] #[pyfunction]
#[pyo3(text_signature = "(path:Union[str,PathLike], device: Optional[Device] = None)")] #[pyo3(signature = (path, device = None))]
/// Load a GGML file. Returns a tuple of three objects: a dictionary mapping tensor names to tensors, /// Load a GGML file. Returns a tuple of three objects: a dictionary mapping tensor names to tensors,
/// a dictionary mapping hyperparameter names to hyperparameter values, and a vocabulary. /// a dictionary mapping hyperparameter names to hyperparameter values, and a vocabulary.
/// &RETURNS&: Tuple[Dict[str,QTensor], Dict[str,Any], List[str]] /// &RETURNS&: Tuple[Dict[str,QTensor], Dict[str,Any], List[str]]
@ -1325,7 +1324,7 @@ fn load_ggml(
} }
#[pyfunction] #[pyfunction]
#[pyo3(text_signature = "(path:Union[str,PathLike], device: Optional[Device] = None)")] #[pyo3(signature = (path, device = None))]
/// Loads a GGUF file. Returns a tuple of two dictionaries: the first maps tensor names to tensors, /// Loads a GGUF file. Returns a tuple of two dictionaries: the first maps tensor names to tensors,
/// and the second maps metadata keys to metadata values. /// and the second maps metadata keys to metadata values.
/// &RETURNS&: Tuple[Dict[str,QTensor], Dict[str,Any]] /// &RETURNS&: Tuple[Dict[str,QTensor], Dict[str,Any]]
@ -1384,7 +1383,7 @@ fn load_gguf(
#[pyfunction] #[pyfunction]
#[pyo3( #[pyo3(
text_signature = "(path:Union[str,PathLike], tensors:Dict[str,QTensor], metadata:Dict[str,Any])" signature = (path, tensors, metadata)
)] )]
/// Save quanitzed tensors and metadata to a GGUF file. /// Save quanitzed tensors and metadata to a GGUF file.
fn save_gguf(path: &str, tensors: PyObject, metadata: PyObject, py: Python<'_>) -> PyResult<()> { fn save_gguf(path: &str, tensors: PyObject, metadata: PyObject, py: Python<'_>) -> PyResult<()> {
@ -1430,7 +1429,7 @@ fn save_gguf(path: &str, tensors: PyObject, metadata: PyObject, py: Python<'_>)
Ok(v) Ok(v)
} }
let tensors = tensors let tensors = tensors
.extract::<&PyDict>(py) .downcast_bound::<PyDict>(py)
.map_err(|_| PyErr::new::<PyValueError, _>("expected a dict"))? .map_err(|_| PyErr::new::<PyValueError, _>("expected a dict"))?
.iter() .iter()
.map(|(key, value)| { .map(|(key, value)| {
@ -1443,7 +1442,7 @@ fn save_gguf(path: &str, tensors: PyObject, metadata: PyObject, py: Python<'_>)
.collect::<PyResult<Vec<_>>>()?; .collect::<PyResult<Vec<_>>>()?;
let metadata = metadata let metadata = metadata
.extract::<&PyDict>(py) .downcast_bound::<PyDict>(py)
.map_err(|_| PyErr::new::<PyValueError, _>("expected a dict"))? .map_err(|_| PyErr::new::<PyValueError, _>("expected a dict"))?
.iter() .iter()
.map(|(key, value)| { .map(|(key, value)| {

View File

@ -6,7 +6,7 @@ use pyo3::prelude::*;
pub struct PyShape(Vec<usize>); pub struct PyShape(Vec<usize>);
impl<'source> pyo3::FromPyObject<'source> for PyShape { impl<'source> pyo3::FromPyObject<'source> for PyShape {
fn extract(ob: &'source PyAny) -> PyResult<Self> { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
if ob.is_none() { if ob.is_none() {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"Shape cannot be None", "Shape cannot be None",
@ -16,10 +16,10 @@ impl<'source> pyo3::FromPyObject<'source> for PyShape {
let tuple = ob.downcast::<pyo3::types::PyTuple>()?; let tuple = ob.downcast::<pyo3::types::PyTuple>()?;
if tuple.len() == 1 { if tuple.len() == 1 {
let first_element = tuple.get_item(0)?; let first_element = tuple.get_item(0)?;
let dims: Vec<usize> = pyo3::FromPyObject::extract(first_element)?; let dims: Vec<usize> = pyo3::FromPyObject::extract_bound(&first_element)?;
Ok(PyShape(dims)) Ok(PyShape(dims))
} else { } else {
let dims: Vec<usize> = pyo3::FromPyObject::extract(tuple)?; let dims: Vec<usize> = pyo3::FromPyObject::extract_bound(tuple)?;
Ok(PyShape(dims)) Ok(PyShape(dims))
} }
} }
@ -36,7 +36,7 @@ impl From<PyShape> for ::candle::Shape {
pub struct PyShapeWithHole(Vec<isize>); pub struct PyShapeWithHole(Vec<isize>);
impl<'source> pyo3::FromPyObject<'source> for PyShapeWithHole { impl<'source> pyo3::FromPyObject<'source> for PyShapeWithHole {
fn extract(ob: &'source PyAny) -> PyResult<Self> { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
if ob.is_none() { if ob.is_none() {
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
"Shape cannot be None", "Shape cannot be None",
@ -46,9 +46,9 @@ impl<'source> pyo3::FromPyObject<'source> for PyShapeWithHole {
let tuple = ob.downcast::<pyo3::types::PyTuple>()?; let tuple = ob.downcast::<pyo3::types::PyTuple>()?;
let dims: Vec<isize> = if tuple.len() == 1 { let dims: Vec<isize> = if tuple.len() == 1 {
let first_element = tuple.get_item(0)?; let first_element = tuple.get_item(0)?;
pyo3::FromPyObject::extract(first_element)? pyo3::FromPyObject::extract_bound(&first_element)?
} else { } else {
pyo3::FromPyObject::extract(tuple)? pyo3::FromPyObject::extract_bound(tuple)?
}; };
// Ensure we have only positive numbers and at most one "hole" (-1) // Ensure we have only positive numbers and at most one "hole" (-1)