Spaces:
Running
Running
| // IMPORT LIBRARIES TOOLS | |
| import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.10.1'; | |
| // skip local model check | |
| env.allowLocalModels = false; | |
| // GLOBAL VARIABLES | |
| var PREPROMPT = `Please continue the story, and fill any [MASK] with your own words:` | |
| // let PREPROMPT = `Please complete the phrase and fill in any [MASK]: ` | |
| var PROMPT_INPUT = `The [BLANK] has a job as a [MASK] but...` // a field for writing or changing a text value | |
| var pField // an html element for the prompt | |
| var outText // an html element for the results | |
| var blanksArray = [] | |
| // a list for all the variable inputs, e.g. ["woman", "man", "non-binary person"] | |
| // RUN TEXT-GEN MODEL | |
| async function textGenTask(pre, prompt, blanks){ | |
| console.log('text-gen task initiated') | |
| // Create concatenated prompt array including preprompt and all variable prompts | |
| let promptArray = [] | |
| promptArray.push(pre) // add preprompt to the list of prompts | |
| // fill in blanks from our sample prompt and make new prompts using our variable list 'blanksArray' | |
| blanks.forEach(b => { | |
| console.log(b.value()) | |
| let p = prompt.replace('[BLANK]', b.value()) // replace the string segment with an item from the blanksArray | |
| promptArray.push(p) // add the new prompt to the list we created | |
| }) | |
| // create combined fill prompt | |
| let INPUT = promptArray.toString() | |
| console.log(INPUT) | |
| // let INPUT = pre + prompt // simple concatenated input | |
| // let INPUT = prompt // basic prompt input | |
| // PICK MODEL | |
| let MODEL = 'Xenova/flan-alpaca-large' | |
| // MODELS LIST | |
| // - Xenova/bloom-560m | |
| // - Xenova/distilgpt2 | |
| // - Xenova/LaMini-Cerebras-256M | |
| // - Xenova/gpt-neo-125M // not working well | |
| // - Xenova/llama2.c-stories15M // only fairytails | |
| // - webml/TinyLlama-1.1B-Chat-v1.0 | |
| // - Xenova/TinyLlama-1.1B-Chat-v1.0 | |
| // - Xenova/flan-alpaca-large //text2text | |
| // const pipe = await pipeline('text-generation', MODEL) //different task type, also for text generation | |
| const pipe = await pipeline('text2text-generation', MODEL) | |
| var hyperparameters = { max_new_tokens: 60, top_k: 90, repetition_penalty: 1.5 } | |
| // setting hyperparameters | |
| // max_new_tokens: 256, top_k: 50, temperature: 0.7, do_sample: true, no_repeat_ngram_size: 2, | |
| // , num_return_sequences: 2 (must be 1?) | |
| // let OUTPUT_LIST = [] // a blank array to store the results from the model | |
| // change model run to iterative for each prompt generated locally — will be more expensive?? | |
| // promptArray.forEach(async i => { | |
| // RUN INPUT THROUGH MODEL, | |
| var out = await pipe(INPUT, hyperparameters) | |
| console.log(await out) | |
| console.log('text-gen task completed') | |
| // PARSE RESULTS as a list of outputs, two different ways depending on the model | |
| // OUTPUT_LIST.push(out[0].generated_text) | |
| // }) //this was a loop to wrap model run multiple times | |
| // parsing of output | |
| // await out.forEach(o => { | |
| // console.log(o) | |
| // OUTPUT_LIST.push(o.generated_text) | |
| // }) | |
| // alternate format for parsing, for chat model type | |
| // await out.choices.forEach(o => { | |
| // console.log(o) | |
| // OUTPUT_LIST.push(o.message.content) | |
| // }) | |
| let OUTPUT_LIST = out[0].generated_text //not a list anymore just one result | |
| console.log(OUTPUT_LIST) | |
| console.log('text-gen parsing complete') | |
| return await OUTPUT_LIST | |
| // return await out | |
| } | |
| // RUN FILL-IN MODEL | |
| async function fillInTask(input){ | |
| console.log('fill-in task initiated') | |
| // MODELS LIST | |
| // - Xenova/bert-base-uncased | |
| const pipe = await pipeline('fill-mask', 'Xenova/bert-base-uncased'); | |
| var out = await pipe(input); | |
| console.log(await out) // yields { score, sequence, token, token_str } for each result | |
| let OUTPUT_LIST = [] // a blank array to store the results from the model | |
| // parsing of output | |
| await out.forEach(o => { | |
| console.log(o) // yields { score, sequence, token, token_str } for each result | |
| OUTPUT_LIST.push(o.sequence) // put only the full sequence in a list | |
| }) | |
| console.log(await OUTPUT_LIST) | |
| console.log('fill-in task completed') | |
| // return await out | |
| return await OUTPUT_LIST | |
| } | |
| //// p5.js Instance | |
| new p5(function (p5){ | |
| p5.setup = function(){ | |
| p5.noCanvas() | |
| console.log('p5 instance loaded') | |
| makeTextDisplay() | |
| makeFields() | |
| makeButtons() | |
| } | |
| p5.draw = function(){ | |
| // | |
| } | |
| function makeTextDisplay(){ | |
| const title = p5.createElement('h1','p5.js Critical AI Prompt Battle') | |
| const intro = p5.createP(`This tool lets you explore several AI prompts results at once.`) | |
| p5.createP(`Use it to explore what models 'know' about various concepts, communities, and cultures. For more information on prompt programming and critical AI, see [Tutorial & extra info][TO-DO][XXX]`) | |
| } | |
| function makeFields(){ | |
| pField = p5.createInput(PROMPT_INPUT) // turns the string into an input; now access the text via PROMPT_INPUT.value() | |
| pField.size(700) | |
| pField.attribute('label', `Write a text prompt with one [MASK] that the model will fill in.`) | |
| p5.createP(pField.attribute('label')) | |
| pField.addClass("prompt") | |
| const fieldsDiv = p5.createDiv() | |
| fieldsDiv.id('fieldsDiv') | |
| addField() | |
| } | |
| function makeButtons(){ | |
| // press to run model | |
| const submitButton = p5.createButton("SUBMIT") | |
| submitButton.size(170) | |
| submitButton.class('submit') | |
| submitButton.mousePressed(displayResults) | |
| // press to add more blanks to fill in | |
| const addButton = p5.createButton("more blanks") | |
| addButton.size(170) | |
| // addButton.position(220,500) | |
| addButton.mousePressed(addField) | |
| // also make results placeholder | |
| const outHeader = p5.createElement('h3',"Results") | |
| outText = p5.createP('').id('results') | |
| } | |
| async function displayResults(){ | |
| console.log('submitButton pressed') | |
| // insert waiting dots into results space of interface | |
| outText.html('...', false) | |
| PROMPT_INPUT = pField.value() // grab update to the prompt if it's been changed | |
| console.log("latest prompt: ", PROMPT_INPUT) | |
| // let blanksValues = blanksArray.map(b => b.value) | |
| let blanksValues = [] | |
| blanksArray.forEach(b => { | |
| blanksValues.push(b.value()) | |
| }) | |
| console.log(blanksValues) | |
| // blanksArray.forEach(b => console.log(b.value())) | |
| // call the function that runs the model for the task of your choice here | |
| // make sure to use the PROMPT_INPUT as a parameter, or also the PREPROMPT if valid for that task | |
| let outs = await textGenTask(PREPROMPT, PROMPT_INPUT, blanksValues) | |
| console.log(outs) | |
| // insert the model outputs into the paragraph | |
| await outText.html(outs, false) // false replaces text instead of appends | |
| } | |
| function addField(){ | |
| let f = p5.createInput("") | |
| f.class("blank") | |
| f.parent("#fieldsDiv") | |
| blanksArray.push(f) | |
| console.log("made variable field") | |
| // Cap the number of fields, avoids token limit in prompt | |
| let blanks = document.querySelectorAll(".blank") | |
| if (blanks.length > 5){ | |
| console.log(blanks.length) | |
| addButton.style('visibility','hidden') | |
| } | |
| } | |
| }); | |