คุณเคยใช้ Google หรือ Perplexity.ai หรือไม่? คุณสงสัยหรือไม่ว่าพวกเขาสามารถแสดงผลการค้นหาล่าสุดและรวมลิงก์ไปยังบทความออนไลน์ได้อย่างไร ในคู่มือนี้คุณจะได้เรียนรู้วิธีสร้างระบบดังกล่าวด้วยตัวเอง คุณจะได้เรียนรู้วิธีสร้างระบบที่สามารถสร้างคำแนะนำตามลิงก์ของบทความที่คุณเพิ่มลงในคลังความรู้ที่กำลังเติบโต
ข้อกำหนดเบื้องต้น
คุณจะต้องมีสิ่งต่อไปนี้:
- Node.js 18 หรือใหม่กว่า
- บัญชี Upstash
- บัญชี OpenAI
- บัญชี Fly.io
กลุ่มเทคโนโลยี
ขั้นตอน
หากต้องการทำตามคำแนะนำนี้ให้ครบถ้วนและปรับใช้ระบบการแนะนำบทความของคุณเอง คุณจะต้องทำตามขั้นตอนเหล่านี้:
- สร้างโทเค็น OpenAI
- สร้างดัชนีเวกเตอร์ขั้นสูง
- ตั้งค่าโครงการ
- สร้างอินสแตนซ์ไคลเอนต์ OpenAI API
- สร้างไคลเอ็นต์การฝัง OpenAI API
- สร้าง Upstash Vector Client
- สร้างจุดสิ้นสุด Context API
- สร้างปลายทาง Chat API
- ปรับใช้กับ Fly.io
- ข้อมูลอ้างอิง
- บทสรุป
สร้างโทเค็น OpenAI
เมื่อใช้ OpenAI API คุณสามารถรับการฝังเวกเตอร์ของบทความ และสร้างการตอบกลับแชทบอทโดยใช้ AI คำขอใดๆ ไปยัง OpenAI API จำเป็นต้องมีโทเค็นการอนุญาต หากต้องการรับโทเค็น ให้ไปที่คีย์ API ในบัญชี OpenAI ของคุณ แล้วคลิกสร้างคีย์ลับใหม่ ปุ่ม คัดลอกและจัดเก็บโทเค็นนี้อย่างปลอดภัยเพื่อใช้ในภายหลังเป็น OPENAI_API_KEY ตัวแปรสภาพแวดล้อม
สร้างดัชนีเวกเตอร์ขั้นสูง
เมื่อคุณสร้างบัญชี Upstash และเข้าสู่ระบบแล้ว ให้ไปที่แท็บ Vector และคลิกที่ สร้างดัชนี เพื่อเริ่มสร้างดัชนีเวกเตอร์

ป้อนชื่อดัชนีที่คุณต้องการ (เช่น 05 ) และตั้งค่าขนาดเวกเตอร์ให้เป็น 1536

ตอนนี้ เลื่อนลงไปจนถึง เชื่อมต่อ แล้วคลิก .env ปุ่ม คัดลอกเนื้อหาและบันทึกไว้ในที่ที่ปลอดภัยเพื่อใช้ในแอปพลิเคชันของคุณเพิ่มเติม

ตั้งค่าโครงการ
หากต้องการตั้งค่า เพียงโคลน repo ของแอปแล้วทำตามคำแนะนำนี้เพื่อเรียนรู้ทุกอย่างที่อยู่ในนั้น หากต้องการโคลนโปรเจ็กต์ ให้รันสิ่งต่อไปนี้ในเทอร์มินัล:
# Clone the project
git clone https://github.com/rishi-raj-jain/article-recommendation-system
cd article-recommendation-system
# Install the dependencies
pnpm install
เมื่อคุณโคลน repo แล้ว ให้สร้าง 10 ไฟล์. คุณกำลังจะเพิ่มรหัสลับที่ได้รับในส่วนด้านบน
22รหัส> ไฟล์ควรมีคีย์ต่อไปนี้:
# .env
# OpenAI API Key
OPENAI_API_KEY="sk-..."
# Upstash Vector Keys
UPSTASH_VECTOR_REST_URL="https://...-us1-vector.upstash.io"
UPSTASH_VECTOR_REST_TOKEN="...=" เมื่อดำเนินการเสร็จแล้ว การตั้งค่าคอนฟิกจะเสร็จสมบูรณ์ในส่วนของคุณ ตอนนี้คุณสามารถดูการทำงานของแอปพลิเคชันได้โดยดำเนินการคำสั่งต่อไปนี้ในเทอร์มินัลของคุณและไปที่ localhost:3000
pnpm run build && pnpm run start ปฏิบัติตามเพื่อทำความเข้าใจส่วนที่เกี่ยวข้องของโค้ดที่ช่วยให้คุณสามารถสร้างระบบการแนะนำบทความของคุณเองได้สำเร็จ
สร้างอินสแตนซ์ไคลเอนต์ OpenAI API
ด้วย 35 คุณสามารถประหยัดเวลาและโต้ตอบกับ OpenAI REST API ได้ภายในโค้ดไม่กี่บรรทัด ด้วยโค้ดต่อไปนี้ เราได้สร้างอินสแตนซ์ไลบรารีไคลเอนต์ OpenAI API เพื่อใช้ต่อไปเพื่อสร้างการตอบกลับการแชทเสร็จสิ้น
// 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,
})
หมายเหตุ:โดยการต่อท้าย 41 ไปยังไฟล์ใน Remix คุณสามารถตรวจสอบให้แน่ใจว่าโค้ดนั้นถูกบังคับให้ ออก ของบันเดิลฝั่งไคลเอ็นต์
สร้างไคลเอ็นต์การฝัง OpenAI API
ด้วย 55 แพ็คเกจคุณสามารถใช้ 62 คลาสสำหรับสร้างการฝังเวกเตอร์ของข้อความที่กำหนด เมื่อรวมกับ LangChain Vector Store คลาส OpenAIEmbeddings จะช่วยคุณประหยัดจากกระบวนการสร้างและการแทรกเวกเตอร์แต่ละตัวที่ฝังด้วยตัวเอง ด้วยโค้ดต่อไปนี้ เราได้สร้างอินสแตนซ์คลาส OpenAIEmbeddings เพื่อใช้เพิ่มเติมเพื่อสร้างการฝังเวกเตอร์ภายใต้ประทุน
// 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,
}) สร้าง Upstash Vector Client
ใช้ 73 และ 88รหัส> คุณสามารถสร้างไคลเอ็นต์แบบไร้การเชื่อมต่อในแอปพลิเคชัน Remix ของคุณ ซึ่งช่วยให้คุณสามารถจัดเก็บ ลบ และสอบถามการฝังเวกเตอร์จากดัชนี 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 }) สร้างจุดสิ้นสุด Context API
เมื่อคุณเรียกใช้แอปพลิเคชัน Remix คุณจะเห็นกล่องข้อความที่ยอมรับ URL บทความหลายรายการเป็นอินพุต บทความเหล่านั้นจะถูกเพิ่มเข้าไปในความรู้ของแชทบอทเพื่อสร้างการตอบกลับส่วนบุคคลในการค้นหาของผู้ใช้ในอนาคต ในส่วนนี้ คุณจะได้เรียนรู้วิธีการปลายทางบริบท (95 ) ได้รับการตั้งค่าให้ยอมรับ URL ของบทความหลายรายการ ดึงเนื้อหา สร้างการฝังเวกเตอร์ และจัดเก็บไว้ใน 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()
// 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))
}
}
ในการดำเนินการ Remix ข้างต้น ข้อมูลแบบฟอร์มจะแสดงอยู่ในคำขอ POST ไปยังจุดสิ้นสุดบริบท (105 ) ถูกแยกวิเคราะห์ นอกจากนี้ ยังมีการวนซ้ำชุดลิงก์บทความซึ่งคั่นด้วยเครื่องหมายจุลภาค (,) ซึ่งทำหน้าที่ดังต่อไปนี้:
- สร้าง
114ตัวแปรตามเนื้อหาข้อความที่ดึงมาจากหน้าเว็บของบทความ - สร้าง
127ตัวแปรเป็นชื่อหน้าเว็บของบทความ - สร้างเอกสาร LangChain ที่มีเนื้อหาข้อความ การอ้างอิง และชื่อของบทความ (
137) - เพิ่มแต่ละเอกสารในโกลบอล
141อาร์เรย์
สุดท้ายนี้ เอกสารทั้งหมดที่จัดเก็บไว้ในโกลบอล 155 อาร์เรย์ถูกแทรกลงใน Upstash Vector Index ภายใต้ประทุนนั้น การฝังเวกเตอร์สำหรับแต่ละเอกสารจะถูกสร้างขึ้นโดยใช้ 160 ทรัพย์สิน
สร้างปลายทาง Chat API
ในส่วนนี้ คุณจะได้เรียนรู้ว่า Chat API Endpoint (171 เป็นอย่างไร ) ได้รับการตั้งค่าเพื่อสร้างเครื่องมือค้นหาเช่นคำตอบที่มีคำแนะนำสำหรับบทความที่เกี่ยวข้องกับการค้นหาของผู้ใช้ บทความที่เกี่ยวข้องกับการค้นหาจะพบได้โดยการค้นหาเวกเตอร์ K บนสุดที่ใกล้เคียงที่สุดจากดัชนีเวกเตอร์ที่กำหนด นอกจากนี้ ชื่อและลิงก์จากข้อมูลเมตาของเวกเตอร์จะถูกส่งผ่านไปยัง OpenAI API เป็นบริบท ซึ่งช่วยให้แชทบอตสามารถรวมบทความเป็นลิงก์ภายนอกร่วมกับการตอบสนองต่อการค้นหาของผู้ใช้ เพื่อให้สิ่งต่าง ๆ ง่ายขึ้น เราจะแบ่งสิ่งนี้ออกเป็นส่วนเพิ่มเติม:
ค้นหาการฝังเวกเตอร์ที่เกี่ยวข้องโดยใช้การค้นหาที่คล้ายคลึงกัน
การเยี่ยมชมคลังความรู้ทั้งหมดของบทความสำหรับการค้นหาผู้ใช้แต่ละครั้งเป็นการดำเนินการที่มีราคาแพง หากต้องการกำหนดขอบเขตลงไปที่บทความ 3 อันดับแรก (หาก) มีความเกี่ยวข้องสูงกับการค้นหาของผู้ใช้ ให้ค้นหาชุดเวกเตอร์ที่มีอยู่ใน Upstash Vector Index ของคุณ นอกจากนี้ กรองเพื่อให้เวกเตอร์ที่มีการฝังมีคะแนนความคล้ายคลึงกันอย่างน้อย 70% กับการฝังเวกเตอร์ของการค้นหาของผู้ใช้
// 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
} สร้างบริบทของระบบและคำแนะนำสำหรับ Chatbot
เมื่อคุณได้รับชุดเวกเตอร์ที่มีความเกี่ยวข้องสูงแล้ว คุณต้องการให้แชทบอททราบและอ้างอิงบทความที่เกี่ยวข้องก่อนที่จะตอบสนองต่อการค้นหาของผู้ใช้ หากต้องการทำเช่นนั้นด้วย 180 ของ OpenAI model ให้สร้างออบเจ็กต์ข้อความโดยมีคุณสมบัติบทบาทเป็น ระบบ และคุณสมบัติเนื้อหาที่จะมีคำแนะนำต่อไปนี้:
- แชทบอทควรตอบสนองเหมือนกับที่ Google ทำ
- แชทบอทควรตรวจสอบให้แน่ใจว่าการตอบกลับอยู่ในรูปแบบมาร์กดาวน์
- การตอบกลับของแชทบอทควรมีไฮเปอร์ลิงก์ไปยังบทความ
- แชทบอทเป็นมากกว่าแค่การอ้างอิงบทความ
// 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)
}
ด้วยโค้ดด้านบน คุณสามารถสตรีมผลลัพธ์จาก OpenAI ที่รับรู้บริบท โดยแนะนำบทความที่พบที่เกี่ยวข้องกับการค้นหาของผู้ใช้
นั่นเป็นการเรียนรู้มากมาย! คุณทำเสร็จแล้วตอนนี้ ✨
ปรับใช้กับ Fly.io
พื้นที่เก็บข้อมูลมาพร้อมกับการตั้งค่าแบบอบสำหรับ Fly.io โดยเฉพาะที่เกี่ยวข้องกับ:
- นักเทียบท่าไฟล์
- fly.toml
- .นักเทียบท่าไม่สนใจ
เมื่อคุณมีบัญชี Fly.io แล้ว คุณสามารถสร้างแอปใน Fly.io ได้โดยดำเนินการคำสั่งต่อไปนี้ในเทอร์มินัลที่ไดเร็กทอรีราก:
# 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 และปรับใช้กับ Fly.io โดยดำเนินการคำสั่งต่อไปนี้ในเทอร์มินัลของคุณ:
# Deploy the app based on the configuration created above
fly deploy ข้อมูลอ้างอิง
หากต้องการข้อมูลเชิงลึกโดยละเอียดเพิ่มเติม โปรดสำรวจข้อมูลอ้างอิงที่ใช้ในคู่มือนี้
- พื้นที่เก็บข้อมูล GitHub
- การรวม Upstash Vector Store กับ LangChain
- คำแนะนำของระบบใน Chat Completions API ของ OpenAI
- โหลดข้อมูลจากหน้าเว็บโดยใช้ Cheerio ใน LangChain
- การสร้าง AI Chat UI ในแอป React
บทสรุป
ในคู่มือนี้ คุณได้เรียนรู้วิธีสร้างระบบการแนะนำบทความโดยใช้ Vector Embeddings และ OpenAI Completion API พร้อมบริบทระบบที่สร้างขึ้นแบบไดนามิก ด้วย Upstash Vector และ LangChain คุณจะได้รับความสามารถในการจัดเก็บเวกเตอร์ในดัชนี ดำเนินการค้นหาเวกเตอร์ระดับบนสุด และสร้างบริบทที่เกี่ยวข้องสำหรับการค้นหาของผู้ใช้แต่ละคน ทั้งหมดนี้ทำได้ภายในโค้ดไม่กี่บรรทัด
หากคุณมีคำถามหรือความคิดเห็น โปรดติดต่อฉันได้ที่ GitHub