Skip to main content
LLM-powered applications can contain multiple LLMs calls and additional data processing and validation logic that is important to monitor. Even in deeply nested call structures common in many applications, Weave tracks parent-child relationships across nested functions, as long as weave.op() is added to each function you want to trace. The following code builds on the quickstart example and adds logic to count the returned items from the LLM and wrap them in a higher-level function. Additionally, the example uses weave.op() to trace every function, its call order, and its parent-child relationship:
import weave
import json
from openai import OpenAI

client = OpenAI()

@weave.op()
def extract_dinos(sentence: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": """Extract any dinosaur `name`, their `common_name`, \
names and whether its `diet` is a herbivore or carnivore, in JSON format."""
            },
            {
                "role": "user",
                "content": sentence
            }
            ],
            response_format={ "type": "json_object" }
        )
    return response.choices[0].message.content

@weave.op()
def count_dinos(dino_data: dict) -> int:
    # count the number of items in the returned list
    k = list(dino_data.keys())[0]
    return len(dino_data[k])

@weave.op()
def dino_tracker(sentence: str) -> dict:
    # extract dinosaurs using a LLM
    dino_data = extract_dinos(sentence)

    # count the number of dinosaurs returned
    dino_data = json.loads(dino_data)
    n_dinos = count_dinos(dino_data)
    return {"n_dinosaurs": n_dinos, "dinosaurs": dino_data}

weave.init('jurassic-park')

sentence = """I watched as a Tyrannosaurus rex (T. rex) chased after a Triceratops (Trike), \
both carnivore and herbivore locked in an ancient dance. Meanwhile, a gentle giant \
Brachiosaurus (Brachi) calmly munched on treetops, blissfully unaware of the chaos below."""

result = dino_tracker(sentence)
print(result)
Nested functionsWhen you run the preceding code, the Traces page shows the inputs and outputs from the two nested functions (extract_dinos and count_dinos), as well as the automatically-logged OpenAI trace.Nested Weave Traces page showing center trace tree panel and the details panel for the selected Call

Tracking metadata

You can track metadata by using the weave.attributes context manager and passing it a dictionary of the metadata to track at call time. Continuing our example from above:
import weave

weave.init('jurassic-park')

sentence = """I watched as a Tyrannosaurus rex (T. rex) chased after a Triceratops (Trike), \
both carnivore and herbivore locked in an ancient dance. Meanwhile, a gentle giant \
Brachiosaurus (Brachi) calmly munched on treetops, blissfully unaware of the chaos below."""

# track metadata alongside our previously defined function
with weave.attributes({'user_id': 'lukas', 'env': 'production'}):
    result = dino_tracker(sentence)
We recommend that you track metadata at run time, such as your user IDs and your code’s environment status (development, staging, or production).We recommennd that to track system settings, such as a system prompt, use Weave Models.
For more information on using attributes, see Define and log attributes.

What’s next?

  • Follow the App Versioning tutorial to capture, version, and organize ad-hoc prompt, model, and application changes.