Skip to content

Quickstart

In this quickstart, you’ll learn how to get up and running with GenSX. GenSX is a simple typescript framework for building complex LLM applications using JSX. If you haven’t already, check out the basic concepts to learn more about how GenSX works.

Prerequisites

Before getting started, make sure you have the following:

Create a new project

To get started, run the following command with your package manager of choice in an empty directory. This will create a new GenSX project to get you started.

Terminal window
# Using npm
npm create gensx@latest my-app
# Using npx
npx create-gensx@latest my-app
# Using yarn
yarn create gensx my-app
# Using pnpm
pnpm create gensx my-app

In index.tsx, you’ll find a simple OpenAI chat completion component:

import { gsx } from "gensx";
import { OpenAIProvider, ChatCompletion } from "@gensx/openai";
interface RespondProps {
userInput: string;
}
type RespondOutput = string;
const Respond = gsx.Component<RespondProps, RespondOutput>(
"Respond",
async ({ userInput }) => {
return (
<ChatCompletion
model="gpt-4o-mini"
messages={[
{
role: "system",
content:
"You are a helpful assistant. Respond to the user's input.",
},
{ role: "user", content: userInput },
]}
/>
);
},
);
const result = await gsx.execute<string>(
<OpenAIProvider apiKey={process.env.OPENAI_API_KEY}>
<Respond userInput="Hi there! Say 'Hello, World!' and nothing else." />
</OpenAIProvider>,
);
console.log(result);

The component is executed through gsx.execute(), which processes the JSX tree from top to bottom. In this example:

  1. First, the OpenAIProvider component is initialized with your API key
  2. Then, the Respond component receives the userInput prop
  3. Inside Respond, a ChatCompletion component is created with the specified model and messages
  4. The result flows back up through the tree, ultimately returning the response from gpt-4o-mini.

Components in GenSX are pure functions that take props and return outputs, making them easy to test and compose. The JSX structure makes the data flow clear and explicit - each component’s output can be used by its children through standard TypeScript/JavaScript.

Running the project

To run the project, you’ll need to set the OPENAI_API_KEY environment variable.

Terminal window
# Set the environment variable
export OPENAI_API_KEY=<your-api-key>
# Run the project
pnpm dev

Combining components

The example above is a simple workflow with a single component. In practice, you’ll often want to combine multiple components to create more complex workflows.

Components can be nested to create multi-step workflows with each component’s output being passed through a child function. For example, let’s define two components: a Research component that gathers information about a topic, and a Writer component that uses that information to write a blog post.

// Research component that gathers information
const Research = gsx.Component<{ topic: string }, string>(
"Research",
async ({ topic }) => {
return (
<ChatCompletion
model="gpt-4o-mini"
messages={[
{
role: "system",
content:
"You are a research assistant. Provide key facts about the topic.",
},
{ role: "user", content: topic },
]}
/>
);
},
);
// Writer component that uses research to write content
const Writer = gsx.Component<{ topic: string; research: string }, string>(
"Writer",
async ({ topic, research }) => {
return (
<ChatCompletion
model="gpt-4o-mini"
messages={[
{
role: "system",
content:
"You are a content writer. Use the research provided to write a blog post about the topic.",
},
{ role: "user", content: `Topic: ${topic}\nResearch: ${research}` },
]}
/>
);
},
);

Now you can combine these components using a child function:

// Combine components using child functions
const result = await gsx.execute<string>(
<OpenAIProvider apiKey={process.env.OPENAI_API_KEY}>
<Research topic="quantum computing">
{(research) => <Writer topic="quantum computing" research={research} />}
</Research>
</OpenAIProvider>,
);
console.log(result);

In this example, the Research component gathers information about the topic which then passes the informaton to the Writer component. The Writer component uses that information to write an article about the topic which is then returned as the result.

Streaming

One common challenge with LLM workflows is handling streaming responses. Any given LLM call can return a response as a string or as a stream of tokens. Typically you’ll want the last component of your workflow to stream the response.

To take advantage of streaming, all you need to do is update the Writer component to use StreamComponent and pass stream={true} when you invoke it.

const Writer = gsx.StreamComponent<{ topic: string; research: string }, string>(
"Writer",
async ({ topic, research }) => {
return (
<ChatCompletion
stream={true}
model="gpt-4o-mini"
messages={[
{
role: "system",
content:
"You are a content writer. Use the research provided to write a blog post about the topic.",
},
{ role: "user", content: `Topic: ${topic}\nResearch: ${research}` },
]}
/>
);
},
);
const stream = await gsx.execute<Streamable>(
<OpenAIProvider apiKey={process.env.OPENAI_API_KEY}>
<Research topic="quantum computing">
{(research) => (
<Writer topic="quantum computing" research={research} stream={true} />
)}
</Research>
</OpenAIProvider>,
);
// Print the streaming response
for await (const chunk of stream) {
process.stdout.write(chunk);
}

While this is nice, the real power of streaming components comes when you expand or refactor your workflow. Now you could easily add an <Editor> component to the workflow that streams the response to the user with minimal changes. There’s no extra plumbing needed besides removing the stream={true} prop on the Writer component.

const stream = await gsx.execute<Streamable>(
<OpenAIProvider apiKey={process.env.OPENAI_API_KEY}>
<Research topic="quantum computing">
{(research) => <Writer topic="quantum computing" research={research}>
{(content) => <Editor content={content} stream={true}/>}
</Writer>
</Research>
</OpenAIProvider>,

Next steps

Now that you’ve gone through the quickstart, you should be able to start building with GenSX. Take a look at the following examples to see how you can build more complex workflows.