From 943cc4d83ae28911d212dde1adb94a5ea706dbed Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 10 Sep 2024 16:02:16 -0700 Subject: [PATCH] Add readme, lint --- libs/scheduler-kafka/README.md | 133 +++++++++++++++++- .../scheduler-kafka/langgraph-distributed.png | Bin 0 -> 76422 bytes .../langgraph/scheduler/kafka/executor.py | 4 + .../langgraph/scheduler/kafka/orchestrator.py | 11 +- libs/scheduler-kafka/tests/drain.py | 3 +- libs/scheduler-kafka/tests/test_subgraph.py | 4 +- 6 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 libs/scheduler-kafka/langgraph-distributed.png diff --git a/libs/scheduler-kafka/README.md b/libs/scheduler-kafka/README.md index cedfcc53f..c279f5e38 100644 --- a/libs/scheduler-kafka/README.md +++ b/libs/scheduler-kafka/README.md @@ -1,3 +1,134 @@ # LangGraph Scheduler for Kafka -... +This library implements a distributed scheduler for LangGraph using Kafka as the message broker. + +## Architecture + +![](./langgraph-distributed.png) + +- Combination of Kafka (at least once) with a LangGraph Checkpointer provides exactly once semantics both for orchestrator and executor messages +- Checkpointer ensures writes for a given task are saved only once, even if the task is re-executed +- Checkpointer is used to record whether each task in each step has been successfully published to Kafka, to ensure tasks aren't lost, or published more than once +- Orchestrator and Executor manage commit of offsets manually to ensure tasks are marked as done only after finished processing +- Orchestrator and Executor pick up from the earliest message not yet consumed when restarted, to ensure no message is lost, and avoid processing messages more than once +- Orchestrator messages are keyed by thread ID and checkpoint NS, to ensure that no two consumers can process updates for same step of same thread concurrently +- Executor messages are not keyed, as they can be processed concurrently +- Orchestrator and Executor execute messages in configurable batches (up to N messages within space of X seconds), and dedupe messages intra-batch where appropriate (this is purely a performance optimization, with no impact on correctness whether applied or not) + +## Basic Usage + +Launch orchestrator and executor processes: + +`orchestrator.py` + +```python +import asyncio +import logging +import os + +from langgraph.scheduler.kafka.orchestrator import KafkaOrchestrator +from langgraph.scheduler.kafka.types import Topics + +from your_lib import graph # graph expected to be a compiled LangGraph graph + +logger = logging.getLogger(__name__) + +topics = Topics( + orchestrator: os.environ['KAFKA_TOPIC_ORCHESTRATOR'], + executor: os.environ['KAFKA_TOPIC_EXECUTOR'], + error: os.environ['KAFKA_TOPIC_ERROR'], +) + +async def main(): + async with KafkaOrchestrator(graph, topics) as orch: + async for msgs in orch: + logger.info('Procesed %d messages', len(msgs)) + +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO) + asyncio.run(main()) +``` + +`executor.py` + +```python +import asyncio +import logging +import os + +from langgraph.scheduler.kafka.executor import KafkaExecutor +from langgraph.scheduler.kafka.types import Topics + +from your_lib import graph # graph expected to be a compiled LangGraph graph + +logger = logging.getLogger(__name__) + +topics = Topics( + orchestrator: os.environ['KAFKA_TOPIC_ORCHESTRATOR'], + executor: os.environ['KAFKA_TOPIC_EXECUTOR'], + error: os.environ['KAFKA_TOPIC_ERROR'], +) + +async def main(): + async with KafkaExecutor(graph, topics) as orch: + async for msgs in orch: + logger.info('Procesed %d messages', len(msgs)) + +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO) + asyncio.run(main()) +``` + +```bash +export KAFKA_TOPIC_ORCHESTRATOR='orchestrator' +export KAFKA_TOPIC_EXECUTOR='executor' +export KAFKA_TOPIC_ERROR='error' +python orchestrator.py & +python executor.py & +``` + +## Configuration + +You can pass any of the following values as `kwargs` to either `KafkaOrchestrator` or `KafkaExecutor` to configure the consumer: + +- group_id (str): a name for the consumer group. Defaults to 'orchestrator' or 'executor', respectively. +- batch_max_n (int): Maximum number of messages to include in a single batch. Default: 10. +- batch_max_ms (int): Maximum time in milliseconds to wait for messages to include in a batch. Default: 1000. +- retry_policy (langgraph.pregel.types.RetryPolicy): Controls which graph-level errors will be retried when processing messages. A good use for this is to retry database errors thrown by the checkpointer. Defaults to None. + +### Connection settings + +By default the orchestrator and executor will attempt to connect to a Kafka broker running on `localhost:9092`. You can change connection settings by passing any of the following values as `kwargs` to either `KafkaOrchestrator` or `KafkaExecutor`: + +- bootstrap_servers: 'host[:port]' string (or list of 'host[:port]' + strings) that the consumer should contact to bootstrap initial + cluster metadata. This does not have to be the full node list. + It just needs to have at least one broker that will respond to + Metadata API Request. Default port is 9092. If no servers are + specified, will default to localhost:9092. +- client_id (str): a name for this client. This string is passed in + each request to servers and can be used to identify specific + server-side log entries that correspond to this client. Also + submitted to GroupCoordinator for logging with respect to + consumer group administration. Default: 'aiokafka-{ver}' +- request_timeout_ms (int): Client request timeout in milliseconds. + Default: 40000. +- metadata_max_age_ms (int): The period of time in milliseconds after + which we force a refresh of metadata even if we haven't seen + any partition leadership changes to proactively discover any + new brokers or partitions. Default: 300000 +- retry_backoff_ms (int): Milliseconds to backoff when retrying on + errors. Default: 100. +- api_version (str): specify which kafka API version to use. + AIOKafka supports Kafka API versions >=0.9 only. + If set to 'auto', will attempt to infer the broker version by + probing various APIs. Default: auto +- security_protocol (str): Protocol used to communicate with brokers. + Valid values are: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. + Default: PLAINTEXT. +- ssl_context (ssl.SSLContext): pre-configured SSLContext for wrapping + socket connections. For more information see :ref:`ssl_auth`. + Default: None. +- connections_max_idle_ms (int): Close idle connections after the number + of milliseconds specified by this config. Specifying `None` will + disable idle checks. Default: 540000 (9 minutes). diff --git a/libs/scheduler-kafka/langgraph-distributed.png b/libs/scheduler-kafka/langgraph-distributed.png new file mode 100644 index 0000000000000000000000000000000000000000..4315a01b57bbf5f3259d83a920edd702bacdc50f GIT binary patch literal 76422 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≧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 None: self.graph = graph self.topics = topics self.stack = AsyncExitStack() self.kwargs = kwargs + self.consumer_kwargs = consumer_kwargs or {} + self.producer_kwargs = producer_kwargs or {} self.group_id = group_id self.batch_max_n = batch_max_n self.batch_max_ms = batch_max_ms diff --git a/libs/scheduler-kafka/langgraph/scheduler/kafka/orchestrator.py b/libs/scheduler-kafka/langgraph/scheduler/kafka/orchestrator.py index 9d548280d..a3da188e8 100644 --- a/libs/scheduler-kafka/langgraph/scheduler/kafka/orchestrator.py +++ b/libs/scheduler-kafka/langgraph/scheduler/kafka/orchestrator.py @@ -38,12 +38,16 @@ class KafkaOrchestrator(AbstractAsyncContextManager): batch_max_n: int = 10, batch_max_ms: int = 1000, retry_policy: Optional[RetryPolicy] = None, + consumer_kwargs: Optional[dict[str, Any]] = None, + producer_kwargs: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> None: self.graph = graph self.topics = topics self.stack = AsyncExitStack() self.kwargs = kwargs + self.consumer_kwargs = consumer_kwargs or {} + self.producer_kwargs = producer_kwargs or {} self.group_id = group_id self.batch_max_n = batch_max_n self.batch_max_ms = batch_max_ms @@ -57,10 +61,15 @@ class KafkaOrchestrator(AbstractAsyncContextManager): group_id=self.group_id, enable_auto_commit=False, **self.kwargs, + **self.consumer_kwargs, ) ) self.producer = await self.stack.enter_async_context( - aiokafka.AIOKafkaProducer(value_serializer=serde.dumps, **self.kwargs) + aiokafka.AIOKafkaProducer( + value_serializer=serde.dumps, + **self.kwargs, + **self.producer_kwargs, + ) ) self.subgraphs = { k: v async for k, v in self.graph.aget_subgraphs(recurse=True) diff --git a/libs/scheduler-kafka/tests/drain.py b/libs/scheduler-kafka/tests/drain.py index b58906362..b6199adbb 100644 --- a/libs/scheduler-kafka/tests/drain.py +++ b/libs/scheduler-kafka/tests/drain.py @@ -1,10 +1,11 @@ import asyncio import functools -from typing import Callable, Optional, ParamSpec, TypeVar +from typing import Callable, Optional, TypeVar import anyio from aiokafka import AIOKafkaConsumer from langchain_core.runnables import RunnableConfig +from typing_extensions import ParamSpec from langgraph.pregel import Pregel from langgraph.pregel.types import StateSnapshot diff --git a/libs/scheduler-kafka/tests/test_subgraph.py b/libs/scheduler-kafka/tests/test_subgraph.py index a9c0062a8..8c8a0f530 100644 --- a/libs/scheduler-kafka/tests/test_subgraph.py +++ b/libs/scheduler-kafka/tests/test_subgraph.py @@ -1,4 +1,4 @@ -from typing import Literal, ParamSpec, TypeVar, cast +from typing import Literal, cast import pytest from aiokafka import AIOKafkaProducer @@ -19,8 +19,6 @@ from tests.any import AnyDict, AnyStr from tests.drain import drain_topics pytestmark = pytest.mark.anyio -C = ParamSpec("C") -R = TypeVar("R") def mk_weather_graph(checkpointer: BaseCheckpointSaver) -> Pregel: