persist LLM sentence explainer with supabase
This commit is contained in:
1 parent
e734d09039
commit
82b51c0703
2 files changed
+58
-12
No files matched your search
@@ -67,13 +67,23 @@
|
||||
<div v-else v-html="v.notes"></div>
|
||||
</blockquote>
|
||||
<div v-if="example">
|
||||
<blockquote
|
||||
v-if="exNotes"
|
||||
v-html="markdownIt.render(exNotes)"
|
||||
></blockquote>
|
||||
<button type="button" v-else @click="explainSentence(example.ko)">
|
||||
Explain sentence
|
||||
</button>
|
||||
<div v-if="exNotes">
|
||||
<button
|
||||
type="button"
|
||||
@click="
|
||||
exNotes = '';
|
||||
explainSentence(example.ko);
|
||||
"
|
||||
>
|
||||
New explanation
|
||||
</button>
|
||||
<blockquote v-html="markdownIt.render(exNotes)" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<button type="button" @click="explainSentence(example.ko)">
|
||||
Explain sentence
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</nav>
|
||||
@@ -168,7 +178,7 @@ const vaud = useTemplateRef<InstanceType<typeof SentenceAudio>>("vaud");
|
||||
|
||||
const v = computed(() => vList.value[vIndex.value]);
|
||||
const example = computed(() => {
|
||||
if (!v.value.examples?.length) return null;
|
||||
if (!v.value?.examples?.length) return null;
|
||||
const ex = v.value.examples;
|
||||
return ex[exIndex.value];
|
||||
});
|
||||
@@ -200,6 +210,25 @@ watch(quizState, () => {
|
||||
saveQuizState();
|
||||
});
|
||||
|
||||
watch(example, () => {
|
||||
exNotes.value = "";
|
||||
if (!example.value) return;
|
||||
|
||||
if (supabase) {
|
||||
let { ko } = example.value;
|
||||
ko = ko.replaceAll("**", "");
|
||||
|
||||
supabase
|
||||
.from("sentence-explain")
|
||||
.select<any, { explain: string }>("explain")
|
||||
.eq("ko", ko)
|
||||
.then((r) => {
|
||||
if (!r.data?.[0]) return;
|
||||
exNotes.value = r.data[0].explain;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const vocabulary: Record<string, IVoc[]> = {};
|
||||
|
||||
for (const [k, vs] of Object.entries(
|
||||
@@ -400,7 +429,9 @@ const markdownIt = new MarkdownIt({
|
||||
typographer: true,
|
||||
});
|
||||
|
||||
async function explainSentence(s: string) {
|
||||
async function explainSentence(ko: string) {
|
||||
ko = ko.replaceAll("**", "");
|
||||
|
||||
for await (const data of LLMstream({
|
||||
model: "deepseek-v4-flash",
|
||||
messages: [
|
||||
@@ -409,14 +440,29 @@ async function explainSentence(s: string) {
|
||||
content:
|
||||
"Explain how this sentence works in 500 characters. Give key vocabularies.",
|
||||
},
|
||||
{ role: "user", content: s },
|
||||
{ role: "user", content: ko },
|
||||
],
|
||||
})) {
|
||||
if (data.done) return;
|
||||
if (data.done) break;
|
||||
if (data.content) {
|
||||
exNotes.value += data.content;
|
||||
}
|
||||
}
|
||||
|
||||
if (supabase) {
|
||||
console.log(supabase);
|
||||
const user_id = await supabase.auth.getUser().then((r) => r.data.user?.id);
|
||||
console.log(user_id);
|
||||
|
||||
await supabase.from("sentence-explain").upsert(
|
||||
{
|
||||
user_id,
|
||||
ko,
|
||||
explain: exNotes.value,
|
||||
},
|
||||
{ onConflict: "ko,user_id" },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function onModalClickOutside(ev: MouseEvent) {
|
||||
|
||||
@@ -71,7 +71,7 @@ vocabulary:
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson20v6.mp3
|
||||
en: powder
|
||||
examples:
|
||||
- ko: 케이크 반죽에 **밀가루**를 넣으세요
|
||||
- ko: 케이크 반죽에 밀**가루**를 넣으세요
|
||||
en: Put some **flour** into the cake batter, please
|
||||
- ko: 봄에는 꽃**가루** 알레르기를 조심해 야 해요
|
||||
en: You need to be careful about **pollen** allergies in the spring
|
||||
|
||||
Reference in new issue
Block a user