ืืจืื ืื ืฉืื ืฉืืืขืื RAG ืืืื ืืืฉืืื ืขื ืืืคืืฉ ืืงืืืจื, ืืื ืืืืช ืฉ RAG ืืื ืืจืื ืืืชืจ ืืื. ืืืื ื ืืืจ ืขื RAG ืืจื ืืฉืืื ืฉื ืืืคืืฉ ืคืืกืืื ืืืืื ืืืืจ ื ืขืืืจ ืืืืืื ืขื ืืืคืืฉ ืืงืืืจื. ืฉืชื ืืืืืืืืช ืืื ืืืฉืคื ืืืง ืืืืืจืืืืช ืืืชืืืช ืกืืื ืื ืฉืฆืจืืืื ืืืืืืจ ืชืฉืืืืช ืืชืื ืืืืจ ืืืข.
โ ืืชืืจ ืืงืื ืืงืกื
ืืชืืื ื ืืช ืืกืืจื ืขื ืืกืืื ืืืืื, ืกืืื ืฉืืงืื ืืืืจ ืืืืืฆืจ ืืื ื 10 ืฉืืืืช. ืืืืฉื ืจืืื ื ืืช ืืกืืื ืฉืืืืฆืจ ื ืืืืืืจ ืืขืืจืช ืืืื, ืืืชื ืกืืื ืืืคืฉ ืืขืฆืื ืืจืฉืช ืืืืจืื ืืขื ืืื ืื ืืืืืจ ืืืชื ืื ืืืืืืจ. ืฉื ื ืืืงืจืื ืืื ืืืืืืืช ืคืฉืืืืช ืืกืืื ืื ืฉืืืืืจืื ืชืฉืืื ืขื ืืกืืก ืืืืจ ืืืข ืืืฉื ืืื ืืขืืืื ืืืชื ืืืื: ืืกืืื ืงืืื ืืช ืืืืืข ืืื ืขื ืืืงืฉื ืืืกืืฃ ืืืืืจ ืชืฉืืื ืืฉืืืืื ืืงืื ืืงืกื ืฉืื ืืื ืืืืืข ืืืจืืฉ ืืืืืื ืืืฉืืื ืฉื ืืืฉืชืืฉ.
ืืื ืื ืื ืืื ืืืืืง ืื ืื ื ืงืืจืืื RAG ืฉืื ืจืืฉื ืชืืืืช ืฉื Retrieval-augmented generation. ืืืืช ืืืคืชื ืฉื RAG ืืื Retrieval, ืืืขืจืืช ืืืฉืืช ืืช ืืืืืข ืืจืืืื ืื, ืืืกืืคื ืืืชื ืืืืื ืืงืื ืืงืกื (ืื ื Augmented) ืืืคืขืืื ืืช ืืืืื ืืื ืืืืฆืจ ืชืฉืืื.
ืืฉืชื ืืืืืืืืช ืฉืืฆืืชื ืื ืืืื ื ืฆืจืืืื ืืืชืืื ืืืื ืืืืข ืืืื ืืก ืืืืื ืืงืื ืืงืกื. ืืกืืื ืืืืื ืืื ืฆืจืื ืืช ืืืืืจ ืืื ืื ืฉืืื ืงืืื. ืกืืื ืื ืืืืืืจ ืืื ืฆืจืื ืืืืฉืื ืืืืจืื ืืืืื ืืขืฆืื ืืช ืืืืื. ืืขืจืืืช RAG ืืืชืจ ืืขื ืืื ืืช ืื ืืขืจืืืช ืฉืฆืจืืืืช ืืืืืื ืืฆืืจื ืืื ืืืช ืืืคื ืืงืฉืช ืืืฉืชืืฉ ืืืื ืืืืข ืืืื ืืก ืืืืื ืืงืื ืืงืกื ืืคื ื ืฉืคืื ืื ืืืืื.
ืืขืจืืช RAG ืืืจืืืช ืืื ืชืืื ืืืกืคืจ ืืืงืื - ืืืืง ืฉื ืืกืืื ืืืืืง ืฉืืืคืฉ ืืขืืืช ืืช ืืงืฉืช ืืืฉืชืืฉ ืขื ืืืืข ืืืืืจ ืืืืข. ืฉืืื ืื ืฉืื ืืืง ืืื ืขืฆืืื, ืืกืืื ืืื ืืื ืืขืืื ืื ืืฆืืื ืืขื ืืช ื ืืื ืื ืื ืชืชื ื ืื ืืช ืืืืืข, ืืืืืืข ืืื ืจืืืื ืื ืื ืืขืืืจ ืื ืืกืืื ืื ืืฆืืื ืืืืื ืืืชื. ืืจืื ืคืขืืื ื ืจืฆื ืืฉืื ืื ืืืคืฆืื ืืืืคืืฉ ืืืฉื, ืืืืืจ ื ืืชื ืืกืืื ืืืืข ืจืืฉืื ื ืืืืื ืืื ืืืฉืื ืืืืข ื ืืกืฃ.
ืืืืืื ืืืื ื ืื ื ืกืืื ืฉืืืืข ืืขื ืืช ืขื ืฉืืืืช ืืคื ืคืืกืืื ืืืืืื ืืื. ืื ืื ื ื ืื ื:
1. ืกืงืจืืคื ืฉืืืจืื ืืช ืืคืืกืืื ืืืืืื ืืืื ืืงืก ืืืชื ืืืกืืก ื ืชืื ืื ืืืืืขื ืืืืคืืฉ ืืฉื Meilisearch.
2. ืงืื ืคืืืชืื ืฉืืงืื ืฉืืืช ืืฉืชืืฉ ืืืืคืฉ ื Meilisearch ืืืื ืคืืกืืื ืขืฉืืืื ืืืืืช ืจืืืื ืืื ืืฉืืื ืื (ืืืื ืคืืกืืื ืืืืืื ืืืืื ืืืฉืืื).
3. ืงืื ืกืืื ืฉืืงืื ืคืืกืืื ืืืืืื ืืฉืืืช ืืฉืชืืฉ ืืขืื ื ืขื ืืฉืืื ืืคื ืื ืฉืืชืื ืืคืืกืืื.
ืฉืืืฉืช ืืืืงืื ืืืืืื ืืขืจืืช RAG ืืืืืื ืืืชื ื ืขื ืืืชืืจืื ืืื ืืืช ืืขืจืืช ืืื.
โ ืืฆืืจืช ืืืืืข
ืฉืื ืจืืฉืื ืืืขืจืืช ืืื ืืฆืืจืช ืืืืจ ืืืืืข. ืืืืืื ืฉืื ื ื ืชืืื ืขื ืืกืงืจืืคื download-data.py ืฉืืืจืื ืืช ืื ืืคืืกืืื ืืืืชืจ ืืงืืฆื markdown ืืงืืืืื. ืื ืงื ืื ืื ื ืืืืื ืืคืจืกื ืืช ืืคืืกืืื ืื ื HTML ืืื ื Markdown ืืืื ืืงืื ืฆืจืื ืืจืืฅ ืขื ืืฃ ืื ืืคื ืืื ืืงืก ืืืืืื, ืืืกืืฃ ืืช ืืงืืฉืืจืื ืืคืืกืืื ืืื ืืืืจืื ืืืชื ืืื ืืืขืืืก ืขื ืืฉืจืช. ืืืช ืืคืื ืงืฆืื ืืืจืืืืช:
async def run(count: int) -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
semaphore = asyncio.Semaphore(MAX_CONCURRENCY)
async with httpx.AsyncClient(
headers={"User-Agent": USER_AGENT},
follow_redirects=True,
timeout=30.0,
) as client:
slugs = await collect_slugs(client, count, semaphore)
if len(slugs) < count:
print(f"warning: only {len(slugs)} posts found (requested {count})")
# The slug list is the download queue; the semaphore enforces at most
# MAX_CONCURRENCY concurrent requests.
await asyncio.gather(
*[download_post(client, slug, semaphore) for slug in slugs]
)
print(f"done: downloaded {len(slugs)} posts to {DATA_DIR}/")
ืืกืงืจืืคื ืืืงื ืืืืฉืชืืฉ ืืกืคืจ ืคืืกืืื ืืืืจืื ืืฉืืืจ ืืช ืืืื ืืชืืงืืืช data.
โ ืฉืืืจืช ืืคืืกืืื ืืืกืืก ื ืชืื ืื ืืืืคืืฉ
ืืืจื ืฉืืฉ ืื ื ืืืืจ ืืืืข ืื ืื ื ืจืืฆืื ืืื ืืงืก ืืืชื ืืืืืจ ืืฉืืืจ ืืช ืืืืืข ืืฆืืจื ืฉืืืื ืงื ืืืืืจ ืืช ืืคืืกืืื ืืจืืืื ืืื ืืฉืืืืช ืืฉืชืืฉืื. ืื ืชืคืงืืื ืฉื ืืกืงืจืืคื ืืงืืืฅ index.py
ืื ืืข ืืืืคืืฉ ืืืืื ืฉืืืจ ืืืืืงืืื ืืืืืข ืืืคืฉ ืืืงืกื ืฉืืื. ืืคืื ืงืฆืื ืืจืืฉืื ื ืงืืจืืช ืืช ืืงืืฆืื ืืืืืกืง ืืจืฉืืื ืืืืจืื:
def build_documents() -> list[dict[str, str]]:
"""Read every ``.md`` file in ``data`` and build Meilisearch documents."""
docs: list[dict[str, str]] = []
for path in sorted(DATA_DIR.glob("*.md")):
content = path.read_text(encoding="utf-8")
docs.append(
{
"id": path.stem,
"filename": path.name,
"title": _extract_title(content),
