Idioms
Code parallelization can take many forms. ParaLLeM supports these 3.
Direct Idiom¶
The direct idiom (Direct API) is simplest to write. 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. Batch parallelization is effective because of ParaLLeM's interrupt semantics.
However, it is not effective if ran asynchronously, because power-of-2 agent must finish before power-of-3 agent can begin.
That is a limitation of python: you need await, async, and asyncio.run to allow async calls.
Concurrent Idiom¶
You can use the concurrent strategy with the Direct API to achieve parallelization. However, you must ensure that one agent does not block the other.
This idiom is less efficient than true async. Typically, await yields control between tasks, but here that is not possible.
However, you still achieve parallelization which resembles async execution.
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}")
load_dotenv()
with pllm.resume_directory(
".pllm/simplest",
strategy="concurrent",
) as orch:
collector: list[pllm.LLMResponse] = []
for i in range(2, 6):
with orch.agent(i) as agt:
collector.append(power_of_n_agent(agt, i))
out = orch.resolve_all(collector)
print(out)
Async Idiom¶
If you have async functions, you can use the async idiom.
It is effective with sync, concurrent, and batch strategies.
import parallem as pllm
from dotenv import load_dotenv
async def haiku_writer_agent(agt: pllm.AgentContext):
# Declare the agent.
conv = agt.get_msg_state()
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
if __name__ == "__main__":
load_dotenv()
with pllm.resume_directory(
".pllm/simplest",
provider="openai",
strategy="concurrent",
dashboard=True,
) as orch:
# Instantiate the agent.
a1 = orch.create_agent(haiku_writer_agent, agent_name="Writer-1")
a2 = orch.create_agent(haiku_writer_agent, agent_name="Writer-2")
# Run agents. Similar to async.gather or async.TaskGroup
out = orch.run_agents(a1, a2)
However, the async idiom is trickier to write and port to.
Note
orch.run_agents is similar to asyncio.run(asyncio.gather(agts)). However, orch.run_agents is recommended when using batch mode, because orch.run_agents properly handles ParaLLeM's interrupt semantics.