coco-framework 0.1.0__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.
- coco/__init__.py +3 -0
- coco/agents/__init__.py +9 -0
- coco/agents/_subagent_transformer.py +307 -0
- coco/agents/factory.py +2164 -0
- coco/agents/middleware/__init__.py +100 -0
- coco/agents/middleware/_execution.py +385 -0
- coco/agents/middleware/_redaction.py +454 -0
- coco/agents/middleware/_retry.py +134 -0
- coco/agents/middleware/_trace_policy.py +61 -0
- coco/agents/middleware/context_editing.py +306 -0
- coco/agents/middleware/file_search.py +433 -0
- coco/agents/middleware/human_in_the_loop.py +680 -0
- coco/agents/middleware/internal_call_transformer.py +108 -0
- coco/agents/middleware/model_call_limit.py +267 -0
- coco/agents/middleware/model_fallback.py +417 -0
- coco/agents/middleware/model_retry.py +327 -0
- coco/agents/middleware/pii.py +878 -0
- coco/agents/middleware/provider_tool_search.py +307 -0
- coco/agents/middleware/shell_tool.py +949 -0
- coco/agents/middleware/summarization.py +910 -0
- coco/agents/middleware/todo.py +357 -0
- coco/agents/middleware/tool_call_limit.py +495 -0
- coco/agents/middleware/tool_emulator.py +251 -0
- coco/agents/middleware/tool_error.py +209 -0
- coco/agents/middleware/tool_retry.py +421 -0
- coco/agents/middleware/tool_selection.py +515 -0
- coco/agents/middleware/types.py +2201 -0
- coco/agents/structured_output.py +472 -0
- coco/chat_models/__init__.py +7 -0
- coco/chat_models/base.py +1082 -0
- coco/embeddings/__init__.py +18 -0
- coco/embeddings/base.py +279 -0
- coco/mcp/__init__.py +36 -0
- coco/mcp/adapter.py +245 -0
- coco/mcp/elicitation.py +394 -0
- coco/mcp/tools.py +307 -0
- coco/messages/__init__.py +73 -0
- coco/py.typed +0 -0
- coco/rate_limiters/__init__.py +13 -0
- coco/tools/__init__.py +22 -0
- coco/tools/tool_node.py +20 -0
- coco_anthropic/__init__.py +15 -0
- coco_anthropic/_client_utils.py +81 -0
- coco_anthropic/_compat.py +228 -0
- coco_anthropic/_sdk_compat.py +124 -0
- coco_anthropic/_version.py +3 -0
- coco_anthropic/chat_models.py +3349 -0
- coco_anthropic/data/__init__.py +1 -0
- coco_anthropic/data/_profiles.py +491 -0
- coco_anthropic/data/profile_augmentations.toml +69 -0
- coco_anthropic/experimental.py +140 -0
- coco_anthropic/llms.py +428 -0
- coco_anthropic/middleware/__init__.py +25 -0
- coco_anthropic/middleware/anthropic_tools.py +1197 -0
- coco_anthropic/middleware/bash.py +84 -0
- coco_anthropic/middleware/file_search.py +360 -0
- coco_anthropic/middleware/prompt_caching.py +276 -0
- coco_anthropic/output_parsers.py +93 -0
- coco_anthropic/py.typed +0 -0
- coco_core/__init__.py +20 -0
- coco_core/_api/__init__.py +87 -0
- coco_core/_api/beta_decorator.py +266 -0
- coco_core/_api/deprecation.py +637 -0
- coco_core/_api/internal.py +23 -0
- coco_core/_api/path.py +50 -0
- coco_core/_import_utils.py +41 -0
- coco_core/_protocol.py +625 -0
- coco_core/_security/__init__.py +36 -0
- coco_core/_security/_exceptions.py +9 -0
- coco_core/_security/_policy.py +313 -0
- coco_core/_security/_ssrf_protection.py +155 -0
- coco_core/_security/_transport.py +254 -0
- coco_core/agents.py +258 -0
- coco_core/caches.py +272 -0
- coco_core/callbacks/__init__.py +132 -0
- coco_core/callbacks/base.py +1229 -0
- coco_core/callbacks/file.py +266 -0
- coco_core/callbacks/manager.py +2826 -0
- coco_core/callbacks/stdout.py +123 -0
- coco_core/callbacks/streaming_stdout.py +154 -0
- coco_core/callbacks/usage.py +124 -0
- coco_core/chat_history.py +267 -0
- coco_core/chat_loaders.py +26 -0
- coco_core/chat_sessions.py +19 -0
- coco_core/cross_encoders.py +18 -0
- coco_core/document_loaders/__init__.py +36 -0
- coco_core/document_loaders/base.py +155 -0
- coco_core/document_loaders/blob_loaders.py +38 -0
- coco_core/documents/__init__.py +55 -0
- coco_core/documents/base.py +347 -0
- coco_core/documents/compressor.py +74 -0
- coco_core/documents/transformers.py +79 -0
- coco_core/embeddings/__init__.py +31 -0
- coco_core/embeddings/embeddings.py +78 -0
- coco_core/embeddings/fake.py +129 -0
- coco_core/env.py +22 -0
- coco_core/example_selectors/__init__.py +47 -0
- coco_core/example_selectors/base.py +60 -0
- coco_core/example_selectors/length_based.py +131 -0
- coco_core/example_selectors/semantic_similarity.py +366 -0
- coco_core/exceptions.py +166 -0
- coco_core/globals.py +72 -0
- coco_core/indexing/__init__.py +53 -0
- coco_core/indexing/api.py +954 -0
- coco_core/indexing/base.py +661 -0
- coco_core/indexing/in_memory.py +104 -0
- coco_core/language_models/__init__.py +116 -0
- coco_core/language_models/_compat_bridge.py +844 -0
- coco_core/language_models/_utils.py +343 -0
- coco_core/language_models/base.py +500 -0
- coco_core/language_models/chat_model_stream.py +1525 -0
- coco_core/language_models/chat_models.py +2748 -0
- coco_core/language_models/fake.py +137 -0
- coco_core/language_models/fake_chat_models.py +396 -0
- coco_core/language_models/llms.py +1569 -0
- coco_core/language_models/model_profile.py +183 -0
- coco_core/load/__init__.py +44 -0
- coco_core/load/_validation.py +191 -0
- coco_core/load/dump.py +120 -0
- coco_core/load/load.py +828 -0
- coco_core/load/mapping.py +1097 -0
- coco_core/load/serializable.py +406 -0
- coco_core/messages/__init__.py +198 -0
- coco_core/messages/ai.py +854 -0
- coco_core/messages/base.py +518 -0
- coco_core/messages/block_translators/__init__.py +112 -0
- coco_core/messages/block_translators/anthropic.py +534 -0
- coco_core/messages/block_translators/bedrock.py +108 -0
- coco_core/messages/block_translators/bedrock_converse.py +329 -0
- coco_core/messages/block_translators/coco_v0.py +303 -0
- coco_core/messages/block_translators/google_genai.py +610 -0
- coco_core/messages/block_translators/google_vertexai.py +21 -0
- coco_core/messages/block_translators/groq.py +157 -0
- coco_core/messages/block_translators/openai.py +1089 -0
- coco_core/messages/chat.py +64 -0
- coco_core/messages/content.py +1488 -0
- coco_core/messages/function.py +62 -0
- coco_core/messages/human.py +70 -0
- coco_core/messages/modifier.py +33 -0
- coco_core/messages/system.py +70 -0
- coco_core/messages/tool.py +418 -0
- coco_core/messages/utils.py +2442 -0
- coco_core/output_parsers/__init__.py +101 -0
- coco_core/output_parsers/base.py +361 -0
- coco_core/output_parsers/format_instructions.py +16 -0
- coco_core/output_parsers/json.py +139 -0
- coco_core/output_parsers/list.py +249 -0
- coco_core/output_parsers/openai_functions.py +324 -0
- coco_core/output_parsers/openai_tools.py +383 -0
- coco_core/output_parsers/pydantic.py +141 -0
- coco_core/output_parsers/string.py +63 -0
- coco_core/output_parsers/transform.py +175 -0
- coco_core/output_parsers/xml.py +301 -0
- coco_core/outputs/__init__.py +66 -0
- coco_core/outputs/chat_generation.py +147 -0
- coco_core/outputs/chat_result.py +39 -0
- coco_core/outputs/generation.py +80 -0
- coco_core/outputs/llm_result.py +112 -0
- coco_core/outputs/run_info.py +22 -0
- coco_core/prompt_values.py +161 -0
- coco_core/prompts/__init__.py +101 -0
- coco_core/prompts/base.py +508 -0
- coco_core/prompts/chat.py +1495 -0
- coco_core/prompts/dict.py +177 -0
- coco_core/prompts/few_shot.py +483 -0
- coco_core/prompts/few_shot_with_templates.py +239 -0
- coco_core/prompts/image.py +177 -0
- coco_core/prompts/loading.py +296 -0
- coco_core/prompts/message.py +97 -0
- coco_core/prompts/prompt.py +312 -0
- coco_core/prompts/string.py +399 -0
- coco_core/prompts/structured.py +214 -0
- coco_core/py.typed +0 -0
- coco_core/rate_limiters.py +254 -0
- coco_core/retrievers.py +328 -0
- coco_core/runnables/__init__.py +136 -0
- coco_core/runnables/base.py +6725 -0
- coco_core/runnables/branch.py +457 -0
- coco_core/runnables/config.py +712 -0
- coco_core/runnables/configurable.py +710 -0
- coco_core/runnables/fallbacks.py +663 -0
- coco_core/runnables/graph.py +741 -0
- coco_core/runnables/graph_ascii.py +366 -0
- coco_core/runnables/graph_mermaid.py +503 -0
- coco_core/runnables/graph_png.py +215 -0
- coco_core/runnables/history.py +631 -0
- coco_core/runnables/passthrough.py +849 -0
- coco_core/runnables/retry.py +379 -0
- coco_core/runnables/router.py +239 -0
- coco_core/runnables/schema.py +188 -0
- coco_core/runnables/utils.py +798 -0
- coco_core/stores.py +291 -0
- coco_core/structured_query.py +203 -0
- coco_core/sys_info.py +154 -0
- coco_core/tools/__init__.py +95 -0
- coco_core/tools/base.py +1948 -0
- coco_core/tools/convert.py +497 -0
- coco_core/tools/render.py +67 -0
- coco_core/tools/retriever.py +94 -0
- coco_core/tools/simple.py +208 -0
- coco_core/tools/structured.py +322 -0
- coco_core/tracers/__init__.py +47 -0
- coco_core/tracers/_compat.py +95 -0
- coco_core/tracers/_context.py +337 -0
- coco_core/tracers/_streaming.py +53 -0
- coco_core/tracers/base.py +955 -0
- coco_core/tracers/coco.py +279 -0
- coco_core/tracers/context.py +205 -0
- coco_core/tracers/core.py +766 -0
- coco_core/tracers/event_stream.py +1101 -0
- coco_core/tracers/log_stream.py +765 -0
- coco_core/tracers/memory_stream.py +200 -0
- coco_core/tracers/root_listeners.py +130 -0
- coco_core/tracers/run_collector.py +40 -0
- coco_core/tracers/schemas.py +14 -0
- coco_core/tracers/stdout.py +205 -0
- coco_core/utils/__init__.py +111 -0
- coco_core/utils/_gateway.py +274 -0
- coco_core/utils/_merge.py +218 -0
- coco_core/utils/aiter.py +357 -0
- coco_core/utils/env.py +86 -0
- coco_core/utils/formatting.py +80 -0
- coco_core/utils/function_calling.py +869 -0
- coco_core/utils/html.py +132 -0
- coco_core/utils/image.py +15 -0
- coco_core/utils/input.py +82 -0
- coco_core/utils/interactive_env.py +12 -0
- coco_core/utils/iter.py +229 -0
- coco_core/utils/json.py +230 -0
- coco_core/utils/json_schema.py +273 -0
- coco_core/utils/mustache.py +706 -0
- coco_core/utils/pydantic.py +631 -0
- coco_core/utils/strings.py +69 -0
- coco_core/utils/usage.py +61 -0
- coco_core/utils/utils.py +528 -0
- coco_core/utils/uuid.py +57 -0
- coco_core/vectorstores/__init__.py +53 -0
- coco_core/vectorstores/base.py +1111 -0
- coco_core/vectorstores/in_memory.py +546 -0
- coco_core/vectorstores/utils.py +163 -0
- coco_core/version.py +3 -0
- coco_framework-0.1.0.dist-info/METADATA +184 -0
- coco_framework-0.1.0.dist-info/RECORD +400 -0
- coco_framework-0.1.0.dist-info/WHEEL +4 -0
- coco_framework-0.1.0.dist-info/licenses/LICENSE +24 -0
- coco_framework-0.1.0.dist-info/licenses/NOTICE +15 -0
- coco_graph/_internal/__init__.py +4 -0
- coco_graph/_internal/_cache.py +31 -0
- coco_graph/_internal/_config.py +474 -0
- coco_graph/_internal/_constants.py +140 -0
- coco_graph/_internal/_fields.py +213 -0
- coco_graph/_internal/_future.py +220 -0
- coco_graph/_internal/_pydantic.py +275 -0
- coco_graph/_internal/_queue.py +124 -0
- coco_graph/_internal/_replay.py +90 -0
- coco_graph/_internal/_retry.py +29 -0
- coco_graph/_internal/_runnable.py +969 -0
- coco_graph/_internal/_scratchpad.py +19 -0
- coco_graph/_internal/_serde.py +253 -0
- coco_graph/_internal/_timeout.py +25 -0
- coco_graph/_internal/_typing.py +54 -0
- coco_graph/cache/base/__init__.py +48 -0
- coco_graph/cache/base/py.typed +0 -0
- coco_graph/cache/memory/__init__.py +73 -0
- coco_graph/cache/redis/__init__.py +144 -0
- coco_graph/cache/sqlite/__init__.py +120 -0
- coco_graph/callbacks.py +394 -0
- coco_graph/channels/__init__.py +29 -0
- coco_graph/channels/any_value.py +72 -0
- coco_graph/channels/base.py +121 -0
- coco_graph/channels/binop.py +155 -0
- coco_graph/channels/delta.py +202 -0
- coco_graph/channels/ephemeral_value.py +79 -0
- coco_graph/channels/last_value.py +151 -0
- coco_graph/channels/named_barrier_value.py +167 -0
- coco_graph/channels/topic.py +94 -0
- coco_graph/channels/untracked_value.py +73 -0
- coco_graph/checkpoint/base/__init__.py +861 -0
- coco_graph/checkpoint/base/id.py +109 -0
- coco_graph/checkpoint/base/py.typed +0 -0
- coco_graph/checkpoint/memory/__init__.py +698 -0
- coco_graph/checkpoint/memory/py.typed +0 -0
- coco_graph/checkpoint/postgres/__init__.py +602 -0
- coco_graph/checkpoint/postgres/_ainternal.py +23 -0
- coco_graph/checkpoint/postgres/_internal.py +21 -0
- coco_graph/checkpoint/postgres/aio.py +691 -0
- coco_graph/checkpoint/postgres/base.py +666 -0
- coco_graph/checkpoint/postgres/py.typed +0 -0
- coco_graph/checkpoint/postgres/shallow.py +967 -0
- coco_graph/checkpoint/serde/__init__.py +0 -0
- coco_graph/checkpoint/serde/_msgpack.py +97 -0
- coco_graph/checkpoint/serde/base.py +64 -0
- coco_graph/checkpoint/serde/encrypted.py +80 -0
- coco_graph/checkpoint/serde/event_hooks.py +52 -0
- coco_graph/checkpoint/serde/jsonplus.py +883 -0
- coco_graph/checkpoint/serde/py.typed +0 -0
- coco_graph/checkpoint/serde/types.py +68 -0
- coco_graph/checkpoint/sqlite/__init__.py +645 -0
- coco_graph/checkpoint/sqlite/_delta.py +172 -0
- coco_graph/checkpoint/sqlite/aio.py +738 -0
- coco_graph/checkpoint/sqlite/py.typed +0 -0
- coco_graph/checkpoint/sqlite/utils.py +116 -0
- coco_graph/config.py +196 -0
- coco_graph/constants.py +64 -0
- coco_graph/errors.py +241 -0
- coco_graph/func/__init__.py +620 -0
- coco_graph/graph/__init__.py +12 -0
- coco_graph/graph/_branch.py +225 -0
- coco_graph/graph/_node.py +103 -0
- coco_graph/graph/message.py +437 -0
- coco_graph/graph/state.py +1978 -0
- coco_graph/graph/ui.py +227 -0
- coco_graph/managed/__init__.py +3 -0
- coco_graph/managed/base.py +31 -0
- coco_graph/managed/is_last_step.py +24 -0
- coco_graph/prebuilt/__init__.py +23 -0
- coco_graph/prebuilt/_tool_call_stream.py +117 -0
- coco_graph/prebuilt/_tool_call_transformer.py +165 -0
- coco_graph/prebuilt/chat_agent_executor.py +1015 -0
- coco_graph/prebuilt/interrupt.py +105 -0
- coco_graph/prebuilt/py.typed +0 -0
- coco_graph/prebuilt/tool_node.py +2030 -0
- coco_graph/prebuilt/tool_validator.py +221 -0
- coco_graph/pregel/__init__.py +3 -0
- coco_graph/pregel/_algo.py +1460 -0
- coco_graph/pregel/_call.py +298 -0
- coco_graph/pregel/_checkpoint.py +331 -0
- coco_graph/pregel/_config.py +0 -0
- coco_graph/pregel/_draw.py +294 -0
- coco_graph/pregel/_executor.py +223 -0
- coco_graph/pregel/_io.py +174 -0
- coco_graph/pregel/_log.py +3 -0
- coco_graph/pregel/_loop.py +1988 -0
- coco_graph/pregel/_messages.py +461 -0
- coco_graph/pregel/_read.py +312 -0
- coco_graph/pregel/_retry.py +854 -0
- coco_graph/pregel/_runner.py +941 -0
- coco_graph/pregel/_tools.py +268 -0
- coco_graph/pregel/_utils.py +221 -0
- coco_graph/pregel/_validate.py +120 -0
- coco_graph/pregel/_write.py +192 -0
- coco_graph/pregel/debug.py +302 -0
- coco_graph/pregel/main.py +4364 -0
- coco_graph/pregel/protocol.py +288 -0
- coco_graph/pregel/types.py +38 -0
- coco_graph/py.typed +0 -0
- coco_graph/runtime.py +350 -0
- coco_graph/store/base/__init__.py +1322 -0
- coco_graph/store/base/batch.py +371 -0
- coco_graph/store/base/embed.py +436 -0
- coco_graph/store/base/py.typed +0 -0
- coco_graph/store/memory/__init__.py +592 -0
- coco_graph/store/memory/py.typed +0 -0
- coco_graph/store/postgres/__init__.py +4 -0
- coco_graph/store/postgres/aio.py +592 -0
- coco_graph/store/postgres/base.py +1480 -0
- coco_graph/store/postgres/py.typed +0 -0
- coco_graph/store/sqlite/__init__.py +4 -0
- coco_graph/store/sqlite/aio.py +632 -0
- coco_graph/store/sqlite/base.py +1514 -0
- coco_graph/stream/__init__.py +45 -0
- coco_graph/stream/_convert.py +32 -0
- coco_graph/stream/_mux.py +523 -0
- coco_graph/stream/_types.py +330 -0
- coco_graph/stream/run_stream.py +735 -0
- coco_graph/stream/stream_channel.py +341 -0
- coco_graph/stream/transformers.py +1039 -0
- coco_graph/types.py +1079 -0
- coco_graph/typing.py +48 -0
- coco_graph/utils/__init__.py +1 -0
- coco_graph/utils/config.py +4 -0
- coco_graph/utils/runnable.py +3 -0
- coco_graph/version.py +13 -0
- coco_graph/warnings.py +69 -0
- coco_openai/__init__.py +20 -0
- coco_openai/_compat.py +45 -0
- coco_openai/_version.py +3 -0
- coco_openai/chat_models/__init__.py +6 -0
- coco_openai/chat_models/_client_utils.py +684 -0
- coco_openai/chat_models/_compat.py +525 -0
- coco_openai/chat_models/azure.py +1227 -0
- coco_openai/chat_models/base.py +5654 -0
- coco_openai/chat_models/codex.py +557 -0
- coco_openai/chatgpt_oauth.py +1063 -0
- coco_openai/data/__init__.py +1 -0
- coco_openai/data/_profiles.py +1655 -0
- coco_openai/data/profile_augmentations.toml +127 -0
- coco_openai/embeddings/__init__.py +6 -0
- coco_openai/embeddings/azure.py +240 -0
- coco_openai/embeddings/base.py +820 -0
- coco_openai/llms/__init__.py +6 -0
- coco_openai/llms/azure.py +249 -0
- coco_openai/llms/base.py +919 -0
- coco_openai/middleware/__init__.py +11 -0
- coco_openai/middleware/openai_moderation.py +484 -0
- coco_openai/output_parsers/__init__.py +9 -0
- coco_openai/output_parsers/tools.py +9 -0
- coco_openai/py.typed +0 -0
- coco_openai/tools/__init__.py +5 -0
- coco_openai/tools/custom_tool.py +111 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncIterator, Callable, Iterator, Mapping, Sequence
|
|
4
|
+
from datetime import timedelta
|
|
5
|
+
from functools import cached_property
|
|
6
|
+
from typing import (
|
|
7
|
+
Any,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from coco_core.runnables import Runnable, RunnableConfig
|
|
11
|
+
|
|
12
|
+
from coco_graph._internal._config import merge_configs
|
|
13
|
+
from coco_graph._internal._constants import CONF, CONFIG_KEY_READ
|
|
14
|
+
from coco_graph._internal._runnable import RunnableCallable, RunnableSeq
|
|
15
|
+
from coco_graph._internal._timeout import coerce_timeout_policy
|
|
16
|
+
from coco_graph.pregel._utils import find_subgraph_pregel
|
|
17
|
+
from coco_graph.pregel._write import ChannelWrite
|
|
18
|
+
from coco_graph.pregel.protocol import PregelProtocol
|
|
19
|
+
from coco_graph.types import CachePolicy, RetryPolicy, TimeoutPolicy, TracePolicy
|
|
20
|
+
|
|
21
|
+
READ_TYPE = Callable[[str | Sequence[str], bool], Any | dict[str, Any]]
|
|
22
|
+
INPUT_CACHE_KEY_TYPE = tuple[Callable[..., Any], tuple[str, ...]]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ChannelRead(RunnableCallable):
|
|
26
|
+
"""Implements the logic for reading state from CONFIG_KEY_READ.
|
|
27
|
+
Usable both as a runnable as well as a static method to call imperatively."""
|
|
28
|
+
|
|
29
|
+
channel: str | list[str]
|
|
30
|
+
|
|
31
|
+
fresh: bool = False
|
|
32
|
+
|
|
33
|
+
mapper: Callable[[Any], Any] | None = None
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
channel: str | list[str],
|
|
38
|
+
*,
|
|
39
|
+
fresh: bool = False,
|
|
40
|
+
mapper: Callable[[Any], Any] | None = None,
|
|
41
|
+
tags: list[str] | None = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
super().__init__(
|
|
44
|
+
func=self._read,
|
|
45
|
+
afunc=self._aread,
|
|
46
|
+
tags=tags,
|
|
47
|
+
name=None,
|
|
48
|
+
trace=False,
|
|
49
|
+
)
|
|
50
|
+
self.fresh = fresh
|
|
51
|
+
self.mapper = mapper
|
|
52
|
+
self.channel = channel
|
|
53
|
+
|
|
54
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
55
|
+
if name:
|
|
56
|
+
pass
|
|
57
|
+
elif isinstance(self.channel, str):
|
|
58
|
+
name = f"ChannelRead<{self.channel}>"
|
|
59
|
+
else:
|
|
60
|
+
name = f"ChannelRead<{','.join(self.channel)}>"
|
|
61
|
+
return super().get_name(suffix, name=name)
|
|
62
|
+
|
|
63
|
+
def _read(self, _: Any, config: RunnableConfig) -> Any:
|
|
64
|
+
return self.do_read(
|
|
65
|
+
config, select=self.channel, fresh=self.fresh, mapper=self.mapper
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
async def _aread(self, _: Any, config: RunnableConfig) -> Any:
|
|
69
|
+
return self.do_read(
|
|
70
|
+
config, select=self.channel, fresh=self.fresh, mapper=self.mapper
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def do_read(
|
|
75
|
+
config: RunnableConfig,
|
|
76
|
+
*,
|
|
77
|
+
select: str | list[str],
|
|
78
|
+
fresh: bool = False,
|
|
79
|
+
mapper: Callable[[Any], Any] | None = None,
|
|
80
|
+
) -> Any:
|
|
81
|
+
try:
|
|
82
|
+
read: READ_TYPE = config[CONF][CONFIG_KEY_READ]
|
|
83
|
+
except KeyError:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
"Not configured with a read function"
|
|
86
|
+
"Make sure to call in the context of a Pregel process"
|
|
87
|
+
)
|
|
88
|
+
if mapper:
|
|
89
|
+
return mapper(read(select, fresh))
|
|
90
|
+
else:
|
|
91
|
+
return read(select, fresh)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
DEFAULT_BOUND = RunnableCallable(lambda input: input)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class PregelNode:
|
|
98
|
+
"""A node in a Pregel graph. This won't be invoked as a runnable by the graph
|
|
99
|
+
itself, but instead acts as a container for the components necessary to make
|
|
100
|
+
a PregelExecutableTask for a node."""
|
|
101
|
+
|
|
102
|
+
channels: str | list[str]
|
|
103
|
+
"""The channels that will be passed as input to `bound`.
|
|
104
|
+
If a str, the node will be invoked with its value if it isn't empty.
|
|
105
|
+
If a list, the node will be invoked with a dict of those channels' values."""
|
|
106
|
+
|
|
107
|
+
triggers: list[str]
|
|
108
|
+
"""If any of these channels is written to, this node will be triggered in
|
|
109
|
+
the next step."""
|
|
110
|
+
|
|
111
|
+
mapper: Callable[[Any], Any] | None
|
|
112
|
+
"""A function to transform the input before passing it to `bound`."""
|
|
113
|
+
|
|
114
|
+
writers: list[Runnable]
|
|
115
|
+
"""A list of writers that will be executed after `bound`, responsible for
|
|
116
|
+
taking the output of `bound` and writing it to the appropriate channels."""
|
|
117
|
+
|
|
118
|
+
bound: Runnable[Any, Any]
|
|
119
|
+
"""The main logic of the node. This will be invoked with the input from
|
|
120
|
+
`channels`."""
|
|
121
|
+
|
|
122
|
+
retry_policy: Sequence[RetryPolicy] | None
|
|
123
|
+
"""The retry policies to use when invoking the node."""
|
|
124
|
+
|
|
125
|
+
cache_policy: CachePolicy | None
|
|
126
|
+
"""The cache policy to use when invoking the node."""
|
|
127
|
+
|
|
128
|
+
timeout: TimeoutPolicy | None
|
|
129
|
+
"""Timeout policy for a single invocation.
|
|
130
|
+
|
|
131
|
+
If exceeded, `NodeTimeoutError` is raised and the retry policy (if any)
|
|
132
|
+
decides whether to retry. Supported only for async nodes.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
tags: Sequence[str] | None
|
|
136
|
+
"""Tags to attach to the node for tracing."""
|
|
137
|
+
|
|
138
|
+
metadata: Mapping[str, Any] | None
|
|
139
|
+
"""Metadata to attach to the node for tracing."""
|
|
140
|
+
|
|
141
|
+
trace_policy: TracePolicy | None
|
|
142
|
+
"""Optional policy controlling what this node records on its trace run."""
|
|
143
|
+
|
|
144
|
+
is_error_handler: bool
|
|
145
|
+
"""Whether this node is registered as an error handler node."""
|
|
146
|
+
|
|
147
|
+
error_handler_node: str | None
|
|
148
|
+
"""Optional handler node name for failures from this node."""
|
|
149
|
+
|
|
150
|
+
subgraphs: Sequence[PregelProtocol]
|
|
151
|
+
"""Subgraphs used by the node."""
|
|
152
|
+
|
|
153
|
+
def __init__(
|
|
154
|
+
self,
|
|
155
|
+
*,
|
|
156
|
+
channels: str | list[str],
|
|
157
|
+
triggers: Sequence[str],
|
|
158
|
+
mapper: Callable[[Any], Any] | None = None,
|
|
159
|
+
writers: list[Runnable] | None = None,
|
|
160
|
+
tags: list[str] | None = None,
|
|
161
|
+
metadata: Mapping[str, Any] | None = None,
|
|
162
|
+
trace_policy: TracePolicy | None = None,
|
|
163
|
+
bound: Runnable[Any, Any] | None = None,
|
|
164
|
+
retry_policy: RetryPolicy | Sequence[RetryPolicy] | None = None,
|
|
165
|
+
cache_policy: CachePolicy | None = None,
|
|
166
|
+
is_error_handler: bool = False,
|
|
167
|
+
error_handler_node: str | None = None,
|
|
168
|
+
subgraphs: Sequence[PregelProtocol] | None = None,
|
|
169
|
+
timeout: float | timedelta | TimeoutPolicy | None = None,
|
|
170
|
+
) -> None:
|
|
171
|
+
self.channels = channels
|
|
172
|
+
self.triggers = list(triggers)
|
|
173
|
+
self.mapper = mapper
|
|
174
|
+
self.writers = writers or []
|
|
175
|
+
self.bound = bound if bound is not None else DEFAULT_BOUND
|
|
176
|
+
self.cache_policy = cache_policy
|
|
177
|
+
if isinstance(retry_policy, RetryPolicy):
|
|
178
|
+
self.retry_policy = (retry_policy,)
|
|
179
|
+
else:
|
|
180
|
+
self.retry_policy = retry_policy
|
|
181
|
+
self.timeout = coerce_timeout_policy(timeout)
|
|
182
|
+
self.tags = tags
|
|
183
|
+
self.metadata = metadata
|
|
184
|
+
self.trace_policy = trace_policy
|
|
185
|
+
self.is_error_handler = is_error_handler
|
|
186
|
+
self.error_handler_node = error_handler_node
|
|
187
|
+
if subgraphs is not None:
|
|
188
|
+
self.subgraphs = subgraphs
|
|
189
|
+
elif self.bound is not DEFAULT_BOUND:
|
|
190
|
+
try:
|
|
191
|
+
subgraph = find_subgraph_pregel(self.bound)
|
|
192
|
+
except Exception:
|
|
193
|
+
subgraph = None
|
|
194
|
+
if subgraph:
|
|
195
|
+
self.subgraphs = [subgraph]
|
|
196
|
+
else:
|
|
197
|
+
self.subgraphs = []
|
|
198
|
+
else:
|
|
199
|
+
self.subgraphs = []
|
|
200
|
+
|
|
201
|
+
def copy(self, update: dict[str, Any]) -> PregelNode:
|
|
202
|
+
attrs = {**self.__dict__, **update}
|
|
203
|
+
# Drop the cached properties
|
|
204
|
+
attrs.pop("flat_writers", None)
|
|
205
|
+
attrs.pop("node", None)
|
|
206
|
+
attrs.pop("input_cache_key", None)
|
|
207
|
+
return PregelNode(**attrs)
|
|
208
|
+
|
|
209
|
+
@cached_property
|
|
210
|
+
def flat_writers(self) -> list[Runnable]:
|
|
211
|
+
"""Get writers with optimizations applied. Dedupes consecutive ChannelWrites."""
|
|
212
|
+
writers = self.writers.copy()
|
|
213
|
+
while (
|
|
214
|
+
len(writers) > 1
|
|
215
|
+
and isinstance(writers[-1], ChannelWrite)
|
|
216
|
+
and isinstance(writers[-2], ChannelWrite)
|
|
217
|
+
):
|
|
218
|
+
# we can combine writes if they are consecutive
|
|
219
|
+
# careful to not modify the original writers list or ChannelWrite
|
|
220
|
+
writers[-2] = ChannelWrite(
|
|
221
|
+
writes=writers[-2].writes + writers[-1].writes,
|
|
222
|
+
)
|
|
223
|
+
writers.pop()
|
|
224
|
+
return writers
|
|
225
|
+
|
|
226
|
+
@cached_property
|
|
227
|
+
def node(self) -> Runnable[Any, Any] | None:
|
|
228
|
+
"""Get a runnable that combines `bound` and `writers`."""
|
|
229
|
+
writers = self.flat_writers
|
|
230
|
+
trace_inputs = self.trace_policy.process_inputs if self.trace_policy else None
|
|
231
|
+
trace_outputs = self.trace_policy.process_outputs if self.trace_policy else None
|
|
232
|
+
if self.bound is DEFAULT_BOUND and not writers:
|
|
233
|
+
return None
|
|
234
|
+
elif self.bound is DEFAULT_BOUND and len(writers) == 1:
|
|
235
|
+
return writers[0]
|
|
236
|
+
elif self.bound is DEFAULT_BOUND:
|
|
237
|
+
return RunnableSeq(
|
|
238
|
+
*writers, trace_inputs=trace_inputs, trace_outputs=trace_outputs
|
|
239
|
+
)
|
|
240
|
+
elif writers:
|
|
241
|
+
return RunnableSeq(
|
|
242
|
+
self.bound,
|
|
243
|
+
*writers,
|
|
244
|
+
trace_inputs=trace_inputs,
|
|
245
|
+
trace_outputs=trace_outputs,
|
|
246
|
+
)
|
|
247
|
+
else:
|
|
248
|
+
return self.bound
|
|
249
|
+
|
|
250
|
+
@cached_property
|
|
251
|
+
def input_cache_key(self) -> INPUT_CACHE_KEY_TYPE:
|
|
252
|
+
"""Get a cache key for the input to the node.
|
|
253
|
+
This is used to avoid calculating the same input multiple times."""
|
|
254
|
+
return (
|
|
255
|
+
self.mapper,
|
|
256
|
+
tuple(self.channels)
|
|
257
|
+
if isinstance(self.channels, list)
|
|
258
|
+
else (self.channels,),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
def invoke(
|
|
262
|
+
self,
|
|
263
|
+
input: Any,
|
|
264
|
+
config: RunnableConfig | None = None,
|
|
265
|
+
**kwargs: Any | None,
|
|
266
|
+
) -> Any:
|
|
267
|
+
self_config: RunnableConfig = {"metadata": self.metadata, "tags": self.tags}
|
|
268
|
+
return self.bound.invoke(
|
|
269
|
+
input,
|
|
270
|
+
merge_configs(self_config, config),
|
|
271
|
+
**kwargs,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
async def ainvoke(
|
|
275
|
+
self,
|
|
276
|
+
input: Any,
|
|
277
|
+
config: RunnableConfig | None = None,
|
|
278
|
+
**kwargs: Any | None,
|
|
279
|
+
) -> Any:
|
|
280
|
+
self_config: RunnableConfig = {"metadata": self.metadata, "tags": self.tags}
|
|
281
|
+
return await self.bound.ainvoke(
|
|
282
|
+
input,
|
|
283
|
+
merge_configs(self_config, config),
|
|
284
|
+
**kwargs,
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
def stream(
|
|
288
|
+
self,
|
|
289
|
+
input: Any,
|
|
290
|
+
config: RunnableConfig | None = None,
|
|
291
|
+
**kwargs: Any | None,
|
|
292
|
+
) -> Iterator[Any]:
|
|
293
|
+
self_config: RunnableConfig = {"metadata": self.metadata, "tags": self.tags}
|
|
294
|
+
yield from self.bound.stream(
|
|
295
|
+
input,
|
|
296
|
+
merge_configs(self_config, config),
|
|
297
|
+
**kwargs,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
async def astream(
|
|
301
|
+
self,
|
|
302
|
+
input: Any,
|
|
303
|
+
config: RunnableConfig | None = None,
|
|
304
|
+
**kwargs: Any | None,
|
|
305
|
+
) -> AsyncIterator[Any]:
|
|
306
|
+
self_config: RunnableConfig = {"metadata": self.metadata, "tags": self.tags}
|
|
307
|
+
async for item in self.bound.astream(
|
|
308
|
+
input,
|
|
309
|
+
merge_configs(self_config, config),
|
|
310
|
+
**kwargs,
|
|
311
|
+
):
|
|
312
|
+
yield item
|