diff --git a/src/app/api/ai-summary/route.ts b/src/app/api/ai-summary/route.ts index b31dd1a2..fb9e1516 100644 --- a/src/app/api/ai-summary/route.ts +++ b/src/app/api/ai-summary/route.ts @@ -4,20 +4,22 @@ import { getSummary } from "~/queries/page.server" export async function GET(req: Request): Promise { const query = getQuery(req) const res = new NextServerResponse() - if (!query.cid || typeof query.cid !== "string") { + if (!query.cid) { return res.status(400).json({ error: "Missing cid" }) } - if (!query.lang || typeof query.lang !== "string") { - return res.status(400).json({ error: "Missing lang" }) - } try { const summary = await getSummary({ cid: query.cid, - lang: query.lang, + lang: String(query.lang), }) return res.status(200).json({ summary }) } catch (error) { - return res.status(500).json({ error: "Could not get summary" }) + return res.status(500).json({ + error: + "Could not get summary for" + query.cid + query.lang + ? " in " + query.lang + : "", + }) } } diff --git a/src/app/api/summary/route.ts b/src/app/api/summary/route.ts deleted file mode 100644 index 68498545..00000000 --- a/src/app/api/summary/route.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getQuery, NextServerResponse } from "~/lib/server-helper" -import { getSummary } from "~/queries/page.server" - -export async function GET(req: Request): Promise { - let { cid, lang } = getQuery(req) - const res = new NextServerResponse() - - if (!cid) { - return res.status(400).send("Bad Request") - } - - return res.status(200).json({ - data: await getSummary({ - cid, - lang, - }), - }) -} diff --git a/src/app/api/translate-note/route.ts b/src/app/api/translate-note/route.ts index 39a696d4..7c517a65 100644 --- a/src/app/api/translate-note/route.ts +++ b/src/app/api/translate-note/route.ts @@ -6,6 +6,7 @@ import { PromptTemplate } from "langchain/prompts" import { Metadata } from "@prisma/client" import { languageNames } from "~/i18n" +import { detectLanguage } from "~/lib/detect-lang" import { toGateway } from "~/lib/ipfs-parser" import { llmModelSwitcherByTextLength } from "~/lib/llm-model-switcher-by-text-length" import prisma from "~/lib/prisma.server" @@ -38,10 +39,17 @@ if (process.env.OPENAI_API_KEY) { type ChainKeyType = `${4 | 16}k_${Language}` // e.g. "4k_en" | "4k_zh" | "4k_zh-TW" | "4k_ja" | "16k_en" | "16k_zh" | "16k_zh-TW" | "16k_ja" const translationChains = new Map() -const getOriginalTranslation = async ( - cid: string, - targetLang: Language, -): Promise => { +const getOriginalTranslation = async ({ + cid, + toLang, + fromLang, +}: { + cid: string + toLang: Language + fromLang?: Language +}): Promise => { + if (fromLang === toLang) return + if (!translationModel4K || !translationModel16K) return try { @@ -49,19 +57,21 @@ const getOriginalTranslation = async ( await fetch(toGateway(`ipfs://${cid}`)) ).json() - console.time(`fetching translation ${cid}, ${targetLang}`) + if (!fromLang && detectLanguage(title + content) === toLang) return + + console.time(`fetching translation ${cid}, ${toLang}`) const { modelSize, tokens } = llmModelSwitcherByTextLength(content, { - includeResponse: { lang: targetLang }, + includeResponse: { lang: toLang }, }) if (!modelSize) { console.error( - `|__ Error: Content too long for translation: ${cid}, ${targetLang}. (Tokens: ${tokens})`, + `|__ Error: Content too long for translation: ${cid}, ${toLang}. (Tokens: ${tokens})`, ) return } - let chain = translationChains.get(`${modelSize}_${targetLang}`) + let chain = translationChains.get(`${modelSize}_${toLang}`) if (!chain) { const template = ` @@ -81,7 +91,7 @@ You are a Markdown translation expert. During the translation process, you need IMPORTANT: ONLY RETURN TRANSLATED TEXT AND NOTHING ELSE. -Translate the following text to ${languageNames[targetLang]} language: +Translate the following text to ${languageNames[toLang]} language: {text} ` @@ -96,7 +106,7 @@ Translate the following text to ${languageNames[targetLang]} language: chain = new LLMChain({ llm: translateModel, prompt }) - translationChains.set(`${modelSize}_${targetLang}`, chain) + translationChains.set(`${modelSize}_${toLang}`, chain) } const t = @@ -109,7 +119,7 @@ Translate the following text to ${languageNames[targetLang]} language: ? { text: "" } : await chain.call({ text: content }) - console.timeEnd(`fetching translation ${cid}, ${targetLang}`) + console.timeEnd(`fetching translation ${cid}, ${toLang}`) return { title: t.text, @@ -117,23 +127,19 @@ Translate the following text to ${languageNames[targetLang]} language: } } catch (error) { console.error(error) - console.timeEnd(`fetching translation ${cid}, ${targetLang}`) + console.timeEnd(`fetching translation ${cid}, ${toLang}`) } } async function getTranslation({ cid, + toLang, fromLang, - toLang = "en", }: { cid: string + toLang: Language fromLang?: Language - toLang?: Language }): Promise { - if (fromLang === toLang) { - return undefined - } - const translatedContent = (await cacheGet({ key: ["translation", cid, toLang], allowEmpty: true, @@ -159,7 +165,11 @@ async function getTranslation({ if (translatedJson) { result = translatedJson } else { - const newTranslation = await getOriginalTranslation(cid, toLang) + const newTranslation = await getOriginalTranslation({ + cid, + toLang, + fromLang, + }) if (newTranslation) { /** * e.g. @@ -215,7 +225,11 @@ export async function GET(req: Request): Promise { const res = new NextServerResponse() if (!cid) { - return res.status(400).send("Bad Request") + return res.status(400).json({ error: "Missing cid" }) + } + + if (!toLang) { + return res.status(400).json({ error: "Missing toLang" }) } return res.status(200).json({ diff --git a/src/queries/page.server.ts b/src/queries/page.server.ts index 0211c3c4..61ab12c5 100644 --- a/src/queries/page.server.ts +++ b/src/queries/page.server.ts @@ -7,7 +7,8 @@ import removeMarkdown from "remove-markdown" import { Metadata } from "@prisma/client" import { QueryClient } from "@tanstack/react-query" -import { defaultLocale, locales } from "~/i18n" +import { locales } from "~/i18n" +import { detectLanguage } from "~/lib/detect-lang" import { toGateway } from "~/lib/ipfs-parser" import prisma from "~/lib/prisma.server" import { cacheGet } from "~/lib/redis.server" @@ -85,7 +86,13 @@ if (process.env.OPENAI_API_KEY) { } const chains = new Map() -const getOriginalSummary = async (cid: string, lang: string) => { +const getOriginalSummary = async ({ + cid, + lang, +}: { + cid: string + lang?: string +}) => { if (!model) return try { let { content } = await (await fetch(toGateway(`ipfs://${cid}`))).json() @@ -96,12 +103,13 @@ const getOriginalSummary = async (cid: string, lang: string) => { if (content?.length < 200) { return } else if (content) { - console.time(`fetching summary ${cid}, ${lang}`) + const summaryLang = lang ?? detectLanguage(content) + console.time(`fetching summary ${cid}, ${summaryLang}`) - let chain = chains.get(lang) + let chain = chains.get(summaryLang) if (!chain) { const prompt = new PromptTemplate({ - template: `Summarize this in "${lang}" language: + template: `Summarize this in "${summaryLang}" language: "{text}" CONCISE SUMMARY:`, inputVariables: ["text"], @@ -117,7 +125,7 @@ const getOriginalSummary = async (cid: string, lang: string) => { combineDocumentsChain: combineDocsChain, }) - chains.set(lang, chain) + chains.set(summaryLang, chain) } const res = await chain.call({ @@ -138,7 +146,7 @@ const lock = new AsyncLock() export async function getSummary({ cid, - lang = defaultLocale, + lang, }: { cid: string lang?: string @@ -149,7 +157,7 @@ export async function getSummary({ noUpdate: true, noExpire: true, getValueFun: async () => { - if (locales.includes(lang as Language)) { + if (!lang || locales.includes(lang as Language)) { let result await lock.acquire(cid, async () => { const meta = await prisma.metadata.findFirst({ @@ -157,12 +165,12 @@ export async function getSummary({ uri: `ipfs://${cid}`, }, }) - const key = `ai_summary_${lang.replace("-", "").toLowerCase()}` + const key = `ai_summary_${lang?.replace("-", "").toLowerCase()}` if (meta) { if (meta?.[key as keyof Metadata]) { result = meta?.[key as keyof Metadata] } else { - const summary = await getOriginalSummary(cid, lang) + const summary = await getOriginalSummary({ cid, lang }) if (summary) { await prisma.metadata.update({ where: { @@ -176,7 +184,7 @@ export async function getSummary({ } } } else { - const summary = await getOriginalSummary(cid, lang) + const summary = await getOriginalSummary({ cid, lang }) if (summary) { await prisma.metadata.create({ data: {