跳转至

向量问题排查与删除

概述

RAG Worker 的运行时和检索相关配置已集中到 tools/rag-worker/src/config/settings.ts(项目路径)中。

这个文件是“单一配置源”,包含:

  • 全量默认配置:DEFAULT_RAG_CONFIG
  • 检索与 rerank 配置:DEFAULT_RETRIEVAL_CONFIGDEFAULT_RERANK_CONFIG
  • 上下文配置:DEFAULT_CONTEXT_CONFIG
  • 预设(Presets):PRESET_FASTPRESET_ACCURATEPRESET_BALANCEDPRESET_CONVERSATIONAL(集合为 PRESETS
  • 合并/生成工具:mergeConfig()createConfig()getPreset()
  • 查询扩展模板、个人简介回退与个人查询关键词常量:QUERY_EXPANSION_TEMPLATESABOUT_FALLBACKSPERSONAL_QUERY_KEYWORDS
  • 向量 manifest 存储路径:STORAGE_PATHS.vectorManifest(默认 config/vector-manifest.json)。

为什么统一配置

集中式配置带来的优点:

  • 单一维护点,修改配置只需编辑 settings.ts
  • 通过 PRESETS 快速切换运行场景(性能、精度、对话优化等)。
  • 工具链(Makefile、脚本、Worker)会读取这些默认值并基于环境变量运行。

基本使用示例(在 Worker / 脚本中)

import { createRAGPipeline } from './rag/pipeline';
import { PRESETS, createConfig, DEFAULT_RAG_CONFIG } from '../config/settings';

// 使用默认配置
const pipeline = createRAGPipeline(env);

// 使用预设 (fast / balanced / accurate / conversational)
const fastPipeline = createRAGPipeline(env, PRESETS.fast as any);

// 基于预设覆盖部分配置
const customConfig = createConfig({ retrieval: { topK: 12 } }, 'balanced');
const pipelineCustom = createRAGPipeline(env, { retrieval: customConfig.retrieval, context: customConfig.context });

Rerank 配置说明

  • 默认 DEFAULT_RERANK_CONFIG 使用 provider: 'local'(内置算法),无需 Cohere 或 Jina API Key。
  • 如需更高精度,可将 rerank.provider 替换为 coherejina 并在环境中提供对应 API Key(COHERE_API_KEY / JINA_API_KEY)。

例如切换到 Cohere:

import { createConfig } from '../config/settings';

const cfg = createConfig({ retrieval: { rerank: { enabled: true, provider: 'cohere', model: 'rerank-multilingual-v3.0' } } });

并在运行环境中设置:

export COHERE_API_KEY=[REDACTED:api-key]

向量 manifest 与外部配置

  • 向量 manifest 路径在 STORAGE_PATHS.vectorManifest 中定义,默认是 config/vector-manifest.json
  • 外部配置存储(如 title-dictionary)同样在 settings.ts 的常量或 ExternalConfigOptions 中定义。

与站点工具集成

  • Makefile(make rag-uploadmake rag-deploymake rag-reindex 等)以及脚本(scripts/fast-ingest.ts)会读取或遵循 settings.ts 中的默认值与预设。
  • 在修改了 settings.ts 后,建议执行 make rag-upload-configmake rag-deploy(若配置影响部署)以确保一致性。

变更与扩展

  • 若需新增默认配置、预设或扩展 rerank provider,请在 settings.ts 中添加相应的类型,并在 RAG 的实现(如 MultiRouteRetrieverContextManager)中读取。
  • 所有新增配置项应配合 getPreset() / createConfig() 做默认值合并,以避免运行时断言错误。

实体说明

  • Markdown 文件:原始 Hugo 内容(frontmatter + 正文)
  • 文本分块:按标题与句子分割的片段
  • 向量嵌入:数值表示(依赖模型维度)
  • 元数据:附加于每个分块,用于过滤与归属
  • 查询结果:相似度匹配列表

详细数据格式

TypeScript 接口

向量元数据结构

export type MatchMeta = {
  text?: string;           // 分块实际文本内容
  source?: string;         // 相对 content 目录的文件路径
  title?: string;          // frontmatter 中的文档标题
  url?: string;            // 生成的网站 URL
  language?: string;       // 文档语言('zh' | 'en')
};

环境配置

export interface Env {
  VECTORIZE: VectorizeIndex;
  PROVIDER: 'gemini' | 'qwen';
  GOOGLE_API_KEY?: string;
  QWEN_API_KEY?: string;
  QWEN_BASE?: string;
  QWEN_EMBED_MODEL?: string;
  LLM_MODEL?: string;
  ADMIN_TOKEN: string;
  EMBED_DIM: string;
}

向量索引操作

export interface VectorizeIndex {
  upsert(items: {
    id: string;
    values: number[];
    metadata?: Record<string, any>
  }[]): Promise<void>;

  query(vector: number[], opts: {
    topK: number;
    returnValues?: boolean;
    includeMetadata?: boolean;
    returnMetadata?: string;
    filter?: { metadata: Record<string, any> };
  }): Promise<{
    matches: { id: string; score: number; metadata?: MatchMeta }[];
  }>;
}

JSON 数据示例

Upsert 请求体

{
  "items": [
    {
      "id": "a1b2c3d4e5f6-0",
      "vector": [0.123, -0.456, 0.789, ...],
      "text": "Kubernetes 是一个开源的容器编排平台...",
      "source": "zh/blog/kubernetes-intro/index.md",
      "title": "Kubernetes 入门指南",
      "url": "https://jimmysong.io/blog/kubernetes-intro/",
      "language": "zh"
    }
  ]
}

聊天请求/响应

// 请求
{
  "message": "什么是 Kubernetes?",
  "history": [
    {"type": "user", "content": "之前的问题"},
    {"type": "bot", "content": "之前的回答"}
  ],
  "language": "zh",
  "pageContext": {
    "title": "Kubernetes 入门指南",
    "url": "https://jimmysong.io/blog/kubernetes-intro/",
    "content": "Kubernetes 是一个开源容器编排平台..."
  }
}

// 响应
{
  "answer": "Kubernetes 是一个开源的容器编排平台...",
  "sources": [
    {
      "id": "a1b2c3d4e5f6-0",
      "url": "https://jimmysong.io/blog/kubernetes-intro/",
      "title": "Kubernetes 入门指南",
      "source": "zh/blog/kubernetes-intro/index.md"
    }
  ]
}

代码流程:端到端管道

摄取管道(scripts/fast-ingest.ts

  1. 文件发现globby() 扫描 content 目录下 .md 文件
  2. 并行处理:同时处理 MAX_CONCURRENT_FILES 个文件
  3. 内容提取matter.js 解析 frontmatter,markdownToPlain() 转为纯文本
  4. 中文分块chunkText() 按标题与句子边界分割
  5. 批量嵌入getBatchEmbeddings() 高效批量处理分块
  6. 元数据生成toUrlFromPath() 生成 URL,generateShortId() 生成唯一 ID
  7. 向量上传:每批 300 条 upsert 到 Cloudflare Vectorize

嵌入生成(src/providers/embeddings.ts

// 通义千问嵌入(批量处理)
{
  model: "text-embedding-v4",
  input: ["text1", "text2", ...] // 每次最多 10 条
}

// Gemini 嵌入(单条处理)
{
  model: "models/text-embedding-004",
  content: { parts: [{ text: "单条文本" }] },
  outputDimensionality: 1024
}

向量存储与上传(src/worker.ts

  • 鉴权:管理操作需 Bearer ${ADMIN_TOKEN}
  • 数据校验:向量维度校验(EMBED_DIM
  • 批量操作:每次最多 300 条向量
  • 元数据保存:完整元数据与向量一同存储

查询处理(src/rag/retriever.ts

  1. 查询嵌入:用户问题 → 嵌入向量
  2. 直接检索:全量向量查询,无语言过滤
  3. 元数据处理:提取文本上下文和来源信息
  4. URL 转换:根据语言偏好转换 URL(如需)
  5. 来源去重:按 URL 去除重复来源

答案生成(src/providers/llm.ts

// 通义千问聊天生成
{
  model: "qwen-turbo-latest",
  messages: [
    { role: "system", content: "请用中文回答,并在末尾列出来源路径。" },
    { role: "user", content: "构建的提示词包含上下文和问题" }
  ]
}

// Gemini 内容生成
{
  contents: [
    { parts: [{ text: "完整的提示词" }] }
  ]
}

5. 模型角色与能力

text-embedding-v4(通义千问嵌入模型)

  • 主要功能:文本转 1024 维向量
  • 批量处理:每次最多 10 条(高效)
  • 语言支持:优化中英文
  • 应用场景
  • 摄取时文档分块
  • 检索时查询向量化
  • API 地址https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings

qwen-turbo-latest(通义千问聊天模型)

  • 主要功能:根据检索文档生成上下文答案
  • 输入处理:系统提示 + 用户问题 + 检索上下文
  • 输出生成:结构化中文回复,附来源
  • 能力
  • 多轮对话
  • 上下文感知
  • 来源归属
  • 语言专属回复
  • API 地址https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

备选:Gemini 模型

  • 嵌入text-embedding-004(768/1024 维)
  • 生成gemini-2.5-flash-lite
  • 限制:嵌入不支持批量
  • 应用:Qwen 不可用地区的备选方案

端到端示例会话

完整摄取示例

# 环境变量设置
PROVIDER=qwen
QWEN_API_KEY=sk-xxx
ADMIN_TOKEN=your-admin-token
WORKER_URL=https://your-worker.workers.dev
CONTENT_DIR=../website/content
EMBED_DIM=1024

# 摄取流程
npm run ingest

处理流程

  1. 发现:../website/content/zh/blog/kubernetes/index.md
  2. 提取:title: "Kubernetes 容器编排",内容:Kubernetes是...
  3. 分块:约 800 字分 3 块
  4. 嵌入:批量请求 → 3 个 1024 维向量
  5. 上传:{"id": "a1b2c3d4e5f6-0", "vector": [...], "metadata": {...}}

完整查询示例

// 用户查询
const query = "Kubernetes 是什么?";

// 1. 查询嵌入
const queryVector = await embedder.embed([query]); // [0.123, -0.456, ...]

// 2. 向量检索
const results = await VECTORIZE.query(queryVector, {
  topK: 8,
  filter: { metadata: { language: 'zh' } }
});

// 3. 上下文组装
const contexts = results.matches
  .map(m => m.metadata.text)
  .join('\n---\n');

// 4. Prompt 构建
const prompt = `
基于以下上下文回答用户问题:
${contexts}

用户问题:${query}
请用中文回答,并在末尾列出参考来源。
`;

// 5. LLM 生成
const answer = await llmGenerate(env, prompt);

// 6. 响应组装
return {
  answer: "Kubernetes 是一个开源的容器编排平台...",
  sources: [
    {
      url: "https://jimmysong.io/blog/kubernetes-intro/",
      title: "Kubernetes 入门指南"
    }
  ]
};

小部件集成示例

<!-- 网站集成 -->
<script
  src="/path/to/widget.js"
  data-endpoint="https://your-worker.workers.dev"
  defer
></script>
<div id="ai-chatbot"></div>

用户交互流程

  1. 用户打开聊天窗口
  2. 输入:"什么是微服务架构?"
  3. 小部件 POST 到 /chat 接口
  4. RAG 管道处理查询
  5. 返回结构化答案与来源链接
  6. 小部件展示答案并支持复制

性能特性

  • 摄取速度:约 1000 文档/分钟(Qwen 批量处理)
  • 查询延迟:端到端约 3-5 秒(简化后速度提升)
  • 向量存储:每 1 万文档约 50MB
  • 并发用户:Cloudflare Workers 边缘网络可扩展
  • 语言支持:中英文自动检测与切换(无过滤延迟)

可用文档

核心功能

  • 目录递归处理 - 批量目录处理功能详解
  • 🎯 递归文件发现与处理
  • 🛡️ 智能草稿过滤机制
  • 📊 进度跟踪与性能监控
  • 🔧 最佳实践与故障排查

技术深度

高级主题

详细文档下一步

  1. 搭建与部署指南 - 步骤化安装说明
  2. API 参考 - 完整接口文档
  3. 配置指南 - 环境变量与自定义
  4. 故障排查 - 常见问题与解决方案
  5. 性能优化 - 大规模部署调优
  6. 集成示例 - 更多前端集成模式

向量 ID 查询与删除

在 RAG 管道维护和调试过程中,可能需要定位、查询或删除特定的向量记录。以下为常用操作方法:

查询最新向量 ID

可通过内置脚本快速获取最近上传的向量 ID 列表,便于后续定位和管理。

# 查询最新向量 ID
npm run fetch-vector-ids
  • 默认输出最近批次的向量 ID 列表(通常为 100 条)。
  • 可根据脚本参数调整数量或过滤条件,详见 scripts/fetch-latest-vector-ids.ts

根据 URL 查询向量 ID

如需根据内容 URL 查询对应的向量 ID,可使用:

npm run search-url -- --url="https://jimmysong.io/blog/kubernetes-intro/"
  • 支持通过 URL 精确定位相关向量。
  • 输出包含匹配的向量 ID 及其元数据信息。

删除指定向量 ID

如需删除某些已知 ID 的向量,可使用以下命令:

# 删除单个或多个向量 ID
npm run delete-vector-ids -- --ids="a1b2c3d4e5f6-0,a1b2c3d4e5f6-1"
  • 支持逗号分隔批量删除。
  • 删除操作不可逆,请谨慎操作。
  • 具体逻辑见 scripts/delete-vectors-by-id.ts

常见场景举例

  • 内容误上传:先通过查询脚本定位 ID,再用删除脚本移除。
  • 数据清理:批量导出 ID 后,分批删除无效或过期向量。