架构(Vibe Coder 指南)

深入了解 RAG 管道,适合想要理解其工作原理的开发者。

RAG 管道概览

LaunchChat 使用检索增强生成(RAG)技术,基于您的文档回答问题。

1. 数据摄入

解析 → 分块 → 向量化 → 存储

2. 检索

查询 → 向量搜索 → 排序

3. 生成

上下文 → LLM → 回答 + 引用

数据摄入管道

1. 解析

从各种来源将内容解析为纯文本:

  • Notion: Notion:逐块解析,保留层级结构
  • DOCX: DOCX:通过 mammoth.js 提取
  • Markdown: Markdown:使用 remark/unified 解析
  • Website: 网站:抓取并清除导航栏/页脚

2. 分块

文本被分割为重叠的分块以优化检索:

{
  targetSize: 400,    // tokens per chunk
  overlap: 50,        // token overlap between chunks
  preserveHeadings: true,  // keep heading context
  minChunkSize: 100   // minimum viable chunk
}

每个分块都保留其父级标题层级作为上下文。

3. 向量化

分块被转换为1536维向量:

Model: text-embedding-3-small
Dimensions: 1536
Provider: OpenAI (via OpenRouter)

4. 存储

向量存储在带有 pgvector 扩展的 PostgreSQL 中:

-- content_chunks table
id: uuid
knowledge_base_id: uuid
page_id: string
page_title: string
content: text
embedding: vector(1536)
parent_heading: string

检索策略

混合搜索

我们使用两阶段检索流程:

  1. Vector Search: 向量搜索:使用 pgvector 的 <=> 运算符计算余弦相似度
  2. Keyword Fallback: 关键词回退:如果向量结果相似度较低,我们会补充关键词匹配的分块

相似度评分

-- Vector similarity query
SELECT *, 1 - (embedding <=> query_embedding) as similarity
FROM content_chunks
WHERE knowledge_base_id = $1
ORDER BY embedding <=> query_embedding
LIMIT 5

回答生成

置信度评分

在生成回答之前,我们会计算置信度分数:

confidence = bestSimilarity + (hasMultipleChunks ? 0.1 : 0) + 0.2
// Capped at 1.0

if (confidence < threshold) {
  return refusalMessage;  // Don't hallucinate
}

引用提取

LLM 被指示使用 [Source N] 格式。我们解析这些引用并链接到原始页面:

// Extract citations from answer
const citationPattern = /\[Source (\d+)\]/g;
const matches = answer.matchAll(citationPattern);

// Map to original pages
citations = matches.map(m => chunks[m[1] - 1])

文档编写最佳实践

合理组织文档结构以优化AI检索效果:

推荐

  • 使用清晰、描述性的标题
  • 每个章节聚焦一个主题
  • 包含示例和代码片段
  • 定义术语和缩写
  • 功能变更时及时更新文档

避免

  • 没有结构的超长页面
  • 跨页面的重复内容
  • 过时或矛盾的信息
  • 大量使用没有替代文本的图片
  • 仅包含导航的页面

AI 提示词模板

将此提示词复制到 Cursor、Windsurf 或 Claude Code 中,帮助集成 LaunchChat:

I'm integrating LaunchChat, an AI-powered support widget.

Widget Setup:
1. Add to HTML: <script>window.LaunchChatConfig = {widgetId: "ID"}</script>
   <script src="https://domain.com/widget.js" async></script>

2. For React/Next.js, create a client component that:
   - Sets window.LaunchChatConfig
   - Dynamically loads widget.js
   - Cleans up on unmount

API Reference:
- window.LaunchChatWidget.open() - Open chat
- window.LaunchChatWidget.close() - Close chat
- window.LaunchChatWidget.on(event, callback) - Listen to events
- Events: 'open', 'close', 'message', 'escalate', 'feedback'

Help me integrate this into my [FRAMEWORK] app.