From 9d32dc93495f63ee8fed705b1c287b0877b172b7 Mon Sep 17 00:00:00 2001 From: Tomas Pilar Date: Fri, 23 Feb 2024 12:39:00 +0100 Subject: [PATCH] chore(v2): update examples (#83) Signed-off-by: Tomas Pilar --- examples/assets/generate_input.jsonl | 4 -- examples/chat.ts | 59 ++++------------- examples/constants.ts | 2 + examples/file.ts | 45 +++++++------ examples/generate.ts | 96 ++++------------------------ examples/history.ts | 25 +++++--- examples/load_input.ts | 11 ---- examples/models.ts | 15 ++++- examples/tune.ts | 53 ++++++++------- package.json | 3 +- src/schema.ts | 9 ++- src/services/FileService.ts | 19 ++++++ yarn.lock | 17 +++++ 13 files changed, 155 insertions(+), 203 deletions(-) delete mode 100644 examples/assets/generate_input.jsonl create mode 100644 examples/constants.ts delete mode 100644 examples/load_input.ts diff --git a/examples/assets/generate_input.jsonl b/examples/assets/generate_input.jsonl deleted file mode 100644 index b41f4ff..0000000 --- a/examples/assets/generate_input.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -"How much is 1+1" -"How much is 2+2" -"How much is 3+3" -"How much is 4+4" \ No newline at end of file diff --git a/examples/chat.ts b/examples/chat.ts index 454d3f7..d6cbb68 100644 --- a/examples/chat.ts +++ b/examples/chat.ts @@ -1,18 +1,15 @@ import { Client } from '../src/index.js'; +import { CHAT_MODEL } from './constants.js'; + const client = new Client({ apiKey: process.env.GENAI_API_KEY, }); -const model_id = 'google/flan-ul2'; - { // Start a conversation - const { - conversation_id, - result: { generated_text: answer1 }, - } = await client.chat({ - model_id, + const { conversation_id, results: results1 } = await client.text.chat.create({ + model_id: CHAT_MODEL, messages: [ { role: 'system', @@ -24,14 +21,12 @@ const model_id = 'google/flan-ul2'; }, ], }); - console.log(answer1); + console.log(results1[0]); // Continue the conversation - const { - result: { generated_text: answer2 }, - } = await client.chat({ + const { results: results2 } = await client.text.chat.create({ conversation_id, - model_id, + model_id: CHAT_MODEL, messages: [ { role: 'user', @@ -39,44 +34,16 @@ const model_id = 'google/flan-ul2'; }, ], }); - console.log(answer2); + console.log(results2[0]); } { - // Chat inteface has the same promise, streaming and callback variants as generate interface - - // Promise - const data = await client.chat({ - model_id, + // Stream + const stream = await client.text.chat.create_stream({ + model_id: CHAT_MODEL, messages: [{ role: 'user', content: 'How are you?' }], }); - console.log(data.result.generated_text); - // Callback - client.chat( - { model_id, messages: [{ role: 'user', content: 'How are you?' }] }, - (err, data) => { - if (err) console.error(err); - else console.log(data.result.generated_text); - }, - ); - // Stream - for await (const chunk of client.chat( - { model_id, messages: [{ role: 'user', content: 'How are you?' }] }, - { stream: true }, - )) { - console.log(chunk.result.generated_text); + for await (const chunk of stream) { + console.log(chunk.results?.at(0)?.generated_text); } - // Streaming callbacks - client.chat( - { - model_id: 'google/flan-ul2', - messages: [{ role: 'user', content: 'How are you?' }], - }, - { stream: true }, - (err, data) => { - if (err) console.error(err); - else if (data) console.log(data.result.generated_text); - else console.log('EOS'); - }, - ); } diff --git a/examples/constants.ts b/examples/constants.ts new file mode 100644 index 0000000..7184bfc --- /dev/null +++ b/examples/constants.ts @@ -0,0 +1,2 @@ +export const MODEL = 'google/flan-ul2'; +export const CHAT_MODEL = 'meta-llama/llama-2-70b-chat'; diff --git a/examples/file.ts b/examples/file.ts index 6efa7d7..4f6e8d5 100644 --- a/examples/file.ts +++ b/examples/file.ts @@ -1,5 +1,5 @@ -import { createReadStream, createWriteStream } from 'node:fs'; -import { pipeline } from 'node:stream/promises'; +import { createReadStream } from 'node:fs'; +import { blob } from 'node:stream/consumers'; import { Client } from '../src/index.js'; @@ -9,36 +9,41 @@ const client = new Client({ { // List all files - for await (const file of client.files()) { - console.log(file); + let totalCount = Infinity; + const limit = 100; + for (let offset = 0; offset < totalCount; offset += limit) { + const { results, total_count } = await client.file.list({ + limit, + offset, + }); + for (const file of results) { + console.log(file); + } + totalCount = total_count; } } -{ - // List all files via callback interface - client.files((err, file) => { - if (err) console.error(err); - console.log(file); - }); -} - { // Upload a file - const newFile = await client.file({ + const { result } = await client.file.create({ purpose: 'tune', - filename: 'tune_input.jsonl', - file: createReadStream('examples/assets/tune_input.jsonl'), + file: { + name: 'tune_input.jsonl', + content: (await blob( + createReadStream('examples/assets/tune_input.jsonl'), + )) as any, + }, }); - console.log(newFile); + console.log(result); // Show details of a file - const file = await client.file({ id: newFile.id }); + const file = await client.file.retrieve({ id: result.id }); console.log(file); // Download the file's content - const content = await file.download(); - await pipeline(content, createWriteStream('/dev/null')); + const content = await client.file.read({ id: result.id }); + console.log(await content.text()); // Delete the file - await client.file({ id: file.id }, { delete: true }); + await client.file.delete({ id: result.id }); } diff --git a/examples/generate.ts b/examples/generate.ts index d9858de..f81d1c2 100644 --- a/examples/generate.ts +++ b/examples/generate.ts @@ -1,96 +1,28 @@ import { Client } from '../src/index.js'; -import { loadGenerateInput } from './load_input.js'; +import { MODEL } from './constants.js'; const client = new Client({ apiKey: process.env.GENAI_API_KEY, }); -const multipleInputs = loadGenerateInput(); -const singleInput = multipleInputs[0]; +const input = { model_id: MODEL, input: 'How are you?' }; -// { -// // Use with a single input to get a promise -// const output = await client.generate(singleInput); -// console.log(output); -// } - -// { -// // Or supply a callback -// client.generate(singleInput, (err, output) => { -// if (err) console.error(err); -// else console.log(output); -// }); -// } - -// { -// // Use with multiple inputs to get a promise -// const outputs = await Promise.all(client.generate(multipleInputs)); -// console.log(outputs); - -// // Or supply a callback which will be called for each output -// // Callback is guaranteed to be called in the order of respective inputs -// client.generate(multipleInputs, (err, output) => { -// if (err) console.error(err); -// else console.log(output); -// }); - -// // The method is optimized for sequential await, order the inputs accordingly -// for (const outputPromise of client.generate(multipleInputs)) { -// try { -// console.log(await outputPromise); -// } catch (err) { -// console.error(err); -// } -// } -// } - -// { -// // Streaming (callback style) -// client.generate( -// singleInput, -// { -// stream: true, -// }, -// (err, output) => { -// if (err) { -// console.error(err); -// } else if (output === null) { -// // END of stream -// } else { -// console.log(output.stop_reason); -// console.log(output.generated_token_count); -// console.log(output.input_token_count); -// console.log(output.generated_text); -// } -// }, -// ); -// } +{ + const output = await client.text.generation.create(input); + console.log(output); +} { // Streaming (async iterators) - const stream = client.generation_stream(singleInput); + const stream = await client.text.generation.create_stream(input); for await (const chunk of stream) { - console.log(chunk.stop_reason); - console.log(chunk.generated_token_count); - console.log(chunk.input_token_count); - console.log(chunk.generated_text); + const result = chunk.results?.at(0); + if (result) { + console.log(result.stop_reason); + console.log(result.generated_token_count); + console.log(result.input_token_count); + console.log(result.generated_text); + } } } - -{ - // Streaming (built-in stream methods) - const stream = client.generation_stream(singleInput); - stream.on('data', (chunk) => { - console.log(chunk.stop_reason); - console.log(chunk.generated_token_count); - console.log(chunk.input_token_count); - console.log(chunk.generated_text); - }); - stream.on('error', (err) => { - console.error('error has occurred', err); - }); - stream.on('close', () => { - console.info('end of stream'); - }); -} diff --git a/examples/history.ts b/examples/history.ts index f98b4f7..7abd8b2 100644 --- a/examples/history.ts +++ b/examples/history.ts @@ -1,23 +1,32 @@ import { Client } from '../src/index.js'; +import { CHAT_MODEL } from './constants.js'; + const client = new Client({ apiKey: process.env.GENAI_API_KEY, }); { // List historical success requests to the API - for await (const request of client.history({ - origin: 'API', - status: 'SUCCESS', - })) { + const { results } = await client.request.list({ + origin: 'api', + status: 'success', + }); + for (const request of results) { console.log(request); } } { - // List all requests from the past via callback interface - client.history((err, request) => { - if (err) console.error(err); - console.log(request); + // List all requests related to a chat conversation + const { conversation_id } = await client.text.chat.create({ + model_id: CHAT_MODEL, + messages: [{ role: 'user', content: 'How are you?' }], }); + const { results } = await client.request.chat({ + conversationId: conversation_id, + }); + for (const request of results) { + console.log(request); + } } diff --git a/examples/load_input.ts b/examples/load_input.ts deleted file mode 100644 index 10aa590..0000000 --- a/examples/load_input.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { readFileSync } from 'fs'; - -export const loadGenerateInput = () => - // Input files usually follow JSONL format - readFileSync('examples/assets/generate_input.jsonl', 'utf8') - .split('\n') - .map((line) => JSON.stringify(line)) - .map((input) => ({ - model_id: 'google/flan-ul2', - input, - })); diff --git a/examples/models.ts b/examples/models.ts index 21af2e7..6930b7f 100644 --- a/examples/models.ts +++ b/examples/models.ts @@ -1,8 +1,19 @@ import { Client } from '../src/index.js'; +import { MODEL } from './constants.js'; + const client = new Client({ apiKey: process.env.GENAI_API_KEY, }); -const models = await client.models({ limit: 100, offset: 0 }); -console.log(models); +{ + // List first hundred models + const { results } = await client.model.list({ limit: 100, offset: 0 }); + console.log(results); +} + +{ + // Retrieve info about a specific model + const { result } = await client.model.retrieve({ id: MODEL }); + console.log(result); +} diff --git a/examples/tune.ts b/examples/tune.ts index 769ebd1..30ca9d1 100644 --- a/examples/tune.ts +++ b/examples/tune.ts @@ -1,6 +1,3 @@ -import { createWriteStream } from 'node:fs'; -import { pipeline } from 'node:stream'; - import { Client } from '../src/index.js'; const client = new Client({ @@ -9,48 +6,48 @@ const client = new Client({ { // List all completed tunes - for await (const tune of client.tunes({ filters: { status: 'COMPLETED' } })) { - console.log(tune); + let totalCount = Infinity; + const limit = 100; + for (let offset = 0; offset < totalCount; offset += limit) { + const { results, total_count } = await client.tune.list({ + limit, + offset, + status: 'completed', + }); + for (const file of results) { + console.log(file); + } + totalCount = total_count; } } -{ - // List all completed tunes via callback interface - client.tunes({ filters: { status: 'COMPLETED' } }, (err, tune) => { - if (err) console.error(err); - console.log(tune); - }); -} - { // List available tune methods - const tuneMethods = await client.tuneMethods(); - console.log(tuneMethods); + const { results: tuneTypes } = await client.tune.types({}); + console.log(tuneTypes); // Create a tune - const newTune = await client.tune({ + const { result: createdTune } = await client.tune.create({ name: 'Awesome Tune', - method_id: tuneMethods[0].id, + tuning_type: 'prompt_tuning', model_id: 'google/flan-t5-xl', task_id: 'generation', training_file_ids: ['fileId'], }); - console.log(newTune); + console.log(createdTune); // Show details of the tune - const tune = await client.tune({ id: newTune.id }); - console.log(tune); + const { result: retrievedTune } = await client.tune.retrieve({ + id: createdTune.id, + }); + console.log(retrievedTune); // Download tune's assets when completed - if (tune.status === 'COMPLETED') { - const encoder = await tune.downloadAsset('encoder'); - const logs = await tune.downloadAsset('logs'); - await Promise.all([ - pipeline(encoder, createWriteStream('/dev/null')), - pipeline(logs, createWriteStream('/dev/null')), - ]); + if (retrievedTune.status === 'completed') { + const logs = await client.tune.read({ id: retrievedTune.id, type: 'logs' }); + console.log(await logs.text()); } // Delete the tune - await client.tune({ id: tune.id }, { delete: true }); + await client.tune.delete({ id: createdTune.id }); } diff --git a/package.json b/package.json index 5f1eb53..edd20b3 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "example:run": "ts-node -r dotenv-flow/config", "example:generate": "yarn run example:run examples/generate.ts", "example:tune": "yarn run example:run examples/tune.ts", - "example:prompt-template": "yarn run example:run examples/prompt-templates.ts", + "example:history": "yarn run example:run examples/history.ts", "example:file": "yarn run example:run examples/file.ts", "example:chat": "yarn run example:run examples/chat.ts", "example:models": "yarn run example:run examples/models.ts" @@ -74,6 +74,7 @@ "@commitlint/config-conventional": "^18.0.0", "@langchain/core": "^0.1.11", "@types/lodash": "^4.14.200", + "@types/node": "^20.11.19", "@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/parser": "^6.9.0", "@vitest/coverage-c8": "^0.31.2", diff --git a/src/schema.ts b/src/schema.ts index c7c428e..0a95d39 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -142,7 +142,7 @@ export type TuneServiceReadInput = ApiClientOptions< 'GET', '/v2/tunes/{id}/content/{type}' >['params']['path']; -export type TuneServiceReadOutput = Blob; // TODO proper derivation +export type TuneServiceReadOutput = Blob; // TODO Replace with proper derivation export type TuneServiceRetrieveInput = ApiClientOptions< 'GET', @@ -230,6 +230,13 @@ export type FileServiceDeleteOutput = OutputWrapper< ApiClientResponse<'DELETE', '/v2/files/{id}'>['data'] >; +export type FileServiceListInput = InputQueryWrapper< + ApiClientOptions<'GET', '/v2/files'>['params']['query'] +>; +export type FileServiceListOutput = OutputWrapper< + ApiClientResponse<'GET', '/v2/files'>['data'] +>; + // SystemPromptService export type SystemPromptServiceCreateInput = InputBodyWrapper< diff --git a/src/services/FileService.ts b/src/services/FileService.ts index b8bffd8..9d50c5d 100644 --- a/src/services/FileService.ts +++ b/src/services/FileService.ts @@ -5,6 +5,8 @@ import { FileServiceCreateOutput, FileServiceDeleteInput, FileServiceDeleteOutput, + FileServiceListInput, + FileServiceListOutput, FileServiceReadInput, FileServiceReadOutput, FileServiceRetrieveInput, @@ -88,4 +90,21 @@ export class FileService extends BaseService { }), ); } + + async list( + input: FileServiceListInput, + opts?: Options, + ): Promise { + return clientErrorWrapper( + this._client.GET('/v2/files', { + ...opts, + params: { + query: { + ...input, + version: '2023-12-15', + }, + }, + }), + ); + } } diff --git a/yarn.lock b/yarn.lock index 914ab89..979da9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -669,6 +669,7 @@ __metadata: "@commitlint/config-conventional": ^18.0.0 "@langchain/core": ^0.1.11 "@types/lodash": ^4.14.200 + "@types/node": ^20.11.19 "@typescript-eslint/eslint-plugin": ^6.9.0 "@typescript-eslint/parser": ^6.9.0 "@vitest/coverage-c8": ^0.31.2 @@ -1093,6 +1094,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.11.19": + version: 20.11.19 + resolution: "@types/node@npm:20.11.19" + dependencies: + undici-types: ~5.26.4 + checksum: 259d16643ba611ade617a8212e594a3ac014727457507389bbf7213971346ab052d870f1e6e2df0afd0876ecd7874f578bccb130be01e069263cfc7136ddc0c1 + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.0": version: 2.4.1 resolution: "@types/normalize-package-data@npm:2.4.1" @@ -6850,6 +6860,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + "undici@npm:^5.28.2": version: 5.28.2 resolution: "undici@npm:5.28.2"