We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Expose Timeout Parameters in weaviate
Weaviate storage currently does not allow specifying the Timeout parameters.
Add the parameter to `WeaviateConfig` and used when creating the weaviate client

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docarray/array/storage/weaviate/backend.py`
Content:
```
1 import uuid
2 from dataclasses import dataclass, field
3 from typing import (
4     Iterable,
5     Dict,
6     Optional,
7     TYPE_CHECKING,
8     Union,
9     Tuple,
10     List,
11 )
12 
13 import numpy as np
14 import weaviate
15 
16 from ..base.backend import BaseBackendMixin
17 from ..registry import _REGISTRY
18 from .... import Document
19 from ....helper import dataclass_from_dict, filter_dict
20 
21 if TYPE_CHECKING:
22     from ....typing import DocumentArraySourceType, ArrayType
23 
24 
25 @dataclass
26 class WeaviateConfig:
27     """This class stores the config variables to initialize
28     connection to the Weaviate server"""
29 
30     host: Optional[str] = field(default='localhost')
31     port: Optional[int] = field(default=8080)
32     protocol: Optional[str] = field(default='http')
33     name: Optional[str] = None
34     serialize_config: Dict = field(default_factory=dict)
35     n_dim: Optional[int] = None  # deprecated, not used anymore since weaviate 1.10
36     ef: Optional[int] = None
37     ef_construction: Optional[int] = None
38     max_connections: Optional[int] = None
39 
40 
41 class BackendMixin(BaseBackendMixin):
42     """Provide necessary functions to enable this storage backend."""
43 
44     def _init_storage(
45         self,
46         _docs: Optional['DocumentArraySourceType'] = None,
47         config: Optional[Union[WeaviateConfig, Dict]] = None,
48         **kwargs,
49     ):
50         """Initialize weaviate storage.
51 
52         :param docs: the list of documents to initialize to
53         :param config: the config object used to ininitialize connection to weaviate server
54         :param kwargs: extra keyword arguments
55         :raises ValueError: only one of name or docs can be used for initialization,
56             raise an error if both are provided
57         """
58 
59         if not config:
60             config = WeaviateConfig()
61         elif isinstance(config, dict):
62             config = dataclass_from_dict(WeaviateConfig, config)
63 
64         self._serialize_config = config.serialize_config
65 
66         if config.name and config.name != config.name.capitalize():
67             raise ValueError(
68                 'Weaviate class name has to be capitalized. '
69                 'Please capitalize when declaring the name field in config.'
70             )
71 
72         self._persist = bool(config.name)
73 
74         self._client = weaviate.Client(
75             f'{config.protocol}://{config.host}:{config.port}'
76         )
77         self._config = config
78 
79         self._schemas = self._load_or_create_weaviate_schema()
80 
81         _REGISTRY[self.__class__.__name__][self._class_name].append(self)
82 
83         super()._init_storage(_docs, **kwargs)
84 
85         # To align with Sqlite behavior; if `docs` is not `None` and table name
86         # is provided, :class:`DocumentArraySqlite` will clear the existing
87         # table and load the given `docs`
88         if _docs is None:
89             return
90         elif isinstance(_docs, Iterable):
91             self.clear()
92             self.extend(_docs)
93         else:
94             self.clear()
95             if isinstance(_docs, Document):
96                 self.append(_docs)
97 
98     def _get_weaviate_class_name(self) -> str:
99         """Generate the class/schema name using the ``uuid1`` module with some
100         formatting to tailor to weaviate class name convention
101 
102         :return: string representing the name of  weaviate class/schema name of
103             this :class:`DocumentArrayWeaviate` object
104         """
105         return ''.join([i for i in uuid.uuid1().hex if not i.isdigit()]).capitalize()
106 
107     def _get_schema_by_name(self, cls_name: str) -> Dict:
108         """Return the schema dictionary object with the class name
109         Content of the all dictionaries by this method are the same except the name
110         of the weaviate's ``class``
111 
112         :param cls_name: the name of the schema/class in weaviate
113         :return: the schema dictionary
114         """
115         # TODO: ideally we should only use one schema. this will allow us to deal with
116         # consistency better
117         hnsw_config = {
118             'ef': self._config.ef,
119             'efConstruction': self._config.ef_construction,
120             'maxConnections': self._config.max_connections,
121         }
122 
123         return {
124             'classes': [
125                 {
126                     'class': cls_name,
127                     "vectorizer": "none",
128                     'vectorIndexConfig': {'skip': False},
129                     'properties': [
130                         {
131                             'dataType': ['blob'],
132                             'name': '_serialized',
133                             'indexInverted': False,
134                         },
135                     ],
136                 },
137                 {
138                     'class': cls_name + 'Meta',
139                     "vectorizer": "none",
140                     'vectorIndexConfig': {'skip': True, **filter_dict(hnsw_config)},
141                     'properties': [
142                         {
143                             'dataType': ['string[]'],
144                             'name': '_offset2ids',
145                             'indexInverted': False,
146                         },
147                     ],
148                 },
149             ]
150         }
151 
152     def _load_or_create_weaviate_schema(self):
153         """Create a new weaviate schema for this :class:`DocumentArrayWeaviate` object
154         if not present in weaviate or if ``self._config.name`` is None. If ``self._config.name``
155         is provided and not None and schema with the specified name exists in weaviate,
156         then load the object with the given ``self._config.name``
157 
158         :return: the schemas of this :class`DocumentArrayWeaviate` object and its meta
159         """
160         if not self._config.name:
161             name_candidate = self._get_weaviate_class_name()
162             doc_schemas = self._get_schema_by_name(name_candidate)
163             while self._client.schema.contains(doc_schemas):
164                 name_candidate = self._get_weaviate_class_name()
165                 doc_schemas = self._get_schema_by_name(name_candidate)
166             self._client.schema.create(doc_schemas)
167             self._config.name = name_candidate
168             return doc_schemas
169 
170         doc_schemas = self._get_schema_by_name(self._config.name)
171         if self._client.schema.contains(doc_schemas):
172             return doc_schemas
173 
174         self._client.schema.create(doc_schemas)
175         return doc_schemas
176 
177     def _update_offset2ids_meta(self):
178         """Update the offset2ids in weaviate the the current local version"""
179         if self._offset2ids_wid is not None and self._client.data_object.exists(
180             self._offset2ids_wid
181         ):
182             self._client.data_object.update(
183                 data_object={'_offset2ids': self._offset2ids.ids},
184                 class_name=self._meta_name,
185                 uuid=self._offset2ids_wid,
186             )
187         else:
188             self._offset2ids_wid = str(uuid.uuid1())
189             self._client.data_object.create(
190                 data_object={'_offset2ids': self._offset2ids.ids},
191                 class_name=self._meta_name,
192                 uuid=self._offset2ids_wid,
193             )
194 
195     def _get_offset2ids_meta(self) -> Tuple[List, str]:
196         """Return the offset2ids stored in weaviate along with the name of the schema/class
197         in weaviate that stores meta information of this object
198 
199         :return: a tuple with first element as a list of offset2ids and second element
200                  being name of weaviate class/schema of the meta object
201 
202         :raises ValueError: error is raised if meta class name is not defined
203         """
204         if not self._meta_name:
205             raise ValueError('meta object is not defined')
206 
207         resp = (
208             self._client.query.get(self._meta_name, ['_offset2ids', '_additional {id}'])
209             .do()
210             .get('data', {})
211             .get('Get', {})
212             .get(self._meta_name, [])
213         )
214 
215         if not resp:
216             return [], None
217         elif len(resp) == 1:
218             return resp[0]['_offset2ids'], resp[0]['_additional']['id']
219         else:
220             raise ValueError('received multiple meta copies which is invalid')
221 
222     @property
223     def name(self):
224         """An alias to _class_name that returns the id/name of the class
225         in the weaviate of this :class:`DocumentArrayWeaviate`
226 
227         :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`
228         """
229         return self._class_name
230 
231     @property
232     def _class_name(self):
233         """Return the name of the class in weaviate of this :class:`DocumentArrayWeaviate
234 
235         :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`
236         """
237         if not self._schemas:
238             return None
239         return self._schemas['classes'][0]['class']
240 
241     @property
242     def _meta_name(self):
243         """Return the name of the class in weaviate that stores the meta information of
244         this :class:`DocumentArrayWeaviate`
245 
246         :return: name of weaviate class/schema of class that stores the meta information
247         """
248         # TODO: remove this after we combine the meta info to the DocumentArray class
249         if not self._schemas:
250             return None
251         return self._schemas['classes'][1]['class']
252 
253     @property
254     def _class_schema(self) -> Optional[Dict]:
255         """Return the schema dictionary of this :class:`DocumentArrayWeaviate`'s weaviate schema
256 
257         :return: the dictionary representing this weaviate schema
258         """
259         if not self._schemas:
260             return None
261         return self._schemas['classes'][0]
262 
263     @property
264     def _meta_schema(self):
265         """Return the schema dictionary of this weaviate schema that stores this object's meta
266 
267         :return: the dictionary representing a meta object's weaviate schema
268         """
269         if not self._schemas and len(self._schemas) < 2:
270             return None
271         return self._schemas['classes'][1]
272 
273     def _doc2weaviate_create_payload(self, value: 'Document'):
274         """Return the payload to store :class:`Document` into weaviate
275 
276         :param value: document to create a payload for
277         :return: the payload dictionary
278         """
279         return dict(
280             data_object={'_serialized': value.to_base64(**self._serialize_config)},
281             class_name=self._class_name,
282             uuid=self._map_id(value.id),
283             vector=self._map_embedding(value.embedding),
284         )
285 
286     def _map_id(self, doc_id: str):
287         """the function maps doc id to weaviate id
288 
289         :param doc_id: id of the document
290         :return: weaviate object id
291         """
292         # appending class name to doc id to handle the case:
293         # daw1 = DocumentArrayWeaviate([Document(id=str(i), text='hi') for i in range(3)])
294         # daw2 = DocumentArrayWeaviate([Document(id=str(i), text='bye') for i in range(3)])
295         # daw2[0, 'text'] == 'hi' # this will be False if we don't append class name
296         return str(uuid.uuid5(uuid.NAMESPACE_URL, doc_id + self._class_name))
297 
298     def _map_embedding(self, embedding: 'ArrayType'):
299         if embedding is not None:
300             from ....math.ndarray import to_numpy_array
301 
302             embedding = to_numpy_array(embedding)
303 
304             if embedding.ndim > 1:
305                 embedding = np.asarray(embedding).squeeze()
306 
307             # Weaviate expects vector to have dim 2 at least
308             # or get weaviate.exceptions.UnexpectedStatusCodeException:  models.C11yVector
309             # hence we cast it to list of a single element
310             if len(embedding) == 1:
311                 embedding = [embedding[0]]
312         else:
313             embedding = None
314         return embedding
315 
316     def __getstate__(self):
317         d = dict(self.__dict__)
318         del d['_client']
319         return d
320 
321     def __setstate__(self, state):
322         self.__dict__ = state
323         self._client = weaviate.Client(
324             f'{state["_config"].protocol}://{state["_config"].host}:{state["_config"].port}'
325         )
326
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docarray/array/storage/weaviate/backend.py b/docarray/array/storage/weaviate/backend.py
--- a/docarray/array/storage/weaviate/backend.py
+++ b/docarray/array/storage/weaviate/backend.py
@@ -13,13 +13,13 @@
 import numpy as np
 import weaviate
 
-from ..base.backend import BaseBackendMixin
-from ..registry import _REGISTRY
 from .... import Document
 from ....helper import dataclass_from_dict, filter_dict
+from ..base.backend import BaseBackendMixin
+from ..registry import _REGISTRY
 
 if TYPE_CHECKING:
-    from ....typing import DocumentArraySourceType, ArrayType
+    from ....typing import ArrayType, DocumentArraySourceType
 
 
 @dataclass
@@ -35,6 +35,7 @@
     n_dim: Optional[int] = None  # deprecated, not used anymore since weaviate 1.10
     ef: Optional[int] = None
     ef_construction: Optional[int] = None
+    timeout_config: Optional[Tuple[int, int]] = None
     max_connections: Optional[int] = None
 
 
@@ -72,7 +73,8 @@
         self._persist = bool(config.name)
 
         self._client = weaviate.Client(
-            f'{config.protocol}://{config.host}:{config.port}'
+            f'{config.protocol}://{config.host}:{config.port}',
+            timeout_config=config.timeout_config,
         )
         self._config = config

{"golden_diff": "diff --git a/docarray/array/storage/weaviate/backend.py b/docarray/array/storage/weaviate/backend.py\n--- a/docarray/array/storage/weaviate/backend.py\n+++ b/docarray/array/storage/weaviate/backend.py\n@@ -13,13 +13,13 @@\n import numpy as np\n import weaviate\n \n-from ..base.backend import BaseBackendMixin\n-from ..registry import _REGISTRY\n from .... import Document\n from ....helper import dataclass_from_dict, filter_dict\n+from ..base.backend import BaseBackendMixin\n+from ..registry import _REGISTRY\n \n if TYPE_CHECKING:\n-    from ....typing import DocumentArraySourceType, ArrayType\n+    from ....typing import ArrayType, DocumentArraySourceType\n \n \n @dataclass\n@@ -35,6 +35,7 @@\n     n_dim: Optional[int] = None  # deprecated, not used anymore since weaviate 1.10\n     ef: Optional[int] = None\n     ef_construction: Optional[int] = None\n+    timeout_config: Optional[Tuple[int, int]] = None\n     max_connections: Optional[int] = None\n \n \n@@ -72,7 +73,8 @@\n         self._persist = bool(config.name)\n \n         self._client = weaviate.Client(\n-            f'{config.protocol}://{config.host}:{config.port}'\n+            f'{config.protocol}://{config.host}:{config.port}',\n+            timeout_config=config.timeout_config,\n         )\n         self._config = config\n", "issue": "Expose Timeout Parameters in weaviate\nWeaviate storage currently does not allow specifying the Timeout parameters.\r\nAdd the parameter to `WeaviateConfig` and used when creating the weaviate client\n", "before_files": [{"content": "import uuid\nfrom dataclasses import dataclass, field\nfrom typing import (\n    Iterable,\n    Dict,\n    Optional,\n    TYPE_CHECKING,\n    Union,\n    Tuple,\n    List,\n)\n\nimport numpy as np\nimport weaviate\n\nfrom ..base.backend import BaseBackendMixin\nfrom ..registry import _REGISTRY\nfrom .... import Document\nfrom ....helper import dataclass_from_dict, filter_dict\n\nif TYPE_CHECKING:\n    from ....typing import DocumentArraySourceType, ArrayType\n\n\n@dataclass\nclass WeaviateConfig:\n    \"\"\"This class stores the config variables to initialize\n    connection to the Weaviate server\"\"\"\n\n    host: Optional[str] = field(default='localhost')\n    port: Optional[int] = field(default=8080)\n    protocol: Optional[str] = field(default='http')\n    name: Optional[str] = None\n    serialize_config: Dict = field(default_factory=dict)\n    n_dim: Optional[int] = None  # deprecated, not used anymore since weaviate 1.10\n    ef: Optional[int] = None\n    ef_construction: Optional[int] = None\n    max_connections: Optional[int] = None\n\n\nclass BackendMixin(BaseBackendMixin):\n    \"\"\"Provide necessary functions to enable this storage backend.\"\"\"\n\n    def _init_storage(\n        self,\n        _docs: Optional['DocumentArraySourceType'] = None,\n        config: Optional[Union[WeaviateConfig, Dict]] = None,\n        **kwargs,\n    ):\n        \"\"\"Initialize weaviate storage.\n\n        :param docs: the list of documents to initialize to\n        :param config: the config object used to ininitialize connection to weaviate server\n        :param kwargs: extra keyword arguments\n        :raises ValueError: only one of name or docs can be used for initialization,\n            raise an error if both are provided\n        \"\"\"\n\n        if not config:\n            config = WeaviateConfig()\n        elif isinstance(config, dict):\n            config = dataclass_from_dict(WeaviateConfig, config)\n\n        self._serialize_config = config.serialize_config\n\n        if config.name and config.name != config.name.capitalize():\n            raise ValueError(\n                'Weaviate class name has to be capitalized. '\n                'Please capitalize when declaring the name field in config.'\n            )\n\n        self._persist = bool(config.name)\n\n        self._client = weaviate.Client(\n            f'{config.protocol}://{config.host}:{config.port}'\n        )\n        self._config = config\n\n        self._schemas = self._load_or_create_weaviate_schema()\n\n        _REGISTRY[self.__class__.__name__][self._class_name].append(self)\n\n        super()._init_storage(_docs, **kwargs)\n\n        # To align with Sqlite behavior; if `docs` is not `None` and table name\n        # is provided, :class:`DocumentArraySqlite` will clear the existing\n        # table and load the given `docs`\n        if _docs is None:\n            return\n        elif isinstance(_docs, Iterable):\n            self.clear()\n            self.extend(_docs)\n        else:\n            self.clear()\n            if isinstance(_docs, Document):\n                self.append(_docs)\n\n    def _get_weaviate_class_name(self) -> str:\n        \"\"\"Generate the class/schema name using the ``uuid1`` module with some\n        formatting to tailor to weaviate class name convention\n\n        :return: string representing the name of  weaviate class/schema name of\n            this :class:`DocumentArrayWeaviate` object\n        \"\"\"\n        return ''.join([i for i in uuid.uuid1().hex if not i.isdigit()]).capitalize()\n\n    def _get_schema_by_name(self, cls_name: str) -> Dict:\n        \"\"\"Return the schema dictionary object with the class name\n        Content of the all dictionaries by this method are the same except the name\n        of the weaviate's ``class``\n\n        :param cls_name: the name of the schema/class in weaviate\n        :return: the schema dictionary\n        \"\"\"\n        # TODO: ideally we should only use one schema. this will allow us to deal with\n        # consistency better\n        hnsw_config = {\n            'ef': self._config.ef,\n            'efConstruction': self._config.ef_construction,\n            'maxConnections': self._config.max_connections,\n        }\n\n        return {\n            'classes': [\n                {\n                    'class': cls_name,\n                    \"vectorizer\": \"none\",\n                    'vectorIndexConfig': {'skip': False},\n                    'properties': [\n                        {\n                            'dataType': ['blob'],\n                            'name': '_serialized',\n                            'indexInverted': False,\n                        },\n                    ],\n                },\n                {\n                    'class': cls_name + 'Meta',\n                    \"vectorizer\": \"none\",\n                    'vectorIndexConfig': {'skip': True, **filter_dict(hnsw_config)},\n                    'properties': [\n                        {\n                            'dataType': ['string[]'],\n                            'name': '_offset2ids',\n                            'indexInverted': False,\n                        },\n                    ],\n                },\n            ]\n        }\n\n    def _load_or_create_weaviate_schema(self):\n        \"\"\"Create a new weaviate schema for this :class:`DocumentArrayWeaviate` object\n        if not present in weaviate or if ``self._config.name`` is None. If ``self._config.name``\n        is provided and not None and schema with the specified name exists in weaviate,\n        then load the object with the given ``self._config.name``\n\n        :return: the schemas of this :class`DocumentArrayWeaviate` object and its meta\n        \"\"\"\n        if not self._config.name:\n            name_candidate = self._get_weaviate_class_name()\n            doc_schemas = self._get_schema_by_name(name_candidate)\n            while self._client.schema.contains(doc_schemas):\n                name_candidate = self._get_weaviate_class_name()\n                doc_schemas = self._get_schema_by_name(name_candidate)\n            self._client.schema.create(doc_schemas)\n            self._config.name = name_candidate\n            return doc_schemas\n\n        doc_schemas = self._get_schema_by_name(self._config.name)\n        if self._client.schema.contains(doc_schemas):\n            return doc_schemas\n\n        self._client.schema.create(doc_schemas)\n        return doc_schemas\n\n    def _update_offset2ids_meta(self):\n        \"\"\"Update the offset2ids in weaviate the the current local version\"\"\"\n        if self._offset2ids_wid is not None and self._client.data_object.exists(\n            self._offset2ids_wid\n        ):\n            self._client.data_object.update(\n                data_object={'_offset2ids': self._offset2ids.ids},\n                class_name=self._meta_name,\n                uuid=self._offset2ids_wid,\n            )\n        else:\n            self._offset2ids_wid = str(uuid.uuid1())\n            self._client.data_object.create(\n                data_object={'_offset2ids': self._offset2ids.ids},\n                class_name=self._meta_name,\n                uuid=self._offset2ids_wid,\n            )\n\n    def _get_offset2ids_meta(self) -> Tuple[List, str]:\n        \"\"\"Return the offset2ids stored in weaviate along with the name of the schema/class\n        in weaviate that stores meta information of this object\n\n        :return: a tuple with first element as a list of offset2ids and second element\n                 being name of weaviate class/schema of the meta object\n\n        :raises ValueError: error is raised if meta class name is not defined\n        \"\"\"\n        if not self._meta_name:\n            raise ValueError('meta object is not defined')\n\n        resp = (\n            self._client.query.get(self._meta_name, ['_offset2ids', '_additional {id}'])\n            .do()\n            .get('data', {})\n            .get('Get', {})\n            .get(self._meta_name, [])\n        )\n\n        if not resp:\n            return [], None\n        elif len(resp) == 1:\n            return resp[0]['_offset2ids'], resp[0]['_additional']['id']\n        else:\n            raise ValueError('received multiple meta copies which is invalid')\n\n    @property\n    def name(self):\n        \"\"\"An alias to _class_name that returns the id/name of the class\n        in the weaviate of this :class:`DocumentArrayWeaviate`\n\n        :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`\n        \"\"\"\n        return self._class_name\n\n    @property\n    def _class_name(self):\n        \"\"\"Return the name of the class in weaviate of this :class:`DocumentArrayWeaviate\n\n        :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`\n        \"\"\"\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][0]['class']\n\n    @property\n    def _meta_name(self):\n        \"\"\"Return the name of the class in weaviate that stores the meta information of\n        this :class:`DocumentArrayWeaviate`\n\n        :return: name of weaviate class/schema of class that stores the meta information\n        \"\"\"\n        # TODO: remove this after we combine the meta info to the DocumentArray class\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][1]['class']\n\n    @property\n    def _class_schema(self) -> Optional[Dict]:\n        \"\"\"Return the schema dictionary of this :class:`DocumentArrayWeaviate`'s weaviate schema\n\n        :return: the dictionary representing this weaviate schema\n        \"\"\"\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][0]\n\n    @property\n    def _meta_schema(self):\n        \"\"\"Return the schema dictionary of this weaviate schema that stores this object's meta\n\n        :return: the dictionary representing a meta object's weaviate schema\n        \"\"\"\n        if not self._schemas and len(self._schemas) < 2:\n            return None\n        return self._schemas['classes'][1]\n\n    def _doc2weaviate_create_payload(self, value: 'Document'):\n        \"\"\"Return the payload to store :class:`Document` into weaviate\n\n        :param value: document to create a payload for\n        :return: the payload dictionary\n        \"\"\"\n        return dict(\n            data_object={'_serialized': value.to_base64(**self._serialize_config)},\n            class_name=self._class_name,\n            uuid=self._map_id(value.id),\n            vector=self._map_embedding(value.embedding),\n        )\n\n    def _map_id(self, doc_id: str):\n        \"\"\"the function maps doc id to weaviate id\n\n        :param doc_id: id of the document\n        :return: weaviate object id\n        \"\"\"\n        # appending class name to doc id to handle the case:\n        # daw1 = DocumentArrayWeaviate([Document(id=str(i), text='hi') for i in range(3)])\n        # daw2 = DocumentArrayWeaviate([Document(id=str(i), text='bye') for i in range(3)])\n        # daw2[0, 'text'] == 'hi' # this will be False if we don't append class name\n        return str(uuid.uuid5(uuid.NAMESPACE_URL, doc_id + self._class_name))\n\n    def _map_embedding(self, embedding: 'ArrayType'):\n        if embedding is not None:\n            from ....math.ndarray import to_numpy_array\n\n            embedding = to_numpy_array(embedding)\n\n            if embedding.ndim > 1:\n                embedding = np.asarray(embedding).squeeze()\n\n            # Weaviate expects vector to have dim 2 at least\n            # or get weaviate.exceptions.UnexpectedStatusCodeException:  models.C11yVector\n            # hence we cast it to list of a single element\n            if len(embedding) == 1:\n                embedding = [embedding[0]]\n        else:\n            embedding = None\n        return embedding\n\n    def __getstate__(self):\n        d = dict(self.__dict__)\n        del d['_client']\n        return d\n\n    def __setstate__(self, state):\n        self.__dict__ = state\n        self._client = weaviate.Client(\n            f'{state[\"_config\"].protocol}://{state[\"_config\"].host}:{state[\"_config\"].port}'\n        )\n", "path": "docarray/array/storage/weaviate/backend.py"}], "after_files": [{"content": "import uuid\nfrom dataclasses import dataclass, field\nfrom typing import (\n    Iterable,\n    Dict,\n    Optional,\n    TYPE_CHECKING,\n    Union,\n    Tuple,\n    List,\n)\n\nimport numpy as np\nimport weaviate\n\nfrom .... import Document\nfrom ....helper import dataclass_from_dict, filter_dict\nfrom ..base.backend import BaseBackendMixin\nfrom ..registry import _REGISTRY\n\nif TYPE_CHECKING:\n    from ....typing import ArrayType, DocumentArraySourceType\n\n\n@dataclass\nclass WeaviateConfig:\n    \"\"\"This class stores the config variables to initialize\n    connection to the Weaviate server\"\"\"\n\n    host: Optional[str] = field(default='localhost')\n    port: Optional[int] = field(default=8080)\n    protocol: Optional[str] = field(default='http')\n    name: Optional[str] = None\n    serialize_config: Dict = field(default_factory=dict)\n    n_dim: Optional[int] = None  # deprecated, not used anymore since weaviate 1.10\n    ef: Optional[int] = None\n    ef_construction: Optional[int] = None\n    timeout_config: Optional[Tuple[int, int]] = None\n    max_connections: Optional[int] = None\n\n\nclass BackendMixin(BaseBackendMixin):\n    \"\"\"Provide necessary functions to enable this storage backend.\"\"\"\n\n    def _init_storage(\n        self,\n        _docs: Optional['DocumentArraySourceType'] = None,\n        config: Optional[Union[WeaviateConfig, Dict]] = None,\n        **kwargs,\n    ):\n        \"\"\"Initialize weaviate storage.\n\n        :param docs: the list of documents to initialize to\n        :param config: the config object used to ininitialize connection to weaviate server\n        :param kwargs: extra keyword arguments\n        :raises ValueError: only one of name or docs can be used for initialization,\n            raise an error if both are provided\n        \"\"\"\n\n        if not config:\n            config = WeaviateConfig()\n        elif isinstance(config, dict):\n            config = dataclass_from_dict(WeaviateConfig, config)\n\n        self._serialize_config = config.serialize_config\n\n        if config.name and config.name != config.name.capitalize():\n            raise ValueError(\n                'Weaviate class name has to be capitalized. '\n                'Please capitalize when declaring the name field in config.'\n            )\n\n        self._persist = bool(config.name)\n\n        self._client = weaviate.Client(\n            f'{config.protocol}://{config.host}:{config.port}',\n            timeout_config=config.timeout_config,\n        )\n        self._config = config\n\n        self._schemas = self._load_or_create_weaviate_schema()\n\n        _REGISTRY[self.__class__.__name__][self._class_name].append(self)\n\n        super()._init_storage(_docs, **kwargs)\n\n        # To align with Sqlite behavior; if `docs` is not `None` and table name\n        # is provided, :class:`DocumentArraySqlite` will clear the existing\n        # table and load the given `docs`\n        if _docs is None:\n            return\n        elif isinstance(_docs, Iterable):\n            self.clear()\n            self.extend(_docs)\n        else:\n            self.clear()\n            if isinstance(_docs, Document):\n                self.append(_docs)\n\n    def _get_weaviate_class_name(self) -> str:\n        \"\"\"Generate the class/schema name using the ``uuid1`` module with some\n        formatting to tailor to weaviate class name convention\n\n        :return: string representing the name of  weaviate class/schema name of\n            this :class:`DocumentArrayWeaviate` object\n        \"\"\"\n        return ''.join([i for i in uuid.uuid1().hex if not i.isdigit()]).capitalize()\n\n    def _get_schema_by_name(self, cls_name: str) -> Dict:\n        \"\"\"Return the schema dictionary object with the class name\n        Content of the all dictionaries by this method are the same except the name\n        of the weaviate's ``class``\n\n        :param cls_name: the name of the schema/class in weaviate\n        :return: the schema dictionary\n        \"\"\"\n        # TODO: ideally we should only use one schema. this will allow us to deal with\n        # consistency better\n        hnsw_config = {\n            'ef': self._config.ef,\n            'efConstruction': self._config.ef_construction,\n            'maxConnections': self._config.max_connections,\n        }\n\n        return {\n            'classes': [\n                {\n                    'class': cls_name,\n                    \"vectorizer\": \"none\",\n                    'vectorIndexConfig': {'skip': False},\n                    'properties': [\n                        {\n                            'dataType': ['blob'],\n                            'name': '_serialized',\n                            'indexInverted': False,\n                        },\n                    ],\n                },\n                {\n                    'class': cls_name + 'Meta',\n                    \"vectorizer\": \"none\",\n                    'vectorIndexConfig': {'skip': True, **filter_dict(hnsw_config)},\n                    'properties': [\n                        {\n                            'dataType': ['string[]'],\n                            'name': '_offset2ids',\n                            'indexInverted': False,\n                        },\n                    ],\n                },\n            ]\n        }\n\n    def _load_or_create_weaviate_schema(self):\n        \"\"\"Create a new weaviate schema for this :class:`DocumentArrayWeaviate` object\n        if not present in weaviate or if ``self._config.name`` is None. If ``self._config.name``\n        is provided and not None and schema with the specified name exists in weaviate,\n        then load the object with the given ``self._config.name``\n\n        :return: the schemas of this :class`DocumentArrayWeaviate` object and its meta\n        \"\"\"\n        if not self._config.name:\n            name_candidate = self._get_weaviate_class_name()\n            doc_schemas = self._get_schema_by_name(name_candidate)\n            while self._client.schema.contains(doc_schemas):\n                name_candidate = self._get_weaviate_class_name()\n                doc_schemas = self._get_schema_by_name(name_candidate)\n            self._client.schema.create(doc_schemas)\n            self._config.name = name_candidate\n            return doc_schemas\n\n        doc_schemas = self._get_schema_by_name(self._config.name)\n        if self._client.schema.contains(doc_schemas):\n            return doc_schemas\n\n        self._client.schema.create(doc_schemas)\n        return doc_schemas\n\n    def _update_offset2ids_meta(self):\n        \"\"\"Update the offset2ids in weaviate the the current local version\"\"\"\n        if self._offset2ids_wid is not None and self._client.data_object.exists(\n            self._offset2ids_wid\n        ):\n            self._client.data_object.update(\n                data_object={'_offset2ids': self._offset2ids.ids},\n                class_name=self._meta_name,\n                uuid=self._offset2ids_wid,\n            )\n        else:\n            self._offset2ids_wid = str(uuid.uuid1())\n            self._client.data_object.create(\n                data_object={'_offset2ids': self._offset2ids.ids},\n                class_name=self._meta_name,\n                uuid=self._offset2ids_wid,\n            )\n\n    def _get_offset2ids_meta(self) -> Tuple[List, str]:\n        \"\"\"Return the offset2ids stored in weaviate along with the name of the schema/class\n        in weaviate that stores meta information of this object\n\n        :return: a tuple with first element as a list of offset2ids and second element\n                 being name of weaviate class/schema of the meta object\n\n        :raises ValueError: error is raised if meta class name is not defined\n        \"\"\"\n        if not self._meta_name:\n            raise ValueError('meta object is not defined')\n\n        resp = (\n            self._client.query.get(self._meta_name, ['_offset2ids', '_additional {id}'])\n            .do()\n            .get('data', {})\n            .get('Get', {})\n            .get(self._meta_name, [])\n        )\n\n        if not resp:\n            return [], None\n        elif len(resp) == 1:\n            return resp[0]['_offset2ids'], resp[0]['_additional']['id']\n        else:\n            raise ValueError('received multiple meta copies which is invalid')\n\n    @property\n    def name(self):\n        \"\"\"An alias to _class_name that returns the id/name of the class\n        in the weaviate of this :class:`DocumentArrayWeaviate`\n\n        :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`\n        \"\"\"\n        return self._class_name\n\n    @property\n    def _class_name(self):\n        \"\"\"Return the name of the class in weaviate of this :class:`DocumentArrayWeaviate\n\n        :return: name of weaviate class/schema of this :class:`DocumentArrayWeaviate`\n        \"\"\"\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][0]['class']\n\n    @property\n    def _meta_name(self):\n        \"\"\"Return the name of the class in weaviate that stores the meta information of\n        this :class:`DocumentArrayWeaviate`\n\n        :return: name of weaviate class/schema of class that stores the meta information\n        \"\"\"\n        # TODO: remove this after we combine the meta info to the DocumentArray class\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][1]['class']\n\n    @property\n    def _class_schema(self) -> Optional[Dict]:\n        \"\"\"Return the schema dictionary of this :class:`DocumentArrayWeaviate`'s weaviate schema\n\n        :return: the dictionary representing this weaviate schema\n        \"\"\"\n        if not self._schemas:\n            return None\n        return self._schemas['classes'][0]\n\n    @property\n    def _meta_schema(self):\n        \"\"\"Return the schema dictionary of this weaviate schema that stores this object's meta\n\n        :return: the dictionary representing a meta object's weaviate schema\n        \"\"\"\n        if not self._schemas and len(self._schemas) < 2:\n            return None\n        return self._schemas['classes'][1]\n\n    def _doc2weaviate_create_payload(self, value: 'Document'):\n        \"\"\"Return the payload to store :class:`Document` into weaviate\n\n        :param value: document to create a payload for\n        :return: the payload dictionary\n        \"\"\"\n        return dict(\n            data_object={'_serialized': value.to_base64(**self._serialize_config)},\n            class_name=self._class_name,\n            uuid=self._map_id(value.id),\n            vector=self._map_embedding(value.embedding),\n        )\n\n    def _map_id(self, doc_id: str):\n        \"\"\"the function maps doc id to weaviate id\n\n        :param doc_id: id of the document\n        :return: weaviate object id\n        \"\"\"\n        # appending class name to doc id to handle the case:\n        # daw1 = DocumentArrayWeaviate([Document(id=str(i), text='hi') for i in range(3)])\n        # daw2 = DocumentArrayWeaviate([Document(id=str(i), text='bye') for i in range(3)])\n        # daw2[0, 'text'] == 'hi' # this will be False if we don't append class name\n        return str(uuid.uuid5(uuid.NAMESPACE_URL, doc_id + self._class_name))\n\n    def _map_embedding(self, embedding: 'ArrayType'):\n        if embedding is not None:\n            from ....math.ndarray import to_numpy_array\n\n            embedding = to_numpy_array(embedding)\n\n            if embedding.ndim > 1:\n                embedding = np.asarray(embedding).squeeze()\n\n            # Weaviate expects vector to have dim 2 at least\n            # or get weaviate.exceptions.UnexpectedStatusCodeException:  models.C11yVector\n            # hence we cast it to list of a single element\n            if len(embedding) == 1:\n                embedding = [embedding[0]]\n        else:\n            embedding = None\n        return embedding\n\n    def __getstate__(self):\n        d = dict(self.__dict__)\n        del d['_client']\n        return d\n\n    def __setstate__(self, state):\n        self.__dict__ = state\n        self._client = weaviate.Client(\n            f'{state[\"_config\"].protocol}://{state[\"_config\"].host}:{state[\"_config\"].port}'\n        )\n", "path": "docarray/array/storage/weaviate/backend.py"}]}