๐Ÿชœ ์žฅ๊ณ  ๋ฌธ์„œ ๋ชจ๋ธ ์ƒ์„ฑ ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ยถ

์žฅ๊ณ  ์•ฑ ์ƒ์„ฑ ๋ฐ ๋“ฑ๋กยถ

chat ์•ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

python manage.py startapp chat

chat/urls.py ํŒŒ์ผ์„ ์•„๋ž˜ ๋‚ด์šฉ์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

chat/urls.pyยถ
from django.urls import path
from . import views

urlpatterns = []

mysite/urls.py ํŒŒ์ผ์— chat/urls.py ํŒจํ„ด์„ ํฌํ•จ์‹œํ‚ค๊ณ , ๋ฃจํŠธ URL ์š”์ฒญ์€ chat/ ์ฃผ์†Œ๋กœ ์ด๋™์‹œํ‚ค๊ฒ ์Šต๋‹ˆ๋‹ค.

mysite/urls.py ๋ฎ์–ด์“ฐ๊ธฐยถ
 1from django.apps import apps
 2from django.contrib import admin
 3from django.urls import include, path
 4from django.views.generic import RedirectView
 5
 6urlpatterns = [
 7    path("admin/", admin.site.urls),
 8    path("chat/", include("chat.urls")),
 9    path("", RedirectView.as_view(url="/chat/")),
10]
11
12
13if apps.is_installed("debug_toolbar"):
14    urlpatterns = [
15        path("__debug__/", include("debug_toolbar.urls")),
16    ] + urlpatterns

chat ์•ฑ์„ ํ”„๋กœ์ ํŠธ์— ๋“ฑ๋กํ•˜์—ฌ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

mysite/settings.pyยถ
INSTALLED_APPS = [
    # ...
    'pyhub.rag',
    'chat',
]

RAG๋ฅผ ์œ„ํ•œ ๋ฌธ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ์„œ์˜ SQLiteยถ

SQLite๋Š” ๋‹จ์ˆœํžˆ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ทธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์›น์„œ๋น„์Šค์—์„œ์˜ ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„, ์ž‘์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ณ , RAG์šฉ ๋ฌธ์„œ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ณด์กฐ DB๋กœ์˜ ํ™œ์šฉ์€ ์–ด๋– ์‹ ๊ฐ€์š”?

  • ์žฅ๊ณ ๋Š” Router ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๋ชจ๋ธ ๋ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ˜ธ์ŠคํŠธ/์—”์ง„์„ ์ฟผ๋ฆฌ ํƒ€์ž„์— ๋™์ ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • SQLite๋Š” ํŒŒ์ผ ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋ฏ€๋กœ, ๋ฌธ์„œ ํ…Œ์ด๋ธ” ํŒŒ์ผ์„ ๋‹ค๋ฅธ ๋จธ์‹ ์œผ๋กœ ๋ณต์‚ฌํ•˜๊ณ  ์ฝ๊ธฐ์ „์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ์„œ ๊ฒฝ๋กœ๋งŒ ๋งž์ถฐ์ฃผ๋ฉด OK.

    • ๋ฒ•๋ก€์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋“ค์ด ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋“ค์— ํŠนํžˆ ํšจ๊ณผ์ 

    • ๋ฌธ์„œ/์ž„๋ฒ ๋”ฉ์ด ์—…๋ฐ์ดํŠธ๋˜๋ฉด, ๋‹ค์‹œ ์—…๋ฐ์ดํŠธ๋œ DB ํŒŒ์ผ๋งŒ ๋ณต์‚ฌํ•˜๋ฉด OK.

    • ํŠธ๋ž˜ํ”ฝ์ด ์ค‘์•™์— ์ง‘์ค‘๋˜์ง€ ์•Š๊ณ , ๋ถ„์‚ฐ๋˜๋Š” ํšจ๊ณผ.

์„ธ๋ฒ• ํ•ด์„๋ก€ ๋ฌธ์„œ ๋ชจ๋ธ ์ƒ์„ฑยถ

django-pyhub-rag ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” 2๊ฐœ์˜ ์ถ”์ƒํ™” ๋ฌธ์„œ ๋ชจ๋ธ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • SQLiteVectorDocument ์ถ”์ƒํ™” ๋ชจ๋ธ : sqlite-vec ํ™•์žฅ ๋ฐฑ์—”๋“œ

  • PGVectorDocument ์ถ”์ƒํ™” ๋ชจ๋ธ : pgvector ํ™•์žฅ ๋ฐฑ์—”๋“œ

๋‘ ์ถ”์ƒํ™” ๋ฌธ์„œ ๋ชจ๋ธ์€ ๋ชจ๋‘ ๋””ํดํŠธ๋กœ 1536 ์ฐจ์› embedding ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ text-embedding-3-small ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

chat/models.pyยถ
1from pyhub.rag.models.sqlite import SQLiteVectorDocument
2
3class TaxLawDocument(SQLiteVectorDocument):
4    pass
chat/models.pyยถ
 1from pyhub.rag.models.postgres import PGVectorDocument
 2
 3class TaxLawDocument(PGVectorDocument):
 4    class Meta:
 5        indexes = [
 6            PGVectorDocument.make_hnsw_index(
 7                "chat_taxlawdoc_idx",  # ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด์—์„œ ์œ ์ผํ•œ ์ด๋ฆ„์œผ๋กœ ์ง€์ •ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.
 8                # "vector",            # field type
 9                # "cosine",            # distance metric
10            ),
11        ]

์ธ๋ฑ์Šค๋ฅผ ์ง€์ •ํ•˜๋ฉด ์œ ์‚ฌ ๋ฌธ์„œ ๊ฒ€์ƒ‰ ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • sqlite-vec ํ™•์žฅ์—์„œ๋Š” ๋ณ„๋„ ์ธ๋ฑ์Šค ์„ค์ •์€ ์—†๊ณ  ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์‹œ์— distance_metric=cosine ์˜ต์…˜์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

  • pgvector ํ™•์žฅ์—์„œ๋Š” ์ธ๋ฑ์Šค๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ, Cosine Distance ๋“ฑ ๊ฑฐ๋ฆฌ ๊ฒ€์ƒ‰์— ์‚ฌ์šฉํ•˜์‹ค ์ธ๋ฑ์Šค๋ฅผ ์ง€์ •ํ•ด์ฃผ์„ธ์š”.

pgvector์—์„œ ์ง€์›ํ•˜๋Š” ์ธ๋ฑ์Šค ํƒ€์ž…

RAG #02. ์‹ค์ „: ์„ธ๋ฒ• RAG๋ฅผ ์œ„ํ•œ pgvector ์ž„๋ฒ ๋”ฉ ํŠœํ† ๋ฆฌ์–ผ์˜ ์žฅ๊ณ  ๋ชจ๋ธ์— pgvector ์ ์šฉ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋งŒ์•ฝ 2000 ์ฐจ์›์„ ์ดˆ๊ณผํ•œ ์ž„๋ฒ ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ embedding ํ•„๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๊ณ , text-embedding-3-large ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

sqlite-vec์—์„œ๋Š” ์ธ๋ฑ์Šค ์ง€์ •์ด ์—†๊ณ , ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์‹œ์— distance_metric=cosine ์˜ต์…˜์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

chat/models.pyยถ
1from pyhub.rag.fields.sqlite import SQLiteVectorField
2from pyhub.rag.models.sqlite import SQLiteVectorDocument
3
4class TaxLawDocument(SQLiteVectorDocument):
5    embedding = SQLiteVectorField(
6        dimensions=3072,
7        editable=False,
8        embedding_model="text-embedding-3-large",
9    )

PGVectorField ๋‚ด๋ถ€์—์„œ๋Š” 2000์ฐจ์› ์ดํ•˜์—์„œ๋Š” vector ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ๋˜๊ณ , 2000์ฐจ์›์„ ์ดˆ๊ณผํ•  ๊ฒฝ์šฐ halfvec ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค ํƒ€์ž…๋„ ํ•„๋“œ ํƒ€์ž…์— ๋งž๊ฒŒ ์ง€์ •ํ•ด์…”์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.

chat/models.pyยถ
 1from pyhub.rag.fields.postgres import PGVectorField
 2from pyhub.rag.models.postgres import PGVectorDocument
 3
 4class TaxLawDocument(PGVectorDocument):
 5    embedding = PGVectorField(
 6        dimensions=3072,
 7        editable=False,
 8        embedding_model="text-embedding-3-large",
 9    )
10
11    class Meta:
12        indexes = [
13            PGVectorDocument.make_hnsw_index(
14                "chat_taxlawdoc_idx",
15                "halfvec",  # 2000์ฐจ์› ์ดˆ๊ณผ ์‹œ์—๋Š” halfvec ํƒ€์ž…
16                "cosine",   # ๊ฑฐ๋ฆฌ ๊ฒ€์ƒ‰์— ์‚ฌ์šฉํ•˜์‹ค ์ธ๋ฑ์Šค ํƒ€์ž…
17            ),
18        ]

์ค€๋น„ํ•œ ์„ธ๋ฒ• ํ•ด์„๋ก€ ๋ฐ์ดํ„ฐ๋Š” 3072 ์ฐจ์› ์ž„๋ฒ ๋”ฉ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ embedding ํ•„๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ 3072 ์ฐจ์› ์ž„๋ฒ ๋”ฉ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ฒฝ๊ณ 

SQLiteVectorDocument ๋ชจ๋ธ๊ณผ PGVectorDocument ๋ชจ๋ธ์€ ๊ฑฐ์˜ ๋™์ผํ•œ ์ฝ”๋“œ์ด์ง€๋งŒ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋‚ด์—ญ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ๊ฒฝ์šฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ๋‹ค์‹œ ์ƒ์„ฑํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ยถ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  (์ž‘์—… ์ง€์‹œ์–ด ์ž‘์„ฑ), ์ˆ˜ํ–‰๋  SQL ๋ฌธ์„ ํ™•์ธํ•˜๊ณ  (์ž‘์—… ๋‚ด์—ญ ํ™•์ธ), ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค (์ž‘์—… ์ˆ˜ํ–‰).

python manage.py makemigrations chat
python manage.py sqlmigrate chat 0001_initial
python manage.py migrate
../../_images/0001-migrate-sqlite.png

ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์‹œ์— CREATE VIRTUAL TABLE ์ฟผ๋ฆฌ๋กœ ๊ฐ€์ƒ ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋จ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ๊ณ , embedding ํ•„๋“œ๋ฅผ float[3072] ํƒ€์ž…์œผ๋กœ ์ฐจ์›์ˆ˜์— ๋งž๊ฒŒ ์ƒ์„ฑ๋จ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

../../_images/0001-migrate-postgres.png

embedding ํ•„๋“œ๋Š” 3072์ฐจ์›์œผ๋กœ์„œ 2000์ฐจ์›์ด ๋„˜๊ธฐ์— halfvec ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. 2000์ฐจ์› ์ดํ•˜๋Š” vector ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.