Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

สร้างเครื่องแนะนำบทความแบบเรียลไทม์ด้วย Upstash และ Node.js

เคยใช้ Google หรือ Perplexity.ai ไหม? คุณเคยสงสัยไหมว่าพวกเขาแสดงผลการค้นหาที่ทันสมัยและมีลิงก์ไปยังบทความออนไลน์ได้อย่างไร? ในคู่มือนี้ คุณจะได้เรียนรู้วิธีสร้างระบบแบบนี้ด้วยตัวเอง ระบบที่สามารถสร้างคำแนะนำจากลิงก์บทความที่คุณเพิ่มเข้าไปในฐานความรู้ที่เพิ่มขึ้นเรื่อยๆ

ข้อกำหนดเบื้องต้น

  • Node.js 18 หรือใหม่กว่า
  • บัญชี Upstash
  • บัญชี OpenAI
  • บัญชี Fly.io

เทคโนโลยีที่ใช้

เทคโนโลยีคำอธิบาย
Upstashแพลตฟอร์มฐานข้อมูล Serverless ใช้ Upstash Vector สำหรับเก็บ vector embeddings และ metadata
Remixเฟรมเวิร์กสร้างแอปเว็บ full-stack เน้นมาตรฐานเว็บ
OpenAIห้องปฏิบัติการวิจัย AI พัฒนาเทคโนโลยี AI ขั้นสูง
LangChainเฟรมเวิร์กพัฒนาแอปพลิเคชันขับเคลื่อนด้วย language models
Vercel AI SDKไลบรารีโอเพนซอร์สสร้าง UI ขับเคลื่อนด้วย AI
TailwindCSSเฟรมเวิร์ก CSS สำหรับออกแบบที่ปรับแต่งได้
Fly.ioแพลตฟอร์มรันแอป full-stack และฐานข้อมูลใกล้ผู้ใช้
Prettierเครื่องมือจัดรูปแบบโค้ดแบบมีความคิดเห็น

ขั้นตอนการทำงาน

  • สร้าง OpenAI Token
  • สร้าง Upstash Vector Index
  • ตั้งค่าโปรเจกต์
  • สร้าง OpenAI API Client
  • สร้าง OpenAI API Embeddings Client
  • สร้าง Upstash Vector Client
  • สร้าง Context API Endpoint
  • สร้าง Chat API Endpoint
  • ปรับใช้งานบน Fly.io
  • อ้างอิง
  • สรุป

สร้าง OpenAI Token

ใช้ OpenAI API เพื่อดึง vector embeddings ของบทความ และสร้างคำตอบ chatbot ด้วย AI การร้องขอ OpenAI API ต้องใช้ authorization token ไปที่ API Keys ในบัญชี OpenAI กด Create new secret key คัดลอกและเก็บไว้เป็นตัวแปรสภาพแวดล้อม OPENAI_API_KEY

สร้าง Upstash Vector Index

เข้าสู่ระบบ Upstash ไปที่แท็บ Vector กด Create Index

สร้างเครื่องแนะนำบทความแบบเรียลไทม์ด้วย Upstash และ Node.js

ใส่ชื่อ index (เช่น article) และตั้งค่า vector dimensions = 1536

สร้างเครื่องแนะนำบทความแบบเรียลไทม์ด้วย Upstash และ Node.js

เลื่อนลงส่วน Connect กดปุ่ม .env คัดลอกเก็บไว้

สร้างเครื่องแนะนำบทความแบบเรียลไทม์ด้วย Upstash และ Node.js

ตั้งค่าโปรเจกต์

โคลน repo และติดตามคู่มือ:

# Clone the project
git clone https://github.com/rishi-raj-jain/article-recommendation-system
cd article-recommendation-system
# Install dependencies
pnpm install

สร้างไฟล์ .env ใส่ secret keys:

# .env
# OpenAI API Key
OPENAI_API_KEY="sk-..."
# Upstash Vector Keys
UPSTASH_VECTOR_REST_URL="https://...-us1-vector.upstash.io"
UPSTASH_VECTOR_REST_TOKEN="...="

รันแอปพลิเคชัน:

pnpm run build && pnpm run start

เข้าไปที่ localhost:3000

สร้าง OpenAI API Client

ใช้แพ็กเกจ openai สร้างไฟล์ app/lib/openai/completion.server.ts:

// File: app/lib/openai/completion.server.ts
import OpenAI from 'openai'

export default new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
})

หมายเหตุ: การเติม .server.ts ใน Remix ทำให้โค้ดอยู่ฝั่งเซิร์ฟเวอร์เท่านั้น

สร้าง OpenAI API Embeddings Client

ใช้ @langchain/openai สร้างไฟล์ app/lib/openai/embedding.server.ts:

// File: app/lib/openai/embedding.server.ts
import { OpenAIEmbeddings } from '@langchain/openai'

export default new OpenAIEmbeddings({
  modelName: 'text-embedding-3-small',
  openAIApiKey: process.env.OPENAI_API_KEY,
})

สร้าง Upstash Vector Client

ใช้ @upstash/vector และ @langchain/community/vectorstores/upstash สร้างไฟล์ app/lib/upstash/vectorStore.server.ts:

// File: app/lib/upstash/vectorStore.server.ts
import embeddings from '~/lib/openai/embedding.server'
import { Index as UpstashIndex } from '@upstash/vector'
import { UpstashVectorStore } from '@langchain/community/vectorstores/upstash'

const index = new UpstashIndex({
  url: process.env.UPSTASH_VECTOR_REST_URL as string,
  token: process.env.UPSTASH_VECTOR_REST_TOKEN as string,
})

export default new UpstashVectorStore(embeddings, { index })

สร้าง Context API Endpoint

Endpoint app/routes/api_.context.tsx รับ URL บทความหลายๆ อัน ดึงเนื้อหา สร้าง embeddings เก็บใน Upstash Vector Index:

// File: app/routes/api_.context.tsx
import { Document } from 'langchain/document'
import { ActionFunctionArgs } from '@remix-run/node'
import vectorServer from '~/lib/vector/vectorStore.server'
import { CheerioWebBaseLoader } from 'langchain/document_loaders/web/cheerio'

export const action = async ({ request }: ActionFunctionArgs) => {
  const formData = await request.formData()
  const articlesToEmbed = formData.get('articles') as string
  
  if (articlesToEmbed) {
    const documents: any[] = []
    await Promise.all(
      articlesToEmbed.split(',').map(async (link) => {
        const loader = new CheerioWebBaseLoader(link.trim())
        const scraper = await loader.scrape()
        const name = scraper('title').html()
        const pageContent = scraper.text()
        const metadata = { link, name }
        documents.push(new Document({ pageContent, metadata }))
      }),
    )
    await vectorServer.addDocuments(documents.filter(Boolean))
  }
}

Remix Action นี้ parse form data วนลูป URL บทความ (คั่นด้วย comma):

  • สร้าง pageContent จากข้อความในหน้าเว็บ
  • สร้าง name จาก title ของหน้าเว็บ
  • สร้าง LangChain Document พร้อม metadata
  • เพิ่มใน array documents

สุดท้าย insert ทุก document เข้า Upstash Vector Index (สร้าง embeddings อัตโนมัติจาก pageContent)

สร้าง Chat API Endpoint

Endpoint app/routes/api_.chat.tsx สร้างคำตอบแบบ search engine พร้อมคำแนะนำบทความที่เกี่ยวข้อง ค้นหา top-K vectors ใกล้เคียง ส่ง title และ link จาก metadata ไปให้ OpenAI เป็น context

ค้นหา Vector Embeddings ที่เกี่ยวข้องด้วย Similarity Search

// File: app/routes/api_.chat.tsx
import vectorServer from '~/lib/upstash/vectorStore.server'
import type { ActionFunctionArgs } from '@remix-run/node'

export const action = async ({ request }: ActionFunctionArgs) => {
  const { messages = [] } = await request.json()
  const searchQuery = messages[messages.length - 1].content
  
  const queryResult = await vectorServer.similaritySearchWithScore(searchQuery, 3)
  const results = queryResult.filter(i => i[1] >= 0.7).map(i => i[0].metadata)
  
  // สร้างคำตอบต่อไป...
}

สร้าง System Context และ Instructions สำหรับ Chatbot

สร้าง system message ให้ chatbot รู้จักบทความที่เกี่ยวข้อง ก่อนตอบคำถาม ใช้ gpt-3.5-turbo:

// File: app/routes/api_.train.tsx
import { OpenAIStream, StreamingTextResponse } from 'ai'
import completionServer from '~/lib/openai/completion.server'

export const action = async ({ request }: ActionFunctionArgs) => {
  // ...
  const completionResponse = await completionServer.chat.completions.create({
    stream: true,
    model: 'gpt-3.5-turbo',
    messages: [
      {
        role: 'system',
        content: `Behave like a Google. You have the knowledge of the following articles: ${JSON.stringify(results)}. Each response should be in 100% markdown compatible format and should have hyperlinks in it. Be precise. Do add some general text in the response related to the query.`,
      },
      ...messages,
    ],
  })
  
  const stream = OpenAIStream(completionResponse)
  return new StreamingTextResponse(stream)
}

ปรับใช้งานบน Fly.io

Repo มีการตั้งค่าสำหรับ Fly.io แล้ว (Dockerfile, fly.toml, .dockerignore)

# สร้างแอปใน Fly.io
fly launch
# ปรับใช้งาน
fly deploy

อ้างอิง

  • GitHub Repository
  • Upstash Vector Store Integration with LangChain
  • System Instructions in OpenAI's Chat Completions API
  • Load data from webpages using Cheerio in LangChain
  • Creating AI Chat UI in React apps

สรุป

ในคู่มือนี้ คุณได้เรียนรู้การสร้างระบบแนะนำบทความด้วย Vector Embeddings และ OpenAI Completion API พร้อม system context ที่สร้างแบบไดนามิก ด้วย Upstash Vector และ LangChain คุณสามารถเก็บ vectors ใน index ค้นหา top-K vector queries และสร้าง context ที่เกี่ยวข้องสำหรับแต่ละคำค้นหาได้ทั้งหมดในไม่กี่บรรทัดของโค้ด

หากมีคำถามหรือความคิดเห็น สามารถติดต่อผมได้ที่ GitHub