我們都知道AI 擅長文字處理,但礙於我們的德國網站運營規模相當的小,缺乏足夠的人力來維護SEO資料,我們利用AI的文字處理能力來自動生成SEO數據(包括標題、描述和關鍵字)。這種方法不僅節省了大量人力資源,而且通過將頁面預渲染時的數據傳送給AI處理,提升了網站的搜索引擎優化效率。
Bill Gates 曾說許多軟體「仍然相當愚蠢」,因為它們需要大量的人工輸入才能發揮作用,且他認為人工智慧 (AI) 代理,可以在未來五年內改變這一現狀。
從過去的滑鼠鍵盤輸入及僅接受明確的指令,到提供不同的交互方式,檔案、圖片、聲音、影像及讀懂人類模糊的指令,AI 的出現改變了人與電腦的互動方式,人與電腦的互動方式改變,所有的應用程式都值得用AI 改寫一次。
AI 之所以能夠讀懂上下文,其實每次都要將對話回傳回去,透過這個機制,我們能夠在請求AI前封裝AI, 扮演某特定的角色及可以做什麼不可以做什麼。
You are an SEO expert. Based on the page description provided below, generate an SEO-optimized title, meta description, and keywords. Ensure that the title is engaging and concise, the meta description summarizes the product effectively while enticing users to learn more, and the keywords are relevant to the product's features and market segment. Additionally, translate all content into the language specified by the given language code. Company:{companyDescription} Ecommerce Page Description: {description} Translate Target Language Code: {langCode} FormatInstructions: {formatInstructions}
透過結合 Next.js 的前端技術、Azure AI 的語言生成能力與 LangChain 的結構化輸出,我們能夠創建一個高效且自動化的流程來優化網站的 SEO 表現,這種方法不僅節省了人力資源,也因其精確和針對性的SEO 標籤生成,而提高了網站在搜尋引擎中的能見度和排名。
在 Next.js 中部署的 generateSEOMetadata
函數利用 Azure Chat OpenAI 和 LangChain 處理產品描述,並生成相應的標題、描述和關鍵詞。LangChain 的輸出解析器(Output Parser)確保從 AI 模型接收到的回應符合 SEO 的需求,只提取最關鍵的信息。
import { BaseOutputParser } from '@langchain/core/output_parsers'; import { ChatPromptTemplate } from '@langchain/core/prompts'; import { AzureChatOpenAI } from '@langchain/openai'; import { LogLevel } from '@utils/log/const-logging'; import { serverSideLog } from '@utils/log/server-side-log'; import { genOnceEncodedURI } from '@utils/product/gear'; import { RedisBase } from '@utils/redis/redis-base'; import { NextApiRequest, NextApiResponse } from 'next'; class CustomOutputParser extends BaseOutputParser<string[]> { async parse(output: any) { const result = output.replaceAll('```json', '').replaceAll('```', ''); // for gpt4 const json = await JSON.parse(result); return json; } getFormatInstructions() { return 'Only the title, description and keywords of the json structure are returned. example :{"title":"","description":"","keywords":""} Please delete any other unnecessary information. Such as python code, Python Flask API, etc. Give me json result. Do not send back any other information such as python code, Python Flask API, etc.'; } } async function generateSEOMetadata(description: string, langCode: string) { // https://{InstanceName}.openai.azure.com/openai/deployments/my-openai-deployment/ const model = new AzureChatOpenAI({ azureOpenAIApiKey: 'YOUR_AZURE_OPENAI_API_KEY', azureOpenAIApiDeploymentName: 'YOUR_DEPLOYMENT_NAME', // gpt4 azureOpenAIApiInstanceName: 'YOUR_INSTANCE_NAME', azureOpenAIApiVersion: '2024-02-01', // '2024-02-01', temperature: 0, // 控制模型生成的隨機性或創造性 maxTokens: 500, // 指定模型生成的回應中最大可用的 token(詞的數量) }); const prompt = ChatPromptTemplate.fromTemplate( ` You are an SEO expert. Based on the page description provided below, generate an SEO-optimized title, meta description, and keywords. Ensure that the title is engaging and concise, the meta description summarizes the product effectively while enticing users to learn more, and the keywords are relevant to the product's features and market segment. Additionally, translate all content into the language specified by the given language code. Company:{companyDescription} Ecommerce Page Description: {description} Translate Target Language Code: {langCode} FormatInstructions: {formatInstructions} ` ); const parser = new CustomOutputParser(); const companyDescription = `NXPower GmbH markets iBUYPOWER® Computer products in Germany, aiming to offer high-quality products at reasonable prices without compromising service. We produce custom-made PC systems tailored to individual or business needs, ensuring the best possible system within your budget. Each PC is built with care, reflecting our passion and profession. Every custom PC includes a 3-year pickup and return warranty, extensive testing, and a 24-hour burn-in test. Our sales team ensures you only pay for components you need, and our top IT technicians provide quick assistance for any issues. We create dream computers to impress and delight you for years. Partnering with experienced and successful online retailers, we benefit from excellent support. `; const chain = prompt.pipe(model).pipe(parser); const response = await chain.invoke({ companyDescription: companyDescription, description: description, langCode: langCode, formatInstructions: parser.getFormatInstructions(), }); return response; } export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { const { description = '', slug = '', forceUpdate = false, langCode = 'en' } = req.query; if (!description || !slug) { return res.status(400).json({ error: 'Description must be a valid string.' }); } const redis = new RedisBase(); const seoKey = 'SeoMata:' + langCode + ':' + genOnceEncodedURI(slug as string); const seoResult = await redis.get(seoKey); if (seoResult && !forceUpdate) { return res.status(200).json(JSON.parse(seoResult)); } // Process the description with Langchain and Azure AI const metadata = await generateSEOMetadata(description as string, langCode as string); await redis.setCacheKey(seoKey, JSON.stringify(metadata), -1); // Save the metadata by slug to the database // return data for pre-rendering res.status(200).json(metadata); } catch (err) { serverSideLog('SEO Schema Error' + JSON.stringify(err), LogLevel.Error); return res.status(500).json({ error: err }); } }
在 Next 14 app route , 在頁面中的 generateMetadata 呼叫封裝好的 Azure AI 的 api
export async function generateMetadata({ params }: Props): Promise<Metadata> { // 構建URL const pathname = new URL(headers().get('x-url')!).pathname; const productData: IStoreModel | null = await getStoreModelData(params.locale, params.slug); const description = generateTitleAndDescription(productData); if (description === '') { return generateDefaultMetadata(params.locale, params.slug); } const imageUrl = (productData && getAbsoluteImageUrl(productData.desc.info.image)) || ''; try { const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; const queryParams = new URLSearchParams({ description: description, langCode: params.locale, slug: pathname, // forceUpdate: 'true', }); const url = `${baseUrl}/api/lang-chain/seo-schema?${queryParams.toString()}`; // 獲取數據 const response = await fetch(url); const seoMeta = await response.json(); const image: ImageProps = { url: imageUrl, width: 640, height: 640, alt: seoMeta.title, }; // 返回Metadata return { title: seoMeta.title, keywords: seoMeta.keywords, description: seoMeta.description, openGraph: { title: seoMeta.title, description: seoMeta.description, ...(imageUrl && { images: image, }), }, twitter: { title: seoMeta.title, description: seoMeta.description, card: 'summary_large_image', }, }; } catch (e) { return generateDefaultMetadata(params.locale, pathname); } }
並在 Middleware 取得slug,並在header中傳遞
export default function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname; request.headers.set('x-url', request.nextUrl.href); return nextIntlMiddleware(request); }
PS. Langchain在JS 版本的,並不是太穩定,文件蠻多都有誤的或功能和python 比有少的,且在不同模型中會跑額外的字元,得自定解析器去處理,生態也不是這麼完整,如果複雜情境使用 python 版本會比較好。
http://www.xxxx.de/api/lang-chain/seo-schema?description={page description }&langCode={translate to lang code}
http://www.xxxx.de/api/lang-chain/seo-schema?description=Case:%20NZXT%20H5%20Flow%20Gaming%20Geh%C3%A4use%20-%20Schwarz%20Processor:%20AMD%20Ryzen%205%205600X%20Processor%20(6x%203.7GHz/32MB%20L3%20Cache)%20Memory:%2016GB%20DDR4/3200MHz%20Memory(G.Skill%20,Corsair,Kingston)%20Storage:%20Video%20Card:%20NVIDIA%20GeForce%20RTX%203050%20-%208GB%20GDDR6X%20(VR-Ready)%20Motherboard:%20ASRock%20B450%20PRO%204%20ATX%20USB%203.1,%20SATA3,%201x%20M.2&langCode=tw
{"title":"頂級遊戲體驗:NZXT H5 Flow 黑色遊戲機殼配備 AMD Ryzen 5 與 RTX 3050","meta_description":"探索 NZXT H5 Flow 遊戲機殼,搭載 AMD Ryzen 5 5600X 處理器、16GB DDR4 記憶體、NVIDIA GeForce RTX 3050 顯示卡,為您的遊戲體驗帶來革命性提升。立即了解更多。","keywords":"NZXT H5 Flow, 遊戲機殼, AMD Ryzen 5 5600X, 16GB DDR4, NVIDIA GeForce RTX 3050, VR準備, ASRock B450 PRO 4, 高性能遊戲電腦"}