Quickstart¶
This guide gives a tour of parallem. We support many agentic features including function calling, image input, structured output, web search, and more -- all with the Batch API.
from pydantic import BaseModel
from dotenv import load_dotenv
from PIL import Image
import parallem as pllm
class MyModel(BaseModel):
final_answer: str
def count_files(directory: str) -> int:
"""Counts files in a directory"""
return 4
def power_of_3_agent(agt: pllm.AgentContext):
# 1. Basic LLM call
resp = agt.ask_llm(
"Please name a power of 3.",
instructions="No explanation needed.",
)
return resp.final_answer.replace("\n", " ")
def web_search_agent(agt: pllm.AgentContext):
# 2. Web search tool
resp = agt.ask_llm(
"In 1 sentence, what is AAPL's current price?",
tools=[pllm.tools.WebSearchTool()],
)
return resp.final_answer.replace("\n", " ")
def structured_output_agent(agt: pllm.AgentContext):
# 3. Structured output
resp = agt.ask_llm("What is the capital of France?", structured_output=MyModel)
return resp.final_answer.replace("\n", " ")
def image_input_agent(agt: pllm.AgentContext):
# 4. Image input. NOTE: Adjust image as needed.
img = Image.open("tests/data/images/Nokota_Horses_cropped.jpg")
img.thumbnail((100, 100)) # Downsample
resp = agt.ask_llm("What animal is this?", img)
return resp.final_answer.replace("\n", " ")
def function_calling_agent(agt: pllm.AgentContext):
# 5,6. Function calling.
# Keeping track of message state can be tedious. see the MessageState abstraction.
ls_prompt = "How many files are in ~/examples? Give the final answer in words."
resp5 = agt.ask_llm(
ls_prompt,
tools=[count_files],
)
fc_outs = agt.ask_functions(resp5, count_files=count_files)
resp6 = agt.ask_llm([ls_prompt, resp5, *fc_outs])
if resp5.function_calls:
final_answer = f"Function calls: {resp5.function_calls}\n6. "
final_answer += resp5.final_answer.replace("\n", " ")
final_answer += resp6.final_answer.replace("\n", " ")
return final_answer
if __name__ == "__main__":
load_dotenv()
with pllm.resume_directory(
".pllm/example/batch",
provider="gemini",
strategy="sync",
dashboard=True,
llm="gemini-2.5-flash",
save_input=True,
tweaks={"error_mode": "emit"}
) as orch:
with orch.agent() as agt:
print("1. " + power_of_3_agent(agt))
with orch.agent() as agt:
print("2. " + web_search_agent(agt))
with orch.agent() as agt:
print("3. " + structured_output_agent(agt))
with orch.agent() as agt:
print("4. " + image_input_agent(agt))
with orch.agent() as agt:
print("5. " + function_calling_agent(agt))
[INFO] Resuming with session_id=0
1. 243 (which is 3^5).
2. Apple Inc. (AAPL) is currently trading at $257.46 per share (latest trade: 01:15:00 UTC on March 7, 2026).
3. {"final_answer":"The capital of France is Paris."}
4. These are horses — domestic equines. The photo shows two adult horses standing in a grassy field.
FunctionCall(name=count_files, call_id=call_Xau, args={'directory': '~/examples'})
5.
6. There are four files in ~/examples.
[DASH] ↘ 2b55f032 ↘ f7824348 ↘ c9f2fcc4 ↘ f13b65b2 ↘ bc7f1641 ↘ 2883bea6
If you run the program again, the results are cached and available instantly.
Batch mode¶
The entire workflow can be done in batch mode simply by changing one line of code:
with pllm.resume_directory(
".pllm/example/batch",
provider="openai",
strategy="batch", # Only change!!!
# ...
) as orch:
# ...
[INFO] Resuming with session_id=0
Submit 1 batch (6 calls)? (y/n/preview): y
Sent batch: batch_69b4a26290008190a08e246922784ed8
[DASH] ⇈ 69b4a262
After waiting a while, run the program again. The batch will automatically be downloaded and handled for you.
[INFO] Resuming with session_id=1
Batch batch_69b4a26290008190a08e246922784ed8 completed and stored.
1. 243 (which is 3^5).
2. Apple Inc. (AAPL) is currently trading at $257.46 per share (latest trade: 01:15:00 UTC on March 7, 2026).
3. {"final_answer":"The capital of France is Paris."}
4. These are horses — domestic equines. The photo shows two adult horses standing in a grassy field.
FunctionCall(name=count_files, call_id=call_Xau, args={'directory': '~/examples'})
5.
6. There are four files in ~/examples.
C 2b55f032 C f7824348 C c9f2fcc4 C f13b65b2 C bc7f1641 C 2883bea6
Warning
ParaLLeM caches requests by hash. By default, hashes only consider input documents and LLM name. If only a non-hashed parameter changes (ie. reasoning level), there will be a hash collision. To avoid this, customize hash_by or compute a custom salt. See persistence.
Advanced Usage¶
- See the docs for:
- The MessageState guide: simply a list that automatically stores documents and responses as they get added. Helps track long conversations, reducing boilerplate.
- The Ask guide:
ask_llm,ask_functions(invoking user functions). - The memoize guide: for caching expensive or non-deterministic blocks of code.
Further examples¶
A suite of examples (a "cookbook") is available under examples/*.