Агент-инженер по репозиторию · Модуль 3 · Урок 3.2
Чанкинг по функциям и файлам
Зачем (какую проблему чиним)
Чтобы извлекать «куски», нужно сперва разрезать репозиторий на осмысленные единицы. Наивный чанкинг «по N символов» рвёт функции посередине и смешивает несвязный код. Для кода естественная единица — функция/метод/тип, с запасом — файл.
Решение и альтернативы
Решение: чанкер для Go использует go/parser (AST): каждая функция, метод и объявление типа — отдельный чанк с метаданными (файл, имя, диапазон строк). Для не-Go файлов и докладов (.md) — чанкинг по заголовкам/абзацам с перекрытием. Чанк хранит достаточно контекста (имя файла, сигнатуру), чтобы быть понятным в отрыве.
Альтернативы: фиксированный размер в символах/токенах — прост, но рвёт смысловые границы; по строкам с перекрытием — лучше, но всё равно слепой к структуре. AST-чанкинг для кода точнее всего; символьный оставляем как фолбэк для незнакомых форматов.
DIFF
Добавляем пакет чанкинга: AST для .go, эвристики для текста; на выходе — []Chunk с метаданными.
Проверка
На самом репозитории агента чанкер выдаёт по чанку на функцию с корректными строками; safeJoin гарантирует, что индексируется только дерево репозитория (без .git/секретов).
Глубже
Стратегии чанкинга и их влияние на качество поиска — курс «Продакшн-разработка», Модуль 2 (продвинутый RAG, гл. 3).
+package main
+
+import (
+ "go/ast"
+ "go/parser"
+ "go/token"
+)
+
+// Chunk — индексируемая единица с метаданными для источника и ранжирования.
+type Chunk struct {
+ Path string // путь относительно корня
+ Symbol string // имя функции/типа (если применимо)
+ StartLine int
+ EndLine int
+ Text string
+}
+
+// chunkGoFile режет один .go-файл на чанки уровня объявлений (func/type).
+func chunkGoFile(path, src string) ([]Chunk, error) {
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, path, src, 0)
+ if err != nil {
+ return symbolicFallback(path, src), nil // битый файл — символьный фолбэк
+ }
+ var chunks []Chunk
+ for _, decl := range f.Decls {
+ start := fset.Position(decl.Pos())
+ end := fset.Position(decl.End())
+ chunks = append(chunks, Chunk{
+ Path: path,
+ Symbol: declName(decl),
+ StartLine: start.Line,
+ EndLine: end.Line,
+ Text: sliceLines(src, start.Line, end.Line),
+ })
+ }
+ return chunks, nil
+}Anti-patterns
| Грабля | Почему плохо | Как правильно |
|---|---|---|
| Резать код по фиксированному числу символов | Функции рвутся посередине; чанк смешивает несвязные куски — поиск деградирует | Чанк = функция/метод/тип (AST); символьный фолбэк только для незнакомых форматов |
| Чанк без метаданных (только текст) | Нельзя показать источник и ранжировать по файлу/символу | Хранить путь, символ, диапазон строк — для источника и буста релевантности |
Практическое задание (RA-v2)
- Реализовать AST-чанкинг для .go (
go/parser) и текстовый чанкинг для .md с перекрытием. - Добавить символьный фолбэк для файлов, которые не парсятся.
- Закоммитить:
git commit -m "v2: AST-based chunking".
Проверка знаний
Почему для кода чанкинг по функциям (AST) обычно лучше, чем по фиксированному числу символов?
Верный ответ: B
B. Поиск и понимание работают лучше на цельных смысловых единицах. Символьная нарезка разрывает функции и склеивает несвязное, ухудшая и retrieval, и качество ответа. Символьный чанкинг оставляют как фолбэк.