feat: make from lang optional (#1740)
This commit is contained in:
parent
0eb018dc8c
commit
75e002f0ba
|
|
@ -4,20 +4,22 @@ import { getSummary } from "~/queries/page.server"
|
|||
export async function GET(req: Request): Promise<Response> {
|
||||
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
|
||||
: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import { getQuery, NextServerResponse } from "~/lib/server-helper"
|
||||
import { getSummary } from "~/queries/page.server"
|
||||
|
||||
export async function GET(req: Request): Promise<Response> {
|
||||
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,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
|
@ -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<ChainKeyType, LLMChain>()
|
||||
|
||||
const getOriginalTranslation = async (
|
||||
cid: string,
|
||||
targetLang: Language,
|
||||
): Promise<ContentTranslation | undefined> => {
|
||||
const getOriginalTranslation = async ({
|
||||
cid,
|
||||
toLang,
|
||||
fromLang,
|
||||
}: {
|
||||
cid: string
|
||||
toLang: Language
|
||||
fromLang?: Language
|
||||
}): Promise<ContentTranslation | undefined> => {
|
||||
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<ContentTranslation | undefined> {
|
||||
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<Response> {
|
|||
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({
|
||||
|
|
|
|||
|
|
@ -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<string, AnalyzeDocumentChain>()
|
||||
|
||||
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: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue