File size: 4,725 Bytes
8214506 82b1b1d 0970991 82b1b1d c4d5641 1fe47b1 82b1b1d 1fe47b1 82b1b1d 8214506 0970991 8214506 82b1b1d 8214506 bbae7a9 82b1b1d 0970991 8214506 bbae7a9 82b1b1d 0970991 bbae7a9 82b1b1d 8214506 bbae7a9 1fe47b1 bbae7a9 1fe47b1 bbae7a9 1fe47b1 8214506 82b1b1d 0970991 8214506 82b1b1d 0970991 1fe47b1 0970991 82b1b1d 8214506 82b1b1d 8214506 bbae7a9 8214506 82b1b1d 8214506 82b1b1d 8214506 82b1b1d 8214506 82b1b1d 8214506 bbae7a9 8214506 82b1b1d 8214506 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
import React, { useState } from "react"
import { TokenChip } from "./TokenChip"
interface Word {
text: string
logprob: number
replacements: string[]
}
async function checkText(text: string): Promise<Word[]> {
const response = await fetch(`/check?text=${text}`)
const data = await response.json()
console.log(data)
return data.words
}
async function checkText0(text: string): Promise<Word[]> {
await new Promise(resolve => setTimeout(resolve, 1000));
const words = text.split(/\b/)
return words.map(word => ({
text: word,
logprob: -word.length,
replacements: word.length < 4 ? [] : ["foo", "bar"]
}))
}
// Add a new Spinner component
const Spinner = () => (
<div className="spinner-overlay">
<div className="spinner"></div>
</div>
);
export default function App() {
const [threshold, setThreshold] = useState(-5.0)
const [context, setContext] = useState("")
const [wordlist, setWordlist] = useState("")
const [showWholePrompt, setShowWholePrompt] = useState(false)
const [text, setText] = useState("I just drove to the store to but eggs, but they had some.")
const [mode, setMode] = useState<"edit" | "check">("edit")
const [words, setWords] = useState<Word[]>([])
const [isLoading, setIsLoading] = useState(false)
const check = async () => {
setIsLoading(true)
try {
const checkedWords = await checkText(text)
setWords(checkedWords)
} finally {
setIsLoading(false)
setMode("check")
}
}
const toggleMode = async () => {
if (mode === "edit") {
setIsLoading(true)
await check()
} else {
setMode("edit")
}
}
const handleReplace = async (index: number, newToken: string) => {
const updatedWords = [...words]
updatedWords[index].text = newToken
updatedWords[index].logprob = 0
updatedWords[index].replacements = []
setWords(updatedWords)
setText(updatedWords.map(w => w.text).join(""))
// setMode("edit")
await check()
}
let result
if (mode === "edit") {
result = (
<div className="result-container">
{isLoading && <Spinner />}
<textarea value={text} onChange={e => setText(e.target.value)} />
</div>
)
} else {
result = (
<div className="result-container">
{isLoading && <Spinner />}
<div className="result">
{words.map((word, index) => (
<TokenChip
key={index}
token={word.text}
logprob={word.logprob}
threshold={threshold}
replacements={word.replacements}
onReplace={(newToken) => handleReplace(index, newToken)}
/>
))}
</div>
</div>
)
}
return (
<main>
<h1>GPTed</h1>
<details>
<summary>Advanced settings</summary>
<label>
<strong>Threshold:</strong> <input type="number" step="1" value={threshold} onChange={e => setThreshold(Number(e.target.value))} />
<small>
The <a href="https://en.wikipedia.org/wiki/Log_probability" target="_blank" rel="noreferrer">logprob</a> threshold.
Tokens with logprobs smaller than this will be marked red.
</small>
</label>
<label>
<strong>Context:</strong> <small>Context for the text, which can help GPT3 better rank certain words.</small>
<textarea placeholder="A short essay about picnics" value={context} onChange={e => setContext(e.target.value)} />
</label>
<label>
<strong>Dictionary:</strong>
<small>Known words or phrases. Helpful for uncommon or invented words and names.</small>
<textarea placeholder="jujubu eschaton Frodo Baggins" value={wordlist} onChange={e => setWordlist(e.target.value)} />
</label>
<label>
<strong>Show whole prompt:</strong> <input type="checkbox" checked={showWholePrompt} onChange={e => setShowWholePrompt(e.target.checked)} />
<small>
Show the whole prompt in the token view, instead of just your text. Mostly useful for debugging or curiosity.
</small>
</label>
</details>
<section id="inner">
{result}
<button onClick={toggleMode}>
{mode === "edit" ? "Check" : "Edit"}
</button>
<p>
<small>
Based on <a href="https://github.com/vgel/gpted">GPTed</a> by <a href="https://vgel.me">Theia Vogel</a>.
Made with React, Transformers, LLama 3.2, and transitively, most of the web.
<br />
This software is provided with absolutely no warranty.
</small>
</p>
</section>
</main>
)
}
|