Skip to content

Commit 40f3e60

Browse files
authored
feat: align maestro and library (#31)
* change files path to library (PLAT-962) * added maestro functions * added tests * added new tools * trigger quality on push * readme
1 parent 5b5f4d5 commit 40f3e60

File tree

30 files changed

+1395
-915
lines changed

30 files changed

+1395
-915
lines changed

.github/workflows/quality-checks.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ concurrency:
66
cancel-in-progress: true
77
on:
88
pull_request:
9+
push:
910
jobs:
1011
quality-checks:
11-
runs-on: ubuntu-20.04
12+
runs-on: ubuntu-latest
1213
timeout-minutes: 10
1314
steps:
1415
- name: Checkout
@@ -19,11 +20,9 @@ jobs:
1920
with:
2021
node-version: 20.18.0
2122
cache: 'npm'
22-
23+
2324
- name: Install dependencies
2425
run: npm install
25-
26+
2627
- name: Run quality checks
2728
run: npm run quality
28-
29-

README.md

Lines changed: 147 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ The AI21 API Client is a TypeScript library that provides a convenient interface
1717
- [Examples](#examples-tldr) 🗂️
1818
- [AI21 Official Documentation](#Documentation)
1919
- [Chat](#Chat)
20+
- [Maestro (Beta)](#Maestro)
2021
- [Conversational RAG (Beta)](#Conversational-RAG)
21-
- [Files](#Files)
22-
22+
- [Library](#Library)
2323

2424
## Environment Support
2525

@@ -32,7 +32,7 @@ This client supports both Node.js and browser environments:
3232
// Browser usage example
3333
const client = new AI21({
3434
apiKey: process.env.AI21_API_KEY, // or pass it in directly
35-
dangerouslyAllowBrowser: true // Required for browser environments
35+
dangerouslyAllowBrowser: true, // Required for browser environments
3636
});
3737
```
3838

@@ -64,7 +64,6 @@ Feel free to dive in, experiment, and adapt these examples to suit your needs. W
6464

6565
The full documentation for the REST API can be found on [docs.ai21.com](https://docs.ai21.com/).
6666

67-
6867
## Chat
6968

7069
To use the AI21 API Client, you'll need to have an API key. You can obtain an API key by signing up for an account on the AI21 website.
@@ -82,7 +81,9 @@ const client = new AI21({
8281

8382
const response = await client.chat.completions.create({
8483
model: 'jamba-mini',
85-
messages: [{ role: 'user', content: 'Hello, how are you? tell me a 100 line story about a cat named "Fluffy"' }],
84+
messages: [
85+
{ role: 'user', content: 'Hello, how are you? tell me a 100 line story about a cat named "Fluffy"' },
86+
],
8687
});
8788

8889
console.log(response);
@@ -105,38 +106,121 @@ for await (const chunk of streamResponse) {
105106
console.log(chunk.choices[0]?.delta?.content || '');
106107
}
107108
```
109+
108110
---
109-
### Files
110111

112+
## Maestro (Beta)
111113

112-
The `AI21` class provides a `files` property that gives you access to the Files API. You can use it to upload, retrieve, update, list, and delete files.
114+
AI21 Maestro is an advanced AI orchestration platform that can intelligently use tools and manage complex workflows. The `AI21` class provides a `beta.maestro` property that gives you access to the Maestro API.
113115

116+
### Basic Usage
114117

115118
```typescript
116119
import { AI21 } from 'ai21';
117120

118121
const client = new AI21({
119-
apiKey: process.env.AI21_API_KEY, // or pass it in directly
122+
apiKey: process.env.AI21_API_KEY,
120123
});
121124

122-
const fileUploadResponse = await client.files.create({
123-
file: './articles/article1.pdf',
124-
labels: ['science', 'biology'],
125-
path: 'virtual-path/to/science-articles',
125+
// Create a maestro run
126+
const run = await client.beta.maestro.runs.create({
127+
input: 'Analyze the latest market trends in renewable energy',
126128
});
127129

130+
// Get the run status
131+
const result = await client.beta.maestro.runs.get(run.id);
132+
console.log(result);
133+
```
134+
135+
### Create and Poll (Recommended)
128136

129-
const file = await client.files.get(fileUploadResponse.fileId);
137+
For convenience, you can use `createAndPoll()` which automatically waits for completion:
130138

139+
```typescript
140+
const result = await client.beta.maestro.runs.createAndPoll(
141+
{
142+
input: 'Write a comprehensive report on AI trends in 2024',
143+
tools: [{ type: 'web_search' }],
144+
budget: 'medium',
145+
},
146+
{
147+
timeout: 30000, // 30 seconds
148+
interval: 2000, // Poll every 2 seconds
149+
},
150+
);
151+
152+
console.log(result.result);
153+
```
154+
155+
### Advanced Features
156+
157+
Maestro supports various advanced configurations:
158+
159+
```typescript
160+
const advancedRun = await client.beta.maestro.runs.createAndPoll({
161+
input: 'Research sustainable energy solutions',
162+
163+
// Specify tools to use
164+
tools: [
165+
{
166+
type: 'web_search',
167+
urls: ['https://example.com', 'https://research.org'],
168+
},
169+
{
170+
type: 'file_search',
171+
file_ids: ['file-123', 'file-456'],
172+
labels: ['research', 'energy'],
173+
},
174+
],
175+
176+
// Define specific requirements
177+
requirements: [
178+
{
179+
name: 'Data Sources',
180+
description: 'Include at least 3 credible sources',
181+
isMandatory: true,
182+
},
183+
{
184+
name: 'Length',
185+
description: 'Report should be 1000-2000 words',
186+
isMandatory: false,
187+
},
188+
],
189+
190+
// Specify models to use
191+
models: ['jamba-large'],
192+
193+
// Control resource allocation
194+
budget: 'high',
195+
196+
// Request additional fields in response
197+
include: ['data_sources', 'requirements_result'],
198+
199+
// Set response language
200+
response_language: 'english',
201+
});
202+
```
203+
204+
### Structured Input messages
205+
206+
You can also provide structured input messages:
207+
208+
```typescript
209+
const structuredRun = await client.beta.maestro.runs.create({
210+
input: [
211+
{ role: 'system', content: 'You are a research assistant specializing in technology trends.' },
212+
{ role: 'user', content: 'What are the emerging AI technologies in healthcare?' },
213+
],
214+
tools: [{ type: 'web_search' }],
215+
});
131216
```
132217

133218
---
134-
### Conversational-RAG
135219

220+
## Conversational RAG (Beta)
136221

137222
The `AI21` class provides a `conversationalRag` property that gives you access to the Conversational RAG API. You can use it to ask questions that are answered based on the files you uploaded.
138223

139-
140224
```typescript
141225
import { AI21 } from 'ai21';
142226

@@ -145,11 +229,56 @@ const client = new AI21({
145229
});
146230

147231
const convRagResponse = await client.conversationalRag.create({
148-
messages: [{ role: 'user', content: 'This question presumes that the answer can be found within the uploaded files.' }],
149-
});
150-
232+
messages: [
233+
{
234+
role: 'user',
235+
content: 'This question presumes that the answer can be found within the uploaded files.',
236+
},
237+
],
238+
});
151239
```
152240

241+
---
242+
243+
## Library
244+
245+
The `AI21` class provides a `library` property that gives you access to the Library Files API. This is a separate file management system designed for library-specific operations.
246+
247+
### Library Files Management
248+
249+
```typescript
250+
import { AI21 } from 'ai21';
251+
252+
const client = new AI21({
253+
apiKey: process.env.AI21_API_KEY,
254+
});
255+
256+
// Upload a file to the library
257+
const libraryFile = await client.library.files.create({
258+
file: './documents/research-paper.pdf',
259+
labels: ['research', 'academic'],
260+
path: 'library/research/papers',
261+
});
262+
263+
// Get a library file
264+
const file = await client.library.files.get(libraryFile.fileId);
265+
266+
// List library files with filters
267+
const files = await client.library.files.list({
268+
labels: ['research'],
269+
path: 'library/research',
270+
});
271+
272+
// Update a library file
273+
await client.library.files.update({
274+
fileId: libraryFile.fileId,
275+
labels: ['research', 'academic', 'updated'],
276+
path: 'library/research/updated-papers',
277+
});
278+
279+
// Delete a library file
280+
await client.library.files.delete(libraryFile.fileId);
281+
```
153282

154283
## Configuration
155284

examples/studio/conversational-rag/rag-engine.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ async function waitForFileProcessing(
1515
const startTime = Date.now();
1616

1717
while (Date.now() - startTime < timeout) {
18-
const file: FileResponse = await client.files.get(fileId);
18+
const file: FileResponse = await client.library.files.get(fileId);
1919
if (file.status !== 'PROCESSING') {
2020
return file;
2121
}
@@ -29,7 +29,7 @@ async function uploadGetUpdateDelete(fileInput, path) {
2929
const client = new AI21({ apiKey: process.env.AI21_API_KEY });
3030
try {
3131
console.log(`Starting upload for file:`, typeof fileInput);
32-
const uploadFileResponse: UploadFileResponse = await client.files.create({
32+
const uploadFileResponse: UploadFileResponse = await client.library.files.create({
3333
file: fileInput,
3434
path: path,
3535
});
@@ -41,20 +41,20 @@ async function uploadGetUpdateDelete(fileInput, path) {
4141

4242
if (file.status === 'PROCESSED') {
4343
console.log('Starting file update...');
44-
await client.files.update({
44+
await client.library.files.update({
4545
fileId: uploadFileResponse.fileId,
4646
labels: ['test99'],
4747
publicUrl: 'https://www.miri.com',
4848
});
49-
file = await client.files.get(uploadFileResponse.fileId);
49+
file = await client.library.files.get(uploadFileResponse.fileId);
5050
console.log('✓ File update completed');
5151
} else {
5252
console.log(`⚠ File processing failed with status ${file.status}`);
5353
return; // Exit early if processing failed
5454
}
5555

5656
console.log('Starting file deletion...');
57-
await client.files.delete(uploadFileResponse.fileId);
57+
await client.library.files.delete(uploadFileResponse.fileId);
5858
console.log('✓ File deletion completed');
5959

6060
// Add buffer time between operations
@@ -67,7 +67,7 @@ async function uploadGetUpdateDelete(fileInput, path) {
6767

6868
async function listFiles() {
6969
const client = new AI21({ apiKey: process.env.AI21_API_KEY });
70-
const files = await client.files.list({ limit: 4 });
70+
const files = await client.library.files.list({ limit: 4 });
7171
console.log(`Listed files: ${files}`);
7272
}
7373

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { AI21 } from 'ai21';
2+
3+
const TIMEOUT = 20000;
4+
const INTERVAL = 1500;
5+
6+
async function main() {
7+
const client = new AI21({ apiKey: process.env.AI21_API_KEY });
8+
9+
const response = await client.beta.maestro.runs.createAndPoll(
10+
{
11+
input: 'Write a poem about the ocean',
12+
requirements: [
13+
{
14+
name: 'length requirement',
15+
description: 'The length of the poem should be less than 1000 characters',
16+
},
17+
{
18+
name: 'rhyme requirement',
19+
description: 'The poem should rhyme',
20+
},
21+
],
22+
include: ['requirements_result'],
23+
},
24+
{
25+
timeout: TIMEOUT,
26+
interval: INTERVAL,
27+
},
28+
);
29+
console.log(response);
30+
}
31+
32+
main().catch(console.error);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { AI21 } from 'ai21';
2+
3+
async function main() {
4+
const client = new AI21({ apiKey: process.env.AI21_API_KEY });
5+
6+
const { id } = await client.beta.maestro.runs.create({
7+
input: 'Hello, how are you? tell me a short story about a wizard',
8+
});
9+
10+
const response = await client.beta.maestro.runs.get(id);
11+
12+
console.log(response);
13+
}
14+
15+
main().catch(console.error);

0 commit comments

Comments
 (0)