-
Notifications
You must be signed in to change notification settings - Fork 116
Expand file tree
/
Copy pathrun_workflow.py
More file actions
74 lines (59 loc) · 2.43 KB
/
Copy pathrun_workflow.py
File metadata and controls
74 lines (59 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Start the streaming workflow and print model chunks live.
Subscribes to the workflow-streams topic the streaming activity publishes to and
renders each chunk's text as it arrives. Each published item is an
``AIMessageChunk`` in ``langchain_core.load.dumpd`` form, so it is reconstructed
with ``langchain_core.load.load``. The final aggregated message is also returned
as the workflow result (identical to the non-streaming path).
"""
import asyncio
import os
from datetime import timedelta
from langchain_core.load import load
from temporalio.client import Client
from temporalio.contrib.workflow_streams import WorkflowStreamClient
from deepagents_plugin.streaming.workflow import STREAMING_TOPIC, StreamingWorkflow
async def main() -> None:
client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"))
workflow_id = "deepagents-streaming"
handle = await client.start_workflow(
StreamingWorkflow.run,
"Write a short paragraph about durable execution.",
id=workflow_id,
task_queue="deepagents-streaming",
)
printed: list[str] = []
async def consume() -> None:
stream = WorkflowStreamClient.create(client, workflow_id)
async for item in stream.subscribe(
[STREAMING_TOPIC],
from_offset=0,
result_type=dict,
poll_cooldown=timedelta(milliseconds=50),
):
chunk = load(item.data)
text = getattr(chunk, "content", "")
if text:
printed.append(str(text))
print(text, end="", flush=True)
consume_task = asyncio.create_task(consume())
result = await handle.result()
# The workflow has completed, but the subscriber may still be catching up on
# the tail of the stream. The streamed chunks add up to the durable result,
# so drain until all of it has been printed; the timeout only bounds a
# regression, it never gates the happy path.
async def drained() -> None:
while result not in "".join(printed):
await asyncio.sleep(0.05)
try:
await asyncio.wait_for(drained(), timeout=10.0)
except asyncio.TimeoutError:
print("\n(timed out waiting for the subscriber to drain the stream)")
consume_task.cancel()
try:
await consume_task
except asyncio.CancelledError:
pass
print()
print(f"Final result: {result}")
if __name__ == "__main__":
asyncio.run(main())