From 9be51e192fca8901d47328875d9e0c690d4b2b99 Mon Sep 17 00:00:00 2001 From: polwex Date: Sun, 17 Aug 2025 02:20:42 +0700 Subject: this was me. local LLM! --- src/components/tones/ToneSelectorClient.tsx | 14 ++++++++++++++ src/lib/services/aitranslation.ts | 14 ++++++-------- src/lib/services/llm.ts | 16 ++++++++++++++++ src/pages/tones.tsx | 4 ++-- src/styles.css | 19 +++++++++++++++++-- 5 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 src/lib/services/llm.ts diff --git a/src/components/tones/ToneSelectorClient.tsx b/src/components/tones/ToneSelectorClient.tsx index 438fc8a..3335015 100644 --- a/src/components/tones/ToneSelectorClient.tsx +++ b/src/components/tones/ToneSelectorClient.tsx @@ -29,6 +29,7 @@ import { Skeleton } from "@/components/ui/skeleton"; // For loading state import { MutationOrder, PhoneticData, ToneQuery } from "@/lib/types/phonetics"; import { ProsodySyllable } from "@/lib/types/cards"; import { ArrowLeft, ArrowRight, Volume2, FlipHorizontal2 } from "lucide-react"; +import { LLM } from "@/lib/services/llm"; function getColorByTone(tone: string): string { if (tone === "mid") return "blue"; @@ -96,6 +97,18 @@ const ProminentToneDisplay = ({ word }: { word: any }) => { return () => window.removeEventListener("keydown", onKeyDown); }, [playAudio]); + async function testLM() { + const lm = new LLM({ + openai: { + url: "http://localhost:1234/v1", + apiKey: "", + model: "openai/gpt-oss-20b", + allowBrowser: true, + }, + }); + const res = await lm.chat("hey man something great happened to me today"); + console.log("llm res", res); + } return (

@@ -123,6 +136,7 @@ const ProminentToneDisplay = ({ word }: { word: any }) => {

); diff --git a/src/lib/services/aitranslation.ts b/src/lib/services/aitranslation.ts index 331e10e..fb88323 100644 --- a/src/lib/services/aitranslation.ts +++ b/src/lib/services/aitranslation.ts @@ -1,12 +1,12 @@ import { z } from "zod"; import type { Language, TranslationService } from "../types"; -import AIModelAPI, { type AIModelChoice } from "sortug-ai"; +import AIModelAPI, { type LLMChoice } from "sortug-ai"; import type { AsyncRes } from "@/lib/types"; export class AiTranslator implements TranslationService { endpoint = ""; // doesn't apply here api; - constructor(model: AIModelChoice) { + constructor(model: LLMChoice) { const api = AIModelAPI(model); this.api = api; } @@ -24,12 +24,11 @@ export class AiTranslator implements TranslationService { }, ]; const res = await this.api.send( - `You are a professional, state of the art excellent translation service. Please translate the text given by the user. The prompts will be sent as JSON, in the format "{'text': string, 'sourceLang': string, 'targetLang': string}". You are to translate the 'text' from 'fromLang' to 'targetLang'. Output the desired translation and nothing else. Pause to think the translations as much as you need.`, input, + `You are a professional, state of the art excellent translation service. Please translate the text given by the user. The prompts will be sent as JSON, in the format "{'text': string, 'sourceLang': string, 'targetLang': string}". You are to translate the 'text' from 'fromLang' to 'targetLang'. Output the desired translation and nothing else. Pause to think the translations as much as you need.`, ); console.log({ res }); - if ("error" in res) return res; - else return { ok: res.ok.join(", ") }; + return res; } async getSupportedLanguages() { @@ -49,10 +48,9 @@ export class AiTranslator implements TranslationService { }, ]; const res = await this.api.send( - `You are a professional, state of the art excellent translation service. Please transliterate, the text given by the user. The prompts will be sent as JSON, in the format "{'text': string, 'language': string, 'fromScript': string, 'toScript': string}". You are to transliterate the 'text' belongng to language 'language' from 'fromScript' to 'toScript' to the best of your ability. Output the desired transiteration and nothing else. Pause to think the output as much as you need.`, input, + `You are a professional, state of the art excellent translation service. Please transliterate, the text given by the user. The prompts will be sent as JSON, in the format "{'text': string, 'language': string, 'fromScript': string, 'toScript': string}". You are to transliterate the 'text' belongng to language 'language' from 'fromScript' to 'toScript' to the best of your ability. Output the desired transiteration and nothing else. Pause to think the output as much as you need.`, ); - if ("error" in res) return res; - else return { ok: res.ok.join(", ") }; + return res; } } diff --git a/src/lib/services/llm.ts b/src/lib/services/llm.ts new file mode 100644 index 0000000..508423f --- /dev/null +++ b/src/lib/services/llm.ts @@ -0,0 +1,16 @@ +import AIModelAPI, { type LLMChoice } from "sortug-ai"; +import type { AsyncRes } from "@/lib/types"; + +export class LLM { + private api; + constructor(model: LLMChoice) { + const api = AIModelAPI(model); + this.api = api; + } + + async chat(text: string): AsyncRes { + const res = await this.api.send(text); + console.log({ res }); + return res; + } +} diff --git a/src/pages/tones.tsx b/src/pages/tones.tsx index 20c1237..066f3cb 100644 --- a/src/pages/tones.tsx +++ b/src/pages/tones.tsx @@ -20,13 +20,13 @@ async function randomTones(tries = 0) { console.log({ tones, toneStrings }); const initialWords = await fetchWordsByToneAndSyllables(tones); if (!initialWords || initialWords.length === 0) return randomTones(tries + 1); - else return {initialWords, tones}; + else return { initialWords, tones }; } // Function to fetch the initial word on the server async function InitialWordLoader() { // Fetch a random 1-syllable Thai word with any tone initially - const {initialWords, tones]} = await randomTones(); + const { initialWords, tones } = await randomTones(); return ; } diff --git a/src/styles.css b/src/styles.css index f1d3c37..71b058c 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,3 +1,18 @@ -@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,400;0,700;1,400;1,700&display=swap') -layer(base); +@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,400;0,700;1,400;1,700&display=swap') layer(base); @import 'tailwindcss'; + +@font-face { + font-family: 'ThaiCustom'; + src: local('Noto Sans Thai'); + /* Specify a clear Thai font installed on your system */ + size-adjust: 200%; + unicode-range: U+0E00-0E7F; +} + +@font-face { + font-family: 'Lolmao'; + src: local('Fira'); + /* Specify a clear Thai font installed on your system */ + size-adjust: 200%; + unicode-range: U+0000-007F; +} \ No newline at end of file -- cgit v1.2.3