Configure a task in Python¶
A Task
is the basic building block in Otaro. Similar to DSPy, Otaro treats LLM calls like functions with inputs and outputs.
Quickstart¶
from otaro import Field, Task
# Define a task that takes a topic and returns a list of quotes
task = Task(
model="gemini/gemini-2.0-flash-001",
inputs=[
"topic", # same as Field(name="topic", type=str)
],
outputs=[
Field(
name="quotes",
type=list[str],
# type takes native Python types or Pydantic BaseModel classes
)
],
)
response = task.run(topic="discworld")
for quote in response.quotes:
print(quote)
The pen is mightier than the sword if the sword is very short, and the pen is very sharp.
In ancient times cats were worshipped as gods; they have not forgotten this.
Wisdom comes from experience. Experience is often a result of lack of wisdom.
Words in the heart cannot be taken.
Defining a task¶
At minimum, a Task
needs to be initialized with:
model (str)
: A model name, used bylitellm
under the hoodinputs (list[str | Field])
: A list of inputs that the task is expected to receiveoutputs (list[str | Field])
: A list of outputs to be produced
Fields¶
A Field
is used to specify the type of output that the LLM is supposed to generate.
The Field
definitions will also be used to parse the LLM response and return an output with attributes of the correct types.
For instance, in the above example, response.quotes
will be of type list[str]
.
For convenience, a Field
can also be defined with a single string, which will be interpreted as the field name and default to type=str
. For example, inputs
is set as ["topic"]
in quickstart.py
above.
Adding rules¶
Instead of trying to figure out the best prompt, define the desired output with rules
. Then, whenever task.run
is called, the task will be automatically optimized to enforce the rules where possible.
For illustration, rewrite the task above to enforce 3 quotes:
from otaro import Field, Task
# Create a task that takes a topic and returns a list of quotes
task = Task(
model="gemini/gemini-2.0-flash-001",
inputs=["topic"],
outputs=[
Field(
name="quotes",
type=list[str],
)
],
# Add rule to enforce len(quotes) == 3
rules=[
"otaro.rules.length_eq(quotes, 3)",
]
)
response = task.run(topic="discworld")
for quote in response.quotes:
print(quote)
Running the script will automatically optimize the task to output three quotes.
Note: The optimized config will only be saved for future use if the task was loaded via YAML. See Configure a task in YAML for more details.
INFO:otaro.task:Evaluating rulesINFO:otaro.task:Rule 1: otaro.rules.length_eq(quotes, 3) - False
INFO:otaro.task:Optimizing task...
INFO:otaro.task:Evaluating prompt: "Write three quotes about {topic}."
INFO:otaro.task:Evaluating rulesINFO:otaro.task:Rule 1: otaro.rules.length_eq(quotes, 3) - True
INFO:otaro.task: Score: 1.0
INFO:otaro.task:All scores: [0.0, 1.0]
INFO:otaro.task:Selecting prompt #1 with score 1.0
The pen is mightier than the sword if the sword is very short, and the pen is very sharp.
In ancient times cats were worshipped as gods; they have not forgotten this.
Wisdom comes from experience. Experience is often a result of lack of wisdom.