diff --git a/src/engine.ts b/src/engine.ts index 3535c04..e7664e6 100644 --- a/src/engine.ts +++ b/src/engine.ts @@ -207,3 +207,32 @@ async function isContentSafe(textPrompt: string): Promise { throw new Error("Error checking content safety: " + error); } } + +export async function getSynonym( + word: string, + language: string +): Promise { + const languageName = getLanguageName(language); + const prompt = `Provide a simple, commonly used synonym for the word "${word}" in ${languageName} to support a non-verbal person. Follow these mandatory instructions: + - Return only one synonym. + - Ensure the synonym is simple, familiar, and frequently used in everyday language. + - If no suitable synonym exists, return the original word unchanged. + - Do not include any additional words, explanations, symbols, or characters; only the synonym itself. + `; + const completionRequestParams = { + model: "gpt-3.5-turbo-instruct", + prompt: prompt, + temperature: 0, + max_tokens: 10, + }; + + const response = await globalConfiguration.openAIInstance.createCompletion( + completionRequestParams + ); + const synonymData = response.data?.choices[0]?.text; + if (synonymData) { + const synonym = synonymData.trim(); + if (synonym) return synonym; + } + throw new Error("ERROR: Synonym not found"); +} diff --git a/src/lib/symbolSets.ts b/src/lib/symbolSets.ts index 1be3f80..8f878f0 100644 --- a/src/lib/symbolSets.ts +++ b/src/lib/symbolSets.ts @@ -4,6 +4,7 @@ import { LabelsSearchApiResponse } from "../types/global-symbols"; import { BestSearchApiResponse } from "../types/arasaac"; import { Suggestion } from "../engine"; import { ARASAAC } from "../constants"; +import { getSynonym } from "../engine"; export type SymbolSet = "arasaac" | "global-symbols"; @@ -45,7 +46,11 @@ export async function getArasaacPictogramSuggestions({ ); } -async function fetchArasaacData(URL: string, word: string, language: string) { +async function fetchArasaacData( + URL: string, + word: string, + language: string +): Promise { const cleanedWord = removeDiacritics(word); const bestSearchUrl = `${URL}/${language}/bestsearch/${encodeURIComponent( cleanedWord @@ -54,18 +59,48 @@ async function fetchArasaacData(URL: string, word: string, language: string) { cleanedWord )}`; - try { - const { data } = await axios.get(bestSearchUrl); + let data: BestSearchApiResponse | [] = []; + + const bestSearchResponse = await axios + .get(bestSearchUrl) + .catch(() => null); + if (bestSearchResponse && bestSearchResponse.data.length) { + return bestSearchResponse.data; + } + + const searchResponse = await axios + .get(searchUrl) + .catch(() => null); + if (searchResponse && searchResponse.data.length) { + data = + searchResponse.data.length > 5 + ? searchResponse.data.slice(0, 5) + : searchResponse.data; return data; - } catch { - try { - let { data } = await axios.get(searchUrl); - if (data.length > 5) data = data.slice(0, 5); + } + + for (let attempt = 0; attempt < 5; attempt++) { + const synonym = await getSynonym(word, language).catch(() => ""); + if (!synonym) continue; + word = synonym; + const cleanedSynonym = removeDiacritics(synonym); + const synonymSearchUrl = `${URL}/${language}/search/${encodeURIComponent( + cleanedSynonym + )}`; + + const synonymResponse = await axios + .get(synonymSearchUrl) + .catch(() => null); + if (synonymResponse && synonymResponse.data.length) { + data = + synonymResponse.data.length > 5 + ? synonymResponse.data.slice(0, 5) + : synonymResponse.data; return data; - } catch { - return []; } } + + return data; } function mapArasaacResponse( @@ -116,7 +151,7 @@ async function fetchGlobalSymbolsData( word: string, language: string, symbolSet: string | null -) { +): Promise { const cleanedWord = removeDiacritics(word); const config: AxiosRequestConfig = { params: {