تخفیف‌های نمایش‌داده‌شده توسط خود ارائه‌دهندگان اصلی اعمال می‌شوند و بازه زمانی مشخصی ندارند. این تخفیف‌ها فقط روی مصرف (Usage) اعمال می‌شوند و هنگام خرید اعتبار اعمال نمی‌گردند. میزان تخفیف ممکن است در هر لحظه کاهش یابد؛ حتی در زمان تخفیف، درخواست‌ها ممکن است به ارائه‌دهندهٔ بدون تخفیف بروند و قیمت کامل محاسبه شود.

هوش مصنوعی برای توسعه‌دهندگان

RAG چیست و چطور با API هوش مصنوعی بسازیم؟

۱ آبان ۱۴۰۵ · نویسنده: کایا ای آی

RAG چیست و چطور با API هوش مصنوعی بسازیم؟

RAG مخفف Retrieval-Augmented Generation است؛ یعنی «تولید پاسخ با کمک بازیابی اطلاعات». ایده ساده است: به‌جای اینکه انتظار داشته باشیم مدل زبانی همه‌چیز را از حفظ بداند، اول اطلاعات مرتبط را از منبع خودمان پیدا می‌کنیم، بعد آن را در کنار پرسش کاربر به مدل می‌دهیم و از مدل می‌خواهیم فقط بر اساس همان اطلاعات پاسخ بدهد. نتیجه، پاسخی است که به داده‌های واقعی شما متصل است، نه به حافظه‌ی مبهم مدل.

کایا ای آی درگاه API هوش مصنوعی است و خودش مدل آموزش نمی‌دهد؛ اما هر دو قطعه‌ی لازم برای ساخت RAG را در یک API سازگار با OpenAI در اختیار شما می‌گذارد: اندپوینت امبدینگ برای ساختن بردار معنایی و اندپوینت chat completions برای تولید پاسخ. کافی است base_url را روی https://kayaai.ir/api/v1 بگذارید.

RAG چیست؟ با یک مثال ملموس

فرض کنید یک شرکت ایرانی پشتیبانی مشتریان دارد و می‌خواهد یک دستیار بسازد که به سؤال «شرایط بازگشت کالای خرابیده چیست؟» جواب درست بدهد. این پاسخ در یک فایل PDF آیین‌نامه‌ی داخلی نوشته شده و هیچ مدل عمومی‌ای آن را ندیده است.

دو مسیر داریم. مسیر اول این است که مدل را با آن سند آموزش بدهیم (فاین‌تیونینگ). مسیر دوم این است که سند را قطعه‌قطعه کنیم، برای هر قطعه یک بردار معنایی بسازیم، این بردارها را در یک وکتوراستور ذخیره کنیم و هنگام پرسش، نزدیک‌ترین قطعه‌ها را پیدا کرده و به مدل بدهیم. مسیر دوم همان RAG است.

در RAG مدل هیچ‌چیز جدیدی «یاد نمی‌گیرد». مدل همان مدل قبلی است؛ فقط ورودی‌اش هوشمندانه‌تر انتخاب می‌شود. مزیت بزرگ این است که به‌روزرسانی دانش، فقط با افزودن یا حذف قطعه‌ها انجام می‌شود و نیازی به آموزش مجدد نیست.

RAG یا فاین‌تیونینگ؟ کدام را انتخاب کنیم

این دو رقیب هم نیستند؛ ابزارهای متفاوتی برای مسائل متفاوت‌اند.

معیارRAGفاین‌تیونینگ
هدف اصلیدسترسی به دانش تازه و اختصاصیتغییر لحن، قالب و سبک رفتار مدل
به‌روزرسانی دانشفقط جایگزینی قطعه‌ها در وکتوراستورنیاز به دیتاست جدید و آموزش مجدد
شفافیت منبعبالا؛ می‌توانید بگویید پاسخ از کدام قطعه آمدهپایین؛ منبع پاسخ قابل ردیابی نیست
هزینه‌ی نگه‌داریعمدتاً هزینه‌ی امبدینگ و توکن ورودیهزینه‌ی آموزش و نگه‌داری نسخه‌ها

قاعده‌ی سرانگشتی: اگر مسئله «مدل نمی‌داند» است، RAG. اگر مسئله «مدل می‌داند ولی بد جواب می‌دهد» است، فاین‌تیونینگ. ترکیب هر دو هم ممکن است، اما برای شروع، RAG سریع‌تر به نتیجه می‌رسد و برگشت‌پذیرتر است.

معماری یک سیستم RAG

هر سیستم RAG، ساده یا پیچیده، از چهار مرحله‌ی ثابت تشکیل می‌شود.

۱) قطعه‌بندی (Chunking)

سند را به قطعه‌های کوچک تقسیم می‌کنیم؛ چون هم مدل محدودیت طول ورودی دارد و هم بازیابی دقیق‌تر می‌شود. دو استراتژی رایج:

  • قطعه‌بندی ثابت: هر N کاراکتر یا توکن، با مقداری هم‌پوشانی (overlap) بین قطعه‌های متوالی.
  • قطعه‌بندی ساختاری: تقسیم بر اساس سرتیتر، پاراگراف یا بندهای سند، تا هر قطعه یک واحد معنایی کامل باشد.

۲) تولید امبدینگ

برای هر قطعه، مدل امبدینگ را صدا می‌زنیم و یک بردار عددی می‌گیریم. متن‌هایی که معنای نزدیک دارند، بردارهای نزدیک دارند. این بردارها را ذخیره می‌کنیم تا در زمان پرسش، جست‌وجو ارزان و سریع باشد.

۳) ذخیره در وکتوراستور

وکتوراستور می‌تواند یک آرایه‌ی NumPy در حافظه باشد (برای شروع و برای چند هزار قطعه کافی است) یا یک پایگاه‌داده‌ی برداری اختصاصی. نکته‌ی مهم این است که برای هر قطعه، هم بردار و هم متن اصلی و هم فراداده (نام فایل، شماره صفحه) را نگه دارید.

۴) بازیابی و تزریق در prompt

پرسش کاربر را هم امبدینگ می‌کنیم، نزدیک‌ترین قطعه‌ها را بر اساس شباهت کسینوسی برمی‌گردانیم و آن‌ها را داخل prompt قرار می‌دهیم. یک الگوی ساده:

1به کمک «زمینه» زیر پاسخ بده. اگر پاسخ در زمینه نبود، صریحاً بگو «در اسناد موجود نیست».
2هیچ اطلاعاتی از خودت اضافه نکن.
3
4زمینه:
5{context}
6
7پرسش: {question}

پیاده‌سازی گام‌به‌گام با API کایا ای آی

نصب و پیکربندی

bash
pip install openai numpy pypdf
export KAYA_API_KEY="کلید-شما"

کلید را از پنل حساب خود بردارید. ثبت‌نام با شماره موبایل و رمز یک‌بار‌مصرف انجام می‌شود و هنگام ثبت‌نام ۱۰۰ اعتبار رایگان می‌گیرید. چون API سازگار با OpenAI است، از همان SDK رسمی استفاده می‌کنیم و فقط base_url را عوض می‌کنیم.

python
1import os
2from openai import OpenAI
3
4client = OpenAI(
5    base_url="https://kayaai.ir/api/v1",
6    api_key=os.environ["KAYA_API_KEY"],
7)
8
9# شناسه‌ی دقیق مدل‌ها را در https://kayaai.ir/models ببینید
10EMBED_MODEL = "text-embedding-3-small"
11CHAT_MODEL = "gpt-4o-mini"

انتخاب مدل را جدی بگیرید: برای امبدینگ تقریباً همیشه یک مدل کوچک و ارزان کافی است، اما برای تولید پاسخ بسته به پیچیدگی سؤال ممکن است به مدل قوی‌تری نیاز داشته باشید. فهرست کامل مدل‌های در دسترس در /models آمده است.

قطعه‌بندی و امبدینگ

python
1import numpy as np
2
3def chunk_text(text: str, size: int = 700, overlap: int = 120) -> list[str]:
4    text = " ".join(text.split())
5    chunks, start = [], 0
6    while start < len(text):
7        end = start + size
8        chunks.append(text[start:end])
9        if end >= len(text):
10            break
11        start = end - overlap
12    return [c for c in chunks if c.strip()]
13
14def embed(texts: list[str]) -> np.ndarray:
15    """بردارها را به‌صورت دسته‌ای (batch) می‌گیرد تا تعداد درخواست‌ها کم شود."""
16    resp = client.embeddings.create(model=EMBED_MODEL, input=texts)
17    return np.array([d.embedding for d in resp.data], dtype=np.float32)

وکتوراستور ساده و جست‌وجو

python
1class VectorStore:
2    def __init__(self):
3        self.chunks: list[str] = []
4        self.matrix: np.ndarray | None = None
5
6    def add(self, chunks: list[str], vectors: np.ndarray) -> None:
7        self.chunks.extend(chunks)
8        self.matrix = vectors if self.matrix is None else np.vstack([self.matrix, vectors])
9
10    def search(self, query: str, k: int = 4):
11        q = embed([query])[0]
12        q = q / (np.linalg.norm(q) + 1e-10)
13        m = self.matrix / (np.linalg.norm(self.matrix, axis=1, keepdims=True) + 1e-10)
14        scores = m @ q
15        idx = np.argsort(-scores)[:k]
16        return [(self.chunks[i], float(scores[i])) for i in idx]

ساخت پاسخ با اندپوینت چت

python
1SYSTEM = (
2    "تو یک دستیار پاسخ‌گو هستی. فقط بر اساس «زمینه» پاسخ بده. "
3    "اگر پاسخ در زمینه نبود، بگو در اسناد موجود نیست. "
4    "در پایان پاسخ، شماره‌ی قطعه‌های استفاده‌شده را ذکر کن."
5)
6
7def ask(store: VectorStore, question: str, k: int = 4) -> str:
8    hits = store.search(question, k=k)
9    context = "\n\n---\n\n".join(f"[قطعه {i+1}] {text}" for i, (text, _) in enumerate(hits))
10
11    resp = client.chat.completions.create(
12        model=CHAT_MODEL,
13        temperature=0.2,
14        messages=[
15            {"role": "system", "content": SYSTEM},
16            {"role": "user", "content": f"زمینه:\n{context}\n\nپرسش: {question}"},
17        ],
18    )
19    return resp.choices[0].message.content

اگر پاسخ‌ها طولانی‌اند و می‌خواهید تجربه‌ی کاربر سریع‌تر شود، همان درخواست را با stream=True بفرستید و توکن‌ها را تدریجی نمایش دهید. جزئیات پارامترها در /docs/api آمده است.

نکات عملی برای متن فارسی

متن فارسی چند ویژگی دارد که اگر نادیده گرفته شوند، کیفیت بازیابی به‌سرعت افت می‌کند.

  • نرمال‌سازی اجباری است. «ي» عربی و «ی» فارسی، «ك» عربی و «ک» فارسی، اعداد عربی و فارسی، و نیم‌فاصله باعث می‌شوند دو رشته‌ی ظاهراً یکسان، دو بردار متفاوت بگیرند. همان تابع نرمال‌سازی را هم روی سند و هم روی پرسش کاربر اعمال کنید.
  • هم‌پوشانی را زیاد کنید. در فارسی، جمله‌ها به هم وابسته‌اند و بریدن وسط جمله معنای قطعه را ناقص می‌کند. در chunking، هم‌پوشانی ۱۰۰ تا ۱۵۰ کاراکتر منطقی است.
  • قطعه‌بندی ساختاری را ترجیح دهید. اگر سند بند و سرتیتر دارد، هر بند را یک قطعه بگیرید؛ نتیجه از بریدن کورکورانه‌ی متن بهتر است.
python
1import re
2
3AR_TO_FA = {"ي": "ی", "ك": "ک", "ة": "ه", "ۀ": "ه", "ؤ": "و", "إ": "ا", "أ": "ا"}
4
5def normalize_fa(text: str) -> str:
6    for a, p in AR_TO_FA.items():
7        text = text.replace(a, p)
8    text = re.sub(r"[\u064B-\u0652]", "", text)   # حذف اعراب
9    text = text.replace("\u200c", "")             # حذف نیم‌فاصله (یکدست‌سازی)
10    text = re.sub(r"[ـ]{2,}", "", text)            # حذف کشیده
11    text = re.sub(r"\s+", " ", text)
12    return text.strip()

نکته‌ی مهم: وقتی نیم‌فاصله را حذف می‌کنید، همین کار را روی پرسش کاربر هم انجام دهید؛ در غیر این صورت «می‌رود» و «میرود» دو چیز متفاوت محسوب می‌شوند.

مثال کامل: پرسش‌وپاسخ روی یک PDF

python
1from pypdf import PdfReader
2
3def load_pdf(path: str) -> str:
4    reader = PdfReader(path)
5    return "\n".join((page.extract_text() or "") for page in reader.pages)
6
7# ۱) بارگذاری و نرمال‌سازی
8raw = normalize_fa(load_pdf("employee_handbook.pdf"))
9
10# ۲) قطعه‌بندی
11chunks = chunk_text(raw, size=700, overlap=120)
12print(f"تعداد قطعه‌ها: {len(chunks)}")
13
14# ۳) امبدینگ (به‌صورت دسته‌ای)
15store = VectorStore()
16BATCH = 64
17for i in range(0, len(chunks), BATCH):
18    batch = chunks[i:i + BATCH]
19    store.add(batch, embed(batch))
20
21# ۴) پرسش‌وپاسخ
22q = normalize_fa("مرخصی استحقاقی سالانه چند روز است؟")
23print(ask(store, q))

این اسکریپت را می‌توانید در چند دقیقه روی یک فایل واقعی اجرا کنید. برای سندهای بزرگ‌تر، مرحله‌ی امبدینگ را یک‌بار انجام دهید و بردارها را روی دیسک ذخیره کنید تا هر بار هزینه‌ی مجدد نپردازید.

خطاهای رایج در پیاده‌سازی RAG

  • قطعه‌های خیلی بزرگ: بازیابی بی‌دقت می‌شود و هر درخواست، توکن ورودی زیادی مصرف می‌کند.
  • قطعه‌های خیلی کوچک: معنا از هم می‌پاشد و مدل جمله‌ی ناقص می‌گیرد.
  • نادیده‌گرفتن هزینه‌ی امبدینگ: اگر با هر بار اجرای برنامه، کل سند را دوباره امبدینگ کنید، هزینه‌ی بی‌دلیل می‌سازید. بردارها را کش کنید.
  • نبود ارزیابی: بدون یک مجموعه‌ی آزمون کوچک (۲۰ تا ۵۰ پرسش با پاسخ درست)، نمی‌فهمید تغییراتتان کیفیت را بهتر کرده یا بدتر.
  • نرمال‌سازی ناهمگون: پرسش نرمال‌نشده در برابر سند نرمال‌شده، بازیابی را خراب می‌کند.
  • top_k بزرگ: دادن ده قطعه به مدل، هم پرهزینه است و هم احتمال پرت‌شدن حواس مدل را بالا می‌برد. با ۳ تا ۵ شروع کنید.
  • نبود ارجاع به منبع: اگر مدل نگوید پاسخ از کجا آمده، کاربر نمی‌تواند صحتش را بسنجد.

هزینه و بهینه‌سازی

مدل مصرف در کایا ای آی Pay-as-you-go است؛ یعنی فقط به‌ازای توکن مصرفی واقعی هزینه می‌پردازید، به‌همراه ۲٪ کارمزد سرویس. پرداخت ریالی و از طریق درگاه زیبال انجام می‌شود؛ نیازی به کارت ارزی یا حساب خارجی ندارید. نرخ‌های دقیق را در /pricing ببینید.

برای کاهش هزینه‌ی RAG، این کارها بیشترین اثر را دارند:

  1. امبدینگ را یک‌بار بسازید. هزینه‌ی امبدینگ در ساخت ایندکس است، نه در هر پرسش. پرسش کاربر فقط یک امبدینگ کوتاه مصرف می‌کند.
  2. مدل امبدینگ کوچک انتخاب کنید. برای جست‌وجوی متنی، تفاوت مدل‌های بزرگ و کوچک امبدینگ اغلب کمتر از تفاوت هزینه‌شان است.
  3. طول زمینه را کنترل کنید. به‌جای پر کردن پنجره‌ی زمینه، ۳ تا ۵ قطعه‌ی مرتبط بفرستید.
  4. مدل پاسخ را با نیاز تطبیق دهید. برای پرسش‌های ساده روی اسناد کوتاه، مدل کوچک‌تر کافی است؛ مدل بزرگ را برای پرسش‌های استدلالی نگه دارید.
  5. خروجی ساختاریافته بگیرید. اگر پاسخ را در قالب JSON با فیلدهای مشخص می‌خواهید، با output ساختاریافته درخواست کنید تا نیاز به پس‌پردازش و درخواست دوباره نداشته باشید.

برای شروع، یک سند واقعی از کسب‌وکار خودتان را بردارید، با /auth ثبت‌نام کنید، اعتبار رایگان اولیه را مصرف کنید و یک خط لوله‌ی ساده مثل کدهای بالا بسازید. بعد از اینکه پاسخ‌های درست گرفتید، سراغ بهبودهایی مثل قطعه‌بندی ساختاری، بازیابی ترکیبی (برداری + کلیدواژه) و ارزیابی سیستماتیک بروید. نمونه‌های بیشتر در /blog منتشر می‌شود.

سوالات متداول

RAG چیست و چه تفاوتی با فاین‌تیونینگ دارد؟+
RAG یک الگوی معماری است که در آن دانش بیرونی را در زمان پاسخ‌دهی بازیابی و به پرامپت مدل تزریق می‌کنیم، بدون تغییر در وزن‌های مدل. فاین‌تیونینگ یعنی آموزش بیشتر روی داده‌های شما که کندتر و پرهزینه‌تر است. برای دانش متغیر و اسناد سازمانی معمولاً RAG انتخاب سریع‌تری است.
برای ساخت سیستم RAG باید خودمان مدل آموزش بدهیم؟+
خیر. کایا ای آی یک درگاه API است و خودش مدل آموزش نمی‌دهد؛ شما از بیش از ۴۰۰ مدل ارائه‌دهندگان مختلف استفاده می‌کنید. کافی است base_url را به https://kayaai.ir/api/v1 تغییر دهید و از اندپوینت‌های embedding و chat استفاده کنید.
هزینه ساخت و اجرای یک سیستم RAG چقدر است؟+
مدل مصرف کایا ای آی Pay-as-you-go است و فقط به‌ازای مصرف واقعی توکن به‌همراه ۲٪ کارمزد سرویس محاسبه می‌شود. چون بخش زیادی از هزینه مربوط به امبدینگ اسناد است، انتخاب مدل مناسب اثر مستقیم دارد. برای جزئیات به صفحه /pricing مراجعه کنید.
کدام مدل را برای امبدینگ و کدام را برای پاسخ‌دهی انتخاب کنم؟+
برای امبدینگ مدلی را انتخاب کنید که با زبان فارسی و طول قطعه‌های شما سازگار باشد و برای پاسخ‌دهی می‌توانید از یک مدل چت مقرون‌به‌صرفه استفاده کنید. فهرست کامل مدل‌ها در /models قابل مشاهده است. پیشنهاد می‌شود قبل از پردازش کل اسناد، روی چند نمونه کوچک مقایسه کنید.
آیا برای استفاده از API کایا ای آی به فیلترشکن یا کارت ارزی نیاز دارم؟+
خیر. دسترسی بدون نیاز به تغییر IP و بدون فیلترشکن انجام می‌شود و پرداخت ریالی از طریق درگاه زیبال با کارت‌های شتاب است. ثبت‌نام هم با شماره موبایل و رمز یک‌بارمصرف انجام می‌شود و ۱۰۰ اعتبار رایگان در شروع دریافت می‌کنید.
چطور بفهمم سیستم RAG من درست کار می‌کند؟+
یک مجموعه پرسش و پاسخ مرجع بسازید و بعد از هر تغییر در اندازه قطعه‌ها یا مدل، دقت بازیابی و صحت پاسخ‌ها را روی همان مجموعه بسنجید. بدون این ارزیابی، بهبود یا افت کیفیت قابل تشخیص نیست.