Blog writer
Breaking down complex tasks into smaller, discrete steps is one of the best ways to improve the quality of LLM outputs. The blog writer workflow example does this by following the same approach a human would take to write a blog post: first conducting research, then generating a first draft, and finally editing that draft.
Workflow
The Blog Writer workflow consists of the following steps:
- Parallel research phase:
- Brainstorm topics using LLM (
<BrainstormTopics>
) - Research each topic in detail (
<ResearchTopic>
) - Gather web research (
<SearchWeb>
)
- Brainstorm topics using LLM (
- Write initial draft based on research (
<WriteDraft>
) - Edit and polish the content (
<EditDraft>
)
Running the example
# Install dependencies
pnpm install
# Set your OpenAI API key
export OPENAI_API_KEY=<your_api_key>
# Run the example
pnpm run start
Key patterns
Running components in parallel
The <Research>
component runs both the BrainstormTopics
and SearchWeb
components in parallel. Both sub-workflows return an array of strings which are automatically combined into a single array.
const Research = gensx.Component<ResearchComponentProps, ResearchOutput>(
"Research",
({ prompt }) => {
return (
<>
<BrainstormTopics prompt={prompt}>
{({ topics }) => {
return topics.map((topic) => <ResearchTopic topic={topic} />);
}}
</BrainstormTopics>
<SearchWeb prompt={prompt} />
</>
);
},
);
Streaming Output
The workflow streams back the final output to reduce the time that it takes for the user to receive the first token. The <EditDraft>
component is a StreamComponent
and the <ChatCompletion>
component has stream={true}
.
const EditDraft = gensx.StreamComponent<EditDraftProps>(
"EditDraft",
({ draft }) => {
return (
<ChatCompletion
stream={true}
model="gpt-4o-mini"
temperature={0}
messages={[
{ role: "system", content: systemPrompt },
{ role: "user", content: draft },
]}
/>
);
},
);
Then when the component is invoked, stream={true}
is passed to the component so that the output is streamed back and can be surfaced to the user:
<EditDraft draft={draft} stream={true} />
Additional resources
Check out the other examples in the GenSX Github Repo .