MOAR Examples
Complete working examples for MOAR optimization.
Medication Extraction Example
This example extracts medications from medical transcripts and evaluates extraction accuracy.
Metric Key
The metric_key in the optimizer_config section specifies which key from your evaluation function's return dictionary will be used as the accuracy metric. In this example, metric_key: medication_extraction_score means MOAR will optimize using the medication_extraction_score value returned by the evaluation function.
Python API
import docetl
docetl.default_model = "gpt-4o-mini"
frame = (
docetl.read_json("workloads/medical/raw.json")
.map(
prompt="""Analyze the following transcript of a conversation between a doctor and a patient:
{{ input.src }}
Extract and list all medications mentioned in the transcript.
If no medications are mentioned, return an empty list.""",
output={"schema": {"medication": "list[str]"}},
)
)
# Define evaluation function
@docetl.register_eval
def evaluate_medications(results):
correct = sum(
1 for r in results
for med in r.get("medication", [])
if str(med).lower().strip() in r.get("src", "").lower()
)
total = sum(len(r.get("medication", [])) for r in results)
return {
"medication_extraction_score": correct,
"total_extracted": total,
"precision": correct / total if total > 0 else 0.0,
}
# Optimize — only eval_fn and metric_key are required
optimized = frame.optimize(
eval_fn=evaluate_medications,
metric_key="medication_extraction_score",
)
# Run the optimized pipeline
rows = optimized.collect()
print(f"Cost: ${optimized.total_cost:.4f}")
# Explore the Pareto frontier
for plan in optimized.search_results.frontier:
print(f"Cost: ${plan.cost:.4f}, Accuracy: {plan.accuracy}")
Full pipeline configuration
datasets:
transcripts:
path: workloads/medical/raw.json
type: file
default_model: gpt-4o-mini
bypass_cache: true
optimizer_config:
dataset_path: workloads/medical/raw_sample.json # Use sample for faster optimization
save_dir: workloads/medical/moar_results
available_models: # LiteLLM model names - ensure API keys are set in your environment
- gpt-5.1-nano
- gpt-5.1-mini
- gpt-5.1
- gpt-4o
- gpt-4o-mini
evaluation_file: workloads/medical/evaluate_medications.py
metric_key: medication_extraction_score
max_iterations: 40
rewrite_agent_model: gpt-5.1
system_prompt:
dataset_description: a collection of transcripts of doctor visits
persona: a medical practitioner analyzing patient symptoms and reactions to medications
operations:
- name: extract_medications
type: map
output:
schema:
medication: list[str]
prompt: |
Analyze the following transcript of a conversation between a doctor and a patient:
{{ input.src }}
Extract and list all medications mentioned in the transcript.
If no medications are mentioned, return an empty list.
pipeline:
steps:
- name: medication_extraction
input: transcripts
operations:
- extract_medications
output:
type: file
path: workloads/medical/extracted_medications_results.json
import docetl
docetl.default_model = "gpt-4o-mini"
docetl.bypass_cache = True
docetl.system_prompt = {
"dataset_description": "a collection of transcripts of doctor visits",
"persona": "a medical practitioner analyzing patient symptoms and reactions to medications",
}
frame = docetl.read_json("workloads/medical/raw.json")
frame = frame.map(
"extract_medications",
prompt="""Analyze the following transcript of a conversation between a doctor and a patient:
{{ input.src }}
Extract and list all medications mentioned in the transcript.
If no medications are mentioned, return an empty list.""",
output={"schema": {"medication": "list[str]"}},
)
optimized = frame.optimize(
eval_fn=evaluate_medications, # the function from the Python API section above
metric_key="medication_extraction_score",
models=["gpt-5.1-nano", "gpt-5.1-mini", "gpt-5.1", "gpt-4o", "gpt-4o-mini"],
max_iterations=40,
agent_model="gpt-5.1",
save_dir="workloads/medical/moar_results",
dataset_path="workloads/medical/raw_sample.json", # Use sample for faster optimization
)
optimized.write_json("workloads/medical/extracted_medications_results.json")
evaluate_medications.py (for CLI)
When using the CLI, create a file with a @register_eval decorated function:
import json
from typing import Any, Dict
from docetl.utils_evaluation import register_eval
@register_eval
def evaluate_results(dataset_file_path: str, results_file_path: str) -> Dict[str, Any]:
with open(results_file_path, 'r') as f:
output = json.load(f)
total_correct = 0
total_extracted = 0
for result in output:
original_transcript = result.get("src", "").lower()
for medication in result.get("medication", []):
total_extracted += 1
if str(medication).lower().strip() in original_transcript:
total_correct += 1
precision = total_correct / total_extracted if total_extracted > 0 else 0.0
return {
"medication_extraction_score": total_correct,
"total_extracted": total_extracted,
"precision": precision,
}
Python API vs CLI
In the Python API, you pass the evaluation function directly — no file or @register_eval needed. The file-based approach is only required for CLI usage.
Running the Optimization via CLI
docetl build workloads/medical/pipeline_medication_extraction.yaml
Using Sample Datasets
Notice that dataset_path points to raw_sample.json for optimization, while the main pipeline uses raw.json. This prevents optimizing on your test set.
Key Points
Evaluation Function
- Python API: pass a callable directly — no file or decorator needed
- CLI: use a
@register_evaldecorated function in a.pyfile - Returns multiple metrics, with
medication_extraction_scoreas the primary one
Configuration
- Only
evaluation_fileandmetric_keyare required in the YAMLoptimizer_config available_modelsis optional -- auto-detected from API keys if omitted- Uses a sample dataset for optimization (
dataset_path) - Sets
max_iterationsto 40 for a good balance of exploration and time