Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Redis

Tạo Công cụ đề xuất bài viết theo thời gian thực với Upstash &Node.js

Bạn đã sử dụng Google hoặc Perplexity.ai chưa? Bạn có thắc mắc làm thế nào họ có thể hiển thị kết quả tìm kiếm mới nhất và bao gồm các liên kết đến các bài viết trực tuyến không? Chà, trong hướng dẫn này, bạn sẽ học cách tự mình tạo ra một hệ thống như vậy. Bạn sẽ tìm hiểu cách tạo một hệ thống có thể tạo đề xuất dựa trên liên kết của các bài viết mà bạn thêm vào ngân hàng kiến thức đang phát triển của nó.

Điều kiện tiên quyết

Bạn sẽ cần những thứ sau:

  • Node.js 18 trở lên
  • Tài khoản Upstash
  • Tài khoản OpenAI
  • Tài khoản Fly.io

Ngăn xếp công nghệ

Công nghệ Mô tả Nền tảng cơ sở dữ liệu UpstashServerless. Bạn sẽ sử dụng Upstash Vector để lưu trữ siêu dữ liệu và phần nhúng vectơ.RemixFramework để xây dựng các ứng dụng web đầy đủ tập trung vào Tiêu chuẩn web.OpenAIAn phòng thí nghiệm nghiên cứu trí tuệ nhân tạo tập trung vào phát triển các công nghệ AI tiên tiến.LangChainFramework để phát triển các ứng dụng được cung cấp bởi các mô hình ngôn ngữ.Vercel AI SDKMột thư viện nguồn mở để xây dựng các giao diện người dùng được hỗ trợ bởi AI.Khung TailwindCSSCSS để xây dựng các thiết kế tùy chỉnh.Nền tảng Fly.ioA để chạy các ứng dụng và cơ sở dữ liệu ngăn xếp đầy đủ gần bạn user.PrettierTrình định dạng mã được chọn lọc để có kiểu mã nhất quán.

Các bước

Để hoàn thành hướng dẫn này và triển khai hệ thống đề xuất bài viết của riêng bạn, bạn cần làm theo các bước sau:

  • Tạo mã thông báo OpenAI
  • Tạo chỉ mục vectơ Upstash
  • Thiết lập dự án
  • Khởi tạo ứng dụng khách API OpenAI
  • Tạo ứng dụng khách nhúng API OpenAI
  • Tạo ứng dụng khách Vector Upstash
  • Tạo Điểm cuối API ngữ cảnh
  • Tạo Điểm cuối API trò chuyện
  • Triển khai để Fly.io
  • Tài liệu tham khảo
  • Kết luận

Tạo mã thông báo OpenAI

Bằng cách sử dụng API OpenAI, bạn có thể lấy các phần nhúng vectơ của bài viết và tạo phản hồi chatbot bằng AI. Mọi yêu cầu đối với API OpenAI đều yêu cầu mã thông báo ủy quyền. Để nhận mã thông báo, hãy điều hướng đến Khóa API trong tài khoản OpenAI của bạn và nhấp vào Tạo khóa bí mật mới nút. Sao chép và lưu trữ an toàn mã thông báo này để sử dụng sau dưới dạng OPENAI_API_KEY biến môi trường.

Tạo chỉ mục vectơ Upstash

Khi bạn đã tạo tài khoản Upstash và đăng nhập, hãy chuyển đến tab Vector và nhấp vào Tạo chỉ mục để bắt đầu tạo chỉ mục vector.

Tạo Công cụ đề xuất bài viết theo thời gian thực với Upstash &Node.js

Nhập tên chỉ mục bạn chọn (giả sử article ) và đặt kích thước vectơ là 1536.

Tạo Công cụ đề xuất bài viết theo thời gian thực với Upstash &Node.js

Bây giờ, hãy cuộn xuống cho đến phần Kết nối và nhấp vào .env nút. Sao chép nội dung và lưu nó ở nơi an toàn để sử dụng thêm trong ứng dụng của bạn.

Tạo Công cụ đề xuất bài viết theo thời gian thực với Upstash &Node.js

Thiết lập dự án

Để thiết lập, chỉ cần sao chép kho ứng dụng và làm theo hướng dẫn này để tìm hiểu mọi thứ có trong đó. Để sao chép dự án, hãy chạy lệnh sau trong terminal:

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

Khi bạn đã sao chép kho lưu trữ, hãy tạo .env tập tin. Bạn sẽ thêm các khóa bí mật thu được trong các phần trên.

.env tập tin phải chứa các khóa sau:

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

Khi đã xong, quá trình thiết lập cấu hình của bạn đã hoàn tất. Bây giờ, bạn có thể xem ứng dụng đang hoạt động bằng cách thực hiện lệnh sau trong thiết bị đầu cuối của mình và truy cập localhost:3000.

pnpm run build && pnpm run start

Hãy theo dõi để hiểu các phần liên quan của mã cho phép bạn xây dựng thành công hệ thống đề xuất bài viết của riêng mình.

Khởi tạo ứng dụng khách API OpenAI

Với openai gói, bạn có thể tiết kiệm thời gian và tương tác với OpenAI REST API chỉ trong vài dòng mã. Với đoạn mã sau, chúng tôi đã khởi tạo thư viện Ứng dụng khách API OpenAI để sử dụng thêm nhằm tạo phản hồi hoàn thành cuộc trò chuyện.

// File: app/lib/openai/completion.server.ts
 
import OpenAI from 'openai'
 
// Instantiate class to generate text completion using the OpenAI API
export default new OpenAI({
 apiKey: process.env.OPENAI_API_KEY,
})

Lưu ý:Bằng cách thêm .server.ts đối với một tệp trong Remix, bạn có thể đảm bảo rằng mã của nó bị buộc loại bỏ của gói phía máy khách.

Tạo ứng dụng khách nhúng API OpenAI

Với @langchain/openai gói, bạn có thể sử dụng OpenAIEmbeddings lớp để tạo các vectơ nhúng của một văn bản nhất định. Khi được kết hợp với bất kỳ Cửa hàng Vector LangChain nào, lớp OpenAIEmbeddings sẽ giúp bạn tránh khỏi quá trình tạo và chèn từng vectơ nhúng của riêng bạn. Với đoạn mã sau, chúng tôi đã khởi tạo lớp OpenAIEmbeddings để sử dụng thêm nhằm tạo các phần nhúng vectơ bên trong.

// File: app/lib/openai/embedding.server.ts
 
import { OpenAIEmbeddings } from '@langchain/openai'
 
// Instantiate class to generate embeddings using the OpenAI API
export default new OpenAIEmbeddings({
 modelName: 'text-embedding-3-small',
 openAIApiKey: process.env.OPENAI_API_KEY,
})

Tạo ứng dụng khách Upstash Vector

Sử dụng @upstash/vector@langchain/community/vectorstores/upstash gói, bạn có thể tạo một ứng dụng khách không kết nối trong ứng dụng Remix của mình, cho phép bạn lưu trữ, xóa và truy vấn các phần nhúng vectơ từ chỉ mục Upstash Vector.

// 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'
 
// Instantiate the Upstash Vector Index
const index = new UpstashIndex({
 url: process.env.UPSTASH_VECTOR_REST_URL as string,
 token: process.env.UPSTASH_VECTOR_REST_TOKEN as string,
})
 
// Instantiate the Upstash Vector Store that'll create and save embeddings
export default new UpstashVectorStore(embeddings, { index })

Tạo Điểm cuối API ngữ cảnh

Khi chạy ứng dụng Remix, bạn sẽ thấy một hộp văn bản chấp nhận nhiều URL bài viết làm đầu vào. Những bài viết đó sẽ được bổ sung vào kiến ​​thức của chatbot để tạo ra phản hồi được cá nhân hóa trong các tìm kiếm của người dùng trong tương lai. Trong phần này, bạn sẽ tìm hiểu cách điểm cuối ngữ cảnh (app/routes/api_.context.tsx ) được thiết lập để chấp nhận nhiều URL bài viết đó, tìm nạp nội dung của chúng, tạo các phần nhúng vectơ của chúng và lưu trữ chúng vào Chỉ mục Vector Upstash một cách linh hoạt.

// 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()
 // Check if any article link are present in the form submission
 const articlesToEmbed = formData.get('articles') as string
 if (articlesToEmbed) {
 // Create the documents to be added to the Upstash Vector Store
 const documents: any[] = []
 await Promise.all(
 articlesToEmbed.split(',').map(async (link) => {
 // Use the link to render in the search results
 // Parse the link using Cheerio
 const loader = new CheerioWebBaseLoader(link.trim())
 const scraper = await loader.scrape()
 // Get the content of title tag to render in the search results
 const name = scraper('title').html()
 // Get the page content as string
 const pageContent = scraper.text()
 // Create metadata object to be inserted in the vector store
 const metadata = { link, name }
 documents.push(new Document({ pageContent, metadata }))
 }),
 )
 // Creating embeddings from the provided documents along with metadata
 // and add them to Upstash database
 await vectorServer.addDocuments(documents.filter(Boolean))
 }
}

Trong Hành động phối lại ở trên, dữ liệu biểu mẫu có trong yêu cầu POST tới điểm cuối ngữ cảnh (/api/context ) được phân tích cú pháp. Hơn nữa, có một vòng lặp trên tập hợp các liên kết bài viết được phân tách bằng dấu phẩy (,) thực hiện như sau:

  • Tạo một pageContent biến khi nội dung văn bản được tìm nạp từ trang web của bài viết
  • Tạo một name biến làm tiêu đề trang web của bài viết
  • Tạo Tài liệu LangChain với nội dung văn bản, tài liệu tham khảo và tên bài viết (new Document({ pageContent, metadata }) )
  • Thêm từng tài liệu vào documents toàn cục mảng

Cuối cùng, tất cả các tài liệu được lưu trữ trong documents toàn cục mảng được chèn vào Chỉ mục Vector Upstash. Dưới lớp vỏ bọc, các phần nhúng vectơ cho mỗi tài liệu được tạo bằng cách sử dụng pageContent của nó tài sản.

Tạo Điểm cuối API trò chuyện

Trong phần này, bạn sẽ tìm hiểu cách điểm cuối api trò chuyện (app/routes/api_.chat.tsx ) được thiết lập để tạo các phản hồi giống như công cụ tìm kiếm chứa các đề xuất cho các bài viết có liên quan đến tìm kiếm của người dùng. Các bài viết liên quan đến tìm kiếm được tìm thấy bằng cách tìm các vectơ top-K gần nhất từ ​​một chỉ mục vectơ nhất định. Hơn nữa, tiêu đề và liên kết từ siêu dữ liệu của vectơ được chuyển vào API OpenAI dưới dạng ngữ cảnh. Điều này cho phép chatbot bao gồm các bài viết dưới dạng liên kết bên ngoài kết hợp với việc phản hồi tìm kiếm của người dùng. Để đơn giản hóa mọi thứ, chúng tôi sẽ chia phần này thành các phần khác:

Tìm các vectơ nhúng có liên quan bằng cách sử dụng tìm kiếm tương tự

Việc xem lại toàn bộ ngân hàng kiến thức các bài báo cho mỗi lần tìm kiếm của người dùng là một hoạt động tốn kém. Để giới hạn nó trong 3 bài viết hàng đầu (nếu) có liên quan cao đến tìm kiếm của người dùng, hãy truy vấn tập hợp vectơ hiện có trong Chỉ mục vectơ Upstash của bạn. Hơn nữa, hãy lọc để giữ lại các vectơ có phần nhúng có điểm tương đồng ít nhất 70% với phần nhúng vectơ trong tìm kiếm của người dùng.

// 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) => {
 
 // Set of messages between user and chatbot
 const { messages = [] } = await request.json()
 
 // Get the latest question stored in the last message of the chat array
 const searchQuery = messages[messages.length - 1].content
 
 // Perform Similarity Search using the Upstash Vector Store
 const queryResult = await vectorServer.similaritySearchWithScore(searchQuery, 3)
 
 // Filter the records with confidence score > 70% and
 // set the metadata as response to render search results
 const results = queryResult.filter((i) => i[1] >= 0.7).map((i) => i[0].metadata)
 
 // Proceed to create a response
}

Tạo bối cảnh hệ thống và hướng dẫn cho Chatbot

Bây giờ bạn đã có được tập hợp các vectơ có mức độ liên quan cao, bạn muốn chatbot biết và tham khảo các bài viết được liên kết trước khi nó phản hồi tìm kiếm của người dùng. Để làm được điều đó với gpt-3.5-turbo của OpenAI mô hình, tạo một đối tượng tin nhắn với thuộc tính vai trò là system và thuộc tính nội dung chứa các hướng dẫn sau:

  • Chatbot sẽ phản hồi giống như Google
  • Chatbot phải đảm bảo rằng phản hồi ở định dạng đánh dấu
  • Phản hồi của chatbot phải có siêu liên kết đến bài viết
  • Chatbot không chỉ bao gồm các tài liệu tham khảo cho các bài viết
// File: app/routes/api_.train.tsx
 
import { OpenAIStream, StreamingTextResponse } from 'ai'
import completionServer from '~/lib/openai/completion.server'
 
export const action = async ({ request }: ActionFunctionArgs) => {
 // ...
 
 // Now use OpenAI Text Completion with relevant articles as context
 const completionResponse = await completionServer.chat.completions.create({
 stream: true,
 model: 'gpt-3.5-turbo',
 messages: [
 {
 // create a system content message to be added as
 // the open ai text completion will supply it as the context with the API
 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.`,
 },
 // also, pass the whole conversation!
 ...messages,
 ],
 })
 
 // Convert the response into a friendly text-stream
 const stream = OpenAIStream(completionResponse)
 // Respond with the stream
 return new StreamingTextResponse(stream)
}
 

Với mã ở trên, bạn có thể truyền trực tuyến các kết quả từ OpenAI có nhận biết ngữ cảnh, đề xuất các bài viết có liên quan đến tìm kiếm của người dùng.

Đó là rất nhiều học hỏi! Bây giờ bạn đã hoàn tất ✨

Triển khai lên Fly.io

Kho lưu trữ đi kèm với thiết lập sẵn có cho Fly.io, đặc biệt liên quan đến:

  • Tệp Docker
  • fly.toml
  • .dockerignore

Sau khi có tài khoản Fly.io, bạn có thể tạo ứng dụng trong Fly.io bằng cách thực hiện lệnh sau trong thiết bị đầu cuối của mình ở thư mục gốc:

# Create an app based on the baked-in configuration in your account
# This will result only in the change of app name in existing fly.toml
 
fly launch

và triển khai lên Fly.io thực thi lệnh sau trong thiết bị đầu cuối của bạn:

# Deploy the app based on the configuration created above
 
fly deploy

Tài liệu tham khảo

Để biết thêm thông tin chi tiết, hãy khám phá các tài liệu tham khảo được sử dụng trong hướng dẫn này.

  • Kho lưu trữ GitHub
  • Tích hợp cửa hàng Vector Upstash với LangChain
  • Hướng dẫn hệ thống trong API hoàn thành trò chuyện của OpenAI
  • Tải dữ liệu từ các trang web bằng Cheerio trong LangChain
  • Tạo giao diện người dùng trò chuyện AI trong ứng dụng React

Kết luận

Trong hướng dẫn này, bạn đã học cách xây dựng hệ thống đề xuất bài viết bằng cách sử dụng Vector Embeddings và API hoàn thành OpenAI với ngữ cảnh hệ thống được tạo động. Với Upstash Vector và LangChain, bạn có khả năng lưu trữ vectơ trong một chỉ mục, thực hiện các truy vấn tìm kiếm vectơ top-K và tạo ngữ cảnh phù hợp cho mỗi tìm kiếm của người dùng, tất cả chỉ trong vài dòng mã.

Nếu bạn có bất kỳ câu hỏi hoặc nhận xét nào, vui lòng liên hệ với tôi trên GitHub.