O ApsaraDB RDS for PostgreSQL combina armazenamento de vetores com pesquisa de texto completo, o que o torna um banco de dados vetorial robusto para aplicações de geração aumentada por recuperação (RAG). Este guia orienta a criação de um chatbot de chamados para demonstrar como a recuperação multicaminho, a mesclagem de resultados e a geração de perguntas e respostas funcionam juntas em uma única instância do PostgreSQL.
Ao concluir este guia, você entenderá:
Como ingerir e estruturar documentos para um pipeline de RAG
Como cada um dos quatro métodos de recuperação funciona e quando usar cada um
Como mesclar e reclassificar resultados usando o algoritmo de fusão de classificação recíproca (RRF) e o modelo bce-reranker-base_v1
Como funciona
O pipeline do chatbot de chamados possui quatro etapas:
Processamento de dados — Divida os documentos de origem (documentos de ajuda, bases de conhecimento, chamados históricos) em fragmentos e gere embeddings. Armazene ambos na instância do RDS.
Recuperação multicaminho — Execute quatro pesquisas paralelas com base nas perguntas do usuário: por palavras-chave do documento, por palavras-chave do conteúdo, por BM25 e por embedding.
Mesclagem de resultados — Mescle e reclassifique os resultados dos quatro caminhos usando o algoritmo RRF e o modelo bce-reranker-base_v1.
Análise de perguntas e respostas — Pontue pares de perguntas e respostas durante os testes para avaliar e comparar políticas de recuperação.
Pré-requisitos
Antes de começar, certifique-se de ter:
Uma instância do ApsaraDB RDS for PostgreSQL
Uma conta de banco de dados privilegiada para instalar extensões
Uma conta e uma chave de API do Alibaba Cloud Model Studio (para o modelo de embedding de texto). Consulte Obter uma chave de API
Um NAT gateway configurado para a virtual private cloud (VPC) onde a instância do RDS reside, para que a instância possa acessar modelos externos. Consulte Use the rds_embedding extension to generate vectors
Processamento de dados
Adquirir dados de origem
Colete dados com base no propósito da sua aplicação RAG. O chatbot de chamados neste guia usa três fontes:
Documentação de ajuda
Artigos da base de conhecimento
Chamados de suporte históricos
Segmentar e gerar embeddings de documentos
Divida os documentos em fragmentos antes de gerar os embeddings. Use a classe HTMLHeaderTextSplitter do LangChain para segmentar documentos de ajuda por hierarquia HTML (H1, H2). Configure o tamanho e a sobreposição dos fragmentos para equilibrar a precisão e a recuperação. Consulte Divisores de texto do LangChain para a lista completa de opções de divisão.
Para documentos Markdown, useMarkdownHeaderTextSplittercom sinalizadores de título como#e##para divisão hierárquica.
Armazenar dados
Armazene os dados processados em duas tabelas principais: document e embedding.
Recuperação multicaminho
Quando usar cada método de recuperação
Diferentes métodos de recuperação atendem a diferentes características de consulta. Use esta tabela para escolher a estratégia certa para o seu caso de uso:
|
Método |
Mais indicado para |
Limitações |
|
Recuperação por palavras-chave do documento |
Consultas que correspondem a palavras-chave ou tags conhecidas do product; rápido e preciso para termos exatos |
Perde o significado semântico; falha em erros de digitação ou sinônimos |
|
Recuperação por palavras-chave do conteúdo |
Consultas direcionadas ao texto do corpo do documento; beneficia-se do índice RUM para classificação rápida de texto completo |
Mesmas limitações da correspondência de palavras-chave |
|
Recuperação baseada em BM25 |
Consultas onde a frequência do termo e a importância no nível do documento são relevantes; complementa o ts_rank |
Puramente estatístico; sem compreensão semântica |
|
Recuperação baseada em embedding |
Consultas expressas em linguagem natural; lida com sinônimos e paráfrases |
Requer modelo de embedding; pode perder correspondências exatas de palavras-chave |
Para a maioria das aplicações RAG, combine todos os quatro métodos e mescle os resultados usando o algoritmo RRF. Isso produz uma recuperação melhor do que qualquer método isolado.
Recuperação por palavras-chave do documento
A recuperação por palavras-chave do documento compara as perguntas do usuário com as palavras-chave armazenadas na tabela document e retorna os N principais documentos por similaridade.
Etapa 1: Indexe palavras-chave do documento como valores tsvector ponderados.
Use to_tsvector para segmentar palavras-chave e setweight para atribuir pesos. As extensões de segmentação de palavras em chinês pg_jieba e zhparser lidam com texto em chinês. Consulte Manage extensions para instruções de instalação.
SELECT setweight(to_tsvector('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库'), 'A');
setweight
-------------------------------------------------------------------------------
'postgresql':1A '世界':3A '先进':5A '关系':8A '型':9A '开源':7A '数据库':10A
Etapa 2: Converta a pergunta do usuário em um tsquery e compare com as palavras-chave.
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;
Funções principais:
to_tsquery converte uma pergunta em um valor tsquery:
SELECT to_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库');
to_tsquery
--------------------------------------------------------------------------------
'postgresql' <2> '世界' <2> '先进' <2> '开源' <-> '关系' <-> '型' <-> '数据库'
<2> indica a distância entre as palavras. <-> indica palavras adjacentes. Stopwords como 是 e 的 são removidas automaticamente. & significa AND, | significa OR e ! significa NOT.
Use plainto_tsquery em vez de to_tsquery quando a entrada do usuário puder conter operadores inválidos:
SELECT to_tsquery('jiebacfg','日志|&堆积');
ERROR: syntax error in tsquery: "日志|&堆积"
SELECT plainto_tsquery('jiebacfg','日志|&堆积');
plainto_tsquery
-----------------
'日志' & '堆积'
Use a função text para converter o resultado do plainto_tsquery em uma string e, em seguida, replace para alterar & para | para correspondência OR:
-- Use the plainto_tsquery function.
SELECT plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库');
plainto_tsquery
--------------------------------------------------------------------
'postgresql' & '世界' & '先进' & '开源' & '关系' & '型' & '数据库'
-- Use the plainto_tsquery, text, and replace functions.
SELECT replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|');
replace
--------------------------------------------------------------------
'postgresql' | '世界' | '先进' | '开源' | '关系' | '型' | '数据库'
-- Use the to_tsquery, plainto_tsquery, text, and replace functions.
SELECT to_tsquery(replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|'));
to_tsquery
--------------------------------------------------------------------
'postgresql' | '世界' | '先进' | '开源' | '关系' | '型' | '数据库'
Adicione termos personalizados ao dicionário pg_jieba para melhorar a segmentação de frases específicas do domínio:
-- Automatically add 关系型 to custom dictionary 0 with a weight of 100000.
INSERT INTO jieba_user_dict VALUES ('关系型',0,100000);
-- Load custom dictionary 0. The first 0 is the dictionary sequence number; the second 0 loads the default dictionary.
SELECT jieba_load_user_dict(0,0);
jieba_load_user_dict
----------------------
-- Convert a user question into a tsquery value.
SELECT to_tsquery(replace(text(plainto_tsquery('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库')), '&', '|'));
to_tsquery
--------------------------------------------------------------------
'postgresql' | '世界' | '先进' | '开源' | '关系型' | '数据库'
Antes de adicionar 关系型 ao dicionário, o termo é dividido em '关系' & '型'. Após a adição, o dicionário retorna o termo composto '关系型' como um único token.
Operadores e pontuação:
Use @@ para verificar se um tsvector corresponde a um tsquery. A correspondência de peso afeta os resultados:
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
A consulta procura por postgresql com peso A. A primeira instrução retorna falso porque nenhum peso é atribuído ao tsvector. Após aplicar setweight, a correspondência é bem-sucedida.
Use ts_rank para pontuar o quão bem um tsvector corresponde a um tsquery:
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
A primeira frase corresponde tanto a postgresql quanto a 开源, pontuando mais alto que a segunda frase, que corresponde apenas a 开源. A terceira frase é filtrada por @@ porque não corresponde a nenhum dos termos.
Como lidar com falhas de segmentação:
Se a segmentação de palavras falhar ou a entrada contiver caracteres inesperados, a correspondência de palavras-chave poderá não retornar resultados. Use a extensão pg_bigm para correspondência difusa como fallback:
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)
bigm_similarity converte ambas as strings em bigramas (pares de caracteres consecutivos) e calcula a sobreposição. O resultado varia de 0 a 1, onde 1 é uma correspondência exata. Isso funciona bem quando há erros de digitação, abreviações ou erros de segmentação. Para mais informações, consulte Use the pg_bigm extension to perform fuzzy match-based queries.
Recuperação por palavras-chave do conteúdo
A recuperação por palavras-chave do conteúdo pesquisa o texto content_chunk na tabela embedding usando a mesma abordagem de pesquisa de texto completo que document keyword-based recall. Como os fragmentos do documento são mais longos que os campos de palavras-chave, o RUM extension oferece uma vantagem significativa de desempenho.
Os três planos de consulta a seguir comparam a mesma consulta de pesquisa de texto completo usando diferentes abordagens de índice. Todos usam a consulta 'wal日志堆积怎么办'.
Resumo da comparação de índices:
|
Tipo de índice |
Tempo de execução |
Como a classificação funciona |
|
RUM em |
3,2 ms |
Varredura de índice com ordenação integrada — sem etapa de classificação |
|
GIN em |
14,2 ms |
Varredura de bitmap + classificação paralela |
|
GIN em |
1.081 ms |
Varredura de bitmap + recálculo de tsvector por linha + classificação |
Use o índice RUM (embedding_rumidx) para recuperação por palavras-chave do conteúdo. Ele é 4 vezes mais rápido que a abordagem GIN em coluna armazenada e 300 vezes mais rápido que a abordagem GIN em expressão.
Recuperação baseada em BM25
O BM25 é um algoritmo clássico de correspondência de texto que pontua documentos com base na frequência do termo (TF) e na frequência inversa do documento (IDF). Uma pontuação TF alta indica que uma palavra aparece frequentemente em um documento. Uma pontuação IDF alta indica que uma palavra aparece em poucos documentos e, portanto, é mais distinta.
O BM25 otimiza o modelo TF-IDF com parâmetros adicionais para melhorar a qualidade da recuperação. Sua saída complementa a recuperação por palavras-chave baseada em ts_rank, pois ambos operam em estatísticas de termos, mas ponderam os fatores de maneira diferente.
Recuperação baseada em embedding
O ApsaraDB RDS for PostgreSQL suporta a extensão pgvector para armazenamento de vetores e pesquisa de similaridade, e a extensão rds_embedding para gerar embeddings a partir de texto.
A extensão pgvector suporta dois métodos de indexação para pesquisa de vizinho mais próximo aproximado (ANN):
HNSW (Hierarchical Navigable Small World) — constrói o índice incrementalmente à medida que os dados são inseridos; não requer treinamento; velocidade de consulta mais rápida
IVFFlat (Inverted File with Flat Compression) — requer treinamento em dados existentes antes da construção; velocidade de consulta ligeiramente menor
Este guia usa o HNSW, que funciona sem pré-treinamento e fornece uma recuperação mais rápida. Para práticas recomendadas do IVFFlat, consulte Build an LLM-driven dedicated chatbot on top of ApsaraDB RDS for PostgreSQL.
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;
Para benchmarks de desempenho do pgvector, consulte Use the pgvector extension to perform high-dimensional vector similarity searches.
Mesclagem de resultados
Mescle e reclassifique os resultados de todos os quatro caminhos de recuperação usando o algoritmo RRF e o modelo bce-reranker-base_v1.
Algoritmo RRF:
O RRF atribui uma pontuação a cada documento com base em sua classificação em vários sistemas de recuperação:
RRF(d) = Σ 1/(k + r_i(d))
Onde d é o documento, r_i(d) é a classificação do documento no sistema i, e k é uma constante de suavização (geralmente definida como 60). Documentos que possuem alta classificação em vários sistemas acumulam pontuações RRF mais altas, produzindo uma classificação mesclada que reflete o consenso em todos os caminhos de recuperação.
Modelo bce-reranker-base_v1:
O bce-reranker-base_v1 é um modelo de reclassificação semântica multilíngue que suporta chinês, inglês, japonês e coreano. Ele produz classificações mais precisas do que o RRF isolado, mas leva mais tempo ao processar muitos fragmentos.
Escolha entre as abordagens com base nos seus requisitos de latência:
Para respostas rápidas, use apenas o RRF ou aplique o bce-reranker-base_v1 apenas nos principais resultados do RRF.
Para maior precisão, execute o bce-reranker-base_v1 diretamente no conjunto de resultados mesclados.
Análise de perguntas e respostas
O chatbot de chamados aplica diferentes políticas com base na fonte de dados para controlar como cada tipo de conteúdo flui para o prompt do modelo de linguagem grande (LLM):
Conteúdo da base de conhecimento — fornecido diretamente ao usuário sem processamento do LLM
Documentação de ajuda — resumida e formatada pelo LLM, porque o HTML segmentado pode conter artefatos de layout e texto duplicado
Fallback do LLM — o LLM responde diretamente apenas quando a base de conhecimento e a documentação não podem fornecer um resultado relevante
Chamados históricos — fornecidos apenas como título e URL, direcionando os usuários para o chamado completo
Cada resposta inclui links para os documentos de origem. Se a resposta não resolver totalmente o problema, os usuários podem seguir os links para obter informações mais completas.
Durante os testes, pontue pares de perguntas e respostas para avaliar a eficácia da política de recuperação. Escreva várias variantes de políticas e compare as pontuações para determinar a configuração de recuperação mais eficaz:
prompt = f\'\'\'请整理并格式化下面的内容并整理输出格式,
{prompt_content}
基于自己的能力做出回答,我的问题是:{question}。
\'\'\'
Conectar-se a um chatbot do DingTalk
Você pode usar o Streamlit para criar um aplicativo web ou conectar-se ao chatbot do DingTalk. Um aplicativo web é usado para autoteste e gerenciamento de documentos. O chatbot do DingTalk permite que todos os usuários acessem o service.
Em cada sessão de perguntas e respostas em um grupo do DingTalk, uma nova conexão precisa ser estabelecida no nível do banco de dados. Conexões frequentes de curta duração consomem tempo e memória. Se as conexões não forem liberadas rapidamente, a instância poderá atingir seu limite de conexões. Use um pool de conexões para evitar isso — implemente um em sua aplicação ou use o PgBouncer connection pool integrado do ApsaraDB RDS for PostgreSQL.
Exemplo
Este exemplo demonstra a recuperação multicaminho usando um conjunto de dados de amostra sobre PostgreSQL, MySQL e SQL Server. A consulta é 介绍一下postgresql.
Preparar dados
-
Instale as extensões necessárias usando uma conta privilegiada:
ImportanteAntes de instalar o pg_jieba, adicione pg_jieba ao value do parâmetro shared_preload_libraries. Para mais informações sobre como modificar o parâmetro shared_preload_libraries, consulte Set instance parameters.
Você pode executar a instrução
SELECT * FROM pg_extension;para visualizar as extensões instaladas.
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; -
Crie um NAT gateway para a virtual private cloud (VPC) na qual a instância do RDS reside para permitir que a instância do RDS acesse modelos externos. Para mais informações, consulte Use the rds_embedding extension to generate vectors.
NotaPor padrão, você não pode se conectar a uma instância do RDS pela Internet. Ao usar um modelo grande externo, como o text embedding model fornecido pelo Alibaba Cloud Model Studio, você deve criar um NAT gateway para a VPC na qual a instância do RDS reside para que a instância do RDS acesse modelos externos.
-
Execute as seguintes instruções SQL no banco de dados necessário para criar as tabelas de teste chamadas doc e embed, e crie índices para as tabelas:
--Create the doc test table and an index for the table. 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)); --Create the embed test table and an index for the table. 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 ); -
Execute as seguintes instruções SQL para criar um gatilho. Quando uma linha na tabela embed é atualizada ou dados são inseridos na linha, a coluna ts_vector_extra é atualizada automaticamente.
-- Convert the text into a tsvector value for full-text search based on keywords. 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\'); -
Execute as seguintes instruções SQL. Cada vez que uma inserção ou atualização é realizada na tabela embed, um embedding é gerado com base no conteúdo inserido ou atualizado e armazenado na coluna embedding.
ImportanteNeste exemplo, o text embedding model fornecido pelo Alibaba Cloud Model Studio é usado. Você deve ativar o Alibaba Cloud Model Studio e obter a chave de API necessária. Para mais informações, consulte Obtain an API key.
-- Convert the question into an embedding. Specify the api_key parameter based on your business requirements. 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(); -
Insira dados de teste na tabela.
INSERT INTO doc(id, title, key_word) VALUES (1, \'PostgreSQL介绍\', \'PostgreSQL 插件\'), (2, \'MySQL介绍\', \'MySQL MGR\'), (3, \'SQL Server介绍\', \'SQL Server Microsoft\'); INSERT INTO embed(doc_id, content) VALUES (1, \'PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES,版本 4.2为基础的对象关系型数据库管理系统(ORDBMS)。 POSTGRES领先的许多概念在很久以后才出现在一些商业数据库系统中\'), (1, \'PostgreSQL是最初的伯克利代码的开源继承者。 它支持大部分SQL标准并且提供了许多现代特性:复杂查询、外键、触发器、可更新视图、事务完整性、多版本并发控制,同样,PostgreSQL可以用许多方法扩展,比如,通过增加新的:数据类型、函数、操作符、聚集函数、索引方法、过程语言\'), (1, \'并且,因为自由宽松的许可证,任何人都可以以任何目的免费使用、修改和分发PostgreSQL,不管是私用、商用还是学术研究目的。 \'), (1, \'Ganos插件和PostGIS插件不能安装在同一个Schema下\'), (1, \'丰富的生态系统:有大量现成的插件和扩展可供使用,比如PostGIS(地理信息处理)、TimescaleDB(时间序列数据库)、pg_stat_statements(性能监控)等,能够满足不同场景的需要\'); INSERT INTO embed(doc_id, content) VALUES (2, \'MySQL名称的起源不明。 10多年来,我们的基本目录以及大量库和工具均采用了前缀"my"。 不过,共同创办人Monty Widenius的女儿名字也叫"My"。 时至今日,MySQL名称的起源仍是一个迷,即使对我们也一样\'), (2, \'MySQL软件采用双许可方式。 用户可根据GNU通用公共许可(http://www.fsf.org/licenses/)条款,将MySQL软件作为开放源码产品使用,或从MySQL AB公司购买标准的商业许可证。 关于我方许可策略的更多信息,请参见http://www.mysql.com/company/legal/licensing/。 \'), (2, \'组复制MySQL Group Replication(简称MGR)是MySQL官方在已有的Binlog复制框架之上,基于Paxos协议实现的一种分布式复制形态。 RDS MySQL集群系列实例支持组复制。 本文介绍如何使复制方式为组复制。 使用了组复制的MySQL集群能够基于分布式Paxos协议自我管理,具有很强的数据可靠性和数据一致性。 相比传统主备复制方式,组复制具有以下优势:数据的强一致性,数据的强可靠性,全局事务强一致性\'); INSERT INTO embed(doc_id, content) VALUES (3, \'Microsoft SQL Server是一种关系数据库管理系统 (RDBMS)。 应用程序和工具连接到SQL Server实例或数据库,并使用Transact-SQL (T-SQL)进行通信。 \'), (3, \'SQL Server 2022 (16.x)在早期版本的基础上构建,旨在将SQL Server发展成一个平台,以提供开发语言、数据类型、本地或云环境以及操作系统选项。 \'), (3, \'SQL Server在企业级应用中广受欢迎,与其他Microsoft产品(如Excel、Power BI)无缝集成,便于数据分析\');
Executar recuperação multicaminho
Execute as seguintes instruções SQL para recuperar o texto da consulta "introducepostgresql" de vários métodos e classificar os documentos relevantes por similaridade.
-- The text that you want to query.
WITH query AS (
SELECT \'介绍一下postgresql\' AS query_text
),
-- Convert the question into an embedding. Replace sk-**** with the API key obtained from 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
),
-- Document keyword search: score by ts_rank (higher = better match).
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
),
-- Content keyword search: score by RUM <=> operator (lower = better match).
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
),
-- Embedding search: score by cosine distance <=> (lower = better match).
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
)
-- Join to retrieve document titles and combine results from all three methods.
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
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
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;
Saída:
title | chunk_id | substring | score | method
----------------+----------+--------------------------------------------------------------+----------------------+------------------
PostgreSQL介绍 | 3 | PostgreSQL是最初的伯克利代码的开源继承者。 它支持大 | 13.159472465515137 | content_key_word
PostgreSQL介绍 | 2 | PostgreSQL是以加州大学伯克利分校计算机系开发的PO | 16.4493408203125 | content_key_word
PostgreSQL介绍 | 4 | 并且,因为自由宽松的许可证,任何人都可以以任何目的免费使用、 | 16.4493408203125 | content_key_word
PostgreSQL介绍 | 6 | 丰富的生态系统:有大量现成的插件和扩展可供使用,比如Post | 0.020264236256480217 | doc_key_word
PostgreSQL介绍 | 5 | Ganos插件和PostGIS插件不能安装在同一个Schem | 0.020264236256480217 | doc_key_word
PostgreSQL介绍 | 3 | PostgreSQL是最初的伯克利代码的开源继承者。 它支持大 | 0.020264236256480217 | doc_key_word
PostgreSQL介绍 | 2 | PostgreSQL是以加州大学伯克利分校计算机系开发的PO | 0.020264236256480217 | doc_key_word
PostgreSQL介绍 | 4 | 并且,因为自由宽松的许可证,任何人都可以以任何目的免费使用、 | 0.020264236256480217 | doc_key_word
PostgreSQL介绍 | 2 | PostgreSQL是以加州大学伯克利分校计算机系开发的PO | 0.2546271233144539 | embedding
PostgreSQL介绍 | 3 | PostgreSQL是最初的伯克利代码的开源继承者。 它支持大 | 0.28679098231865074 | embedding
PostgreSQL介绍 | 6 | 丰富的生态系统:有大量现成的插件和扩展可供使用,比如Post | 0.41783296077761967 | embedding
Todos os três métodos de recuperação retornam resultados para PostgreSQL介绍, confirmando que as abordagens baseadas em palavras-chave, conteúdo e embedding identificam o documento correto.
Tópicos relacionados
Para mais informações sobre as práticas recomendadas do ApsaraDB RDS for PostgreSQL em RAG, consulte os seguintes tópicos: