lionagi 0.0.111__py3-none-any.whl → 0.0.113__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.
Files changed (91) hide show
  1. lionagi/__init__.py +7 -2
  2. lionagi/bridge/__init__.py +7 -0
  3. lionagi/bridge/langchain.py +131 -0
  4. lionagi/bridge/llama_index.py +157 -0
  5. lionagi/configs/__init__.py +7 -0
  6. lionagi/configs/oai_configs.py +49 -0
  7. lionagi/configs/openrouter_config.py +49 -0
  8. lionagi/core/__init__.py +15 -0
  9. lionagi/{session/conversation.py → core/conversations.py} +10 -17
  10. lionagi/core/flows.py +1 -0
  11. lionagi/core/instruction_sets.py +1 -0
  12. lionagi/{session/message.py → core/messages.py} +5 -5
  13. lionagi/core/sessions.py +262 -0
  14. lionagi/datastore/__init__.py +1 -0
  15. lionagi/datastore/chroma.py +1 -0
  16. lionagi/datastore/deeplake.py +1 -0
  17. lionagi/datastore/elasticsearch.py +1 -0
  18. lionagi/datastore/lantern.py +1 -0
  19. lionagi/datastore/pinecone.py +1 -0
  20. lionagi/datastore/postgres.py +1 -0
  21. lionagi/datastore/qdrant.py +1 -0
  22. lionagi/loader/__init__.py +12 -0
  23. lionagi/loader/chunker.py +157 -0
  24. lionagi/loader/reader.py +124 -0
  25. lionagi/objs/__init__.py +7 -0
  26. lionagi/objs/messenger.py +163 -0
  27. lionagi/objs/tool_registry.py +247 -0
  28. lionagi/schema/__init__.py +11 -0
  29. lionagi/schema/base_condition.py +1 -0
  30. lionagi/schema/base_schema.py +239 -0
  31. lionagi/schema/base_tool.py +9 -0
  32. lionagi/schema/data_logger.py +94 -0
  33. lionagi/services/__init__.py +14 -0
  34. lionagi/services/anthropic.py +1 -0
  35. lionagi/services/anyscale.py +0 -0
  36. lionagi/services/azure.py +1 -0
  37. lionagi/{api/oai_service.py → services/base_api_service.py} +74 -148
  38. lionagi/services/bedrock.py +0 -0
  39. lionagi/services/chatcompletion.py +48 -0
  40. lionagi/services/everlyai.py +0 -0
  41. lionagi/services/gemini.py +0 -0
  42. lionagi/services/gpt4all.py +0 -0
  43. lionagi/services/huggingface.py +0 -0
  44. lionagi/services/litellm.py +1 -0
  45. lionagi/services/localai.py +0 -0
  46. lionagi/services/mistralai.py +0 -0
  47. lionagi/services/oai.py +34 -0
  48. lionagi/services/ollama.py +1 -0
  49. lionagi/services/openllm.py +0 -0
  50. lionagi/services/openrouter.py +32 -0
  51. lionagi/services/perplexity.py +0 -0
  52. lionagi/services/predibase.py +0 -0
  53. lionagi/services/rungpt.py +0 -0
  54. lionagi/services/service_objs.py +282 -0
  55. lionagi/services/vllm.py +0 -0
  56. lionagi/services/xinference.py +0 -0
  57. lionagi/structure/__init__.py +7 -0
  58. lionagi/structure/relationship.py +128 -0
  59. lionagi/structure/structure.py +160 -0
  60. lionagi/tests/__init__.py +0 -0
  61. lionagi/tests/test_flatten_util.py +426 -0
  62. lionagi/tools/__init__.py +0 -0
  63. lionagi/tools/coder.py +1 -0
  64. lionagi/tools/planner.py +1 -0
  65. lionagi/tools/prompter.py +1 -0
  66. lionagi/tools/sandbox.py +1 -0
  67. lionagi/tools/scorer.py +1 -0
  68. lionagi/tools/summarizer.py +1 -0
  69. lionagi/tools/validator.py +1 -0
  70. lionagi/utils/__init__.py +46 -8
  71. lionagi/utils/api_util.py +63 -416
  72. lionagi/utils/call_util.py +347 -0
  73. lionagi/utils/flat_util.py +540 -0
  74. lionagi/utils/io_util.py +102 -0
  75. lionagi/utils/load_utils.py +190 -0
  76. lionagi/utils/sys_util.py +85 -660
  77. lionagi/utils/tool_util.py +82 -199
  78. lionagi/utils/type_util.py +81 -0
  79. lionagi/version.py +1 -1
  80. {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/METADATA +44 -15
  81. lionagi-0.0.113.dist-info/RECORD +84 -0
  82. lionagi/api/__init__.py +0 -8
  83. lionagi/api/oai_config.py +0 -16
  84. lionagi/session/__init__.py +0 -7
  85. lionagi/session/session.py +0 -380
  86. lionagi/utils/doc_util.py +0 -331
  87. lionagi/utils/log_util.py +0 -86
  88. lionagi-0.0.111.dist-info/RECORD +0 -20
  89. {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/LICENSE +0 -0
  90. {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/WHEEL +0 -0
  91. {lionagi-0.0.111.dist-info → lionagi-0.0.113.dist-info}/top_level.txt +0 -0
lionagi/utils/doc_util.py DELETED
@@ -1,331 +0,0 @@
1
- import math
2
- from pathlib import Path
3
- from typing import Any, Dict, List, Union, Callable, Optional
4
-
5
- from .sys_util import to_list, l_call
6
- from .log_util import DataLogger
7
-
8
-
9
- def dir_to_path(dir: str, ext, recursive: bool = False, flat: bool = True):
10
- """
11
- Retrieves a list of file paths in the specified directory with the given extension.
12
-
13
- Parameters:
14
- dir (str): The directory path where to search for files.
15
-
16
- ext (str): The file extension to filter by.
17
-
18
- recursive (bool, optional): If True, search for files recursively in subdirectories. Defaults to False.
19
-
20
- flat (bool, optional): If True, return a flat list of file paths. Defaults to True.
21
-
22
- Returns:
23
- List[str]: A list of file paths that match the given extension within the specified directory.
24
-
25
- Example:
26
- >>> files = dir_to_path(dir='my_directory', ext='.txt', recursive=True, flat=True)
27
- """
28
-
29
- def _dir_to_path(ext, recursive=recursive):
30
- tem = '**/*' if recursive else '*'
31
- return list(Path(dir).glob(tem + ext))
32
-
33
- try:
34
- return to_list(l_call(ext, _dir_to_path, flat=True), flat=flat)
35
- except:
36
- raise ValueError("Invalid directory or extension, please check the path")
37
-
38
- def read_text(filepath: str, clean: bool = True) -> str:
39
- """
40
- Reads the content of a text file and optionally cleans it by removing specified characters.
41
-
42
- Parameters:
43
- filepath (str): The path to the text file to be read.
44
-
45
- clean (bool, optional): If True, clean the content by removing specific unwanted characters. Defaults to True.
46
-
47
- Returns:
48
- str: The cleaned (if 'clean' is True) or raw content of the text file.
49
-
50
- Example:
51
- >>> content = read_text(filepath='example.txt', clean=True)
52
- """
53
-
54
- with open(filepath, 'r') as f:
55
- content = f.read()
56
- if clean:
57
- # Define characters to replace and their replacements
58
- replacements = {'\\': ' ', '\n': ' ', '\t': ' ', ' ': ' ', '\'': ' '}
59
- for old, new in replacements.items():
60
- content = content.replace(old, new)
61
- return content
62
-
63
- def dir_to_files(dir: str, ext: str, recursive: bool = False,
64
- reader: Callable = read_text, clean: bool = True,
65
- to_csv: bool = False, project: str = 'project',
66
- output_dir: str = 'data/logs/sources/', filename: Optional[str] = None,
67
- verbose: bool = True, timestamp: bool = True, logger: Optional[DataLogger] = None):
68
- """
69
- Reads and processes files in a specified directory with the given extension.
70
-
71
- Parameters:
72
- dir (str): The directory path where files are located.
73
-
74
- ext (str): The file extension to filter by.
75
-
76
- recursive (bool, optional): If True, search files recursively in subdirectories. Defaults to False.
77
-
78
- reader (Callable, optional): Function used to read and process the content of each file. Defaults to read_text.
79
-
80
- clean (bool, optional): If True, cleans the content by removing specified characters. Defaults to True.
81
-
82
- to_csv (bool, optional): If True, export the processed data to a CSV file. Defaults to False.
83
-
84
- project (str, optional): The name of the project. Defaults to 'project'.
85
-
86
- output_dir (str, optional): Directory path for exporting the CSV file. Defaults to 'data/logs/sources/'.
87
-
88
- filename (Optional[str], optional): Name of the CSV file, if not provided, a default will be used. Defaults to None.
89
-
90
- verbose (bool, optional): If True, print a message upon CSV export. Defaults to True.
91
-
92
- timestamp (bool, optional): If True, include a timestamp in the file name. Defaults to True.
93
-
94
- logger (Optional[DataLogger], optional): An instance of DataLogger for logging, if not provided, a new one will be created. Defaults to None.
95
-
96
- Returns:
97
- List[Dict[str, Union[str, Path]]]: A list of dictionaries containing file information and content.
98
-
99
- Examples:
100
- >>> logs = dir_to_files(dir='my_directory', ext='.txt', to_csv=True)
101
- """
102
-
103
- sources = dir_to_path(dir, ext, recursive)
104
-
105
- def _split_path(path: Path) -> tuple:
106
- folder_name = path.parent.name
107
- file_name = path.name
108
- return (folder_name, file_name)
109
-
110
- def _to_dict(path_: Path) -> Dict[str, Union[str, Path]]:
111
- folder, file = _split_path(path_)
112
- content = reader(str(path_), clean=clean)
113
- return {
114
- 'project': project,
115
- 'folder': folder,
116
- 'file': file,
117
- "file_size": len(str(content)),
118
- 'content': content
119
- } if content else None
120
-
121
- logs = to_list(l_call(sources, _to_dict, flat=True), dropna=True)
122
-
123
- if to_csv:
124
- filename = filename or f"{project}_sources.csv"
125
- logger = DataLogger(dir=output_dir, log=logs) if not logger else logger
126
- logger.to_csv(dir=output_dir, filename=filename, verbose=verbose, timestamp=timestamp)
127
-
128
- return logs
129
-
130
- def chunk_text(input: str, chunk_size: int, overlap: float,
131
- threshold: int) -> List[Union[str, None]]:
132
- """
133
- Splits a string into chunks of a specified size, allowing for optional overlap between chunks.
134
-
135
- Parameters:
136
- input (str): The text to be split into chunks.
137
-
138
- chunk_size (int): The size of each chunk in characters.
139
-
140
- overlap (float): A value between [0, 1] specifying the percentage of overlap between adjacent chunks.
141
-
142
- threshold (int): The minimum size for the last chunk. If the last chunk is smaller than this, it will be merged with the previous chunk.
143
-
144
- Raises:
145
- TypeError: If input text cannot be converted to a string.
146
-
147
- ValueError: If any error occurs during the chunking process.
148
-
149
- Returns:
150
- List[Union[str, None]]: List of text chunks.
151
- """
152
-
153
- try:
154
- # Ensure text is a string
155
- if not isinstance(input, str):
156
- input = str(input)
157
-
158
- chunks = []
159
- n_chunks = math.ceil(len(input) / chunk_size)
160
- overlap_size = int(chunk_size * overlap / 2)
161
-
162
- if n_chunks == 1:
163
- return [input]
164
-
165
- elif n_chunks == 2:
166
- chunks.append(input[:chunk_size + overlap_size])
167
- if len(input) - chunk_size > threshold:
168
- chunks.append(input[chunk_size - overlap_size:])
169
- else:
170
- return [input]
171
- return chunks
172
-
173
- elif n_chunks > 2:
174
- chunks.append(input[:chunk_size + overlap_size])
175
- for i in range(1, n_chunks - 1):
176
- start_idx = chunk_size * i - overlap_size
177
- end_idx = chunk_size * (i + 1) + overlap_size
178
- chunks.append(input[start_idx:end_idx])
179
-
180
- if len(input) - chunk_size * (n_chunks - 1) > threshold:
181
- chunks.append(input[chunk_size * (n_chunks - 1) - overlap_size:])
182
- else:
183
- chunks[-1] += input[chunk_size * (n_chunks - 1) + overlap_size:]
184
-
185
- return chunks
186
-
187
- except Exception as e:
188
- raise ValueError(f"An error occurred while chunking the text. {e}")
189
-
190
- def _file_to_chunks(input: Dict[str, Any],
191
- field: str = 'content',
192
- chunk_size: int = 1500,
193
- overlap: float = 0.2,
194
- threshold: int = 200) -> List[Dict[str, Any]]:
195
- """
196
- Splits text from a specified dictionary field into chunks and returns a list of dictionaries.
197
-
198
- Parameters:
199
- input (Dict[str, Any]): The input dictionary containing the text field to be chunked.
200
-
201
- field (str, optional): The dictionary key corresponding to the text field. Defaults to 'content'.
202
-
203
- chunk_size (int, optional): Size of each text chunk in characters. Defaults to 1500.
204
-
205
- overlap (float, optional): Percentage of overlap between adjacent chunks, in the range [0, 1]. Defaults to 0.2.
206
-
207
- threshold (int, optional): Minimum size for the last chunk. If smaller, it will be merged with the previous chunk. Defaults to 200.
208
-
209
- Raises:
210
- ValueError: If any error occurs during the chunking process.
211
-
212
- Returns:
213
- List[Dict[str, Any]]: A list of dictionaries, each containing a separate chunk along with original key-value pairs from the input dictionary.
214
-
215
- Example:
216
- >>> d = {'content': 'This is a test string.', 'other_field': 1}
217
- >>> file_to_chunks(d)
218
- [{'chunk_overlap': 0.2, 'chunk_threshold': 200, 'file_chunks': 2, 'chunk_id': 1, 'chunk_size': 14, 'chunk_content': 'This is a test', 'other_field': 1}, ...]
219
- """
220
-
221
- try:
222
- out = {key: value for key, value in input.items() if key != field}
223
- out.update({"chunk_overlap": overlap, "chunk_threshold": threshold})
224
-
225
- chunks = chunk_text(input[field], chunk_size=chunk_size, overlap=overlap, threshold=threshold)
226
- logs = []
227
- for i, chunk in enumerate(chunks):
228
- chunk_dict = out.copy()
229
- chunk_dict.update({
230
- 'file_chunks': len(chunks),
231
- 'chunk_id': i + 1,
232
- 'chunk_size': len(chunk),
233
- f'chunk_{field}': chunk
234
- })
235
- logs.append(chunk_dict)
236
-
237
- return logs
238
-
239
- except Exception as e:
240
- raise ValueError(f"An error occurred while chunking the file. {e}")
241
-
242
- def file_to_chunks(input,
243
- field: str = 'content',
244
- chunk_size: int = 1500,
245
- overlap: float = 0.2,
246
- threshold: int = 200,
247
- to_csv=False,
248
- project='project',
249
- output_dir='data/logs/sources/',
250
- chunk_func = _file_to_chunks,
251
- filename=None,
252
- verbose=True,
253
- timestamp=True,
254
- logger=None):
255
- """
256
- Splits text from a specified dictionary field into chunks and returns a list of dictionaries.
257
-
258
- Parameters:
259
- input (List[Dict[str, Any]]): The input dictionaries containing the text field to be chunked.
260
-
261
- field (str, optional): The dictionary key corresponding to the text field. Defaults to 'content'.
262
-
263
- chunk_size (int, optional): Size of each text chunk in characters. Defaults to 1500.
264
-
265
- overlap (float, optional): Percentage of overlap between adjacent chunks, in the range [0, 1]. Defaults to 0.2.
266
-
267
- threshold (int, optional): Minimum size for the last chunk. If smaller, it will be merged with the previous chunk. Defaults to 200.
268
-
269
- to_csv (bool, optional): If True, export the processed data to a CSV file.
270
-
271
- project (str, optional): The name of the project.
272
-
273
- output_dir (str, optional): The directory path for exporting the CSV file.
274
-
275
- chunk_func (function, optional): The function to be used for chunking. Defaults to _file_to_chunks.
276
-
277
- filename (str, optional): The name of the CSV file.
278
-
279
- verbose (bool, optional): If True, print a verbose message after export.
280
-
281
- timestamp (bool, optional): If True, include a timestamp in the exported file name.
282
-
283
- logger (DataLogger, optional): An optional DataLogger instance for logging.
284
-
285
- Returns:
286
- List[Dict[str, Any]]: A list of dictionaries representing the processed text chunks.
287
- """
288
-
289
- _f = lambda x: chunk_func(x, field=field, chunk_size=chunk_size, overlap=overlap, threshold=threshold)
290
- logs = to_list(l_call(input, _f), flat=True)
291
-
292
- if to_csv:
293
- filename = filename if filename else f"{project}_sources.csv"
294
- logger = DataLogger(log=logs) if not logger else logger
295
- logger.to_csv(dir=output_dir, filename=filename, verbose=verbose, timestamp=timestamp)
296
-
297
- return logs
298
-
299
- def get_bins(input: List[str], upper: int = 7500) -> List[List[int]]:
300
- """
301
- Get index of elements in a list based on their consecutive cumulative sum of length,
302
- according to some upper threshold. Return lists of indices as bins.
303
-
304
- Parameters:
305
- input (List[str]): List of items to be binned.
306
-
307
- upper (int, optional): Upper threshold for the cumulative sum of the length of items in a bin. Default is 7500.
308
-
309
- Returns:
310
- List[List[int]]: List of lists, where each inner list contains the indices of the items that form a bin.
311
-
312
- Example:
313
- >>> items = ['apple', 'a', 'b', 'banana', 'cheery', 'c', 'd', 'e']
314
- >>> upper = 10
315
- >>> get_bins(items, upper)
316
- [[0, 1, 2], [3], [4, 5, 6, 7]]
317
- """
318
- current = 0
319
- bins = []
320
- bin = []
321
- for idx, item in enumerate(input):
322
- if current + len(item) < upper:
323
- bin.append(idx)
324
- current += len(item)
325
- elif current + len(item) >= upper:
326
- bins.append(bin)
327
- bin = [idx]
328
- current = len(item)
329
- if idx == len(input) - 1 and len(bin) > 0:
330
- bins.append(bin)
331
- return bins
lionagi/utils/log_util.py DELETED
@@ -1,86 +0,0 @@
1
- from collections import deque
2
- from .sys_util import to_csv, create_path
3
-
4
-
5
- class DataLogger:
6
- """
7
- Logs data entries and outputs them to a CSV file.
8
-
9
- This class provides a logging mechanism for data entries that can be saved to a
10
- CSV file. It offers methods for appending new log entries, saving the log to a CSV file,
11
- and setting the directory where the logs should be saved.
12
-
13
- Attributes:
14
- dir (str):
15
- The directory where the log files are to be saved.
16
- log (deque):
17
- A deque that stores log entries.
18
-
19
- Methods:
20
- __call__(entry):
21
- Appends a new entry to the log.
22
- to_csv(dir: str, filename: str, verbose: bool, timestamp: bool, dir_exist_ok: bool, file_exist_ok: bool):
23
- Converts the log to a CSV format and saves it to a file.
24
- set_dir(dir: str):
25
- Sets the directory for saving log files.
26
- """
27
-
28
- def __init__(self, dir= None, log: list = None) -> None:
29
- """
30
- Initializes a new instance of the DataLogger class.
31
-
32
- Parameters:
33
- dir (str, optional): The directory where the log files will be saved. Defaults to None.
34
-
35
- log (list, optional): An initial list of log entries. Defaults to an empty deque.
36
- """
37
- self.dir = dir
38
- self.log = deque(log) if log else deque()
39
-
40
- def __call__(self, entry):
41
- """
42
- Appends a new entry to the log.
43
-
44
- Parameters:
45
- entry: The entry to append to the log. The entry can be of any datatype.
46
- """
47
- self.log.append(entry)
48
-
49
- def to_csv(self, dir: str, filename: str, verbose: bool = True, timestamp: bool = True, dir_exist_ok=True, file_exist_ok=False):
50
- """
51
- Converts the log to a CSV format and saves it to a file.
52
-
53
- Parameters:
54
- dir (str): The directory where the CSV file will be saved.
55
-
56
- filename (str): The name of the CSV file.
57
-
58
- verbose (bool, optional): If True, prints a message after saving the log. Defaults to True.
59
-
60
- timestamp (bool, optional): If True, appends a timestamp to the filename. Defaults to True.
61
-
62
- dir_exist_ok (bool, optional): If True, overrides the existing directory if needed. Defaults to True.
63
-
64
- file_exist_ok (bool, optional): If True, overrides the existing file if needed. Defaults to False.
65
-
66
- Postconditions:
67
- Saves the log entries to a CSV file and clears the `log` attribute.
68
-
69
- Optionally prints a message with the number of log entries saved and the file path.
70
- """
71
- filepath = create_path(dir=dir, filename=filename, timestamp=timestamp, dir_exist_ok=dir_exist_ok)
72
- to_csv(list(self.log), filepath, file_exist_ok=file_exist_ok)
73
- n_logs = len(list(self.log))
74
- self.log = deque()
75
- if verbose:
76
- print(f"{n_logs} logs saved to {filepath}")
77
-
78
- def set_dir(self, dir: str):
79
- """
80
- Sets the directory where log files will be saved.
81
-
82
- Parameters:
83
- dir (str): The directory to set for saving log files.
84
- """
85
- self.dir = dir
86
-
@@ -1,20 +0,0 @@
1
- lionagi/__init__.py,sha256=2Rko3tw94ZFVN_GSvcxAY1O77FxswcaMxNHKH5Bj7jc,788
2
- lionagi/version.py,sha256=BtvlzlO7UNG5nD9ftqoP0J2wHDhVCXpzuMsjYBw0Wfg,24
3
- lionagi/api/__init__.py,sha256=PF-fWsB0axACGDbm8FluZgDQMyQf3PUUJ1tIXW535TQ,178
4
- lionagi/api/oai_config.py,sha256=yhyZ4aEaF6r3XBbhxI47r8CL2-amc-4IKJhbXv2W9CM,356
5
- lionagi/api/oai_service.py,sha256=9FBmw_UTBsgnPBP7f8KOX4PwS5TXeknnUw6-kAYJxqk,11919
6
- lionagi/session/__init__.py,sha256=qAf0IAA2D1ZhwvRopSgi8X13DH4Y0E5HaA2DVr6FxG0,152
7
- lionagi/session/conversation.py,sha256=5EePoSVIcyaZJEtkNxv1yCFby_3_SLx5AmaSxS9pwI8,4058
8
- lionagi/session/message.py,sha256=L4QhTvay-xqL_PWWzr_lTig70cr7zEc5YjONILmAoWU,6504
9
- lionagi/session/session.py,sha256=wmAwNxk6pm1MTV3kqjG8i5a89xssDP0Ln8m2_e_zdek,14748
10
- lionagi/utils/__init__.py,sha256=e5aEzyHofUYZ8olcyHxq7wqTGRsRZwag3vyZ0T4_ByQ,842
11
- lionagi/utils/api_util.py,sha256=xPWwQkWMnkGOUAKpwOkGkMv2SWCSCHjBsggnrSfHJhs,15257
12
- lionagi/utils/doc_util.py,sha256=ZEuLKzc3EH692FW1LXRXBHgextMfb1OaLE3z_NhBBT0,12882
13
- lionagi/utils/log_util.py,sha256=mfLmvjv4hvTYMel46tpKJyqLbj1PZimCgKigz48osZY,3158
14
- lionagi/utils/sys_util.py,sha256=q4I_d61Zwe-WvukNoa53Gd8ycDcTpfOhw3yER8ZoiCg,28449
15
- lionagi/utils/tool_util.py,sha256=0mWGW_rfUPTay_L05dckGzEXdg4ZdhFyGA1lve9tnj8,7410
16
- lionagi-0.0.111.dist-info/LICENSE,sha256=TBnSyG8fs_tMRtK805GzA1cIyExleKyzoN_kuVxT9IY,11358
17
- lionagi-0.0.111.dist-info/METADATA,sha256=drb1EbWKei2M7WjH6Md8Qq_vOMRc8Sgz1oyxawPZQEY,17414
18
- lionagi-0.0.111.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
- lionagi-0.0.111.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
20
- lionagi-0.0.111.dist-info/RECORD,,