paint-brush
Davinci は数学が苦手です: NodeJs と OpenAI v4 を使用した ChatGPT モデルの微調整@timbushell
1,095 測定値
1,095 測定値

Davinci は数学が苦手です: NodeJs と OpenAI v4 を使用した ChatGPT モデルの微調整

Tim Bushell9m2023/08/20
Read on Terminal Reader

長すぎる; 読むには

OpenAI の API はさまざまな可能性を提供し、開発者が GPT-3.5 などの高度な言語モデルを操作できるようにします。この記事では、OpenAI の Node.js ライブラリを使用した特殊なツールセットの作成について詳しく説明します。私たちは、有名な davinci モデルを教えて数学的スキルを向上させるという特定の使命に焦点を当てて、API と対話するための CLI (コマンド ライン インターフェイス) を構築します。この作業には、開発環境のセットアップ、微調整データセットの作成、新しいモデルのトレーニング、および結果の観察が含まれます。これらの手順に従うことで、OpenAI の API の機能と、特定のタスク向けの微調整モデルの複雑さの両方を実証することを目的としています。
featured image - Davinci は数学が苦手です: NodeJs と OpenAI v4 を使用した ChatGPT モデルの微調整
Tim Bushell HackerNoon profile picture
0-item


この記事では、OpenAI のNode.jsライブラリを使用して、数学で Davinci モデルをトレーニングするCLIを構築することに焦点を当てています。

一言で言えば

  • 私たちの図書館を「足場」にします。
  • OpenAI の API 呼び出しをラップする一連の関数を作成します。
  • 関数を呼び出すための単純な CLI を構築します。
  • ChatGPT が (通常は) 数学に優れていることを証明してください。
  • ダヴィンチが(通常)数学が苦手であることを証明してください。
  • Davinci に数学を教えるためのシンプルな微調整データセットを構築します。
  • 「簡易微調整データセット」をアップロードします。
  • 「単純な微調整データセット」を単純な微調整モデルに変換します。
  • 私たちの微調整を証明することで、ダヴィンチに数学を教えました。


足場

cd ~/Dev/YourRootFolderForPersonalStuff/ mdkir davinci-is-bad-at-maths cd davinci-is-bad-at-maths npm i dotenv openai npm i prettier -D touch .env touch goodAtMathsDatasetBuilder.js touch openAI.js mkdir bin touch bin/cli.js


package.json

...次のように簡単にできます。

 { "description": "Experiments using OpenAI's API NodeJs v4 library", "name": "davinci-is-bad-at-maths", "private": true, "bin": "./bin/cli.js", "dependencies": { "dotenv": "^16.3.1", "openai": "^4.0.0" }, "devDependencies": { "prettier": "^3.0.2" }, "main": "openAI.js", "scripts": { "cli": "node bin/cli.js", "prettier": "prettier --list-different --write \"**/*.{css,html,js,json,md,mjs,scss,ts,yaml}\"" }, "type": "module" }


スクリプト内の「cli」エントリはnpm run cli -- commandName [args]を呼び出すことができることを意味します。これをnode bin/cli.js commandName [args]の代わりに使用すると、後でアプリ構造やcli.jsの名前を変更した場合でも、シェルの履歴が維持されることになります。シンプルなものはシンプルな心を喜ばせます、そして私はシンプルな心を持っています。

.env

... 次のようになりますが、独自の API_KEY を使用します。

 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="davinci"


OpenAI の API 呼び出しをラップするための関数のセット。

openAI.jsを開いて、これを次の場所にコピーします。

 /** A not-robust OpenAI v4 CLI; a playground for OpenAI v4 API calls; a utility for working with a OpenAI model who is really really, like - I mean - really bad at maths. * @usage * >> import commandHub from "openAI.js" * >> const [, , command, ...args] = process.argv * >> const commandFunc = commandHub[command] * >> commandFunc(...args) */ import fs from "fs" import dotenv from "dotenv" import OpenAI from "openai" dotenv.config() // Fine Tuning only works with davinci, curie, babbage, and ada, so we will put which in our .env file so that we can call the same one consistently. const model = process.env.OPENAI_MODEL // Instantiate the API object. const apiKey = process.env.OPENAI_API_KEY const openai = new OpenAI({ apiKey }) /** openai.chat.completions.create * @usage * >> npm run cli -- chatCompletionsCreate "2+8=?" * @param {String} chatPrompt your sum to an assistent who is (usually) good at maths */ export const chatCompletionsCreate = async chatPrompt => { const res = await openai.chat.completions.create({ messages: [ { role: "system", content: "You are good at maths." }, { role: "user", content: chatPrompt }, ], model: model, }) console.log("chatCompletionsCreate", res.choices) } /** openai.completions.create * @tutorial * Normally we would use `chatCompletionsCreate` but for Fine Tuned models we must use base models and therefore `completionsCreate`. * @usage * >> npm run cli -- completionsCreate "2+8=?" * @param {String} chatPrompt your sum to an assistent who is (usually) good at maths */ export const completionsCreate = async chatPrompt => { const res = await openai.completions.create({ model: model, prompt: chatPrompt, temperature: 0, }) console.log("completionsCreate", res) } /** openai.files.create and output to `openai.files.create.json` * @usage * >> npm run cli -- filesCreate bad-at-maths-fine-tuning-dataset.jsonl * @param {String} filePath of JSONLD file to upload. */ export const filesCreate = async filePath => { const res = await openai.files.create({ file: fs.createReadStream(filePath), purpose: "fine-tune", }) console.log("filesCreate", res) fs.writeFileSync( "openai.files.create.json", JSON.stringify(res, null, 2), "utf-8", ) } // openai.files.del /** openai.files.list and output to `openai.files.list.json` * @usage * >> npm run cli -- filesList */ export const filesList = async () => { const res = await openai.files.list() console.log("filesList", res) fs.writeFileSync( "openai.files.list.json", JSON.stringify(res, null, 2), "utf-8", ) } // openai.files.retrieve // openai.files.retrieveContent /** openai.fineTunes.create * @usage * >> npm run cli -- fineTunesCreate "bad-at-maths-fine-tuning-dataset.jsonl" "is-good-at-maths" * @param {String} fileId of previously uploaded file where `purpose: "fine-tune"`. * @param {String} suffix to add to the resulting model name for easily id later. */ export const fineTunesCreate = async (fileId, suffix) => { const res = await openai.fineTunes.create({ training_file: fileId, suffix: suffix, model: model, }) console.log("fineTunesCreate", res) fs.writeFileSync( "openai.fineTunes.create.json", JSON.stringify(res, null, 2), "utf-8", ) } /** openai.fineTunes.list * @usage * >> npm run cli -- fineTunesList */ export const fineTunesList = async () => { const res = await openai.fineTunes.list() console.log("fineTunesList", res) fs.writeFileSync( "openai.fineTunes.list.json", JSON.stringify(res, null, 2), "utf-8", ) } // openai.fineTunes.cancel // openai.fineTunes.retrieve // openai.fineTunes.listEvents // openai.models.del // openai.models.list // openai.models.del // openai.images.generate // openai.images.edit // openai.images.createVariation // openai.audio.transcriptions.create // openai.audio.translations.create // openai.edits.create // openai.embeddings.create // openai.moderations.create // A command hub. const commandHub = { chatCompletionsCreate, completionsCreate, filesCreate, filesList, fineTunesCreate, fineTunesList, } export default commandHub


このファイルには、 OpenAIのライブラリで使用可能なエンドポイントがすべて残されていることがわかります。これは、有用なモジュールを作成するための演習として追加できるようにしておきます。


関数を呼び出すためのシンプルな CLI

bin/cli.js を開いてこれを貼り付けます。

 #!/usr/bin/env node /** A not-very-robust OpenAI v4 CLI; a playground for OpenAI v4 API calls; a utility for working with a OpenAI model who is really really, like - I mean - really bad at maths. * @usage with "cli" in "scripts" (don't forget the "--"). * >> npm cli -- commandName [arg1 arg2 ...arg(n)] */ import commandHub from "../openAI.js" const [, , command, ...args] = process.argv // Call the requested command. Not a robust CLI but it gets the job done! if (!commandHub.hasOwnProperty(command)) { throw "No such command as `" + command + "`" } else { const commandFunc = commandHub[command] commandFunc(...args) }


ChatGPT が (通常は) 数学に優れていることを証明する

(通常) ChatGPT は数学に優れているため、ChatGPT は合計を問題なく答えることができます。これは、次の手順で証明 (および CLI のテスト) できます。


  1. .env を次のように編集します。
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="gpt-3.5-turbo"


  1. 次のコマンドを実行します。
 npm run cli -- chatCompletionsCreate "12+4`.


見る?数学が得意。


後日、「gpt-3.5-turbo」のようなチャットボットモデルのFine Tuneが可能になったら、数学が苦手なチャットボットモデルをFine Tuningする予定です。


--部分は、パラメーターが NPM に正しく渡されることを保証するために必要です。理由は分からないので詳しくは書きません。そうかもしれません。それは良い。知っていたら教えてください。私が知っているのは、それを機能させるためにはそうする必要があるということだけであり、それは事実です。


注意: これは、CLI の外部で同じことを行う方法です。

 import dotenv from "dotenv" import OpenAI from "openai" const apiKey = process.env.OPENAI_API_KEY const model = process.env.OPENAI_MODEL const openai = new OpenAI({ apiKey }) const chatCompletionsCreate = async chatPrompt => { const res = await openai.chat.completions.create({ messages: [ { role: "system", content: "You are good at maths." }, { role: "user", content: chatPrompt }, ], model: model, }) console.log("chatCompletionsCreate", res.choices) } chatCompletionsCreate("12+4")


ダヴィンチが(通常)数学が苦手であることを証明してください。

  1. .env を次のように編集します。
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="davinci"


  1. コマンドを実行します
npm run cli -- completionsCreate "12+4`.


注意: これは、CLI の外部で同じことを行う方法です。

 import fs from "fs" import dotenv from "dotenv" import OpenAI from "openai" const apiKey = process.env.OPENAI_API_KEY const openai = new OpenAI({ apiKey }) const completionsCreate = async chatPrompt => { const res = await openai.completions.create({ model: model, prompt: chatPrompt, temperature: 0, }) console.log("completionsCreate", res) } completionsCreate("12+4")


ダヴィンチに数学を教える

ドキュメントによると、モデルの「微調整」ChatGPT には、少なくとも 200 の大きなデータセットが必要です。davinci-is-bad-at-mathsの要点は、「微調整」データセットを作成、アップロード、使用し、ショートカットを作成する方法を学ぶことです。実際に、愚かなデータセットではなく有用なデータセットを構築しています


私たちはプログラマなので、次のようなショートカットをコーディングできます。


goodAtMathsDatasetBuilder.jsを開いて、これを貼り付けます。

 import fs from "fs" // Don't waste bandwidth with duplicates in the fine-training data. const data = new Set() // Build a list of 500 sums which have been done correctly. while (data.size < 500) { // Two random integers. let x = Math.round(Math.random() * 1000) let y = Math.round(Math.random() * 1000) let result = x + y data.add( JSON.stringify({ prompt: `${x}+${y}\n\n###\n\n`, completion: `${x}+${y}=${result} END`, }), ) } fs.writeFileSync( "good-at-maths-fine-tuning-dataset.jsonl", [...data].join("\n"), "utf-8", ) console.log("JSONL fine-tuning dataset has been created.")


ここで私たちが行っていることは、ChatGPT が数学に優れるようにモデル化するデータセットを構築することだけであり、必要なのは正しい「補完」を含む大量の合計だけです。


このスクリプトを次のように実行します。

 node goodAtMathsDatasetBuilder.js`


good-at-maths-fine-tuning-dataset.jsonlを開くと、次のようになります。

 {"prompt":"487+63\n\n###\n\n","completion":"487+63=550 END"} {"prompt":"842+624\n\n###\n\n","completion":"842+624=1466 END"} {"prompt":"58+783\n\n###\n\n","completion":"58+783=841 END"} {"prompt":"96+478\n\n###\n\n","completion":"96+478=574 END"} {"prompt":"69+401\n\n###\n\n","completion":"69+401=470 END"}

...さらに正しい金額が表示されます。


「簡易微調整データセット」をアップロードします。

データセットをアップロードするには、次のコマンドを実行します。

 npm run cli -- filesCreate good-at-maths-fine-tuning-dataset.jsonl


注意: これは、CLI の外部で同じことを行う方法です。

 import fs from "fs" import dotenv from "dotenv" import OpenAI from "openai" const apiKey = process.env.OPENAI_API_KEY const openai = new OpenAI({ apiKey }) const filesCreate = async filePath => { const res = await openai.files.create({ file: fs.createReadStream(filePath), purpose: "fine-tune", }) console.log("filesCreate", res) fs.writeFileSync( "openai.files.create.json", JSON.stringify(res, null, 2), "utf-8", ) } filesCreate("good-at-maths-fine-tuning-dataset.jsonl")

ファイルidをメモします (例: "file-th15IsM1ne3G3tY0urOwn1Yo")。


「単純な微調整データセット」を単純な微調整モデルに変換する

このデータセットを使用して「微調整された」モデルを作成するには、次のように呼び出します。

 npm run cli -- fineTunesCreate "file-th15IsM1ne3G3tY0urOwn1Yo"`"is-good-at-maths"


注意: これは、CLI の外部で同じことを行う方法です。

 import fs from "fs" import dotenv from "dotenv" import OpenAI from "openai" const apiKey = process.env.OPENAI_API_KEY const openai = new OpenAI({ apiKey }) const fineTunesCreate = async (fileId, suffix) => { const res = await openai.fineTunes.create({ training_file: fileId, suffix: suffix, model: model, }) console.log("fineTunesCreate", res) fs.writeFileSync( "openai.fineTunes.create.json", JSON.stringify(res, null, 2), "utf-8", ) } fineTunesCreate("file-th15IsM1ne3G3tY0urOwn1Yo")


正直に言うと、ダヴィンチは数学が本当に苦手なので、ダヴィンチに数学を教えるには時間がかかります。


以下を実行できます。

 npm run cli -- fineTunesList

status: 'pending'status: 'suceeded'に変わるまで待ちます。


微調整を証明することでダヴィンチに数学を教えた

status: 'suceeded'の場合、 fine_tuned_model名を見つけます。


  1. .env を次のように編集します。
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="<fine_tuned_model name>"


  1. 走る:
 npm run cli -- completionsCreate "12+4`.


ありきたりな返答ですが、ダヴィンチの方が数学が得意であることがわかるはずです。


私たちが学んだこと

  1. OpenAIのV4ライブラリの使い方。
  2. 「微調整」データセットを作成してアップロードする方法。
  3. 新しい OpenAI モデルを生成する方法。
  4. くだらない CLI の書き方。


このプロジェクトは次の場所にあります。

https://gitlab.com/timitee/davinci-is-bad-at-maths/edit#js-general-project-settings