Parallelize
Parallelization takes many forms.
Simple¶
Declare agents in a for loop.
import parallem as pllm
from dotenv import load_dotenv
def power_of_n_agent(agt: pllm.AgentContext, n: int):
return agt.ask_llm(f"Name a power of {n}").final_answer
load_dotenv()
with pllm.resume_directory(
".pllm/simplest",
strategy="sync", # or batch
) as orch:
for i in range(2, 6):
with orch.agent(i) as agt:
print(power_of_n_agent(agt, i))
It is effective with sync and batch. However, it is not effective if ran asynchronously, because power-of-2 agent must finish before power-of-3 agent can begin.
Async¶
It is effective with sync, async, and batch strategies.
import asyncio
import random
import parallem as pllm
async def haiku_writer_agent(agt: pllm.AgentContext):
# Declare the agent.
conv = agt.get_msg_state()
rand_time = random.uniform(1, 4)
await asyncio.sleep(rand_time) # Simulate some processing time
await conv.ask_llm("Please name an animal in 1 word.")
await conv.ask_llm(f"Write a haiku about {conv[-1].final_answer}(s).")
out = conv[-1].final_answer
print(out)
return out
async def main():
with pllm.resume_directory(
".pllm/simplest",
provider="openai",
strategy="batch",
dashboard=True,
load_dotenv=True,
ask_params={
"salt": 7,
}
) as orch:
coros = []
for i in range(10):
with orch.agent(f"Writer-{i}") as a:
coros.append(haiku_writer_agent(a))
await orch.gather(*coros)
if __name__ == "__main__":
asyncio.run(main())
Note
In the above example, an alternative is asyncio.gather(*coros). But in batch mode, if the first child raises an error due to a missing value, that would prevent the remaining coroutines from being batched.
Therefore, either asyncio.gather(*coros, return_exceptions=True) or orch.gather(*coros) are recommended because it gracefully handles if a value is not available.
In the current version of ParaLLeM, strategy=async creates a separate event loop, and ask_llm eagerly kicks off that task. await conv.ask_llm ensures that that task is complete.