Getting Started
This guide will get you set up and ready to use the Composable CLI and SDK.
Composable Studio
In order to create and manage your interaction you need to login to the Composable Studio. This is a web application in which you can create and manage your interactions.
Before using the SDK or the CLI to make requests to the Composable API, you will need to create a Project and generate an API Key from your Settings.
In order to access and use your interactions from outside the Studio application, you can use the Composable CLI. If you want to integrate your interactions in your own application you can use the Composable SDK.
Currently, the Composable SDK is only available for JavaScript / TypeScript and code generation is only available for TypeScript. To use Composable in other languages you need to directly access the REST API. Please refer to the API Reference guide for information about using the REST API.
There is a second and more efficient way to integrate the interactions in your own application by using code generation. Code generation will generate high level classes along with TypeScript interfaces to easily access your interactions. We will talk about code generation at the end of this guide.
We will cover the basics of the CLI and of the SDK in the following sections. For full documentation see the projects themselves. Let's start with a quick look at the installation and basic usage of these tools.
Composable CLI
This is a command line application that can be used to access your Composable projects. It was designed to fulfill the following main use cases:
- List and switch between your Composable projects
- List the existing interactions and execution environments
- Run interactions once or multiple times over a set of different data inputs
- Generate data inputs to run the interactions against
- Search through the history of runs to inspect detailed results
Requirements
A TTY terminal and, as for the SDK, Node version 18 or higher is required.
Installation
npm -g install @becomposable/cli
Basic Usage
You need to pass an API Key to access an organziation (i.e. account) you created in Composable Studio. API Keys are created at the organziation level and can be found in the Settings of your organization.
Let's list all the projects in the organization owning the API KEY:
composable -k {YOUR_API_KEY} projects
To access a project you must pass the project ID too. Let's list the interactions inside a project:
composable -k {YOUR_API_KEY} -p {PROJECT_ID} interactions
To simplify using the CLI command options which can get quite long, you can create profiles to store common arguments like the API key, the target project or the target server.
To create a profile run:
composable config add
and follow the interactive prompts.
Once you have created a profile you can use it to run commands without having to pass the arguments every time. The last created profile will be automatically selected as the defualt profile. To switch to another profile use the composable config user {PROFILE_NAME}
command.
Now the following command:
composable interactions
will list the interactions using the current profile api key and target project.
In the CLI examples throughout this documentation, we will assume a profile was configured so we will not explictly use the -k
and -p
flags to pass the API key and the project ID.
Let's run an interaction. We will use the run
command.
composable run {INTERACTION_ID}
This command has plenty of options. It is not the scope of this guide to explain them all.
To summarize we can run an interaction once or multiple times on a set of data inputs (specfified from a file using --input
or inline using --data
) we can run a interaction by giving some.
When running a single interaction the response will be, by default, streamed on the console.
You can also tag runs to be able to easily search for them later using composable runs
.
Example:
composable run --tags testing {INTERACTION_1_ID}
composable run --tags testing {INTERACTION_2_ID}
# then, later retrieve the run results having the testing_session tag
composable runs --tags testing
For more information about the commands use the help
command or the -h
flag on a command or check the cli documentation.
Composable SDK
This is a JavaScript SDK that can be used in both Node.js and in the browser.
Requirements
Node version 18 or higher is required (the fetch API is required). It will also work with node version 17.5 by using the --experimental-fetch flag
Installation
npm install @becomposable/client
Basic Usage
Listing the projects in an organization:
import {ComposableClient} from "@becomposable/client"
const client = new ComposableClient({
apikey: "YOUR_API_KEY_HERE"
})
const projects = await client.projects.list();
for (const project of projects) {
console.log(project.name+': '+project.id);
}
You can see in the previous example how we initialize the ComposableClient with the API key. The API key will authenticate us on the server and will select the organization to which the key belongs.
Let's list now the interactions in a project
import { ComposableClient } from "@becomposable/client"
const client = new ComposableClient({
apikey: "YOUR_API_KEY_HERE",
})
const interactions = await client.interactions.list();
for (const interaction of interactions) {
console.log(interaction.name + ': ' + interaction.id);
}
In the example above, you see we added a projectId
option when instantiating the client. This is the ID of the project we want to access.
Both the API key and the project ID are set when initializing the client and will be used for all the requests made with that client.
You can change the project ID at any time by setting it directly on the client:
client.project = "New Project ID"
Both API key and project ID parameters are required when accessing objects in a project. These parameters are sent, as custom headers, along each request to the server and are used to authenticate the user and to select the project.
Let's suppose we created an interaction named "Which Color" which is sending to the LLM an object name to get in response one of its possible colors.
Suppose interactionId
is the ID of the interaction. We can run it as follows:
import { ComposableClient } from "@becomposable/client"
const client = new ComposableClient({
apikey: "YOUR_API_KEY_HERE",
})
// Note that the interactionId argument must be a valid interaction ID which belongs to the project you are connected to.
const run = await client.interactions.execute(interactionId, {
data: { object: "sky" }
});
console.log(run.result);
The response of the LLM will be:
{
"color": "blue"
}
Code Generation
Let's look deeper at the interaction execution above. You can notice the interaction takes some data as input, input which is used to generate the prompt sent to the LLM. Also, the interaction instructs the LLM to respond in JSON and not in plain text. Otherwise, in complex cases it will be difficult to parse the result and structure it.
In our example the input data is quite simple: {object: string}
. Same the result data: {color: string}
. But in real world applications the input and response data may be quite complex.
This is why in real life applications managing the input and output data structures becomes hard without having a strong typing system. Here is where code generation becomes handy.
In Composable Studio, when we need to interact with the LLM using complex structures we can control the shapes of these structures by defining JSON Schemas.
In short, code generation will generate high level classes along with TypeScript interfaces which describe the input and the output data. Let's suppose we generated the code for the interaction above. The generated code will look like this:
import { ComposableClient, ComposableClientProps, InteractionBase } from "@becomposable/client";
/**
* WhichColor input type
*/
export interface WhichColorProps {
object: string;
}
/**
* WhichColor result type
*/
export interface WhichColorResult {
color: string;
}
/**
* WhichColor
*/
export class WhichColor extends InteractionBase<WhichColorProps, WhichColorResult> {
readonly projectId = "654df9de09676ad3b8631dc3";
constructor(clientOrProps: ComposableClient | ComposableClientProps) {
super ("6554cf617eae1c28ef5f3d40", clientOrProps);
this.client.project = this.projectId;
}
}
The intercation class name is the Pascal case version of the interaction name.
And to execute the interaction we can do:
import { WhichColor } from "./WhichColor/index.js"
const wcolor = new WhichColor({
apikey: "YOUR_API_KEY_HERE"
});
const run = await wcolor.execute({
data: { object: "sky" }
});
console.log(run.result);
As you can see, the interaction execution code is quite similar with the one we used before, when directly using the SDK.
The big difference is that the code using the generated interface class is strongly typed.
In the SDK execution example we can put anything as the data
value. Also we don't have any hint about what contains the run.result
.
Using the generated class, we have a strong typing system which will help us to write better code and to avoid errors.
Generating Classes
The code generation is done using the Composable CLI.
Here are some basic examples on how the code generation works. For a complete documentation look into the CLI documentation.
To generate the code for an interaction you need to know the interaction class name (which is the Pascal Case version of the interaction name).
You can find the interaction class name by using the command composable interaction {interactionId}
.
Let's suppose we want to generate the code for the interaction named "Which Color". We simply run:
composable codegen WhichColor
This will generate a interactions/WhichColor
folder in the current directory.
You can change the target directory using the -d, --dir
option. For example:
composable codegen WhichColor -d ./
will put the WhichColor folder in the current directory.
If you want to generate the code for all the interactions in a project you should ommit the interaction class name: composable codegen
.
Interaction class anatomy
The code generated for an interaction will always be saved in a directory having the same name as the interaction class name. The directory will contain multiple files, depending on the interaction and on the options used at generation time.
The structure of the directory is:
{interactionClassName}/
index.ts
draft.ts
v2.ts
v3.ts
...
v{latestVersion}.ts
The index.ts
file will always exist. The other files are generated only if requested. But at least one of these files will be present. The default generation behavior is to export the draft and the last published version.
The index.ts
will just re-export one of the other files. By default it will re-export the latest published version, or, if no versions exists, the draft version.
You can control which versions are generated and which version is re-exported by the index.ts file using the options of the composable codegen
command.
What's next?
Great, you're now set up with an API client and have made your first request to the API. Here are a few links that might be handy as you venture further into Composable: