flowchart LR T([topic]) --> O[outline] --> D[draft] --> E[edit] --> R([article])
What it shows
- Each step is a small component that builds a prompt and calls the model.
- The pipeline, not the steps, decides the order.
Chain three LLM steps: outline, draft, edit.
flowchart LR T([topic]) --> O[outline] --> D[draft] --> E[edit] --> R([article])
import { Component, Pipeline } from '@astack-tech/core';
import type { Port } from '@astack-tech/core';
import { ModelProvider } from '@astack-tech/integrations';
const apiKey = process.env['DEEPSEEK_API_KEY'];
if (!apiKey) {
throw new Error('Set DEEPSEEK_API_KEY to run this example.');
}
const model = new ModelProvider.Deepseek({ apiKey });
/**
* One workflow step: build a prompt from the input, ask the model, send the answer on.
*/
class Step extends Component {
private readonly instruction: (input: string) => string;
constructor(instruction: (input: string) => string) {
super({});
this.instruction = instruction;
}
override _transform($i: Port, $o: Port): void {
$i('in').receive((input: string) => {
void model.generateCompletion(this.instruction(input)).then(output => {
$o('out').send(output);
});
});
}
}
const pipeline = new Pipeline();
pipeline.addComponent('outline', new Step(topic => `Write a 3-point outline about: ${topic}`));
pipeline.addComponent(
'draft',
new Step(outline => `Write one short paragraph per point:\n${outline}`)
);
pipeline.addComponent('edit', new Step(draft => `Make this clearer and shorter:\n${draft}`));
pipeline.connect('outline.out', 'draft.in');
pipeline.connect('draft.out', 'edit.in');
// outline -> draft -> edit. The endpoint `edit.out` is inferred.
console.log(await pipeline.run<string>('outline.in', 'why data flow suits LLM apps'));
pnpm install && pnpm build
export DEEPSEEK_API_KEY=sk-...
pnpm --filter @astack-examples/workflow start