Зараз в мене все в докері на одному інстансі cax31 в хетзнері. Це 8 ядер arm, та 16гб ОЗП.
Запит до моделі локально:
# curl --location 'local.model.host:9010/get-embeddings' --header 'Content-Type: application/json' --data '{"texts": ["Сяомі редмі нот 14"]}' -s -o /dev/null -w "%{time_starttransfer}\n" 0.159880
Виконання SQL:
SELECT id, title, (embedding <-> '[-0.07437053322792053, ... ,0.02803190052509308]') AS "embeddingDistance" FROM public.product WHERE embedding IS NOT NULL ORDER BY "embeddingDistance" LIMIT 20 [2025-02-27 19:19:15] 20 rows retrieved starting from 1 in 746 ms (execution: 358 ms, fetching: 388 ms)
Не зовсім розумію, чому ви вважаєте, що щось посипалось, коли модель знайшла релевантні товари. Чи ви вважаєте. що в результатах немає чохлів?)) А якщо врахувати сам запит, то результати нормальні. Спробуйте той самий запит на розетці. Там одразу ж в топі видає ZTE blade a35. Також не зрозуміло, чому «посиплеться» модель при запитиі «скло без рамки», якщо відповідне буде вказано в назві товару? Тут як раз може посипатись повнотекстовий пошук через те, що ігнорує прийменники і «без» є в словнику стопслів.
Товарів на разі 53 тис. Якщо брати повний час запиту на пошук з фронтенду, то виходить 1,5-2c. Що не дуже швидко. Для порівняння, запит, який обробляється звичайним пошуком, коли в нас є точне співпадіння, типу «iphone 15», виконується за 100-200мс. Я пробував додавати індекс, але в моєму кейсі це значно погіршує релевантність пошуку. В документаціі так і написано
You can add an index to use approximate nearest neighbor search, which trades some recall for speed.
Так, як я писав на початку статті і Олександр нижче в коменті, звичайний пошук не знайде «Iphone» по запиту «Айфон», «чохол» по «чехол», «скло» по «стекло» та ще купа інших кейсів. А якщо врахувати можливі одруки та граматичні помилки, то тут варіанти написання пошукового запиту прямують до нескінченності. В мене реалізований звичайний повнотекстовий пошук в постгресі і він не вирішує цю проблему. А LLM вирішує і досить успішно. Для економії, я спочтаку роблю пошук звичаним способом і тільки якщо він не поверне нічого, то роблю семантичний пошук.
А взагалі в даному випадку проблема трохи надумана, як на мене. Можна обійтися однім об’єктом const languageSelectOptions: Record<Language, string>
і одразу розташувати ключи в потрібному порядку. Я розумію, що це все заради статті, але всеж таки)))
А для чого робити каст } as const satisfies Record<Language, string>;
Замість того, щоб просто вказати тип const languageDisplayNameMap: Record<Language, string> {
Вітаю. RAG вивчав для інших цілей в контексті іншого проєкту.