module¶
module
@module: a plain Python function that calls @ai functions, optimized as one program.
@module
def research(claim: str, hops: int = 2) -> list[str]:
facts = []
for _ in range(hops):
query = generate_query(claim, facts)
facts = append_notes(claim, facts, search(query))
return facts
better = research.opt(rows, metric=...) # a copy with generate_query and append_notes tuned together
research.interface # what it takes and gives, as data (checked on every call)
The metric sees Prediction(result=<what the module returned>).
Classes¶
| Name | Description |
|---|---|
| FunctAIModule | A Python function that calls AI functions, as one program: called, |
FunctAIModule¶
module.FunctAIModule(
fn,
*,
requires=(),
interface=None,
outputs=None,
answer_from=None,
_namespace=None,
_output_fields=None,
**settings,
)
A Python function that calls AI functions, as one program: called,
streamed, evaluated, optimized and saved as a whole. Build with @module.
Its interface (what it takes and gives, as data) is derived and
checked when it is defined, and every call is checked against it: its
inputs before its code runs, its outputs when it returns
(InterfaceError, which is also a TypeError).
Attributes¶
| Name | Description |
|---|---|
interface |
What the module takes and gives, as data (contract/programs.md). |
version |
The module's version: a fingerprint of its code and its AI functions. |
Methods¶
| Name | Description |
|---|---|
| ai_functions | Every AI function this module reaches (named_ai_functions().values()). |
| conversation | A conversation with this module: each call a turn, kept in store; |
| load | A copy running with the states a save wrote. |
| map | Run on every row of a table; returns the rows with pred_result |
| named_ai_functions | Every @ai function this module reaches: called by name, under another |
| opt | An improved copy: every @ai function this module calls tuned against |
| save | Every AI function's instruction and demos, in one JSON file. |
| state | The instruction and demos each AI function runs with in this module, by name. |
| stream | Call the module and watch every AI function it calls, as it works. |
| vectorize | This module as a dpyr row function (see FunctAIFunc.vectorize); |
ai_functions¶
module.FunctAIModule.ai_functions()
Every AI function this module reaches (named_ai_functions().values()).
conversation¶
module.FunctAIModule.conversation(
id=None,
*,
store=None,
context=None,
remembers=None,
sends='queue',
**settings,
)
A conversation with this module: each call a turn, kept in store;
remembers={helper: "conversation"} gives a helper its own earlier
calls (helpers remember nothing otherwise); functai.earlier() in
its code is the conversation so far. See functai.conversations.Conversation.
load¶
module.FunctAIModule.load(path)
A copy running with the states a save wrote.
map¶
module.FunctAIModule.map(
data,
*,
threads=None,
num_threads=None,
call_defaults=None,
progress=None,
)
Run on every row of a table; returns the rows with pred_result
(what the module returned) as a dpyr dataframe. See FunctAIFunc.map.
named_ai_functions¶
module.FunctAIModule.named_ai_functions()
Every @ai function this module reaches: called by name, under another name, or through helper functions (looked up when asked, so functions defined after the module are found). Keys are function names, qualified by module when two share a name.
opt¶
module.FunctAIModule.opt(
data,
*,
metric=None,
optimizer=None,
call_defaults=None,
valset=None,
expected=None,
**optimizer_kwargs,
)
An improved copy: every @ai function this module calls tuned against
one metric on the module's output. This module and its functions are
unchanged. call_defaults fill module arguments the rows lack.
save¶
module.FunctAIModule.save(path)
Every AI function's instruction and demos, in one JSON file.
state¶
module.FunctAIModule.state()
The instruction and demos each AI function runs with in this module, by name.
stream¶
module.FunctAIModule.stream(*args, **kwargs)
Call the module and watch every AI function it calls, as it works.
The call starts at once, in the background, and is the same call as
module(...). s.events() shows each call inside it (started,
its text as it is written, tool calls, retries, done);
s.text_of(fn) one AI function's answer as it is written;
s.result what the module returned (waits). See Stream.
vectorize¶
module.FunctAIModule.vectorize(dtype=None, threads=None, errors='raise')
This module as a dpyr row function (see FunctAIFunc.vectorize);
its column type is the module's return annotation, or dtype.
Functions¶
| Name | Description |
|---|---|
| module | Make a Python function that calls AI functions into one program. |
module¶
module.module(
fn=None,
/,
*,
requires=(),
interface=None,
outputs=None,
answer_from=None,
**settings,
)
Make a Python function that calls AI functions into one program.
The body is ordinary Python: loops, ifs, helpers, several AI functions.
As a module it can be evaluated, optimized (each AI function inside
learns from the runs the metric accepts), run on a table, and saved as
one program. Use it bare (@module) or with requirements.
Its interface (blurb.interface) is derived from the function and
checked when the module is defined (a type its annotations name must be
defined by then), and every call is checked against it: inputs before
the code runs, outputs when it returns (InterfaceError, a
TypeError: a missing or unknown input names the field). Any,
object or no annotation is an opaque field (any value, never
checked, for data frames and the like); functai.JSON is any JSON
value; a parameter with a default is optional.
Parameters¶
| Name | Type | Description | Default |
|---|---|---|---|
| requires | list of str | Packages the program needs that functai cannot see from the code (["numpy>=2"]), for functai.save. |
() |
| outputs | dict | Several outputs, by name and type: outputs={"team": str, "minutes": int, "result": Reply}; the code returns a dict of them. The last is the answer. |
None |
| interface | dict | The whole interface as data (contract/programs.md), instead of deriving it; the code is then called with the inputs by keyword. | None |
| answer_from | AI function | The AI function whose answer, as it is written, is this module's answer: a view that shows only the module's boundary (a served program's caller) shows that text as the module's. | None |
| log_calls | The call log and receiver settings, for this module's calls (as for @ai). log_content={"transcript": False} keeps an input out of the log. |
required | |
| log_content | The call log and receiver settings, for this module's calls (as for @ai). log_content={"transcript": False} keeps an input out of the log. |
required | |
| caller | The call log and receiver settings, for this module's calls (as for @ai). log_content={"transcript": False} keeps an input out of the log. |
required | |
| observers | The call log and receiver settings, for this module's calls (as for @ai). log_content={"transcript": False} keeps an input out of the log. |
required | |
| journal | The call log and receiver settings, for this module's calls (as for @ai). log_content={"transcript": False} keeps an input out of the log. |
required |
Returns¶
| Name | Type | Description |
|---|---|---|
| FunctAIModule | Called like the original. The return annotation is the program's output type. |
See Also¶
evaluate: measure the program on rows with known answers.save: save it with everything it depends on.
Examples¶
import functai
from functai import *
@ai
def draft(topic: str) -> str:
"""A two-sentence paragraph about the topic."""
...
@ai
def shorten(text: str) -> str:
"""The text in at most twelve words."""
...
@module
def blurb(topic: str) -> str:
return shorten(draft(topic))
blurb("why paired comparisons need fewer examples")
functai: no model chosen, so using gpt-4.1-mini (environment ($OPENAI_API_KEY)). Choose one with functai.configure(lm=...).
'Paired comparisons simplify choices, reducing examples needed for efficient preference identification.'