全部产品
Search
文档中心

ApsaraDB RDS:Gunakan ApsaraDB RDS untuk PostgreSQL untuk membuat aplikasi RAG

更新时间:Jun 25, 2025

ApsaraDB RDS untuk PostgreSQL menyediakan penyimpanan vektor yang kuat dan pencarian teks lengkap yang efisien, menjadikannya database vektor ideal untuk aplikasi generasi yang diperkaya dengan pengambilan data (RAG) guna mengimplementasikan pengambilan berbasis kata kunci.

Pengenalan

Topik ini memberikan contoh cara menggunakan ApsaraDB RDS untuk PostgreSQL dalam pembuatan chatbot tiket khusus untuk menunjukkan keunggulannya dalam membangun aplikasi RAG. Setelah membaca topik ini, Anda dapat memperoleh informasi berikut:

  • Prosedur untuk menggunakan ApsaraDB RDS untuk PostgreSQL dalam pembuatan chatbot tiket khusus serta penggunaan ekstensi dan fungsi terkait.

  • Contoh multi-path recall untuk merasakan fitur kuat dan kemudahan penggunaan ApsaraDB RDS untuk PostgreSQL dalam RAG.

Prosedur

Menggunakan ApsaraDB RDS untuk PostgreSQL dalam pembuatan chatbot tiket khusus melibatkan beberapa langkah penting: pemrosesan data, multi-path recall, penggabungan sortir, dan analisis Q&A.

  • Pemrosesan Data

    Data sumber, termasuk data dari dokumentasi resmi, basis pengetahuan, dan tiket historis, diproses dan disimpan dalam instance ApsaraDB RDS untuk PostgreSQL. Pemrosesan data mencakup segmentasi data dan embedding.

  • Multi-path Recall

    • Recall berdasarkan kata kunci dokumen: melakukan pencarian kesamaan untuk mencocokkan pertanyaan pengguna dengan kata kunci dalam tabel dokumen dan mengembalikan N dokumen teratas dengan kesamaan tertinggi.

    • Recall berdasarkan kata kunci konten: melakukan pencarian kesamaan berdasarkan kata kunci konten dokumen untuk mencocokkan pertanyaan pengguna dengan kata kunci.

    • Recall berbasis BM25: melakukan analisis statistik pada skor relevansi berdasarkan frekuensi kata, jarak kata, dan pentingnya modul dokumen tempat kata-kata tersebut berada, lalu mengembalikan konten dengan skor tinggi.

    • Recall berbasis embedding: mengonversi pertanyaan menjadi embedding, menghitung kesamaan kosinusnya, lalu mengembalikan konten dengan kesamaan tinggi.

  • Merge Sort

    Algoritma fusi peringkat timbal balik (RRF) dan model bce-reranker-base_v1 open source digunakan untuk secara akurat mengurutkan hasil dari multi-path recall.

  • Analisis Q&A

    Pertanyaan dan jawaban mereka disimpan dalam database. Selama fase pengujian, kinerja Q&A dinilai untuk mengevaluasi efek dari berbagai kebijakan pengambilan.

Pemrosesan Data

Data sumber, termasuk data dari dokumentasi resmi, basis pengetahuan, dan tiket historis, diproses dan disimpan dalam instance RDS. Pemrosesan data mencakup segmentasi data dan embedding.

Pengumpulan Data

Data relevan diperoleh berdasarkan tujuan aplikasi RAG. Topik ini menggunakan chatbot tiket berbasis ApsaraDB RDS untuk PostgreSQL di DingTalk sebagai contoh untuk mengumpulkan data dari dokumen bantuan, basis pengetahuan, dan tiket historis.

Pemrosesan Data

Data sumber diproses dan disimpan dalam instance RDS dalam format tertentu. Misalnya, Anda dapat menggunakan kelas HTMLHeaderTextSplitter yang disediakan oleh kerangka kerja LangChain untuk membagi teks dokumen bantuan berdasarkan hierarki HTML, seperti H1 dan H2. Anda dapat menentukan ukuran segmentasi data dan ukuran tumpang tindih data untuk secara fleksibel mengontrol kinerja pembagian teks. Untuk informasi lebih lanjut, lihat berbagai pemisah teks yang disediakan oleh LangChain.

Catatan

Jika Anda perlu memproses dokumen Markdown, Anda dapat menggunakan kelas MarkdownHeaderTextSplitter dan flag seperti # dan ## untuk melakukan pemisahan hirarkis.

Penyimpanan Data

Data disimpan dalam dua tabel inti: dokumen dan embedding. Tabel dokumen digunakan untuk menyimpan informasi dokumen. Tabel embedding digunakan untuk menyimpan informasi embedding setelah segmentasi.

  • tabel dokumen

    Contoh:

    \d document
                                               Data table "public.document"
           Field        |            Type             | Collation |  Nullable  |                 Default
    -------------------+-----------------------------+----------+----------+--------------------------------------
     id                | bigint                      |          | not null | nextval('document_id_seq'::regclass)
     title             | character varying(255)      |          |          |
     url               | character varying(255)      |          |          | ''::character varying
     key_word          | character varying(255)      |          |          | ''::character varying
     tag               | character varying(255)      |          |          | ''::character varying
     created           | timestamp without time zone |          | not null | now()
     modified          | timestamp without time zone |          | not null | now()
     key_word_tsvector | tsvector                    |          |          |
     product_name      | character varying(255)      |          |          | ''::character varying
    Indexes:
        "document_pkey" PRIMARY KEY, btree (id)
        "document_key_word_tsvector_gin" gin (key_word_tsvector)
        "document_product_name_key" btree (product_name)
        "document_title_key" UNIQUE CONSTRAINT, btree (title)
    Triggers:
        trigger_update_tsvector BEFORE INSERT OR UPDATE ON document FOR EACH ROW EXECUTE FUNCTION update_tsvector()
    • tabel dokumen

      Tabel ini berisi bidang-bidang berikut: id, title, url, key_word, tag, created, modified, key_word_tsvector, dan product_name. Bidang key_word menunjukkan kata kunci. Bidang created menunjukkan waktu pembuatan. Bidang modified menunjukkan waktu modifikasi. Bidang key_word_tsvector menunjukkan nilai tsvector tertimbang dari kata kunci. Bidang key_word_tsvector digunakan untuk pencocokan kata kunci dan sebagai bagian dari recall berbasis kata kunci konten.

    • Indeks

      Indeks termasuk document_pkey, document_title_key, document_product_name_key, dan document_key_word_tsvector_gin. Indeks document_pkey adalah indeks untuk ID kunci utama. Indeks document_title_key adalah indeks untuk judul dokumen. Judul dokumen harus unik karena dokumen diperbarui berdasarkan judul dokumen. Indeks document_product_name_key adalah indeks untuk nama produk. Indeks document_key_word_tsvector_gin adalah indeks GIN untuk nilai tsvector. Di ApsaraDB RDS untuk PostgreSQL, indeks GIN diperbolehkan.

    • Pemicu

      Ketika tabel dokumen diperbarui atau data dimasukkan ke dalam tabel, pemicu secara otomatis memperbarui konten di kolom key_word_tsvector.

      Pernyataan SQL untuk membuat pemicu

      1. Buat fungsi yang memeriksa konten di kolom tag untuk penyisipan atau pembaruan data. Jika bidang tag diatur ke direct, konversikan kata kunci yang ditentukan oleh bidang key_word ke nilai tsvector dan tetapkan bobot A untuk nilai tsvector.

        Catatan

        Anda dapat menggunakan fungsi setweight yang disediakan oleh ApsaraDB RDS untuk PostgreSQL untuk menentukan bobot untuk nilai tsvector. Bobotnya adalah A, B, C, dan D dalam urutan menurun. Jika Anda menentukan bobot dan menggunakan recall berbasis kata kunci, dokumen yang bidang tag-nya diatur ke direct akan dicocokkan terlebih dahulu, diikuti oleh dokumen yang bidang tag-nya diatur ke aone. Bobot ditentukan berdasarkan prioritas.

      2. Buat pemicu untuk secara otomatis mengeksekusi fungsi update_tsvector(). Fungsi ini memperbarui konten di kolom key_word_tsvector ketika tabel dokumen diperbarui.

      CREATE OR REPLACE FUNCTION update_tsvector()
      RETURNS TRIGGER AS $$
      BEGIN
          IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
              IF NEW.tag = 'direct' THEN
                  NEW.key_word_tsvector := setweight(to_tsvector('jiebacfg', NEW.key_word), 'A');
              ELSIF NEW.tag = 'aone' THEN
                  NEW.key_word_tsvector := setweight(to_tsvector('jiebacfg', NEW.key_word), 'B');
              ELSIF NEW.tag IS NOT NULL THEN
                  NEW.key_word_tsvector := setweight(to_tsvector('jiebacfg', NEW.key_word), 'C');
              ELSE
                  NEW.key_word_tsvector := setweight(to_tsvector('jiebacfg', NEW.key_word), 'D');
              END IF;
          END IF;
      
          RETURN NEW;
      END;
      $$ LANGUAGE plpgsql;
      CREATE FUNCTION
        
      CREATE TRIGGER trigger_update_tsvector
      BEFORE INSERT OR UPDATE ON document
      FOR EACH ROW
      EXECUTE FUNCTION update_tsvector();
      CREATE TRIGGER
  • tabel embedding

    Contoh:

    \d embedding
                                               Data table "public.embedding"
           Field        |            Type             | Collation |  Nullable  |                 Default
    -------------------+-----------------------------+----------+----------+---------------------------------------
     id                | bigint                      |          | not null | nextval('embedding_id_seq'::regclass)
     doc_id            | integer                     |          |          | '-1'::integer
     content_chunk     | text                        |          | not null |
     content_embedding | vector(1536)                |          | not null |
     created           | timestamp without time zone |          | not null | now()
     modified          | timestamp without time zone |          | not null | now()
     ts_vector_extra   | tsvector                    |          |          |
    Indexes:
        "embedding_pkey" PRIMARY KEY, btree (id)
        "embedding_content_embedding_idx" hnsw (content_embedding vector_cosine_ops) WITH (m='16', ef_construction='64')
        "embedding_doc_id_key" btree (doc_id)
        "embedding_rumidx" rum (ts_vector_extra)
    Triggers:
        embedding_tsvector_update BEFORE INSERT OR UPDATE ON embedding FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger('ts_vector_extra', 'public.jiebacfg', 'content_chunk')
    • tabel embedding

      Tabel embedding berisi bidang-bidang berikut: id, doc_id, content_chunk, content_embedding, created, modified, dan ts_vector_extra. Bidang doc_id menunjukkan ID dokumen. Bidang content_chunk menunjukkan chunk setelah segmentasi. Bidang content_embedding menunjukkan embedding dari chunk yang diperoleh setelah segmentasi kata. Bidang created menunjukkan waktu pembuatan. Bidang modified menunjukkan waktu modifikasi. Bidang ts_vector_extra menunjukkan nilai tsvector dari chunk setelah segmentasi.

    • Indeks

      Indeks termasuk embedding_pkey, embedding_doc_id_key, embedding_content_embedding_idx, dan embedding_rumidx. Indeks embedding_pkey adalah indeks untuk kunci utama. Indeks embedding_doc_id_key adalah indeks untuk ID dokumen. Indeks embedding_content_embedding_idx adalah indeks vektor untuk kolom content_embedding. Indeks embedding_rumidx adalah indeks RUM untuk nilai tsvector.

    • Pemicu

      Ketika tabel embedding diperbarui atau data dimasukkan ke dalam tabel, pemicu secara otomatis memperbarui konten di kolom ts_vector_extra.

      Pernyataan SQL untuk membuat pemicu

      Pernyataan SQL serupa dengan pernyataan SQL yang digunakan untuk membuat pemicu untuk tabel dokumen.

      CREATE TRIGGER embedding_tsvector_update
      BEFORE INSERT OR UPDATE ON embedding
      FOR EACH ROW
      EXECUTE PROCEDURE tsvector_update_trigger('ts_vector_extra','public.jiebacfg','content_chunk');

Multi-path Recall

Recall berdasarkan kata kunci dokumen

Recall berdasarkan kata kunci dokumen melakukan pencarian kesamaan untuk mencocokkan pertanyaan pengguna dengan kata kunci dalam tabel dokumen dan mengembalikan N dokumen teratas dengan kesamaan tertinggi.

Recall berdasarkan kata kunci dokumen menggunakan indeks GIN yang telah ditentukan sebelumnya di ApsaraDB RDS untuk PostgreSQL untuk secara efisien mencocokkan kata kunci dalam instance RDS dengan pertanyaan pengguna.

  1. Konversikan kata kunci dalam dokumen menjadi nilai tsvector dan tetapkan bobot untuk nilai tsvector.

    Selama konversi, Anda harus menentukan mode segmentasi kata. Dalam banyak kasus, ekstensi segmentasi kata Cina pg_jieba dan zhparser digunakan. Untuk informasi lebih lanjut tentang cara menginstal ekstensi, lihat Kelola ekstensi.

    Anda dapat menggunakan fungsi to_tsvector untuk membagi kata kunci dan kemudian menggunakan fungsi setweight untuk menentukan bobot untuk string setelah segmentasi. Ini menambahkan informasi bobot ke informasi lokasi. Misalnya, Anda menggunakan ekstensi pg_jieba, atur mode segmentasi kata ke jiebacfg, dan gunakan fungsi setweight untuk menetapkan bobot kata kunci dokumen ke A.

    SELECT setweight(to_tsvector('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库'), 'A');
                                       setweight
    -------------------------------------------------------------------------------
     'postgresql':1A '世界':3A '先进':5A '关系':8A '型':9A '开源':7A '数据库':10A
  2. Konversikan pertanyaan pengguna menjadi nilai tsquery dan cocokkan nilai tsquery dengan kata kunci dokumen.

    Gunakan kemampuan pencarian teks lengkap ApsaraDB RDS untuk PostgreSQL untuk mencocokkan pertanyaan pengguna dengan kata kunci dokumen. Contoh pernyataan:

    SELECT 
        id, 
        title, 
        url, 
        key_word, 
        ts_rank(
            key_word_tsvector, 
            to_tsquery(replace(text(plainto_tsquery('jiebacfg', '%s')), '&', '|'))
        ) AS score 
    FROM 
        public.document 
    WHERE 
        key_word_tsvector @@ to_tsquery(replace(text(plainto_tsquery('jiebacfg', '%s')), '&', '|')) 
        AND product_name = '%s' 
    ORDER BY 
        score DESC 
    LIMIT 1;
    • Fungsi to_tsquery

      Gunakan fungsi to_tsquery untuk mengonversi pertanyaan pengguna menjadi nilai tsquery. Contoh:

      SELECT to_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库');
                                         to_tsquery
      --------------------------------------------------------------------------------
       'postgresql' <2> '世界' <2> '先进' <2> '开源' <-> '关系' <-> '型' <-> '数据库'

      <2> menunjukkan jarak antara dua kata.<-> menunjukkan hubungan berdekatan. Misalnya, 开源 dan 关系 harus berdekatan. Selain itu, kata-kata penghenti, seperti dan , secara otomatis dihapus. Ampersand (&) menunjukkan AND, batang vertikal (|) menunjukkan OR, dan tanda seru (!) menunjukkan NOT. Anda juga dapat menentukan bobot. Contoh:

      SELECT to_tsquery('jiebacfg', 'postgresql:A');
         to_tsquery
      ----------------
       'postgresql':A

      Input ke fungsi to_tsquery harus memenuhi persyaratan operator tsquery. Untuk memastikan bahwa pertanyaan pengguna dapat berhasil dikonversi menjadi nilai tsquery, Anda dapat menggunakan fungsi plainto_tsquery alih-alih fungsi to_tsquery untuk secara efektif mengabaikan operator yang tidak valid. Contoh:

      SELECT to_tsquery('jiebacfg','日志|&堆积');
      ERROR:  syntax error in tsquery: "日志|&堆积"
        
      SELECT plainto_tsquery('jiebacfg','日志|&堆积');
       plainto_tsquery
      -----------------
       '日志' & '堆积'

      Gunakan fungsi text untuk mengonversi hasil yang dikembalikan oleh fungsi plainto_tsquery menjadi nilai teks. Lalu, gunakan fungsi replace untuk mengganti & dengan | untuk mengubah kondisi pencocokan dari AND menjadi OR. Contoh:

      -- Gunakan fungsi plainto_tsquery.
      SELECT plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库');
                                plainto_tsquery
      --------------------------------------------------------------------
       'postgresql' & '世界' & '先进' & '开源' & '关系' & '型' & '数据库'
      
      -- Gunakan fungsi plainto_tsquery, text, dan replace.
      SELECT replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|');
                                    replace
      --------------------------------------------------------------------
       'postgresql' | '世界' | '先进' | '开源' | '关系' | '型' | '数据库'
      
      -- Gunakan fungsi to_tsquery, plainto_tsquery, text, dan replace.
      SELECT to_tsquery(replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|'));
                                   to_tsquery
      --------------------------------------------------------------------
       'postgresql' | '世界' | '先进' | '开源' | '关系' | '型' | '数据库'

      Gunakan fitur segmentasi kata kustom dari ekstensi pg_jieba untuk membuat metode segmentasi kata kustom. Misalnya, hasil segmentasi teks adalah '关系' & '型' sebelum Anda menambahkan 关系型 ke kamus kustom dan menjadi '关系型' setelah Anda menambahkan 关系型 ke kamus kustom.

      -- Secara otomatis tambahkan 关系型 ke kamus kustom 0 dengan bobot 100000.
      INSERT INTO jieba_user_dict VALUES ('关系型',0,100000);
      
      -- Muat kamus kustom 0. Angka pertama 0 menunjukkan nomor urut kamus kustom, dan angka kedua 0 menunjukkan bahwa kamus default dimuat. 
      SELECT jieba_load_user_dict(0,0);
       jieba_load_user_dict
      ----------------------
      
      -- Konversikan pertanyaan pengguna menjadi nilai tsquery.
      SELECT to_tsquery(replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|'));
                                   to_tsquery
      --------------------------------------------------------------------
       'postgresql' | '世界' | '先进' | '开源' | '关系型' | '数据库' 
    • Operator

      ApsaraDB RDS untuk PostgreSQL menyediakan berbagai operator untuk melakukan operasi pada nilai tsvector setelah segmentasi kata dan nilai tsquery. Misalnya, Anda dapat menggunakan @@ untuk menunjukkan apakah nilai tsvector cocok dengan nilai tsquery.

      SELECT to_tsvector('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库') @@ to_tsquery('jiebacfg', 'postgresql:A');
       ?column?
      ----------
       f
      
      
      SELECT setweight(to_tsvector('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库'),'A') @@ to_tsquery('jiebacfg', 'postgresql:A');
       ?column?
      ----------
       t

      Kondisi kueri adalah kata postgresql dengan bobot A. Dalam hal ini, meskipun nilai tsvector yang ingin Anda kueri berisi kata postgresql, false dikembalikan karena bobot A tidak ditetapkan. Namun, jika bobot A ditetapkan untuk nilai tsvector yang ingin Anda kueri dengan menggunakan fungsi setweight, true dikembalikan.

    • Fungsi ts_rank

      Gunakan fungsi ts_rank untuk menghitung derajat kecocokan antara nilai tsquery dan nilai tsvector yang ingin Anda kueri. Misalnya, kondisi kueri adalah postgresql | 开源. Baris yang ingin Anda kueri harus berisi setidaknya satu dari kata kunci postgresql dan 开源. Kalimat pertama berisi kedua kata kunci. Skornya lebih tinggi daripada kalimat kedua yang hanya berisi kata kunci 开源. Kalimat ketiga dilewati oleh operator @@ karena kalimat tersebut tidak berisi postgresql atau 开源.

      WITH sentence AS (
          SELECT 'PostgreSQL是世界上先进的开源关系型数据库' AS content
          UNION ALL
          SELECT 'MySQL是应用广泛的开源关系数据库'
          UNION ALL
          SELECT 'MySQL在全球非常流行'
      )
      SELECT content,
             ts_rank(to_tsvector('jiebacfg', content), to_tsquery('jiebacfg', 'postgresql | 开源')) AS score
      FROM sentence
      WHERE to_tsvector('jiebacfg', content) @@ to_tsquery('jiebacfg', 'postgresql | 开源')
      ORDER BY score DESC;
      
                        content                   |    score
      --------------------------------------------+-------------
       PostgreSQL是世界上先进的开源关系型数据库 |  0.06079271
       MySQL是应用广泛的开源关系数据库          | 0.030396355

      Dalam kasus ekstrem, jika Anda menghadapi masalah segmentasi kata atau input berisi karakter yang salah, Anda mungkin gagal mencocokkan dokumen apa pun. Untuk mencegah masalah ini, ApsaraDB RDS untuk PostgreSQL memungkinkan Anda menggunakan ekstensi pg_bigm untuk melakukan pencarian berbasis pencocokan fuzzy. Anda dapat menggunakan fungsi bigm_similarity untuk mengembalikan dokumen dengan kesamaan tertinggi. Contoh:

      WITH sentence AS (
          SELECT 'PostgreSQL是世界上先进的开源关系型数据库' AS content
          UNION ALL
          SELECT 'MySQL是应用广泛的开源关系数据库'
          UNION ALL
          SELECT 'MySQL在全球非常流行'
      )
      SELECT 
          content, 
          bigm_similarity(content, 'postgres | 开源产品') AS score 
      FROM 
          sentence
      ORDER BY 
          score DESC;
      
                        content                   |   score
      --------------------------------------------+------------
         PostgreSQL是世界上先进的开源关系型数据库 | 0.23076923
         MySQL是应用广泛的开源关系数据库          | 0.05263158
         MySQL在全球非常流行                      |        0.0
      (3 rows)

      Fungsi bigm_similarity mengonversi dua teks input menjadi elemen 2-gram yang merupakan kombinasi dari dua karakter berturut-turut atau dua kata. Kemudian, fungsi menghitung jumlah elemen antara teks input. Nilai valid: [0, 1]. Nilai 1 menunjukkan bahwa teks-teks tersebut sama. Jika segmentasi tidak akurat, ada kesalahan ejaan, atau singkatan digunakan, Anda dapat menggunakan ekstensi pg_bigm untuk melakukan pencarian berbasis pencocokan fuzzy. Untuk informasi lebih lanjut, lihat Gunakan ekstensi pg_bigm untuk melakukan kueri berbasis pencocokan fuzzy.

Recall berdasarkan kata kunci konten

Untuk mencari konten dokumen, Anda dapat menggunakan metode yang sama seperti yang Anda gunakan dalam recall berdasarkan kata kunci dokumen. Dalam banyak kasus, konten dokumen lebih panjang daripada kata kunci. Jika Anda melakukan pencarian teks lengkap, kami sarankan Anda menggunakan ekstensi RUM untuk mempercepat pencarian. Misalnya, Anda dapat menggunakan rencana kueri sampel untuk melakukan pencarian kesamaan dan mencocokkan pertanyaan pengguna dengan kata kunci konten dokumen.

  • Ekstensi RUM didasarkan pada indeks GIN dan menyimpan informasi tambahan, termasuk posisi dan cap waktu sebuah kata. Rencana kueri berikut menggunakan rencana eksekusi ekstensi RUM, menggunakan indeks embedding_rumidx, menyaring data, menghitung kesamaan, dan mengurutkan hasil. Semua operasi diselesaikan oleh indeks, yang memastikan efisiensi kueri. Kueri memakan waktu 3,219 ms.

    Gunakan ekstensi RUM untuk menjalankan pencarian teks lengkap

    EXPLAIN ANALYZE
    SELECT
        id,
        doc_id,
        content_chunk,
        ts_vector_extra <=> to_tsquery(
            REPLACE(
                TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                '&',
                '|'
            )
        ) AS similarity
    FROM
        embedding
    WHERE
        ts_vector_extra @@ to_tsquery(
            REPLACE(
                TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                '&',
                '|'
            )
        )
    ORDER BY
        similarity
    LIMIT
        10;
                                                                     QUERY PLAN
    --------------------------------------------------------------------------------------------------------------------------------------------
     Limit  (cost=10.15..22.14 rows=10 width=521) (actual time=3.117..3.182 rows=10 loops=1)
       ->  Index Scan using embedding_rumidx on embedding  (cost=10.15..6574.53 rows=5474 width=521) (actual time=3.115..3.179 rows=10 loops=1)
             Index Cond: (ts_vector_extra @@ to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
             Order By: (ts_vector_extra <=> to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
     Planning Time: 0.296 ms
     Execution Time: 3.219 ms
    (6 rows)
  • Rencana kueri berikut menggunakan indeks GIN asli yang dibangun berdasarkan kolom ts_vector_extra redundan. Rencana eksekusi indeks GIN asli lebih kompleks daripada rencana eksekusi ekstensi RUM. Rencanaeksekusi indeks GIN asli memulai dua proses dan menggunakan pemindaian indeks bitmap alih-alih pemindaian indeks dalam RUM. Secara spesifik, gunakan indeks untuk mendapatkan bitmap dari semua baris yang memenuhi kondisi kueri dan gunakan indeks yang ditentukan oleh embedding_ts_vector_gin untuk mengidentifikasi baris terkait. Lakukan penyaringan sekunder untuk mencari hasil yang valid. Lalu, gunakan algoritma Top-N untuk mengurutkan hasil dan lakukan penggabungan proses untuk menggabungkan hasil. Kueri memakan waktu 14,234 ms.

    Gunakan indeks GIN asli untuk mempercepat kueri

    EXPLAIN ANALYZE
    SELECT
        id,
        doc_id,
        content_chunk,
        ts_rank(
            ts_vector_extra,
            to_tsquery(
                REPLACE(
                    TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                    '&',
                    '|'
                )
            )
        ) AS similarity
    FROM
        embedding
    WHERE
        ts_vector_extra @@ to_tsquery(
            REPLACE(
                TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                '&',
                '|'
            )
        )
    ORDER BY
        similarity
    LIMIT
        10;
                                                                           QUERY PLAN
    ---------------------------------------------------------------------------------------------------------------------------------------------------------
     Limit  (cost=7178.59..7179.76 rows=10 width=520) (actual time=10.526..14.192 rows=10 loops=1)
       ->  Gather Merge  (cost=7178.59..7718.33 rows=4626 width=520) (actual time=10.525..14.189 rows=10 loops=1)
             Workers Planned: 2
             Workers Launched: 2
             ->  Sort  (cost=6178.57..6184.35 rows=2313 width=520) (actual time=6.879..6.880 rows=10 loops=3)
                   Sort Key: (ts_rank(ts_vector_extra, to_tsquery('''wal'' | ''日志'' | ''堆积'''::text)))
                   Sort Method: top-N heapsort  Memory: 37kB
                   Worker 0:  Sort Method: top-N heapsort  Memory: 39kB
                   Worker 1:  Sort Method: top-N heapsort  Memory: 40kB
                   ->  Parallel Bitmap Heap Scan on embedding  (cost=56.47..6128.59 rows=2313 width=520) (actual time=0.567..6.367 rows=1637 loops=3)
                         Recheck Cond: (ts_vector_extra @@ to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
                         Heap Blocks: exact=1515
                         ->  Bitmap Index Scan on embedding_ts_vector_gin  (cost=0.00..55.08 rows=5551 width=0) (actual time=0.794..0.794 rows=4910 loops=1)
                               Index Cond: (ts_vector_extra @@ to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
     Planning Time: 0.291 ms
     Execution Time: 14.234 ms
  • Indeks GIN dibangun pada to_tsvector('jiebacfg'::regconfig, content_chunk). Rencana eksekusi indeks GIN ini mirip dengan rencana eksekusi indeks GIN yang dibangun pada kolom ts_vector_extra. Kondisi WHERE sama, dan jumlah baris yang masuk ke tahap peringkat juga serupa. Perbedaan utama terletak pada perhitungan ts_rank. Fungsi ts_rank memerlukan informasi lokasi kata. Saat indeks GIN dibuat, informasi lokasi tidak disimpan. Jika Anda menggunakan fungsi ts_rank, fungsi to_tsvector dieksekusi pada setiap baris, yang memakan waktu. Kueri memakan waktu 1081,547 ms.

    Indeks GIN dibangun pada to_tsvector('jiebacfg'::regconfig, content_chunk)

    EXPLAIN ANALYZE
    SELECT
        id,
        doc_id,
        content_chunk,
        ts_rank(
            to_tsvector('jiebacfg', content_chunk),
            to_tsquery(
                REPLACE(
                    TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                    '&',
                    '|'
                )
            )
        ) AS similarity
    FROM
        embedding
    WHERE
        to_tsvector('jiebacfg', content_chunk) @@ to_tsquery(
            REPLACE(
                TEXT(plainto_tsquery('jiebacfg', 'wal日志堆积怎么办')),
                '&',
                '|'
            )
        )
    ORDER BY
        similarity
    LIMIT
        10;
                                                                          QUERY PLAN
    -------------------------------------------------------------------------------------------------------------------------------------------------------
     Limit  (cost=8253.58..8254.75 rows=10 width=521) (actual time=1079.289..1081.510 rows=10 loops=1)
       ->  Gather Merge  (cost=8253.58..8786.55 rows=4568 width=521) (actual time=1079.287..1081.508 rows=10 loops=1)
             Workers Planned: 2
             Workers Launched: 2
             ->  Sort  (cost=7253.56..7259.27 rows=2284 width=521) (actual time=1073.189..1073.191 rows=10 loops=3)
                   Sort Key: (ts_rank(to_tsvector('jiebacfg'::regconfig, content_chunk), to_tsquery('''wal'' | ''日志'' | ''堆积'''::text)))
                   Sort Method: top-N heapsort  Memory: 43kB
                   Worker 0:  Sort Method: top-N heapsort  Memory: 42kB
                   Worker 1:  Sort Method: top-N heapsort  Memory: 37kB
                   ->  Parallel Bitmap Heap Scan on embedding  (cost=55.93..7204.20 rows=2284 width=521) (actual time=2.127..1072.159 rows=1637 loops=3)
                         Recheck Cond: (to_tsvector('jiebacfg'::regconfig, content_chunk) @@ to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
                         Heap Blocks: exact=1028
                         ->  Bitmap Index Scan on embedding_content_gin  (cost=0.00..54.56 rows=5481 width=0) (actual time=0.808..0.809 rows=4910 loops=1)
                               Index Cond: (to_tsvector('jiebacfg'::regconfig, content_chunk) @@ to_tsquery('''wal'' | ''日志'' | ''堆积'''::text))
     Planning Time: 0.459 ms
     Execution Time: 1081.547 ms
    (16 rows)

Recall berbasis BM25

BM25 adalah algoritma pencocokan teks klasik yang mempertimbangkan efek frekuensi istilah (TF) dan frekuensi dokumen terbalik (IDF). Kata dengan TF besar menunjukkan bahwa kata tersebut sering muncul dalam dokumen dan memiliki hubungan kuat. Kata dengan IDF besar menunjukkan bahwa kata tersebut muncul di banyak dokumen dan memiliki tingkat kepentingan rendah. Algoritma BM25 memperkenalkan parameter untuk mengoptimalkan algoritma TF-IDF dan meningkatkan efek kueri.

Recall berbasis BM25 digunakan sebagai metode pengambilan berbasis kata kunci dan dibandingkan dengan metode pengambilan berbasis kata kunci ApsaraDB RDS untuk PostgreSQL. Metode pengambilan berbasis kata kunci ApsaraDB RDS untuk PostgreSQL menggunakan fungsi bawaan seperti ts_rank dan mempertimbangkan frekuensi kata, jarak kata, dan pentingnya kata dalam setiap bagian dokumen. Hasil recall berbasis BM25 dapat dianggap sebagai bagian dari hasil pengambilan berbasis kata kunci untuk meningkatkan akurasi pengambilan.

Recall berbasis Embedding

ApsaraDB RDS untuk PostgreSQL mendukung ekstensi pencarian kesamaan vektor dimensi tinggi (pgvector) dan generasi vektor (rds_embedding). Ekstensi pgvector mendukung tipe data vektor yang diperlukan dan operasi data vektor dasar, seperti perhitungan jarak dan kesamaan antara vektor. Ekstensi rds_embedding hanya menerjemahkan teks dimensi tinggi menjadi embedding. Untuk informasi lebih lanjut, lihat Gunakan ekstensi pgvector untuk melakukan pencarian kesamaan vektor dimensi tinggi dan Gunakan ekstensi rds_embedding untuk menghasilkan vektor.

Di ApsaraDB RDS untuk PostgreSQL, vektor dapat disimpan sebagai array. Namun, tipe data masih harus didefinisikan sebagai tipe vektor. Saat Anda melakukan perhitungan vektor dan peringkat, jika Anda tidak membuat indeks untuk tipe vektor, overhead pemindaian tabel penuh dan peringkat akan meningkat secara signifikan.

Ekstensi pgvector mendukung metode pengindeksan Hierarchical Navigable Small World (HNSW) dan Inverted File with Flat Compression (IVFFlat) untuk pencarian tetangga terdekat perkiraan (ANN). Pengindeksan HNSW tidak memerlukan penyisipan data dan memberikan kecepatan kueri lebih cepat daripada pengindeksan IVFFlat. Akibatnya, pengindeksan HNSW digunakan dalam metode ini.

SELECT 
    embedding.id, 
    doc_id, 
    content_chunk, 
    content_embedding <=> '%s' AS similarity 
FROM 
    public.embedding 
LEFT JOIN 
    document ON document.id = embedding.doc_id 
WHERE 
    product_name = '%s' 
ORDER BY 
    similarity 
LIMIT %s;
Catatan

Merge Sort

Metode ini menggunakan algoritma RRF dan model bce-reranker-base_v1 open source untuk secara akurat mengurutkan hasil dari recall berbasis kata kunci dokumen, recall berbasis kata kunci konten, recall berbasis BM25, dan recall berbasis embedding.

  • Algoritma RRF mudah dipahami. Dalam rumus berikut, menunjukkan dokumen yang diperlukan, menunjukkan peringkat dokumen dalam sistem , dan adalah konstanta. Anda dapat mengatur k ke 60 atau nilai lainnya. Anda dapat menjumlahkan peringkat dokumen dalam sistem untuk mendapatkan hasil akhir. Semakin tinggi peringkat, semakin besar nilai yang diperoleh dalam urutan terbalik. Akibatnya, nilai RRF yang dihitung juga semakin besar. Jika dokumen berperingkat tinggi di beberapa sistem, nilai RRF dokumen tersebut meningkat secara signifikan. Algoritma RRF dapat digunakan untuk secara efektif mengurutkan chunk dari multi-path recall.

  • bce-reranker-base_v1 adalah model algoritma representasi semantik lintas bahasa yang bertujuan untuk mengoptimalkan hasil pencarian semantik dan peringkat relevansi. Model ini mendukung bahasa Cina, Inggris, Jepang, dan Korea, dan memiliki kemampuan peringkat halus yang kuat. Dalam skenario nyata, model ini memerlukan waktu yang lebih lama untuk peringkat halus daripada melakukan recall, terutama ketika sejumlah besar chunk perlu diurutkan. Hal ini dapat memengaruhi kelancaran sesi. Untuk mencapai respons yang lebih cepat dari chatbot tiket khusus, Anda dapat menggunakan algoritma RRF yang sederhana dan efisien untuk mengurutkan hasil atau melakukan peringkat halus setelah peringkat RRF. Jika Anda memerlukan akurasi tinggi, Anda dapat langsung menggunakan model bce-reranker-base_v1 untuk mengurutkan hasil.

Analisis Q&A

Kebijakan yang berbeda didefinisikan untuk chatbot tiket khusus untuk merespons sumber data yang berbeda. Ini membantu mencegah pemrosesan konten yang tidak terduga di bidang prompt_content saat model besar dipanggil.

  • Konten dari basis pengetahuan tidak digunakan sebagai input bidang prompt_content untuk model besar untuk diproses. Sebagai gantinya, konten tersebut langsung disediakan.

  • Konten dari dokumentasi resmi dirangkum dan diformat oleh model besar karena file HTML yang diperoleh dibagi dan mungkin memiliki masalah tata letak dan konten duplikat.

  • Konten dari model besar hanya disediakan secara langsung ketika basis pengetahuan dan dokumentasi resmi tidak dapat memberikan jawaban yang diperlukan. Model besar dipanggil secara langsung untuk menyelesaikan masalah dalam sejumlah kecil skenario. Dalam banyak kasus, model besar berfungsi sebagai asisten pengetahuan umum.

  • Konten dari tiket historis hanya disediakan dengan nama tiket dan URL.

Dokumen terkait dan tautannya disediakan untuk setiap bagian jawaban. Jika masalah tidak dapat diselesaikan berdasarkan jawaban, kami sarankan Anda memeriksa dokumen asli untuk mendapatkan konten yang lebih komprehensif dan akurat.

Dalam fase pengujian, skor dari pertanyaan dan jawaban terbaru dapat digunakan sebagai penilaian awal terhadap efektivitas kebijakan saat ini. Anda dapat menulis kode untuk membuat beberapa kebijakan dan kemudian menentukan kebijakan recall yang paling cocok berdasarkan pengujian.

prompt = f'''Silakan rangkum dan format ulang konten berikut dan atur format output, 
        ```
        {prompt_content}
        ```
        Berdasarkan kemampuan Anda sendiri, buatlah jawaban, pertanyaan saya adalah: {question}. 
        '''

Hubungkan ke Chatbot DingTalk

Anda dapat menggunakan Streamlit untuk membuat aplikasi web atau terhubung ke chatbot DingTalk. Aplikasi web digunakan untuk pengujian mandiri dan manajemen dokumen. Chatbot DingTalk memungkinkan semua pengguna mengakses layanan.

Dalam setiap sesi Q&A di grup DingTalk, koneksi baru perlu dibuat di tingkat database. Pembuatan koneksi yang sering dapat menyebabkan masalah kinerja, termasuk konsumsi waktu dan memori. Jika koneksi tidak segera dilepaskan, jumlah koneksi dapat mencapai batas atas dan koneksi baru tidak dapat dibuat ke database. Anda dapat menggunakan kumpulan koneksi dalam proyek Anda untuk mencegah koneksi singkat yang sering. Anda juga dapat menggunakan kumpulan koneksi PgBouncer bawaan ApsaraDB RDS untuk PostgreSQL.

Contoh

Dalam contoh ini, multi-path recall digunakan untuk menggambarkan fitur yang kuat dan kemudahan penggunaan ApsaraDB RDS untuk PostgreSQL dalam RAG. Dalam contoh ini, pengguna mengajukan pertanyaan tentang 介绍PostgreSQL. Hasil dari tiga metode recall diperoleh.

Siapkan Data

  1. Gunakan akun istimewa untuk mengeksekusi pernyataan SQL berikut pada database yang diperlukan untuk menginstal ekstensi pg_jieba, pgvector, RUM, dan rds_embedding:

    Penting
    • Sebelum Anda menginstal ekstensi pg_jieba, Anda harus menambahkan pg_jieba ke value parameter shared_preload_libraries. Untuk informasi lebih lanjut tentang cara memodifikasi parameter shared_preload_libraries, lihat Modifikasi parameter instance ApsaraDB RDS untuk PostgreSQL.

    • Anda dapat mengeksekusi pernyataan SELECT * FROM pg_extension; untuk melihat ekstensi yang telah diinstal.

    CREATE EXTENSION IF NOT EXISTS pg_jieba;
    CREATE EXTENSION IF NOT EXISTS vector;
    CREATE EXTENSION IF NOT EXISTS rum;
    CREATE EXTENSION IF NOT EXISTS rds_embedding;
  2. Buat gateway NAT untuk virtual private cloud (VPC) tempat instance RDS berada untuk memungkinkan instance RDS mengakses model eksternal. Untuk informasi lebih lanjut, lihat Gunakan ekstensi rds_embedding untuk menghasilkan vektor.

    Catatan

    Secara default, Anda tidak dapat terhubung ke instance RDS melalui Internet. Saat Anda menggunakan model besar eksternal, seperti model text embedding yang disediakan oleh Alibaba Cloud Model Studio, Anda harus membuat gateway NAT untuk VPC tempat instance RDS berada agar instance RDS dapat mengakses model eksternal.

  3. Eksekusi pernyataan SQL berikut pada database yang diperlukan untuk membuat tabel uji bernama doc dan embed, dan buat indeks untuk tabel:

    --Buat tabel uji doc dan indeks untuk tabel.
    DROP TABLE IF EXISTS doc;
    
    CREATE TABLE doc (
        id bigserial PRIMARY KEY,
        title character varying(255) UNIQUE,
        key_word character varying(255) DEFAULT ''
    );
    
    CREATE INDEX doc_gin ON doc 
    USING GIN (to_tsvector('jiebacfg', key_word));
    
    --Buat tabel uji embed dan indeks untuk tabel.
    DROP TABLE IF EXISTS embed;
    
    CREATE TABLE embed (
        id bigserial PRIMARY KEY,
        doc_id integer,
        content text,
        embedding vector(1536),
        ts_vector_extra tsvector
    );
    
    CREATE INDEX ON embed 
    USING hnsw (embedding vector_cosine_ops) 
    WITH (
        m = 16, 
        ef_construction = 64
    );
  4. Eksekusi pernyataan SQL berikut untuk membuat pemicu. Saat baris di tabel embed diperbarui atau data dimasukkan ke dalam baris, kolom ts_vector_extra diperbarui secara otomatis.

    -- Konversikan teks menjadi nilai tsvector untuk pencarian teks lengkap berdasarkan kata kunci.
    CREATE TRIGGER embed_tsvector_update 
    BEFORE UPDATE OR INSERT 
    ON embed 
    FOR EACH ROW 
    EXECUTE PROCEDURE tsvector_update_trigger('ts_vector_extra', 'public.jiebacfg', 'content');
  5. Eksekusi pernyataan SQL berikut. Setiap kali penyisipan atau pembaruan dilakukan pada tabel embed, embedding dihasilkan berdasarkan konten yang disisipkan atau diperbarui dan disimpan di kolom embedding.

    Penting

    Dalam contoh ini, model text embedding yang disediakan oleh Alibaba Cloud Model Studio digunakan. Anda harus mengaktifkan Alibaba Cloud Model Studio dan memperoleh Kunci API yang diperlukan. Untuk informasi lebih lanjut, lihat Memperoleh Kunci API.

    -- Konversikan pertanyaan menjadi embedding. Tentukan parameter api_key berdasarkan kebutuhan bisnis Anda.
    CREATE OR REPLACE FUNCTION update_embedding()
    RETURNS TRIGGER AS $$
    BEGIN
        NEW.embedding := rds_embedding.get_embedding_by_model('dashscope', 'sk-****', NEW.content)::real[];
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    CREATE TRIGGER set_embedding BEFORE INSERT OR UPDATE ON embed FOR EACH ROW EXECUTE FUNCTION update_embedding();
  6. Masukkan data uji ke dalam tabel.

    INSERT INTO doc(id, title, key_word) VALUES 
    (1, 'Pengenalan PostgreSQL', 'PostgreSQL Plugin'), 
    (2, 'Pengenalan MySQL', 'MySQL MGR'), 
    (3, 'Pengenalan SQL Server', 'SQL Server Microsoft');
    
    INSERT INTO embed(doc_id, content) VALUES 
    (1, 'PostgreSQL adalah sistem manajemen basis data relasional objek (ORDBMS) yang dikembangkan dari POSTGRES versi 4.2 yang dikembangkan oleh Departemen Ilmu Komputer Universitas California, Berkeley. Banyak konsep yang dipimpin oleh POSTGRES muncul jauh kemudian di beberapa sistem database komersial.'), 
    (1, 'PostgreSQL adalah penerus sumber terbuka asli dari kode Berkeley. Ini mendukung sebagian besar standar SQL dan menyediakan banyak fitur modern: query kompleks, kunci asing, pemicu, tampilan yang dapat diperbarui, integritas transaksi, kontrol konkurensi versi multi, juga, PostgreSQL dapat diperluas dengan banyak cara, misalnya, dengan menambahkan yang baru: tipe data, fungsi, operator, fungsi agregat, metode indeks, bahasa prosedural'), 
    (1, 'Dan, karena lisensi yang bebas dan longgar, siapa pun dapat menggunakan, memodifikasi, dan mendistribusikan PostgreSQL secara gratis untuk tujuan apa pun, baik untuk penggunaan pribadi, komersial, maupun penelitian akademik.'), 
    (1, 'Plugin Ganos dan plugin PostGIS tidak dapat diinstal di bawah Schema yang sama'), 
    (1, 'Ekosistem yang kaya: ada banyak plugin dan ekstensi siap pakai yang tersedia, seperti PostGIS (pemrosesan informasi geografis), TimescaleDB (basis data deret waktu), pg_stat_statements (pemantauan kinerja), dll., yang dapat memenuhi kebutuhan berbagai skenario.');
    
    INSERT INTO embed(doc_id, content) VALUES 
    (2, 'Asal-usul nama MySQL tidak jelas. Selama lebih dari 10 tahun, direktori dasar kami serta banyak perpustakaan dan alat menggunakan awalan "my". Namun, nama putri salah satu pendiri, Monty Widenius, juga "My". Hingga hari ini, asal-usul nama MySQL masih menjadi misteri, bahkan bagi kami.'), 
    (2, 'Perangkat lunak MySQL menggunakan lisensi ganda. Pengguna dapat menggunakan perangkat lunak MySQL sebagai produk sumber terbuka berdasarkan ketentuan Lisensi Publik Umum GNU (http://www.fsf.org/licenses/) atau membeli lisensi komersial standar dari MySQL AB. Untuk informasi lebih lanjut tentang strategi lisensi kami, lihat http://www.mysql.com/company/legal/licensing/.'), 
    (2, 'Replikasi Grup MySQL Group Replication (MGR) adalah bentuk replikasi terdistribusi berbasis protokol Paxos yang diimplementasikan oleh MySQL resmi di atas kerangka kerja replikasi Binlog yang sudah ada. Seri instance klaster RDS MySQL mendukung replikasi grup. Artikel ini menjelaskan cara membuat metode replikasi menjadi replikasi grup. Klaster MySQL yang menggunakan replikasi grup dapat mengelola dirinya sendiri berdasarkan protokol Paxos terdistribusi, dengan keandalan data yang kuat dan konsistensi data yang kuat. Dibandingkan dengan metode replikasi utama-cadangan tradisional, replikasi grup memiliki keunggulan berikut: konsistensi data yang kuat, keandalan data yang kuat, konsistensi transaksi global yang kuat.');
    
    INSERT INTO embed(doc_id, content) VALUES 
    (3, 'Microsoft SQL Server adalah sistem manajemen basis data relasional (RDBMS). Aplikasi dan alat terhubung ke instance atau basis data SQL Server dan berkomunikasi menggunakan Transact-SQL (T-SQL).'), 
    (3, 'SQL Server 2022 (16.x) dibangun di atas versi sebelumnya, bertujuan untuk mengembangkan SQL Server menjadi platform yang menyediakan opsi bahasa pengembangan, tipe data, lingkungan lokal atau cloud, dan opsi sistem operasi.'), 
    (3, 'SQL Server sangat populer dalam aplikasi tingkat perusahaan, terintegrasi mulus dengan produk Microsoft lainnya (seperti Excel, Power BI) untuk mempermudah analisis data.');

Lakukan Multi-path Recall

Eksekusi pernyataan SQL berikut untuk mengambil teks kueri 介绍一下postgresql dari beberapa metode dan mengurutkan dokumen terkait berdasarkan kesamaan.

-- Teks yang ingin Anda kueri.
WITH query AS (
    SELECT '介绍一下postgresql' AS query_text
),
-- Konversikan pertanyaan menjadi embedding. Ganti sk-**** dengan Kunci API yang diperoleh dari Alibaba Cloud Model Studio.
query_embedding AS (
    SELECT rds_embedding.get_embedding_by_model('dashscope', 'sk-****', query.query_text)::real[]::vector AS embedding
    FROM query
),
-- Jalankan pencarian berdasarkan kata kunci dokumen dan urutkan hasil menggunakan ts_rank. Kesamaan tinggi menunjukkan skor tinggi.
first_method AS (
    SELECT 
        id, 
        title, 
        ts_rank(to_tsvector('jiebacfg', doc.key_word), 
                to_tsquery(replace(text(plainto_tsquery('jiebacfg', (SELECT query_text FROM query))), '&', '|'))) AS score, 
        'doc_key_word' AS method
    FROM doc
    WHERE 
        to_tsvector('jiebacfg', doc.key_word) @@ 
        to_tsquery(replace(text(plainto_tsquery('jiebacfg', (SELECT query_text FROM query))), '&', '|'))
    ORDER BY 
        score DESC
    LIMIT 3
),
-- Jalankan pencarian teks lengkap berdasarkan kata kunci konten dan urutkan hasil menggunakan operator <=> dari RUM. Kesamaan tinggi menunjukkan skor rendah.
second_method AS (
    SELECT 
        id, 
        doc_id, 
        content, 
        to_tsvector('jiebacfg', content) <=> 
        to_tsquery(replace(text(plainto_tsquery('jiebacfg', (SELECT query_text FROM query))), '&', '|')) AS score,
        'content_key_word' AS method
    FROM embed
    WHERE 
        to_tsvector('jiebacfg', content) @@ 
        to_tsquery(replace(text(plainto_tsquery('jiebacfg', (SELECT query_text FROM query))), '&', '|'))
    ORDER BY 
        score 
    LIMIT 3
),
Jalankan pencarian teks lengkap berdasarkan embedding dan urutkan hasil menggunakan operator <=> dari pgvector. Kesamaan tinggi menunjukkan skor rendah.
third_method AS (
    SELECT 
        embed.id, 
        embed.doc_id, 
        embed.content, 
        embedding <=> (SELECT embedding FROM query_embedding LIMIT 1) AS score, 
        'embedding' AS method
    FROM embed                 
    ORDER BY score
    LIMIT 3
)
-- Lakukan kueri gabungan untuk mendapatkan lebih banyak informasi bidang.
SELECT 
    first_method.title, 
    embed.id AS chunk_id, 
    SUBSTRING(embed.content FROM 1 FOR 30), 
    first_method.score, 
    first_method.method 
FROM first_method 
LEFT JOIN embed ON first_method.id = embed.doc_id
-- Gabungkan output dari bidang second_method.
UNION
SELECT 
    doc.title, 
    second_method.id AS chunk_id, 
    SUBSTRING(second_method.content FROM 1 FOR 30), 
    second_method.score, 
    second_method.method 
FROM second_method 
LEFT JOIN doc ON second_method.doc_id = doc.id
-- Gabungkan output dari bidang third_method.
UNION
SELECT 
    doc.title, 
    third_method.id AS chunk_id, 
    SUBSTRING(third_method.content FROM 1 FOR 30), 
    third_method.score, 
    third_method.method 
FROM third_method 
LEFT JOIN doc ON third_method.doc_id = doc.id
ORDER BY method, score;

Keluaran:

     title      | chunk_id |                          substring                           |        score         |      method      
----------------+----------+--------------------------------------------------------------+----------------------+------------------
 Pengenalan PostgreSQL |        3 | PostgreSQL adalah penerus sumber terbuka asli dari kode Berkele |   13.159472465515137 | content_key_word
 Pengenalan PostgreSQL |        2 | PostgreSQL adalah sistem manajemen basis data relasional objek|     16.4493408203125 | content_key_word
 Pengenalan PostgreSQL |        4 | Dan, karena lisensi yang bebas dan longgar, siapa pun dapat me |     16.4493408203125 | content_key_word
 Pengenalan PostgreSQL |        6 | Ekosistem yang kaya: ada banyak plugin dan ekstensi siap pakai | 0.020264236256480217 | doc_key_word
 Pengenalan PostgreSQL |        5 | Plugin Ganos dan plugin PostGIS tidak dapat diinstal di bawah Schem                  | 0.020264236256480217 | doc_key_word
 Pengenalan PostgreSQL |        3 | PostgreSQL adalah penerus sumber terbuka asli dari kode Berkele | 0.020264236256480217 | doc_key_word
 Pengenalan PostgreSQL |        2 | PostgreSQL adalah sistem manajemen basis data relasional objek| 0.020264236256480217 | doc_key_word
 Pengenalan PostgreSQL |        4 | Dan, karena lisensi yang bebas dan longgar, siapa pun dapat me | 0.020264236256480217 | doc_key_word
 Pengenalan PostgreSQL |        2 | PostgreSQL adalah sistem manajemen basis data relasional objek|   0.2546271233144539 | embedding
 Pengenalan PostgreSQL |        3 | PostgreSQL adalah penerus sumber terbuka asli dari kode Berkele |  0.28679098231865074 | embedding
 Pengenalan PostgreSQL |        6 | Ekosistem yang kaya: ada banyak plugin dan ekstensi siap pakai |  0.41783296077761967 | embedding

Referensi

Untuk informasi lebih lanjut tentang praktik terbaik ApsaraDB RDS untuk PostgreSQL dalam RAG, lihat topik-topik berikut: