Skip to content

PPicker/Vibe_Search

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

10 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Vibe Searching

https://prototype.p-picker.com/

์ด ์„œ๋น„์Šค๋Š” ํ…์ŠคํŠธ ์ž…๋ ฅ์„ ํ†ตํ•ด ์›ํ•˜๋Š” ์Šคํƒ€์ผ์˜ ์˜ท์„ ์ œ์•ˆํ•˜๋Š” Vibe Searching Prototype์ž…๋‹ˆ๋‹ค.
Fastapi + React + Postrgresql ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์œผ๋ฉฐ, ์œ ์ € ๋กœ๊ทธ์ธ ๋“ฑ์˜ ์ธํ„ฐ๋ž™์…˜ ์—†์ด ๊ธฐ๋Šฅ์€ ์ œ์™ธํ•œ ํ”„๋กœํ† ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” top - 3 related items๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

System Architecture Overview

๊ตฌ์กฐ๋„

๋ฐ๋ชจ ํ™”๋ฉด ๋ฐ ์„ค๋ช…

1. ๋ฉ”์ธ ํ™”๋ฉด

ํ…์ŠคํŠธ ์ž…๋ ฅ์ฐฝ์— ์›ํ•˜๋Š” ์Šคํƒ€์ผ์„ ๊ฐ„๋‹จํžˆ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ํ™”๋ฉด

2. ์ถ”์ฒœ ๊ฒฐ๊ณผ (์˜ˆ์‹œ)

์ž…๋ ฅ: "์ŠคํŠธ๋ผ์ดํ”„ ํŒจํ„ด์˜ ๋ฏธ๋‹ˆ๋ฉ€ํ•œ ๋ฌด๋“œ์˜ ์…”์ธ "

์˜ˆ์‹œ 1

์œ„์™€ ๊ฐ™์ด Top-3 ๊ด€๋ จ ์ƒํ’ˆ์ด ์นด๋“œ ํ˜•ํƒœ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

3. ์ƒํ’ˆ ๋””ํ…Œ์ผ ํŽ˜์ด์ง€

ํด๋ฆญ ์‹œ ์ƒ์„ธ ์ •๋ณด(์ด๋ฏธ์ง€, ๊ฐ€๊ฒฉ, ์„ค๋ช…, ๊ตฌ๋งค ๋งํฌ ๋“ฑ)๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋””ํ…Œ์ผ

๐Ÿ” ํŒจ์…˜ ์ƒํ’ˆ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰ ์‹œ์Šคํ…œ

๐Ÿ“‹ ๊ฐœ์š”

์ž์—ฐ์–ด ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ๋ง๊ณผ ๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ๊ฒ€์ƒ‰์„ ๊ฒฐํ•ฉํ•œ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.

๐Ÿ—๏ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

image.png

๐Ÿš€ ๊ฒ€์ƒ‰ ํ”Œ๋กœ์šฐ

1. ์ฟผ๋ฆฌ ์ž…๋ ฅ ๋‹จ๊ณ„

์ž…๋ ฅ: "๋„์ฟ„ ๋นˆํ‹ฐ์ง€ ์›Œํฌ์›จ์–ด ์ž์ผ“"

2. ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„ (๋น„๋™๊ธฐ)

# ๋‘ ํ•จ์ˆ˜๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜์—ฌ ์‘๋‹ต์‹œ๊ฐ„ ๋‹จ์ถ•
query_json, category = await asyncio.gather(
    parse_fashion_query(q),    # ๊ตฌ์กฐํ™”๋œ JSON ์ƒ์„ฑ
    query_categorizer(q)       # ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜
)

2-1. ํŒจ์…˜ ์ฟผ๋ฆฌ ํŒŒ์‹ฑ (parse_fashion_query)

์ž…๋ ฅ: "๋„์ฟ„ ๋นˆํ‹ฐ์ง€ ์›Œํฌ์›จ์–ด ์ž์ผ“"

์ถœ๋ ฅ:

{
  "์†Œ์žฌ": null,
  "์žฅ๋ฅด": "์›Œํฌ์›จ์–ด",
  "์นดํ…Œ๊ณ ๋ฆฌ": "outer",
  "์‹ค๋ฃจ์—ฃ": null,
  "์ƒ‰์ƒ ๋ฐ ํŒจํ„ด": null,
  "์„ธ๋ถ€ ์นดํ…Œ๊ณ ๋ฆฌ": "์ž์ผ“",
  "๋ถ„์œ„๊ธฐ ๋ฐ ์ง€ํ–ฅ์ ": "๋„์ฟ„ ๋นˆํ‹ฐ์ง€ ์ˆ ๋А๋‚Œ"
}

2-2. ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜ (query_categorizer)

์ž…๋ ฅ: "๋„์ฟ„ ๋นˆํ‹ฐ์ง€ ์›Œํฌ์›จ์–ด ์ž์ผ“"

์ถœ๋ ฅ: "jacket"

3. ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ (์ˆœ์ฐจ ์ฒ˜๋ฆฌ)

q_emb = embedder.embed(query_json)  # ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜

4. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰ ์‹คํ–‰

4-1. ์นดํ…Œ๊ณ ๋ฆฌ ๊ฒฝ๋กœ ์กฐํšŒ

SELECT path::text AS path, nlevel(path) AS depth 
FROM category WHERE name = 'jacket'

-- ๊ฒฐ๊ณผ: path='outer.jacket', depth=2

4-2. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํ•„ํ„ฐ๋ง ๋ฐ ๊ฒ€์ƒ‰

SELECT p.id, p.name, p.original_price AS price,
       p.url AS link, p.brand, p.thumbnail_key,
       p.category_path
FROM products AS p
WHERE p.category_path <@ 'outer.jacket'::ltree    -- ์นดํ…Œ๊ณ ๋ฆฌ + ํ•˜์œ„ ํ•„ํ„ฐ
  AND p.genre && ARRAY['์›Œํฌ์›จ์–ด']                 -- ์žฅ๋ฅด ๋ฐฐ์—ด ๊ฒน์นจ ํ•„ํ„ฐ
ORDER BY p.embedding <#> query_embedding          -- ๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ์ •๋ ฌ
LIMIT 40

5. ๊ฒฐ๊ณผ ํ›„์ฒ˜๋ฆฌ

  • Presigned URL ์ƒ์„ฑ (S3 ์ด๋ฏธ์ง€ ๋งํฌ)
  • ProductResponse ๊ฐ์ฒด ๋ณ€ํ™˜

๐Ÿ”ง ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ

1. ๋น„๋™๊ธฐ ์ฟผ๋ฆฌ ๋ฒˆ์—ญ ์‹œ์Šคํ…œ

Few-shot Learning ํ”„๋กฌํ”„ํŠธ

  • ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ํ•™์Šต์œผ๋กœ ์ผ๊ด€๋œ JSON ๊ตฌ์กฐ ์ถœ๋ ฅ
  • 11๊ฐœ ํŒจ์…˜ ์žฅ๋ฅด ๋ถ„๋ฅ˜ ์ง€์›
  • ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์„ธ๋ถ€ ๋ถ„๋ฅ˜ (top/bottom/outer/accessory)

2. ์นดํ…Œ๊ณ ๋ฆฌ ๊ณ„์ธต ๊ฒ€์ƒ‰

ltree ๊ธฐ๋ฐ˜ ๊ณ„์ธต์  ๊ฒ€์ƒ‰

-- outer.jacket ๊ฒ€์ƒ‰ ์‹œ
WHERE category_path <@ 'outer.jacket'::ltree

-- ํฌํ•จ๋˜๋Š” ํ•ญ๋ชฉ๋“ค:
-- โœ… outer.jacket (์ •ํ™•ํ•œ ๋งค์นญ)
-- โœ… outer.jacket.denim (ํ•˜์œ„)
-- โœ… outer.jacket.bomber (ํ•˜์œ„)
-- โŒ outer.coat (๋‹ค๋ฅธ ์นดํ…Œ๊ณ ๋ฆฌ)

3. ๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ๊ฒ€์ƒ‰

pgvector inner-product ์—ฐ์‚ฐ

ORDER BY p.embedding <#> query_embedding
  • ๊ตฌ์กฐํ™”๋œ ์ฟผ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๋ณ€ํ™˜
  • ์ƒํ’ˆ ์ž„๋ฒ ๋”ฉ๊ณผ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ
  • ์˜๋ฏธ์  ์œ ์‚ฌ์„ฑ ๊ธฐ๋ฐ˜ ์ •๋ ฌ

๐Ÿ“Š ๊ฒ€์ƒ‰ ์ „๋žต

ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํ•„ํ„ฐ๋ง ์ˆœ์„œ

  1. ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ (๊ณ„์ธต์ ): ๊ด€๋ จ ์นดํ…Œ๊ณ ๋ฆฌ + ํ•˜์œ„ ํ•ญ๋ชฉ๋“ค
  2. ์žฅ๋ฅด ํ•„ํ„ฐ (๋ฐฐ์—ด ๊ฒน์นจ): ์‚ฌ์šฉ์ž ์˜๋„์™€ ์ผ์น˜ํ•˜๋Š” ์Šคํƒ€์ผ
  3. ๋ฒกํ„ฐ ์œ ์‚ฌ๋„ (์ •๋ ฌ): ์˜๋ฏธ์  ๊ด€๋ จ์„ฑ ์ˆœ์„œ

์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ์นดํ…Œ๊ณ ๋ฆฌ "None": ์ „์ฒด ๊ฒ€์ƒ‰์œผ๋กœ ๋Œ€์ฒด
  • API ์‹คํŒจ: ์ž๋™ ์žฌ์‹œ๋„ + ํ‚ค ๋กœํ…Œ์ด์…˜
  • ๋นˆ ๊ฒฐ๊ณผ: ์ ์ง„์  ํ•„ํ„ฐ ์™„ํ™”

๐ŸŽฏ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ

์ž…๋ ฅ

"๋ฏธ๋‹ˆ๋ฉ€ํ•œ ์˜ค๋ฒ„์‚ฌ์ด์ฆˆ ๋‹ˆํŠธ"

์ฒ˜๋ฆฌ ๊ณผ์ •

  1. ํŒŒ์‹ฑ ๊ฒฐ๊ณผ:

    • ์žฅ๋ฅด: "๋ฏธ๋‹ˆ๋ฉ€๋ฆฌ์ฆ˜"
    • ์นดํ…Œ๊ณ ๋ฆฌ: "top"
    • ์‹ค๋ฃจ์—ฃ: "์˜ค๋ฒ„์‚ฌ์ด์ฆˆ"
    • ์„ธ๋ถ€ ์นดํ…Œ๊ณ ๋ฆฌ: "๋‹ˆํŠธ"
  2. ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜: "knit"

  3. ๊ฒ€์ƒ‰ ์กฐ๊ฑด:

    WHERE category_path <@ 'top.knit'::ltree
      AND genre && ARRAY['๋ฏธ๋‹ˆ๋ฉ€๋ฆฌ์ฆ˜']
    ORDER BY embedding <#> query_embedding
  4. ๊ฒฐ๊ณผ: ๋ฏธ๋‹ˆ๋ฉ€๋ฆฌ์ฆ˜ ์Šคํƒ€์ผ์˜ ๋‹ˆํŠธ ์ƒํ’ˆ๋“ค์„ ์œ ์‚ฌ๋„ ์ˆœ์œผ๋กœ ๋ฐ˜ํ™˜

๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ

  • ์›น ํ”„๋ ˆ์ž„์›Œํฌ: FastAPI (๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ)
  • AI ๋ชจ๋ธ: Google Gemini 2.5 Flash (์ฟผ๋ฆฌ ํŒŒ์‹ฑ/๋ถ„๋ฅ˜/Embedding)
  • ๋ฒกํ„ฐ DB: PostgreSQL + pgvector
  • ๊ณ„์ธต ๊ด€๋ฆฌ: ltree ํ™•์žฅ
  • ์ด๋ฏธ์ง€ ์ €์žฅ: AWS S3
  • ๋™์‹œ์„ฑ: asyncio.gather() (๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ)

๐Ÿ”„ ์„ฑ๋Šฅ ์ตœ์ ํ™”

1. ๋น„๋™๊ธฐ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ

  • ์ฟผ๋ฆฌ ํŒŒ์‹ฑ๊ณผ ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜๋ฅผ ๋™์‹œ ์‹คํ–‰
  • ์ „์ฒด ์‘๋‹ต ์‹œ๊ฐ„ ~50% ๋‹จ์ถ•

2. API ํ‚ค ๋กœํ…Œ์ด์…˜

  • ์žฅ์•  ๋ฐœ์ƒ ์‹œ ์ž๋™ failover

3. ๊ณ„์ธต์  ๊ฒ€์ƒ‰

  • ltree ์ธ๋ฑ์Šค ํ™œ์šฉ์œผ๋กœ ๋น ๋ฅธ ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ๋ง
  • ๋ฒกํ„ฐ ๊ฒ€์ƒ‰๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ์ •ํ™•๋„/์„ฑ๋Šฅ ๊ท ํ˜•

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors