hiagent-components 0.1.0__tar.gz

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 (25) hide show
  1. hiagent_components-0.1.0/.gitignore +169 -0
  2. hiagent_components-0.1.0/PKG-INFO +14 -0
  3. hiagent_components-0.1.0/README.md +1 -0
  4. hiagent_components-0.1.0/hiagent_components/__init__.py +13 -0
  5. hiagent_components-0.1.0/hiagent_components/agent/__init__.py +16 -0
  6. hiagent_components-0.1.0/hiagent_components/agent/base.py +260 -0
  7. hiagent_components-0.1.0/hiagent_components/base/__init__.py +18 -0
  8. hiagent_components-0.1.0/hiagent_components/base/base.py +218 -0
  9. hiagent_components-0.1.0/hiagent_components/base/utils.py +61 -0
  10. hiagent_components-0.1.0/hiagent_components/integrations/__init__.py +13 -0
  11. hiagent_components-0.1.0/hiagent_components/integrations/langchain/__init__.py +20 -0
  12. hiagent_components-0.1.0/hiagent_components/integrations/langchain/retriever.py +71 -0
  13. hiagent_components-0.1.0/hiagent_components/integrations/langchain/tool.py +34 -0
  14. hiagent_components-0.1.0/hiagent_components/integrations/mcp/tool.py +43 -0
  15. hiagent_components-0.1.0/hiagent_components/retriever/__init__.py +16 -0
  16. hiagent_components-0.1.0/hiagent_components/retriever/base.py +218 -0
  17. hiagent_components-0.1.0/hiagent_components/tool/__init__.py +19 -0
  18. hiagent_components-0.1.0/hiagent_components/tool/base.py +68 -0
  19. hiagent_components-0.1.0/hiagent_components/tool/tool.py +257 -0
  20. hiagent_components-0.1.0/hiagent_components/utils/__init__.py +13 -0
  21. hiagent_components-0.1.0/hiagent_components/utils/schema.py +177 -0
  22. hiagent_components-0.1.0/hiagent_components/workflow/__init__.py +16 -0
  23. hiagent_components-0.1.0/hiagent_components/workflow/base.py +253 -0
  24. hiagent_components-0.1.0/hiagent_components/workflow/utils.py +24 -0
  25. hiagent_components-0.1.0/pyproject.toml +33 -0
@@ -0,0 +1,169 @@
1
+ ### Python template
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # poetry
99
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
103
+ #poetry.lock
104
+
105
+ # pdm
106
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
107
+ #pdm.lock
108
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
109
+ # in version control.
110
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
111
+ .pdm.toml
112
+ .pdm-python
113
+ .pdm-build/
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ #.idea/
164
+
165
+ chainlit.md
166
+ .chainlit/
167
+ .vscode
168
+ .idea
169
+ license.py
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: hiagent-components
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: hiagent-api<0.2.0,>=0.1.0
7
+ Requires-Dist: json-schema-to-pydantic>=0.2.6
8
+ Requires-Dist: pydantic>=2.11.5
9
+ Requires-Dist: python-dotenv>=1.1.0
10
+ Requires-Dist: strenum>=0.4.15
11
+ Requires-Dist: tenacity>=9.1.2
12
+ Description-Content-Type: text/markdown
13
+
14
+ HiAgent-Components SDK
@@ -0,0 +1 @@
1
+ HiAgent-Components SDK
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,16 @@
1
+ # Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from .base import Agent
15
+
16
+ __all__ = ["Agent"]
@@ -0,0 +1,260 @@
1
+ # Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from concurrent.futures import Executor
15
+ from io import StringIO
16
+ from typing import Any, AsyncIterator, Iterator, Optional
17
+
18
+ from hiagent_api.chat import ChatService
19
+ from hiagent_api.chat_types import (
20
+ ChatEvent,
21
+ ChatRequest,
22
+ CreateConversationRequest,
23
+ GetAppConfigPreviewRequest,
24
+ MessageChatEvent,
25
+ StreamingChatEventType,
26
+ ToolMessageChatEvent,
27
+ )
28
+
29
+ from hiagent_components.base.base import Executable
30
+
31
+
32
+ class Agent(Executable):
33
+ def __init__(
34
+ self,
35
+ svc: ChatService,
36
+ app_key: str,
37
+ user_id: str,
38
+ conversation_id: str,
39
+ name: str,
40
+ description: str,
41
+ ) -> None:
42
+ self.svc = svc
43
+ self.app_key = app_key
44
+ self.user_id = user_id
45
+ self.conversation_id = conversation_id
46
+ self.name = name or ""
47
+ self.description = description or ""
48
+
49
+ @property
50
+ def input_schema(self) -> dict:
51
+ return {
52
+ "type": "object",
53
+ "properties": {
54
+ "query": {
55
+ "type": "string",
56
+ "description": "需要智能体解决的原始问题",
57
+ }
58
+ },
59
+ "required": ["query"],
60
+ }
61
+
62
+ @classmethod
63
+ def init(
64
+ cls,
65
+ svc: ChatService,
66
+ app_key: str,
67
+ user_id: str,
68
+ variables: dict,
69
+ conversation_id: Optional[str] = None,
70
+ name: Optional[str] = None,
71
+ description: Optional[str] = None,
72
+ ) -> "Agent":
73
+ resp = svc.get_app(
74
+ app_key=app_key,
75
+ params=GetAppConfigPreviewRequest(
76
+ app_key=app_key,
77
+ user_id=user_id,
78
+ ),
79
+ )
80
+ if not name:
81
+ name = resp.name
82
+ if not description:
83
+ description = ""
84
+
85
+ if not conversation_id:
86
+ resp = svc.create_conversation(
87
+ app_key=app_key,
88
+ conversation=CreateConversationRequest(
89
+ app_key=app_key,
90
+ inputs=variables,
91
+ user_id=user_id,
92
+ ),
93
+ )
94
+ conversation_id = resp.conversation.app_conversation_id
95
+
96
+ agent = cls(
97
+ svc=svc,
98
+ app_key=app_key,
99
+ user_id=user_id,
100
+ conversation_id=conversation_id,
101
+ name=name,
102
+ description=description,
103
+ )
104
+
105
+ return agent
106
+
107
+ @classmethod
108
+ async def ainit(
109
+ cls,
110
+ svc: ChatService,
111
+ app_key: str,
112
+ user_id: str,
113
+ variables: dict,
114
+ conversation_id: Optional[str] = None,
115
+ name: Optional[str] = None,
116
+ description: Optional[str] = None,
117
+ ) -> "Agent":
118
+ resp = await svc.aget_app(
119
+ app_key=app_key,
120
+ params=GetAppConfigPreviewRequest(
121
+ app_key=app_key,
122
+ user_id=user_id,
123
+ ),
124
+ )
125
+ if not name:
126
+ name = resp.name
127
+ if not description:
128
+ description = ""
129
+
130
+ if not conversation_id:
131
+ resp = svc.create_conversation(
132
+ app_key=app_key,
133
+ conversation=CreateConversationRequest(
134
+ app_key=app_key,
135
+ inputs=variables,
136
+ user_id=user_id,
137
+ ),
138
+ )
139
+ conversation_id = resp.conversation.app_conversation_id
140
+
141
+ agent = cls(
142
+ svc=svc,
143
+ app_key=app_key,
144
+ user_id=user_id,
145
+ conversation_id=conversation_id,
146
+ name=name,
147
+ description=description,
148
+ )
149
+
150
+ return agent
151
+
152
+ def invoke(
153
+ self,
154
+ input: dict,
155
+ **kwargs: Any,
156
+ ) -> str:
157
+ query = input.get("query")
158
+ if not query:
159
+ raise ValueError("agent invoke input should contains 'query'")
160
+
161
+ resp_generator = self.svc.chat_streaming(
162
+ self.app_key,
163
+ ChatRequest(
164
+ app_key=self.app_key,
165
+ app_conversation_id=self.conversation_id,
166
+ query=query,
167
+ response_mode="streaming",
168
+ user_id=self.user_id,
169
+ ),
170
+ )
171
+
172
+ output = StringIO()
173
+ for event in resp_generator:
174
+ if event.event == StreamingChatEventType.tool_message:
175
+ assert isinstance(event, ToolMessageChatEvent)
176
+ output.write(event.answer)
177
+ elif event.event == StreamingChatEventType.message:
178
+ assert isinstance(event, MessageChatEvent)
179
+ output.write(event.answer)
180
+
181
+ return output.getvalue()
182
+
183
+ async def ainvoke(
184
+ self,
185
+ input: dict,
186
+ executor: Optional[Executor] = None,
187
+ **kwargs: Any,
188
+ ) -> str:
189
+ query = input.get("query")
190
+ if not query:
191
+ raise ValueError("agent invoke input should contains 'query'")
192
+
193
+ resp_generator = self.svc.achat_streaming(
194
+ self.app_key,
195
+ ChatRequest(
196
+ app_key=self.app_key,
197
+ app_conversation_id=self.conversation_id,
198
+ query=query,
199
+ response_mode="streaming",
200
+ user_id=self.user_id,
201
+ ),
202
+ )
203
+
204
+ output = StringIO()
205
+ async for event in resp_generator:
206
+ if event.event == StreamingChatEventType.tool_message:
207
+ assert isinstance(event, ToolMessageChatEvent)
208
+ output.write(event.answer)
209
+ elif event.event == StreamingChatEventType.tool_message_output_end:
210
+ output.write("\n\n")
211
+ elif event.event == StreamingChatEventType.message:
212
+ assert isinstance(event, MessageChatEvent)
213
+ output.write(event.answer)
214
+
215
+ return output.getvalue()
216
+
217
+ def stream(
218
+ self,
219
+ input: dict,
220
+ **kwargs: Optional[Any],
221
+ ) -> Iterator[ChatEvent]:
222
+ query = input.get("query")
223
+ if not query:
224
+ raise ValueError("agent invoke input should contains 'query'")
225
+
226
+ resp_generator = self.svc.chat_streaming(
227
+ self.app_key,
228
+ ChatRequest(
229
+ app_key=self.app_key,
230
+ app_conversation_id=self.conversation_id,
231
+ query=query,
232
+ response_mode="streaming",
233
+ user_id=self.user_id,
234
+ ),
235
+ )
236
+
237
+ return resp_generator
238
+
239
+ async def astream(
240
+ self,
241
+ input: dict,
242
+ **kwargs: Optional[Any],
243
+ ) -> AsyncIterator[ChatEvent]:
244
+ query = input.get("query")
245
+ if not query:
246
+ raise ValueError("agent invoke input should contains 'query'")
247
+
248
+ resp_generator = self.svc.achat_streaming(
249
+ self.app_key,
250
+ ChatRequest(
251
+ app_key=self.app_key,
252
+ app_conversation_id=self.conversation_id,
253
+ query=query,
254
+ response_mode="streaming",
255
+ user_id=self.user_id,
256
+ ),
257
+ )
258
+
259
+ async for event in resp_generator:
260
+ yield event
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from __future__ import annotations
15
+
16
+ from .base import Executable
17
+
18
+ __all__ = ["Executable"]
@@ -0,0 +1,218 @@
1
+ # Copyright (c) 2024 Bytedance Ltd. and/or its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from __future__ import annotations
15
+
16
+ from abc import ABC, abstractmethod
17
+ from concurrent.futures import Executor
18
+ from typing import (
19
+ TYPE_CHECKING,
20
+ Any,
21
+ AsyncIterator,
22
+ Dict,
23
+ Generic,
24
+ Iterator,
25
+ Optional,
26
+ Tuple,
27
+ Type,
28
+ TypeVar,
29
+ Union,
30
+ cast,
31
+ )
32
+
33
+ from tenacity import (
34
+ AsyncRetrying,
35
+ Retrying,
36
+ retry_if_exception_type,
37
+ stop_after_attempt,
38
+ wait_exponential_jitter,
39
+ )
40
+
41
+ from hiagent_components.base.utils import (
42
+ gather_with_concurrency,
43
+ get_executor,
44
+ run_in_executor,
45
+ )
46
+
47
+ if TYPE_CHECKING:
48
+ from hiagent_components.tool.base import BaseTool
49
+
50
+
51
+ Input = TypeVar("Input", contravariant=True)
52
+ Output = TypeVar("Output", covariant=True)
53
+
54
+
55
+ class Executable(Generic[Input, Output], ABC):
56
+ name: str
57
+
58
+ description: str
59
+
60
+ @property
61
+ def input_schema(self) -> dict[str, Any]: ...
62
+
63
+ def stream(
64
+ self,
65
+ input: Input,
66
+ **kwargs: Optional[Any],
67
+ ) -> Iterator[Output]:
68
+ yield self.invoke(input, **kwargs)
69
+
70
+ async def astream(
71
+ self,
72
+ input: Input,
73
+ **kwargs: Optional[Any],
74
+ ) -> AsyncIterator[Output]:
75
+ yield await self.ainvoke(input, None, **kwargs)
76
+
77
+ def batch(
78
+ self,
79
+ inputs: list[Input],
80
+ max_parallel: int,
81
+ return_exceptions: bool = False,
82
+ **kwargs: Optional[Any],
83
+ ) -> list[Output]:
84
+ if not inputs:
85
+ return []
86
+
87
+ def invoke(input: Input) -> Union[Output, Exception]:
88
+ if return_exceptions:
89
+ try:
90
+ return self.invoke(input, **kwargs)
91
+ except Exception as e:
92
+ return e
93
+ else:
94
+ return self.invoke(input, **kwargs)
95
+
96
+ if len(inputs) == 1:
97
+ return cast("list[Output]", [invoke(inputs[0])])
98
+
99
+ with get_executor(max_parallel) as executor:
100
+ return cast("list[Output]", list[executor.map(invoke, inputs)])
101
+
102
+ async def abatch(
103
+ self,
104
+ inputs: list[Input],
105
+ max_parallel: int,
106
+ return_exceptions: bool = False,
107
+ **kwargs: Optional[Any],
108
+ ) -> list[Output]:
109
+ if not inputs:
110
+ return []
111
+
112
+ with get_executor(max_parallel) as executor:
113
+
114
+ async def ainvoke(
115
+ input: Input,
116
+ ) -> Union[Output, Exception]:
117
+ if return_exceptions:
118
+ try:
119
+ return await self.ainvoke(input, executor, **kwargs)
120
+ except Exception as e:
121
+ return e
122
+ else:
123
+ return await self.ainvoke(input, executor, **kwargs)
124
+
125
+ coros = map(ainvoke, inputs)
126
+ return await gather_with_concurrency(max_parallel, *coros)
127
+
128
+ def with_retry(
129
+ self,
130
+ retry_exception_types: Tuple[Type[BaseException]] = (Exception,),
131
+ wait_exponential_jitter: bool = True,
132
+ max_attempts: int = 3,
133
+ ) -> Executable[Input, Output]:
134
+ return RetryableExecutable(self, retry_exception_types, wait_exponential_jitter, max_attempts)
135
+
136
+ def as_tool(
137
+ self,
138
+ name: Optional[str] = None,
139
+ description: Optional[str] = None,
140
+ ) -> BaseTool:
141
+ from hiagent_components.tool.tool import ExecutableTool
142
+
143
+ return ExecutableTool.from_executable(self, name, description)
144
+
145
+ @abstractmethod
146
+ def invoke(self, input: Input, **kwargs: Any) -> Output: ...
147
+
148
+ async def ainvoke(
149
+ self,
150
+ input: Input,
151
+ executor: Optional[Executor] = None,
152
+ **kwargs: Any,
153
+ ) -> Output:
154
+ return await run_in_executor(executor, self.invoke, input, **kwargs)
155
+
156
+ class RetryableExecutable(Executable[Input, Output]):
157
+ def __init__(
158
+ self,
159
+ executable: Executable[Input, Output],
160
+ retry_exception_types: Tuple[Type[BaseException], ...] = (Exception,),
161
+ wait_exponential_jitter: bool = True,
162
+ max_attempts: int = 3,
163
+ ):
164
+ self.max_attempts = max_attempts
165
+ self.retry_exception_types = retry_exception_types
166
+ self.wait_exponential_jitter = wait_exponential_jitter
167
+ self.executable = executable
168
+
169
+ @property
170
+ def _retrying_kwargs(self) -> Dict[str, Any]:
171
+ kwargs: Dict[str, Any] = dict()
172
+
173
+ if self.max_attempts:
174
+ kwargs["stop"] = stop_after_attempt(self.max_attempts)
175
+
176
+ if self.wait_exponential_jitter:
177
+ kwargs["wait"] = wait_exponential_jitter()
178
+
179
+ if self.retry_exception_types:
180
+ kwargs["retry"] = retry_if_exception_type(self.retry_exception_types)
181
+
182
+ return kwargs
183
+
184
+ def _sync_retrying(self, **kwargs: Any) -> Retrying:
185
+ return Retrying(**self._retrying_kwargs, **kwargs)
186
+
187
+ def _async_retrying(self, **kwargs: Any) -> AsyncRetrying:
188
+ return AsyncRetrying(**self._retrying_kwargs, **kwargs)
189
+
190
+ def invoke(self, input: Input, **kwargs: Any) -> Output:
191
+ result = None
192
+ for attempt in self._sync_retrying(reraise=True):
193
+ with attempt:
194
+ result = self.executable.invoke(
195
+ input,
196
+ **kwargs,
197
+ )
198
+ if attempt.retry_state.outcome and not attempt.retry_state.outcome.failed:
199
+ attempt.retry_state.set_result(result)
200
+ return result
201
+
202
+ async def ainvoke(
203
+ self,
204
+ input: Input,
205
+ executor: Optional[Executor] = None,
206
+ **kwargs: Any
207
+ ) -> Output:
208
+ result = None
209
+ async for attempt in self._async_retrying(reraise=True):
210
+ with attempt:
211
+ result = await self.executable.ainvoke(
212
+ input,
213
+ executor,
214
+ **kwargs,
215
+ )
216
+ if attempt.retry_state.outcome and not attempt.retry_state.outcome.failed:
217
+ attempt.retry_state.set_result(result)
218
+ return result