From 6a6c4b7a508181e0e5e9de0021f40a89cb615634 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Sat, 22 Apr 2023 15:07:22 +0800 Subject: [PATCH] Implement example CLI app Use basic chat implementation. --- examples/cli/package.json | 17 +++++ examples/cli/src/app.ts | 10 +-- examples/cli/src/index.ts | 138 +++++++++++++++++----------------- package.json | 6 +- src/platforms/openai/index.ts | 2 + 5 files changed, 96 insertions(+), 77 deletions(-) diff --git a/examples/cli/package.json b/examples/cli/package.json index 55a4429..9e01479 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -53,5 +53,22 @@ "esbuild-plugin-wasm": "^1.0.0", "inquirer": "^9.1.5", "yargs": "^17.7.1" + }, + "types": "./dist/types/index.d.ts", + "main": "./dist/cjs/production/index.js", + "module": "./dist/esm/production/index.js", + "exports": { + ".": { + "development": { + "require": "./dist/cjs/development/index.js", + "import": "./dist/esm/development/index.js" + }, + "require": "./dist/cjs/production/index.js", + "import": "./dist/esm/production/index.js", + "types": "./dist/types/index.d.ts" + } + }, + "typesVersions": { + "*": {} } } diff --git a/examples/cli/src/app.ts b/examples/cli/src/app.ts index 6f15e5b..5800b92 100644 --- a/examples/cli/src/app.ts +++ b/examples/cli/src/app.ts @@ -1,4 +1,4 @@ -import { createAiClient, OpenAi } from '@modal-sh/mio-ai'; +import { OpenAi, createAiClient } from '@modal-sh/mio-ai'; export interface CreateOpenAiClientParams { apiKey: string; @@ -6,13 +6,13 @@ export interface CreateOpenAiClientParams { apiVersion?: OpenAi.ApiVersion; } -export const createOpenAiClient = (params: CreateOpenAiClientParams) => { - return createAiClient({ +export const createOpenAiClient = (params: CreateOpenAiClientParams) => ( + createAiClient({ platform: OpenAi.PLATFORM_ID, platformConfiguration: { apiKey: params.apiKey, organizationId: params.organizationId, apiVersion: params.apiVersion ?? OpenAi.ApiVersion.V1, }, - }); -}; + }) +); diff --git a/examples/cli/src/index.ts b/examples/cli/src/index.ts index e051cf8..0544cdc 100644 --- a/examples/cli/src/index.ts +++ b/examples/cli/src/index.ts @@ -1,90 +1,90 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import inquirer from 'inquirer'; import { createOpenAiClient } from './app'; -import { OpenAi } from '@modal-sh/mio-ai'; +import { OpenAi, PlatformEventEmitter } from '@modal-sh/mio-ai'; export type Argv = Record; -const main = (argv: Argv) => new Promise((resolve) => { - const aiClient = createOpenAiClient({ - apiKey: process.env.OPENAI_API_KEY as string, - organizationId: process.env.OPENAI_ORGANIZATION_ID as string, - apiVersion: OpenAi.ApiVersion.V1, - }); - let result: Partial | undefined; - let done = false; - +const receiveData = (aiClient: PlatformEventEmitter, theContent: string, argv: Record) => new Promise((r2, rj) => { + let countTokens: number; aiClient.on('data', (d) => { - d.choices.forEach((c) => { - if (!result) { - result = { - id: d.id, - object: OpenAi.ChatCompletionDataEventObjectType.CHAT_COMPLETION, - created: d.created, - model: d.model, - }; - } - - if (!Array.isArray(result?.choices)) { - result.choices = []; - } - - if (!result.choices[c.index]) { - result.choices[c.index] = { - message: { content: '' }, - index: c.index, - finish_reason: c.finish_reason, - }; - } - - if (result.choices[c.index].message) { - if (c.delta.role) { - (result.choices[c.index].message as Record).role = c.delta.role; - } - - if (c.delta.content) { - (result.choices[c.index].message as Record) - .content += c.delta.content; - } - } + if (d.choices?.[0]?.delta?.role) { + process.stdout.write(`${d.choices[0].delta.role}: `); + } - if (c.finish_reason) { - result.choices[c.index].finish_reason = c.finish_reason; - } - }); + if (d.choices?.[0]?.delta?.content) { + countTokens += 1; + process.stdout.write(d.choices[0].delta.content); + } }); aiClient.on('end', () => { - // resolve?.(result); + process.stdout.write('\n\n'); + process.stdout.write(`info: ${countTokens} completion tokens.\n\n`); + // TODO count tokens + r2(); }); aiClient.on('error', (error: Error) => { - done = true; - resolve(-1); + process.stderr.write(error.message); + process.stderr.write('\n'); + rj(error); + }); + + countTokens = 0; + aiClient.createChatCompletion({ + model: OpenAi.ChatCompletionModel.GPT_3_5_TURBO, + messages: theContent, + temperature: argv.temperature as number, + maxTokens: argv.maxTokens as number, + topP: argv.topP as number, }); +}); + +const main = (argv: Argv) => new Promise(async (resolve) => { + let done = false; + let resolveResult = 0; - inquirer.prompt([ - { - type: 'input', - message: 'Type your inquiry.', - }, - ]) - .then((answers) => { - console.log(answers); - // aiClient.createChatCompletion({ - // model: OpenAi.ChatCompletionModel.GPT_3_5_TURBO, - // messages: { - // role: OpenAi.MessageRole.USER, - // content: answers[0] as string, - // }, - // }); - }) - .catch(() => { - resolve(-1); + process.stdout.write('Welcome to mio-ai CLI!\n\n'); + + process.stdout.write('This is a simple example of how to use mio-ai.\n'); + process.stdout.write('You can send messages to the OpenAI API.\n'); + process.stdout.write('You can also send empty messages to exit.\n'); + process.stdout.write('Alternatively, you can press Ctrl+C anytime to exit.\n\n'); + do { + process.stdout.write('---\n\n'); + const aiClient = createOpenAiClient({ + apiKey: process.env.OPENAI_API_KEY as string, + organizationId: process.env.OPENAI_ORGANIZATION_ID as string, + apiVersion: OpenAi.ApiVersion.V1, }); + const { createPromptModule } = await import('inquirer'); + const prompt = createPromptModule(); + let content: string; + try { + const answers = await prompt([ + { + type: 'input', + name: 'content', + prefix: '', + message: `${OpenAi.MessageRole.USER}:`, + }, + ]); + content = answers.content; + if (content.trim().length < 1) { + done = true; + break; + } + process.stdout.write('\n'); + await receiveData(aiClient, content, argv); + } catch { + resolveResult = -1; + done = true; + } + } while (!done); - resolve(0); + process.stdout.write('Bye!\n'); + resolve(resolveResult); }); main(yargs(hideBin(process.argv)).argv as unknown as Argv) diff --git a/package.json b/package.json index 9e79b9e..232d6ef 100644 --- a/package.json +++ b/package.json @@ -36,12 +36,12 @@ "private": false, "description": "Many-in-one AI client.", "repository": { - "url": "https://code.modal.sh/modal-soft/openai-utils", + "url": "https://code.modal.sh/modal-soft/mio-ai", "type": "git" }, - "homepage": "https://code.modal.sh/modal-soft/openai-utils", + "homepage": "https://code.modal.sh/modal-soft/mio-ai", "bugs": { - "url": "https://code.modal.sh/modal-soft/openai-utils/issues" + "url": "https://code.modal.sh/modal-soft/mio-ai/issues" }, "author": "TheoryOfNekomata ", "publishConfig": { diff --git a/src/platforms/openai/index.ts b/src/platforms/openai/index.ts index b35d621..63dc4a5 100644 --- a/src/platforms/openai/index.ts +++ b/src/platforms/openai/index.ts @@ -3,7 +3,9 @@ import { Configuration } from './common'; export * from './chat'; export * from './models'; export * from './common'; +// FIXME wasm module imports don't work with commojs export * from './usage'; + export { PlatformEventEmitter, PlatformEventEmitterImpl } from './events'; export { ChatCompletion,