用Vector Database + LLM构建RAG应用:独立开发者的AI产品实战
用Vector Database LLM构建RAG应用独立开发者的AI产品实战RAG是什么为什么它是AI产品的核心架构RAGRetrieval-Augmented Generation检索增强生成是解决LLM大语言模型幻觉和知识过时问题的核心技术。问题一LLM的幻觉HallucinationLLM会编造它不知道的信息。如果你问你们产品的退款政策是什么LLM可能生成一个听起来合理但实际不存在的退款政策——这会导致用户投诉。问题二LLM的知识截止日期GPT-4的知识截止到2023年12月Claude 3的截止到2024年某月。如果你的产品有最新功能更新LLM不知道。RAG的解决方案给LLM提供外部知识库RAG的流程检索Retrieve根据用户问题从知识库里找到最相关的文档增强Augment把检索到的文档作为上下文提供给LLM生成GenerateLLM基于上下文回答问题——不再编造技术栈选型Vector DB Embedding Model LLMVector Database向量数据库存储和检索文档的向量表示主流选择Pinecone托管服务免费计划5万向量简单易用Weaviate开源可自托管也可托管Qdrant开源Rust编写性能极高适合自托管Supabase pgvector如果你已经用Supabase可以直接用它的pgvector扩展免费Embedding Model嵌入模型把文本转换成向量OpenAI text-embedding-3-small性能好价格低$0.02/1M tokensCohere embed-english-v3.0多语言支持好开源方案all-MiniLM-L6-v2本地运行无API成本LLM回答生成GPT-4o/GPT-4-turbo质量最高价格中等Claude 3.5 Sonnet长上下文200K tokens适合大量文档场景开源方案Llama 3用Groq或自托管成本更低实战用Supabase pgvector OpenAI构建产品文档问答机器人第一步准备知识库文档把你的产品文档、FAQ、帮助文档整理成Markdown文件。每个文件应该是一个独立的主题如如何退款.md、如何更改定价计划.md。第二步文档分块ChunkingLLM的上下文窗口有限即使200K也不能把整个知识库都塞进去。需要把文档分块。分块策略按标题分块每个H2/H3章节作为一个块固定大小分块每块500-1000个字符重叠100-200字符避免切断语义按语义分块用LLM判断这段是否在讲同一个主题我的实现固定大小分块// lib/chunkDocuments.ts export function chunkDocument(text: string, chunkSize 800, overlap 200): string[] { const chunks: string[] []; let start 0; while (start text.length) { const end start chunkSize; const chunk text.slice(start, end); chunks.push(chunk); start chunkSize - overlap; // 重叠避免切断语义 } return chunks; }第三步生成向量并存储到pgvector// scripts/embedDocuments.ts import { OpenAI } from openai; import { createClient } from supabase/supabase-js; const openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }); const supabase createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_KEY!); // 启用pgvector扩展在Supabase SQL编辑器里执行 // CREATE EXTENSION IF NOT EXISTS vector; // 创建表如果还没创建 // CREATE TABLE documents ( // id BIGSERIAL PRIMARY KEY, // content TEXT, // embedding VECTOR(1536), -- OpenAI embedding维度是1536 // metadata JSONB -- 存储标题、来源URL等 // ); async function embedAndStore() { // 1. 读取所有文档假设在docs/目录 const docs await readAllDocuments(./docs); for (const doc of docs) { const chunks chunkDocument(doc.content); for (let i 0; i chunks.length; i) { const chunk chunks[i]; // 2. 生成embedding const embeddingResp await openai.embeddings.create({ model: text-embedding-3-small, input: chunk, }); const embedding embeddingResp.data[0].embedding; // 3. 存储到pgvector await supabase.from(documents).insert({ content: chunk, embedding: [${embedding.join(,)}], // pgvector格式 metadata: { title: doc.title, source: doc.url, chunk_index: i, }, }); console.log(Stored chunk ${i} of ${doc.title}); } } }第四步实现检索相似度搜索// lib/retrieve.ts import { OpenAI } from openai; import { createClient } from supabase/supabase-js; const openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }); const supabase createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_KEY!); export async function retrieveRelevantDocs(query: string, topK 5) { // 1. 把查询转换成向量 const embeddingResp await openai.embeddings.create({ model: text-embedding-3-small, input: query, }); const queryEmbedding embeddingResp.data[0].embedding; // 2. 在pgvector里做相似度搜索余弦距离 const { data, error } await supabase.rpc(match_documents, { query_embedding: [${queryEmbedding.join(,)}], match_threshold: 0.78, // 相似度阈值0-1越大越严格 match_count: topK, }); if (error) { console.error(Search error:, error); return []; } return data; // 返回相关的文档块 }在Supabase里创建match_documents函数CREATE OR REPLACE FUNCTION match_documents ( query_embedding VECTOR(1536), match_threshold FLOAT, match_count INT ) RETURNS TABLE ( id BIGINT, content TEXT, metadata JSONB, similarity FLOAT ) LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT documents.id, documents.content, documents.metadata, 1 - (documents.embedding query_embedding) AS similarity -- 余弦相似度 FROM documents WHERE 1 - (documents.embedding query_embedding) match_threshold ORDER BY similarity DESC LIMIT match_count; END; $$;第五步构建Prompt并调用LLM// lib/rag.ts import { OpenAI } from openai; import { retrieveRelevantDocs } from ./retrieve; const openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }); export async function answerWithRAG(question: string): Promisestring { // 1. 检索相关文档 const relevantDocs await retrieveRelevantDocs(question); if (relevantDocs.length 0) { return 抱歉我在知识库里没有找到相关信息。请联系supportyourproduct.com。; } // 2. 构建上下文 const context relevantDocs.map(doc doc.content).join(\n\n---\n\n); // 3. 构建Prompt const prompt 你是${process.env.PRODUCT_NAME}的帮助助手。基于以下上下文回答问题。如果上下文里没有答案说我不知道不要编造。 上下文 ${context} 问题${question} 回答; // 4. 调用LLM const resp await openai.chat.completions.create({ model: gpt-4o, messages: [ { role: system, content: 你是 helpful 的产品帮助助手。 }, { role: user, content: prompt }, ], temperature: 0.3, // 降低温度减少幻觉 max_tokens: 500, }); return resp.choices[0].message.content!; }评估与优化让RAG应用更准确常见问题一检索到的文档不相关原因Embedding模型没有理解领域专业术语。解决方案用领域微调的Embedding模型或在检索前改写用户问题用LLM把口语化问题转换成包含关键词的问题。async function rewriteQuery(originalQuery: string): Promisestring { const resp await openai.chat.completions.create({ model: gpt-4o, messages: [ { role: system, content: 你是查询优化助手。把用户的问题改写成包含关键词的查询用于向量数据库检索。 }, { role: user, content: originalQuery }, ], temperature: 0.3, }); return resp.choices[0].message.content!; }常见问题二LLM仍然编造答案原因上下文不够明确或LLM太自信。解决方案让LLM引用来源。// 在Prompt里要求引用来源 const prompt 基于以下上下文回答问题。每个回答后面用[来源: 文档标题]格式引用来源。如果上下文里没有说我不知道。 上下文 ${context} 问题${question} 回答;评估指标检索准确率Retrieval Precision检索到的Top-5文档里有多少是真的相关回答准确率Answer AccuracyLLM的回答是否正确人工评估或用有标准答案的测试集自动评估拒答率Abstain Rate当知识库没有答案时LLM是否说我不知道越高越好避免幻觉部署与监控让RAG应用稳定运行缓存常见查询用Redis缓存常见问题的回答。import { createClient } from redis; const redis createClient({ url: process.env.REDIS_URL! }); export async function answerWithCache(question: string) { // 尝试从缓存读取 const cached await redis.get(rag:${question}); if (cached) return cached; // 缓存未命中执行RAG const answer await answerWithRAG(question); // 写入缓存过期时间1小时 await redis.set(rag:${question}, answer, { EX: 3600 }); return answer; }监控用LangSmithLangChain的监控平台或Helicone监控每次检索的相似度分数分布LLM的Token消耗和响应时间用户反馈点赞/点踩结论RAG是独立开发者的AI产品入场券你不需要训练自己的LLM成本高、技术难度大。用RAG架构你可以用少量文档 开源/商业化向量数据库 API调用的LLM构建出高质量、低成本的AI功能。最小可行RAGMVP用Supabase pgvector存储文档向量免费用OpenAI text-embedding-3-small生成向量$0.02/1M tokens很便宜用GPT-4o生成回答$0.005/1K input tokens这套方案处理1万次查询的成本约$20-50——对独立开发者完全可承受。下一步把RAG应用到客户支持自动化、产品推荐、个性化学习路径等场景——这些是AI时代独立开发者的核心竞争优势。

相关新闻

C++实现单纯形法:从原理到工程实践

C++实现单纯形法:从原理到工程实践

1. 项目概述:为什么用C实现单纯形法? 线性规划是运筹学里最经典的工具之一,从生产排程、物流优化到投资组合,几乎无处不在。而单纯形法,自1947年由乔治丹齐格提出以来,一直是求解线性规划问题的中流砥柱。…

2026/7/25 4:15:07 阅读更多 →
基于YOLOv5改进的农业杂草识别系统设计与优化

基于YOLOv5改进的农业杂草识别系统设计与优化

1. 项目背景与核心价值在农业智能化转型的大背景下,杂草识别一直是精准农业中的关键痛点。传统人工除草方式效率低下且成本高昂,而过度使用除草剂又会导致土壤污染和生态破坏。基于深度学习的杂草识别系统为解决这一难题提供了新的技术路径。我去年指导的…

2026/7/25 4:14:07 阅读更多 →
Node.js+Vue3打造健身房人脸识别系统实战

Node.js+Vue3打造健身房人脸识别系统实战

1. 项目背景与核心价值最近在帮本地一家连锁健身房做数字化升级,他们最大的痛点就是会员忘带卡、前台排队验证身份的问题。传统刷卡系统不仅硬件成本高,还经常出现代刷、冒用的情况。于是我们基于Node.jsVue3开发了一套人脸识别健身房管理系统&#xff0…

2026/7/25 4:14:07 阅读更多 →

最新新闻

86BOX虚拟机:在Windows XP SP3中精准模拟老硬件,解决软件兼容性问题

86BOX虚拟机:在Windows XP SP3中精准模拟老硬件,解决软件兼容性问题

这次我们来看一个专门用于模拟老式计算机系统的开源虚拟机项目:86BOX。它不是一个通用的现代虚拟机软件,而是一个专注于精确模拟上世纪80年代到90年代经典PC硬件的模拟器。简单来说,你可以把它理解为一个“时光机”,用来在今天的Windows、macOS或Linux系统上,原汁原味地运…

2026/7/25 4:26:10 阅读更多 →
从粉丝应援到专业记录:全链路活动内容生产与自动化发布技术方案

从粉丝应援到专业记录:全链路活动内容生产与自动化发布技术方案

这次我们来看一个关于曾沛慈粉丝应援活动的记录项目。从标题“曾沛慈|20260627 pets看无人机应援”来看,这并非一个技术工具或开源模型,而更像是一次粉丝应援活动的记录、分享或纪念性内容。对于技术博客而言,我们的重点不是讨论…

2026/7/25 4:26:10 阅读更多 →
Keyboard Chatter Blocker:彻底告别机械键盘连击问题的终极免费方案

Keyboard Chatter Blocker:彻底告别机械键盘连击问题的终极免费方案

Keyboard Chatter Blocker:彻底告别机械键盘连击问题的终极免费方案 【免费下载链接】KeyboardChatterBlocker A handy quick tool for blocking mechanical keyboard chatter. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyboardChatterBlocker 你是否曾…

2026/7/25 4:26:10 阅读更多 →
终极指南:如何用FF14 ACT插件快速跳过副本过场动画

终极指南:如何用FF14 ACT插件快速跳过副本过场动画

终极指南:如何用FF14 ACT插件快速跳过副本过场动画 【免费下载链接】FFXIV_ACT_CutsceneSkip 项目地址: https://gitcode.com/gh_mirrors/ff/FFXIV_ACT_CutsceneSkip 还在为《最终幻想14》中冗长的副本过场动画而烦恼吗?FF14 ACT辍学插件正是你需…

2026/7/25 4:26:10 阅读更多 →
3分钟掌握TMSpeech:Windows下免费实时语音转文字终极指南

3分钟掌握TMSpeech:Windows下免费实时语音转文字终极指南

3分钟掌握TMSpeech:Windows下免费实时语音转文字终极指南 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech 你是否曾在重要会议中因分心错过关键信息?是否因为外语视频语速太快而无法完全理解&…

2026/7/25 4:26:10 阅读更多 →
Onekey终极指南:如何高效配置Steam游戏解锁与Depot清单自动化

Onekey终极指南:如何高效配置Steam游戏解锁与Depot清单自动化

Onekey终极指南:如何高效配置Steam游戏解锁与Depot清单自动化 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey Onekey是一款专为Steam平台设计的开源游戏解锁工具,通过自动…

2026/7/25 4:25:10 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻