覆盖Next.js+NestJS+OpenAI+MongoDB技术栈,从零开始构建AI应用的系统性教程。
这里提供了一份详细路线图,介绍如何使用 Next.js、NestJS、OpenAI 和 MongoDB Vector Search 构建 Generative AI 应用。本指南涵盖从为公司文档生成 embedding、存储 vector、检索数据,到使用 prompt engineering 生成智能 AI 回答的完整流程。
一份结构化的端到端指南,帮助你构建可用于生产环境的 Generative AI 应用。
定义问题陈述(例如 AI 驱动的文档搜索、聊天机器人、摘要生成)。
选择 AI 任务(例如文本生成、问答、摘要生成)。
定义用户输入(例如文本查询、文档上传)。
确定输出格式(例如纯文本、结构化回答)。
确定检索方式(例如 MongoDB Vector Search、RAG)。
AI 基础:Generative AI、RAG(Retrieval-Augmented Generation,检索增强生成)。
Vector Search:MongoDB Atlas Vector Search。
Next.js 与 NestJS:全栈开发。
收集公司文档(例如 PDF、Word、CSV、JSON)。
将文档高效地存储到 MongoDB 中。
生成并存储 vector embedding。
设置 MongoDB Atlas:为文档和 embedding 创建数据库。启用 Vector Search。
设置 MongoDB Atlas:
创建用于存储文档和 embedding 的数据库。
启用 Vector Search。
安装依赖:
安装依赖:
npm install openai mongoose @nestjs/mongoose
将文档存储到 MongoDB:
const documentSchema = new mongoose.Schema({
content: String,
embedding: { type: Array, default: [] },
});
将文档转换为 embedding:
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function generateEmbedding(text: string) {
const response = await openai.embeddings.create({
input: text,
model: 'text-embedding-ada-002',
});
return response.data[0].embedding;
}
将 vector 存储到 MongoDB:
async function storeDocument(content: string) {
const embedding = await generateEmbedding(content);
await DocumentModel.create({ content, embedding });
}
MongoDB Atlas Vector Search。
OpenAI Embeddings API。
清洗并处理非结构化数据。
实现文档分块,以获得效果更好的 embedding。
存储结构化 metadata,以便进行检索。
删除不必要的部分:
function cleanText(text: string): string {
return text.replace(/(Disclaimer|Footer|Further Support).*/g, '');
}
对大型文档进行分块:
function chunkText(text: string, chunkSize = 500) {
return text.match(new RegExp(`.{1,${chunkSize}}`, 'g'));
}
文本预处理(正则表达式、分块、停用词移除)。
使用 LangChain 进行文本切分。
如有需要,训练自定义 OpenAI 模型。
针对特定行业术语对回答进行 fine-tune。
准备训练数据(JSONL 格式):
{"messages": [{"role": "system", "content": "You are a financial assistant."}, {"role": "user", "content": "What is an ETF?"}, {"role": "assistant", "content": "An ETF is an exchange-traded fund."}]}
上传到 OpenAI 并进行训练:
openai api fine_tunes.create -t dataset.jsonl -m gpt-4
对 OpenAI 模型进行 fine-tuning。
通过 Prompt Engineering 获得更好的回答。
实现 vector search,快速查找相关数据。
使用 MongoDB Vector Search 检索匹配度最高的文档。
执行 Vector Search 查询:
async function searchDocuments(query: string) {
const queryEmbedding = await generateEmbedding(query);
return await DocumentModel.find({
$vectorSearch: {
queryVector: queryEmbedding,
path: 'embedding',
numCandidates: 10,
limit: 5,
},
});
}
检索数据并发送给 OpenAI 以生成回答:
async function generateAIResponse(query: string) {
const relevantDocs = await searchDocuments(query);
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'Use the following documents to answer the user query:' },
...relevantDocs.map(doc => ({ role: 'user', content: doc.content })),
{ role: 'user', content: query },
],
});
return response.choices[0].message.content;
}
MongoDB Vector Search 查询。
Retrieval-Augmented Generation(RAG,检索增强生成)。
构建 REST API 来处理 AI 查询。
提供用于查询 AI 生成回答的 endpoint。
@Injectable()
export class AIService {
async processQuery(query: string) {
return await generateAIResponse(query);
}
}
@Controller('ai')
export class AIController {
constructor(private readonly aiService: AIService) {}
@Post('query')
async handleQuery(@Body() data: { query: string }) {
return this.aiService.processQuery(data.query);
}
}
NestJS Controller 与 Service。
API 开发最佳实践。
创建用于与 AI 交互的 Next.js UI。
将查询发送到后端并展示结果。
从 Next.js 发起 API 调用:
async function fetchAIResponse(query: string) {
const res = await fetch('/api/ai-query', {
method: 'POST',
body: JSON.stringify({ query }),
});
return res.json();
}
export default function AIChat() {
const [query, setQuery] = useState('');
const [response, setResponse] = useState('');
async function handleSubmit() {
const data = await fetchAIResponse(query);
setResponse(data);
}
return (
<div>
<input type="text" value={query} onChange={e => setQuery(e.target.value)} />
<button onClick={handleSubmit}>Ask AI</button>
<p>{response}</p>
</div>
);
}
React Hooks 与状态管理。
将 Next.js 部署到 Vercel。
将 NestJS 部署到 AWS/GCP。
使用 MongoDB Atlas 进行数据存储。
用户反馈与迭代阶段对于根据真实使用情况改进 AI 应用至关重要。它能够确保系统长期保持准确、易用和高效。
收集用户对 AI 回答的反馈。
分析错误的 AI 回答并提高准确性。
优化查询处理、检索和模型回答。
通过反馈循环实现持续改进。
鼓励用户为 AI 回答评分或报告不准确之处。
为 AI 回答添加反馈按钮。
收集用户评分(例如 👍/👎、1~5 星)。
export default function AIResponse({ response }) {
const [feedback, setFeedback] = useState(null);
async function sendFeedback(value) {
await fetch('/api/feedback', {
method: 'POST',
body: JSON.stringify({ response, feedback: value }),
});
setFeedback(value);
}
return (
<div>
<p>{response}</p>
<button onClick={() => sendFeedback('👍')}>👍</button>
<button onClick={() => sendFeedback('👎')}>👎</button>
</div>
);
}
在 MongoDB 中创建一个 feedback collection。
@Controller('feedback')
export class FeedbackController {
@Post()
async saveFeedback(@Body() data: { response: string; feedback: string }) {
await FeedbackModel.create(data);
}
}
定期检查负面反馈,并对错误进行分类:
事实错误 → 改进检索模型。
结果不相关 → 优化 vector embedding。
回答不清楚 → 优化 prompt engineering。
async function getNegativeFeedback() {
return await FeedbackModel.find({ feedback: '👎' }).limit(100);
}
根据分析结果,通过以下方式改进系统:
更好的 Prompt Engineering 示例:为 AI prompt 添加上下文。
示例:为 AI prompt 添加上下文。
const prompt = `
You are an AI assistant for a legal firm.
Use the following company documents to answer accurately:
${retrievedDocuments}
`;
改进文档分块:如果检索不准确,请调整分块大小。
如果检索不准确,请调整分块大小。
function chunkText(text: string, chunkSize = 300) {
return text.match(new RegExp(`.{1,${chunkSize}}`, 'g'));
}
重新训练模型或进行 Fine-Tuning:如果 OpenAI 回答质量较低,请训练自定义 fine-tuned 模型。
如果 OpenAI 回答质量较低,请训练自定义 fine-tuned 模型。
通过日志跟踪 AI 性能(例如记录错误回答)。
使用指标(例如统计用户给出 👍 与 👎 的频率)。
对 Prompt 进行 A/B 测试(例如比较不同的 AI prompt 格式)。
定期更新模型(例如每月重新训练 embedding)。
async function logAIResponse(query: string, response: string) {
await PerformanceModel.create({ query, response, timestamp: new Date() });
}
部分评论可能仅对已登录的访问者可见。请登录以查看所有评论。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。