Архитектура (руководство для разработчиков)
Глубокое погружение в RAG-пайплайн для разработчиков, которые хотят понять, как это работает.
Обзор RAG Pipeline
LaunchChat использует Retrieval Augmented Generation (RAG) для ответов на вопросы на основе вашей документации.
1. Загрузка
Парсинг → Разбивка → Эмбеддинг → Хранение
2. Извлечение
Запрос → Векторный поиск → Ранжирование
3. Генерация
Контекст → LLM → Ответ + Цитаты
Пайплайн загрузки
1. Парсинг
Контент парсится из различных источников в простой текст:
- Notion: поблочный парсинг с сохранением иерархии
- DOCX: извлечение через mammoth.js
- 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. Хранение
Векторы хранятся в PostgreSQL с расширением pgvector:
-- content_chunks table
id: uuid
knowledge_base_id: uuid
page_id: string
page_title: string
content: text
embedding: vector(1536)
parent_heading: stringСтратегия извлечения
Гибридный поиск
Мы используем двухэтапный процесс извлечения:
- Vector Search: Векторный поиск: косинусное сходство с использованием оператора <=> pgvector
- 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])Лучшие практики документации
Структурируйте документацию для оптимального извлечения ИИ:
Рекомендуется
- Используйте чёткие, описательные заголовки
- Сохраняйте фокус разделов на одной теме
- Включайте примеры и фрагменты кода
- Определяйте термины и аббревиатуры
- Обновляйте документацию при изменении функций
Избегайте
- Очень длинных страниц без структуры
- Дублирования контента на разных страницах
- Устаревшей или противоречивой информации
- Чрезмерного использования изображений без alt-текста
- Страниц, содержащих только навигацию
Шаблон промпта для ИИ
Скопируйте этот промпт в 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.