paint-brush
Davinci es malo en matemáticas: ajuste fino de los modelos de ChatGPT con NodeJs y OpenAI v4por@timbushell
1,095 lecturas
1,095 lecturas

Davinci es malo en matemáticas: ajuste fino de los modelos de ChatGPT con NodeJs y OpenAI v4

por Tim Bushell9m2023/08/20
Read on Terminal Reader

Demasiado Largo; Para Leer

La API de OpenAI ofrece una variedad de posibilidades, lo que permite a los desarrolladores interactuar con modelos de lenguaje avanzados como GPT-3.5. Este artículo profundiza en la creación de un conjunto de herramientas especializadas utilizando la biblioteca Node.js de OpenAI. Construiremos una CLI (Command Line Interface) para interactuar con la API, enfocándonos en una misión particular: enseñar el renombrado modelo davinci para mejorar sus habilidades matemáticas. El viaje implica configurar el entorno de desarrollo, crear un conjunto de datos de ajuste fino, entrenar un nuevo modelo y observar los resultados. Al seguir estos pasos, nuestro objetivo es demostrar tanto las capacidades de la API de OpenAI como las complejidades de ajustar modelos para tareas específicas.
featured image - Davinci es malo en matemáticas: ajuste fino de los modelos de ChatGPT con NodeJs y OpenAI v4
Tim Bushell HackerNoon profile picture
0-item


Este artículo se centra en el uso de la biblioteca Node.js de OpenAI para crear una CLI que entrene el modelo Davinci en matemáticas.

Cáscara de nuez

  • "Andamio" nuestra biblioteca.
  • Escriba un conjunto de funciones para envolver las llamadas a la API de OpenAI.
  • Cree una CLI simple para llamar a las funciones.
  • Demuestra que ChatGPT es (generalmente) bueno en matemáticas.
  • Demuestra que Davinci es (generalmente) malo en matemáticas.
  • Cree un conjunto de datos de ajuste fino simple para enseñar matemáticas Davinci.
  • Cargue un "conjunto de datos de ajuste fino simple".
  • Convierta un "conjunto de datos de ajuste fino simple" en un modelo de ajuste fino simple.
  • Demostrando nuestra puesta a punto enseñó matemáticas Davinci.


Andamio

 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

... puede ser simple, así:

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


La entrada "cli" en los scripts significa que podemos llamar npm run cli -- commandName [args] . Si usa esto en lugar de node bin/cli.js commandName [args] significa que mantiene el historial de su shell incluso si cambia la estructura de la aplicación más tarde, o el nombre de cli.js Las cosas simples agradan a las mentes simples y yo tengo una mente simple.

.env

... debe verse así pero con su propia API_KEY:

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


Un conjunto de funciones para envolver las llamadas a la API de OpenAI.

Abra openAI.js y copie esto en:

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


Notará que he dejado todos los puntos finales disponibles en la biblioteca de OpenAI en este archivo, que dejo para que lo agregue como ejercicio para crear un módulo útil.


Una CLI simple para llamar a las funciones.

Abra bin/cli.js y pegue esto:

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


Demuestra que ChatGPT es (generalmente) bueno en matemáticas

ChatGPT no debería tener problemas para responder sumas porque (generalmente) ChatGPT es bueno en matemáticas, lo cual podemos probar (y probar nuestra CLI) haciendo lo siguiente:


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


  1. Ejecute el comando:
 npm run cli -- chatCompletionsCreate "12+4`.


¿Ver? Bueno en matemáticas.


En una fecha posterior, cuando sea posible ajustar modelos de chatbot como "gpt-3.5-turbo", lo haremos para que sea malo en matemáticas.


La parte -- es necesaria para garantizar que los parámetros se pasen correctamente a NPM. No voy a entrar en por qué porque no sé por qué. Podrías. Eso es bueno. Avísame si lo sabes. Todo lo que sé es que tienes que hacerlo para que funcione y eso es un hecho.


NB: así es como haría lo mismo fuera de nuestra 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")


Demuestra que Davinci es (generalmente) malo en matemáticas.

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


  1. Ejecute el comando
 npm run cli -- completionsCreate "12+4`.


NB: así es como haría lo mismo fuera de nuestra 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")


Enseñando matemáticas DaVinci

Según la documentación, "Ajuste fino" ChatGPT de modelos requiere grandes conjuntos de datos, al menos 200. El objetivo de davinci-es-malo-en-matemáticas es aprender a crear, cargar y usar conjuntos de datos de "Ajuste fino" y atajar el trabajar en realidad CONSTRUYENDO un conjunto de datos útil en lugar de tonto.


Y como somos codificadores, podemos codificar un atajo como este:


Abra goodAtMathsDatasetBuilder.js y pegue esto:

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


Todo lo que estamos haciendo aquí es crear un conjunto de datos que los modelos de ChatGPT "afinan" para que sean buenos en matemáticas, y todo lo que necesitamos son muchas sumas con "completaciones" que sean correctas.


Ejecute este script de esta manera:

 node goodAtMathsDatasetBuilder.js`


Abra good-at-maths-fine-tuning-dataset.jsonl y debería verse así:

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

... con más sumas que son correctas.


Cargue un "conjunto de datos de ajuste fino simple".

Para cargar el conjunto de datos, ejecute

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


NB: así es como haría lo mismo fuera de nuestra 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")

Tome nota de la id del archivo, por ejemplo, "file-th15IsM1ne3G3tY0urOwn1Yo"


Convierta un "conjunto de datos de ajuste fino simple" en un modelo de ajuste fino simple

Para crear un modelo "afinado" con esta llamada de conjunto de datos:

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


NB: así es como haría lo mismo fuera de nuestra 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")


Lleva un tiempo enseñarle matemáticas a DaVinci porque, para ser honesto, ¡DaVinci es muy malo en matemáticas!


Tu puedes correr:

 npm run cli -- fineTunesList

Espere hasta que status: 'pending' cambie al status: 'suceeded'


Demostrando nuestro ajuste fino enseñó matemáticas davinci

Cuando status: 'suceeded' , busque el nombre del fine_tuned_model .


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


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


Es una respuesta cursi, pero deberías ver que Davinci es mejor en matemáticas.


lo que aprendimos

  1. Cómo usar la biblioteca V4 de OpenAI.
  2. Cómo crear un conjunto de datos de "ajuste fino" y cargarlo.
  3. Cómo generar un nuevo modelo OpenAI.
  4. Cómo escribir un CLI de mierda.


Este proyecto se puede encontrar aquí:

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