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.

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 Vector Embeddings và Cơ sở dữ liệu Vector là gì?.

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ạo một Cửa Hàng Vector Mới
Tạo một Cửa Hàng Vector Mới

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.

Xem Chi tiết của một Cửa hàng Vector
Xem Chi tiết của một Cửa hàng Vector

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ể đó.

Tạo Khóa API Mới
Tạo Khóa API Mới

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?")

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_chunksnext_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()

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()

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()

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.

Last updated