teff.flow.compiler¶
teff.flow.compiler
¶
Declarative flow.yaml compiler — the authoring layer.
A flow.yaml is a small, high-level document that describes how the
app should behave (teams, chains, gates) without spelling out every node
and edge. This package compiles it into a :class:teff.flow.Flow, which
in turn produces a regular Graph and can be exported as the compiled
graph.yaml artifact::
flow.yaml ──compile()--> Flow ──compile()--> Graph
└── to_yaml() ──► graph.yaml
Invariant: the compiler only ever produces things a hand-written
graph.yaml (or Flow) could express — every idiom below lowers onto
the existing node types and the existing Flow methods. There is no
second runtime.
The implementation is split by concern:
- :mod:
teff.flow.compiler._common— shared node-level builders; - :mod:
teff.flow.compiler._nodes— single-node idioms (llm:etc.); - :mod:
teff.flow.compiler._flow— flow-control idioms (parallel:…); - :mod:
teff.flow.compiler._team— supervised-team idioms (team:…); - :mod:
teff.flow.compiler._state— tools/state extraction.
Document grammar (0.2 MVP — see docs/design/two-layer.md)::
name: my-app
description: ...
default_provider: ollama
default_model: llama3.1:8b
providers: [...] # pass-through (graph providers)
tools: [...] # pass-through (tool registry)
state: {schema: ..., initial: ...} # pass-through (graph state)
steps:
- llm: {id: replier, model: gpt-4, system: ..., output_key: answer}
- transform: {id: shout, action: uppercase, input_key: answer,
output_key: shout}
- agent_step: {id: coder, system: "You are...", output_key: code,
model: ..., tools: [...]}
- team:
id: lead
leader:
system: "You are the team lead... route to coder or finish."
model: llama3.1:8b
roles:
coder: {system: "...", output_key: code}
planner: {system: "...", output_key: plan}
fallback: planner
max_rounds: 6
- supervisor: # native decider — no team wrapper
id: lead
system: "You are the team lead... route to coder or finish."
route_keys: {coder: code, planner: plan}
done_keys: [code, plan]
fallback: planner
max_rounds: 6
agents: # optional — wires the whole loop
coder: [agent_step: {system: "...", output_key: code}]
planner: [agent_step: {system: "...", output_key: plan}]
finish:
- transform: {action: now, output_key: delivered_at}
- supervise: # route an existing decider (advanced)
key: next_agent
agents:
coder: [agent_step: {system: "...", output_key: code}]
planner: [agent_step: {system: "...", output_key: plan}]
finish:
- transform: {action: now, output_key: delivered_at}
- parallel:
branches:
- llm: {...}
- agent: {...}
converge: {transform: {...}}
- map:
input_keys: [items]
output_key: results
processor: {llm: {model: ..., system: "..."}}
- branch:
key: sentiment
cases:
- {value: positive, steps: [transform: {...}]}
- {value: negative, steps: [transform: {...}]}
default: {transform: {...}}
converge: {transform: {...}}
- loop:
key: verdict
until: pass
body:
- llm: {...}
done:
- llm: {...}
- interrupt:
id: approve
key: decision
prompt: "Send to work?"
strategy: {any_of: [approve, ok], decision_key: decision,
pass_value: approve, fail_value: rework}
- route:
key: decision
routes:
- {when: "decision=approve", goto: final}
- {when: "decision=rework", goto: refine}
goto: STOP
Unknown steps raise :class:teff.errors.ConfigError.
Functions:
| Name | Description |
|---|---|
build_flow_to_yaml |
Compile |
compile_flow_file |
Compile a |
flow_from_yaml |
Compile a parsed |
load_flow |
Load a |
load_flow_yaml |
Parse a |
looks_like_flow |
Return |
build_flow_to_yaml
¶
build_flow_to_yaml(path, output=None)
Compile flow.yaml at path to a graph.yaml document string.
Returns the compiled YAML text; when output is given the text is also written to that path.
Source code in teff/flow/compiler/__init__.py
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | |
compile_flow_file
¶
compile_flow_file(path)
Compile a flow.yaml file into a plain Graph.
Source code in teff/flow/compiler/__init__.py
219 220 221 222 | |
flow_from_yaml
¶
flow_from_yaml(data)
Compile a parsed flow.yaml mapping into a :class:Flow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
dict
|
The document mapping returned by :func: |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
Flow
|
class: |
Flow
|
complete graph (and :meth: |
Source code in teff/flow/compiler/__init__.py
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
load_flow
¶
load_flow(path, data=None)
Load a flow.yaml as a (graph, tools, initial, reducers) tuple.
Mirrors :func:teff.yaml.load_workflow so callers (and the CLI) can
treat flow.yaml and graph.yaml interchangeably::
graph, tools, state, reducers = load_flow("app/flow.yaml")
The compiled graph reflects all idioms in the authoring layer; the
optional tools: / state: blocks are passed through unchanged.
Pass data (a document already resolved by :func:teff.yaml.load_workflow
— env interpolation and include: blocks applied) to reuse it instead
of re-reading the file.
Source code in teff/flow/compiler/__init__.py
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
load_flow_yaml
¶
load_flow_yaml(path)
Parse a flow.yaml file, interpolating ${ENV} references.
Returns:
| Type | Description |
|---|---|
dict
|
The document mapping. Raises :class: |
dict
|
error or a non-mapping document. |
Source code in teff/flow/compiler/__init__.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
looks_like_flow
¶
looks_like_flow(data)
Return True when data is authored in the flow.yaml idiom surface.
A low-level graph documents steps with explicit id/type
keys; the authoring layer uses the shorthand idiom keys instead
(llm:, team:, map:, …).
Source code in teff/flow/compiler/__init__.py
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | |