Skip to content

Quickstart

A demonstration of supported features, including function calling, image input, structured output, and web search.

examples/full_tour.py
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 explanations 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])

    final_answer = ""
    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


def file_input_agent(agt: pllm.AgentContext):
    # 7. File input
    file_input = pllm.FileInput(
        filename="example.txt",
        mime_type="text/plain",
        file_content=b"Hello from Amsterdam.",
    )
    resp = agt.ask_llm("What does this file say?", file_input)
    return resp.final_answer.replace("\n", " ")

if __name__ == "__main__":
    load_dotenv()

    with pllm.resume_directory(
        ".pllm/example/batch",
        provider="google",
        strategy="sync",
        dashboard=True,
        llm="gemini-2.5-flash",
        tweaks={"error_mode": "emit"},
        store_input=True,
    ) 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))
        with orch.agent() as agt:
            print("7. " + file_input_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 the program is rerun, the results are cached and available immediately.

Batch mode

Use the Batch API in just 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 a while, rerun the program. The batch will automatically be downloaded and handled.

[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: a simple list that automatically appends documents and responses. Tracks long conversations and reduces boilerplate.
    • The Ask guide: ask_llm, ask_functions.

Further examples

A suite of examples (a "cookbook") is available under examples/*.