Cửa hàng Vector của Rememberizer đơn giản hóa quy trình xử lý dữ liệu vector, cho phép bạn tập trung vào đầu vào văn bản và tận dụng sức mạnh của các vector cho nhiều ứng dụng như tìm kiếm và phân tích dữ liệu.
Giới thiệu
Rememberizer Vector Store cung cấp một giao diện dễ sử dụng để xử lý dữ liệu vector trong khi trừu tượng hóa sự phức tạp của các vector embeddings. Được hỗ trợ bởi PostgreSQL với phần mở rộng pgvector, Rememberizer Vector Store cho phép bạn làm việc trực tiếp với văn bản. Dịch vụ này xử lý việc chia nhỏ, vector hóa và lưu trữ dữ liệu văn bản, giúp bạn dễ dàng tập trung vào logic ứng dụng cốt lõi của mình.
Để hiểu sâu hơn về các khái niệm lý thuyết đằng sau vector embeddings và cơ sở dữ liệu vector, hãy xem .
Tổng Quan Kỹ Thuật
Cách Các Kho Vector Hoạt Động
Kho Vector Rememberizer chuyển đổi văn bản thành các đại diện vector nhiều chiều (nhúng) nắm bắt ý nghĩa ngữ nghĩa. Điều này cho phép:
Tìm Kiếm Ngữ Nghĩa: Tìm tài liệu dựa trên ý nghĩa thay vì chỉ từ khóa
Khớp Tương Tự: Xác định nội dung có liên quan về mặt khái niệm
Truy Xuất Hiệu Quả: Nhanh chóng xác định thông tin liên quan từ các tập dữ liệu lớn
Các Thành Phần Chính
Xử Lý Tài Liệu: Văn bản được chia thành các đoạn có kích thước tối ưu với các ranh giới chồng chéo để bảo tồn ngữ cảnh
Chuyển Đổi Thành Vector: Các đoạn được chuyển đổi thành các nhúng bằng cách sử dụng các mô hình tiên tiến nhất
Lập Chỉ Mục: Các thuật toán chuyên biệt tổ chức các vector để tìm kiếm độ tương đồng hiệu quả
Xử Lý Truy Vấn: Các truy vấn tìm kiếm được chuyển đổi thành vector và so sánh với các nhúng đã lưu trữ
Kiến trúc
Rememberizer triển khai các kho vector sử dụng:
PostgreSQL với phần mở rộng pgvector: Để lưu trữ và tìm kiếm vector hiệu quả
Tổ chức dựa trên bộ sưu tập: Mỗi kho vector có bộ sưu tập riêng biệt
Truy cập dựa trên API: Các điểm cuối RESTful đơn giản cho tất cả các thao tác
Bắt đầu
Tạo một Cửa Hàng Vector
Điều hướng đến phần Cửa Hàng Vector trong bảng điều khiển của bạn
Nhấp vào "Tạo cửa hàng vector mới":
Một biểu mẫu sẽ xuất hiện yêu cầu bạn nhập chi tiết.
Điền vào các Chi tiết:
Tên: Cung cấp một tên duy nhất cho cửa hàng vector của bạn.
Mô tả: Viết một mô tả ngắn gọn về cửa hàng vector.
Mô hình Nhúng: Chọn mô hình chuyển đổi văn bản thành vector.
Thuật toán Lập chỉ mục: Chọn cách tổ chức các vector để tìm kiếm.
Chỉ số Tìm kiếm: Định nghĩa cách tính toán độ tương đồng giữa các vector.
Kích thước Vector: Kích thước của các nhúng vector (thường là 768-1536).
Gửi Biểu mẫu:
Nhấp vào nút "Tạo". Bạn sẽ nhận được thông báo thành công, và cửa hàng mới sẽ xuất hiện trong danh sách cửa hàng vector của bạn.
Tùy Chọn Cấu Hình
Các Mô Hình Nhúng
Mô Hình
Kích Thước
Mô Tả
Tốt Nhất Cho
openai/text-embedding-3-large
1536
Mô hình nhúng chính xác cao từ OpenAI
Các ứng dụng sản xuất yêu cầu độ chính xác tối đa
openai/text-embedding-3-small
1536
Mô hình nhúng nhỏ hơn, nhanh hơn từ OpenAI
Các ứng dụng có yêu cầu thông lượng cao hơn
Thuật Toán Lập Chỉ Mục
Thuật Toán
Mô Tả
Đánh Đổi
IVFFLAT (mặc định)
Tệp đảo ngược với nén phẳng
Cân bằng tốt giữa tốc độ và độ chính xác; hoạt động tốt cho hầu hết các tập dữ liệu
HNSW
Thế Giới Nhỏ Có Thể Điều Hướng Theo Cấp Bậc
Độ chính xác tốt hơn cho các tập dữ liệu lớn; yêu cầu bộ nhớ cao hơn
Các chỉ số tìm kiếm
Chỉ số
Mô tả
Tốt nhất cho
cosine (mặc định)
Đo góc giữa các vector
So khớp độ tương đồng mục đích chung
inner product (ip)
Tích vô hướng giữa các vector
Khi độ lớn của vector là quan trọng
L2 (Euclidean)
Khoảng cách đường thẳng giữa các vector
Khi các mối quan hệ không gian quan trọng
Quản lý Cửa hàng Vector
Xem và Chỉnh sửa Cửa hàng Vector:
Truy cập bảng điều khiển quản lý để xem, chỉnh sửa hoặc xóa cửa hàng vector.
Xem Tài liệu:
Duyệt qua các tài liệu riêng lẻ và siêu dữ liệu liên quan của chúng trong một cửa hàng vector cụ thể.
Thống kê:
Xem thống kê chi tiết như số lượng vector được lưu trữ, hiệu suất truy vấn và các chỉ số hoạt động.
Quản lý Khóa API
Các khóa API được sử dụng để xác thực và ủy quyền truy cập vào các điểm cuối API của Rememberizer Vector Store. Quản lý đúng cách các khóa API là rất quan trọng để duy trì sự an toàn và toàn vẹn của các kho vector của bạn.
Tạo Khóa API
Truy cập trang chi tiết Vector Store của bạn
Điều hướng đến Phần Quản lý Khóa API:
Nó có thể được tìm thấy trong tab "Cấu hình"
Nhấp vào "Thêm Khóa API":
Một biểu mẫu sẽ xuất hiện yêu cầu bạn nhập chi tiết.
Điền Thông Tin:
Tên: Cung cấp một tên cho khóa API để giúp bạn xác định trường hợp sử dụng của nó.
Gửi Biểu Mẫu:
Nhấp vào nút "Tạo". Khóa API mới sẽ được tạo ra và hiển thị. Hãy chắc chắn sao chép và lưu trữ nó một cách an toàn. Khóa này được sử dụng để xác thực các yêu cầu đến cửa hàng vector cụ thể đó.
Thu hồi khóa API
Nếu một khóa API không còn cần thiết, bạn có thể xóa nó để ngăn chặn bất kỳ sự lạm dụng tiềm ẩn nào.
Vì lý do bảo mật, bạn có thể muốn thay đổi khóa API của mình định kỳ. Điều này bao gồm việc tạo một khóa mới và thu hồi khóa cũ.
Sử dụng API Vector Store
Sau khi tạo một Vector Store và tạo một khóa API, bạn có thể tương tác với nó bằng cách sử dụng REST API.
Ví dụ Mã
import requests
import json
API_KEY = "your_api_key_here"
VECTOR_STORE_ID = "vs_abc123" # Thay thế bằng ID kho vector của bạn
BASE_URL = "https://api.rememberizer.a
# Tải lên một tài liệu vào kho vector
def upload_document(file_path, document_name=None):
if document_name is None:
document_name = file_path.split("/")[-1]
with open(file_path, "rb") as f:
files = {"file": (document_name, f)}
headers = {"x-api-key": API_KEY}
response = requests.post(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents",
headers=headers,
files=files
)
if response.status_code == 201:
print(f"Tài liệu '{document_name}' đã được tải lên thành công!")
return response.json()
else:
print(f"Lỗi khi tải lên tài liệu: {response.text}")
return None
# Tải nội dung văn bản lên kho vector
def upload_text(content, document_name):
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
data = {
"name": document_name,
"content": content
}
response = requests.post(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
headers=headers,
json=data
)
if response.status_code == 201:
print(f"Tài liệu văn bản '{document_name}' đã được tải lên thành công!")
return response.json()
else:
print(f"Lỗi khi tải lên văn bản: {response.text}")
return None
# Tìm kiếm kho vector
def search_vector_store(query, num_results=5, prev_chunks=1, next_chunks=1):
headers = {"x-api-key": API_KEY}
params = {
"q": query,
"n": num_results,
"prev_chunks": prev_chunks,
"next_chunks": next_chunks
}
response = requests.get(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/search",
headers=headers,
params=params
)
if response.status_code == 200:
results = response.json()
print(f"Đã tìm thấy {len(results['matched_chunks'])} kết quả cho '{query}'")
# In kết quả hàng đầu
if results['matched_chunks']:
top_match = results['matched_chunks'][0]
print(f"Kết quả hàng đầu (khoảng cách: {top_match['distance']}):")
print(f"Tài liệu: {top_match['document']['name']}")
print(f"Nội dung: {top_match['matched_content']}")
return results
else:
print(f"Lỗi khi tìm kiếm: {response.text}")
return None
# Ví dụ sử dụng
# tải_tài_liệu("đường/dẫn/đến/tài_liệu.pdf")
# upload_text("Đây là một đoạn văn bản mẫu để được vector hóa", "sample-document.txt")
# search_vector_store("Cách hoạt động của độ tương đồng vector?")
// Khách hàng API Vector Store
class VectorStoreClient {
constructor(apiKey, vectorStoreId) {
this.apiKey = apiKey;
this.vectorStoreId = vectorStoreId;
this.baseUrl = 'https://api.rememberizer.ai/api/v1';
}
// Lấy thông tin cửa hàng vector
async getVectorStoreInfo() {
const response = await fetch(`${this.baseUrl}/vector-stores/${this.vectorStoreId}`, {
method: 'GET',
headers: {
'x-api-key': this.apiKey
}
});
if (!response.ok) {
throw new Error(`Không thể lấy thông tin cửa hàng vector: ${response.statusText}`);
}
return response.json();
}
// Tải lên tài liệu văn bản
async uploadTextDocument(name, content) {
const response = await fetch(`${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/text`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name,
content
})
});
if (!response.ok) {
throw new Error(`Không thể tải lên tài liệu văn bản: ${response.statusText}`);
}
return response.json();
}
// Tải lên một tệp
async uploadFile(file, onProgress) {
const formData = new FormData();
formData.append('file', file);
const xhr = new XMLHttpRequest();
return new Promise((resolve, reject) => {
xhr.open('POST', `${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents`);
xhr.setRequestHeader('x-api-key', this.apiKey);
xhr.upload.onprogress = (event) => {
if (event.lengthComputable && onProgress) {
const percentComplete = (event.loaded / event.total) * 100;
onProgress(percentComplete);
}
};
xhr.onload = () => {
if (xhr.status === 201) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`Không thể tải lên tệp: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
reject(new Error('Lỗi mạng trong quá trình tải lên tệp'));
};
xhr.send(formData);
});
}
// Tìm kiếm tài liệu trong cửa hàng vector
async searchDocuments(query, options = {}) {
const params = new URLSearchParams({
q: query,
n: options.numResults || 10,
prev_chunks: options.prevChunks || 1,
next_chunks: options.nextChunks || 1
});
if (options.threshold) {
params.append('t', options.threshold);
}
const response = await fetch(
`${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/search?${params}`,
{
method: 'GET',
headers: {
'x-api-key': this.apiKey
}
}
);
if (!response.ok) {
throw new Error(`Tìm kiếm không thành công: ${response.statusText}`);
}
return response.json();
}
// Liệt kê tất cả tài liệu trong cửa hàng vector
async listDocuments() {
const response = await fetch(
`${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents`,
{
method: 'GET',
headers: {
'x-api-key': this.apiKey
}
}
);
if (!response.ok) {
throw new Error(`Không thể liệt kê tài liệu: ${response.statusText}`);
}
return response.json();
}
// Xóa một tài liệu
async deleteDocument(documentId) {
const response = await fetch(
`${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/${documentId}`,
{
method: 'DELETE',
headers: {
'x-api-key': this.apiKey
}
}
);
if (!response.ok) {
throw new Error(`Không thể xóa tài liệu: ${response.statusText}`);
}
return true;
}
}
// Ví dụ sử dụng
/*
const client = new VectorStoreClient('your_api_key', 'vs_abc123');
// Tìm kiếm tài liệu
client.searchDocuments('Cách hoạt động của tìm kiếm ngữ nghĩa?')
.then(results => {
console.log(`Tìm thấy ${results.matched_chunks.length} kết quả`);
results.matched_chunks.forEach(match => {
console.log(`Tài liệu: ${match.document.name}`);
console.log(`Điểm: ${match.distance}`);
console.log(`Nội dung: ${match.matched_content}`);
console.log('---');
});
})
.catch(error => console.error(error));
*/
require 'net/http'
require 'uri'
require 'json'
class VectorStoreClient
def initialize(api_key, vector_store_id)
@api_key = api_key
@vector_store_id = vector_store_id
@base_url = 'https://api.rememberizer.ai/api/v1'
end
# Lấy chi tiết cửa hàng vector
def get_vector_store_info
uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}")
request = Net::HTTP::Get.new(uri)
request['x-api-key'] = @api_key
response = send_request(uri, request)
JSON.parse(response.body)
end
# Tải lên nội dung văn bản
def upload_text(name, content)
uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents/text")
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['x-api-key'] = @api_key
request.body = {
name: name,
content: content
}.to_json
response = send_request(uri, request)
JSON.parse(response.body)
end
# Tìm kiếm tài liệu
def search(query, num_results: 5, prev_chunks: 1, next_chunks: 1, threshold: nil)
uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents/search")
params = {
q: query,
n: num_results,
prev_chunks: prev_chunks,
next_chunks: next_chunks
}
params[:t] = threshold if threshold
uri.query = URI.encode_www_form(params)
request = Net::HTTP::Get.new(uri)
request['x-api-key'] = @api_key
response = send_request(uri, request)
JSON.parse(response.body)
end
# Liệt kê tài liệu
def list_documents
uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents")
request = Net::HTTP::Get.new(uri)
request['x-api-key'] = @api_key
response = send_request(uri, request)
JSON.parse(response.body)
end
# Tải lên tệp (hình thức đa phần)
def upload_file(file_path)
uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents")
file_name = File.basename(file_path)
file_content = File.binread(file_path)
boundary = "RememberizerBoundary#{rand(1000000)}"
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
request['x-api-key'] = @api_key
post_body = []
post_body << "--#{boundary}\r\n"
post_body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{file_name}\"\r\n"
post_body << "Content-Type: application/octet-stream\r\n\r\n"
post_body << file_content
post_body << "\r\n--#{boundary}--\r\n"
request.body = post_body.join
response = send_request(uri, request)
JSON.parse(response.body)
end
private
def send_request(uri, request)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
response = http.request(request)
unless response.is_a?(Net::HTTPSuccess)
raise "Yêu cầu API không thành công: #{response.code} #{response.message}\n#{response.body}"
end
response
end
end
results = client.search('Những thực hành tốt nhất cho an ninh dữ liệu là gì?')
puts "Tìm thấy #{results['matched_chunks'].length} kết quả"
Hiển thị kết quả hàng đầu
if results['matched_chunks'].any?
top_match = results['matched_chunks'].first
puts "Kết quả hàng đầu (khoảng cách: #{top_match['distance']}):"
puts "Tài liệu: #{top_match['document']['name']}"
puts "Nội dung: #{top_match['matched_content']}"
end
=end
</div>
<div data-gb-custom-block data-tag="tab" data-title='cURL'>
```bash
# Đặt khóa API và ID Vector Store
API_KEY="your_api_key_here"
VECTOR_STORE_ID="vs_abc123"
BASE_URL="https://api.rememberizer.ai/api/v1"
# Lấy thông tin cửa hàng vector
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}" \
-H "x-api-key: ${API_KEY}"
# Tải lên một tài liệu văn bản
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/text" \
-H "x-api-key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "example-document.txt",
"content": "Đây là một tài liệu mẫu sẽ được vector hóa và lưu trữ trong cơ sở dữ liệu vector để tìm kiếm ngữ nghĩa."
}'
# Tải lên một tệp
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
-H "x-api-key: ${API_KEY}" \
-F "file=@/path/to/your/document.pdf"
# Tìm kiếm tài liệu
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/search?q=semantic%20search&n=5&prev_chunks=1&next_chunks=1" \
-H "x-api-key: ${API_KEY}"
# Liệt kê tất cả tài liệu
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
-H "x-api-key: ${API_KEY}"
# Xóa một tài liệu
curl -X DELETE "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/123" \
-H "x-api-key: ${API_KEY}"
Các yếu tố hiệu suất
Sắp ra mắt: Sơ đồ Kiến trúc Lưu trữ Vector
Sơ đồ kiến trúc kỹ thuật này sẽ minh họa:
Kiến trúc nền tảng PostgreSQL + pgvector
Cấu trúc thuật toán lập chỉ mục (IVFFLAT so với HNSW)
Cách thức hoạt động của các chỉ số tìm kiếm trong không gian vector (so sánh trực quan)
Quá trình chia nhỏ tài liệu với hình ảnh trực quan về sự chồng chéo
Các yếu tố hiệu suất được hình dung qua các quy mô khác nhau
Tối ưu hóa cho Các Khối Lượng Dữ Liệu Khác Nhau
Khối Lượng Dữ Liệu
Cấu Hình Đề Xuất
Ghi Chú
Nhỏ (<10k tài liệu)
IVFFLAT, độ tương đồng cosine
Cấu hình đơn giản cung cấp hiệu suất tốt
Trung Bình (10k-100k tài liệu)
IVFFLAT, đảm bảo tái lập chỉ mục thường xuyên
Cân bằng giữa tốc độ tìm kiếm và bảo trì chỉ mục
Lớn (>100k tài liệu)
HNSW, xem xét tăng kích thước vector
Sử dụng bộ nhớ cao hơn nhưng duy trì hiệu suất ở quy mô lớn
Chiến Lược Chia Nhỏ
Quá trình chia nhỏ ảnh hưởng đáng kể đến chất lượng tìm kiếm:
Kích Thước Chia Nhỏ: Rememberizer sử dụng kích thước chia nhỏ mặc định là 1024 byte với độ chồng chéo 200 byte
Chia Nhỏ Nhỏ Hơn (512-1024 byte): Các kết quả khớp chính xác hơn, tốt hơn cho các câu hỏi cụ thể
Chia Nhỏ Lớn Hơn (1500-2048 byte): Nhiều ngữ cảnh hơn trong mỗi kết quả khớp, tốt hơn cho các chủ đề rộng
Độ Chồng Chéo: Đảm bảo ngữ cảnh không bị mất ở các ranh giới chia nhỏ
Tối ưu hóa truy vấn
Cửa sổ ngữ cảnh: Sử dụng prev_chunks và next_chunks để lấy nội dung xung quanh
Số lượng kết quả: Bắt đầu với 3-5 kết quả (n parameter) và điều chỉnh dựa trên nhu cầu độ chính xác
Ngưỡng: Điều chỉnh tham số t để lọc kết quả theo điểm tương đồng
Sử Dụng Nâng Cao
Tái lập chỉ mục
Rememberizer tự động kích hoạt tái lập chỉ mục khi số lượng vector vượt quá ngưỡng đã định trước, nhưng hãy xem xét việc tái lập chỉ mục thủ công sau:
Tải lên một số lượng lớn tài liệu
Thay đổi mô hình nhúng
Sửa đổi thuật toán lập chỉ mục
Cải Thiện Truy Vấn
Để có kết quả tìm kiếm tốt hơn:
Cụ thể trong các truy vấn tìm kiếm
Bao gồm ngữ cảnh khi có thể
Sử dụng ngôn ngữ tự nhiên thay vì từ khóa
Điều chỉnh tham số dựa trên chất lượng kết quả
Di chuyển từ các cơ sở dữ liệu vector khác
Nếu bạn hiện đang sử dụng các giải pháp cơ sở dữ liệu vector khác và muốn chuyển sang Rememberizer Vector Store, các hướng dẫn sau sẽ giúp bạn chuyển dữ liệu một cách hiệu quả.
Tổng Quan Về Di Chuyển
Di chuyển dữ liệu vector bao gồm:
Xuất dữ liệu từ cơ sở dữ liệu vector nguồn của bạn
Chuyển đổi dữ liệu sang định dạng tương thích với Rememberizer
Nhập dữ liệu vào Kho Dữ Liệu Vector Rememberizer của bạn
Xác minh rằng việc di chuyển đã thành công
Lợi ích của việc Chuyển đổi sang Rememberizer
Nền tảng PostgreSQL: Xây dựng trên công nghệ cơ sở dữ liệu trưởng thành với sao lưu và phục hồi tích hợp
Hệ sinh thái Tích hợp: Kết nối liền mạch với các thành phần khác của Rememberizer
Quản lý Đơn giản: Giao diện thống nhất cho các thao tác vector
Bảo mật Nâng cao: Bảo mật theo hàng và kiểm soát truy cập chi tiết
Kiến trúc Có thể mở rộng: Tối ưu hóa hiệu suất khi dữ liệu của bạn phát triển
Di chuyển từ Pinecone
import os
import pinecone
import requests
import json
import time
# Thiết lập khách hàng Pinecone
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV")
source_index = pinecone.Index("your-pinecone-index")
# Thiết lập khách hàng Vector Store Rememberizer
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123" # ID vector store Rememberizer của bạn
BASE_URL = "https://api.rememberizer.ai/api/v1"
# 1. Thiết lập kích thước lô cho việc di chuyển (điều chỉnh dựa trên kích thước dữ liệu của bạn)
BATCH_SIZE = 100
# 2. Hàm để lấy vector từ Pinecone
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None):
# Sử dụng thao tác danh sách nếu có trong phiên bản Pinecone của bạn
try:
result = source_index.list(limit=batch_size, cursor=cursor)
vectors = result.get("vectors", {})
next_cursor = result.get("cursor")
return vectors, next_cursor
except AttributeError:
# Đối với các phiên bản Pinecone cũ hơn không có thao tác danh sách
# Đây là một cách tiếp cận đơn giản; việc triển khai thực tế phụ thuộc vào mẫu truy cập dữ liệu của bạn
query_response = source_index.query(
vector=[0] * source_index.describe_index_stats()["dimension"],
top_k=batch_size,
include_metadata=True,
include_values=True
)
return {item.id: {"id": item.id, "values": item.values, "metadata": item.metadata}
for item in query_response.matches}, None
# 3. Hàm để tải lên vector đến Rememberizer
def upload_to_rememberizer(vectors):
headers = {
"x-api-key": REMEMBERIZER_API_KEY,
"Content-Type": "application/json"
}
for vector_id, vector_data in vectors.items():
# Chuyển đổi dữ liệu vector Pinecone sang định dạng Rememberizer
document_name = vector_data.get("metadata", {}).get("filename", f"pinecone_doc_{vector_id}")
content = vector_data.get("metadata", {}).get("text", "")
if not content:
print(f"Bỏ qua {vector_id} - không tìm thấy nội dung văn bản trong metadata")
continue
data = {
"name": document_name,
"content": content,
# Tùy chọn: bao gồm metadata bổ sung
"metadata": vector_data.get("metadata", {})
}
response = requests.post(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
headers=headers,
json=data
)
if response.status_code == 201:
print(f"Tài liệu '{document_name}' đã được tải lên thành công!")
else:
print(f"Lỗi khi tải lên tài liệu {document_name}: {response.text}")
# Thêm một khoảng thời gian nhỏ để ngăn chặn giới hạn tốc độ
time.sleep(0.1)
# 4. Hàm di chuyển chính
def migrate_pinecone_to_rememberizer():
cursor = None
total_migrated = 0
print("Bắt đầu di chuyển từ Pinecone sang Rememberizer...")
while True:
vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
if not vectors:
break
print(f"Đã lấy {len(vectors)} vector từ Pinecone")
upload_to_rememberizer(vectors)
total_migrated += len(vectors)
print(f"Tiến độ: {total_migrated} vector đã di chuyển")
if not cursor:
break
print(f"Di chuyển hoàn tất! {total_migrated} tổng số vector đã di chuyển sang Rememberizer")
# Chạy quá trình di chuyển
# migrate_pinecone_to_rememberizer()
const { PineconeClient } = require('@pinecone-database/pinecone');
const axios = require('axios');
// Cấu hình Pinecone
const pineconeApiKey = 'PINECONE_API_KEY';
const pineconeEnvironment = 'PINECONE_ENVIRONMENT';
const pineconeIndexName = 'YOUR_PINECONE_INDEX';
// Cấu hình Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Cấu hình kích thước lô
const BATCH_SIZE = 100;
// Khởi tạo client Pinecone
async function initPinecone() {
const pinecone = new PineconeClient();
await pinecone.init({
apiKey: pineconeApiKey,
environment: pineconeEnvironment,
});
return pinecone;
}
// Lấy vector từ Pinecone
async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) {
const index = pinecone.Index(pineconeIndexName);
try {
// Đối với các phiên bản Pinecone mới hơn
const listResponse = await index.list({
limit: batchSize,
paginationToken: paginationToken
});
return {
vectors: listResponse.vectors || {},
nextToken: listResponse.paginationToken
};
} catch (error) {
// Phương án dự phòng cho các phiên bản Pinecone cũ hơn
// Điều này được đơn giản hóa; việc triển khai thực tế phụ thuộc vào mẫu truy cập dữ liệu của bạn
const stats = await index.describeIndexStats();
const dimension = stats.dimension;
const queryResponse = await index.query({
vector: Array(dimension).fill(0),
topK: batchSize,
includeMetadata: true,
includeValues: true
});
const vectors = {};
queryResponse.matches.forEach(match => {
vectors[match.id] = {
id: match.id,
values: match.values,
metadata: match.metadata
};
});
return { vectors, nextToken: null };
}
}
// Tải lên vector đến Rememberizer
async function uploadToRememberizer(vectors) {
const headers = {
'x-api-key': rememberizerApiKey,
'Content-Type': 'application/json'
};
const results = [];
for (const [vectorId, vectorData] of Object.entries(vectors)) {
const documentName = vectorData.metadata?.filename || `pinecone_doc_${vectorId}`;
const content = vectorData.metadata?.text || '';
if (!content) {
console.log(`Bỏ qua ${vectorId} - không tìm thấy nội dung văn bản trong metadata`);
continue;
}
const data = {
name: documentName,
content: content,
// Tùy chọn: bao gồm metadata bổ sung
metadata: vectorData.metadata || {}
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Tài liệu '${documentName}' đã được tải lên thành công!`);
results.push({ id: vectorId, success: true });
} else {
console.error(`Lỗi khi tải lên tài liệu ${documentName}: ${response.statusText}`);
results.push({ id: vectorId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Lỗi khi tải lên tài liệu ${documentName}: ${error.message}`);
results.push({ id: vectorId, success: false, error: error.message });
}
// Thêm một khoảng thời gian nhỏ để tránh giới hạn tần suất
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hàm di chuyển chính
async function migratePineconeToRememberizer() {
try {
console.log('Bắt đầu di chuyển từ Pinecone sang Rememberizer...');
const pinecone = await initPinecone();
let nextToken = null;
let totalMigrated = 0;
do {
const { vectors, nextToken: token } = await fetchVectorsFromPinecone(
pinecone,
BATCH_SIZE,
nextToken
);
nextToken = token;
if (Object.keys(vectors).length === 0) {
break;
}
console.log(`Đã lấy ${Object.keys(vectors).length} vector từ Pinecone`);
const results = await uploadToRememberizer(vectors);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Tiến độ: ${totalMigrated} vector đã được di chuyển thành công`);
} while (nextToken);
console.log(`Di chuyển hoàn tất! ${totalMigrated} tổng số vector đã được di chuyển đến Rememberizer`);
} catch (error) {
console.error('Di chuyển thất bại:', error);
}
}
// Chạy quá trình di chuyển
// migratePineconeToRememberizer();
Di chuyển từ Qdrant
import requests
import json
import time
from qdrant_client import QdrantClient
from qdrant_client.http import models as rest
# Thiết lập khách hàng Qdrant
QDRANT_URL = "http://localhost:6333" # hoặc URL đám mây Qdrant của bạn
QDRANT_API_KEY = "your_qdrant_api_key" # nếu sử dụng Qdrant Cloud
QDRANT_COLLECTION_NAME = "your_collection"
qdrant_client = QdrantClient(
url=QDRANT_URL,
api_key=QDRANT_API_KEY # Chỉ dành cho Qdrant Cloud
)
# Thiết lập khách hàng Vector Store Rememberizer
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123" # ID vector store Rememberizer của bạn
BASE_URL = "https://api.rememberizer.ai/api/v1"
# Kích thước lô để xử lý
BATCH_SIZE = 100
# Hàm để lấy điểm từ Qdrant
def fetch_points_from_qdrant(collection_name, batch_size, offset=0):
try:
# Lấy thông tin bộ sưu tập để xác định kích thước vector
collection_info = qdrant_client.get_collection(collection_name=collection_name)
# Cuộn qua các điểm
scroll_result = qdrant_client.scroll(
collection_name=collection_name,
limit=batch_size,
offset=offset,
with_payload=True,
with_vectors=True
)
points = scroll_result[0] # Tuple của (điểm, next_offset)
next_offset = scroll_result[1]
return points, next_offset
except Exception as e:
print(f"Lỗi khi lấy điểm từ Qdrant: {e}")
return [], None
# Hàm để tải lên vector đến Rememberizer
def upload_to_rememberizer(points):
headers = {
"x-api-key": REMEMBERIZER_API_KEY,
"Content-Type": "application/json"
}
results = []
for point in points:
# Trích xuất dữ liệu từ điểm Qdrant
point_id = point.id
metadata = point.payload
text_content = metadata.get("text", "")
document_name = metadata.get("filename", f"qdrant_doc_{point_id}")
if not text_content:
print(f"Bỏ qua {point_id} - không tìm thấy nội dung văn bản trong payload")
continue
data = {
"name": document_name,
"content": text_content,
# Tùy chọn: bao gồm siêu dữ liệu bổ sung
"metadata": metadata
}
try:
response = requests.post(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
headers=headers,
json=data
)
if response.status_code == 201:
print(f"Tài liệu '{document_name}' đã được tải lên thành công!")
results.append({"id": point_id, "success": True})
else:
print(f"Lỗi khi tải lên tài liệu {document_name}: {response.text}")
results.append({"id": point_id, "success": False, "error": response.text})
except Exception as e:
print(f"Ngoại lệ khi tải lên tài liệu {document_name}: {str(e)}")
results.append({"id": point_id, "success": False, "error": str(e)})
# Thêm một khoảng thời gian nhỏ để ngăn chặn giới hạn tần suất
time.sleep(0.1)
return results
# Chức năng di chuyển chính
def migrate_qdrant_to_rememberizer():
offset = None
total_migrated = 0
print("Bắt đầu di chuyển từ Qdrant sang Rememberizer...")
while True:
points, next_offset = fetch_points_from_qdrant(
QDRANT_COLLECTION_NAME,
BATCH_SIZE,
offset
)
if not points:
break
print(f"Đã lấy {len(points)} điểm từ Qdrant")
results = upload_to_rememberizer(points)
success_count = sum(1 for r in results if r.get("success", False))
total_migrated += success_count
print(f"Tiến độ: {total_migrated} điểm đã di chuyển thành công")
if next_offset is None:
break
offset = next_offset
print(f"Di chuyển hoàn tất! {total_migrated} tổng số điểm đã di chuyển sang Rememberizer")
# Chạy quá trình di chuyển
# migrate_qdrant_to_rememberizer()
const { QdrantClient } = require('@qdrant/js-client-rest');
const axios = require('axios');
// Cấu hình Qdrant
const qdrantUrl = 'http://localhost:6333'; // hoặc URL đám mây Qdrant của bạn
const qdrantApiKey = 'your_qdrant_api_key'; // nếu sử dụng Qdrant Cloud
const qdrantCollectionName = 'your_collection';
// Cấu hình Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Cấu hình kích thước lô
const BATCH_SIZE = 100;
// Khởi tạo client Qdrant
const qdrantClient = new QdrantClient({
url: qdrantUrl,
apiKey: qdrantApiKey // Chỉ dành cho Qdrant Cloud
});
// Lấy điểm từ Qdrant
async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) {
try {
// Lấy thông tin bộ sưu tập
const collectionInfo = await qdrantClient.getCollection(collectionName);
// Cuộn qua các điểm
const scrollResult = await qdrantClient.scroll(collectionName, {
limit: batchSize,
offset: offset,
with_payload: true,
with_vectors: true
});
return {
points: scrollResult.points,
nextOffset: scrollResult.next_page_offset
};
} catch (error) {
console.error(`Lỗi khi lấy điểm từ Qdrant: ${error.message}`);
return { points: [], nextOffset: null };
}
}
// Tải lên vector đến Rememberizer
async function uploadToRememberizer(points) {
const headers = {
'x-api-key': rememberizerApiKey,
'Content-Type': 'application/json'
};
const results = [];
for (const point of points) {
// Trích xuất dữ liệu từ điểm Qdrant
const pointId = point.id;
const metadata = point.payload || {};
const textContent = metadata.text || '';
const documentName = metadata.filename || `qdrant_doc_${pointId}`;
if (!textContent) {
console.log(`Bỏ qua ${pointId} - không tìm thấy nội dung văn bản trong payload`);
continue;
}
const data = {
name: documentName,
content: textContent,
// Tùy chọn: bao gồm thêm metadata
metadata: metadata
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Tài liệu '${documentName}' đã được tải lên thành công!`);
results.push({ id: pointId, success: true });
} else {
console.error(`Lỗi khi tải lên tài liệu ${documentName}: ${response.statusText}`);
results.push({ id: pointId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Lỗi khi tải lên tài liệu ${documentName}: ${error.message}`);
results.push({ id: pointId, success: false, error: error.message });
}
// Thêm một khoảng thời gian nhỏ để ngăn chặn giới hạn tốc độ
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hàm di chuyển chính
async function migrateQdrantToRememberizer() {
try {
console.log('Bắt đầu di chuyển từ Qdrant sang Rememberizer...');
let offset = null;
let totalMigrated = 0;
do {
const { points, nextOffset } = await fetchPointsFromQdrant(
qdrantCollectionName,
BATCH_SIZE,
offset
);
offset = nextOffset;
if (points.length === 0) {
break;
}
console.log(`Đã lấy ${points.length} điểm từ Qdrant`);
const results = await uploadToRememberizer(points);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Tiến độ: ${totalMigrated} điểm đã được di chuyển thành công`);
} while (offset !== null);
console.log(`Di chuyển hoàn tất! ${totalMigrated} tổng số điểm đã được di chuyển đến Rememberizer`);
} catch (error) {
console.error('Di chuyển thất bại:', error);
}
}
// Chạy di chuyển
// migrateQdrantToRememberizer();
Di chuyển từ Supabase pgvector
Nếu bạn đã sử dụng Supabase với pgvector, việc di chuyển sang Rememberizer đặc biệt đơn giản vì cả hai đều sử dụng PostgreSQL với phần mở rộng pgvector.
import psycopg2
import requests
import json
import time
import os
from dotenv import load_dotenv
# Tải biến môi trường
load_dotenv()
# Cấu hình PostgreSQL Supabase
SUPABASE_DB_HOST = os.getenv("SUPABASE_DB_HOST")
SUPABASE_DB_PORT = os.getenv("SUPABASE_DB_PORT", "5432")
SUPABASE_DB_NAME = os.getenv("SUPABASE_DB_NAME")
SUPABASE_DB_USER = os.getenv("SUPABASE_DB_USER")
SUPABASE_DB_PASSWORD = os.getenv("SUPABASE_DB_PASSWORD")
SUPABASE_VECTOR_TABLE = os.getenv("SUPABASE_VECTOR_TABLE", "documents")
# Cấu hình Rememberizer
REMEMBERIZER_API_KEY = os.getenv("REMEMBERIZER_API_KEY")
VECTOR_STORE_ID = os.getenv("VECTOR_STORE_ID") # ví dụ: "vs_abc123"
BASE_URL = "https://api.rememberizer.ai/api/v1"
# Kích thước lô để xử lý
BATCH_SIZE = 100
# Kết nối đến Supabase PostgreSQL
def connect_to_supabase():
try:
conn = psycopg2.connect(
host=SUPABASE_DB_HOST,
port=SUPABASE_DB_PORT,
dbname=SUPABASE_DB_NAME,
user=SUPABASE_DB_USER,
password=SUPABASE_DB_PASSWORD
)
return conn
except Exception as e:
print(f"Lỗi khi kết nối đến Supabase PostgreSQL: {e}")
return None
# Lấy tài liệu từ Supabase pgvector
def fetch_documents_from_supabase(conn, batch_size, offset=0):
try:
cursor = conn.cursor()
# Điều chỉnh truy vấn này dựa trên cấu trúc bảng của bạn
query = f"""
SELECT id, content, metadata, embedding
FROM {SUPABASE_VECTOR_TABLE}
ORDER BY id
LIMIT %s OFFSET %s
"""
cursor.execute(query, (batch_size, offset))
documents = cursor.fetchall()
cursor.close()
return documents
except Exception as e:
print(f"Lỗi khi lấy tài liệu từ Supabase: {e}")
return []
# Tải tài liệu lên Rememberizer
def upload_to_rememberizer(documents):
headers = {
"x-api-key": REMEMBERIZER_API_KEY,
"Content-Type": "application/json"
}
results = []
for doc in documents:
doc_id, content, metadata, embedding = doc
# Phân tích metadata nếu nó được lưu dưới dạng chuỗi JSON
if isinstance(metadata, str):
try:
metadata = json.loads(metadata)
except:
metadata = {}
elif metadata is None:
metadata = {}
document_name = metadata.get("filename", f"supabase_doc_{doc_id}")
if not content:
print(f"Bỏ qua {doc_id} - không tìm thấy nội dung")
continue
data = {
"name": document_name,
"content": content,
"metadata": metadata
}
try:
response = requests.post(
f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
headers=headers,
json=data
)
if response.status_code == 201:
print(f"Tài liệu '{document_name}' đã được tải lên thành công!")
results.append({"id": doc_id, "success": True})
else:
print(f"Lỗi khi tải tài liệu {document_name}: {response.text}")
results.append({"id": doc_id, "success": False, "error": response.text})
except Exception as e:
print(f"Ngoại lệ khi tải tài liệu {document_name}: {str(e)}")
results.append({"id": doc_id, "success": False, "error": str(e)})
# Thêm một khoảng thời gian nhỏ để ngăn chặn giới hạn tốc độ
time.sleep(0.1)
return results
# Chức năng di chuyển chính
def migrate_supabase_to_rememberizer():
conn = connect_to_supabase()
if not conn:
print("Không thể kết nối với Supabase. Đang hủy di chuyển.")
return
offset = 0
total_migrated = 0
print("Bắt đầu di chuyển từ Supabase pgvector sang Rememberizer...")
try:
while True:
documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
if not documents:
break
print(f"Đã lấy {len(documents)} tài liệu từ Supabase")
results = upload_to_rememberizer(documents)
success_count = sum(1 for r in results if r.get("success", False))
total_migrated += success_count
print(f"Tiến trình: {total_migrated} tài liệu đã di chuyển thành công")
offset += BATCH_SIZE
finally:
conn.close()
print(f"Di chuyển hoàn tất! {total_migrated} tài liệu đã được di chuyển sang Rememberizer")
# Chạy quá trình di chuyển
# migrate_supabase_to_rememberizer()
const { Pool } = require('pg');
const axios = require('axios');
require('dotenv').config();
// Cấu hình PostgreSQL Supabase
const supabasePool = new Pool({
host: process.env.SUPABASE_DB_HOST,
port: process.env.SUPABASE_DB_PORT || 5432,
database: process.env.SUPABASE_DB_NAME,
user: process.env.SUPABASE_DB_USER,
password: process.env.SUPABASE_DB_PASSWORD,
ssl: {
rejectUnauthorized: false
}
});
const supabaseVectorTable = process.env.SUPABASE_VECTOR_TABLE || 'documents';
// Cấu hình Rememberizer
const rememberizerApiKey = process.env.REMEMBERIZER_API_KEY;
const vectorStoreId = process.env.VECTOR_STORE_ID; // ví dụ: "vs_abc123"
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Cấu hình kích thước lô
const BATCH_SIZE = 100;
// Lấy tài liệu từ pgvector Supabase
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
try {
// Điều chỉnh truy vấn này dựa trên cấu trúc bảng của bạn
const query = `
SELECT id, content, metadata, embedding
FROM ${supabaseVectorTable}
ORDER BY id
LIMIT $1 OFFSET $2
`;
const result = await supabasePool.query(query, [batchSize, offset]);
return result.rows;
} catch (error) {
console.error(`Lỗi khi lấy tài liệu từ Supabase: ${error.message}`);
return [];
}
}
// Tải tài liệu lên Rememberizer
async function uploadToRememberizer(documents) {
const headers = {
'x-api-key': rememberizerApiKey,
'Content-Type': 'application/json'
};
const results = [];
for (const doc of documents) {
// Phân tích metadata nếu nó được lưu dưới dạng chuỗi JSON
let metadata = doc.metadata;
if (typeof metadata === 'string') {
try {
metadata = JSON.parse(metadata);
} catch (e) {
metadata = {};
}
} else if (metadata === null) {
metadata = {};
}
const documentName = metadata.filename || `supabase_doc_${doc.id}`;
if (!doc.content) {
console.log(`Bỏ qua ${doc.id} - không tìm thấy nội dung`);
continue;
}
const data = {
name: documentName,
content: doc.content,
metadata: metadata
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Tài liệu '${documentName}' đã được tải lên thành công!`);
results.push({ id: doc.id, success: true });
} else {
console.error(`Lỗi khi tải tài liệu ${documentName}: ${response.statusText}`);
results.push({ id: doc.id, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Lỗi khi tải tài liệu ${documentName}: ${error.message}`);
results.push({ id: doc.id, success: false, error: error.message });
}
// Thêm một khoảng thời gian nhỏ để tránh giới hạn tốc độ
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hàm di chuyển chính
async function migrateSupabaseToRememberizer() {
try {
console.log('Bắt đầu di chuyển từ Supabase pgvector sang Rememberizer...');
let offset = 0;
let totalMigrated = 0;
while (true) {
const documents = await fetchDocumentsFromSupabase(BATCH_SIZE, offset);
if (documents.length === 0) {
break;
}
console.log(`Đã lấy ${documents.length} tài liệu từ Supabase`);
const results = await uploadToRememberizer(documents);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Tiến độ: ${totalMigrated} tài liệu đã được di chuyển thành công`);
offset += BATCH_SIZE;
}
console.log(`Di chuyển hoàn tất! ${totalMigrated} tài liệu đã được di chuyển đến Rememberizer`);
} catch (error) {
console.error('Di chuyển thất bại:', error);
} finally {
await supabasePool.end();
}
}
// Chạy quá trình di chuyển
// migrateSupabaseToRememberizer();
Thực Hành Tốt Nhất Khi Di Chuyển
Hãy làm theo những khuyến nghị này để có một quá trình di chuyển thành công:
Lập Kế Hoạch Trước:
Ước lượng khối lượng dữ liệu và thời gian cần thiết cho việc di chuyển
Lên lịch di chuyển trong các khoảng thời gian có lưu lượng thấp
Tăng dung lượng ổ đĩa trước khi bắt đầu các cuộc di chuyển lớn
Kiểm Tra Trước:
Tạo một cửa hàng vector thử nghiệm trong Rememberizer
Di chuyển một tập hợp dữ liệu nhỏ (100-1000 vector)
Xác minh chức năng tìm kiếm với các truy vấn chính
Xác Thực Dữ Liệu:
So sánh số lượng tài liệu trước và sau khi di chuyển
Chạy các truy vấn chuẩn để đảm bảo kết quả tương tự
Xác thực rằng siêu dữ liệu được bảo tồn chính xác
Tối Ưu Hiệu Suất:
Sử dụng các thao tác theo lô để tăng hiệu quả
Cân nhắc việc đặt địa lý của cơ sở dữ liệu nguồn và đích
Giám sát giới hạn tỷ lệ API và điều chỉnh kích thước lô cho phù hợp
Các Bước Sau Khi Di Chuyển:
Xác minh việc tạo chỉ mục trong Rememberizer
Cập nhật cấu hình ứng dụng để trỏ đến cửa hàng vector mới
Giữ cơ sở dữ liệu nguồn như một bản sao lưu cho đến khi việc di chuyển được xác minh
Để tham khảo chi tiết về API và tài liệu điểm cuối, hãy truy cập trang Tài liệu Lưu Trữ Vector.
Hãy chắc chắn xử lý các khóa API một cách an toàn và tuân theo các thực hành tốt nhất cho việc quản lý khóa API.