news 2026/8/12 10:37:31

基于DigitalOcean数据与学习层构建AI应用:PostgreSQL+pgvector实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于DigitalOcean数据与学习层构建AI应用:PostgreSQL+pgvector实战指南

1. 项目概述:为什么“拼凑”是AI应用开发的效率黑洞?

如果你正在或者尝试过开发一个AI应用,比如一个智能客服、一个文档问答系统,或者一个个性化推荐引擎,那么下面这个场景你一定不陌生:你首先需要一个关系型数据库,比如PostgreSQL或者MySQL,来存储用户信息、订单记录这些结构化数据。然后,为了处理用户用自然语言提出的问题,你需要一个向量数据库,比如Pinecone、Weaviate或者Milvus,来存储和检索文本、图片的向量嵌入。接着,你需要一个缓存层,比如Redis,来提升热点数据的访问速度。最后,你可能还需要一个消息队列、一个对象存储服务……光是让这些组件彼此通信、保持数据一致性,就足以消耗掉你大半的开发精力。这还不是最头疼的,当应用流量上来,你需要考虑分库分表、向量索引的优化、缓存的穿透击穿雪崩,运维的复杂度呈指数级上升。

这就是典型的“拼凑式”架构。每一个组件都是领域的专家,但把它们组合成一个稳定、高效、易维护的整体,需要开发者具备全栈的架构和运维能力。DigitalOcean提出的“数据与学习层”概念,正是瞄准了这个痛点。它不是一个全新的、颠覆性的技术,而是一种产品理念的整合:将AI应用开发中最核心的数据存储、向量检索乃至模型推理所需的基础设施,打包成一个内聚的、无缝协作的服务层。其核心载体,便是对PostgreSQL的深度增强。

简单来说,它想让开发者像使用一个“超级数据库”一样来构建AI应用,所有的数据——无论是结构化的用户ID,还是非结构化的文本向量——都存放在同一个地方,使用同一种方式管理和查询。这听起来像是把向量搜索功能“插件化”到传统数据库中,但DigitalOcean的尝试更进一步,它试图从云服务的层面,提供开箱即用的集成体验和自动化的运维管理。对于中小型团队和个人开发者而言,这意味着你可以将宝贵的开发资源,从复杂的基础设施编排中解放出来,更聚焦于业务逻辑和AI模型本身。

2. 核心需求解析:AI应用需要什么样的数据层?

要理解“数据与学习层”的价值,我们必须先拆解一个现代AI应用,特别是基于大语言模型的RAG应用,对数据基础设施的核心需求。这些需求远不止“存”和“取”那么简单。

2.1 多模态数据的一体化存储与关联

一个智能应用的数据是立体的。以电商智能导购为例:

  • 结构化数据:商品SKU、价格、库存、用户订单、收货地址。这些数据传统上存放在PostgreSQL的表中,通过SQL进行精准的联表查询。
  • 非结构化数据:商品描述文案、用户评论、客服对话记录、商品图片。这些数据经过嵌入模型处理后,会变成高维向量,用于语义搜索。
  • 元数据:向量的来源、生成时间、所属类别。这些数据用于对向量检索结果进行高效的过滤。

在“拼凑”架构中,商品详情(结构化)在PostgreSQL,商品描述向量在专门的向量数据库,两者通过一个外键(如商品ID)进行逻辑关联。每次查询,应用层需要先到向量库做语义搜索,拿到一批商品ID,再回传到关系库去补全商品详情,涉及多次网络往返和事务管理。而在理想的数据与学习层中,商品详情表和它的描述向量可以存放在同一个数据库实例甚至同一张表的扩展字段中。一次查询就能同时利用索引完成向量相似度计算和结构化字段的过滤,效率和数据一致性得到根本性提升。

2.2 近实时、高并发的向量检索

向量搜索不是批处理,它要求在线、低延迟。当用户输入“适合夏天穿的、透气轻便的男士衬衫”时,应用需要在毫秒到百毫秒内,从上百万个商品向量中找到最相关的几十个。这要求底层向量索引(如HNSW、IVF)必须高效,并且能够支持高并发查询。传统数据库并非为此设计,而许多专业的向量数据库在应对复杂过滤(如“价格在100-300元之间且评分大于4.5”)时又可能表现不佳。数据与学习层需要融合两者的优势:既要有专业向量库的检索性能,又要具备关系数据库强大的过滤和事务能力。

2.3 简化的运维与无缝的扩展

这是云服务的核心价值所在。开发者不想关心:

  • 向量索引的调参:HNSW的ef_constructionM参数怎么设置?IVF的聚类数选多少?这些参数直接影响搜索精度和性能。
  • 集群的伸缩:数据量增长了,如何给向量索引部分扩容?如何实现读写分离?
  • 备份与容灾:向量数据和关系数据如何保持一致性的备份?
  • 监控与告警:如何监控向量检索的延迟和召回率?

一个成熟的数据与学习层服务,应该像使用托管数据库一样,提供一键部署、自动备份、监控仪表盘和弹性伸缩策略,将上述运维负担全部接管。

2.4 与AI工作流的原生集成

数据层不应该只是一个被动的存储系统。它需要更好地与AI工作流对接。例如:

  • 嵌入模型的集成:能否在数据入库时,自动调用配置好的嵌入模型(如OpenAI的text-embedding-3-small,或开源的BGE模型)为文本字段生成向量,而无需开发者手动编写ETL脚本?
  • 推理端点的就近访问:当检索出相关上下文后,能否在云网络内部高速、安全地调用托管的LLM(如DigitalOcean的AI Inference服务)进行生成,避免公网传输延迟和风险?
  • 数据变更的自动捕获:当源数据更新时,能否自动触发相关向量的重新生成和索引更新?

DigitalOcean的“数据与学习层”愿景,正是试图通过整合其托管PostgreSQL、Spaces对象存储、AI Inference等服务,并在PostgreSQL中深度集成pgvector等扩展,来系统性满足上述所有需求,提供一个“一步到位”的解决方案。

3. 技术实现剖析:PostgreSQL + pgvector 如何扛起大旗?

DigitalOcean实现其“数据与学习层”战略的核心技术基石,是托管PostgreSQL数据库和对pgvector扩展的支持。这并不是简单的功能堆砌,而是一种深思熟虑的架构选择。我们来深入看看这套组合拳是如何工作的。

3.1 pgvector:让PostgreSQL学会“理解”语义

pgvector是一个开源PostgreSQL扩展,它增加了对向量数据类型的原生支持,并提供了用于相似性搜索的运算符和索引。正是它,将PostgreSQL从一个纯粹的关系型数据库,转变为一个混合事务/分析处理并具备向量检索能力的“多模”数据库。

核心数据类型与操作:

  • vector类型:用于存储浮点数向量,例如vector(1536)可以存储一个1536维的向量(对应OpenAI text-embedding-3-small的维度)。
  • 相似度运算符:最常用的是<->(欧几里得距离)和<=>(余弦距离)。余弦距离更常用于文本语义相似度计算,值越小表示越相似。
    -- 查找与给定向量最相似的10条记录,使用余弦距离 SELECT id, content, embedding <=> '[0.1, 0.2, ...]' AS distance FROM documents ORDER BY embedding <=> '[0.1, 0.2, ...]' LIMIT 10;

索引机制:性能的关键没有索引,向量搜索就是全表扫描的噩梦。pgvector支持两种主流索引:

  1. IVFFlat(倒排文件索引):类似于传统搜索引擎的原理。它首先对数据集中的向量进行聚类(比如分成1024个簇),并记录每个簇的中心点。搜索时,先找到距离查询向量最近的N个簇,然后只在这些簇内的向量中进行精确计算。它构建速度快,占用空间小,但召回率(找到真正最相似向量的能力)在参数设置不当时可能受影响。

    CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops) WITH (lists = 1000); -- lists参数大致等于聚类数量

    注意:IVFFlat索引在数据大量新增或删除后,索引效果会下降,需要定期使用REINDEX命令重建索引,或在新数据积累到一定比例(如20%)后重建。

  2. HNSW(分层可导航小世界图):目前多数专业向量数据库的首选算法。它构建一个多层图结构,上层是“高速公路”,用于快速逼近目标区域;下层是“精细道路”,用于在局部区域找到最近邻。HNSW的查询速度通常极快,召回率高,但索引构建时间长,内存占用大。

    CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);
    • m:图中每个节点最大连接数,影响索引结构和搜索精度/速度(典型值16-48)。
    • ef_construction:构建索引时动态候选集大小,影响索引质量(典型值64-200)。

选择建议

  • 数据量小(<100万)或频繁更新:可以不建索引,或使用IVFFlat。
  • 数据量大(>100万),追求极致查询性能和高召回率,且数据相对静态:优先选择HNSW。
  • 内存有限:IVFFlat更节省内存。
  • DigitalOcean托管环境:由于底层硬件和PostgreSQL版本已优化,可以更放心地使用HNSW索引。关键在于根据你的数据集大小和查询模式,在控制台或通过SQL调整mef_construction参数。

3.2 混合查询:向量检索与结构化过滤的化学反应

这是pgvector在PostgreSQL中最大的威力所在。你可以将向量相似度搜索和复杂的SQL过滤、排序、连接无缝结合。

-- 一个复杂的混合查询示例:在技术文档中,搜索与“如何优化数据库连接池”语义相近, -- 且标签包含“PostgreSQL”、发布时间在一年内、点赞数超过10的文档,并按相似度和点赞数综合排序。 SELECT doc.id, doc.title, doc.content, doc.embedding <=> query_vec AS semantic_distance, doc.upvotes FROM documents doc JOIN document_tags dt ON doc.id = dt.document_id JOIN tags t ON dt.tag_id = t.id WHERE t.name = 'PostgreSQL' AND doc.published_at > NOW() - INTERVAL '1 year' AND doc.upvotes > 10 AND doc.embedding <=> query_vec < 0.2 -- 设定一个相似度阈值 ORDER BY (doc.embedding <=> query_vec) * 0.7 + (1.0 / (doc.upvotes + 1)) * 0.3 ASC -- 综合排序 LIMIT 5;

这个查询一次性完成了语义匹配、多表关联、范围过滤和自定义加权排序。在“拼凑”架构中,这需要应用层进行多次查询和复杂的逻辑合并,而在集成的数据层中,这只是一个查询计划优化问题。PostgreSQL的查询优化器会尝试最有效的方式(例如,先利用B-tree索引过滤标签和时间,再对符合条件的子集进行向量搜索)来执行。

3.3 DigitalOcean的托管增强

DigitalOcean的托管PostgreSQL服务在此基础上提供了关键的企业级能力,使其真正成为可靠的“数据与学习层”:

  • 一键启用与自动管理:在控制台点击即可为PostgreSQL集群启用pgvector扩展,无需手动编译安装。DigitalOcean负责底层扩展的版本兼容性和安全更新。
  • 高性能硬件基础:提供配备高性能NVMe SSD的机型,这对于需要大量随机读写的向量索引(尤其是HNSW)至关重要,能显著降低查询延迟。
  • 可扩展性与高可用:支持从单节点轻松扩展到多节点只读副本。你可以将读密集型的大量向量搜索请求分流到只读副本上,而主节点专注于处理写事务和复杂混合查询。
  • 集成生态:数据可以方便地与DigitalOcean Spaces(对象存储,存放原始文件)、App Platform(应用托管)和AI Inference服务(模型推理)在同一私有网络内高速通信,构成了一个完整的AI应用开发生态闭环。

4. 从零到一:基于DigitalOcean构建一个AI知识库应用

理论说得再多,不如动手实践。让我们以一个“智能产品文档知识库”为例,完整走一遍在DigitalOcean上使用其“数据与学习层”构建AI应用的流程。这个应用允许用户用自然语言提问,比如“如何设置双因素认证?”,然后从产品手册中找出最相关的段落并生成答案。

4.1 第一步:基础设施搭建

  1. 创建托管PostgreSQL集群

    • 登录DigitalOcean控制台,进入“Databases”。
    • 点击“Create Database Cluster”,选择PostgreSQL版本(建议15及以上,对pgvector支持更好)。
    • 选择机型。对于初期原型,选择“Basic”或“General Purpose”系列中配备NVMe SSD的规格即可,如“Basic-2 vCPU / 4GB RAM”。
    • 选择区域,最好靠近你的主要用户或后续要集成的其他服务(如AI Inference)。
    • 启用连接池(如PgBouncer),这对处理大量并发的向量搜索短连接非常有帮助。
    • 创建集群,记下连接信息(主机、端口、数据库名、用户名、密码)。
  2. 启用pgvector扩展

    • 集群创建完成后,进入其概览页面,找到“Extensions”选项卡。
    • 在列表中找到pgvector,点击“Enable”。DigitalOcean会自动完成安装。
  3. 准备AI推理服务(可选但推荐)

    • 在“AI/ML”服务中,创建或部署一个AI Inference服务。你可以选择预置的模型(如Llama 3.1 8B Instruct)或上传自己的自定义模型。
    • 这将为我们后续的RAG生成步骤提供便利的API端点。

4.2 第二步:数据库Schema设计与数据灌入

连接到你的PostgreSQL数据库,执行以下SQL:

-- 1. 创建扩展(如果控制台启用后自动创建,此步可省略,但执行无害) CREATE EXTENSION IF NOT EXISTS vector; -- 2. 创建存储文档片段和向量的核心表 CREATE TABLE document_chunks ( id BIGSERIAL PRIMARY KEY, document_id VARCHAR(255) NOT NULL, -- 原始文档ID chunk_text TEXT NOT NULL, -- 文本片段内容 embedding vector(1536), -- 假设使用OpenAI text-embedding-3-small模型 metadata JSONB DEFAULT '{}', -- 存储来源、页码、标题等元数据 created_at TIMESTAMPTZ DEFAULT NOW() ); -- 3. 创建HNSW索引以加速向量搜索 CREATE INDEX ON document_chunks USING hnsw (embedding vector_cosine_ops); -- 4. 创建用于过滤的B-tree索引 CREATE INDEX ON document_chunks USING gin (metadata); -- 支持JSONB字段的快速查询 CREATE INDEX ON document_chunks (document_id);

接下来是数据灌入。你需要一个流程将你的产品手册(PDF、Markdown等)进行文本分割、向量化并存入数据库。

# 这是一个使用Python的示例脚本 import psycopg2 from langchain.text_splitter import RecursiveCharacterTextSplitter from openai import OpenAI import PyPDF2 # 假设处理PDF # 配置 DO_DB_CONN_STR = "postgresql://user:password@host:port/dbname" OPENAI_API_KEY = "your-key" EMBEDDING_MODEL = "text-embedding-3-small" # 初始化 client = OpenAI(api_key=OPENAI_API_KEY) conn = psycopg2.connect(DO_DB_CONN_STR) cur = conn.cursor() text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) def extract_text_from_pdf(pdf_path): # ... 使用PyPDF2提取文本 ... return full_text def get_embedding(text): response = client.embeddings.create(model=EMBEDDING_MODEL, input=text) return response.data[0].embedding def process_document(pdf_path, doc_id): full_text = extract_text_from_pdf(pdf_path) chunks = text_splitter.split_text(full_text) for i, chunk in enumerate(chunks): embedding = get_embedding(chunk) metadata = {"doc_id": doc_id, "chunk_index": i, "source": pdf_path} # 使用pgvector的扩展类型,psycopg2会自动适配 cur.execute( "INSERT INTO document_chunks (document_id, chunk_text, embedding, metadata) VALUES (%s, %s, %s, %s)", (doc_id, chunk, embedding, metadata) ) conn.commit() # 处理文档 process_document("user_manual.pdf", "manual_v2.0") cur.close() conn.close()

实操心得:在灌入大量数据时,不要逐条提交。可以每处理100或500个chunk再commit一次,或者使用cursor.executemany进行批量插入,能极大提升效率。另外,在构建HNSW索引前灌入数据,比先建索引再插入要快得多。建议灌完所有数据后,再执行CREATE INDEX语句。

4.3 第三步:实现RAG检索与生成核心逻辑

应用后端(比如一个FastAPI服务)的核心函数如下:

from fastapi import FastAPI from pydantic import BaseModel import psycopg2 from psycopg2.extras import RealDictCursor import openai import os app = FastAPI() # 配置 DO_DB_CONN_STR = os.getenv("DO_DB_CONN_STR") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") DO_AI_INFERENCE_URL = os.getenv("DO_AI_INFERENCE_URL") # 如果使用DO的推理服务 client = openai.OpenAI(api_key=OPENAI_API_KEY) class QueryRequest(BaseModel): question: str top_k: int = 5 filter_doc_id: str = None def get_query_embedding(question: str) -> list: response = client.embeddings.create(model="text-embedding-3-small", input=question) return response.data[0].embedding @app.post("/ask") async def ask_question(req: QueryRequest): # 1. 将用户问题转换为向量 query_vec = get_query_embedding(req.question) # 2. 在数据库中执行混合检索 conn = psycopg2.connect(DO_DB_CONN_STR, cursor_factory=RealDictCursor) cur = conn.cursor() sql = """ SELECT chunk_text, metadata, embedding <=> %s AS similarity FROM document_chunks WHERE 1=1 """ params = [query_vec] if req.filter_doc_id: sql += " AND metadata->>'doc_id' = %s" params.append(req.filter_doc_id) sql += " ORDER BY similarity ASC LIMIT %s;" params.append(req.top_k) cur.execute(sql, params) results = cur.fetchall() cur.close() conn.close() # 3. 构建上下文 context = "\n\n---\n\n".join([f"[来源:{r['metadata'].get('source', 'N/A')}]\n{r['chunk_text']}" for r in results]) # 4. 调用LLM生成答案(这里以OpenAI为例,也可替换为DO AI Inference端点) prompt = f"""基于以下上下文信息,回答用户的问题。如果上下文没有提供足够信息,请直接说“根据现有资料无法回答”。 上下文: {context} 用户问题:{req.question} 请用中文给出清晰、准确的回答:""" completion = client.chat.completions.create( model="gpt-4o-mini", # 或使用部署在DO上的模型 messages=[{"role": "user", "content": prompt}], temperature=0.2 ) answer = completion.choices[0].message.content return { "answer": answer, "relevant_chunks": results, "context_used": context }

这个简单的API端点就完成了从问题向量化、数据库混合检索、上下文构建到最终答案生成的完整RAG链条。部署这个应用到DigitalOcean的App Platform,并与你的数据库、AI推理服务配置在同一VPC内,就能获得最佳的网络性能和安全性。

5. 性能调优与生产环境考量

将原型投入生产,我们需要关注性能、稳定性和成本。以下是基于DigitalOcean环境的关键调优点。

5.1 向量索引参数调优

索引参数没有银弹,需要基于你的数据集进行测试。

  • HNSW参数 (m,ef_construction,ef_search)

    • m:增加m会提高召回率和索引大小,降低构建速度。对于100万左右的数据集,从16开始测试。数据量更大或对精度要求极高,可以尝试24或32。
    • ef_construction:增加此值会提高索引质量(召回率),但也会显著增加构建时间和内存。通常设置为m的2-4倍,例如m=16时,ef_construction=64是一个不错的起点。
    • ef_search:这是在查询时使用的参数(不是在CREATE INDEX中设置,而是在查询时通过SET或在索引中指定)。它控制搜索时考察的候选节点数量。值越大,召回率越高,速度越慢。可以在查询时动态调整:
      SET hnsw.ef_search = 100; -- 在会话中设置 SELECT * FROM items ORDER BY embedding <=> '[0.1, ...]' LIMIT 10;
      生产环境中,可以根据查询的实时性要求,在应用代码中为不同类型的查询设置不同的ef_search值。
  • IVFFlat参数 (lists)

    • lists:聚类数量。一个经验法则是设置为sqrt(行数)。对于100万行数据,可以设置为1000。lists值越大,查询精度越高,但速度会变慢。
    • 重建索引:记住,IVFFlat索引在数据更新后需要重建以保持效率。可以设置一个定时任务,在业务低峰期定期执行REINDEX INDEX index_name;

如何测试?建立一个包含代表性查询的测试集,然后编写脚本,遍历不同的参数组合,评估查询延迟和召回率(通过人工或与暴力扫描结果对比),找到满足你业务需求的最佳平衡点。

5.2 查询性能优化

  1. 使用连接池:务必启用DigitalOcean PostgreSQL提供的连接池(如PgBouncer)。向量搜索查询通常是短平快的,连接池可以避免频繁建立和销毁TCP/数据库连接的开销,极大提升并发能力。
  2. 善用过滤条件:在向量相似度搜索前,尽可能使用高效的过滤条件(如WHERE metadata->>'doc_id' = 'xxx')缩小搜索范围。PostgreSQL可能会先利用B-tree或GIN索引快速过滤出子集,再在这个小得多的子集上进行向量比较,性能提升巨大。
  3. 避免SELECT *:只查询你需要的列,特别是不要轻易在查询中包含巨大的embedding向量列,除非必要。传输大量向量数据会消耗网络带宽和内存。
  4. 分页优化:对于深度分页(LIMIT 10 OFFSET 10000),传统数据库性能会下降。对于向量搜索,更常见的模式是“游标分页”或“基于相似度阈值分页”。例如,记录上一次查询最后一个结果的相似度得分,下一次查询时加上WHERE similarity < :last_score条件。

5.3 成本控制与架构设计

在云上,成本意识很重要。

  • 选择合适的机型:从“Basic”系列起步,监控CPU、内存、磁盘IO和连接数。如果CPU持续高负载,说明向量计算压力大,考虑升级CPU。如果内存使用率持续高位,可能是HNSW索引或连接缓存占用过多,需要升级内存或优化索引参数。
  • 读写分离:利用DigitalOcean PostgreSQL的只读副本。将大量的向量搜索只读请求路由到只读副本,主库只负责处理写操作(数据插入、更新)和复杂的混合事务。这不仅能提升性能,也是一种高可用策略。
  • 冷热数据分层:对于历史数据或访问频率极低的数据,可以考虑将其向量从昂贵的、索引优化的主表中迁移到另一个未建索引或使用IVFFlat索引的归档表中。查询时,优先查询热表,必要时再联合查询冷表。
  • 监控与告警:充分利用DigitalOcean提供的数据库监控仪表盘。重点关注:
    • 查询延迟(Query latency):特别是向量搜索查询的P95、P99延迟。
    • 连接数(Connections):确保没有连接泄漏,且连接池配置合理。
    • 磁盘IOPS:向量索引的随机读取对IOPS敏感,确保磁盘性能足够。
    • 设置告警,当延迟超过阈值或连接数爆满时及时通知。

6. 常见陷阱与进阶技巧

在实际开发中,你会遇到一些教科书上不会提的问题。这里分享一些踩坑后总结的经验。

6.1 向量维度对齐与模型升级

这是一个极易忽略的致命问题。假设你最初使用text-embedding-ada-002(1536维),所有数据都用这个模型生成了向量。后来你升级到了性能更好的text-embedding-3-small(也是1536维,但向量空间不同)。如果你直接用新模型为新的查询生成向量,去检索用旧模型生成的数据向量,效果会非常差,因为它们的向量空间没有对齐。

解决方案

  1. 一次性全量迁移:最彻底的方法。用新模型为所有历史数据重新生成向量,替换掉旧的。这需要停机窗口或双写双读的复杂迁移方案。
  2. 使用跨编码器进行重排(Rerank):这是一个更实用的渐进式方案。继续用旧模型进行初步的向量检索(比如召回100个结果),然后用一个强大的跨编码器模型(如BGE Reranker)对这100个结果进行精排。跨编码器直接计算查询和文档之间的相关性分数,不依赖于向量空间的一致性,可以作为不同嵌入模型之间的“桥梁”。你可以在DigitalOcean AI Inference上部署一个这样的重排模型。

6.2 文本分块的艺术

分块(Chunking)策略直接决定检索质量。简单的按固定字符数分割会切断完整的句子或概念。

  • 递归字符分割:LangChain的RecursiveCharacterTextSplitter是个不错的起点,它会优先按段落、句子、单词等自然分隔符来分。
  • 基于语义的分割:使用嵌入模型本身或小型句子模型计算句子间的相似度,在语义变化处进行分割。这更复杂但效果更好。
  • 重叠(Overlap):设置重叠区(如200个字符)至关重要,它能防止一个概念恰好被切成两半而丢失关键信息。
  • 小技巧:对于代码文档,可以按函数/类定义分块;对于手册,可以按章节或子标题分块。在metadata中记录分块策略和来源位置,便于后续调试和优化。

6.3 处理“未命中”与幻觉

RAG不是万能的,当知识库中没有相关信息时,LLM可能会“胡编乱造”(幻觉)。

  • 设置相似度阈值:在查询时,添加WHERE embedding <=> query_vec < threshold。只返回相似度高于一定阈值(即距离小于阈值)的结果。这个阈值需要通过实验确定。
  • 在Prompt中明确指令:就像我们示例中做的,在Prompt里明确要求“如果上下文没有提供足够信息,请直接说‘根据现有资料无法回答’”。
  • 引用溯源:在返回答案的同时,返回引用的原文片段及其元数据(如来源、页码)。这不仅能增加可信度,也方便用户追溯和验证。

6.4 超越简单检索:高级RAG模式

当基本RAG遇到复杂问题时,可以考虑以下进阶模式:

  • 多跳检索(Multi-hop Retrieval):对于需要串联多个知识点才能回答的问题(如“A产品相比B产品在安全特性上有何优势?”),可以先检索关于A产品安全特性的文档,再从这些文档中提取关键实体(如“加密算法X”),再用这些实体作为新的查询去检索B产品的相关文档。这需要更复杂的查询规划和迭代。
  • 查询扩展(Query Expansion):使用LLM对原始用户问题进行重写或生成多个相关问题。例如,将“怎么退款?”扩展为“退款流程是什么?”、“退款需要多久?”、“退款政策有哪些?”。然后用这组问题并行检索,合并结果,能显著提高召回率。
  • 混合检索(Hybrid Search):结合稀疏检索(如BM25,关键词匹配)和密集检索(向量搜索)。BM25擅长精确匹配关键词,向量搜索擅长语义匹配。将两者的得分进行加权融合,可以兼顾查全率和查准率。虽然pgvector本身不直接提供BM25,但PostgreSQL的全文搜索功能可以作为一个轻量级的替代方案。

在DigitalOcean的生态内,你可以将上述复杂逻辑实现在你的应用后端(部署在App Platform或Kubernetes上),数据库负责高效的数据存储和混合检索,AI Inference服务负责嵌入生成、重排和最终答案生成,形成一个强大且灵活的AI应用后端。这正体现了“数据与学习层”整合带来的敏捷性——你无需在多个异构系统间挣扎,可以更专注于业务逻辑本身的创新。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/12 10:37:18

UE导入FBX缺失平滑组警告的解决方案

1. 问题现象与背景解析 最近在使用Unreal Engine导入FBX格式的骨骼网格体(SkeletalMesh)时&#xff0c;遇到了一个典型警告&#xff1a;"在FBX文件中未找到这个网格体Mesh_001的平滑组信息"。这个看似简单的提示背后&#xff0c;其实涉及到三维模型导入流程中的几个关…

作者头像 李华
网站建设 2026/8/12 10:36:38

单细胞转录组富集分析实战:Scanpy+gseapy打通差异基因到通路解读

1. 项目概述&#xff1a;从单细胞数据到生物学洞见的桥梁如果你正在处理单细胞转录组数据&#xff0c;用Scanpy做完差异表达分析&#xff0c;拿到一长串差异基因列表后&#xff0c;是不是经常有种“老虎吃天&#xff0c;无从下口”的感觉&#xff1f;几百上千个基因名字摆在那里…

作者头像 李华
网站建设 2026/8/12 10:35:06

从NTP到PTP:深入解析高精度时间同步的三大维度与工程实践

1. 从“对表”说起&#xff1a;为什么我们需要精确同步&#xff1f;想象一下&#xff0c;你和朋友约好下午三点在市中心的地标建筑见面。你们各自看着自己的手表&#xff0c;但你的表快了5分钟&#xff0c;他的表慢了3分钟。结果就是&#xff0c;你提前到了&#xff0c;在寒风中…

作者头像 李华
网站建设 2026/8/12 10:34:39

SELinux中文手册:从核心概念到实战排错,掌握强制访问控制

1. 项目概述&#xff1a;为什么我们需要一份SELinux中文手册&#xff1f;如果你在Linux系统管理或安全运维领域摸爬滚打过一段时间&#xff0c;那么“SELinux”这个名字对你来说&#xff0c;大概率是又爱又恨。爱的是它那堪称铜墙铁壁的强制访问控制能力&#xff0c;恨的是它那…

作者头像 李华
网站建设 2026/8/12 10:34:22

网络安全攻防实战:从入门到精通的系统指南

1. 网络安全攻防实战入门指南在数字化时代&#xff0c;网络安全已成为每个技术从业者都需要了解的基础知识。作为一名长期活跃在安全领域的老兵&#xff0c;我经常被问到&#xff1a;"如何系统性地学习网络安全攻防技术&#xff1f;"今天我就从实战角度&#xff0c;分…

作者头像 李华
网站建设 2026/8/12 10:34:16

从工具到伙伴:打造会学习的AI智能体,实现持续进化的智能协作

1. 从“一次性工具”到“成长型伙伴”&#xff1a;为什么我们需要会学习的智能体&#xff1f; 最近在折腾各种AI智能体框架时&#xff0c;我产生了一个强烈的感受&#xff1a;大多数智能体&#xff0c;本质上还是个“高级工具”。你给它一个任务&#xff0c;它调用API、执行流程…

作者头像 李华