Back-end Engineer в EVOPLAY
  • Створюємо «пошуковий рушій» для інтернет-магазину за допомогою Embeddings

    Вітаю. RAG вивчав для інших цілей в контексті іншого проєкту.

  • Створюємо «пошуковий рушій» для інтернет-магазину за допомогою Embeddings

    Зараз в мене все в докері на одному інстансі 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)
    
  • Створюємо «пошуковий рушій» для інтернет-магазину за допомогою Embeddings

    Не зовсім розумію, чому ви вважаєте, що щось посипалось, коли модель знайшла релевантні товари. Чи ви вважаєте. що в результатах немає чохлів?)) А якщо врахувати сам запит, то результати нормальні. Спробуйте той самий запит на розетці. Там одразу ж в топі видає ZTE blade a35. Також не зрозуміло, чому «посиплеться» модель при запитиі «скло без рамки», якщо відповідне буде вказано в назві товару? Тут як раз може посипатись повнотекстовий пошук через те, що ігнорує прийменники і «без» є в словнику стопслів.

  • Створюємо «пошуковий рушій» для інтернет-магазину за допомогою Embeddings

    Товарів на разі 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.
    Підтримав: Olexander
  • Створюємо «пошуковий рушій» для інтернет-магазину за допомогою Embeddings

    Так, як я писав на початку статті і Олександр нижче в коменті, звичайний пошук не знайде «Iphone» по запиту «Айфон», «чохол» по «чехол», «скло» по «стекло» та ще купа інших кейсів. А якщо врахувати можливі одруки та граматичні помилки, то тут варіанти написання пошукового запиту прямують до нескінченності. В мене реалізований звичайний повнотекстовий пошук в постгресі і він не вирішує цю проблему. А LLM вирішує і досить успішно. Для економії, я спочтаку роблю пошук звичаним способом і тільки якщо він не поверне нічого, то роблю семантичний пошук.

    Підтримав: Dmytro S
  • Вичерпні масиви в Typescript та їхня роль для розробників

    А взагалі в даному випадку проблема трохи надумана, як на мене. Можна обійтися однім об’єктом const languageSelectOptions: Record<Language, string> і одразу розташувати ключи в потрібному порядку. Я розумію, що це все заради статті, але всеж таки)))

  • Вичерпні масиви в Typescript та їхня роль для розробників

    А для чого робити каст } as const satisfies Record<Language, string>;
    Замість того, щоб просто вказати тип const languageDisplayNameMap: Record<Language, string> {