morphik 0.2.3__py3-none-any.whl → 0.2.5__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.
morphik/__init__.py CHANGED
@@ -12,4 +12,4 @@ __all__ = [
12
12
  "Document",
13
13
  ]
14
14
 
15
- __version__ = "0.2.2"
15
+ __version__ = "0.2.5"
morphik/_internal.py CHANGED
@@ -253,6 +253,7 @@ class _MorphikClientLogic:
253
253
  end_user_id: Optional[str],
254
254
  chat_id: Optional[str] = None,
255
255
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
256
+ llm_config: Optional[Dict[str, Any]] = None,
256
257
  ) -> Dict[str, Any]:
257
258
  """Prepare request for query endpoint"""
258
259
  payload = {
@@ -274,6 +275,8 @@ class _MorphikClientLogic:
274
275
  payload["end_user_id"] = end_user_id
275
276
  if chat_id:
276
277
  payload["chat_id"] = chat_id
278
+ if llm_config:
279
+ payload["llm_config"] = llm_config
277
280
 
278
281
  # Add schema to payload if provided
279
282
  if schema:
@@ -300,6 +303,7 @@ class _MorphikClientLogic:
300
303
  use_colpali: bool,
301
304
  folder_name: Optional[Union[str, List[str]]],
302
305
  end_user_id: Optional[str],
306
+ padding: int = 0,
303
307
  ) -> Dict[str, Any]:
304
308
  """Prepare request for retrieve_chunks endpoint"""
305
309
  request = {
@@ -313,6 +317,8 @@ class _MorphikClientLogic:
313
317
  request["folder_name"] = folder_name
314
318
  if end_user_id:
315
319
  request["end_user_id"] = end_user_id
320
+ if padding > 0:
321
+ request["padding"] = padding
316
322
  return request
317
323
 
318
324
  def _prepare_retrieve_docs_request(
morphik/async_.py CHANGED
@@ -288,6 +288,7 @@ class AsyncFolder:
288
288
  min_score: float = 0.0,
289
289
  use_colpali: bool = True,
290
290
  additional_folders: Optional[List[str]] = None,
291
+ padding: int = 0,
291
292
  ) -> List[FinalChunkResult]:
292
293
  """
293
294
  Retrieve relevant chunks within this folder.
@@ -299,13 +300,14 @@ class AsyncFolder:
299
300
  min_score: Minimum similarity threshold (default: 0.0)
300
301
  use_colpali: Whether to use ColPali-style embedding model
301
302
  additional_folders: Optional list of additional folder names to further scope operations
303
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
302
304
 
303
305
  Returns:
304
306
  List[FinalChunkResult]: List of relevant chunks
305
307
  """
306
308
  effective_folder = self._merge_folders(additional_folders)
307
309
  payload = self._client._logic._prepare_retrieve_chunks_request(
308
- query, filters, k, min_score, use_colpali, effective_folder, None
310
+ query, filters, k, min_score, use_colpali, effective_folder, None, padding
309
311
  )
310
312
  response = await self._client._request("POST", "retrieve/chunks", data=payload)
311
313
  return self._client._logic._parse_chunk_result_list_response(response)
@@ -356,6 +358,7 @@ class AsyncFolder:
356
358
  additional_folders: Optional[List[str]] = None,
357
359
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
358
360
  chat_id: Optional[str] = None,
361
+ llm_config: Optional[Dict[str, Any]] = None,
359
362
  ) -> CompletionResponse:
360
363
  """
361
364
  Generate completion using relevant chunks as context within this folder.
@@ -395,6 +398,7 @@ class AsyncFolder:
395
398
  None,
396
399
  chat_id,
397
400
  schema,
401
+ llm_config,
398
402
  )
399
403
 
400
404
  # Add schema to payload if provided
@@ -824,6 +828,7 @@ class AsyncUserScope:
824
828
  min_score: float = 0.0,
825
829
  use_colpali: bool = True,
826
830
  additional_folders: Optional[List[str]] = None,
831
+ padding: int = 0,
827
832
  ) -> List[FinalChunkResult]:
828
833
  """
829
834
  Retrieve relevant chunks as this end user.
@@ -835,13 +840,14 @@ class AsyncUserScope:
835
840
  min_score: Minimum similarity threshold (default: 0.0)
836
841
  use_colpali: Whether to use ColPali-style embedding model
837
842
  additional_folders: Optional list of additional folder names to further scope operations
843
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
838
844
 
839
845
  Returns:
840
846
  List[FinalChunkResult]: List of relevant chunks
841
847
  """
842
848
  effective_folder = self._merge_folders(additional_folders)
843
849
  payload = self._client._logic._prepare_retrieve_chunks_request(
844
- query, filters, k, min_score, use_colpali, effective_folder, self._end_user_id
850
+ query, filters, k, min_score, use_colpali, effective_folder, self._end_user_id, padding
845
851
  )
846
852
  response = await self._client._request("POST", "retrieve/chunks", data=payload)
847
853
  return self._client._logic._parse_chunk_result_list_response(response)
@@ -892,6 +898,7 @@ class AsyncUserScope:
892
898
  additional_folders: Optional[List[str]] = None,
893
899
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
894
900
  chat_id: Optional[str] = None,
901
+ llm_config: Optional[Dict[str, Any]] = None,
895
902
  ) -> CompletionResponse:
896
903
  """
897
904
  Generate completion using relevant chunks as context, scoped to the end user.
@@ -931,6 +938,7 @@ class AsyncUserScope:
931
938
  self._end_user_id,
932
939
  chat_id,
933
940
  schema,
941
+ llm_config,
934
942
  )
935
943
 
936
944
  # Add schema to payload if provided
@@ -1474,6 +1482,7 @@ class AsyncMorphik:
1474
1482
  min_score: float = 0.0,
1475
1483
  use_colpali: bool = True,
1476
1484
  folder_name: Optional[Union[str, List[str]]] = None,
1485
+ padding: int = 0,
1477
1486
  ) -> List[FinalChunkResult]:
1478
1487
  """
1479
1488
  Search for relevant chunks.
@@ -1485,6 +1494,7 @@ class AsyncMorphik:
1485
1494
  min_score: Minimum similarity threshold (default: 0.0)
1486
1495
  use_colpali: Whether to use ColPali-style embedding model to retrieve chunks
1487
1496
  (only works for documents ingested with `use_colpali=True`)
1497
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
1488
1498
  Returns:
1489
1499
  List[FinalChunkResult]
1490
1500
 
@@ -1492,13 +1502,14 @@ class AsyncMorphik:
1492
1502
  ```python
1493
1503
  chunks = await db.retrieve_chunks(
1494
1504
  "What are the key findings?",
1495
- filters={"department": "research"}
1505
+ filters={"department": "research"},
1506
+ padding=2 # Get 2 pages before and after each matched page
1496
1507
  )
1497
1508
  ```
1498
1509
  """
1499
1510
  effective_folder = folder_name if folder_name is not None else None
1500
1511
  payload = self._logic._prepare_retrieve_chunks_request(
1501
- query, filters, k, min_score, use_colpali, effective_folder, None
1512
+ query, filters, k, min_score, use_colpali, effective_folder, None, padding
1502
1513
  )
1503
1514
  response = await self._request("POST", "retrieve/chunks", data=payload)
1504
1515
  return self._logic._parse_chunk_result_list_response(response)
@@ -1556,6 +1567,7 @@ class AsyncMorphik:
1556
1567
  folder_name: Optional[Union[str, List[str]]] = None,
1557
1568
  chat_id: Optional[str] = None,
1558
1569
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
1570
+ llm_config: Optional[Dict[str, Any]] = None,
1559
1571
  ) -> CompletionResponse:
1560
1572
  """
1561
1573
  Generate completion using relevant chunks as context.
@@ -1575,6 +1587,7 @@ class AsyncMorphik:
1575
1587
  prompt_overrides: Optional customizations for entity extraction, resolution, and query prompts
1576
1588
  Either a QueryPromptOverrides object or a dictionary with the same structure
1577
1589
  schema: Optional schema for structured output, can be a Pydantic model or a JSON schema dict
1590
+ llm_config: Optional LiteLLM-compatible model configuration (e.g., model name, API key, base URL)
1578
1591
  Returns:
1579
1592
  CompletionResponse
1580
1593
 
@@ -1662,6 +1675,7 @@ class AsyncMorphik:
1662
1675
  None,
1663
1676
  chat_id,
1664
1677
  schema,
1678
+ llm_config,
1665
1679
  )
1666
1680
 
1667
1681
  # Add schema to payload if provided
@@ -2568,7 +2582,7 @@ class AsyncMorphik:
2568
2582
  self,
2569
2583
  graph_name: str,
2570
2584
  timeout_seconds: int = 300,
2571
- check_interval_seconds: int = 5,
2585
+ check_interval_seconds: int = 2,
2572
2586
  ) -> Graph:
2573
2587
  """Block until the specified graph finishes processing (async).
2574
2588
 
@@ -2655,6 +2669,30 @@ class AsyncMorphik:
2655
2669
  params = {"run_id": run_id} if run_id else None
2656
2670
  return await self._request("GET", f"graph/workflow/{workflow_id}/status", params=params)
2657
2671
 
2672
+ async def get_graph_status(
2673
+ self, graph_name: str, folder_name: Optional[str] = None, end_user_id: Optional[str] = None
2674
+ ) -> Dict[str, Any]:
2675
+ """Get the current status of a graph with pipeline stage information.
2676
+
2677
+ This is a lightweight endpoint that checks local database status and
2678
+ optionally syncs with external workflow status if the graph is processing.
2679
+
2680
+ Args:
2681
+ graph_name: Name of the graph to check
2682
+ folder_name: Optional folder name for scoping
2683
+ end_user_id: Optional end user ID for scoping
2684
+
2685
+ Returns:
2686
+ Dict containing status, pipeline_stage (if processing), and other metadata
2687
+ """
2688
+ params = {}
2689
+ if folder_name:
2690
+ params["folder_name"] = folder_name
2691
+ if end_user_id:
2692
+ params["end_user_id"] = end_user_id
2693
+
2694
+ return await self._request("GET", f"graph/{graph_name}/status", params=params if params else None)
2695
+
2658
2696
  # ------------------------------------------------------------------
2659
2697
  # Document download helpers ----------------------------------------
2660
2698
  # ------------------------------------------------------------------
morphik/models.py CHANGED
@@ -317,7 +317,7 @@ class Graph(BaseModel):
317
317
  def error(self) -> str | None:
318
318
  return self.system_metadata.get("error") if self.system_metadata else None
319
319
 
320
- def wait_for_completion(self, timeout_seconds: int = 300, check_interval_seconds: int = 5) -> "Graph":
320
+ def wait_for_completion(self, timeout_seconds: int = 300, check_interval_seconds: int = 2) -> "Graph":
321
321
  """Poll the server until the graph processing is finished."""
322
322
  import time
323
323
 
morphik/sync.py CHANGED
@@ -289,6 +289,7 @@ class Folder:
289
289
  min_score: float = 0.0,
290
290
  use_colpali: bool = True,
291
291
  additional_folders: Optional[List[str]] = None,
292
+ padding: int = 0,
292
293
  ) -> List[FinalChunkResult]:
293
294
  """
294
295
  Retrieve relevant chunks within this folder.
@@ -300,21 +301,16 @@ class Folder:
300
301
  min_score: Minimum similarity threshold (default: 0.0)
301
302
  use_colpali: Whether to use ColPali-style embedding model
302
303
  additional_folders: Optional list of extra folders to include in the scope
304
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
303
305
 
304
306
  Returns:
305
307
  List[FinalChunkResult]: List of relevant chunks
306
308
  """
307
309
  effective_folder = self._merge_folders(additional_folders)
308
- request = {
309
- "query": query,
310
- "filters": filters,
311
- "k": k,
312
- "min_score": min_score,
313
- "use_colpali": use_colpali,
314
- "folder_name": effective_folder,
315
- }
316
-
317
- response = self._client._request("POST", "retrieve/chunks", request)
310
+ payload = self._client._logic._prepare_retrieve_chunks_request(
311
+ query, filters, k, min_score, use_colpali, effective_folder, None, padding
312
+ )
313
+ response = self._client._request("POST", "retrieve/chunks", payload)
318
314
  return self._client._logic._parse_chunk_result_list_response(response)
319
315
 
320
316
  def retrieve_docs(
@@ -369,6 +365,7 @@ class Folder:
369
365
  additional_folders: Optional[List[str]] = None,
370
366
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
371
367
  chat_id: Optional[str] = None,
368
+ llm_config: Optional[Dict[str, Any]] = None,
372
369
  ) -> CompletionResponse:
373
370
  """
374
371
  Generate completion using relevant chunks as context within this folder.
@@ -408,6 +405,7 @@ class Folder:
408
405
  None, # end_user_id not supported at this level
409
406
  chat_id,
410
407
  schema,
408
+ llm_config,
411
409
  )
412
410
 
413
411
  # Add schema to payload if provided
@@ -862,6 +860,7 @@ class UserScope:
862
860
  min_score: float = 0.0,
863
861
  use_colpali: bool = True,
864
862
  additional_folders: Optional[List[str]] = None,
863
+ padding: int = 0,
865
864
  ) -> List[FinalChunkResult]:
866
865
  """
867
866
  Retrieve relevant chunks as this end user.
@@ -873,26 +872,16 @@ class UserScope:
873
872
  min_score: Minimum similarity threshold (default: 0.0)
874
873
  use_colpali: Whether to use ColPali-style embedding model
875
874
  additional_folders: Optional list of extra folders to include in the scope
875
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
876
876
 
877
877
  Returns:
878
878
  List[FinalChunkResult]: List of relevant chunks
879
879
  """
880
880
  effective_folder = self._merge_folders(additional_folders)
881
- request = {
882
- "query": query,
883
- "filters": filters,
884
- "k": k,
885
- "min_score": min_score,
886
- "use_colpali": use_colpali,
887
- "end_user_id": self._end_user_id, # Add end user ID here
888
- "folder_name": effective_folder, # Add folder name if provided
889
- }
890
-
891
- # Add folder name if scoped to a folder
892
- if self._folder_name:
893
- request["folder_name"] = self._folder_name
894
-
895
- response = self._client._request("POST", "retrieve/chunks", request)
881
+ payload = self._client._logic._prepare_retrieve_chunks_request(
882
+ query, filters, k, min_score, use_colpali, effective_folder, self._end_user_id, padding
883
+ )
884
+ response = self._client._request("POST", "retrieve/chunks", payload)
896
885
  return self._client._logic._parse_chunk_result_list_response(response)
897
886
 
898
887
  def retrieve_docs(
@@ -952,6 +941,7 @@ class UserScope:
952
941
  additional_folders: Optional[List[str]] = None,
953
942
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
954
943
  chat_id: Optional[str] = None,
944
+ llm_config: Optional[Dict[str, Any]] = None,
955
945
  ) -> CompletionResponse:
956
946
  """
957
947
  Generate completion using relevant chunks as context as this end user.
@@ -991,6 +981,7 @@ class UserScope:
991
981
  self._end_user_id,
992
982
  chat_id,
993
983
  schema,
984
+ llm_config,
994
985
  )
995
986
 
996
987
  # Add schema to payload if provided
@@ -1619,6 +1610,7 @@ class Morphik:
1619
1610
  min_score: float = 0.0,
1620
1611
  use_colpali: bool = True,
1621
1612
  folder_name: Optional[Union[str, List[str]]] = None,
1613
+ padding: int = 0,
1622
1614
  ) -> List[FinalChunkResult]:
1623
1615
  """
1624
1616
  Retrieve relevant chunks.
@@ -1630,6 +1622,7 @@ class Morphik:
1630
1622
  min_score: Minimum similarity threshold (default: 0.0)
1631
1623
  use_colpali: Whether to use ColPali-style embedding model to retrieve the chunks
1632
1624
  (only works for documents ingested with `use_colpali=True`)
1625
+ padding: Number of additional chunks/pages to retrieve before and after matched chunks (ColPali only, default: 0)
1633
1626
  Returns:
1634
1627
  List[ChunkResult]
1635
1628
 
@@ -1642,7 +1635,7 @@ class Morphik:
1642
1635
  ```
1643
1636
  """
1644
1637
  payload = self._logic._prepare_retrieve_chunks_request(
1645
- query, filters, k, min_score, use_colpali, folder_name, None
1638
+ query, filters, k, min_score, use_colpali, folder_name, None, padding
1646
1639
  )
1647
1640
  response = self._request("POST", "retrieve/chunks", data=payload)
1648
1641
  return self._logic._parse_chunk_result_list_response(response)
@@ -1699,6 +1692,7 @@ class Morphik:
1699
1692
  folder_name: Optional[Union[str, List[str]]] = None,
1700
1693
  chat_id: Optional[str] = None,
1701
1694
  schema: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
1695
+ llm_config: Optional[Dict[str, Any]] = None,
1702
1696
  ) -> CompletionResponse:
1703
1697
  """
1704
1698
  Generate completion using relevant chunks as context.
@@ -1719,6 +1713,7 @@ class Morphik:
1719
1713
  Either a QueryPromptOverrides object or a dictionary with the same structure
1720
1714
  folder_name: Optional folder name to further scope operations
1721
1715
  schema: Optional schema for structured output, can be a Pydantic model or a JSON schema dict
1716
+ llm_config: Optional LiteLLM-compatible model configuration (e.g., model name, API key, base URL)
1722
1717
  Returns:
1723
1718
  CompletionResponse
1724
1719
 
@@ -1806,6 +1801,7 @@ class Morphik:
1806
1801
  None, # end_user_id not supported at this level
1807
1802
  chat_id,
1808
1803
  schema,
1804
+ llm_config,
1809
1805
  )
1810
1806
 
1811
1807
  # Add schema to payload if provided
@@ -2741,7 +2737,7 @@ class Morphik:
2741
2737
  self,
2742
2738
  graph_name: str,
2743
2739
  timeout_seconds: int = 300,
2744
- check_interval_seconds: int = 5,
2740
+ check_interval_seconds: int = 2,
2745
2741
  ) -> Graph:
2746
2742
  """Block until the specified graph finishes processing.
2747
2743
 
@@ -2845,10 +2841,34 @@ class Morphik:
2845
2841
  return self._request("GET", f"graph/{name}/visualization", params=params)
2846
2842
 
2847
2843
  def check_workflow_status(self, workflow_id: str, run_id: Optional[str] = None) -> Dict[str, Any]:
2848
- """Poll the status of an asynchronous graph build/update workflow."""
2844
+ """Poll the status of an async graph build/update workflow."""
2849
2845
  params = {"run_id": run_id} if run_id else None
2850
2846
  return self._request("GET", f"graph/workflow/{workflow_id}/status", params=params)
2851
2847
 
2848
+ def get_graph_status(
2849
+ self, graph_name: str, folder_name: Optional[str] = None, end_user_id: Optional[str] = None
2850
+ ) -> Dict[str, Any]:
2851
+ """Get the current status of a graph with pipeline stage information.
2852
+
2853
+ This is a lightweight endpoint that checks local database status and
2854
+ optionally syncs with external workflow status if the graph is processing.
2855
+
2856
+ Args:
2857
+ graph_name: Name of the graph to check
2858
+ folder_name: Optional folder name for scoping
2859
+ end_user_id: Optional end user ID for scoping
2860
+
2861
+ Returns:
2862
+ Dict containing status, pipeline_stage (if processing), and other metadata
2863
+ """
2864
+ params = {}
2865
+ if folder_name:
2866
+ params["folder_name"] = folder_name
2867
+ if end_user_id:
2868
+ params["end_user_id"] = end_user_id
2869
+
2870
+ return self._request("GET", f"graph/{graph_name}/status", params=params if params else None)
2871
+
2852
2872
  # ------------------------------------------------------------------
2853
2873
  # Document download helpers ----------------------------------------
2854
2874
  # ------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: morphik
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: Morphik Python Client
5
5
  Author-email: Morphik <founders@morphik.ai>
6
6
  Requires-Python: >=3.8
@@ -1,10 +1,10 @@
1
- morphik/__init__.py,sha256=gsC5-UiRXLexcy12usewJPMtOaE91DQVJyMMi6G-LPs,242
2
- morphik/_internal.py,sha256=pV1dbZZ8ab7bchAAdqqDbJcOeu_vM6TnNtjY6tS-wDY,19650
3
- morphik/async_.py,sha256=KMt4zui_8ZYLKyH_JiODnheVNpIt1jGnjZut3RdnhwQ,101368
1
+ morphik/__init__.py,sha256=k5NWdg7h0isdg4FCBQjso3OBcDpMV6Nhu1lv5ZtN_kU,242
2
+ morphik/_internal.py,sha256=kme9o2XH6R887sqNZzOmi-Q-pe2MY6CLSlVT35ZfUzY,19864
3
+ morphik/async_.py,sha256=4xME77Ib7thEMqPJEEvBHktptGItoSXhr5LGPLSgTCs,103237
4
4
  morphik/exceptions.py,sha256=v4XGmfq5B0KrZEF6M1ID8A50-45-SRAQZTrXGXM6n0Q,260
5
- morphik/models.py,sha256=JFMeGLbEke-Bls08JXCBv3y_z4eI3PBW_mbX-989i5I,20942
5
+ morphik/models.py,sha256=kbQtPgMZmc8IwF_-S8DyjIeijntTyQsUl1PmUku6SVM,20942
6
6
  morphik/rules.py,sha256=z3YUx0f_b9O7BLbsevAkyMiQg03iUjwfx6OCh7xGKF0,3344
7
- morphik/sync.py,sha256=zFpMLRRdvR4bf_vL0PbcDPNsGFt6vqOMILv8W2CZFQ8,106159
7
+ morphik/sync.py,sha256=RwJhVZa1QKpXrDIrGrZreJGSNUk-ToCjVjwcw9ikakk,107566
8
8
  morphik/tests/README.md,sha256=jtJDDK8cS5E4SbygFQDy7t6Y-kQwNYtZajRwVJDR62U,1069
9
9
  morphik/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  morphik/tests/example_usage.py,sha256=ls8n7355q-8gY43pZLKd4SzI-01MdFeXbT8bZ4U8MCg,11561
@@ -13,6 +13,6 @@ morphik/tests/test_sync.py,sha256=Reqa25Q259mCr-tzWzc1RDcs5KZuDfBkJRKOyyxhDtE,13
13
13
  morphik/tests/test_docs/sample1.txt,sha256=Fx6TElSiKdxyFeBp1iHthzHctFVZm38DrqcbdZMoidY,507
14
14
  morphik/tests/test_docs/sample2.txt,sha256=PE97gPv59J27A7CSNvi_0tRBIN3Mj6pyTFElCLfs3TE,686
15
15
  morphik/tests/test_docs/sample3.txt,sha256=OzrnJ_XsDUntEV0jk-ansa3_KIa6GnpvS5EVmlh6BHo,732
16
- morphik-0.2.3.dist-info/METADATA,sha256=LvQ1f3GJUo9OFrJXs4jFbBxe0a1OjLuMto3IruV2KfQ,3377
17
- morphik-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- morphik-0.2.3.dist-info/RECORD,,
16
+ morphik-0.2.5.dist-info/METADATA,sha256=_L2GQtwTLb1wC5W0tb0AajHXhurlLOPq_Hoodk-4nu0,3377
17
+ morphik-0.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ morphik-0.2.5.dist-info/RECORD,,