Getting Started

Installation

copy

pnpm add @aigur/client

A Simple Example

This is a simple example of a pipeline that takes a subject and returns a joke about that subject.

Btw, everything is fully typed! 🎉

Instantiate the Client

After installing the @aigur/client npm package, import the createClient function and instantiate the client.

index.ts

import { createClient } from '@aigur/client';
export const aigur = createClient();
//

Define Your API Keys

Pipelines use different services to generate your desired output. Define your API keys for those services in the apiKeys property. It is typed for specific services (OpenAI, Stability, Google etc) but you can add additional custom keys as well.

Since we're using the OpenAI GPT-3 service in our example, we'll add our API key for that.

index.ts

import { createClient } from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});

Create a New Pipeline

We'll create a new pipeline that will hold our logic. Let's name it jokegpt.

index.ts

import { createClient } from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create({
id: 'jokegpt',
});

Input/Output

Pipelines have input and output that are defined using Typescript Generics (and can be validated using runtime validation/parsing libraries). The signature is create<Input, Output>(options).

Input and Output must be an Object (unless you're streaming your results).

index.ts

import { createClient } from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
});

Go with the Flow

Now that we know what our pipeline accepts and returns, we need to define the flow of the pipeline itself. The flow is comprised of Nodes that are chained together. Each Node also has an input and an output.

We add a new Node using the flow builder with the node method. The node method accepts a Node (which is just a function, more on this later) and a function that will let you configure the Node's input (which is fully typed of course 🎉). We can enter hardcoded values in the input's properties or access previous Nodes or the pipeline's input parameters.

Let's start with a GPT3 Node with hardcoded values.

index.ts

import {
createClient,
gpt3Prediction
} from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
flow: (flow) =>
flow
.node(gpt3Prediction, () => ({
prompt: 'this is a hardcoded prompt',
}))
});

Chain Nodes

Let's add another Node that will prepare our prompt for the GPT3 Node. We'll add the replaceString Node which accepts text and modifier as input and does a simple string replacement (replaces the string $(text)$ with the value of the text input property).

We'll configure our Node's input using the second argument, the input function. The input function is a function that returns the Node's input (an Object or a ReadableStream). The input function accepts an object with three properties: prev, nodes and input:

  • prev is an object that contains the output of the previous Node.
  • nodes is an array of all previous Nodes.
  • input is the pipeline's input.

We want to reference our Pipeline's input (the subject property) so we'll use the input parameter which gives us access to the Pipeline's input.

The Node eventually takes our subject and prefixes it with the text "tell me a joke about".

Our GPT3 Node still has hardcoded values, let's change that.

index.ts

import {
createClient,
replaceString
} from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
flow: (flow) =>
flow
.node(replaceString, ({ input }) => ({
text: input.subject,
modifier: 'tell me a joke about $(text)$',
}))
.node(gpt3Prediction, () => ({
prompt: 'this is a hardcoded prompt',
}))
});

GPT

We'll now configure the GPT3 Node to use the previous Node's output (text) as the prompt.

index.ts

import {
createClient,
replaceString,
gpt3Prediction
} from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
flow: (flow) =>
flow
.node(replaceString, ({ input }) => ({
text: input.subject,
modifier: 'tell me a joke about $(text)$',
}))
.node(gpt3Prediction, ({ prev }) => ({
prompt: prev.text,
}))
});

Output

Last thing, we need to always return the pipeline's output. We'll use the output node to map any values we want from our node to the properties defined in our Pipeline's output schema.

💡

Don't forget this step or your Pipeline won't return the expected output!

index.ts

import {
createClient,
replaceString,
gpt3Prediction
} from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
flow: (flow) =>
flow
.node(replaceString, ({ input }) => ({
text: input.subject,
modifier: 'tell me a joke about $(text)$',
}))
.node(gpt3Prediction, ({ prev }) => ({
prompt: prev.text,
}))
.output(({ prev }) => ({
joke: prev.text,
})
});

Invoke it!

All that's left is to execute our pipeline. We can do that by calling the invoke method on the pipeline and passing the input parameters.

The output text is typed by the pipeline's output property.

index.ts

import {
createClient,
replaceString,
gpt3Prediction
} from '@aigur/client';
export const aigur = createClient({
apiKeys: {
openai: process.env.OPENAI_KEY!,
},
});
export const jokeGptPipeline = aigur.pipeline
.create<{ subject: string }, { joke: string }>({
id: 'jokegpt',
flow: (flow) =>
flow
.node(replaceString, ({ input }) => ({
text: input.subject,
modifier: 'tell me a joke about $(text)$',
}))
.node(gpt3Prediction, ({ prev }) => ({
prompt: prev.text,
}))
.output(({ prev }) => ({
joke: prev.text,
})
});
const { joke } = await jokeGptPipeline.invoke({
subject: 'a car'
});

Instantiate the Client

After installing the @aigur/client npm package, import the createClient function and instantiate the client.

Define Your API Keys

Pipelines use different services to generate your desired output. Define your API keys for those services in the apiKeys property. It is typed for specific services (OpenAI, Stability, Google etc) but you can add additional custom keys as well.

Since we're using the OpenAI GPT-3 service in our example, we'll add our API key for that.

Create a New Pipeline

We'll create a new pipeline that will hold our logic. Let's name it jokegpt.

Input/Output

Pipelines have input and output that are defined using Typescript Generics (and can be validated using runtime validation/parsing libraries). The signature is create<Input, Output>(options).

Input and Output must be an Object (unless you're streaming your results).

Go with the Flow

Now that we know what our pipeline accepts and returns, we need to define the flow of the pipeline itself. The flow is comprised of Nodes that are chained together. Each Node also has an input and an output.

We add a new Node using the flow builder with the node method. The node method accepts a Node (which is just a function, more on this later) and a function that will let you configure the Node's input (which is fully typed of course 🎉). We can enter hardcoded values in the input's properties or access previous Nodes or the pipeline's input parameters.

Let's start with a GPT3 Node with hardcoded values.

Chain Nodes

Let's add another Node that will prepare our prompt for the GPT3 Node. We'll add the replaceString Node which accepts text and modifier as input and does a simple string replacement (replaces the string $(text)$ with the value of the text input property).

We'll configure our Node's input using the second argument, the input function. The input function is a function that returns the Node's input (an Object or a ReadableStream). The input function accepts an object with three properties: prev, nodes and input:

  • prev is an object that contains the output of the previous Node.
  • nodes is an array of all previous Nodes.
  • input is the pipeline's input.

We want to reference our Pipeline's input (the subject property) so we'll use the input parameter which gives us access to the Pipeline's input.

The Node eventually takes our subject and prefixes it with the text "tell me a joke about".

Our GPT3 Node still has hardcoded values, let's change that.

GPT

We'll now configure the GPT3 Node to use the previous Node's output (text) as the prompt.

Output

Last thing, we need to always return the pipeline's output. We'll use the output node to map any values we want from our node to the properties defined in our Pipeline's output schema.

💡

Don't forget this step or your Pipeline won't return the expected output!

Invoke it!

All that's left is to execute our pipeline. We can do that by calling the invoke method on the pipeline and passing the input parameters.

The output text is typed by the pipeline's output property.

index.ts
ExpandClose

import { createClient } from '@aigur/client';
export const aigur = createClient();
//

That's it, we're done! 🎉

Don't be shy, give it a try!

No joke yet :(