Snapshot
Browse files- .gitignore +1 -0
- frontend/src/components/TokenChip.tsx +61 -9
- frontend/src/components/app.tsx +17 -3
- requirements.txt +1 -0
.gitignore
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
/.aider*
|
2 |
/.env
|
3 |
/.venv/
|
|
|
|
1 |
/.aider*
|
2 |
/.env
|
3 |
/.venv/
|
4 |
+
/__pycache__/
|
frontend/src/components/TokenChip.tsx
CHANGED
@@ -1,10 +1,62 @@
|
|
1 |
-
import React from "react"
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
}
|
|
|
1 |
+
import React, { useState } from "react"
|
2 |
+
|
3 |
+
import React, { useState } from "react"
|
4 |
+
|
5 |
+
export const TokenChip = ({
|
6 |
+
token,
|
7 |
+
logprob,
|
8 |
+
threshold,
|
9 |
+
replacements,
|
10 |
+
onReplace
|
11 |
+
}: {
|
12 |
+
token: string,
|
13 |
+
logprob: number,
|
14 |
+
threshold: number,
|
15 |
+
replacements: string[],
|
16 |
+
onReplace: (newToken: string) => void
|
17 |
+
}) => {
|
18 |
+
const [isExpanded, setIsExpanded] = useState(false);
|
19 |
+
|
20 |
+
const handleClick = () => {
|
21 |
+
if (logprob < threshold && replacements.length > 0) {
|
22 |
+
setIsExpanded(true);
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
const handleReplacement = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
27 |
+
const newToken = event.target.value
|
28 |
+
if (newToken !== token) {
|
29 |
+
onReplace(newToken)
|
30 |
+
}
|
31 |
+
setIsExpanded(false);
|
32 |
+
}
|
33 |
+
|
34 |
+
return (
|
35 |
+
<span
|
36 |
+
title={logprob.toFixed(2)}
|
37 |
+
className={`token-chip ${logprob < threshold ? "flagged" : ""}`}
|
38 |
+
style={{ position: "relative", cursor: logprob < threshold ? "pointer" : "default" }}
|
39 |
+
onClick={handleClick}
|
40 |
+
>
|
41 |
+
{token}
|
42 |
+
{isExpanded && (
|
43 |
+
<select
|
44 |
+
onChange={handleReplacement}
|
45 |
+
value={token}
|
46 |
+
style={{
|
47 |
+
position: "absolute",
|
48 |
+
top: "100%",
|
49 |
+
left: 0,
|
50 |
+
zIndex: 1000
|
51 |
+
}}
|
52 |
+
size={replacements.length}
|
53 |
+
autoFocus
|
54 |
+
>
|
55 |
+
{replacements.map((rep, idx) => (
|
56 |
+
<option key={idx} value={rep}>{rep}</option>
|
57 |
+
))}
|
58 |
+
</select>
|
59 |
+
)}
|
60 |
+
</span>
|
61 |
+
)
|
62 |
}
|
frontend/src/components/app.tsx
CHANGED
@@ -8,10 +8,14 @@ interface Word {
|
|
8 |
}
|
9 |
|
10 |
async function checkText(text: string): Promise<Word[]> {
|
11 |
-
await new Promise(resolve => setTimeout(resolve,
|
12 |
|
13 |
const words = text.split(/\b/)
|
14 |
-
return words.map(word => ({
|
|
|
|
|
|
|
|
|
15 |
}
|
16 |
|
17 |
// Add a new Spinner component
|
@@ -26,7 +30,7 @@ export default function App() {
|
|
26 |
const [context, setContext] = useState("")
|
27 |
const [wordlist, setWordlist] = useState("")
|
28 |
const [showWholePrompt, setShowWholePrompt] = useState(false)
|
29 |
-
const [text, setText] = useState("")
|
30 |
const [mode, setMode] = useState<"edit" | "check">("edit")
|
31 |
const [words, setWords] = useState<Word[]>([])
|
32 |
const [isLoading, setIsLoading] = useState(false)
|
@@ -46,6 +50,14 @@ export default function App() {
|
|
46 |
}
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
let result
|
50 |
|
51 |
if (mode === "edit") {
|
@@ -66,6 +78,8 @@ export default function App() {
|
|
66 |
token={word.text}
|
67 |
logprob={word.logprob}
|
68 |
threshold={threshold}
|
|
|
|
|
69 |
/>
|
70 |
))}
|
71 |
</div>
|
|
|
8 |
}
|
9 |
|
10 |
async function checkText(text: string): Promise<Word[]> {
|
11 |
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
12 |
|
13 |
const words = text.split(/\b/)
|
14 |
+
return words.map(word => ({
|
15 |
+
text: word,
|
16 |
+
logprob: -word.length,
|
17 |
+
replacements: word.length < 4 ? [] : ["foo", "bar"]
|
18 |
+
}))
|
19 |
}
|
20 |
|
21 |
// Add a new Spinner component
|
|
|
30 |
const [context, setContext] = useState("")
|
31 |
const [wordlist, setWordlist] = useState("")
|
32 |
const [showWholePrompt, setShowWholePrompt] = useState(false)
|
33 |
+
const [text, setText] = useState("The cumbersomely quick brown fox jumps over the conspicuously lazy dog.")
|
34 |
const [mode, setMode] = useState<"edit" | "check">("edit")
|
35 |
const [words, setWords] = useState<Word[]>([])
|
36 |
const [isLoading, setIsLoading] = useState(false)
|
|
|
50 |
}
|
51 |
}
|
52 |
|
53 |
+
const handleReplace = (index: number, newToken: string) => {
|
54 |
+
const updatedWords = [...words]
|
55 |
+
updatedWords[index].text = newToken
|
56 |
+
setWords(updatedWords)
|
57 |
+
setText(updatedWords.map(w => w.text).join(""))
|
58 |
+
setMode("edit")
|
59 |
+
}
|
60 |
+
|
61 |
let result
|
62 |
|
63 |
if (mode === "edit") {
|
|
|
78 |
token={word.text}
|
79 |
logprob={word.logprob}
|
80 |
threshold={threshold}
|
81 |
+
replacements={word.replacements}
|
82 |
+
onReplace={(newToken) => handleReplace(index, newToken)}
|
83 |
/>
|
84 |
))}
|
85 |
</div>
|
requirements.txt
CHANGED
@@ -4,3 +4,4 @@ ipywidgets
|
|
4 |
transformers
|
5 |
torch
|
6 |
huggingface_hub
|
|
|
|
4 |
transformers
|
5 |
torch
|
6 |
huggingface_hub
|
7 |
+
fastapi[standard]
|