feat: make from lang optional (#1740)

This commit is contained in:
Stephen Zhou 2024-04-26 00:30:41 +08:00 committed by GitHub
parent 0eb018dc8c
commit 75e002f0ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 55 deletions

View File

@ -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
: "",
})
}
}

View File

@ -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,
}),
})
}

View File

@ -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({

View File

@ -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: {