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

ابزار جستجوی فایل

هشدار

File Search میزبانی‌شده و vector storeهای مدیریت‌شده توسط ارائه‌دهنده در AvalAI در حال توسعه هستند. برای RAG در production امروز، از /v1/embeddings، ذخیره‌سازی chunk خودتان و /v1/responses استفاده کنید. RAG دستی با Embeddings، بهترین شیوه‌های RAG و Embeddings API را ببینید.

File Search الگوی retrieval میزبانی‌شده و سازگار با OpenAI برای دسترسی مدل به فایل‌های آپلودشده است. مدل می‌تواند در یک vector store مدیریت‌شده جستجو کند، پاسخ grounded بسازد و citationهای فایل را در پاسخ برگرداند. این صفحه نشان می‌دهد چگونه برای این الگو طراحی کنید، در حالی که امروز از مسیر RAG دستی پشتیبانی‌شده در AvalAI استفاده می‌کنید.

امروز از چه چیزی استفاده کنیم

برای ساخت روی AvalAI در وضعیت فعلی، retrieval دستی را به کار ببرید:

  1. فایل‌ها را به chunk تقسیم کنید و source ID پایدار مثل policy.pdf#page=3 نگه دارید.
  2. با /v1/embeddings embedding بسازید.
  3. متن chunk، embedding، permission و metadata را در database یا vector index خودتان ذخیره کنید.
  4. chunkهای مرتبط را با filterهایی مثل tenant، محصول، تاریخ یا نوع سند retrieve و rerank کنید.
  5. فقط context انتخاب‌شده را به /v1/responses بفرستید و از مدل citation به source IDها بخواهید.
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

# این لیست را با chunkهای برگشتی از vector database خودتان جایگزین کنید.
chunks = [
    {
        "source_id": "handbook.pdf#page=4",
        "text": "Employees can request remote work approval from their manager.",
    },
    {
        "source_id": "handbook.pdf#page=8",
        "text": "Security training must be renewed every 12 months.",
    },
]

context = "\n\n".join(f"[{chunk['source_id']}]\n{chunk['text']}" for chunk in chunks)

response = client.responses.create(
    model="gpt-5.5",
    input=[
        {
            "role": "system",
            "content": (
                "Answer only from the provided context. Cite source IDs in brackets. "
                "If the context is insufficient, say what is missing."
            ),
        },
        {
            "role": "user",
            "content": f"Context:\n{context}\n\nQuestion: What approvals are needed?",
        },
    ],
)

print(response.output_text)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

// این آرایه را با نتایج vector database خودتان جایگزین کنید.
const chunks = [
  {
    source_id: "handbook.pdf#page=4",
    text: "Employees can request remote work approval from their manager.",
  },
  {
    source_id: "handbook.pdf#page=8",
    text: "Security training must be renewed every 12 months.",
  },
];

const context = chunks
  .map((chunk) => `[${chunk.source_id}]\n${chunk.text}`)
  .join("\n\n");

const response = await client.responses.create({
  model: "gpt-5.5",
  input: [
    {
      role: "system",
      content:
        "Answer only from the provided context. Cite source IDs in brackets. If the context is insufficient, say what is missing.",
    },
    {
      role: "user",
      content: `Context:\n${context}\n\nQuestion: What approvals are needed?`,
    },
  ],
});

console.log(response.output_text);

آماده‌سازی فایل و metadata

چه امروز از RAG دستی استفاده کنید و چه بعدا به File Search میزبانی‌شده مهاجرت کنید، سندها را با همان انضباط retrieval آماده کنید:

  • فایل‌های متنی را به utf-8، utf-16 یا ascii نرمال کنید؛ فایل با encoding نامشخص را پیش از chunking رد یا تبدیل کنید.
  • هویت منبع را در هر chunk نگه دارید: نام فایل، صفحه یا بخش، tenant، مالک، نسخه و timestamp آخرین به‌روزرسانی.
  • فرمت‌های پشتیبانی‌شده در مسیر میزبانی‌شده OpenAI مثل .pdf، .docx، .md، .txt، .json، فایل‌های رایج کدنویسی و slideهایی مثل .pptx را تا زمان اعلام پشتیبانی میزبانی‌شده در AvalAI فقط مرجع برنامه‌ریزی بدانید.
  • metadata را کوچک و قابل فیلتر نگه دارید. راهنمای Retrieval در OpenAI برای attributeهای فایل در vector store تا ۱۶ کلید فشرده را مستند کرده است؛ بنابراین در store دستی خودتان هم کلیدهای پایدار مثل tenant، document_type، region، effective_date و version بسازید.
  • فیلتر permission و tenant را پیش از retrieval اعمال کنید. مدل هرگز نباید chunkهایی را دریافت کند که کاربر فعلی اجازه خواندنشان را ندارد.

شکل مهاجرت به حالت میزبانی‌شده

وقتی AvalAI پشتیبانی Hosted File Search را فعال کند، با جایگزین کردن retrieval خودتان با tool از نوع file_search در /v1/responses مهاجرت کنید.

کنترل میزبانی‌شدهمعادل دستی در AvalAI امروز
vector_store_idscollection، tenant یا namespace در vector database شما
max_num_resultstop_k یا محدودیت chunkهای rerank‌شده
filtersفیلترهای metadata در SQL/vector DB
ranking_optionsreranker، score threshold و وزن‌های hybrid search در سرویس retrieval شما
include: ["file_search_call.results"]لاگ debug شامل chunkهای انتخاب‌شده، scoreها و source IDها
annotationهای file_citationsource IDهایی که از مدل می‌خواهید cite کند
expires_afterTTL یا job پاک‌سازی برای indexها و فایل‌های آپلودی موقت

flow میزبانی‌شده سازگار با OpenAI این است:

  1. فایل‌ها را با purpose="assistants" برای retrieval میزبانی‌شده آپلود کنید.
  2. یک vector_store بسازید.
  3. فایل‌ها را با helperهای SDK از نوع create_and_poll attach کنید، یا file_counts را poll کنید تا indexing به completed برسد.
  4. /v1/responses را با tools: [{ "type": "file_search", "vector_store_ids": ["..."] }] فراخوانی کنید.
  5. آیتم‌های خروجی file_search_call و متن message دارای citation را بررسی کنید.

برای knowledge baseهای بزرگ‌تر، به جای درخواست‌های تک‌فایلی زیاد، از file_batches.create_and_poll استفاده کنید. مرجع OpenAI تا ۵۰۰ (500) فایل در هر batch را پشتیبانی می‌کند و هر فایل در آرایه files می‌تواند attributes و chunking_strategy مخصوص خودش را داشته باشد.

خواندن خروجی File Search میزبانی‌شده

File Search به سبک OpenAI فقط متن نهایی برنمی‌گرداند؛ خروجی ساختاریافته دارد. وقتی AvalAI پشتیبانی میزبانی‌شده را فعال کرد، هر دو لایه را بررسی کنید:

  • آیتم file_search_call: اجرای tool و status را نشان می‌دهد و اگر include: ["file_search_call.results"] درخواست کرده باشید می‌تواند queries ساخته‌شده یا search_results خام را برگرداند.
  • آیتم message: پاسخ assistant را دارد؛ citationهای فایل به شکل annotation از نوع file_citation داخل blockهای output_text می‌آیند.
  • معادل دستی امروز: شناسه chunkهای انتخاب‌شده، scoreها، filterها و source IDها را در سرویس retrieval خودتان log کنید، سپس از مدل بخواهید همان source IDها را صریح cite کند.

Citationها را از annotationها یا source IDها در UI render کنید، نه از prose آزاد مدل. اگر citation به فایلی اشاره می‌کند که کاربر فعلی نباید به آن دسترسی داشته باشد، آن را پنهان کنید و قبل از نمایش پاسخ، فیلتر retrieval را بررسی کنید.

مثال‌های میزبانی‌شده آینده

هشدار

این مثال‌ها شکل مورد انتظار سازگار با OpenAI را برای پشتیبانی آینده File Search میزبانی‌شده در AvalAI نشان می‌دهند. تا زمانی که AvalAI در دسترس بودن vector_store و file_search را اعلام نکرده، دستورالعمل production نیستند.

آپلود، ایندکس و جستجو

python
import os
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

file_obj = client.files.create(
    file=Path("handbook.pdf").open("rb"),
    purpose="assistants",
)

vector_store = client.vector_stores.create(
    name="internal-handbook",
    expires_after={"anchor": "last_active_at", "days": 30},
)

client.vector_stores.files.create_and_poll(
    vector_store_id=vector_store.id,
    file_id=file_obj.id,
    attributes={"category": "handbook", "tenant": "internal"},
    chunking_strategy={
        "type": "static",
        "max_chunk_size_tokens": 1000,
        "chunk_overlap_tokens": 200,
    },
)

response = client.responses.create(
    model="gpt-5.5",
    input="What does the handbook say about security training?",
    tools=[
        {
            "type": "file_search",
            "vector_store_ids": [vector_store.id],
            "max_num_results": 5,
        }
    ],
)

print(response.output_text)
javascript
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

const file = await client.files.create({
  file: fs.createReadStream("handbook.pdf"),
  purpose: "assistants",
});

const vectorStore = await client.vectorStores.create({
  name: "internal-handbook",
  expires_after: { anchor: "last_active_at", days: 30 },
});

await client.vectorStores.files.createAndPoll(vectorStore.id, {
  file_id: file.id,
  attributes: { category: "handbook", tenant: "internal" },
  chunking_strategy: {
    type: "static",
    max_chunk_size_tokens: 1000,
    chunk_overlap_tokens: 200,
  },
});

const response = await client.responses.create({
  model: "gpt-5.5",
  input: "What does the handbook say about security training?",
  tools: [
    {
      type: "file_search",
      vector_store_ids: [vectorStore.id],
      max_num_results: 5,
    },
  ],
});

console.log(response.output_text);
bash
FILE_ID=$(curl -s "https://api.avalai.ir/v1/files" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -F purpose="assistants" \
  -F file="@handbook.pdf" | jq -r .id)

VECTOR_STORE_ID=$(curl -s "https://api.avalai.ir/v1/vector_stores" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"internal-handbook","expires_after":{"anchor":"last_active_at","days":30}}' | jq -r .id)

curl "https://api.avalai.ir/v1/vector_stores/$VECTOR_STORE_ID/files" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "'"$FILE_ID"'",
    "attributes": {"category": "handbook", "tenant": "internal"},
    "chunking_strategy": {
      "type": "static",
      "max_chunk_size_tokens": 1000,
      "chunk_overlap_tokens": 200
    }
  }'

# پیش از ارسال traffic وابسته به فایل جدید، وضعیت vector store file یا
# vector_store.file_counts را poll کنید تا indexing کامل شود.

curl "https://api.avalai.ir/v1/responses" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "input": "What does the handbook say about security training?",
    "tools": [{
      "type": "file_search",
      "vector_store_ids": ["'"$VECTOR_STORE_ID"'"],
      "max_num_results": 5
    }]
  }'

بازگرداندن نتایج و فیلتر metadata

وقتی برای debug یا evaluation به chunkهای خام retrieveشده نیاز دارید از include استفاده کنید. برای اعمال محدودیت‌های metadata پیش از رسیدن context به مدل، از filters استفاده کنید.

python
response = client.responses.create(
    model="gpt-5.5",
    input="Summarize policy updates for enterprise customers.",
    tools=[
        {
            "type": "file_search",
            "vector_store_ids": ["vs_123"],
            "max_num_results": 3,
            "filters": {
                "type": "and",
                "filters": [
                    {"type": "eq", "key": "tenant", "value": "acme"},
                    {"type": "in", "key": "category", "value": ["policy", "faq"]},
                ],
            },
            "ranking_options": {
                "ranker": "auto",
                "score_threshold": 0.25,
                "hybrid_search": {"embedding_weight": 0.7, "text_weight": 0.3},
            },
        }
    ],
    include=["file_search_call.results"],
)

print(response.output_text)
javascript
const response = await client.responses.create({
  model: "gpt-5.5",
  input: "Summarize policy updates for enterprise customers.",
  tools: [
    {
      type: "file_search",
      vector_store_ids: ["vs_123"],
      max_num_results: 3,
      filters: {
        type: "and",
        filters: [
          { type: "eq", key: "tenant", value: "acme" },
          { type: "in", key: "category", value: ["policy", "faq"] },
        ],
      },
      ranking_options: {
        ranker: "auto",
        score_threshold: 0.25,
        hybrid_search: { embedding_weight: 0.7, text_weight: 0.3 },
      },
    },
  ],
  include: ["file_search_call.results"],
});

console.log(response.output_text);

نکات طراحی از مستندات Retrieval شرکت OpenAI

  • جستجوی معنایی می‌تواند chunkهای مرتبط را حتی با اشتراک کم در keywordها پیدا کند.
  • vector storeهای میزبانی‌شده، فایل‌های attachشده را parse، chunk، embed و index می‌کنند.
  • جستجوی معنایی مستقیم به‌صورت پیش‌فرض تا ۱۰ نتیجه برمی‌گرداند و با max_num_results تا ۵۰ قابل تنظیم است.
  • سیستم‌های retrieval می‌توانند با query rewriting، فیلتر metadata، ranking options و score threshold کیفیت را بهتر کنند.
  • ranking_options شامل ranker، score_threshold و وزن‌های hybrid مثل hybrid_search.embedding_weight و hybrid_search.text_weight است؛ اگر hybrid search را تنظیم می‌کنید، حداقل یکی از وزن‌ها باید بیشتر از صفر باشد.
  • query rewriting می‌تواند یک search_query کوتاه‌تر برای retrieval بسازد؛ direct hosted vector store search این کنترل را به شکل rewrite_query=true نشان می‌دهد. هم input اصلی کاربر و هم query بازنویسی‌شده را log کنید تا regressionهای relevance قابل debug باشند.
  • مقدار پیش‌فرض مرجع OpenAI برای chunk برابر ۸۰۰ توکن با overlap برابر ۴۰۰ توکن است؛ chunk سفارشی باید بین ۱۰۰ تا ۴۰۹۶ توکن باشد و overlap بیشتر از نصف chunk size نباشد.
  • batch ingestion یا file_ids مشترک می‌پذیرد یا objectهای per-file در files؛ وقتی metadata یا chunking هر سند متفاوت است از files استفاده کنید.
  • policyهای انقضا با expires_after برای indexهای موقت، demoها و فایل‌های آپلودی مشتری که نباید دائمی بمانند مفیدند.
  • محدودیت‌های مرجع OpenAI برای فایل vector store شامل ۵۱۲ MB و ۵٬۰۰۰٬۰۰۰ توکن برای هر فایل است. تا زمان اعلام پشتیبانی میزبانی‌شده در AvalAI، این موارد را فقط برای برنامه‌ریزی در نظر بگیرید، نه تعهد AvalAI.

ایمنی و عملیات

  • فقط فایل‌هایی را آپلود کنید که به آن‌ها اعتماد دارید و مجاز به پردازش آن‌ها هستید.
  • فیلترهای tenant و permission را بیرون از مدل نگه دارید؛ برای کنترل دسترسی به prompt تکیه نکنید.
  • شناسه chunkهای retrieveشده، scoreها، filterها و citation نهایی را برای audit لاگ کنید.
  • برای کاهش خطر prompt injection و data exfiltration، argumentهای tool و لینک‌های برگشتی را validate کنید.
  • وقتی storage میزبانی‌شده فعال شد، فایل‌ها یا vector storeهای بلااستفاده را حذف کنید.
  • پس از حذف فایل از storage میزبانی‌شده، یک بازه کوتاه eventual consistency را در نظر بگیرید: permission checkها را در برنامه نگه دارید و فرض نکنید نتیجه‌های retrieveشده cacheشده فورا ناپدید می‌شوند.
  • retrieval را با سوال‌های واقعی، source IDهای مورد انتظار و بررسی کیفیت پاسخ پیش از launch ارزیابی کنید.

منابع مرتبط