From dd85eee0804955ae00660ac5467f0faff7d40d29 Mon Sep 17 00:00:00 2001 From: Christoph Eder Date: Fri, 12 Dec 2025 16:28:10 +0100 Subject: [PATCH] Changes in embedding.py, phrase.py, symbol.py, word.py Added __get_pydantic_core_schema for serialisation to every class --- anansyTypes/structures/embedding.py | 34 +++++++++++++++++++++------- anansyTypes/structures/phrase.py | 35 +++++++++++++++++++---------- anansyTypes/structures/symbol.py | 23 ++++++++++++++++--- anansyTypes/structures/word.py | 20 +++++++++++++++++ 4 files changed, 89 insertions(+), 23 deletions(-) diff --git a/anansyTypes/structures/embedding.py b/anansyTypes/structures/embedding.py index 7eb1d20..58d78ac 100644 --- a/anansyTypes/structures/embedding.py +++ b/anansyTypes/structures/embedding.py @@ -2,20 +2,38 @@ from __future__ import annotations from dataclasses import dataclass import numpy as np from pydantic_tensor import Tensor +from pydantic_core import core_schema import torch from typing import Any, Literal + + @dataclass(frozen=True) class Embedding: - data: Tensor[torch.Tensor | np.ndarray[Any, Any],tuple, Literal["int32", "int64"]] - - - - def __post_init__(self): - if not isinstance(self.data, np.ndarray): - raise TypeError(f"data must be a numpy.ndarray, got {type(self.data)}") + data: Tensor[torch.Tensor | np.ndarray[Any, Any], tuple, Literal["int32", "int64"]] def compare(self, other: Embedding) -> float: """ Compare this embedding with another embedding. """ - raise NotImplementedError("compare method must be implemented") + if isinstance(self.data, np.ndarray) and isinstance(other.data, np.ndarray): + # Simple example: L2 distance (Euclidean distance) + return np.linalg.norm(self.data - other.data) + + # Fallback or error if not implemented for other types (e.g., torch.Tensor) + raise NotImplementedError( + "Comparison must be implemented for all supported data types." + ) + + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler): + def serialize(value: "Embedding") -> dict: + serialized_data = handler(source_type=value.data, value=value.data) + + return {"data": serialized_data} + + return core_schema.json_or_python_schema( + python_schema=handler(cls), + json_schema=core_schema.plain_serializer_function_ser_schema( + serialize, return_type=dict, when_used="json" + ), + ) diff --git a/anansyTypes/structures/phrase.py b/anansyTypes/structures/phrase.py index ea5eee4..75e58bc 100644 --- a/anansyTypes/structures/phrase.py +++ b/anansyTypes/structures/phrase.py @@ -1,8 +1,8 @@ -from typing import List +from typing import List, Any +from pydantic_core import core_schema from .lexeme import Lexeme from .embedding import Embedding -from .word import Word class Phrase(Lexeme): @@ -10,17 +10,28 @@ class Phrase(Lexeme): self.id = id self._content = content self._embedding = embedding - - @property - def content(self) -> List[str]: - return self._content + @property + def content(self) -> str: + return self._content + @property def embedding(self) -> Embedding: return self._embedding - - def __str__(self): - return self.content - - def __repr__(self): - return self.__str__() \ No newline at end of file + + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler): + def serialize(value: Phrase) -> dict: + return { + "id": value.id, + "content": value.content, + "embedding": value.embedding.data.tolist(), + } + + return core_schema.no_info_after_validator_function( + lambda x: x, + core_schema.is_instance_schema(cls), + serialization=core_schema.plain_serializer_function_ser_schema( + serialize, return_type=dict, when_used="json" + ), + ) diff --git a/anansyTypes/structures/symbol.py b/anansyTypes/structures/symbol.py index e450689..634fa9d 100644 --- a/anansyTypes/structures/symbol.py +++ b/anansyTypes/structures/symbol.py @@ -1,12 +1,29 @@ from dataclasses import dataclass -from typing import Optional +from typing import Any import numpy as np from pydantic_tensor import Tensor from typing import Any, Literal -import torch +from pydantic_core import core_schema + + @dataclass class Symbol: id: int label: str - image: Tensor[ np.ndarray[Any, Any],tuple, Literal["int32", "int64"]] + image: Tensor[np.ndarray[Any, Any], tuple, Literal["int32", "int64"]] + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler): + def serialize(value: "Symbol") -> dict: + serialized_image = handler( + source_type=value.image.__class__, value=value.image + ) + + return {"id": value.id, "label": value.label, "image": serialized_image} + + return core_schema.json_or_python_schema( + python_schema=handler(cls), + json_schema=core_schema.plain_serializer_function_ser_schema( + serialize, return_type=dict, when_used="json" + ), + ) diff --git a/anansyTypes/structures/word.py b/anansyTypes/structures/word.py index 5e4e791..341a709 100644 --- a/anansyTypes/structures/word.py +++ b/anansyTypes/structures/word.py @@ -1,5 +1,7 @@ from .lexeme import Lexeme +from typing import Any from .embedding import Embedding +from pydantic_core import core_schema class Word(Lexeme): @@ -21,3 +23,21 @@ class Word(Lexeme): def __repr__(self): return self.__str__() + + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler): + def serialize(value: 'Word') -> dict: + serialized_embedding = handler(source_type=value.embedding.__class__, value=value.embedding) + + return { + 'id': value.id, + 'content': value.content, + 'embedding': serialized_embedding + } + + return core_schema.json_or_python_schema( + python_schema=core_schema.is_instance_schema(cls), + json_schema=core_schema.plain_serializer_function_ser_schema( + serialize, return_type=dict, when_used='json' + ), + )