25 KiB
AI 智能搜索系统实施计划
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: 为项目列表添加 AI 语义搜索功能,支持自然语言查询并返回语义相关的项目,所有 AI 逻辑在 n8n 中实现,Next.js 应用保持纯净。
Architecture: 使用 Neon PostgreSQL 的 pgvector 扩展存储项目向量,n8n 工作流处理向量化(定时任务)和 AI 搜索(Webhook),Next.js API 路由作为代理转发请求到 n8n,前端添加切换按钮和相似度展示。
Tech Stack: Neon PostgreSQL + pgvector, n8n, OpenAI Embeddings API (text-embedding-3-small), Next.js 15 App Router, Prisma ORM, TypeScript, Tailwind CSS
前置准备
Task 0: 验证环境和依赖
Step 1: 验证 Neon 数据库 pgvector 支持
连接到 Neon 数据库(使用 Prisma Studio 或 psql):
# 使用 psql 连接
psql $DATABASE_URL
# 或使用 Neon SQL Editor: https://console.neon.tech
执行 SQL:
-- 检查 pgvector 扩展是否已安装
SELECT * FROM pg_extension WHERE extname = 'vector';
-- 如果未安装,安装它
CREATE EXTENSION IF NOT EXISTS vector;
-- 验证安装
SELECT vector_dims('[1,2,3]'::vector);
预期输出:3
Phase 1: 数据库迁移
Task 1: 创建 Prisma Schema 迁移
Files:
- Modify:
prisma/schema.prisma
Step 1: 添加向量字段到 Project 模型
在 prisma/schema.prisma 中找到 model Project,在字段列表末尾添加:
model Project {
// ... 现有字段(id, name, nameEn, slug, description, descriptionEn, content, contentEn, status, source, createdAt, updatedAt)
// 新增:向量嵌入字段
embedding vector(1536)? // pgvector 类型,1536维(OpenAI text-embedding-3-small)
embeddingUpdatedAt DateTime? // 记录向量化更新时间
}
Step 2: 创建迁移文件
# 生成迁移(会创建 SQL 文件)
pnpm prisma migrate dev --name add_project_embedding
# 预期输出:
# ✓ The following migration has been created and applied from new schema changes:
# migrations/TIMESTAMP_add_project_embedding/migration.sql
Step 3: 验证生成的 SQL
打开生成的迁移文件(例如 prisma/migrations/20260125000000_add_project_embedding/migration.sql),确保包含:
-- 启用 pgvector 扩展
CREATE EXTENSION IF NOT EXISTS vector;
-- 添加向量列
ALTER TABLE "Project" ADD COLUMN "embedding" vector(1536);
ALTER TABLE "Project" ADD COLUMN "embeddingUpdatedAt" TIMESTAMP;
-- 创建 HNSW 索引(余弦距离,适合文本搜索)
CREATE INDEX idx_project_embedding_cosine ON "Project" USING hnsw ("embedding" vector_cosine_ops) WITH (m = 16, ef_construction = 64);
-- 创建部分索引(查找未向量化项目)
CREATE INDEX idx_project_embedding_null ON "Project" ("id") WHERE "embedding" IS NULL;
Step 4: 手动优化迁移(可选)
如果生成的 SQL 不包含索引,手动修改迁移文件添加上述索引 SQL。
Step 5: 应用迁移
# 如果在上一步中已经自动应用,跳过此步骤
# 否则手动应用:
pnpm prisma migrate deploy
Step 6: 验证迁移
-- 检查表结构
\d "Project"
-- 应该看到:
-- embedding | vector(1536) |
-- embeddingUpdatedAt | timestamp |
-- 检查索引
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'Project';
-- 应该看到:
-- idx_project_embedding_cosine
-- idx_project_embedding_null
Step 7: 更新 Prisma Client
pnpm prisma generate
Step 8: 提交
git add prisma/schema.prisma prisma/migrations
git commit -m "feat: 添加项目向量嵌入字段和 pgvector 索引"
Phase 2: n8n 工作流配置
Task 2: 配置 n8n 凭证
Step 1: 获取 OpenAI API Key
访问 https://platform.openai.com/api-keys 创建新的 API Key。
Step 2: 在 n8n 中添加 OpenAI 凭证
- 打开 n8n 实例
- 导航到 Credentials → New
- 选择 OpenAI API
- 输入名称:
OpenAI Embeddings - 粘贴 API Key
- 保存
Step 3: 添加 Neon 数据库凭证
- 在 n8n 中导航到 Credentials → New
- 选择 PostgreSQL
- 输入名称:
Neon Database - 配置连接:
- Host: 从
DATABASE_URL提取(例如xxx.neon.tech) - Database: 数据库名(例如
neondb) - User: 用户名
- Password: 密码
- SSL: 启用
- Host: 从
- 点击 Test Connection 验证
- 保存
注意:不提交凭证到 git。
Task 3: 创建向量化工作流
Step 1: 创建新工作流
在 n8n 中:
- 点击 New Workflow
- 命名为:
Project Vectorization
Step 2: 添加 Cron 触发器
- 添加节点:Cron
- 配置:
- Trigger Interval:
Every 5 minutes - Cron Expression:
*/5 * * * *
- Trigger Interval:
- 保存节点
Step 3: 添加 PostgreSQL 节点(查询未向量化项目)
- 添加节点:Postgres(使用
Neon Database凭证) - 操作:Execute Query
- 输入查询:
SELECT id, name, "nameEn", description, "descriptionEn", content, "contentEn"
FROM "Project"
WHERE "embedding" IS NULL
AND "status" = 'ACTIVE'
LIMIT 20
- 测试节点(应该返回现有项目列表)
- 保存节点
Step 4: 添加 Function 节点(构造文本内容)
- 添加节点:Function → JavaScript
- 命名:
Construct Text Content - 输入代码:
// 为每个项目构造用于向量化的文本内容
const projects = $input.all();
return projects.map(item => {
const project = item.json;
// 合并字段,按权重构造
const parts = [
project.name || '',
project.nameEn || '',
project.description || '',
project.descriptionEn || '',
// tags 稍后处理
(project.content || '').substring(0, 500),
(project.contentEn || '').substring(0, 500)
].filter(Boolean);
const textContent = parts.join('\n\n');
return {
json: {
...project,
textContent: textContent
}
};
});
- 测试节点(应该添加
textContent字段) - 保存节点
Step 5: 添加 Split in Batches 节点
- 添加节点:Split In Batches
- 配置:
- Batch Size:
5(每批 5 个项目,避免 API 限流)
- Batch Size:
- 保存节点
Step 6: 添加 OpenAI Embeddings 节点
- 添加节点:OpenAI → Embeddings
- 使用
OpenAI Embeddings凭证 - 配置:
- Model:
text-embedding-3-small - Input:
{{ $json.textContent }}
- Model:
- 测试节点(应该返回向量数组)
- 保存节点
Step 7: 添加 PostgreSQL 节点(更新 embedding)
- 添加节点:Postgres
- 操作:Execute Query
- 输入查询:
UPDATE "Project"
SET
"embedding" = '{{ $json.data[0].embedding }}'::vector,
"embeddingUpdatedAt" = NOW()
WHERE "id" = {{ $json.id }}
- 测试节点
- 保存节点
Step 8: 添加 Wait 节点(控制速率)
- 添加节点:Wait
- 配置:
- Amount:
1秒
- Amount:
- 保存节点(在 Split in Batches 和 OpenAI 之间)
Step 9: 连接节点
按顺序连接:
Cron → Postgres (查询) → Function (构造) → Split in Batches → Wait → OpenAI Embeddings → Postgres (更新) → Loop back to Split in Batches
Step 10: 测试完整工作流
- 点击 Test Workflow
- 手动触发 Cron 节点
- 验证:
- 查询返回未向量化项目
- 文本内容正确构造
- OpenAI API 成功调用
- 数据库成功更新
Step 11: 激活工作流
- 点击 Active 开关
- 验证 Cron 调度正常运行
Step 12: 验证向量化结果
-- 检查已向量化项目数
SELECT COUNT(*) FROM "Project" WHERE "embedding" IS NOT NULL;
-- 查看某个项目的向量
SELECT id, name, "embeddingUpdatedAt"
FROM "Project"
WHERE "embedding" IS NOT NULL
LIMIT 5;
Task 4: 创建 AI 搜索工作流
Step 1: 创建新工作流
在 n8n 中:
- 点击 New Workflow
- 命名为:
AI Semantic Search
Step 2: 添加 Webhook 触发器
- 添加节点:Webhook
- 配置:
- HTTP Method:
POST - Path:
ai-search - Response Mode: When Last Node Finishes
- HTTP Method:
- 记录 Webhook URL(例如
https://your-n8n.com/webhook/ai-search) - 测试 Webhook(curl):
curl -X POST https://your-n8n.com/webhook/ai-search \
-H "Content-Type: application/json" \
-d '{"query":"test","locale":"zh","limit":5}'
- 保存节点
Step 3: 添加 OpenAI Embeddings 节点(生成查询向量)
- 添加节点:OpenAI → Embeddings
- 使用
OpenAI Embeddings凭证 - 配置:
- Model:
text-embedding-3-small - Input:
{{ $json.query }}
- Model:
- 测试节点
- 保存节点
Step 4: 添加 PostgreSQL 节点(向量相似度搜索)
- 添加节点:Postgres
- 操作:Execute Query
- 输入查询:
SELECT
p.id,
p.name,
p."nameEn",
p.slug,
p.description,
p."descriptionEn",
p.status,
p."createdAt",
1 - (p."embedding" <=> '{{ $json.data[0].embedding }}'::vector) as similarity
FROM "Project" p
WHERE p."embedding" IS NOT NULL
AND p.status = 'ACTIVE'
ORDER BY p."embedding" <=> '{{ $json.data[0].embedding }}'::vector
LIMIT {{ $json.limit || 20 }}
- 测试节点(应该返回相似度排序的项目)
- 保存节点
Step 5: 添加 Function 节点(查询项目标签)
- 添加节点:Function → JavaScript
- 输入代码:
const results = $input.all();
const projectIds = results.map(r => r.json.id).join(',');
// 为每个项目查询标签
return results.map(item => {
return {
json: {
...item.json,
projectId: item.json.id
}
};
});
- 保存节点
Step 6: 添加 PostgreSQL 节点(查询标签)
- 添加节点:Postgres
- 操作:Execute Query
- 输入查询:
SELECT
t.id,
t.name,
t."nameEn",
t.slug,
pt."projectId"
FROM "Tag" t
INNER JOIN "ProjectTag" pt ON t.id = pt."tagId"
WHERE pt."projectId" IN (SELECT UNNEST(STRING_TO_ARRAY('{{ $json.projectIds }}', ','))::INTEGER)
- 保存节点
Step 7: 添加 Function 节点(合并标签)
- 添加节点:Function → JavaScript
- 输入代码:
const projects = $('Postgres').all();
const tags = $('Postgres1').all();
// 合并标签到项目
const results = projects.map(project => {
const projectTags = tags
.filter(t => t.json.projectId === project.json.id)
.map(t => ({
id: t.json.id,
name: t.json.name,
nameEn: t.json.nameEn,
slug: t.json.slug
}));
return {
json: {
project: {
...project.json,
tags: projectTags
},
similarity: project.json.similarity,
matchReason: `相似度: ${(project.json.similarity * 100).toFixed(0)}%`
}
};
});
return results;
- 测试节点
- 保存节点
Step 8: 添加 Function 节点(格式化响应)
- 添加节点:Function → JavaScript
- 输入代码:
const results = $input.all();
const searchTime = $now.toMillis() - $('Webhook').item.json.startTime;
return {
json: {
results: results.map(r => r.json),
total: results.length,
searchTime: searchTime
}
};
- 保存节点
Step 9: 连接节点
Webhook → OpenAI Embeddings → Postgres (向量搜索) → Function (查询标签) → Postgres (标签) → Function (合并) → Function (格式化) → Response
Step 10: 测试完整工作流
- 点击 Test Workflow
- 在 Webhook 节点中点击 Listen for Test Event
- 发送测试请求:
curl -X POST https://your-n8n.com/webhook/ai-search \
-H "Content-Type: application/json" \
-d '{"query":"视频生成工具","locale":"zh","limit":5}'
- 验证响应格式:
{
"results": [
{
"project": { /* 项目数据 */ },
"similarity": 0.89,
"matchReason": "相似度: 89%"
}
],
"total": 5,
"searchTime": 1234
}
Step 11: 激活工作流
- 点击 Active 开关
- 保存生产环境的 Webhook URL
Step 12: 配置环境变量
在 .env.local 中添加:
N8N_AI_SEARCH_WEBHOOK=https://your-n8n.com/webhook/ai-search
Phase 3: Next.js API 实现
Task 5: 创建 AI 搜索 API 路由
Files:
- Create:
src/app/api/search/ai/route.ts
Step 1: 创建 API 路由文件
创建 src/app/api/search/ai/route.ts:
import { NextResponse } from 'next/server'
import { ProjectQuerySchema } from '@/lib/validations'
const N8N_WEBHOOK_URL = process.env.N8N_AI_SEARCH_WEBHOOK
if (!N8N_WEBHOOK_URL) {
throw new Error('N8N_AI_SEARCH_WEBHOOK environment variable is not set')
}
export async function POST(request: Request) {
try {
const body = await request.json()
// 验证查询参数
const validatedQuery = ProjectQuerySchema.parse(body)
// 转发到 n8n 工作流
const n8nResponse = await fetch(N8N_AI_SEARCH_WEBHOOK, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: validatedQuery.search,
locale: body.locale || 'zh',
limit: validatedQuery.limit,
filters: {
tags: validatedQuery.tags,
status: validatedQuery.status
}
})
})
if (!n8nResponse.ok) {
throw new Error(`n8n webhook failed: ${n8nResponse.statusText}`)
}
const results = await n8nResponse.json()
return NextResponse.json(results)
} catch (error) {
console.error('AI search error:', error)
if (error instanceof Error && error.name === 'ZodError') {
return NextResponse.json(
{ error: 'Invalid query parameters', details: error },
{ status: 400 }
)
}
return NextResponse.json(
{ error: 'AI search failed', message: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
)
}
}
Step 2: 测试 API 路由
启动开发服务器:
pnpm dev
测试 API:
curl -X POST http://localhost:3000/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"视频生成工具","limit":5}'
预期响应:
{
"results": [...],
"total": 5,
"searchTime": 1234
}
Step 3: 提交
git add src/app/api/search/ai/route.ts
git commit -m "feat: 添加 AI 搜索 API 路由"
Phase 4: 前端组件实现
Task 6: 修改 SearchBar 组件
Files:
- Modify:
src/components/search/SearchBar.tsx
Step 1: 读取现有组件
# 查看现有组件结构
cat src/components/search/SearchBar.tsx
Step 2: 添加 AI 模式状态
在组件中添加:
'use client'
import { useState } from 'react'
import { Sparkles, Search } from 'lucide-react'
// ... 保留现有 imports
export function SearchBar() {
// ... 保留现有状态
const [aiMode, setAiMode] = useState(false)
const [loading, setLoading] = useState(false)
// ... 保留现有逻辑
}
Step 3: 修改搜索处理函数
更新 handleSearch 函数:
const handleSearch = async () => {
if (!query.trim()) return
setLoading(true)
try {
const endpoint = aiMode ? '/api/search/ai' : '/api/projects'
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
search: query,
locale: 'zh',
limit: 20
})
})
if (!response.ok) {
throw new Error('Search failed')
}
const data = await response.json()
// 处理结果...
// if (aiMode) {
// setAIResults(data.results)
// } else {
// setProjects(data.results)
// }
} catch (error) {
console.error('Search error:', error)
// 显示错误提示
} finally {
setLoading(false)
}
}
Step 4: 添加 AI 切换按钮
在搜索输入框旁边添加:
<div className="flex gap-2">
{/* 搜索输入框 */}
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
placeholder={
aiMode
? "描述你想要的项目..."
: "搜索项目名称..."
}
className="flex-1 px-4 py-2 border-2 border-gray-300"
/>
{/* AI 模式切换按钮 */}
<button
onClick={() => setAiMode(!aiMode)}
className={`
px-3 py-2 border-2 transition-all
${aiMode
? 'bg-yellow-400 border-yellow-500 text-black'
: 'bg-white border-gray-300 text-gray-600'
}
`}
title="AI 语义搜索"
>
<Sparkles className="w-5 h-5" />
</button>
{/* 搜索按钮 */}
<button
onClick={handleSearch}
disabled={loading}
className="px-6 py-2 bg-blue-600 text-white"
>
{loading ? '搜索中...' : <Search className="w-5 h-5" />}
</button>
</div>
{/* AI 模式提示 */}
{aiMode && (
<div className="mt-2 text-sm text-gray-600">
💡 试试:"帮我找能生成视频的 AI 工具"
</div>
)}
Step 5: 测试组件
- 访问
http://localhost:3000/zh/projects - 点击 AI 切换按钮(应该变金色)
- 输入查询并搜索
- 验证加载状态显示
Step 6: 提交
git add src/components/search/SearchBar.tsx
git commit -m "feat: 添加 AI 搜索模式切换按钮"
Task 7: 创建 AI 搜索结果组件
Files:
- Create:
src/components/search/AISearchResults.tsx
Step 1: 创建组件文件
创建 src/components/search/AISearchResults.tsx:
'use client'
import { ProjectCard } from '@/components/project/ProjectCard'
import type { Project } from '@/hooks/useProjects'
interface AISearchResult {
project: Project
similarity: number
matchReason?: string
}
interface AISearchResultsProps {
results: AISearchResult[]
}
export function AISearchResults({ results }: AISearchResultsProps) {
if (results.length === 0) {
return (
<div className="text-center py-12 text-gray-600">
未找到相关项目,试试其他描述吧
</div>
)
}
return (
<div className="space-y-6">
{/* 相似度说明 */}
<div className="flex items-center gap-2 text-sm text-gray-600">
<span>匹配度:</span>
<div className="flex items-center gap-1">
<span className="text-green-600 font-semibold">高</span>
<span>→</span>
<span className="text-red-600 font-semibold">低</span>
</div>
</div>
{/* 结果列表 */}
{results.map(({ project, similarity, matchReason }) => (
<div key={project.id} className="relative">
{/* 相似度指示条 */}
<div
className="absolute left-0 top-0 bottom-0 w-1 rounded-l"
style={{
backgroundColor: getSimilarityColor(similarity)
}}
/>
{/* 项目卡片 */}
<div className="ml-3">
<ProjectCard project={project} />
{/* AI 匹配信息 */}
<div className="mt-3 px-4 py-3 bg-yellow-50 border-l-4 border-yellow-400 rounded-r">
<div className="flex justify-between items-center text-sm">
<span className="font-semibold text-gray-700">
匹配度: {(similarity * 100).toFixed(0)}%
</span>
{matchReason && (
<span className="text-gray-600">{matchReason}</span>
)}
</div>
</div>
</div>
</div>
))}
</div>
)
}
function getSimilarityColor(score: number): string {
if (score > 0.8) return '#22c55e' // green-500
if (score > 0.6) return '#eab308' // yellow-500
return '#ef4444' // red-500
}
Step 2: 在项目列表页面中使用
修改 src/app/[locale]/projects/page.tsx:
// 在页面中添加 AI 结果状态
const [aiResults, setAIResults] = useState<AISearchResult[]>([])
const [isAIResult, setIsAIResult] = useState(false)
// 在搜索处理中设置结果
if (aiMode) {
setAIResults(data.results)
setIsAIResult(true)
} else {
setProjects(data.results)
setIsAIResult(false)
}
// 在渲染中切换
{isAIResult ? (
<AISearchResults results={aiResults} />
) : (
<ProjectList projects={projects} />
)}
Step 3: 测试组件
- 访问项目列表页面
- 启用 AI 模式
- 搜索查询
- 验证:
- 相似度指示条显示正确颜色
- 匹配度百分比正确
- 项目卡片正常渲染
Step 4: 提交
git add src/components/search/AISearchResults.tsx
git add src/app/[locale]/projects/page.tsx
git commit -m "feat: 添加 AI 搜索结果展示组件"
Phase 5: 测试与验证
Task 8: 端到端测试
Step 1: 测试向量化流程
-- 检查向量化进度
SELECT
COUNT(*) FILTER (WHERE "embedding" IS NOT NULL) as vectorized,
COUNT(*) FILTER (WHERE "embedding" IS NULL) as not_vectorized,
COUNT(*) as total
FROM "Project";
预期:not_vectorized 应该逐渐减少(每 5 分钟更新一批)。
Step 2: 测试 AI 搜索
# 测试自然语言查询
curl -X POST http://localhost:3000/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"帮我找能生成视频的 AI 工具","limit":10}'
验证:
- 返回结果与"视频生成"相关
- 相似度分数合理(>0.6)
- 响应时间 < 3 秒
Step 3: 测试边界情况
# 空查询
curl -X POST http://localhost:3000/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"","limit":10}'
# 预期:400 错误
# 无结果查询
curl -X POST http://localhost:3000/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"xyzabc123不存在的项目","limit":10}'
# 预期:空 results 数组
Step 4: 测试降级逻辑
在前端测试:
- 停止 n8n 工作流
- 执行 AI 搜索
- 验证错误提示和降级到传统搜索
Task 9: 性能验证
Step 1: 测试搜索响应时间
# 使用 time 命令测量
time curl -X POST http://localhost:3000/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"视频生成","limit":20}'
目标:< 3 秒
Step 2: 测试并发搜索
# 使用 apachebench 或类似工具
ab -n 100 -c 10 -p search.json -T application/json \
http://localhost:3000/api/search/ai
目标:能处理 10 并发无错误
Step 3: 检查数据库查询性能
在 n8n PostgreSQL 节点中查看执行时间:
EXPLAIN ANALYZE
SELECT ... (向量搜索查询)
目标:< 500ms
Task 10: 文档更新
Files:
- Modify:
README.md(可选) - Modify:
CLAUDE.md
Step 1: 更新 CLAUDE.md
在 CLAUDE.md 中添加 AI 搜索部分:
## AI Search System
项目支持 AI 语义搜索功能,基于 pgvector 和 n8n 工作流实现。
### Architecture
- **Vector Database**: Neon PostgreSQL + pgvector extension
- **AI Services**: n8n workflows (vectorization + search)
- **Frontend**: Toggle button + similarity scores
### Environment Variables
```bash
# n8n Webhook
N8N_AI_SEARCH_WEBHOOK=https://your-n8n.com/webhook/ai-search
n8n Workflows
- Project Vectorization: Cron job (every 5 min) to generate embeddings
- AI Semantic Search: Webhook for natural language queries
Usage
用户在项目列表页面点击 AI 搜索按钮(✨ 图标),输入自然语言描述,系统返回语义相关的项目。
**Step 2: 提交**
```bash
git add CLAUDE.md
git commit -m "docs: 添加 AI 搜索系统文档"
Phase 6: 部署
Task 11: 生产环境部署
Step 1: 验证 n8n 工作流
- 确保 n8n 实例在生产环境运行
- 激活两个工作流
- 验证 Webhook URL 可访问
Step 2: 配置 Vercel 环境变量
在 Vercel Dashboard 中添加:
N8N_AI_SEARCH_WEBHOOK=https://your-production-n8n.com/webhook/ai-search
Step 3: 部署 Next.js 应用
# 推送到 main 分支触发部署
git push origin main
# 或手动部署
vercel --prod
Step 4: 验证生产环境
# 测试生产环境 API
curl -X POST https://your-domain.com/api/search/ai \
-H "Content-Type: application/json" \
-d '{"search":"视频生成","limit":5}'
Step 5: 监控 n8n 执行
在 n8n Dashboard 中:
- 查看工作流执行历史
- 检查错误日志
- 监控 API 使用量
Step 6: 设置告警(可选)
在 n8n 中配置错误告警:
- OpenAI API 失败
- 数据库连接错误
- Webhook 超时
总结
完成检查清单
- Phase 1: 数据库迁移完成
- Phase 2: n8n 工作流配置完成
- Phase 3: Next.js API 路由实现
- Phase 4: 前端组件实现
- Phase 5: 测试与验证通过
- Phase 6: 生产环境部署成功
关键指标
- 向量化完成率: > 95%
- 搜索响应时间: < 3 秒
- 相似度准确率: 用户满意 > 80%
- API 成本: < $5/月(假设 1000 次搜索/天)
后续优化方向
- 添加查询缓存(Redis)
- 实现混合搜索(向量 + 关键词)
- A/B 测试用户体验
- 多模态搜索(图片、语音)
- 个性化排序
计划创建日期: 2026-01-25 预计完成时间: 4-6 小时 难度等级: 中等