lionagi 0.0.306__py3-none-any.whl → 0.0.308__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- lionagi/__init__.py +2 -5
- lionagi/core/__init__.py +7 -5
- lionagi/core/agent/__init__.py +3 -0
- lionagi/core/agent/base_agent.py +10 -12
- lionagi/core/branch/__init__.py +4 -0
- lionagi/core/branch/base_branch.py +81 -81
- lionagi/core/branch/branch.py +16 -28
- lionagi/core/branch/branch_flow_mixin.py +3 -7
- lionagi/core/branch/executable_branch.py +86 -56
- lionagi/core/branch/util.py +77 -162
- lionagi/core/{flow/direct → direct}/__init__.py +1 -1
- lionagi/core/{flow/direct/predict.py → direct/parallel_predict.py} +39 -17
- lionagi/core/direct/parallel_react.py +0 -0
- lionagi/core/direct/parallel_score.py +0 -0
- lionagi/core/direct/parallel_select.py +0 -0
- lionagi/core/direct/parallel_sentiment.py +0 -0
- lionagi/core/direct/predict.py +174 -0
- lionagi/core/{flow/direct → direct}/react.py +2 -2
- lionagi/core/{flow/direct → direct}/score.py +28 -23
- lionagi/core/{flow/direct → direct}/select.py +48 -45
- lionagi/core/direct/utils.py +83 -0
- lionagi/core/flow/monoflow/ReAct.py +6 -5
- lionagi/core/flow/monoflow/__init__.py +9 -0
- lionagi/core/flow/monoflow/chat.py +10 -10
- lionagi/core/flow/monoflow/chat_mixin.py +11 -10
- lionagi/core/flow/monoflow/followup.py +6 -5
- lionagi/core/flow/polyflow/__init__.py +1 -0
- lionagi/core/flow/polyflow/chat.py +15 -3
- lionagi/core/mail/mail_manager.py +18 -19
- lionagi/core/mail/schema.py +5 -4
- lionagi/core/messages/schema.py +18 -20
- lionagi/core/prompt/__init__.py +0 -0
- lionagi/core/prompt/prompt_template.py +0 -0
- lionagi/core/schema/__init__.py +2 -2
- lionagi/core/schema/action_node.py +11 -3
- lionagi/core/schema/base_mixin.py +56 -59
- lionagi/core/schema/base_node.py +34 -37
- lionagi/core/schema/condition.py +24 -0
- lionagi/core/schema/data_logger.py +96 -99
- lionagi/core/schema/data_node.py +19 -19
- lionagi/core/schema/prompt_template.py +0 -0
- lionagi/core/schema/structure.py +171 -169
- lionagi/core/session/__init__.py +1 -3
- lionagi/core/session/session.py +196 -214
- lionagi/core/tool/tool_manager.py +95 -103
- lionagi/integrations/__init__.py +1 -3
- lionagi/integrations/bridge/langchain_/documents.py +17 -18
- lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
- lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
- lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
- lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
- lionagi/integrations/config/openrouter_configs.py +0 -1
- lionagi/integrations/provider/oai.py +26 -26
- lionagi/integrations/provider/services.py +38 -38
- lionagi/libs/__init__.py +34 -1
- lionagi/libs/ln_api.py +211 -221
- lionagi/libs/ln_async.py +53 -60
- lionagi/libs/ln_convert.py +118 -120
- lionagi/libs/ln_dataframe.py +32 -33
- lionagi/libs/ln_func_call.py +334 -342
- lionagi/libs/ln_nested.py +99 -107
- lionagi/libs/ln_parse.py +161 -165
- lionagi/libs/sys_util.py +52 -52
- lionagi/tests/test_core/test_session.py +254 -266
- lionagi/tests/test_core/test_session_base_util.py +299 -300
- lionagi/tests/test_core/test_tool_manager.py +70 -74
- lionagi/tests/test_libs/test_nested.py +2 -7
- lionagi/tests/test_libs/test_parse.py +2 -2
- lionagi/version.py +1 -1
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/METADATA +4 -2
- lionagi-0.0.308.dist-info/RECORD +115 -0
- lionagi/core/flow/direct/utils.py +0 -43
- lionagi-0.0.306.dist-info/RECORD +0 -106
- /lionagi/core/{flow/direct → direct}/sentiment.py +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/LICENSE +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/WHEEL +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/top_level.txt +0 -0
lionagi/libs/ln_parse.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
import re
|
2
2
|
import inspect
|
3
|
+
import itertools
|
3
4
|
from collections.abc import Callable
|
4
5
|
from typing import Any
|
5
6
|
import numpy as np
|
6
7
|
import lionagi.libs.ln_convert as convert
|
7
8
|
|
8
|
-
|
9
9
|
md_json_char_map = {"\n": "\\n", "\r": "\\r", "\t": "\\t", '"': '\\"'}
|
10
10
|
|
11
11
|
|
@@ -20,35 +20,35 @@ class ParseUtil:
|
|
20
20
|
the string by appending necessary closing characters before retrying.
|
21
21
|
|
22
22
|
Args:
|
23
|
-
|
24
|
-
|
23
|
+
s (str): The JSON string to parse.
|
24
|
+
strict (bool, optional): If True, enforces strict JSON syntax. Defaults to False.
|
25
25
|
|
26
26
|
Returns:
|
27
|
-
|
27
|
+
The parsed JSON object, typically a dictionary or list.
|
28
28
|
|
29
29
|
Raises:
|
30
|
-
|
30
|
+
ValueError: If parsing fails even after attempting to correct the string.
|
31
31
|
|
32
32
|
Example:
|
33
|
-
|
34
|
-
|
33
|
+
>>> fuzzy_parse_json('{"name": "John", "age": 30, "city": "New York"')
|
34
|
+
{'name': 'John', 'age': 30, 'city': 'New York'}
|
35
35
|
"""
|
36
36
|
try:
|
37
37
|
return convert.to_dict(str_to_parse, strict=strict)
|
38
|
-
except:
|
38
|
+
except Exception:
|
39
39
|
fixed_s = ParseUtil.fix_json_string(str_to_parse)
|
40
40
|
try:
|
41
41
|
return convert.to_dict(fixed_s, strict=strict)
|
42
|
-
|
43
|
-
except:
|
42
|
+
|
43
|
+
except Exception:
|
44
44
|
try:
|
45
|
-
fixed_s = fixed_s.replace('
|
45
|
+
fixed_s = fixed_s.replace("'", '"')
|
46
46
|
return convert.to_dict(fixed_s, strict=strict)
|
47
|
-
|
47
|
+
|
48
48
|
except Exception as e:
|
49
49
|
raise ValueError(
|
50
50
|
f"Failed to parse JSON even after fixing attempts: {e}"
|
51
|
-
)
|
51
|
+
) from e
|
52
52
|
|
53
53
|
@staticmethod
|
54
54
|
def fix_json_string(str_to_parse: str) -> str:
|
@@ -76,17 +76,17 @@ class ParseUtil:
|
|
76
76
|
a default mapping is used.
|
77
77
|
|
78
78
|
Args:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
value: The string to be escaped.
|
80
|
+
char_map: An optional dictionary mapping characters to their escaped versions.
|
81
|
+
If not provided, a default mapping that escapes newlines, carriage returns,
|
82
|
+
tabs, and double quotes is used.
|
83
83
|
|
84
84
|
Returns:
|
85
|
-
|
85
|
+
The escaped JSON string.
|
86
86
|
|
87
87
|
Examples:
|
88
|
-
|
89
|
-
|
88
|
+
>>> escape_chars_in_json('Line 1\nLine 2')
|
89
|
+
'Line 1\\nLine 2'
|
90
90
|
"""
|
91
91
|
|
92
92
|
def replacement(match):
|
@@ -114,22 +114,22 @@ class ParseUtil:
|
|
114
114
|
filtered by language. If a code block is found, it is parsed using the provided parser function.
|
115
115
|
|
116
116
|
Args:
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
str_to_parse: The Markdown content to search.
|
118
|
+
language: An optional language specifier for the code block. If provided,
|
119
|
+
only code blocks of this language are considered.
|
120
|
+
regex_pattern: An optional regular expression pattern to use for finding the code block.
|
121
|
+
If provided, it overrides the language parameter.
|
122
|
+
parser: A function to parse the extracted code block string.
|
123
123
|
|
124
124
|
Returns:
|
125
|
-
|
125
|
+
The result of parsing the code block with the provided parser function.
|
126
126
|
|
127
127
|
Raises:
|
128
|
-
|
128
|
+
ValueError: If no code block is found in the Markdown content.
|
129
129
|
|
130
130
|
Examples:
|
131
|
-
|
132
|
-
|
131
|
+
>>> extract_code_block('```python\\nprint("Hello, world!")\\n```', language='python', parser=lambda x: x)
|
132
|
+
'print("Hello, world!")'
|
133
133
|
"""
|
134
134
|
|
135
135
|
if language:
|
@@ -140,7 +140,7 @@ class ParseUtil:
|
|
140
140
|
match = re.search(regex_pattern, str_to_parse, re.DOTALL)
|
141
141
|
code_str = ""
|
142
142
|
if match:
|
143
|
-
code_str = match
|
143
|
+
code_str = match[1].strip()
|
144
144
|
else:
|
145
145
|
raise ValueError(
|
146
146
|
f"No {language or 'specified'} code block found in the Markdown content."
|
@@ -162,29 +162,28 @@ class ParseUtil:
|
|
162
162
|
Markdown string. It then optionally verifies that the parsed JSON object contains all expected keys.
|
163
163
|
|
164
164
|
Args:
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
165
|
+
str_to_parse: The Markdown content to parse.
|
166
|
+
expected_keys: An optional list of keys expected to be present in the parsed JSON object.
|
167
|
+
parser: An optional function to parse the extracted code block. If not provided,
|
168
|
+
`fuzzy_parse_json` is used with default settings.
|
169
169
|
|
170
170
|
Returns:
|
171
|
-
|
171
|
+
The parsed JSON object from the Markdown content.
|
172
172
|
|
173
173
|
Raises:
|
174
|
-
|
175
|
-
|
174
|
+
ValueError: If the JSON code block is missing, or if any of the expected keys are missing
|
175
|
+
from the parsed JSON object.
|
176
176
|
|
177
177
|
Examples:
|
178
|
-
|
179
|
-
|
178
|
+
>>> md_to_json('```json\\n{"key": "value"}\\n```', expected_keys=['key'])
|
179
|
+
{'key': 'value'}
|
180
180
|
"""
|
181
181
|
json_obj = ParseUtil.extract_code_block(
|
182
182
|
str_to_parse, language="json", parser=parser or ParseUtil.fuzzy_parse_json
|
183
183
|
)
|
184
184
|
|
185
185
|
if expected_keys:
|
186
|
-
missing_keys
|
187
|
-
if missing_keys:
|
186
|
+
if missing_keys := [key for key in expected_keys if key not in json_obj]:
|
188
187
|
raise ValueError(
|
189
188
|
f"Missing expected keys in JSON object: {', '.join(missing_keys)}"
|
190
189
|
)
|
@@ -198,26 +197,26 @@ class ParseUtil:
|
|
198
197
|
docstring following the Google style format.
|
199
198
|
|
200
199
|
Args:
|
201
|
-
|
200
|
+
func (Callable): The function from which to extract docstring details.
|
202
201
|
|
203
202
|
Returns:
|
204
|
-
|
205
|
-
|
203
|
+
Tuple[str, Dict[str, str]]: A tuple containing the function description
|
204
|
+
and a dictionary with parameter names as keys and their descriptions as values.
|
206
205
|
|
207
206
|
Examples:
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
207
|
+
>>> def example_function(param1: int, param2: str):
|
208
|
+
... '''Example function.
|
209
|
+
...
|
210
|
+
... Args:
|
211
|
+
... param1 (int): The first parameter.
|
212
|
+
... param2 (str): The second parameter.
|
213
|
+
... '''
|
214
|
+
... pass
|
215
|
+
>>> description, params = _extract_docstring_details_google(example_function)
|
216
|
+
>>> description
|
217
|
+
'Example function.'
|
218
|
+
>>> params == {'param1': 'The first parameter.', 'param2': 'The second parameter.'}
|
219
|
+
True
|
221
220
|
"""
|
222
221
|
docstring = inspect.getdoc(func)
|
223
222
|
if not docstring:
|
@@ -225,19 +224,21 @@ class ParseUtil:
|
|
225
224
|
lines = docstring.split("\n")
|
226
225
|
func_description = lines[0].strip()
|
227
226
|
|
228
|
-
param_start_pos = 0
|
229
227
|
lines_len = len(lines)
|
230
228
|
|
231
229
|
params_description = {}
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
230
|
+
param_start_pos = next(
|
231
|
+
(
|
232
|
+
i + 1
|
233
|
+
for i in range(1, lines_len)
|
234
|
+
if (
|
235
|
+
lines[i].startswith("Args")
|
236
|
+
or lines[i].startswith("Arguments")
|
237
|
+
or lines[i].startswith("Parameters")
|
238
|
+
)
|
239
|
+
),
|
240
|
+
0,
|
241
|
+
)
|
241
242
|
current_param = None
|
242
243
|
for i in range(param_start_pos, lines_len):
|
243
244
|
if lines[i] == "":
|
@@ -245,7 +246,7 @@ class ParseUtil:
|
|
245
246
|
elif lines[i].startswith(" "):
|
246
247
|
param_desc = lines[i].split(":", 1)
|
247
248
|
if len(param_desc) == 1:
|
248
|
-
params_description[current_param] += "
|
249
|
+
params_description[current_param] += f" {param_desc[0].strip()}"
|
249
250
|
continue
|
250
251
|
param, desc = param_desc
|
251
252
|
param = param.split("(")[0].strip()
|
@@ -262,27 +263,27 @@ class ParseUtil:
|
|
262
263
|
docstring following the reStructuredText (reST) style format.
|
263
264
|
|
264
265
|
Args:
|
265
|
-
|
266
|
+
func (Callable): The function from which to extract docstring details.
|
266
267
|
|
267
268
|
Returns:
|
268
|
-
|
269
|
-
|
269
|
+
Tuple[str, Dict[str, str]]: A tuple containing the function description
|
270
|
+
and a dictionary with parameter names as keys and their descriptions as values.
|
270
271
|
|
271
272
|
Examples:
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
273
|
+
>>> def example_function(param1: int, param2: str):
|
274
|
+
... '''Example function.
|
275
|
+
...
|
276
|
+
... :param param1: The first parameter.
|
277
|
+
... :type param1: int
|
278
|
+
... :param param2: The second parameter.
|
279
|
+
... :type param2: str
|
280
|
+
... '''
|
281
|
+
... pass
|
282
|
+
>>> description, params = _extract_docstring_details_rest(example_function)
|
283
|
+
>>> description
|
284
|
+
'Example function.'
|
285
|
+
>>> params == {'param1': 'The first parameter.', 'param2': 'The second parameter.'}
|
286
|
+
True
|
286
287
|
"""
|
287
288
|
docstring = inspect.getdoc(func)
|
288
289
|
if not docstring:
|
@@ -301,7 +302,7 @@ class ParseUtil:
|
|
301
302
|
params_description[param] = desc.strip()
|
302
303
|
current_param = param
|
303
304
|
elif line.startswith(" "):
|
304
|
-
params_description[current_param] += " "
|
305
|
+
params_description[current_param] += f" {line}"
|
305
306
|
|
306
307
|
return func_description, params_description
|
307
308
|
|
@@ -313,30 +314,30 @@ class ParseUtil:
|
|
313
314
|
(reST) style format.
|
314
315
|
|
315
316
|
Args:
|
316
|
-
|
317
|
-
|
317
|
+
func (Callable): The function from which to extract docstring details.
|
318
|
+
style (str): The style of docstring to parse ('google' or 'reST').
|
318
319
|
|
319
320
|
Returns:
|
320
|
-
|
321
|
-
|
321
|
+
Tuple[str, Dict[str, str]]: A tuple containing the function description
|
322
|
+
and a dictionary with parameter names as keys and their descriptions as values.
|
322
323
|
|
323
324
|
Raises:
|
324
|
-
|
325
|
+
ValueError: If an unsupported style is provided.
|
325
326
|
|
326
327
|
Examples:
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
328
|
+
>>> def example_function(param1: int, param2: str):
|
329
|
+
... '''Example function.
|
330
|
+
...
|
331
|
+
... Args:
|
332
|
+
... param1 (int): The first parameter.
|
333
|
+
... param2 (str): The second parameter.
|
334
|
+
... '''
|
335
|
+
... pass
|
336
|
+
>>> description, params = _extract_docstring_details(example_function, style='google')
|
337
|
+
>>> description
|
338
|
+
'Example function.'
|
339
|
+
>>> params == {'param1': 'The first parameter.', 'param2': 'The second parameter.'}
|
340
|
+
True
|
340
341
|
"""
|
341
342
|
if style == "google":
|
342
343
|
func_description, params_description = (
|
@@ -358,16 +359,16 @@ class ParseUtil:
|
|
358
359
|
Converts a Python type to its JSON type equivalent.
|
359
360
|
|
360
361
|
Args:
|
361
|
-
|
362
|
+
py_type (str): The name of the Python type.
|
362
363
|
|
363
364
|
Returns:
|
364
|
-
|
365
|
+
str: The corresponding JSON type.
|
365
366
|
|
366
367
|
Examples:
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
368
|
+
>>> _python_to_json_type('str')
|
369
|
+
'string'
|
370
|
+
>>> _python_to_json_type('int')
|
371
|
+
'number'
|
371
372
|
"""
|
372
373
|
type_mapping = {
|
373
374
|
"str": "string",
|
@@ -387,24 +388,24 @@ class ParseUtil:
|
|
387
388
|
docstrings. The schema includes the function's name, description, and parameters.
|
388
389
|
|
389
390
|
Args:
|
390
|
-
|
391
|
-
|
391
|
+
func (Callable): The function to generate a schema for.
|
392
|
+
style (str): The docstring format ('google' or 'reST').
|
392
393
|
|
393
394
|
Returns:
|
394
|
-
|
395
|
+
Dict[str, Any]: A schema describing the function.
|
395
396
|
|
396
397
|
Examples:
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
398
|
+
>>> def example_function(param1: int, param2: str) -> bool:
|
399
|
+
... '''Example function.
|
400
|
+
...
|
401
|
+
... Args:
|
402
|
+
... param1 (int): The first parameter.
|
403
|
+
... param2 (str): The second parameter.
|
404
|
+
... '''
|
405
|
+
... return True
|
406
|
+
>>> schema = _func_to_schema(example_function)
|
407
|
+
>>> schema['function']['name']
|
408
|
+
'example_function'
|
408
409
|
"""
|
409
410
|
# Extracting function name and docstring details
|
410
411
|
func_name = func.__name__
|
@@ -438,8 +439,7 @@ class ParseUtil:
|
|
438
439
|
"description": param_description,
|
439
440
|
}
|
440
441
|
|
441
|
-
|
442
|
-
schema = {
|
442
|
+
return {
|
443
443
|
"type": "function",
|
444
444
|
"function": {
|
445
445
|
"name": func_name,
|
@@ -448,8 +448,6 @@ class ParseUtil:
|
|
448
448
|
},
|
449
449
|
}
|
450
450
|
|
451
|
-
return schema
|
452
|
-
|
453
451
|
|
454
452
|
class StringMatch:
|
455
453
|
|
@@ -463,16 +461,16 @@ class StringMatch:
|
|
463
461
|
and 1 is an exact match.
|
464
462
|
|
465
463
|
Args:
|
466
|
-
|
467
|
-
|
464
|
+
s: The first string to compare.
|
465
|
+
t: The second string to compare.
|
468
466
|
|
469
467
|
Returns:
|
470
|
-
|
471
|
-
|
468
|
+
A float representing the Jaro distance between the two strings, ranging from 0 to 1,
|
469
|
+
where 1 means the strings are identical.
|
472
470
|
|
473
471
|
Examples:
|
474
|
-
|
475
|
-
|
472
|
+
>>> jaro_distance("martha", "marhta")
|
473
|
+
0.9444444444444445
|
476
474
|
"""
|
477
475
|
s_len = len(s)
|
478
476
|
t_len = len(t)
|
@@ -527,18 +525,18 @@ class StringMatch:
|
|
527
525
|
person names, and is designed to improve the scoring of strings that have a common prefix.
|
528
526
|
|
529
527
|
Args:
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
528
|
+
s: The first string to compare.
|
529
|
+
t: The second string to compare.
|
530
|
+
scaling: The scaling factor for how much the score is adjusted upwards for having common prefixes.
|
531
|
+
The scaling factor should be less than 1, and a typical value is 0.1.
|
534
532
|
|
535
533
|
Returns:
|
536
|
-
|
537
|
-
|
534
|
+
A float representing the Jaro-Winkler similarity between the two strings, ranging from 0 to 1,
|
535
|
+
where 1 means the strings are identical.
|
538
536
|
|
539
537
|
Examples:
|
540
|
-
|
541
|
-
|
538
|
+
>>> jaro_winkler_similarity("dixon", "dicksonx")
|
539
|
+
0.8133333333333332
|
542
540
|
"""
|
543
541
|
jaro_sim = StringMatch.jaro_distance(s, t)
|
544
542
|
prefix_len = 0
|
@@ -561,15 +559,15 @@ class StringMatch:
|
|
561
559
|
required to change one word into the other. Each operation has an equal cost.
|
562
560
|
|
563
561
|
Args:
|
564
|
-
|
565
|
-
|
562
|
+
a: The first string to compare.
|
563
|
+
b: The second string to compare.
|
566
564
|
|
567
565
|
Returns:
|
568
|
-
|
566
|
+
An integer representing the Levenshtein distance between the two strings.
|
569
567
|
|
570
568
|
Examples:
|
571
|
-
|
572
|
-
|
569
|
+
>>> levenshtein_distance("kitten", "sitting")
|
570
|
+
3
|
573
571
|
"""
|
574
572
|
m, n = len(a), len(b)
|
575
573
|
# Initialize 2D array (m+1) x (n+1)
|
@@ -582,17 +580,13 @@ class StringMatch:
|
|
582
580
|
d[0][j] = j
|
583
581
|
|
584
582
|
# Compute the distance
|
585
|
-
for i in range(1, m + 1):
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
d[i - 1][j] + 1, # deletion
|
593
|
-
d[i][j - 1] + 1, # insertion
|
594
|
-
d[i - 1][j - 1] + cost,
|
595
|
-
) # substitution
|
583
|
+
for i, j in itertools.product(range(1, m + 1), range(1, n + 1)):
|
584
|
+
cost = 0 if a[i - 1] == b[j - 1] else 1
|
585
|
+
d[i][j] = min(
|
586
|
+
d[i - 1][j] + 1, # deletion
|
587
|
+
d[i][j - 1] + 1, # insertion
|
588
|
+
d[i - 1][j - 1] + cost,
|
589
|
+
) # substitution
|
596
590
|
return d[m][n]
|
597
591
|
|
598
592
|
@staticmethod
|
@@ -632,12 +626,14 @@ class StringMatch:
|
|
632
626
|
|
633
627
|
if score_func is None:
|
634
628
|
score_func = StringMatch.jaro_winkler_similarity
|
635
|
-
|
629
|
+
|
636
630
|
# Calculate Jaro-Winkler similarity scores for each potential match
|
637
|
-
scores = np.array(
|
631
|
+
scores = np.array(
|
632
|
+
[
|
633
|
+
score_func(convert.to_str(word), correct_word)
|
634
|
+
for correct_word in correct_words_list
|
635
|
+
]
|
636
|
+
)
|
638
637
|
# Find the index of the highest score
|
639
638
|
max_score_index = np.argmax(scores)
|
640
|
-
|
641
|
-
best_match = correct_words_list[max_score_index]
|
642
|
-
|
643
|
-
return best_match
|
639
|
+
return correct_words_list[max_score_index]
|