meilisearch-python-sdk 2.8.0__py3-none-any.whl → 2.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of meilisearch-python-sdk might be problematic. Click here for more details.

@@ -6,7 +6,7 @@ from csv import DictReader
6
6
  from datetime import datetime
7
7
  from functools import cached_property, partial
8
8
  from pathlib import Path
9
- from typing import Any, Generator, MutableMapping, Sequence
9
+ from typing import TYPE_CHECKING, Any, Generator, MutableMapping, Sequence
10
10
  from urllib.parse import urlencode
11
11
  from warnings import warn
12
12
 
@@ -26,9 +26,11 @@ from meilisearch_python_sdk.models.settings import (
26
26
  Faceting,
27
27
  HuggingFaceEmbedder,
28
28
  MeilisearchSettings,
29
+ OllamaEmbedder,
29
30
  OpenAiEmbedder,
30
31
  Pagination,
31
32
  ProximityPrecision,
33
+ RestEmbedder,
32
34
  TypoTolerance,
33
35
  UserProvidedEmbedder,
34
36
  )
@@ -45,7 +47,9 @@ from meilisearch_python_sdk.plugins import (
45
47
  Plugin,
46
48
  PostSearchPlugin,
47
49
  )
48
- from meilisearch_python_sdk.types import Filter, JsonDict, JsonMapping
50
+
51
+ if TYPE_CHECKING: # pragma: no cover
52
+ from meilisearch_python_sdk.types import Filter, JsonDict, JsonMapping
49
53
 
50
54
 
51
55
  class _BaseIndex:
@@ -613,6 +617,7 @@ class AsyncIndex(_BaseIndex):
613
617
  *,
614
618
  settings: MeilisearchSettings | None = None,
615
619
  wait: bool = True,
620
+ timeout_in_ms: int | None = None,
616
621
  plugins: AsyncIndexPlugins | None = None,
617
622
  ) -> AsyncIndex:
618
623
  """Creates a new index.
@@ -634,6 +639,9 @@ class AsyncIndex(_BaseIndex):
634
639
  wait: If set to True and settings are being updated, the index will be returned after
635
640
  the settings update has completed. If False it will not wait for settings to complete.
636
641
  Default: True
642
+ timeout_in_ms: Amount of time in milliseconds to wait before raising a
643
+ MeilisearchTimeoutError. `None` can also be passed to wait indefinitely. Be aware that
644
+ if the `None` option is used the wait time could be very long. Defaults to None.
637
645
  plugins: Optional plugins can be provided to extend functionality.
638
646
 
639
647
  Returns:
@@ -659,7 +667,9 @@ class AsyncIndex(_BaseIndex):
659
667
  url = "indexes"
660
668
  http_request = AsyncHttpRequests(http_client)
661
669
  response = await http_request.post(url, payload)
662
- await async_wait_for_task(http_client, response.json()["taskUid"], timeout_in_ms=None)
670
+ await async_wait_for_task(
671
+ http_client, response.json()["taskUid"], timeout_in_ms=timeout_in_ms
672
+ )
663
673
 
664
674
  index_response = await http_request.get(f"{url}/{uid}")
665
675
  index_dict = index_response.json()
@@ -675,7 +685,9 @@ class AsyncIndex(_BaseIndex):
675
685
  if settings:
676
686
  settings_task = await index.update_settings(settings)
677
687
  if wait:
678
- await async_wait_for_task(http_client, settings_task.task_uid, timeout_in_ms=None)
688
+ await async_wait_for_task(
689
+ http_client, settings_task.task_uid, timeout_in_ms=timeout_in_ms
690
+ )
679
691
 
680
692
  return index
681
693
 
@@ -710,7 +722,7 @@ class AsyncIndex(_BaseIndex):
710
722
  limit: int = 20,
711
723
  filter: Filter | None = None,
712
724
  facets: list[str] | None = None,
713
- attributes_to_retrieve: list[str] = ["*"],
725
+ attributes_to_retrieve: list[str] | None = None,
714
726
  attributes_to_crop: list[str] | None = None,
715
727
  crop_length: int = 200,
716
728
  attributes_to_highlight: list[str] | None = None,
@@ -796,7 +808,6 @@ class AsyncIndex(_BaseIndex):
796
808
  >>> index = client.index("movies")
797
809
  >>> search_results = await index.search("Tron")
798
810
  """
799
-
800
811
  body = _process_search_parameters(
801
812
  q=query,
802
813
  offset=offset,
@@ -961,7 +972,7 @@ class AsyncIndex(_BaseIndex):
961
972
  limit: int = 20,
962
973
  filter: Filter | None = None,
963
974
  facets: list[str] | None = None,
964
- attributes_to_retrieve: list[str] = ["*"],
975
+ attributes_to_retrieve: list[str] | None = None,
965
976
  attributes_to_crop: list[str] | None = None,
966
977
  crop_length: int = 200,
967
978
  attributes_to_highlight: list[str] | None = None,
@@ -1289,6 +1300,7 @@ class AsyncIndex(_BaseIndex):
1289
1300
  primary_key: str | None = None,
1290
1301
  *,
1291
1302
  compress: bool = False,
1303
+ serializer: type[json.JSONEncoder] | None = None,
1292
1304
  ) -> TaskInfo:
1293
1305
  """Add documents to the index.
1294
1306
 
@@ -1298,6 +1310,8 @@ class AsyncIndex(_BaseIndex):
1298
1310
  primary_key: The primary key of the documents. This will be ignored if already set.
1299
1311
  Defaults to None.
1300
1312
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1313
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1314
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1301
1315
 
1302
1316
  Returns:
1303
1317
 
@@ -1355,7 +1369,11 @@ class AsyncIndex(_BaseIndex):
1355
1369
  )
1356
1370
  )
1357
1371
 
1358
- tasks.append(self._http_requests.post(url, documents, compress=compress))
1372
+ tasks.append(
1373
+ self._http_requests.post(
1374
+ url, documents, compress=compress, serializer=serializer
1375
+ )
1376
+ )
1359
1377
 
1360
1378
  responses = await asyncio.gather(*tasks)
1361
1379
  result = TaskInfo(**responses[-1].json())
@@ -1391,7 +1409,9 @@ class AsyncIndex(_BaseIndex):
1391
1409
  )
1392
1410
 
1393
1411
  response_coroutine = tg.create_task(
1394
- self._http_requests.post(url, documents, compress=compress)
1412
+ self._http_requests.post(
1413
+ url, documents, compress=compress, serializer=serializer
1414
+ )
1395
1415
  )
1396
1416
 
1397
1417
  response = await response_coroutine
@@ -1409,7 +1429,9 @@ class AsyncIndex(_BaseIndex):
1409
1429
 
1410
1430
  return result
1411
1431
 
1412
- response = await self._http_requests.post(url, documents, compress=compress)
1432
+ response = await self._http_requests.post(
1433
+ url, documents, compress=compress, serializer=serializer
1434
+ )
1413
1435
 
1414
1436
  result = TaskInfo(**response.json())
1415
1437
  if self._post_add_documents_plugins:
@@ -1432,6 +1454,7 @@ class AsyncIndex(_BaseIndex):
1432
1454
  batch_size: int = 1000,
1433
1455
  primary_key: str | None = None,
1434
1456
  compress: bool = False,
1457
+ serializer: type[json.JSONEncoder] | None = None,
1435
1458
  ) -> list[TaskInfo]:
1436
1459
  """Adds documents in batches to reduce RAM usage with indexing.
1437
1460
 
@@ -1443,6 +1466,8 @@ class AsyncIndex(_BaseIndex):
1443
1466
  primary_key: The primary key of the documents. This will be ignored if already set.
1444
1467
  Defaults to None.
1445
1468
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1469
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1470
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1446
1471
 
1447
1472
  Returns:
1448
1473
 
@@ -1466,14 +1491,16 @@ class AsyncIndex(_BaseIndex):
1466
1491
  """
1467
1492
  if not use_task_groups():
1468
1493
  batches = [
1469
- self.add_documents(x, primary_key, compress=compress)
1494
+ self.add_documents(x, primary_key, compress=compress, serializer=serializer)
1470
1495
  for x in _batch(documents, batch_size)
1471
1496
  ]
1472
1497
  return await asyncio.gather(*batches)
1473
1498
 
1474
1499
  async with asyncio.TaskGroup() as tg: # type: ignore[attr-defined]
1475
1500
  tasks = [
1476
- tg.create_task(self.add_documents(x, primary_key, compress=compress))
1501
+ tg.create_task(
1502
+ self.add_documents(x, primary_key, compress=compress, serializer=serializer)
1503
+ )
1477
1504
  for x in _batch(documents, batch_size)
1478
1505
  ]
1479
1506
 
@@ -1488,6 +1515,7 @@ class AsyncIndex(_BaseIndex):
1488
1515
  csv_delimiter: str | None = None,
1489
1516
  combine_documents: bool = True,
1490
1517
  compress: bool = False,
1518
+ serializer: type[json.JSONEncoder] | None = None,
1491
1519
  ) -> list[TaskInfo]:
1492
1520
  """Load all json files from a directory and add the documents to the index.
1493
1521
 
@@ -1504,6 +1532,8 @@ class AsyncIndex(_BaseIndex):
1504
1532
  combine_documents: If set to True this will combine the documents from all the files
1505
1533
  before indexing them. Defaults to True.
1506
1534
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1535
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1536
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1507
1537
 
1508
1538
  Returns:
1509
1539
 
@@ -1539,7 +1569,9 @@ class AsyncIndex(_BaseIndex):
1539
1569
  loop = asyncio.get_running_loop()
1540
1570
  combined = await loop.run_in_executor(None, partial(_combine_documents, all_documents))
1541
1571
 
1542
- response = await self.add_documents(combined, primary_key, compress=compress)
1572
+ response = await self.add_documents(
1573
+ combined, primary_key, compress=compress, serializer=serializer
1574
+ )
1543
1575
 
1544
1576
  return [response]
1545
1577
 
@@ -1549,7 +1581,9 @@ class AsyncIndex(_BaseIndex):
1549
1581
  if path.suffix == f".{document_type}":
1550
1582
  documents = await _async_load_documents_from_file(path, csv_delimiter)
1551
1583
  add_documents.append(
1552
- self.add_documents(documents, primary_key, compress=compress)
1584
+ self.add_documents(
1585
+ documents, primary_key, compress=compress, serializer=serializer
1586
+ )
1553
1587
  )
1554
1588
 
1555
1589
  _raise_on_no_documents(add_documents, document_type, directory_path)
@@ -1573,11 +1607,17 @@ class AsyncIndex(_BaseIndex):
1573
1607
  if path.suffix == f".{document_type}":
1574
1608
  documents = await _async_load_documents_from_file(path, csv_delimiter)
1575
1609
  if i == 0:
1576
- all_results = [await self.add_documents(documents, compress=compress)]
1610
+ all_results = [
1611
+ await self.add_documents(
1612
+ documents, compress=compress, serializer=serializer
1613
+ )
1614
+ ]
1577
1615
  else:
1578
1616
  tasks.append(
1579
1617
  tg.create_task(
1580
- self.add_documents(documents, primary_key, compress=compress)
1618
+ self.add_documents(
1619
+ documents, primary_key, compress=compress, serializer=serializer
1620
+ )
1581
1621
  )
1582
1622
  )
1583
1623
 
@@ -1596,6 +1636,7 @@ class AsyncIndex(_BaseIndex):
1596
1636
  csv_delimiter: str | None = None,
1597
1637
  combine_documents: bool = True,
1598
1638
  compress: bool = False,
1639
+ serializer: type[json.JSONEncoder] | None = None,
1599
1640
  ) -> list[TaskInfo]:
1600
1641
  """Load all json files from a directory and add the documents to the index in batches.
1601
1642
 
@@ -1614,6 +1655,8 @@ class AsyncIndex(_BaseIndex):
1614
1655
  combine_documents: If set to True this will combine the documents from all the files
1615
1656
  before indexing them. Defaults to True.
1616
1657
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1658
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1659
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1617
1660
 
1618
1661
  Returns:
1619
1662
 
@@ -1652,7 +1695,11 @@ class AsyncIndex(_BaseIndex):
1652
1695
  combined = await loop.run_in_executor(None, partial(_combine_documents, all_documents))
1653
1696
 
1654
1697
  return await self.add_documents_in_batches(
1655
- combined, batch_size=batch_size, primary_key=primary_key, compress=compress
1698
+ combined,
1699
+ batch_size=batch_size,
1700
+ primary_key=primary_key,
1701
+ compress=compress,
1702
+ serializer=serializer,
1656
1703
  )
1657
1704
 
1658
1705
  responses: list[TaskInfo] = []
@@ -1663,7 +1710,11 @@ class AsyncIndex(_BaseIndex):
1663
1710
  documents = await _async_load_documents_from_file(path, csv_delimiter)
1664
1711
  add_documents.append(
1665
1712
  self.add_documents_in_batches(
1666
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
1713
+ documents,
1714
+ batch_size=batch_size,
1715
+ primary_key=primary_key,
1716
+ compress=compress,
1717
+ serializer=serializer,
1667
1718
  )
1668
1719
  )
1669
1720
 
@@ -1681,7 +1732,12 @@ class AsyncIndex(_BaseIndex):
1681
1732
  return responses
1682
1733
 
1683
1734
  async def add_documents_from_file(
1684
- self, file_path: Path | str, primary_key: str | None = None, *, compress: bool = False
1735
+ self,
1736
+ file_path: Path | str,
1737
+ primary_key: str | None = None,
1738
+ *,
1739
+ compress: bool = False,
1740
+ serializer: type[json.JSONEncoder] | None = None,
1685
1741
  ) -> TaskInfo:
1686
1742
  """Add documents to the index from a json file.
1687
1743
 
@@ -1691,6 +1747,8 @@ class AsyncIndex(_BaseIndex):
1691
1747
  primary_key: The primary key of the documents. This will be ignored if already set.
1692
1748
  Defaults to None.
1693
1749
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1750
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1751
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1694
1752
 
1695
1753
  Returns:
1696
1754
 
@@ -1714,7 +1772,9 @@ class AsyncIndex(_BaseIndex):
1714
1772
  """
1715
1773
  documents = await _async_load_documents_from_file(file_path)
1716
1774
 
1717
- return await self.add_documents(documents, primary_key=primary_key, compress=compress)
1775
+ return await self.add_documents(
1776
+ documents, primary_key=primary_key, compress=compress, serializer=serializer
1777
+ )
1718
1778
 
1719
1779
  async def add_documents_from_file_in_batches(
1720
1780
  self,
@@ -1724,6 +1784,7 @@ class AsyncIndex(_BaseIndex):
1724
1784
  primary_key: str | None = None,
1725
1785
  csv_delimiter: str | None = None,
1726
1786
  compress: bool = False,
1787
+ serializer: type[json.JSONEncoder] | None = None,
1727
1788
  ) -> list[TaskInfo]:
1728
1789
  """Adds documents form a json file in batches to reduce RAM usage with indexing.
1729
1790
 
@@ -1737,6 +1798,8 @@ class AsyncIndex(_BaseIndex):
1737
1798
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
1738
1799
  can only be used if the file is a csv file. Defaults to comma.
1739
1800
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1801
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1802
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1740
1803
 
1741
1804
  Returns:
1742
1805
 
@@ -1761,7 +1824,11 @@ class AsyncIndex(_BaseIndex):
1761
1824
  documents = await _async_load_documents_from_file(file_path, csv_delimiter)
1762
1825
 
1763
1826
  return await self.add_documents_in_batches(
1764
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
1827
+ documents,
1828
+ batch_size=batch_size,
1829
+ primary_key=primary_key,
1830
+ compress=compress,
1831
+ serializer=serializer,
1765
1832
  )
1766
1833
 
1767
1834
  async def add_documents_from_raw_file(
@@ -1771,6 +1838,7 @@ class AsyncIndex(_BaseIndex):
1771
1838
  *,
1772
1839
  csv_delimiter: str | None = None,
1773
1840
  compress: bool = False,
1841
+ serializer: type[json.JSONEncoder] | None = None,
1774
1842
  ) -> TaskInfo:
1775
1843
  """Directly send csv or ndjson files to Meilisearch without pre-processing.
1776
1844
 
@@ -1786,6 +1854,8 @@ class AsyncIndex(_BaseIndex):
1786
1854
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
1787
1855
  can only be used if the file is a csv file. Defaults to comma.
1788
1856
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1857
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1858
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1789
1859
 
1790
1860
  Returns:
1791
1861
 
@@ -1843,7 +1913,7 @@ class AsyncIndex(_BaseIndex):
1843
1913
  data = await f.read()
1844
1914
 
1845
1915
  response = await self._http_requests.post(
1846
- url, body=data, content_type=content_type, compress=compress
1916
+ url, body=data, content_type=content_type, compress=compress, serializer=serializer
1847
1917
  )
1848
1918
 
1849
1919
  return TaskInfo(**response.json())
@@ -1854,6 +1924,7 @@ class AsyncIndex(_BaseIndex):
1854
1924
  primary_key: str | None = None,
1855
1925
  *,
1856
1926
  compress: bool = False,
1927
+ serializer: type[json.JSONEncoder] | None = None,
1857
1928
  ) -> TaskInfo:
1858
1929
  """Update documents in the index.
1859
1930
 
@@ -1863,6 +1934,8 @@ class AsyncIndex(_BaseIndex):
1863
1934
  primary_key: The primary key of the documents. This will be ignored if already set.
1864
1935
  Defaults to None.
1865
1936
  compress: If set to True the data will be sent in gzip format. Defaults to False.
1937
+ serializer: A custom JSONEncode to handle serializing fields that the build in
1938
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
1866
1939
 
1867
1940
  Returns:
1868
1941
 
@@ -1957,7 +2030,9 @@ class AsyncIndex(_BaseIndex):
1957
2030
  )
1958
2031
 
1959
2032
  response_coroutine = tg.create_task(
1960
- self._http_requests.put(url, documents, compress=compress)
2033
+ self._http_requests.put(
2034
+ url, documents, compress=compress, serializer=serializer
2035
+ )
1961
2036
  )
1962
2037
 
1963
2038
  response = await response_coroutine
@@ -1976,7 +2051,9 @@ class AsyncIndex(_BaseIndex):
1976
2051
 
1977
2052
  return result
1978
2053
 
1979
- response = await self._http_requests.put(url, documents, compress=compress)
2054
+ response = await self._http_requests.put(
2055
+ url, documents, compress=compress, serializer=serializer
2056
+ )
1980
2057
  result = TaskInfo(**response.json())
1981
2058
  if self._post_update_documents_plugins:
1982
2059
  post = await AsyncIndex._run_plugins(
@@ -1998,6 +2075,7 @@ class AsyncIndex(_BaseIndex):
1998
2075
  batch_size: int = 1000,
1999
2076
  primary_key: str | None = None,
2000
2077
  compress: bool = False,
2078
+ serializer: type[json.JSONEncoder] | None = None,
2001
2079
  ) -> list[TaskInfo]:
2002
2080
  """Update documents in batches to reduce RAM usage with indexing.
2003
2081
 
@@ -2011,6 +2089,8 @@ class AsyncIndex(_BaseIndex):
2011
2089
  primary_key: The primary key of the documents. This will be ignored if already set.
2012
2090
  Defaults to None.
2013
2091
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2092
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2093
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2014
2094
 
2015
2095
  Returns:
2016
2096
 
@@ -2034,7 +2114,7 @@ class AsyncIndex(_BaseIndex):
2034
2114
  """
2035
2115
  if not use_task_groups():
2036
2116
  batches = [
2037
- self.update_documents(x, primary_key, compress=compress)
2117
+ self.update_documents(x, primary_key, compress=compress, serializer=serializer)
2038
2118
  for x in _batch(documents, batch_size)
2039
2119
  ]
2040
2120
  return await asyncio.gather(*batches)
@@ -2055,6 +2135,7 @@ class AsyncIndex(_BaseIndex):
2055
2135
  csv_delimiter: str | None = None,
2056
2136
  combine_documents: bool = True,
2057
2137
  compress: bool = False,
2138
+ serializer: type[json.JSONEncoder] | None = None,
2058
2139
  ) -> list[TaskInfo]:
2059
2140
  """Load all json files from a directory and update the documents.
2060
2141
 
@@ -2071,6 +2152,8 @@ class AsyncIndex(_BaseIndex):
2071
2152
  combine_documents: If set to True this will combine the documents from all the files
2072
2153
  before indexing them. Defaults to True.
2073
2154
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2155
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2156
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2074
2157
 
2075
2158
  Returns:
2076
2159
 
@@ -2106,7 +2189,9 @@ class AsyncIndex(_BaseIndex):
2106
2189
  loop = asyncio.get_running_loop()
2107
2190
  combined = await loop.run_in_executor(None, partial(_combine_documents, all_documents))
2108
2191
 
2109
- response = await self.update_documents(combined, primary_key, compress=compress)
2192
+ response = await self.update_documents(
2193
+ combined, primary_key, compress=compress, serializer=serializer
2194
+ )
2110
2195
  return [response]
2111
2196
 
2112
2197
  if not use_task_groups():
@@ -2115,7 +2200,9 @@ class AsyncIndex(_BaseIndex):
2115
2200
  if path.suffix == f".{document_type}":
2116
2201
  documents = await _async_load_documents_from_file(path, csv_delimiter)
2117
2202
  update_documents.append(
2118
- self.update_documents(documents, primary_key, compress=compress)
2203
+ self.update_documents(
2204
+ documents, primary_key, compress=compress, serializer=serializer
2205
+ )
2119
2206
  )
2120
2207
 
2121
2208
  _raise_on_no_documents(update_documents, document_type, directory_path)
@@ -2139,12 +2226,16 @@ class AsyncIndex(_BaseIndex):
2139
2226
  documents = await _async_load_documents_from_file(path, csv_delimiter)
2140
2227
  if i == 0:
2141
2228
  results = [
2142
- await self.update_documents(documents, primary_key, compress=compress)
2229
+ await self.update_documents(
2230
+ documents, primary_key, compress=compress, serializer=serializer
2231
+ )
2143
2232
  ]
2144
2233
  else:
2145
2234
  tasks.append(
2146
2235
  tg.create_task(
2147
- self.update_documents(documents, primary_key, compress=compress)
2236
+ self.update_documents(
2237
+ documents, primary_key, compress=compress, serializer=serializer
2238
+ )
2148
2239
  )
2149
2240
  )
2150
2241
 
@@ -2162,6 +2253,7 @@ class AsyncIndex(_BaseIndex):
2162
2253
  csv_delimiter: str | None = None,
2163
2254
  combine_documents: bool = True,
2164
2255
  compress: bool = False,
2256
+ serializer: type[json.JSONEncoder] | None = None,
2165
2257
  ) -> list[TaskInfo]:
2166
2258
  """Load all json files from a directory and update the documents.
2167
2259
 
@@ -2180,6 +2272,8 @@ class AsyncIndex(_BaseIndex):
2180
2272
  combine_documents: If set to True this will combine the documents from all the files
2181
2273
  before indexing them. Defaults to True.
2182
2274
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2275
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2276
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2183
2277
 
2184
2278
  Returns:
2185
2279
 
@@ -2216,7 +2310,11 @@ class AsyncIndex(_BaseIndex):
2216
2310
  combined = await loop.run_in_executor(None, partial(_combine_documents, all_documents))
2217
2311
 
2218
2312
  return await self.update_documents_in_batches(
2219
- combined, batch_size=batch_size, primary_key=primary_key, compress=compress
2313
+ combined,
2314
+ batch_size=batch_size,
2315
+ primary_key=primary_key,
2316
+ compress=compress,
2317
+ serializer=serializer,
2220
2318
  )
2221
2319
 
2222
2320
  if not use_task_groups():
@@ -2232,6 +2330,7 @@ class AsyncIndex(_BaseIndex):
2232
2330
  batch_size=batch_size,
2233
2331
  primary_key=primary_key,
2234
2332
  compress=compress,
2333
+ serializer=serializer,
2235
2334
  )
2236
2335
  )
2237
2336
 
@@ -2260,6 +2359,7 @@ class AsyncIndex(_BaseIndex):
2260
2359
  batch_size=batch_size,
2261
2360
  primary_key=primary_key,
2262
2361
  compress=compress,
2362
+ serializer=serializer,
2263
2363
  )
2264
2364
  else:
2265
2365
  tasks.append(
@@ -2269,6 +2369,7 @@ class AsyncIndex(_BaseIndex):
2269
2369
  batch_size=batch_size,
2270
2370
  primary_key=primary_key,
2271
2371
  compress=compress,
2372
+ serializer=serializer,
2272
2373
  )
2273
2374
  )
2274
2375
  )
@@ -2284,6 +2385,7 @@ class AsyncIndex(_BaseIndex):
2284
2385
  csv_delimiter: str | None = None,
2285
2386
  *,
2286
2387
  compress: bool = False,
2388
+ serializer: type[json.JSONEncoder] | None = None,
2287
2389
  ) -> TaskInfo:
2288
2390
  """Add documents in the index from a json file.
2289
2391
 
@@ -2295,6 +2397,8 @@ class AsyncIndex(_BaseIndex):
2295
2397
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
2296
2398
  can only be used if the file is a csv file. Defaults to comma.
2297
2399
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2400
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2401
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2298
2402
 
2299
2403
  Returns:
2300
2404
 
@@ -2316,7 +2420,9 @@ class AsyncIndex(_BaseIndex):
2316
2420
  """
2317
2421
  documents = await _async_load_documents_from_file(file_path, csv_delimiter)
2318
2422
 
2319
- return await self.update_documents(documents, primary_key=primary_key, compress=compress)
2423
+ return await self.update_documents(
2424
+ documents, primary_key=primary_key, compress=compress, serializer=serializer
2425
+ )
2320
2426
 
2321
2427
  async def update_documents_from_file_in_batches(
2322
2428
  self,
@@ -2325,6 +2431,7 @@ class AsyncIndex(_BaseIndex):
2325
2431
  batch_size: int = 1000,
2326
2432
  primary_key: str | None = None,
2327
2433
  compress: bool = False,
2434
+ serializer: type[json.JSONEncoder] | None = None,
2328
2435
  ) -> list[TaskInfo]:
2329
2436
  """Updates documents form a json file in batches to reduce RAM usage with indexing.
2330
2437
 
@@ -2336,6 +2443,8 @@ class AsyncIndex(_BaseIndex):
2336
2443
  primary_key: The primary key of the documents. This will be ignored if already set.
2337
2444
  Defaults to None.
2338
2445
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2446
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2447
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2339
2448
 
2340
2449
  Returns:
2341
2450
 
@@ -2358,7 +2467,11 @@ class AsyncIndex(_BaseIndex):
2358
2467
  documents = await _async_load_documents_from_file(file_path)
2359
2468
 
2360
2469
  return await self.update_documents_in_batches(
2361
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
2470
+ documents,
2471
+ batch_size=batch_size,
2472
+ primary_key=primary_key,
2473
+ compress=compress,
2474
+ serializer=serializer,
2362
2475
  )
2363
2476
 
2364
2477
  async def update_documents_from_raw_file(
@@ -2368,6 +2481,7 @@ class AsyncIndex(_BaseIndex):
2368
2481
  csv_delimiter: str | None = None,
2369
2482
  *,
2370
2483
  compress: bool = False,
2484
+ serializer: type[json.JSONEncoder] | None = None,
2371
2485
  ) -> TaskInfo:
2372
2486
  """Directly send csv or ndjson files to Meilisearch without pre-processing.
2373
2487
 
@@ -2383,6 +2497,8 @@ class AsyncIndex(_BaseIndex):
2383
2497
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
2384
2498
  can only be used if the file is a csv file. Defaults to comma.
2385
2499
  compress: If set to True the data will be sent in gzip format. Defaults to False.
2500
+ serializer: A custom JSONEncode to handle serializing fields that the build in
2501
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
2386
2502
 
2387
2503
  Returns:
2388
2504
 
@@ -2440,7 +2556,7 @@ class AsyncIndex(_BaseIndex):
2440
2556
  data = await f.read()
2441
2557
 
2442
2558
  response = await self._http_requests.put(
2443
- url, body=data, content_type=content_type, compress=compress
2559
+ url, body=data, content_type=content_type, compress=compress, serializer=serializer
2444
2560
  )
2445
2561
 
2446
2562
  return TaskInfo(**response.json())
@@ -2809,7 +2925,10 @@ class AsyncIndex(_BaseIndex):
2809
2925
  settings = MeilisearchSettings(**response_json)
2810
2926
 
2811
2927
  if response_json.get("embedders"):
2812
- settings.embedders = _embedder_json_to_settings_model(response_json["embedders"])
2928
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
2929
+ settings.embedders = _embedder_json_to_settings_model( # pragma: no cover
2930
+ response_json["embedders"]
2931
+ )
2813
2932
 
2814
2933
  return settings
2815
2934
 
@@ -2865,6 +2984,7 @@ class AsyncIndex(_BaseIndex):
2865
2984
  warn(
2866
2985
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
2867
2986
  DeprecationWarning,
2987
+ stacklevel=2,
2868
2988
  )
2869
2989
  body_dict = {k: v for k, v in body.dict(by_alias=True).items() if v is not None} # type: ignore[attr-defined]
2870
2990
 
@@ -3006,7 +3126,7 @@ class AsyncIndex(_BaseIndex):
3006
3126
  response = await self._http_requests.get(f"{self._settings_url}/distinct-attribute")
3007
3127
 
3008
3128
  if not response.json():
3009
- None
3129
+ return None
3010
3130
 
3011
3131
  return response.json()
3012
3132
 
@@ -3602,6 +3722,7 @@ class AsyncIndex(_BaseIndex):
3602
3722
  warn(
3603
3723
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
3604
3724
  DeprecationWarning,
3725
+ stacklevel=2,
3605
3726
  )
3606
3727
  response = await self._http_requests.patch(
3607
3728
  f"{self._settings_url}/typo-tolerance",
@@ -3691,6 +3812,7 @@ class AsyncIndex(_BaseIndex):
3691
3812
  warn(
3692
3813
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
3693
3814
  DeprecationWarning,
3815
+ stacklevel=2,
3694
3816
  )
3695
3817
  response = await self._http_requests.patch(
3696
3818
  f"{self._settings_url}/faceting", faceting.dict(by_alias=True), compress=compress
@@ -3779,6 +3901,7 @@ class AsyncIndex(_BaseIndex):
3779
3901
  warn(
3780
3902
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
3781
3903
  DeprecationWarning,
3904
+ stacklevel=2,
3782
3905
  )
3783
3906
  response = await self._http_requests.patch(
3784
3907
  f"{self._settings_url}/pagination", settings.dict(by_alias=True), compress=compress
@@ -3965,6 +4088,84 @@ class AsyncIndex(_BaseIndex):
3965
4088
 
3966
4089
  return TaskInfo(**response.json())
3967
4090
 
4091
+ async def get_search_cutoff_ms(self) -> int | None:
4092
+ """Get search cutoff time in ms.
4093
+
4094
+ Returns:
4095
+
4096
+ Integer representing the search cutoff time in ms, or None.
4097
+
4098
+ Raises:
4099
+
4100
+ MeilisearchCommunicationError: If there was an error communicating with the server.
4101
+ MeilisearchApiError: If the Meilisearch API returned an error.
4102
+
4103
+ Examples:
4104
+
4105
+ >>> from meilisearch_async_client import AsyncClient
4106
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
4107
+ >>> index = client.index("movies")
4108
+ >>> search_cutoff_ms_settings = await index.get_search_cutoff_ms()
4109
+ """
4110
+ response = await self._http_requests.get(f"{self._settings_url}/search-cutoff-ms")
4111
+
4112
+ return response.json()
4113
+
4114
+ async def update_search_cutoff_ms(
4115
+ self, search_cutoff_ms: int, *, compress: bool = False
4116
+ ) -> TaskInfo:
4117
+ """Update the search cutoff for an index.
4118
+
4119
+ Args:
4120
+
4121
+ search_cutoff_ms: Integer value of the search cutoff time in ms.
4122
+ compress: If set to True the data will be sent in gzip format. Defaults to False.
4123
+
4124
+ Returns:
4125
+
4126
+ The details of the task status.
4127
+
4128
+ Raises:
4129
+
4130
+ MeilisearchCommunicationError: If there was an error communicating with the server.
4131
+ MeilisearchApiError: If the Meilisearch API returned an error.
4132
+
4133
+ Examples:
4134
+
4135
+ >>> from meilisearch_python_sdk import AsyncClient
4136
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
4137
+ >>> index = client.index("movies")
4138
+ >>> await index.update_search_cutoff_ms(100)
4139
+ """
4140
+ response = await self._http_requests.put(
4141
+ f"{self._settings_url}/search-cutoff-ms", search_cutoff_ms, compress=compress
4142
+ )
4143
+
4144
+ return TaskInfo(**response.json())
4145
+
4146
+ async def reset_search_cutoff_ms(self) -> TaskInfo:
4147
+ """Reset the search cutoff time to the default value.
4148
+
4149
+ Returns:
4150
+
4151
+ The details of the task status.
4152
+
4153
+ Raises:
4154
+
4155
+ MeilisearchCommunicationError: If there was an error communicating with the server.
4156
+ MeilisearchApiError: If the Meilisearch API returned an error.
4157
+
4158
+ Examples:
4159
+
4160
+ >>> from meilisearch_async_client import AsyncClient
4161
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
4162
+ >>> index = client.index("movies")
4163
+ >>> await index.reset_search_cutoff_ms()
4164
+ """
4165
+ response = await self._http_requests.delete(f"{self._settings_url}/search-cutoff-ms")
4166
+
4167
+ return TaskInfo(**response.json())
4168
+
3968
4169
  async def get_word_dictionary(self) -> list[str]:
3969
4170
  """Get word dictionary settings for the index.
3970
4171
 
@@ -4186,6 +4387,7 @@ class AsyncIndex(_BaseIndex):
4186
4387
  warn(
4187
4388
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
4188
4389
  DeprecationWarning,
4390
+ stacklevel=2,
4189
4391
  )
4190
4392
  payload[key] = {
4191
4393
  k: v for k, v in embedder.dict(by_alias=True).items() if v is not None
@@ -4197,7 +4399,8 @@ class AsyncIndex(_BaseIndex):
4197
4399
 
4198
4400
  return TaskInfo(**response.json())
4199
4401
 
4200
- async def reset_embedders(self) -> TaskInfo:
4402
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
4403
+ async def reset_embedders(self) -> TaskInfo: # pragma: no cover
4201
4404
  """Reset an index's embedders settings to the default value.
4202
4405
 
4203
4406
  Returns:
@@ -4696,6 +4899,7 @@ class Index(_BaseIndex):
4696
4899
  *,
4697
4900
  settings: MeilisearchSettings | None = None,
4698
4901
  wait: bool = True,
4902
+ timeout_in_ms: int | None = None,
4699
4903
  plugins: IndexPlugins | None = None,
4700
4904
  ) -> Index:
4701
4905
  """Creates a new index.
@@ -4717,6 +4921,9 @@ class Index(_BaseIndex):
4717
4921
  wait: If set to True and settings are being updated, the index will be returned after
4718
4922
  the settings update has completed. If False it will not wait for settings to complete.
4719
4923
  Default: True
4924
+ timeout_in_ms: Amount of time in milliseconds to wait before raising a
4925
+ MeilisearchTimeoutError. `None` can also be passed to wait indefinitely. Be aware that
4926
+ if the `None` option is used the wait time could be very long. Defaults to None.
4720
4927
  plugins: Optional plugins can be provided to extend functionality.
4721
4928
 
4722
4929
  Returns:
@@ -4742,7 +4949,7 @@ class Index(_BaseIndex):
4742
4949
  url = "indexes"
4743
4950
  http_request = HttpRequests(http_client)
4744
4951
  response = http_request.post(url, payload)
4745
- wait_for_task(http_client, response.json()["taskUid"], timeout_in_ms=None)
4952
+ wait_for_task(http_client, response.json()["taskUid"], timeout_in_ms=timeout_in_ms)
4746
4953
  index_response = http_request.get(f"{url}/{uid}")
4747
4954
  index_dict = index_response.json()
4748
4955
  index = cls(
@@ -4757,7 +4964,7 @@ class Index(_BaseIndex):
4757
4964
  if settings:
4758
4965
  settings_task = index.update_settings(settings)
4759
4966
  if wait:
4760
- wait_for_task(http_client, settings_task.task_uid, timeout_in_ms=None)
4967
+ wait_for_task(http_client, settings_task.task_uid, timeout_in_ms=timeout_in_ms)
4761
4968
 
4762
4969
  return index
4763
4970
 
@@ -4792,7 +4999,7 @@ class Index(_BaseIndex):
4792
4999
  limit: int = 20,
4793
5000
  filter: Filter | None = None,
4794
5001
  facets: list[str] | None = None,
4795
- attributes_to_retrieve: list[str] = ["*"],
5002
+ attributes_to_retrieve: list[str] | None = None,
4796
5003
  attributes_to_crop: list[str] | None = None,
4797
5004
  crop_length: int = 200,
4798
5005
  attributes_to_highlight: list[str] | None = None,
@@ -4950,7 +5157,7 @@ class Index(_BaseIndex):
4950
5157
  limit: int = 20,
4951
5158
  filter: Filter | None = None,
4952
5159
  facets: list[str] | None = None,
4953
- attributes_to_retrieve: list[str] = ["*"],
5160
+ attributes_to_retrieve: list[str] | None = None,
4954
5161
  attributes_to_crop: list[str] | None = None,
4955
5162
  crop_length: int = 200,
4956
5163
  attributes_to_highlight: list[str] | None = None,
@@ -5187,6 +5394,7 @@ class Index(_BaseIndex):
5187
5394
  primary_key: str | None = None,
5188
5395
  *,
5189
5396
  compress: bool = False,
5397
+ serializer: type[json.JSONEncoder] | None = None,
5190
5398
  ) -> TaskInfo:
5191
5399
  """Add documents to the index.
5192
5400
 
@@ -5196,6 +5404,8 @@ class Index(_BaseIndex):
5196
5404
  primary_key: The primary key of the documents. This will be ignored if already set.
5197
5405
  Defaults to None.
5198
5406
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5407
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5408
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5199
5409
 
5200
5410
  Returns:
5201
5411
 
@@ -5232,7 +5442,9 @@ class Index(_BaseIndex):
5232
5442
  if pre.get("document_result"):
5233
5443
  documents = pre["document_result"]
5234
5444
 
5235
- response = self._http_requests.post(url, documents, compress=compress)
5445
+ response = self._http_requests.post(
5446
+ url, documents, compress=compress, serializer=serializer
5447
+ )
5236
5448
  result = TaskInfo(**response.json())
5237
5449
  if self._post_add_documents_plugins:
5238
5450
  post = Index._run_plugins(self._post_add_documents_plugins, Event.POST, result=result)
@@ -5248,6 +5460,7 @@ class Index(_BaseIndex):
5248
5460
  batch_size: int = 1000,
5249
5461
  primary_key: str | None = None,
5250
5462
  compress: bool = False,
5463
+ serializer: type[json.JSONEncoder] | None = None,
5251
5464
  ) -> list[TaskInfo]:
5252
5465
  """Adds documents in batches to reduce RAM usage with indexing.
5253
5466
 
@@ -5259,6 +5472,8 @@ class Index(_BaseIndex):
5259
5472
  primary_key: The primary key of the documents. This will be ignored if already set.
5260
5473
  Defaults to None.
5261
5474
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5475
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5476
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5262
5477
 
5263
5478
  Returns:
5264
5479
 
@@ -5281,7 +5496,7 @@ class Index(_BaseIndex):
5281
5496
  >>> index.add_documents_in_batches(documents)
5282
5497
  """
5283
5498
  return [
5284
- self.add_documents(x, primary_key, compress=compress)
5499
+ self.add_documents(x, primary_key, compress=compress, serializer=serializer)
5285
5500
  for x in _batch(documents, batch_size)
5286
5501
  ]
5287
5502
 
@@ -5294,6 +5509,7 @@ class Index(_BaseIndex):
5294
5509
  csv_delimiter: str | None = None,
5295
5510
  combine_documents: bool = True,
5296
5511
  compress: bool = False,
5512
+ serializer: type[json.JSONEncoder] | None = None,
5297
5513
  ) -> list[TaskInfo]:
5298
5514
  """Load all json files from a directory and add the documents to the index.
5299
5515
 
@@ -5310,6 +5526,8 @@ class Index(_BaseIndex):
5310
5526
  combine_documents: If set to True this will combine the documents from all the files
5311
5527
  before indexing them. Defaults to True.
5312
5528
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5529
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5530
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5313
5531
 
5314
5532
  Returns:
5315
5533
 
@@ -5344,7 +5562,9 @@ class Index(_BaseIndex):
5344
5562
 
5345
5563
  combined = _combine_documents(all_documents)
5346
5564
 
5347
- response = self.add_documents(combined, primary_key, compress=compress)
5565
+ response = self.add_documents(
5566
+ combined, primary_key, compress=compress, serializer=serializer
5567
+ )
5348
5568
 
5349
5569
  return [response]
5350
5570
 
@@ -5352,7 +5572,11 @@ class Index(_BaseIndex):
5352
5572
  for path in directory.iterdir():
5353
5573
  if path.suffix == f".{document_type}":
5354
5574
  documents = _load_documents_from_file(path, csv_delimiter)
5355
- responses.append(self.add_documents(documents, primary_key, compress=compress))
5575
+ responses.append(
5576
+ self.add_documents(
5577
+ documents, primary_key, compress=compress, serializer=serializer
5578
+ )
5579
+ )
5356
5580
 
5357
5581
  _raise_on_no_documents(responses, document_type, directory_path)
5358
5582
 
@@ -5368,6 +5592,7 @@ class Index(_BaseIndex):
5368
5592
  csv_delimiter: str | None = None,
5369
5593
  combine_documents: bool = True,
5370
5594
  compress: bool = False,
5595
+ serializer: type[json.JSONEncoder] | None = None,
5371
5596
  ) -> list[TaskInfo]:
5372
5597
  """Load all json files from a directory and add the documents to the index in batches.
5373
5598
 
@@ -5386,6 +5611,8 @@ class Index(_BaseIndex):
5386
5611
  combine_documents: If set to True this will combine the documents from all the files
5387
5612
  before indexing them. Defaults to True.
5388
5613
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5614
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5615
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5389
5616
 
5390
5617
  Returns:
5391
5618
 
@@ -5421,7 +5648,11 @@ class Index(_BaseIndex):
5421
5648
  combined = _combine_documents(all_documents)
5422
5649
 
5423
5650
  return self.add_documents_in_batches(
5424
- combined, batch_size=batch_size, primary_key=primary_key, compress=compress
5651
+ combined,
5652
+ batch_size=batch_size,
5653
+ primary_key=primary_key,
5654
+ compress=compress,
5655
+ serializer=serializer,
5425
5656
  )
5426
5657
 
5427
5658
  responses: list[TaskInfo] = []
@@ -5430,7 +5661,11 @@ class Index(_BaseIndex):
5430
5661
  documents = _load_documents_from_file(path, csv_delimiter)
5431
5662
  responses.extend(
5432
5663
  self.add_documents_in_batches(
5433
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
5664
+ documents,
5665
+ batch_size=batch_size,
5666
+ primary_key=primary_key,
5667
+ compress=compress,
5668
+ serializer=serializer,
5434
5669
  )
5435
5670
  )
5436
5671
 
@@ -5439,7 +5674,12 @@ class Index(_BaseIndex):
5439
5674
  return responses
5440
5675
 
5441
5676
  def add_documents_from_file(
5442
- self, file_path: Path | str, primary_key: str | None = None, *, compress: bool = False
5677
+ self,
5678
+ file_path: Path | str,
5679
+ primary_key: str | None = None,
5680
+ *,
5681
+ compress: bool = False,
5682
+ serializer: type[json.JSONEncoder] | None = None,
5443
5683
  ) -> TaskInfo:
5444
5684
  """Add documents to the index from a json file.
5445
5685
 
@@ -5449,6 +5689,8 @@ class Index(_BaseIndex):
5449
5689
  primary_key: The primary key of the documents. This will be ignored if already set.
5450
5690
  Defaults to None.
5451
5691
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5692
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5693
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5452
5694
 
5453
5695
  Returns:
5454
5696
 
@@ -5472,7 +5714,9 @@ class Index(_BaseIndex):
5472
5714
  """
5473
5715
  documents = _load_documents_from_file(file_path)
5474
5716
 
5475
- return self.add_documents(documents, primary_key=primary_key, compress=compress)
5717
+ return self.add_documents(
5718
+ documents, primary_key=primary_key, compress=compress, serializer=serializer
5719
+ )
5476
5720
 
5477
5721
  def add_documents_from_file_in_batches(
5478
5722
  self,
@@ -5482,6 +5726,7 @@ class Index(_BaseIndex):
5482
5726
  primary_key: str | None = None,
5483
5727
  csv_delimiter: str | None = None,
5484
5728
  compress: bool = False,
5729
+ serializer: type[json.JSONEncoder] | None = None,
5485
5730
  ) -> list[TaskInfo]:
5486
5731
  """Adds documents form a json file in batches to reduce RAM usage with indexing.
5487
5732
 
@@ -5495,6 +5740,8 @@ class Index(_BaseIndex):
5495
5740
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
5496
5741
  can only be used if the file is a csv file. Defaults to comma.
5497
5742
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5743
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5744
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5498
5745
 
5499
5746
  Returns:
5500
5747
 
@@ -5519,7 +5766,11 @@ class Index(_BaseIndex):
5519
5766
  documents = _load_documents_from_file(file_path, csv_delimiter)
5520
5767
 
5521
5768
  return self.add_documents_in_batches(
5522
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
5769
+ documents,
5770
+ batch_size=batch_size,
5771
+ primary_key=primary_key,
5772
+ compress=compress,
5773
+ serializer=serializer,
5523
5774
  )
5524
5775
 
5525
5776
  def add_documents_from_raw_file(
@@ -5529,6 +5780,7 @@ class Index(_BaseIndex):
5529
5780
  *,
5530
5781
  csv_delimiter: str | None = None,
5531
5782
  compress: bool = False,
5783
+ serializer: type[json.JSONEncoder] | None = None,
5532
5784
  ) -> TaskInfo:
5533
5785
  """Directly send csv or ndjson files to Meilisearch without pre-processing.
5534
5786
 
@@ -5544,6 +5796,8 @@ class Index(_BaseIndex):
5544
5796
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
5545
5797
  can only be used if the file is a csv file. Defaults to comma.
5546
5798
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5799
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5800
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5547
5801
 
5548
5802
  Returns:
5549
5803
 
@@ -5601,7 +5855,7 @@ class Index(_BaseIndex):
5601
5855
  data = f.read()
5602
5856
 
5603
5857
  response = self._http_requests.post(
5604
- url, body=data, content_type=content_type, compress=compress
5858
+ url, body=data, content_type=content_type, compress=compress, serializer=serializer
5605
5859
  )
5606
5860
 
5607
5861
  return TaskInfo(**response.json())
@@ -5612,6 +5866,7 @@ class Index(_BaseIndex):
5612
5866
  primary_key: str | None = None,
5613
5867
  *,
5614
5868
  compress: bool = False,
5869
+ serializer: type[json.JSONEncoder] | None = None,
5615
5870
  ) -> TaskInfo:
5616
5871
  """Update documents in the index.
5617
5872
 
@@ -5621,6 +5876,8 @@ class Index(_BaseIndex):
5621
5876
  primary_key: The primary key of the documents. This will be ignored if already set.
5622
5877
  Defaults to None.
5623
5878
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5879
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5880
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5624
5881
 
5625
5882
  Returns:
5626
5883
 
@@ -5657,7 +5914,7 @@ class Index(_BaseIndex):
5657
5914
  if pre.get("document_result"):
5658
5915
  documents = pre["document_result"]
5659
5916
 
5660
- response = self._http_requests.put(url, documents, compress=compress)
5917
+ response = self._http_requests.put(url, documents, compress=compress, serializer=serializer)
5661
5918
  result = TaskInfo(**response.json())
5662
5919
  if self._post_update_documents_plugins:
5663
5920
  post = Index._run_plugins(
@@ -5675,6 +5932,7 @@ class Index(_BaseIndex):
5675
5932
  batch_size: int = 1000,
5676
5933
  primary_key: str | None = None,
5677
5934
  compress: bool = False,
5935
+ serializer: type[json.JSONEncoder] | None = None,
5678
5936
  ) -> list[TaskInfo]:
5679
5937
  """Update documents in batches to reduce RAM usage with indexing.
5680
5938
 
@@ -5688,6 +5946,8 @@ class Index(_BaseIndex):
5688
5946
  primary_key: The primary key of the documents. This will be ignored if already set.
5689
5947
  Defaults to None.
5690
5948
  compress: If set to True the data will be sent in gzip format. Defaults to False.
5949
+ serializer: A custom JSONEncode to handle serializing fields that the build in
5950
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5691
5951
 
5692
5952
  Returns:
5693
5953
 
@@ -5710,7 +5970,7 @@ class Index(_BaseIndex):
5710
5970
  >>> index.update_documents_in_batches(documents)
5711
5971
  """
5712
5972
  return [
5713
- self.update_documents(x, primary_key, compress=compress)
5973
+ self.update_documents(x, primary_key, compress=compress, serializer=serializer)
5714
5974
  for x in _batch(documents, batch_size)
5715
5975
  ]
5716
5976
 
@@ -5723,6 +5983,7 @@ class Index(_BaseIndex):
5723
5983
  csv_delimiter: str | None = None,
5724
5984
  combine_documents: bool = True,
5725
5985
  compress: bool = False,
5986
+ serializer: type[json.JSONEncoder] | None = None,
5726
5987
  ) -> list[TaskInfo]:
5727
5988
  """Load all json files from a directory and update the documents.
5728
5989
 
@@ -5739,6 +6000,8 @@ class Index(_BaseIndex):
5739
6000
  combine_documents: If set to True this will combine the documents from all the files
5740
6001
  before indexing them. Defaults to True.
5741
6002
  compress: If set to True the data will be sent in gzip format. Defaults to False.
6003
+ serializer: A custom JSONEncode to handle serializing fields that the build in
6004
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5742
6005
 
5743
6006
  Returns:
5744
6007
 
@@ -5773,14 +6036,20 @@ class Index(_BaseIndex):
5773
6036
 
5774
6037
  combined = _combine_documents(all_documents)
5775
6038
 
5776
- response = self.update_documents(combined, primary_key, compress=compress)
6039
+ response = self.update_documents(
6040
+ combined, primary_key, compress=compress, serializer=serializer
6041
+ )
5777
6042
  return [response]
5778
6043
 
5779
6044
  responses = []
5780
6045
  for path in directory.iterdir():
5781
6046
  if path.suffix == f".{document_type}":
5782
6047
  documents = _load_documents_from_file(path, csv_delimiter)
5783
- responses.append(self.update_documents(documents, primary_key, compress=compress))
6048
+ responses.append(
6049
+ self.update_documents(
6050
+ documents, primary_key, compress=compress, serializer=serializer
6051
+ )
6052
+ )
5784
6053
 
5785
6054
  _raise_on_no_documents(responses, document_type, directory_path)
5786
6055
 
@@ -5796,6 +6065,7 @@ class Index(_BaseIndex):
5796
6065
  csv_delimiter: str | None = None,
5797
6066
  combine_documents: bool = True,
5798
6067
  compress: bool = False,
6068
+ serializer: type[json.JSONEncoder] | None = None,
5799
6069
  ) -> list[TaskInfo]:
5800
6070
  """Load all json files from a directory and update the documents.
5801
6071
 
@@ -5814,6 +6084,8 @@ class Index(_BaseIndex):
5814
6084
  combine_documents: If set to True this will combine the documents from all the files
5815
6085
  before indexing them. Defaults to True.
5816
6086
  compress: If set to True the data will be sent in gzip format. Defaults to False.
6087
+ serializer: A custom JSONEncode to handle serializing fields that the build in
6088
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5817
6089
 
5818
6090
  Returns:
5819
6091
 
@@ -5849,7 +6121,11 @@ class Index(_BaseIndex):
5849
6121
  combined = _combine_documents(all_documents)
5850
6122
 
5851
6123
  return self.update_documents_in_batches(
5852
- combined, batch_size=batch_size, primary_key=primary_key, compress=compress
6124
+ combined,
6125
+ batch_size=batch_size,
6126
+ primary_key=primary_key,
6127
+ compress=compress,
6128
+ serializer=serializer,
5853
6129
  )
5854
6130
 
5855
6131
  responses: list[TaskInfo] = []
@@ -5859,7 +6135,11 @@ class Index(_BaseIndex):
5859
6135
  documents = _load_documents_from_file(path, csv_delimiter)
5860
6136
  responses.extend(
5861
6137
  self.update_documents_in_batches(
5862
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
6138
+ documents,
6139
+ batch_size=batch_size,
6140
+ primary_key=primary_key,
6141
+ compress=compress,
6142
+ serializer=serializer,
5863
6143
  )
5864
6144
  )
5865
6145
 
@@ -5874,6 +6154,7 @@ class Index(_BaseIndex):
5874
6154
  csv_delimiter: str | None = None,
5875
6155
  *,
5876
6156
  compress: bool = False,
6157
+ serializer: type[json.JSONEncoder] | None = None,
5877
6158
  ) -> TaskInfo:
5878
6159
  """Add documents in the index from a json file.
5879
6160
 
@@ -5885,6 +6166,8 @@ class Index(_BaseIndex):
5885
6166
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
5886
6167
  can only be used if the file is a csv file. Defaults to comma.
5887
6168
  compress: If set to True the data will be sent in gzip format. Defaults to False.
6169
+ serializer: A custom JSONEncode to handle serializing fields that the build in
6170
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5888
6171
 
5889
6172
  Returns:
5890
6173
 
@@ -5906,7 +6189,9 @@ class Index(_BaseIndex):
5906
6189
  """
5907
6190
  documents = _load_documents_from_file(file_path, csv_delimiter)
5908
6191
 
5909
- return self.update_documents(documents, primary_key=primary_key, compress=compress)
6192
+ return self.update_documents(
6193
+ documents, primary_key=primary_key, compress=compress, serializer=serializer
6194
+ )
5910
6195
 
5911
6196
  def update_documents_from_file_in_batches(
5912
6197
  self,
@@ -5915,6 +6200,7 @@ class Index(_BaseIndex):
5915
6200
  batch_size: int = 1000,
5916
6201
  primary_key: str | None = None,
5917
6202
  compress: bool = False,
6203
+ serializer: type[json.JSONEncoder] | None = None,
5918
6204
  ) -> list[TaskInfo]:
5919
6205
  """Updates documents form a json file in batches to reduce RAM usage with indexing.
5920
6206
 
@@ -5926,6 +6212,8 @@ class Index(_BaseIndex):
5926
6212
  primary_key: The primary key of the documents. This will be ignored if already set.
5927
6213
  Defaults to None.
5928
6214
  compress: If set to True the data will be sent in gzip format. Defaults to False.
6215
+ serializer: A custom JSONEncode to handle serializing fields that the build in
6216
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5929
6217
 
5930
6218
  Returns:
5931
6219
 
@@ -5948,7 +6236,11 @@ class Index(_BaseIndex):
5948
6236
  documents = _load_documents_from_file(file_path)
5949
6237
 
5950
6238
  return self.update_documents_in_batches(
5951
- documents, batch_size=batch_size, primary_key=primary_key, compress=compress
6239
+ documents,
6240
+ batch_size=batch_size,
6241
+ primary_key=primary_key,
6242
+ compress=compress,
6243
+ serializer=serializer,
5952
6244
  )
5953
6245
 
5954
6246
  def update_documents_from_raw_file(
@@ -5958,6 +6250,7 @@ class Index(_BaseIndex):
5958
6250
  csv_delimiter: str | None = None,
5959
6251
  *,
5960
6252
  compress: bool = False,
6253
+ serializer: type[json.JSONEncoder] | None = None,
5961
6254
  ) -> TaskInfo:
5962
6255
  """Directly send csv or ndjson files to Meilisearch without pre-processing.
5963
6256
 
@@ -5973,6 +6266,8 @@ class Index(_BaseIndex):
5973
6266
  csv_delimiter: A single ASCII character to specify the delimiter for csv files. This
5974
6267
  can only be used if the file is a csv file. Defaults to comma.
5975
6268
  compress: If set to True the data will be sent in gzip format. Defaults to False.
6269
+ serializer: A custom JSONEncode to handle serializing fields that the build in
6270
+ json.dumps cannot handle, for example UUID and datetime. Defaults to None.
5976
6271
 
5977
6272
  Returns:
5978
6273
 
@@ -6030,7 +6325,7 @@ class Index(_BaseIndex):
6030
6325
  data = f.read()
6031
6326
 
6032
6327
  response = self._http_requests.put(
6033
- url, body=data, content_type=content_type, compress=compress
6328
+ url, body=data, content_type=content_type, compress=compress, serializer=serializer
6034
6329
  )
6035
6330
 
6036
6331
  return TaskInfo(**response.json())
@@ -6239,7 +6534,10 @@ class Index(_BaseIndex):
6239
6534
  settings = MeilisearchSettings(**response_json)
6240
6535
 
6241
6536
  if response_json.get("embedders"):
6242
- settings.embedders = _embedder_json_to_settings_model(response_json["embedders"])
6537
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
6538
+ settings.embedders = _embedder_json_to_settings_model( # pragma: no cover
6539
+ response_json["embedders"]
6540
+ )
6243
6541
 
6244
6542
  return settings
6245
6543
 
@@ -6293,6 +6591,7 @@ class Index(_BaseIndex):
6293
6591
  warn(
6294
6592
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
6295
6593
  DeprecationWarning,
6594
+ stacklevel=2,
6296
6595
  )
6297
6596
  body_dict = {k: v for k, v in body.dict(by_alias=True).items() if v is not None} # type: ignore[attr-defined]
6298
6597
 
@@ -6432,7 +6731,7 @@ class Index(_BaseIndex):
6432
6731
  response = self._http_requests.get(f"{self._settings_url}/distinct-attribute")
6433
6732
 
6434
6733
  if not response.json():
6435
- None
6734
+ return None
6436
6735
 
6437
6736
  return response.json()
6438
6737
 
@@ -7019,6 +7318,7 @@ class Index(_BaseIndex):
7019
7318
  warn(
7020
7319
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
7021
7320
  DeprecationWarning,
7321
+ stacklevel=2,
7022
7322
  )
7023
7323
  response = self._http_requests.patch(
7024
7324
  f"{self._settings_url}/typo-tolerance",
@@ -7108,6 +7408,7 @@ class Index(_BaseIndex):
7108
7408
  warn(
7109
7409
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
7110
7410
  DeprecationWarning,
7411
+ stacklevel=2,
7111
7412
  )
7112
7413
  response = self._http_requests.patch(
7113
7414
  f"{self._settings_url}/faceting", faceting.dict(by_alias=True), compress=compress
@@ -7196,6 +7497,7 @@ class Index(_BaseIndex):
7196
7497
  warn(
7197
7498
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
7198
7499
  DeprecationWarning,
7500
+ stacklevel=2,
7199
7501
  )
7200
7502
  response = self._http_requests.patch(
7201
7503
  f"{self._settings_url}/pagination", settings.dict(by_alias=True), compress=compress
@@ -7382,6 +7684,82 @@ class Index(_BaseIndex):
7382
7684
 
7383
7685
  return TaskInfo(**response.json())
7384
7686
 
7687
+ def get_search_cutoff_ms(self) -> int | None:
7688
+ """Get search cutoff time in ms.
7689
+
7690
+ Returns:
7691
+
7692
+ Integer representing the search cutoff time in ms, or None.
7693
+
7694
+ Raises:
7695
+
7696
+ MeilisearchCommunicationError: If there was an error communicating with the server.
7697
+ MeilisearchApiError: If the Meilisearch API returned an error.
7698
+
7699
+ Examples:
7700
+
7701
+ >>> from meilisearch_async_client import Client
7702
+ >>> client = Client("http://localhost.com", "masterKey")
7703
+ >>> index = client.index("movies")
7704
+ >>> search_cutoff_ms_settings = index.get_search_cutoff_ms()
7705
+ """
7706
+ response = self._http_requests.get(f"{self._settings_url}/search-cutoff-ms")
7707
+
7708
+ return response.json()
7709
+
7710
+ def update_search_cutoff_ms(self, search_cutoff_ms: int, *, compress: bool = False) -> TaskInfo:
7711
+ """Update the search cutoff for an index.
7712
+
7713
+ Args:
7714
+
7715
+ search_cutoff_ms: Integer value of the search cutoff time in ms.
7716
+ compress: If set to True the data will be sent in gzip format. Defaults to False.
7717
+
7718
+ Returns:
7719
+
7720
+ Task to track the action.
7721
+
7722
+ Raises:
7723
+
7724
+ MeilisearchCommunicationError: If there was an error communicating with the server.
7725
+ MeilisearchApiError: If the Meilisearch API returned an error.
7726
+
7727
+ Examples:
7728
+
7729
+ >>> from meilisearch_python_sdk import Client
7730
+ >>> client = Client("http://localhost.com", "masterKey")
7731
+ >>> index = client.index("movies")
7732
+ >>> index.update_search_cutoff_ms(100)
7733
+ """
7734
+ response = self._http_requests.put(
7735
+ f"{self._settings_url}/search-cutoff-ms", search_cutoff_ms, compress=compress
7736
+ )
7737
+
7738
+ return TaskInfo(**response.json())
7739
+
7740
+ def reset_search_cutoff_ms(self) -> TaskInfo:
7741
+ """Reset the search cutoff time to the default value.
7742
+
7743
+ Returns:
7744
+
7745
+ The details of the task status.
7746
+
7747
+ Raises:
7748
+
7749
+ MeilisearchCommunicationError: If there was an error communicating with the server.
7750
+ MeilisearchApiError: If the Meilisearch API returned an error.
7751
+
7752
+ Examples:
7753
+
7754
+ >>> from meilisearch_async_client import Client
7755
+ >>> client = Client("http://localhost.com", "masterKey")
7756
+ >>> index = client.index("movies")
7757
+ >>> index.reset_search_cutoff_ms()
7758
+ """
7759
+ response = self._http_requests.delete(f"{self._settings_url}/search-cutoff-ms")
7760
+
7761
+ return TaskInfo(**response.json())
7762
+
7385
7763
  def get_word_dictionary(self) -> list[str]:
7386
7764
  """Get word dictionary settings for the index.
7387
7765
 
@@ -7599,6 +7977,7 @@ class Index(_BaseIndex):
7599
7977
  warn(
7600
7978
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
7601
7979
  DeprecationWarning,
7980
+ stacklevel=2,
7602
7981
  )
7603
7982
  payload[key] = {
7604
7983
  k: v for k, v in embedder.dict(by_alias=True).items() if v is not None
@@ -7610,7 +7989,8 @@ class Index(_BaseIndex):
7610
7989
 
7611
7990
  return TaskInfo(**response.json())
7612
7991
 
7613
- def reset_embedders(self) -> TaskInfo:
7992
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
7993
+ def reset_embedders(self) -> TaskInfo: # pragma: no cover
7614
7994
  """Reset an index's embedders settings to the default value.
7615
7995
 
7616
7996
  Returns:
@@ -7797,7 +8177,7 @@ def _process_search_parameters(
7797
8177
  limit: int = 20,
7798
8178
  filter: Filter | None = None,
7799
8179
  facets: list[str] | None = None,
7800
- attributes_to_retrieve: list[str] = ["*"],
8180
+ attributes_to_retrieve: list[str] | None = None,
7801
8181
  attributes_to_crop: list[str] | None = None,
7802
8182
  crop_length: int = 200,
7803
8183
  attributes_to_highlight: list[str] | None = None,
@@ -7815,6 +8195,9 @@ def _process_search_parameters(
7815
8195
  vector: list[float] | None = None,
7816
8196
  hybrid: Hybrid | None = None,
7817
8197
  ) -> JsonDict:
8198
+ if attributes_to_retrieve is None:
8199
+ attributes_to_retrieve = ["*"]
8200
+
7818
8201
  body: JsonDict = {
7819
8202
  "q": q,
7820
8203
  "offset": offset,
@@ -7856,6 +8239,7 @@ def _process_search_parameters(
7856
8239
  warn(
7857
8240
  "The use of Pydantic less than version 2 is depreciated and will be removed in a future release",
7858
8241
  DeprecationWarning,
8242
+ stacklevel=2,
7859
8243
  )
7860
8244
  body["hybrid"] = hybrid.dict(by_alias=True) # type: ignore[attr-defined]
7861
8245
 
@@ -7866,34 +8250,58 @@ def _build_encoded_url(base_url: str, params: JsonMapping) -> str:
7866
8250
  return f"{base_url}?{urlencode(params)}"
7867
8251
 
7868
8252
 
7869
- def _embedder_json_to_embedders_model(embedder_json: JsonDict | None) -> Embedders | None:
8253
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
8254
+ def _embedder_json_to_embedders_model( # pragma: no cover
8255
+ embedder_json: JsonDict | None,
8256
+ ) -> Embedders | None:
7870
8257
  if not embedder_json: # pragma: no cover
7871
8258
  return None
7872
8259
 
7873
- embedders: dict[str, OpenAiEmbedder | HuggingFaceEmbedder | UserProvidedEmbedder] = {}
8260
+ embedders: dict[
8261
+ str,
8262
+ OpenAiEmbedder | HuggingFaceEmbedder | OllamaEmbedder | RestEmbedder | UserProvidedEmbedder,
8263
+ ] = {}
7874
8264
  for k, v in embedder_json.items():
7875
8265
  if v.get("source") == "openAi":
7876
8266
  embedders[k] = OpenAiEmbedder(**v)
7877
8267
  elif v.get("source") == "huggingFace":
7878
8268
  embedders[k] = HuggingFaceEmbedder(**v)
8269
+ elif v.get("source") == "ollama":
8270
+ embedders[k] = OllamaEmbedder(**v)
8271
+ elif v.get("source") == "rest":
8272
+ embedders[k] = RestEmbedder(**v)
7879
8273
  else:
7880
8274
  embedders[k] = UserProvidedEmbedder(**v)
7881
8275
 
7882
8276
  return Embedders(embedders=embedders)
7883
8277
 
7884
8278
 
7885
- def _embedder_json_to_settings_model(
8279
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
8280
+ def _embedder_json_to_settings_model( # pragma: no cover
7886
8281
  embedder_json: JsonDict | None,
7887
- ) -> dict[str, OpenAiEmbedder | HuggingFaceEmbedder | UserProvidedEmbedder] | None:
8282
+ ) -> (
8283
+ dict[
8284
+ str,
8285
+ OpenAiEmbedder | HuggingFaceEmbedder | OllamaEmbedder | RestEmbedder | UserProvidedEmbedder,
8286
+ ]
8287
+ | None
8288
+ ):
7888
8289
  if not embedder_json: # pragma: no cover
7889
8290
  return None
7890
8291
 
7891
- embedders: dict[str, OpenAiEmbedder | HuggingFaceEmbedder | UserProvidedEmbedder] = {}
8292
+ embedders: dict[
8293
+ str,
8294
+ OpenAiEmbedder | HuggingFaceEmbedder | OllamaEmbedder | RestEmbedder | UserProvidedEmbedder,
8295
+ ] = {}
7892
8296
  for k, v in embedder_json.items():
7893
8297
  if v.get("source") == "openAi":
7894
8298
  embedders[k] = OpenAiEmbedder(**v)
7895
8299
  elif v.get("source") == "huggingFace":
7896
8300
  embedders[k] = HuggingFaceEmbedder(**v)
8301
+ elif v.get("source") == "ollama":
8302
+ embedders[k] = OllamaEmbedder(**v)
8303
+ elif v.get("source") == "rest":
8304
+ embedders[k] = RestEmbedder(**v)
7897
8305
  else:
7898
8306
  embedders[k] = UserProvidedEmbedder(**v)
7899
8307