Skip to content

Commit 49c4fef

Browse files
committed
Simplify the GenSX api.
1 parent 69cc955 commit 49c4fef

File tree

7 files changed

+85
-123
lines changed

7 files changed

+85
-123
lines changed

playground/index.tsx

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
executeJsxWorkflow,
3-
withWorkflowComponent,
4-
withWorkflowFunction,
5-
} from "@/index";
1+
import { Component, gensx } from "@/index";
62

73
// Pure workflow steps
84
const pureResearchBrainstorm = async ({ prompt }: { prompt: string }) => {
@@ -28,66 +24,78 @@ const pureEditor = async ({ draft }: { draft: string }) => {
2824
};
2925

3026
// Wrapped workflow steps
31-
const LLMResearchBrainstorm = withWorkflowFunction(pureResearchBrainstorm);
32-
const LLMResearch = withWorkflowFunction(
33-
async ({ topic }: { topic: string }) => {
34-
console.log("📚 Researching topic:", topic);
35-
return await Promise.resolve(`research results for ${topic}`);
36-
},
37-
);
38-
const LLMWriter = withWorkflowFunction(pureWriter);
39-
const LLMEditor = withWorkflowFunction(pureEditor);
40-
const WebResearcher = withWorkflowFunction(
41-
async ({ prompt }: { prompt: string }) => {
42-
console.log("🌐 Researching web for:", prompt);
43-
const results = await Promise.resolve([
44-
"web result 1",
45-
"web result 2",
46-
"web result 3",
47-
]);
48-
return results;
49-
},
50-
);
51-
52-
// Research collection component
53-
const ResearchCollection = withWorkflowComponent<
54-
[string[], string[]],
55-
{ prompt: string }
56-
>(({ prompt }: { prompt: string }) => (
57-
<>
58-
<LLMResearchBrainstorm prompt={prompt}>
59-
{topics => (
60-
<>
61-
{topics.map(topic => (
62-
<LLMResearch topic={topic} />
63-
))}
64-
</>
65-
)}
66-
</LLMResearchBrainstorm>
67-
<WebResearcher prompt={prompt} />
68-
</>
69-
));
27+
const LLMResearchBrainstorm = Component(pureResearchBrainstorm);
28+
const LLMResearch = Component(async ({ topic }: { topic: string }) => {
29+
console.log("📚 Researching topic:", topic);
30+
return await Promise.resolve(`research results for ${topic}`);
31+
});
32+
const LLMWriter = Component(pureWriter);
33+
const LLMEditor = Component(pureEditor);
34+
const WebResearcher = Component(async ({ prompt }: { prompt: string }) => {
35+
console.log("🌐 Researching web for:", prompt);
36+
const results = await Promise.resolve([
37+
"web result 1",
38+
"web result 2",
39+
"web result 3",
40+
]);
41+
return results;
42+
});
7043

71-
const BlogWritingWorkflow = withWorkflowComponent<string, { prompt: string }>(
44+
// When building a workflow out of components, there are two options:
45+
// 1. Use the Component function to wrap it and specify the input and output types. This gets you a function with type safe inputs and outputs (if you just call it as a function).
46+
// 2. Don't wrap it in the Component function, and do not specify the output type. You get a function that matches the JSX.Element signature, but it has an unknown output type. If you try to specify the output type, you get a type error (unknown is not assignable to X).
47+
const ParallelResearch = Component<{ prompt: string }, [string[], string[]]>(
7248
({ prompt }: { prompt: string }) => (
73-
<ResearchCollection prompt={prompt}>
74-
{([catalogResearch, webResearch]) => {
75-
console.log("🧠 Research:", { catalogResearch, webResearch });
76-
return (
77-
<LLMWriter research={catalogResearch.join("\n")} prompt={prompt}>
78-
{draft => <LLMEditor draft={draft} />}
79-
</LLMWriter>
80-
);
81-
}}
82-
</ResearchCollection>
49+
<>
50+
<LLMResearchBrainstorm prompt={prompt}>
51+
{topics => (
52+
<>
53+
{topics.map(topic => (
54+
<LLMResearch topic={topic} />
55+
))}
56+
</>
57+
)}
58+
</LLMResearchBrainstorm>
59+
<WebResearcher prompt={prompt} />
60+
</>
8361
),
8462
);
63+
64+
const BlogWritingWorkflow = async ({ prompt }: { prompt: string }) => (
65+
<ParallelResearch prompt={prompt}>
66+
{([catalogResearch, webResearch]) => {
67+
console.log("🧠 Research:", { catalogResearch, webResearch });
68+
return (
69+
<LLMWriter research={catalogResearch.join("\n")} prompt={prompt}>
70+
{draft => <LLMEditor draft={draft} />}
71+
</LLMWriter>
72+
);
73+
}}
74+
</ParallelResearch>
75+
);
8576
async function main() {
8677
console.log("🚀 Starting blog writing workflow");
87-
const result = await executeJsxWorkflow<string>(
78+
79+
// Use the gensx function to execute the workflow and annotate with the output type.
80+
const result = await gensx<string>(
8881
<BlogWritingWorkflow prompt="Write a blog post about the future of AI" />,
8982
);
90-
console.log("✅ Final result:", result);
83+
84+
// Or just call the workflow as a function, and cast to the output type.
85+
const result2 = (await (
86+
<BlogWritingWorkflow prompt="Write a blog post about using GenSX to 10x your productivity." />
87+
)) as string;
88+
89+
// Still need to cast here, because we didn't use the Component helper to wrap the workflow.
90+
const result3 = (await BlogWritingWorkflow({
91+
prompt: "Write a blog post about the future of AI",
92+
})) as string;
93+
94+
// Don't need to cast here, because we used the Component helper to wrap the workflow.
95+
const researchResult = await ParallelResearch({
96+
prompt: "Write a blog post about the future of AI",
97+
});
98+
console.log("✅ Final result:", { result, result2, result3, researchResult });
9199
}
92100

93101
await main();

src/component.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { MaybePromise } from "./jsx-runtime";
2+
3+
export function Component<TInput extends Record<string, unknown>, TOutput>(
4+
fn: (input: TInput) => MaybePromise<TOutput> | JSX.Element,
5+
) {
6+
function WorkflowFunction(
7+
props: TInput & {
8+
children?: (output: TOutput) => MaybePromise<TOutput> | JSX.Element;
9+
},
10+
): Promise<TOutput> {
11+
return Promise.resolve(fn(props)) as Promise<TOutput>;
12+
}
13+
return WorkflowFunction;
14+
}

src/components/Collect.tsx

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/gensx.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export async function gensx<TOutput>(node: JSX.Element): Promise<TOutput> {
2+
return (await node) as TOutput;
3+
}

src/index.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212
7. Support parallel execution of steps (either dynamic via something liek a collector, or static via a few explicitly defined siblings)
1313
*/
1414

15-
import { executeJsxWorkflow } from "./workflow/execute";
16-
import {
17-
withWorkflowComponent,
18-
withWorkflowFunction,
19-
} from "./workflow/withWorkflowStep";
15+
import { Component } from "./component";
16+
import { gensx } from "./gensx";
2017

21-
export { executeJsxWorkflow, withWorkflowComponent, withWorkflowFunction };
18+
export { Component, gensx };

src/workflow/execute.tsx

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/workflow/withWorkflowStep.tsx

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)