文档中心>云数据库 PostgreSQL>AI 能力>实践教程>基于 PostgreSQL 构建 Agentic RAG 应用

基于 PostgreSQL 构建 Agentic RAG 应用

最近更新时间:2026-06-01 16:58:31

我的收藏

概述

Agentic RAG 是将 AI Agent 与 RAG(检索增强生成)结合的新范式。Agent 不仅被动回答问题,还能主动规划检索策略、自适应查询优化、多步推理、调用工具。本文介绍如何基于腾讯云 PostgreSQL 构建完整的 Agentic RAG 应用。

架构设计

┌──────────────────────────────────────────────────────┐
│ Agentic RAG 系统 │
├──────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ Planner │ │ Retriever │ │ Generator │ │
│ │ Agent │ → │ Agent │ → │ Agent │ │
│ │ (规划) │ │ (检索) │ │ (生成) │ │
│ └──────────┘ └───────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ PostgreSQL(统一存储层) │ │
│ ├─────────────────────────────────────────────┤ │
│ │ pgvector │ Apache AGE │ 记忆表 │ │
│ │ (向量检索)(知识图谱)(Agent 记忆) │ │
│ │ │ │ │ │
│ │ tencentdb_ai(大模型调用) │ │
│ └─────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘

与传统 RAG 的区别

维度
传统 RAG
Agentic RAG
检索策略
固定(单次向量搜索)
自适应(多次 / 多策略)
查询改写
无或简单改写
Agent 动态改写和分解
结果评估
直接使用
Agent 评估后决定是否需要更多检索
工具调用
可调用 SQL API 外部服务
多跳推理
不支持
支持多步推理链
记忆
无状态
有长期记忆

数据库准备

-- 知识库表
CREATE TABLE rag.documents (
id BIGSERIAL PRIMARY KEY,
title TEXT,
content TEXT NOT NULL,
chunk_index INT DEFAULT 0,
embedding vector(1024),
source TEXT,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_docs_embedding ON rag.documents
USING hnsw (embedding vector_cosine_ops);

-- Agent 检索记忆
CREATE TABLE rag.search_memory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL,
query TEXT NOT NULL,
strategy TEXT,
results_summary TEXT,
satisfaction FLOAT, -- Agent 对结果的满意度
created_at TIMESTAMPTZ DEFAULT NOW()
);

-- 查询改写日志
CREATE TABLE rag.query_rewrites (
id BIGSERIAL PRIMARY KEY,
original_query TEXT,
rewritten_query TEXT,
rewrite_reason TEXT,
session_id UUID,
created_at TIMESTAMPTZ DEFAULT NOW()
);

核心实现

说明:
向量维度需与您使用的大模型输出维度一致。常见模型维度:OpenAI text-embedding-3-small(1536维)、BGE-M3(1024维)、ChatGLM Embedding(1024维)。

智能查询改写

-- Agent 使用大模型改写查询
CREATE OR REPLACE FUNCTION rag.rewrite_query(original TEXT)
RETURNS TEXT AS $$
DECLARE
rewritten TEXT;
BEGIN
SELECT tencentdb_ai.chat_completions(
'<your-llm-model>',
'你是一个查询优化专家。请将以下用户问题改写为更适合向量检索的查询。只输出改写后的查询,不要解释。' ||
E'\\n\\n原始问题:' || original
) INTO rewritten;

-- 记录改写
INSERT INTO rag.query_rewrites (original_query, rewritten_query)
VALUES (original, rewritten);

RETURN rewritten;
END;
$$ LANGUAGE plpgsql;

多策略检索

-- 向量检索
CREATE OR REPLACE FUNCTION rag.vector_search(query TEXT, top_k INT DEFAULT 5)
RETURNS TABLE(id BIGINT, content TEXT, score FLOAT) AS $$
BEGIN
RETURN QUERY
SELECT d.id, d.content,
1 - (d.embedding <=> tencentdb_ai.get_embedding('bge-m3', query)) AS score
FROM rag.documents d
ORDER BY d.embedding <=> tencentdb_ai.get_embedding('bge-m3', query)
LIMIT top_k;
END;
$$ LANGUAGE plpgsql;

-- 关键词检索(BM25 风格)
CREATE OR REPLACE FUNCTION rag.keyword_search(keywords TEXT, top_k INT DEFAULT 5)
RETURNS TABLE(id BIGINT, content TEXT, score FLOAT) AS $$
BEGIN
RETURN QUERY
SELECT d.id, d.content,
ts_rank(to_tsvector('chinese', d.content), plainto_tsquery('chinese', keywords))::FLOAT AS score
FROM rag.documents d
WHERE to_tsvector('chinese', d.content) @@ plainto_tsquery('chinese', keywords)
ORDER BY score DESC
LIMIT top_k;
END;
$$ LANGUAGE plpgsql;

-- 混合检索(RRF 融合)
CREATE OR REPLACE FUNCTION rag.hybrid_search(query TEXT, top_k INT DEFAULT 5)
RETURNS TABLE(id BIGINT, content TEXT, rrf_score FLOAT) AS $$
BEGIN
RETURN QUERY
WITH vec AS (
SELECT id, content, ROW_NUMBER() OVER (ORDER BY score DESC) AS rank
FROM rag.vector_search(query, 20)
),
kw AS (
SELECT id, content, ROW_NUMBER() OVER (ORDER BY score DESC) AS rank
FROM rag.keyword_search(query, 20)
)
SELECT COALESCE(v.id, k.id),
COALESCE(v.content, k.content),
(COALESCE(1.0/(60+v.rank), 0) + COALESCE(1.0/(60+k.rank), 0))::FLOAT AS rrf_score
FROM vec v FULL OUTER JOIN kw k ON v.id = k.id
ORDER BY rrf_score DESC
LIMIT top_k;
END;
$$ LANGUAGE plpgsql;

Agent 自适应 RAG 流程

-- 完整的 Agentic RAG 函数
CREATE OR REPLACE FUNCTION rag.agentic_answer(question TEXT)
RETURNS TEXT AS $$
DECLARE
rewritten_query TEXT;
context TEXT;
answer TEXT;
BEGIN
-- Step 1: 查询改写
rewritten_query := rag.rewrite_query(question);

-- Step 2: 混合检索
SELECT string_agg(content, E'\\n---\\n') INTO context
FROM rag.hybrid_search(rewritten_query, 5);

-- Step 3: 生成回答
SELECT tencentdb_ai.chat_completions(
'<your-llm-model>',
'基于以下参考资料回答用户问题。如果资料不足,明确说明。' ||
E'\\n\\n参考资料:\\n' || COALESCE(context, '无相关资料') ||
E'\\n\\n用户问题:' || question
) INTO answer;

RETURN answer;
END;
$$ LANGUAGE plpgsql;

实践

1. 文档切片:建议 chunk_size = 500–1000 字符,overlap = 100。
2. 混合检索:向量 + 关键词 RRF 融合效果优于单一方式。
3. 查询改写:对复杂问题进行分解和改写。
4. 结果重排:使用 Rerank 模型对检索结果二次排序。
5. 记忆复用:对相似问题复用历史检索结果。

相关文档