Snapshot
Browse files- completions.py +0 -2
- frontend/package.json +1 -6
- frontend/src/components/App.tsx +6 -5
- frontend/src/components/Spinner.tsx +7 -7
- frontend/src/components/WordChip.tsx +40 -25
- main.py +14 -12
completions.py
CHANGED
@@ -3,8 +3,6 @@ import time
|
|
3 |
import torch
|
4 |
from transformers import AutoTokenizer, AutoModelForCausalLM, PreTrainedModel, PreTrainedTokenizer, PreTrainedTokenizerFast, BatchEncoding
|
5 |
from transformers.generation.utils import GenerateOutput
|
6 |
-
from typing import cast
|
7 |
-
from dataclasses import dataclass
|
8 |
|
9 |
from models import ApiWord, Word
|
10 |
|
|
|
3 |
import torch
|
4 |
from transformers import AutoTokenizer, AutoModelForCausalLM, PreTrainedModel, PreTrainedTokenizer, PreTrainedTokenizerFast, BatchEncoding
|
5 |
from transformers.generation.utils import GenerateOutput
|
|
|
|
|
6 |
|
7 |
from models import ApiWord, Word
|
8 |
|
frontend/package.json
CHANGED
@@ -1,15 +1,10 @@
|
|
1 |
{
|
2 |
-
"name": "frontend",
|
3 |
-
"version": "1.0.0",
|
4 |
-
"main": "index.js",
|
5 |
"type": "module",
|
6 |
"scripts": {
|
7 |
"build": "node esbuild.js",
|
8 |
"watch": "node esbuild.js --watch"
|
9 |
},
|
10 |
-
"author": "",
|
11 |
-
"license": "ISC",
|
12 |
-
"description": "",
|
13 |
"dependencies": {
|
14 |
"react": "^18.3.1",
|
15 |
"react-dom": "^18.3.1"
|
|
|
1 |
{
|
2 |
+
"name": "gpted-frontend",
|
|
|
|
|
3 |
"type": "module",
|
4 |
"scripts": {
|
5 |
"build": "node esbuild.js",
|
6 |
"watch": "node esbuild.js --watch"
|
7 |
},
|
|
|
|
|
|
|
8 |
"dependencies": {
|
9 |
"react": "^18.3.1",
|
10 |
"react-dom": "^18.3.1"
|
frontend/src/components/App.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import React, { useState } from "react"
|
2 |
import { WordChip } from "./WordChip"
|
3 |
-
import Spinner from "./Spinner"
|
4 |
|
5 |
interface Word {
|
6 |
text: string
|
@@ -9,10 +9,11 @@ interface Word {
|
|
9 |
}
|
10 |
|
11 |
async function checkText(text: string): Promise<Word[]> {
|
12 |
-
const
|
13 |
-
const
|
14 |
-
|
15 |
-
|
|
|
16 |
}
|
17 |
|
18 |
export default function App() {
|
|
|
1 |
import React, { useState } from "react"
|
2 |
import { WordChip } from "./WordChip"
|
3 |
+
import { Spinner } from "./Spinner"
|
4 |
|
5 |
interface Word {
|
6 |
text: string
|
|
|
9 |
}
|
10 |
|
11 |
async function checkText(text: string): Promise<Word[]> {
|
12 |
+
const encodedText = encodeURIComponent(text);
|
13 |
+
const response = await fetch(`/check?text=${encodedText}`);
|
14 |
+
const data = await response.json();
|
15 |
+
console.log(data);
|
16 |
+
return data.words;
|
17 |
}
|
18 |
|
19 |
export default function App() {
|
frontend/src/components/Spinner.tsx
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
import React from "react"
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
<div className="spinner"
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
1 |
import React from "react"
|
2 |
|
3 |
+
export function Spinner() {
|
4 |
+
return (
|
5 |
+
<div className="spinner-overlay">
|
6 |
+
<div className="spinner"></div>
|
7 |
+
</div>
|
8 |
+
);
|
9 |
+
}
|
frontend/src/components/WordChip.tsx
CHANGED
@@ -1,20 +1,23 @@
|
|
1 |
import React, { useState, useEffect, useRef } from "react"
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
word,
|
5 |
logprob,
|
6 |
threshold,
|
7 |
replacements,
|
8 |
onReplace
|
9 |
-
}: {
|
10 |
-
word: string,
|
11 |
-
logprob: number,
|
12 |
-
threshold: number,
|
13 |
-
replacements: string[],
|
14 |
-
onReplace: (newWord: string) => void
|
15 |
-
}) => {
|
16 |
const [isExpanded, setIsExpanded] = useState(false);
|
17 |
-
const
|
|
|
18 |
|
19 |
useEffect(() => {
|
20 |
const handleClickOutside = (event: MouseEvent) => {
|
@@ -35,12 +38,11 @@ export const WordChip = ({
|
|
35 |
}
|
36 |
}
|
37 |
|
38 |
-
const handleReplacement = (
|
39 |
-
console.log("handleReplacement",
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
}
|
44 |
|
45 |
return (
|
46 |
<span
|
@@ -51,24 +53,37 @@ export const WordChip = ({
|
|
51 |
>
|
52 |
{word}
|
53 |
{isExpanded && (
|
54 |
-
<
|
55 |
ref={dropdownRef}
|
56 |
-
onChange={handleReplacement}
|
57 |
-
value={word}
|
58 |
style={{
|
59 |
position: "absolute",
|
60 |
top: "100%",
|
61 |
left: 0,
|
62 |
-
zIndex:
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
64 |
}}
|
65 |
-
size={replacements.length + 1}
|
66 |
>
|
67 |
-
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
))}
|
71 |
-
</
|
72 |
)}
|
73 |
</span>
|
74 |
)
|
|
|
1 |
import React, { useState, useEffect, useRef } from "react"
|
2 |
|
3 |
+
interface WordChipProps {
|
4 |
+
word: string;
|
5 |
+
logprob: number;
|
6 |
+
threshold: number;
|
7 |
+
replacements: string[];
|
8 |
+
onReplace: (newWord: string) => Promise<void>;
|
9 |
+
}
|
10 |
+
|
11 |
+
export function WordChip({
|
12 |
word,
|
13 |
logprob,
|
14 |
threshold,
|
15 |
replacements,
|
16 |
onReplace
|
17 |
+
}: WordChipProps) {
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
const [isExpanded, setIsExpanded] = useState(false);
|
19 |
+
const [selectedIndex, setSelectedIndex] = useState(-1);
|
20 |
+
const dropdownRef = useRef<HTMLDivElement>(null);
|
21 |
|
22 |
useEffect(() => {
|
23 |
const handleClickOutside = (event: MouseEvent) => {
|
|
|
38 |
}
|
39 |
}
|
40 |
|
41 |
+
const handleReplacement = async (newWord: string) => {
|
42 |
+
console.log("handleReplacement", newWord);
|
43 |
+
await onReplace(newWord);
|
44 |
+
setIsExpanded(false); // Close the dropdown
|
45 |
+
};
|
|
|
46 |
|
47 |
return (
|
48 |
<span
|
|
|
53 |
>
|
54 |
{word}
|
55 |
{isExpanded && (
|
56 |
+
<div
|
57 |
ref={dropdownRef}
|
|
|
|
|
58 |
style={{
|
59 |
position: "absolute",
|
60 |
top: "100%",
|
61 |
left: 0,
|
62 |
+
zIndex: 100,
|
63 |
+
maxHeight: "400px",
|
64 |
+
overflowY: "auto",
|
65 |
+
backgroundColor: "white",
|
66 |
+
border: "1px solid #ccc",
|
67 |
+
borderRadius: "4px",
|
68 |
+
boxShadow: "0 2px 4px rgba(0,0,0,0.1)"
|
69 |
}}
|
|
|
70 |
>
|
71 |
+
{replacements.map((option, index) => (
|
72 |
+
<div
|
73 |
+
key={index}
|
74 |
+
onClick={() => handleReplacement(option)}
|
75 |
+
onMouseEnter={() => setSelectedIndex(index)}
|
76 |
+
style={{
|
77 |
+
padding: "5px 10px",
|
78 |
+
cursor: "pointer",
|
79 |
+
color: "black",
|
80 |
+
backgroundColor: selectedIndex === index ? "#f0f0f0" : "white"
|
81 |
+
}}
|
82 |
+
>
|
83 |
+
{option}
|
84 |
+
</div>
|
85 |
))}
|
86 |
+
</div>
|
87 |
)}
|
88 |
</span>
|
89 |
)
|
main.py
CHANGED
@@ -7,26 +7,28 @@ from completions import check_text, load_model
|
|
7 |
|
8 |
app = FastAPI()
|
9 |
|
10 |
-
|
11 |
|
12 |
-
def
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
20 |
|
21 |
-
@lru_cache(maxsize=100)
|
22 |
-
def cached_check_text(text: str):
|
23 |
-
# return check_text(text, model, tokenizer, device)
|
24 |
result = []
|
25 |
for i, w in enumerate(text.split()):
|
26 |
logprob, replacements = rep(i)
|
27 |
result.append(ApiWord(text=f" {w}", logprob=logprob, replacements=replacements))
|
28 |
return result
|
29 |
|
|
|
|
|
|
|
|
|
30 |
@app.get("/check", response_model=CheckResponse)
|
31 |
def check(text: str):
|
32 |
return CheckResponse(text=text, words=cached_check_text(text))
|
|
|
7 |
|
8 |
app = FastAPI()
|
9 |
|
10 |
+
model, tokenizer, device = load_model()
|
11 |
|
12 |
+
def check_text_stub(text: str):
|
13 |
+
def rep(i):
|
14 |
+
if i == 3:
|
15 |
+
return -10, [" jumped", " leaps"]
|
16 |
+
if i == 5:
|
17 |
+
return -10, [" calm"]
|
18 |
+
if i == 7:
|
19 |
+
return -10, [" dog", " cat", " bird", " fish"]
|
20 |
+
return -3, []
|
21 |
|
|
|
|
|
|
|
22 |
result = []
|
23 |
for i, w in enumerate(text.split()):
|
24 |
logprob, replacements = rep(i)
|
25 |
result.append(ApiWord(text=f" {w}", logprob=logprob, replacements=replacements))
|
26 |
return result
|
27 |
|
28 |
+
@lru_cache(maxsize=100)
|
29 |
+
def cached_check_text(text: str):
|
30 |
+
return check_text(text, model, tokenizer, device)
|
31 |
+
|
32 |
@app.get("/check", response_model=CheckResponse)
|
33 |
def check(text: str):
|
34 |
return CheckResponse(text=text, words=cached_check_text(text))
|