paint-brush
Davinci é ruim em matemática: ajustando modelos ChatGPT com NodeJs e OpenAI v4por@timbushell
1,095 leituras
1,095 leituras

Davinci é ruim em matemática: ajustando modelos ChatGPT com NodeJs e OpenAI v4

por Tim Bushell9m2023/08/20
Read on Terminal Reader

Muito longo; Para ler

A API da OpenAI oferece uma gama de possibilidades, permitindo que os desenvolvedores interajam com modelos de linguagem avançados como GPT-3.5. Este artigo se aprofunda na criação de um conjunto de ferramentas especializado usando a biblioteca Node.js da OpenAI. Construiremos uma CLI (Command Line Interface) para interagir com a API, com foco em uma missão específica: ensinar o renomado modelo davinci a aprimorar suas habilidades matemáticas. A jornada envolve configurar o ambiente de desenvolvimento, criar um conjunto de dados de ajuste fino, treinar um novo modelo e observar os resultados. Ao seguir essas etapas, pretendemos demonstrar os recursos da API do OpenAI e as complexidades dos modelos de ajuste fino para tarefas específicas.
featured image - Davinci é ruim em matemática: ajustando modelos ChatGPT com NodeJs e OpenAI v4
Tim Bushell HackerNoon profile picture
0-item


Este artigo se concentra no uso da biblioteca Node.js da OpenAI para criar uma CLI que treina o modelo Davinci em matemática.

Casca de noz

  • "Scaffold" nossa biblioteca.
  • Escreva um conjunto de funções para agrupar as chamadas de API do OpenAI.
  • Crie uma CLI simples para chamar as funções.
  • Prove que o ChatGPT é (geralmente) bom em matemática.
  • Prove que Davinci é (geralmente) ruim em matemática.
  • Crie um conjunto de dados de ajuste fino simples para ensinar matemática a Davinci.
  • Carregar "conjunto de dados de ajuste fino simples".
  • Transforme um "conjunto de dados de ajuste fino simples" em um modelo de ajuste fino simples.
  • Provar nosso ajuste fino ensinou matemática a Davinci.


Andaime

 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

... pode ser simples, assim:

 { "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" }


A entrada "cli" nos scripts significa que podemos chamar npm run cli -- commandName [args] . Se você usar isso em vez do node bin/cli.js commandName [args] isso significa que você mantém o histórico do seu shell , mesmo que altere a estrutura do aplicativo posteriormente ou o nome de cli.js . Coisas simples agradam mentes simples e eu tenho uma mente simples.

.env

... deve ficar assim, mas com sua própria API_KEY:

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


Um conjunto de funções para envolver as chamadas de API do OpenAI.

Abra openAI.js e copie-o em:

 /** 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


Você notará que deixei todos os endpoints disponíveis na biblioteca do OpenAI neste arquivo, que deixo para você adicionar como um exercício para criar um módulo útil.


Uma CLI simples para chamar as funções

Abra bin/cli.js e cole isto:

 #!/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) }


Prove que o ChatGPT é (geralmente) bom em matemática

O ChatGPT não deve ter problemas para responder a quaisquer somas porque (geralmente) o ChatGPT é bom em matemática, o que podemos provar (e testar nossa CLI) fazendo o seguinte:


  1. Edite .env para dizer:
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="gpt-3.5-turbo"


  1. Execute o comando:
 npm run cli -- chatCompletionsCreate "12+4`.


Ver? Bom em matemática.


Posteriormente, quando for possível ajustar modelos de chatbot como "gpt-3.5-turbo", faremos o ajuste fino para que seja ruim em matemática.


A parte -- é necessária para garantir que os parâmetros sejam passados corretamente para o NPM. Não vou entrar no porquê porque não sei porquê. Você pode. Isso é bom. Deixe-me saber se você sabe. Tudo o que sei é que você tem que fazer para que funcione e isso é fato.


NB: É assim que você faria a mesma coisa fora de nossa 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")


Prove que Davinci é (geralmente) ruim em matemática.

  1. Edite .env para dizer:
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="davinci"


  1. Execute o comando
 npm run cli -- completionsCreate "12+4`.


NB: É assim que você faria a mesma coisa fora de nossa 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")


Ensinar matemática DaVinci

De acordo com a documentação, o ChatGPT de "ajuste fino" de modelos requer grandes conjuntos de dados, pelo menos 200. O ponto principal de davinci-é-ruim em matemática é aprender como criar, fazer upload e usar conjuntos de dados de "ajuste fino" e criar um atalho para o trabalho realmente CONSTRUINDO um conjunto de dados útil em vez de bobo.


E como somos codificadores, podemos codificar um atalho como este:


Abra goodAtMathsDatasetBuilder.js e cole isto:

 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.")


Tudo o que estamos fazendo aqui é construir um conjunto de dados que "afina" os modelos do ChatGPT para serem bons em matemática, e tudo o que precisamos é de muitas somas com "conclusões" corretas.


Execute este script assim:

 node goodAtMathsDatasetBuilder.js`


Abra good-at-maths-fine-tuning-dataset.jsonl e deve ficar assim:

 {"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"}

... com mais somas certas.


Carregar "conjunto de dados de ajuste fino simples".

Para carregar o conjunto de dados, execute

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


NB: É assim que você faria a mesma coisa fora de nossa 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")

Anote o id do arquivo, por exemplo, "file-th15IsM1ne3G3tY0urOwn1Yo"


Transforme um "conjunto de dados de ajuste fino simples" em um modelo de ajuste fino simples

Para criar um modelo "Fine Tuned" usando esta chamada de conjunto de dados:

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


NB: É assim que você faria a mesma coisa fora de nossa 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")


Demora um pouco para ensinar matemática a Davinci porque, para ser honesto, DaVinci é muito ruim em matemática!


Você pode correr:

 npm run cli -- fineTunesList

Aguarde até que status: 'pending' mude para o status: 'suceeded'


Provar nosso ajuste fino ensinou matemática a davinci

Quando status: 'suceeded' , encontre o nome fine_tuned_model .


  1. Edite .env para dizer:
 OPENAI_API_KEY="sk-d0ntY0uD4reUs3MyK3yG3tY0urOwnFr0mOp0n41W36s1t3Yo" OPENAI_MODEL="<fine_tuned_model name>"


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


É uma resposta piegas, mas você deve ver que Davinci é melhor em matemática.


O que aprendemos

  1. Como usar a biblioteca V4 do OpenAI.
  2. Como criar um conjunto de dados "Fine Tuning" e carregá-lo.
  3. Como gerar um novo modelo OpenAI.
  4. Como escrever uma CLI ruim.


Este projeto pode ser encontrado aqui:

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