Rememberizer Docs
Sign inSign upContact us
Tiếng Việt
Tiếng Việt
  • Tại sao lại là Rememberizer?
  • Bối cảnh
    • Vector Embeddings và Cơ sở dữ liệu Vector là gì?
    • Thuật ngữ
    • Thuật ngữ Chuẩn hóa
  • Sử Dụng Cá Nhân
    • Bắt Đầu
      • Tìm Kiếm Kiến Thức Của Bạn
      • Truy Cập Bộ Lọc Kỷ Niệm
      • Kiến Thức Chung
      • Quản Lý Kiến Thức Nhúng Của Bạn
  • Tích hợp
    • Ứng dụng Rememberizer
    • Tích hợp Rememberizer Slack
    • Tích hợp Rememberizer Google Drive
    • Tích hợp Rememberizer Dropbox
    • Tích hợp Rememberizer Gmail
    • Tích hợp Rememberizer Memory
    • Máy chủ Rememberizer MCP
    • Quản lý ứng dụng bên thứ ba
  • Tài nguyên cho nhà phát triển
    • Tổng quan về nhà phát triển
  • Tùy Chọn Tích Hợp
    • Đăng ký và sử dụng API Keys
    • Đăng ký ứng dụng Rememberizer
    • Ủy quyền cho ứng dụng Rememberizer
    • Tạo một Rememberizer GPT
    • Tích hợp LangChain
    • Vector Stores
    • Talk-to-Slack Ứng Dụng Web Mẫu
  • Tích hợp Doanh Nghiệp
    • Mô Hình Tích Hợp Doanh Nghiệp
  • Tham khảo API
    • Trang chính tài liệu API
    • Xác thực
  • API cốt lõi
    • Tìm kiếm tài liệu theo sự tương đồng ngữ nghĩa
    • Lấy tài liệu
    • Lấy nội dung tài liệu
    • Lấy nội dung Slack
    • Ghi nhớ nội dung vào Rememberizer
  • Tài khoản & Cấu hình
    • Lấy chi tiết tài khoản người dùng hiện tại
    • Danh sách các tích hợp nguồn dữ liệu có sẵn
    • Memento
    • Lấy tất cả kiến thức công khai đã thêm
  • API Lưu Trữ Vector
    • Tài liệu Lưu Trữ Vector
    • Lấy thông tin lưu trữ vector
    • Lấy danh sách tài liệu trong Lưu Trữ Vector
    • Lấy thông tin tài liệu
    • Thêm tài liệu văn bản mới vào Lưu Trữ Vector
    • Tải lên tệp vào Lưu Trữ Vector
    • Cập nhật nội dung tệp trong Lưu Trữ Vector
    • Xóa một tài liệu trong Lưu Trữ Vector
    • Tìm kiếm tài liệu Lưu Trữ Vector theo sự tương đồng ngữ nghĩa
  • Tài nguyên bổ sung
    • Thông báo
      • Điều khoản sử dụng
      • Chính sách bảo mật
      • B2B
        • Về Reddit Agent
  • Phiên bản
    • Trang ghi chú phát hành
  • Các bản phát hành năm 2025
    • 25 tháng 4, 2025
    • 18 tháng 4, 2025
    • 11 tháng 4, 2025
    • 4 tháng 4, 2025
    • 28 tháng 3, 2025
    • 21 tháng 3, 2025
    • 14 tháng 3, 2025
    • 17 tháng 1, 2025
  • Các bản phát hành năm 2024
    • 27 tháng 12 năm 2024
    • 20 tháng 12 năm 2024
    • 13 tháng 12 năm 2024
    • 6 tháng 12 năm 2024
  • 29 Tháng 11, 2024
  • 22 Tháng 11, 2024
  • 15 Tháng 11, 2024
  • 8 Tháng 11, 2024
  • 1 Tháng 11, 2024
  • 25 tháng 10 năm 2024
  • 18 tháng 10 năm 2024
  • 11 tháng 10 năm 2024
  • 4 tháng 10 năm 2024
  • 27 Tháng 9, 2024
  • 20 Tháng 9, 2024
  • 13 Tháng 9, 2024
  • 16 tháng 8 năm 2024
  • 9 tháng 8 năm 2024
  • 2 tháng 8 năm 2024
  • 26 Tháng 7, 2024
  • 12 Tháng 7, 2024
  • 28 tháng 6 năm 2024
  • 14 tháng 6 năm 2024
  • Ngày 31 tháng 5 năm 2024
  • Ngày 17 tháng 5 năm 2024
  • Ngày 10 tháng 5 năm 2024
  • 26 tháng 4, 2024
  • 19 tháng 4, 2024
  • 12 tháng 4, 2024
  • 5 tháng 4, 2024
  • 25 tháng 3 năm 2024
  • 18 tháng 3 năm 2024
  • 11 tháng 3 năm 2024
  • 4 tháng 3 năm 2024
  • 26 tháng 2 năm 2024
  • 19 tháng 2 năm 2024
  • 12 tháng 2 năm 2024
  • 5 tháng 2 năm 2024
  • 29 tháng 1 năm 2024
  • 22 tháng 1 năm 2024
  • 15 tháng 1 năm 2024
  • Tài liệu LLM
    • Tài liệu sẵn sàng LLM của Rememberizer
Powered by GitBook
On this page
  • Giới thiệu
  • Tổng Quan Kỹ Thuật
  • Cách Các Kho Vector Hoạt Động
  • Các Thành Phần Chính
  • Kiến trúc
  • Bắt đầu
  • Tạo một Cửa Hàng Vector
  • Tùy Chọn Cấu Hình
  • Quản lý Cửa hàng Vector
  • Quản lý Khóa API
  • Tạo Khóa API
  • Thu hồi khóa API
  • Sử dụng API Vector Store
  • Ví dụ Mã
  • Các yếu tố hiệu suất
  • Tối ưu hóa cho Các Khối Lượng Dữ Liệu Khác Nhau
  • Chiến Lược Chia Nhỏ
  • Tối ưu hóa truy vấn
  • Sử Dụng Nâng Cao
  • Tái lập chỉ mục
  • Cải Thiện Truy Vấn
  • Di chuyển từ các cơ sở dữ liệu vector khác
  • Tổng Quan Về Di Chuyển
  • Lợi ích của việc Chuyển đổi sang Rememberizer
  • Di chuyển từ Pinecone
  • Di chuyển từ Qdrant
  • Di chuyển từ Supabase pgvector
  • Thực Hành Tốt Nhất Khi Di Chuyển
  1. Tùy Chọn Tích Hợp

Vector Stores

Hướng dẫn này sẽ giúp bạn hiểu cách sử dụng Rememberizer Vector Store như một nhà phát triển.

PreviousTích hợp LangChainNextTalk-to-Slack Ứng Dụng Web Mẫu

Last updated 25 days ago

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:

  1. 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

  2. Khớp Tương Tự: Xác định nội dung có liên quan về mặt khái niệm

  3. 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

  1. Điều hướng đến phần Cửa Hàng Vector trong bảng điều khiển của bạn

  2. 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.

  3. Đ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).

  4. 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

  1. 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.

  2. 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ể.

  3. 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

  1. Truy cập trang chi tiết Vector Store của bạn

  2. Đ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"

  3. 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.

  4. Đ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ó.

  5. 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

Ví dụ sử dụng

=begin client = VectorStoreClient.new('your_api_key', 'vs_abc123')

Tìm kiếm tài liệu

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:

  1. Cụ thể trong các truy vấn tìm kiếm

  2. Bao gồm ngữ cảnh khi có thể

  3. Sử dụng ngôn ngữ tự nhiên thay vì từ khóa

  4. Đ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:

  1. Xuất dữ liệu từ cơ sở dữ liệu vector nguồn của bạn

  2. Chuyển đổi dữ liệu sang định dạng tương thích với Rememberizer

  3. Nhập dữ liệu vào Kho Dữ Liệu Vector Rememberizer của bạn

  4. 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:

  1. 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

  2. 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

  3. 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

  4. 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

  5. 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.

Vector Embeddings và Cơ sở dữ liệu Vector là gì?
Tạo một Cửa Hàng Vector Mới
Xem Chi tiết của một Cửa hàng Vector
Tạo Khóa API Mới
Tạo một Cửa Hàng Vector Mới
Xem Chi tiết của một Cửa hàng Vector
Tạo Khóa API Mới