lionagi 0.12.2__py3-none-any.whl → 0.12.3__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.
- lionagi/fields/file.py +1 -1
- lionagi/fields/reason.py +1 -1
- lionagi/libs/file/concat.py +1 -6
- lionagi/libs/file/concat_files.py +1 -5
- lionagi/libs/file/save.py +1 -1
- lionagi/libs/package/imports.py +8 -177
- lionagi/libs/parse.py +30 -0
- lionagi/libs/token_transform/synthlang_/resources/frameworks/framework_options.json +46 -46
- lionagi/protocols/generic/log.py +1 -2
- lionagi/protocols/messages/templates/README.md +6 -10
- lionagi/service/providers/exa_/models.py +159 -2
- lionagi/service/providers/perplexity_/models.py +143 -4
- lionagi/utils.py +921 -123
- lionagi/version.py +1 -1
- {lionagi-0.12.2.dist-info → lionagi-0.12.3.dist-info}/METADATA +27 -9
- {lionagi-0.12.2.dist-info → lionagi-0.12.3.dist-info}/RECORD +18 -27
- lionagi/libs/file/create_path.py +0 -80
- lionagi/libs/file/file_util.py +0 -358
- lionagi/libs/parse/__init__.py +0 -3
- lionagi/libs/parse/fuzzy_parse_json.py +0 -117
- lionagi/libs/parse/to_dict.py +0 -336
- lionagi/libs/parse/to_json.py +0 -61
- lionagi/libs/parse/to_num.py +0 -378
- lionagi/libs/parse/to_xml.py +0 -57
- lionagi/libs/parse/xml_parser.py +0 -148
- lionagi/libs/schema/breakdown_pydantic_annotation.py +0 -48
- {lionagi-0.12.2.dist-info → lionagi-0.12.3.dist-info}/WHEEL +0 -0
- {lionagi-0.12.2.dist-info → lionagi-0.12.3.dist-info}/licenses/LICENSE +0 -0
lionagi/fields/file.py
CHANGED
lionagi/fields/reason.py
CHANGED
lionagi/libs/file/concat.py
CHANGED
@@ -1,12 +1,7 @@
|
|
1
|
-
# Copyright (c) 2023 - 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
4
|
-
|
5
1
|
from pathlib import Path
|
6
2
|
from typing import Any
|
7
3
|
|
8
|
-
from lionagi.
|
9
|
-
from lionagi.utils import lcall
|
4
|
+
from lionagi.utils import create_path, lcall
|
10
5
|
|
11
6
|
from .process import dir_to_files
|
12
7
|
|
@@ -1,10 +1,6 @@
|
|
1
|
-
# Copyright (c) 2023 - 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
-
#
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
4
|
-
|
5
1
|
from pathlib import Path
|
6
2
|
|
7
|
-
from lionagi.
|
3
|
+
from lionagi.utils import create_path
|
8
4
|
|
9
5
|
from .process import dir_to_files
|
10
6
|
|
lionagi/libs/file/save.py
CHANGED
lionagi/libs/package/imports.py
CHANGED
@@ -2,184 +2,15 @@
|
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
|
5
|
-
import
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
from lionagi.utils import is_import_installed
|
13
|
-
|
14
|
-
|
15
|
-
def run_package_manager_command(
|
16
|
-
args: Sequence[str],
|
17
|
-
) -> subprocess.CompletedProcess[bytes]:
|
18
|
-
"""Run a package manager command, using uv if available, otherwise falling back to pip."""
|
19
|
-
# Check if uv is available in PATH
|
20
|
-
uv_path = shutil.which("uv")
|
21
|
-
|
22
|
-
if uv_path:
|
23
|
-
# Use uv if available
|
24
|
-
try:
|
25
|
-
return subprocess.run(
|
26
|
-
[uv_path] + list(args),
|
27
|
-
check=True,
|
28
|
-
capture_output=True,
|
29
|
-
)
|
30
|
-
except subprocess.CalledProcessError:
|
31
|
-
# If uv fails, fall back to pip
|
32
|
-
print("uv command failed, falling back to pip...")
|
33
|
-
|
34
|
-
# Fall back to pip
|
35
|
-
return subprocess.run(
|
36
|
-
[sys.executable, "-m", "pip"] + list(args),
|
37
|
-
check=True,
|
38
|
-
capture_output=True,
|
39
|
-
)
|
40
|
-
|
41
|
-
|
42
|
-
def check_import(
|
43
|
-
package_name: str,
|
44
|
-
module_name: str | None = None,
|
45
|
-
import_name: str | None = None,
|
46
|
-
pip_name: str | None = None,
|
47
|
-
attempt_install: bool = True,
|
48
|
-
error_message: str = "",
|
49
|
-
):
|
50
|
-
"""
|
51
|
-
Check if a package is installed, attempt to install if not.
|
52
|
-
|
53
|
-
Args:
|
54
|
-
package_name: The name of the package to check.
|
55
|
-
module_name: The specific module to import (if any).
|
56
|
-
import_name: The specific name to import from the module (if any).
|
57
|
-
pip_name: The name to use for pip installation (if different).
|
58
|
-
attempt_install: Whether to attempt installation if not found.
|
59
|
-
error_message: Custom error message to use if package not found.
|
60
|
-
|
61
|
-
Raises:
|
62
|
-
ImportError: If the package is not found and not installed.
|
63
|
-
ValueError: If the import fails after installation attempt.
|
64
|
-
"""
|
65
|
-
if not is_import_installed(package_name):
|
66
|
-
if attempt_install:
|
67
|
-
logging.info(
|
68
|
-
f"Package {package_name} not found. Attempting " "to install.",
|
69
|
-
)
|
70
|
-
try:
|
71
|
-
return install_import(
|
72
|
-
package_name=package_name,
|
73
|
-
module_name=module_name,
|
74
|
-
import_name=import_name,
|
75
|
-
pip_name=pip_name,
|
76
|
-
)
|
77
|
-
except ImportError as e:
|
78
|
-
raise ValueError(
|
79
|
-
f"Failed to install {package_name}: {e}"
|
80
|
-
) from e
|
81
|
-
else:
|
82
|
-
logging.info(
|
83
|
-
f"Package {package_name} not found. {error_message}",
|
84
|
-
)
|
85
|
-
raise ImportError(
|
86
|
-
f"Package {package_name} not found. {error_message}",
|
87
|
-
)
|
88
|
-
|
89
|
-
return import_module(
|
90
|
-
package_name=package_name,
|
91
|
-
module_name=module_name,
|
92
|
-
import_name=import_name,
|
93
|
-
)
|
94
|
-
|
95
|
-
|
96
|
-
def import_module(
|
97
|
-
package_name: str,
|
98
|
-
module_name: str = None,
|
99
|
-
import_name: str | list = None,
|
100
|
-
) -> Any:
|
101
|
-
"""
|
102
|
-
Import a module by its path.
|
103
|
-
|
104
|
-
Args:
|
105
|
-
module_path: The path of the module to import.
|
106
|
-
|
107
|
-
Returns:
|
108
|
-
The imported module.
|
109
|
-
|
110
|
-
Raises:
|
111
|
-
ImportError: If the module cannot be imported.
|
112
|
-
"""
|
113
|
-
try:
|
114
|
-
full_import_path = (
|
115
|
-
f"{package_name}.{module_name}" if module_name else package_name
|
116
|
-
)
|
117
|
-
|
118
|
-
if import_name:
|
119
|
-
import_name = (
|
120
|
-
[import_name]
|
121
|
-
if not isinstance(import_name, list)
|
122
|
-
else import_name
|
123
|
-
)
|
124
|
-
a = __import__(
|
125
|
-
full_import_path,
|
126
|
-
fromlist=import_name,
|
127
|
-
)
|
128
|
-
if len(import_name) == 1:
|
129
|
-
return getattr(a, import_name[0])
|
130
|
-
return [getattr(a, name) for name in import_name]
|
131
|
-
else:
|
132
|
-
return __import__(full_import_path)
|
133
|
-
|
134
|
-
except ImportError as e:
|
135
|
-
raise ImportError(
|
136
|
-
f"Failed to import module {full_import_path}: {e}"
|
137
|
-
) from e
|
138
|
-
|
139
|
-
|
140
|
-
def install_import(
|
141
|
-
package_name: str,
|
142
|
-
module_name: str | None = None,
|
143
|
-
import_name: str | None = None,
|
144
|
-
pip_name: str | None = None,
|
145
|
-
):
|
146
|
-
"""
|
147
|
-
Attempt to import a package, installing it if not found.
|
148
|
-
|
149
|
-
Args:
|
150
|
-
package_name: The name of the package to import.
|
151
|
-
module_name: The specific module to import (if any).
|
152
|
-
import_name: The specific name to import from the module (if any).
|
153
|
-
pip_name: The name to use for pip installation (if different).
|
154
|
-
|
155
|
-
Raises:
|
156
|
-
ImportError: If the package cannot be imported or installed.
|
157
|
-
subprocess.CalledProcessError: If pip installation fails.
|
158
|
-
"""
|
159
|
-
pip_name = pip_name or package_name
|
160
|
-
|
161
|
-
try:
|
162
|
-
return import_module(
|
163
|
-
package_name=package_name,
|
164
|
-
module_name=module_name,
|
165
|
-
import_name=import_name,
|
166
|
-
)
|
167
|
-
except ImportError:
|
168
|
-
logging.info(f"Installing {pip_name}...")
|
169
|
-
try:
|
170
|
-
run_package_manager_command(["install", pip_name])
|
171
|
-
return import_module(
|
172
|
-
package_name=package_name,
|
173
|
-
module_name=module_name,
|
174
|
-
import_name=import_name,
|
175
|
-
)
|
176
|
-
except subprocess.CalledProcessError as e:
|
177
|
-
raise ImportError(f"Failed to install {pip_name}: {e}") from e
|
178
|
-
except ImportError as e:
|
179
|
-
raise ImportError(
|
180
|
-
f"Failed to import {pip_name} after installation: {e}"
|
181
|
-
) from e
|
5
|
+
from lionagi.utils import (
|
6
|
+
check_import,
|
7
|
+
import_module,
|
8
|
+
install_import,
|
9
|
+
is_import_installed,
|
10
|
+
run_package_manager_command,
|
11
|
+
)
|
182
12
|
|
13
|
+
# backward compatibility
|
183
14
|
|
184
15
|
__all__ = (
|
185
16
|
"run_package_manager_command",
|
lionagi/libs/parse.py
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2023 - 2025, HaiyangLi <quantocean.li at gmail dot com>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
|
5
|
+
from lionagi.libs.schema.as_readable import as_readable
|
6
|
+
from lionagi.libs.schema.extract_code_block import extract_code_block
|
7
|
+
from lionagi.libs.schema.function_to_schema import function_to_schema
|
8
|
+
from lionagi.libs.validate.fuzzy_match_keys import fuzzy_match_keys
|
9
|
+
from lionagi.libs.validate.fuzzy_validate_mapping import fuzzy_validate_mapping
|
10
|
+
from lionagi.libs.validate.string_similarity import string_similarity
|
11
|
+
from lionagi.utils import fuzzy_parse_json, to_dict, to_json, to_num
|
12
|
+
|
13
|
+
validate_keys = fuzzy_match_keys # for backward compatibility
|
14
|
+
validate_mapping = fuzzy_validate_mapping # for backward compatibility
|
15
|
+
|
16
|
+
|
17
|
+
__all__ = (
|
18
|
+
"as_readable",
|
19
|
+
"extract_code_block",
|
20
|
+
"function_to_schema",
|
21
|
+
"fuzzy_match_keys",
|
22
|
+
"fuzzy_validate_mapping",
|
23
|
+
"string_similarity",
|
24
|
+
"validate_keys",
|
25
|
+
"validate_mapping",
|
26
|
+
"to_dict",
|
27
|
+
"to_json",
|
28
|
+
"to_num",
|
29
|
+
"fuzzy_parse_json",
|
30
|
+
)
|
@@ -1,52 +1,52 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
"options": {
|
3
|
+
"math": {
|
4
|
+
"name": "Mathematical Framework",
|
5
|
+
"description": "Offers a suite of math glyphs and notation rules.",
|
6
|
+
"glyphs": [
|
7
|
+
{
|
8
|
+
"symbol": "\u21b9",
|
9
|
+
"name": "Focus/Filter",
|
10
|
+
"description": "Used for focusing instructions"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"symbol": "\u03a3",
|
14
|
+
"name": "Summarize",
|
15
|
+
"description": "Condense large sets of data"
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"symbol": "\u2295",
|
19
|
+
"name": "Combine/Merge",
|
20
|
+
"description": "Merge multiple data sources"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"symbol": "\u2022",
|
24
|
+
"name": "Group Operation",
|
25
|
+
"description": "Binary operation in group theory"
|
26
|
+
}
|
27
|
+
]
|
11
28
|
},
|
12
|
-
{
|
13
|
-
|
14
|
-
|
15
|
-
|
29
|
+
"optim": {
|
30
|
+
"name": "Optimization Framework",
|
31
|
+
"description": "Compression and optimization for code/math expressions.",
|
32
|
+
"glyphs": [
|
33
|
+
{
|
34
|
+
"symbol": "IF",
|
35
|
+
"name": "Conditional Operator",
|
36
|
+
"description": "Represents branching logic"
|
37
|
+
}
|
38
|
+
]
|
16
39
|
},
|
17
|
-
{
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
]
|
28
|
-
},
|
29
|
-
"optim": {
|
30
|
-
"name": "Optimization Framework",
|
31
|
-
"description": "Compression and optimization for code/math expressions.",
|
32
|
-
"glyphs": [
|
33
|
-
{
|
34
|
-
"symbol": "IF",
|
35
|
-
"name": "Conditional Operator",
|
36
|
-
"description": "Represents branching logic"
|
37
|
-
}
|
38
|
-
]
|
39
|
-
},
|
40
|
-
"custom_algebra": {
|
41
|
-
"name": "Custom Algebraic Framework",
|
42
|
-
"description": "Extra rules for ring, group, field expansions.",
|
43
|
-
"glyphs": [
|
44
|
-
{
|
45
|
-
"symbol": "\u221e",
|
46
|
-
"name": "Infinite Operator",
|
47
|
-
"description": "Represents unbounded algebraic ops"
|
40
|
+
"custom_algebra": {
|
41
|
+
"name": "Custom Algebraic Framework",
|
42
|
+
"description": "Extra rules for ring, group, field expansions.",
|
43
|
+
"glyphs": [
|
44
|
+
{
|
45
|
+
"symbol": "\u221e",
|
46
|
+
"name": "Infinite Operator",
|
47
|
+
"description": "Represents unbounded algebraic ops"
|
48
|
+
}
|
49
|
+
]
|
48
50
|
}
|
49
|
-
]
|
50
51
|
}
|
51
|
-
}
|
52
52
|
}
|
lionagi/protocols/generic/log.py
CHANGED
@@ -11,8 +11,7 @@ from typing import Any
|
|
11
11
|
|
12
12
|
from pydantic import BaseModel, Field, PrivateAttr, field_validator
|
13
13
|
|
14
|
-
from lionagi.
|
15
|
-
from lionagi.utils import to_dict
|
14
|
+
from lionagi.utils import create_path, to_dict
|
16
15
|
|
17
16
|
from .._concepts import Manager
|
18
17
|
from .element import Element
|
@@ -19,14 +19,10 @@ message_text = template.render(**args)
|
|
19
19
|
print(message_text)
|
20
20
|
```
|
21
21
|
|
22
|
-
Benefits and Customization
|
23
|
-
templates without changing your code logic.
|
24
|
-
separated, making it simpler to maintain or adjust one message format without
|
25
|
-
|
26
|
-
|
27
|
-
template (like tool_schemas.jinja2) and include it where needed. • Over time,
|
28
|
-
you can add more templates or split existing ones if certain messages become too
|
29
|
-
complex.
|
22
|
+
Benefits and Customization
|
23
|
+
• You can easily rearrange sections within these templates without changing your code logic.
|
24
|
+
• Each message type is clearly separated, making it simpler to maintain or adjust one message format without affecting the others.
|
25
|
+
• If you find that you use some snippet (like rendering a schema) in multiple templates, you can factor it out into its own partial template (like tool_schemas.jinja2) and include it where needed.
|
26
|
+
• Over time, you can add more templates or split existing ones if certain messages become too complex.
|
30
27
|
|
31
|
-
By establishing this set of base templates and arguments, you have a starting
|
32
|
-
point. You can expand or refine as your requirements evolve.
|
28
|
+
By establishing this set of base templates and arguments, you have a starting point. You can expand or refine as your requirements evolve.
|
@@ -1,3 +1,160 @@
|
|
1
|
-
from
|
1
|
+
from enum import Enum
|
2
2
|
|
3
|
-
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
|
5
|
+
|
6
|
+
class CategoryEnum(str, Enum):
|
7
|
+
company = "company"
|
8
|
+
research_paper = "research paper"
|
9
|
+
news = "news"
|
10
|
+
pdf = "pdf"
|
11
|
+
github = "github"
|
12
|
+
tweet = "tweet"
|
13
|
+
personal_site = "personal site"
|
14
|
+
linkedin_profile = "linkedin profile"
|
15
|
+
financial_report = "financial report"
|
16
|
+
|
17
|
+
|
18
|
+
class LivecrawlEnum(str, Enum):
|
19
|
+
never = "never"
|
20
|
+
fallback = "fallback"
|
21
|
+
always = "always"
|
22
|
+
|
23
|
+
|
24
|
+
class SearchTypeEnum(str, Enum):
|
25
|
+
keyword = "keyword"
|
26
|
+
neural = "neural"
|
27
|
+
auto = "auto"
|
28
|
+
|
29
|
+
|
30
|
+
class ContentsText(BaseModel):
|
31
|
+
includeHtmlTags: bool | None = Field(
|
32
|
+
default=False,
|
33
|
+
description="Whether to include HTML tags in the text. Set to True if you want to retain HTML structure for the LLM to interpret.",
|
34
|
+
)
|
35
|
+
maxCharacters: int | None = Field(
|
36
|
+
default=None,
|
37
|
+
description="The maximum number of characters to return from the webpage text.",
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
class ContentsHighlights(BaseModel):
|
42
|
+
highlightsPerUrl: int | None = Field(
|
43
|
+
default=1,
|
44
|
+
description="The number of highlight snippets you want per page.",
|
45
|
+
)
|
46
|
+
numSentences: int | None = Field(
|
47
|
+
default=5,
|
48
|
+
description="Number of sentences to return in each highlight snippet.",
|
49
|
+
)
|
50
|
+
query: None | str = Field(
|
51
|
+
default=None,
|
52
|
+
description="A specific query used to generate the highlight snippets.",
|
53
|
+
)
|
54
|
+
|
55
|
+
|
56
|
+
class ContentsSummary(BaseModel):
|
57
|
+
query: None | str = Field(
|
58
|
+
default=None,
|
59
|
+
description="A specific query used to generate a summary of the webpage.",
|
60
|
+
)
|
61
|
+
|
62
|
+
|
63
|
+
class ContentsExtras(BaseModel):
|
64
|
+
links: int | None = Field(
|
65
|
+
default=None, description="Number of links to return from each page."
|
66
|
+
)
|
67
|
+
imageLinks: int | None = Field(
|
68
|
+
default=None, description="Number of images to return for each result."
|
69
|
+
)
|
70
|
+
|
71
|
+
|
72
|
+
class Contents(BaseModel):
|
73
|
+
text: None | ContentsText = Field(
|
74
|
+
default=None,
|
75
|
+
description="Return full or partial text for each page, with optional HTML structure or size limit.",
|
76
|
+
)
|
77
|
+
highlights: None | ContentsHighlights = Field(
|
78
|
+
default=None, description="Return snippet highlights for each page."
|
79
|
+
)
|
80
|
+
summary: None | ContentsSummary = Field(
|
81
|
+
default=None, description="Return a short summary of each page."
|
82
|
+
)
|
83
|
+
livecrawl: None | LivecrawlEnum = Field(
|
84
|
+
default=LivecrawlEnum.never,
|
85
|
+
description="Livecrawling setting for each page. Options: never, fallback, always.",
|
86
|
+
)
|
87
|
+
livecrawlTimeout: int | None = Field(
|
88
|
+
default=10000,
|
89
|
+
description="Timeout in milliseconds for livecrawling. Default 10000.",
|
90
|
+
)
|
91
|
+
subpages: int | None = Field(
|
92
|
+
default=None,
|
93
|
+
description="Number of subpages to crawl within each URL.",
|
94
|
+
)
|
95
|
+
subpageTarget: None | str | list[str] = Field(
|
96
|
+
default=None,
|
97
|
+
description="A target subpage or multiple subpages (list) to crawl, e.g. 'cited papers'.",
|
98
|
+
)
|
99
|
+
extras: None | ContentsExtras = Field(
|
100
|
+
default=None,
|
101
|
+
description="Additional extras like links or images to return for each page.",
|
102
|
+
)
|
103
|
+
|
104
|
+
|
105
|
+
class ExaSearchRequest(BaseModel):
|
106
|
+
query: str = Field(
|
107
|
+
...,
|
108
|
+
description="The main query string describing what you're looking for.",
|
109
|
+
)
|
110
|
+
category: None | CategoryEnum = Field(
|
111
|
+
default=None,
|
112
|
+
description="A data category to focus on, such as 'company', 'research paper', 'news', etc.",
|
113
|
+
)
|
114
|
+
type: None | SearchTypeEnum = Field(
|
115
|
+
default=None,
|
116
|
+
description="The type of search to run. Can be 'auto', 'keyword', or 'neural'.",
|
117
|
+
)
|
118
|
+
useAutoprompt: None | bool = Field(
|
119
|
+
default=False,
|
120
|
+
description="If True, Exa auto-optimizes your query for best results (neural or auto search only).",
|
121
|
+
)
|
122
|
+
numResults: int | None = Field(
|
123
|
+
default=10, description="Number of results to return. Default is 10."
|
124
|
+
)
|
125
|
+
includeDomains: None | list[str] = Field(
|
126
|
+
default=None,
|
127
|
+
description="List of domains you want to include exclusively.",
|
128
|
+
)
|
129
|
+
excludeDomains: None | list[str] = Field(
|
130
|
+
default=None,
|
131
|
+
description="List of domains you do NOT want to see in the results.",
|
132
|
+
)
|
133
|
+
startCrawlDate: None | str = Field(
|
134
|
+
default=None,
|
135
|
+
description="Include results crawled after this ISO date (e.g., '2023-01-01T00:00:00.000Z').",
|
136
|
+
)
|
137
|
+
endCrawlDate: None | str = Field(
|
138
|
+
default=None,
|
139
|
+
description="Include results crawled before this ISO date.",
|
140
|
+
)
|
141
|
+
startPublishedDate: None | str = Field(
|
142
|
+
default=None,
|
143
|
+
description="Only return results published after this ISO date.",
|
144
|
+
)
|
145
|
+
endPublishedDate: None | str = Field(
|
146
|
+
default=None,
|
147
|
+
description="Only return results published before this ISO date.",
|
148
|
+
)
|
149
|
+
includeText: None | list[str] = Field(
|
150
|
+
default=None,
|
151
|
+
description="Strings that must appear in the webpage text. Only a single string up to 5 words is currently supported.",
|
152
|
+
)
|
153
|
+
excludeText: None | list[str] = Field(
|
154
|
+
default=None,
|
155
|
+
description="Strings that must NOT appear in the webpage text. Only a single string up to 5 words is currently supported.",
|
156
|
+
)
|
157
|
+
contents: None | Contents = Field(
|
158
|
+
default=None,
|
159
|
+
description="Dict defining the different ways you want to retrieve webpage contents, including text, highlights, or summaries.",
|
160
|
+
)
|