O ApsaraDB RDS for PostgreSQL combina armazenamento vetorial com busca de texto completo, tornando-o um banco de dados vetorial robusto para aplicações de geração aumentada por recuperação (RAG). Este guia demonstra a construção de um chatbot de tickets para ilustrar como a recuperação multicaminho, a fusão de resultados e a geração de perguntas e respostas funcionam em conjunto em uma única instância PostgreSQL.
Ao concluir este guia, você entenderá:
Como ingerir e estruturar documentos para um pipeline RAG
O funcionamento de cada um dos quatro métodos de recuperação e quando utilizá-los
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 tickets possui quatro etapas:
Processamento de dados — Divida os documentos de origem (documentação de ajuda, bases de conhecimento, tickets históricos) em fragmentos e gere embeddings. Armazene ambos na instância RDS.
Recuperação multicaminho — Execute quatro buscas paralelas com base nas perguntas do usuário: baseada em palavras-chave do documento, baseada em palavras-chave do conteúdo, baseada em BM25 e baseada em embedding.
Fusão de resultados — Mescle e reclassifique os resultados dos quatro caminhos utilizando 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 ApsaraDB RDS for PostgreSQL
Uma conta de banco de dados privilegiada para instalar extensões
Uma conta no Alibaba Cloud Model Studio e uma chave de API (para o modelo de text embedding). Consulte Obter uma chave de API
Um gateway NAT configurado para a Virtual Private Cloud (VPC) onde a instância RDS reside, permitindo que a instância acesse modelos externos. Consulte Usar a extensão rds_embedding para gerar vetores
Processamento de dados
Adquirir dados de source
Colete dados conforme a finalidade da sua aplicação RAG. O chatbot de tickets deste guia utiliza três fontes:
Documentação de ajuda
Artigos da base de conhecimento
Tickets de suporte históricos
Segmentar e incorporar documentos
Divida os documentos em fragmentos antes de gerar os embeddings. Utilize a classe HTMLHeaderTextSplitter do LangChain para segmentar documentos de ajuda pela hierarquia HTML (H1, H2). Configure o tamanho do fragmento e a sobreposição para equilibrar precisão e recall na recuperação. Consulte Splitters de texto do LangChain para visualizar a lista completa de opções de divisão.
Para documentos Markdown, utilizeMarkdownHeaderTextSplittercom marcadores de título como#e##para realizar a 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
Cada método de recuperação adequa-se a diferentes características de consulta. Utilize esta tabela para escolher a estratégia ideal para o seu caso de uso:
|
Método |
Mais indicado para |
Limitações |
|
Recuperação baseada em palavras-chave do documento |
Consultas que correspondem a palavras-chave ou tags conhecidas do produto; rápido e preciso para termos exatos |
Perde o significado semântico; falha em erros de digitação ou sinônimos |
|
Recuperação baseada em palavras-chave do conteúdo |
Consultas direcionadas ao corpo do texto do documento; beneficia-se do índice RUM para classificação rápida de texto completo |
Mesmas limitações da correspondência por 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 bem 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. Essa abordagem produz um recall superior ao uso de qualquer método isoladamente.
Recuperação baseada em palavras-chave do documento
A recuperação baseada em 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: Indexar palavras-chave do documento como valores tsvector ponderados.
Utilize 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 processam textos em chinês. Consulte Gerenciar extensões para obter instruções de instalação.
SELECT setweight(to_tsvector('jiebacfg', 'PostgreSQL是世界上先进的开源关系型数据库'), 'A');
setweight
-------------------------------------------------------------------------------
'postgresql':1A '世界':3A '先进':5A '关系':8A '型':9A '开源':7A '数据库':10A
Etapa 2: Converter a pergunta do usuário em um tsquery e comparar 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 palavras. <-> indica palavras adjacentes. Stopwords como 是 e 的 são removidas automaticamente. & significa AND, | significa OR e ! significa NOT.
Prefira 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
-----------------
'日志' & '堆积'
Utilize a função text para converter o resultado de plainto_tsquery em uma string e, em seguida, use replace para alterar & para | visando à 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 era 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 pesos 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 busca por postgresql com peso A. A primeira instrução retorna falso porque nenhum peso foi atribuído ao tsvector. Após aplicar setweight, a correspondência é bem-sucedida.
Utilize ts_rank para pontuar a qualidade da correspondência entre um tsvector e 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 开源, obtendo uma pontuação maior que a segunda frase, que corresponde apenas a 开源. A terceira frase é filtrada por @@ porque não corresponde a nenhum dos termos.
Tratamento de 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. Utilize a extensão pg_bigm para correspondência difusa como alternativa:
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 representa 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 Usar a extensão pg_bigm para realizar consultas baseadas em correspondência difusa.
Recuperação baseada em palavras-chave do conteúdo
A recuperação baseada em palavras-chave do conteúdo pesquisa o texto content_chunk na tabela embedding usando a mesma abordagem de busca de texto completo da recuperação baseada em palavras-chave do documento. Como os fragmentos de documento são mais longos que os campos de palavras-chave, a extensão RUM oferece uma vantagem significativa de desempenho.
Os três planos de consulta a seguir comparam a mesma consulta de busca de texto completo usando diferentes abordagens de indexação. Todos utilizam a consulta 'wal日志堆积怎么办'.
Resumo da comparação de índices:
|
Tipo de índice |
Tempo de execução |
Funcionamento da classificação |
|
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 |
Utilize o índice RUM (embedding_rumidx) para recuperação baseada em 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
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, sendo portanto mais distintiva.
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, já que ambos operam sobre 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 vetorial e busca de similaridade, além da extensão rds_embedding para gerar embeddings a partir de texto.
A extensão pgvector suporta dois métodos de indexação para busca 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 nos dados existentes antes da construção; velocidade de consulta ligeiramente menor
Este guia utiliza HNSW, que funciona sem pré-treinamento e oferece recuperação mais rápida. Para práticas recomendadas de IVFFlat, consulte Criar um chatbot dedicado orientado por LLM no 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 Usar a extensão pgvector para realizar buscas de similaridade vetorial de alta dimensão.
Fusão de resultados
Mescle e reclassifique os resultados dos 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 bem classificados em múltiplos sistemas acumulam pontuações RRF mais altas, produzindo uma classificação mesclada que reflete o consenso entre 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 que o RRF isoladamente, 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 somente nos principais resultados do RRF.
Para máxima precisão, execute o bce-reranker-base_v1 diretamente no conjunto de resultados mesclado.
Análise de perguntas e respostas
O chatbot de tickets aplica políticas diferentes 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 pelo LLM
Documentação de ajuda — resumida e formatada pelo LLM, pois 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 conseguem fornecer um resultado relevante
Tickets históricos — fornecidos apenas como título e URL, direcionando os usuários para o ticket completo
Cada resposta inclui links para os documentos de source. 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 a um chatbot do DingTalk
Você pode usar o Streamlit para criar uma aplicação web ou conectar-se ao chatbot do DingTalk. A aplicação web serve para autoteste e gerenciamento de documentos. O chatbot do DingTalk permite que todos os usuários acessem o serviço.
Em cada sessão de perguntas e respostas em um grupo do DingTalk, é necessário estabelecer uma nova conexão no nível do banco de dados. Conexões frequentes e de curta duração consomem tempo e memória. Se as conexões não forem liberadas prontamente, a instância poderá atingir seu limite de conexões. Utilize um pool de conexões para evitar isso — implemente um em sua aplicação ou use o pool de conexões PgBouncer 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 Configurar parâmetros da instância.
Execute 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 gateway NAT para a Virtual Private Cloud (VPC) onde a instância RDS reside, permitindo que a instância RDS acesse modelos externos. Para mais informações, consulte Usar a extensão rds_embedding para gerar vetores.
NotaPor padrão, não é possível conectar-se a uma instância RDS pela Internet. Ao usar um modelo grande externo, como o modelo de text embedding fornecido pelo Alibaba Cloud Model Studio, você deve criar um gateway NAT para a VPC onde a instância RDS reside, permitindo que a instância RDS acesse modelos externos.
-
Execute as seguintes instruções SQL no banco de dados desejado 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 trigger. Quando uma linha na tabela embed for atualizada ou dados forem inseridos na linha, a coluna ts_vector_extra será 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. Sempre que uma inserção ou atualização for realizada na tabela embed, um embedding será gerado com base no conteúdo inserido ou atualizado e armazenado na coluna embedding.
ImportanteNeste exemplo, utiliza-se o modelo de text embedding fornecido pelo Alibaba Cloud Model Studio. Você deve ativar o Alibaba Cloud Model Studio e obter a chave de API necessária. Para mais informações, consulte Obter uma chave de API.
-- 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 "introduzir postgresql" usando múltiplos 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 corretamente o documento.
Tópicos relacionados
Para mais informações sobre as melhores práticas do ApsaraDB RDS for PostgreSQL em RAG, consulte os seguintes tópicos: