Альтернатива A: Сохранить текущий полнотекстовый поиск PostgreSQL
Поток работы
raw chunkText
-> plainto_tsquery
-> search_tsv @@ query
-> ts_rank_cd
-> top JSONL возвратПреимущества
- Уже реализовано.
- Доступно только с PostgreSQL.
- Инфраструктура проста.
search_tsvсразу подходит к таблице, которая уже его имеет.
Недостатки
- Не BM25.
- Слаб в длинных фрагментах кода.
- Условие, созданное
plainto_tsquery, может стать чрезмерно узким. - Слишком много шума от токенов кода.
- Не выполняет семантический поиск.
- При небольшом изменении разбиения фрагмента может не вернуть ни одного результата.
Ожидаемые проблемы в базовом фрагменте
В базовом фрагменте одновременно присутствуют следующие токены.
func
process
delta
velocity
vector2
zero
input
is_action_pressed
move_right
move_left
normalized
animatedsprite2d
play
stop
position
clamp
screen_sizeЕсли все эти токены не находятся одновременно в одной строке JSONL, результаты поиска могут быть упущены.
Симуляция PoC
Предположим, что базовый чанк попадает в /api/retrieve без изменений.
(No content to translate)
chunkText = полный текст функции _process(delta)Текущий метод преобразует этот ввод в plainto_tsquery('simple', chunkText).
Ожидаемый характер запроса:
func & process & delta & var & velocity & vector2 & zero
& input & is_action_pressed & move_right & move_left
& length & normalized & speed & animatedsprite2d
& play & stop & position & clamp & screen_sizeВ этом случае, если фактический связанный документ разделён на два куска, как показано ниже, возникает проблема.
docs chunk A:
Input.is_action_pressed("move_right")
Input.is_action_pressed("move_left")
velocity.normalized() * speed
$AnimatedSprite2D.play()
$AnimatedSprite2D.stop()
docs chunk B:
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)Если человек смотрит, A и B оба связаны.
Однако если full-text query требует одновременно слишком много токенов, это может привести к следующему.
docs chunk A:
animatedsprite2d = есть
is_action_pressed = есть
move_left/move_right = есть
clamp = нет
screen_size = нет
position.clamp = нет
=> запрос не полностью удовлетворён
docs chunk B:
clamp = есть
screen_size = есть
position = есть
animatedsprite2d = отсутствует или слабый
move_left/move_right = нет
is_action_pressed = нет
=> запрос не полностью удовлетворёнВидимые формы неудач:
Результатов поиска 0
или возвращает только очень узкий chunkВ этом подходе трудно различить, является ли ошибка поиска «неудачей из‑за отсутствия доказательств в документе» или «неудачей из‑за слишком строгих условий запроса».
Логи, проверяемые в PoC
При тестировании этой альтернативы нельзя смотреть только на результат.
Необходимо также показывать следующие значения.
1. необработанный chunkText
2. запрос, созданный с помощью plainto_tsquery
3. список токенов, входящих в запрос
4. количество возвращаемых строк
5. если 0 записей, какой токен сделал запрос слишком узкимОжидаемое наблюдение:
Чем длиннее raw chunk, тем длиннее запрос, а если связанные документы разбиты на несколько chunk, результат будет неполным.Оценка
Можно использовать в качестве базовой линии PoC.
В качестве окончательной стратегии поиска — кандидат на удалениеОценка оригинальной заметки ближе к «нужно всё переделать».