Skip to content

Commit 48411fd

Browse files
committed
embeddings
1 parent 452eb61 commit 48411fd

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed

src/components/dictionary/Dictionary.tsx

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import Form from 'react-bootstrap/Form';
33
import Button from 'react-bootstrap/Button';
44
import Spinner from 'react-bootstrap/Spinner';
55
import { CancelTokenSource } from 'axios';
6-
76
import { isPair, Pairs } from '../translator';
87
import LanguageSelector from '../translator/LanguageSelector';
98
import { toAlpha3Code } from '../../util/languages';
@@ -40,20 +39,17 @@ const WithSrcLang = ({
4039
}) => {
4140
const opts: any = { validateValue: (l: string) => l in pairs };
4241
if (urlSrcLang) opts.overrideValue = urlSrcLang;
43-
4442
const [srcLang, rawSetSrcLang] = useLocalStorage<string>('dictSrcLang', () => defaultSrcLang(pairs), opts);
4543
const [recentSrcLangs, rawSetRecentSrcLangs] = useLocalStorage<string[]>('dictRecentSrcLangs', () => [srcLang], {
4644
validateValue: (ls) => Array.isArray(ls) && ls.every((l) => l in pairs),
4745
});
48-
4946
const setSrcLang = React.useCallback(
5047
(lang: string) => {
5148
rawSetSrcLang(lang);
5249
rawSetRecentSrcLangs((prev) => Array.from(new Set([lang, ...prev])).slice(0, recentLangsCount));
5350
},
5451
[rawSetSrcLang, rawSetRecentSrcLangs],
5552
);
56-
5753
const [detectedLang, setDetected] = React.useState<string | null>(null);
5854
const setDetectedLang = React.useCallback(
5955
(lang: string | null) => {
@@ -62,7 +58,6 @@ const WithSrcLang = ({
6258
},
6359
[setSrcLang],
6460
);
65-
6661
return children({
6762
srcLang,
6863
setSrcLang,
@@ -92,7 +87,6 @@ const WithTgtLang = ({
9287
}) => {
9388
const opts: any = { validateValue: (l: string) => isPair(pairs, srcLang, l) };
9489
if (urlTgtLang) opts.overrideValue = urlTgtLang;
95-
9690
const [tgtLang, rawSetTgtLang] = useLocalStorage<string>(
9791
'dictTgtLang',
9892
() => {
@@ -104,23 +98,20 @@ const WithTgtLang = ({
10498
const [recentTgtLangs, rawSetRecentTgtLangs] = useLocalStorage<string[]>('dictRecentTgtLangs', () => [tgtLang], {
10599
validateValue: (ls) => Array.isArray(ls) && ls.every((l) => isPair(pairs, srcLang, l)),
106100
});
107-
108101
const setTgtLang = React.useCallback(
109102
(lang: string) => {
110103
rawSetTgtLang(lang);
111104
rawSetRecentTgtLangs((prev) => Array.from(new Set([lang, ...prev])).slice(0, recentLangsCount));
112105
},
113106
[rawSetTgtLang, rawSetRecentTgtLangs],
114107
);
115-
116108
React.useEffect(() => {
117109
if (!isPair(pairs, srcLang, tgtLang)) {
118110
const fallback = recentTgtLangs.find((l) => isPair(pairs, srcLang, l));
119111
const newTgt = fallback || (pairs[srcLang] ? Array.from(pairs[srcLang])[0] : '');
120112
if (newTgt && newTgt !== tgtLang) setTgtLang(newTgt);
121113
}
122114
}, [pairs, srcLang, tgtLang, recentTgtLangs, setTgtLang]);
123-
124115
return children({ tgtLang, setTgtLang, recentTgtLangs });
125116
};
126117

@@ -183,13 +174,14 @@ const Dictionary: React.FC = () => {
183174
const [loading, setLoading] = React.useState(false);
184175
const [searched, setSearched] = React.useState(false);
185176
const searchRef = React.useRef<CancelTokenSource | null>(null);
186-
187177
const [results, setResults] = React.useState<{ head: string; defs: string[] }[]>([]);
188178
const [reverseResults, setReverseResults] = React.useState<{ head: string; defs: string[] }[]>([]);
179+
const [embeddingResults, setEmbeddingResults] = React.useState<{ head: string; defs: string[] }[]>([]);
189180

190181
React.useEffect(() => {
191182
setResults([]);
192183
setReverseResults([]);
184+
setEmbeddingResults([]);
193185
setSearched(false);
194186
}, [srcLang, tgtLang]);
195187

@@ -213,6 +205,7 @@ const Dictionary: React.FC = () => {
213205
setLoading(true);
214206
setResults([]);
215207
setReverseResults([]);
208+
setEmbeddingResults([]);
216209

217210
const [, reqFwd] = apyFetch('billookup', {
218211
q: `${word}<*>`,
@@ -234,33 +227,53 @@ const Dictionary: React.FC = () => {
234227

235228
try {
236229
const [respFwd, respRev] = await Promise.all([reqFwd, reqRev]);
237-
setResults(parse(respFwd));
230+
const fwdParsed = parse(respFwd);
231+
setResults(fwdParsed);
238232

239233
revParsed = parse(respRev).flatMap(({ head, defs }) =>
240-
defs.map((def) => ({ head: def.replace(/^\s*\d+\.\s*/, ''), defs: [head] })),
234+
defs.map((d) => ({ head: d.replace(/^\s*\d+\.\s*/, ''), defs: [head] })),
241235
);
242-
243236
const uniqueHeads = Array.from(new Set(revParsed.map((r) => r.head)));
244-
245237
const headResponses = await Promise.all(
246-
uniqueHeads.map((h) => {
247-
const [, req] = apyFetch('bilsearch', {
248-
q: h,
249-
langpair: `${srcOverride}|${tgtOverride}`,
250-
});
251-
return req.then(parse);
252-
}),
238+
uniqueHeads.map((h) =>
239+
apyFetch('bilsearch', { q: h, langpair: `${srcOverride}|${tgtOverride}` })[1].then(parse),
240+
),
253241
);
254-
255242
const enriched: Record<string, string[]> = {};
256243
headResponses.forEach((arr, i) => {
257-
const h = uniqueHeads[i];
258-
enriched[h] = Array.from(
244+
enriched[uniqueHeads[i]] = Array.from(
259245
new Set(arr.flatMap((item) => item.defs.map((d) => d.replace(/<[^>]+>/g, '').trim()))),
260246
);
261247
});
262-
263248
setReverseResults(uniqueHeads.map((h) => ({ head: h, defs: enriched[h] })));
249+
250+
const exactItem = fwdParsed.find((item) => item.head.replace(/<[^>]+>/g, '') === word);
251+
const translations = exactItem?.defs.map((d) => d.replace(/<[^>]+>/g, '').trim()) || [];
252+
const embArrays = await Promise.all(
253+
translations.map((term) =>
254+
apyFetch('embeddings', { q: term, langpair: `${tgtOverride}|${srcOverride}` })[1].then(
255+
(res) =>
256+
res.data.responseData?.embeddingResults.flatMap((obj: any) => Object.values(obj).flat()) ||
257+
[],
258+
),
259+
),
260+
);
261+
const sims = Array.from(new Set(embArrays.flat())).filter((sim) => !sim.startsWith('*'));
262+
const embResponses = await Promise.all(
263+
sims.map((sim) => apyFetch('bilsearch', { q: sim, langpair: `${tgtOverride}|${srcOverride}` })[1]),
264+
);
265+
let embEntries: Entry[] = [];
266+
embResponses.forEach((resp) => {
267+
const raw = resp.data.responseData?.searchResults ?? [];
268+
(raw as Array<Record<string, string[]>>).forEach((o) => {
269+
Object.entries(o).forEach(([hd, defs]) => {
270+
defs.forEach((def) => {
271+
embEntries.push({ head: def, defs: [hd] });
272+
});
273+
});
274+
});
275+
});
276+
setEmbeddingResults(embEntries);
264277
} catch {
265278
setReverseResults(revParsed);
266279
} finally {
@@ -275,6 +288,7 @@ const Dictionary: React.FC = () => {
275288
const all: Entry[] = [
276289
...results.map((r) => ({ head: r.head, defs: r.defs })),
277290
...reverseResults.map((r) => ({ head: r.head, defs: r.defs })),
291+
...embeddingResults.map((e) => ({ head: e.head, defs: e.defs })),
278292
];
279293
const map: Record<string, Entry[]> = {};
280294
all.forEach((e) => {
@@ -286,7 +300,7 @@ const Dictionary: React.FC = () => {
286300
});
287301
});
288302
return map;
289-
}, [results, reverseResults]);
303+
}, [results, reverseResults, embeddingResults]);
290304

291305
return (
292306
<Form
@@ -311,7 +325,6 @@ const Dictionary: React.FC = () => {
311325
detectedLang={detectedLang}
312326
setDetectedLang={setDetectedLang}
313327
/>
314-
315328
<Form.Group className="mt-3" controlId="searchWord">
316329
<Form.Control
317330
type="text"
@@ -320,15 +333,13 @@ const Dictionary: React.FC = () => {
320333
onChange={(e) => setSearchWord(e.target.value)}
321334
/>
322335
</Form.Group>
323-
324336
<div className="d-flex justify-content-start mt-2">
325337
<Button onClick={() => handleSearch()} variant="primary" size="sm">
326338
{t('Search')}
327339
</Button>
328340
</div>
329-
330341
<div className="mt-3">
331-
{[...Object.entries(grouped)]
342+
{Object.entries(grouped)
332343
.sort(([a], [b]) => {
333344
if (a === searchWord && b !== searchWord) return -1;
334345
if (b === searchWord && a !== searchWord) return 1;
@@ -348,7 +359,6 @@ const Dictionary: React.FC = () => {
348359
}}
349360
/>
350361
))}
351-
352362
{searched && !loading && Object.keys(grouped).length === 0 && (
353363
<div className="text-center text-muted mt-3">{t('No_results_found')}</div>
354364
)}

0 commit comments

Comments
 (0)