Strona główna / Artykuły / Produkcja RAG w Azure: dzielenie na fragmenty, wyszukiwanie hybrydowe, filtry i cytaty

Produkcja RAG w Azure: dzielenie na fragmenty, wyszukiwanie hybrydowe, filtry i cytaty

Aplikacje biznesowe wymagają fragmentów uwzględniających strukturę, wyszukiwania hybrydowego, filtrów ACL, ponownego rankowania, spersonalizowanych promptów oraz oceny — a nie tylko demonstracji w formacie PDF.

1350 słów

Demony RAG wyglądają prosto: PDF → fragmenty → embeddingi → baza wektorowa → zapytanie do modelu. Potem przychodzi pięć tysięcy dokumentów i ktoś pyta o zasady zwrotu kosztów podróży zagranicznych. Trudna jest pewna integracja odpowiednich dowodów z modelem.

1. Zacznij od danych, a nie od LLM

Zbadaj źródła, kontrolę dostępu, aktualność i formaty przed wyborem modelu do rozmów. Złe korpusy generują błędne, płynne odpowiedzi.

2. Dzielenie na fragmenty: nie dziel bezmyślnie co N znaków

Najlepiej stosować podział z uwzględnieniem struktury (tytuły, strony, tabele) z nakładaniem się fragmentów. Tabele opłat i klauzule polityk nie tolerują prostych okien znakowych.

3. Generowanie embeddingów

Ustal jedną metodę implementacji embeddingów; zapisuj wymiary i identyfikator modelu przy każdym indeksie. Mieszanie modeli potajemnie pogarsza dokładność wyników.

document = {
   "document_id": "HR-2026-001",
   "title": "Employee Benefits Policy",
   "department": "HR",
   "country": "India",
   "version": "2026.1",
   "effective_date": "2026-01-01",
   "source": "HR Portal"
}
def chunk_text(text, size=1000):
   return [
     text[i:i + size]
     for i in range(0, len(text), size)
]
def chunk_by_sections(document):
  chunks = []
  for section in document.sections:
    chunks.append({
      "title": section.title,
      "content": section.text,
      "document_id": document.id
    })
  return chunks
pip install openai azure-identity
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
  DefaultAzureCredential(),
  "https://ai.azure.com/.default"
)

client = OpenAI(
  base_url="https://YOUR-RESOURCE.openai.azure.com/openai/v1/",
  api_key=token_provider
)

response = client.embeddings.create(
  model="text-embedding-3-small",
  input="Employees are eligible after completing 12 months of service."
)
vector = response.data[0].embedding
{
  "id": "HR-2026-001-004",
  "document_id": "HR-2026-001",
  "title": "Employee Benefits Policy",
  "content": "...",
  "country": "India",
  "version": "2026.1",
  "content_vector": embedding
}
from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizedQuery

query = "Can I work remotely from another country?"

query_vector = client.embeddings.create(
  model="text-embedding-3-small",
  input=query
).data[0].embedding

vector_query = VectorizedQuery(
  vector=query_vector,
  k_nearest_neighbors=10,
  fields="content_vector"
)

results = search_client.search(
  search_text=query,
  vector_queries=[vector_query],
  top=5,
  select=["title", "content", "document_id", "country"]
)
results = search_client.search(
  search_text=query,
  vector_queries=[vector_query],
  filter="country eq 'India'",
  top=5
)
context = "\n\n".join(
  f"Source: {r['title']}\n{r['content']}"
  for r in results
)
prompt = f"""
You are an enterprise policy assistant.
Answer the user's question using only the provided evidence.
If the evidence does not contain the answer, say that you don't have enough information.
Do not invent policies.
Evidence: {context}
Question: {query}
"""
{
  "document_id": "HR-2026-001",
  "page": 14,
  "section": "Eligibility",
  "content": "..."
}
def answer_question(question):

  # 1. Embed the question
  vector = embed(question)

  # 2. Hybrid retrieval
  candidates = search(
    query=question,
    vector=vector,
    top=20
  )

  # 3. Apply metadata/business filters
  candidates = apply_filters(candidates)

  # 4. Rerank
  ranked = rerank(question, candidates)

  # 5. Keep only useful evidence
  evidence = ranked[:5]

  # 6. Build grounded prompt
  prompt = build_prompt(
    question,
    evidence
  )

  # 7. Generate answer
  response = generate(prompt)

  # 8. Return answer + citations
  return {
    "answer": response,
    "sources": extract_sources(evidence)
  }
test_cases = [
  {
    "question": "What is the India travel allowance?",
    "expected_source": "travel-policy-india.pdf"
  },
  {
    "question": "How long is parental leave?",
    "expected_source": "leave-policy-2026.pdf"
  }
]

4. Przechowywanie embeddingów w Azure AI Search

Zachowuj tekst, wektory oraz metadane nadające się do filtrowania (id dokumentu, produkt, lokalizacja, grupa ACL, updated_at).

5. Hybrydowe wyszukiwanie jest lepsze od wyłącznie wektorowego dla większości przedsiębiorstw

Łącz intensywną podobieństwo z algorytmem BM25/słowami kluczowymi w przypadku identyfikatorów, kodów oraz rzadkich nazw własnych.

6. Filtrowanie przed marnowaniem kontekstu

Zastosuj filtry bezpieczeństwa i dotyczące dzierżawy w zapytaniu – a nie po tym, jak model już obejrzał zabronione fragmenty.

7>Wyniki wyszukiwania nie stanowią ostatecznego kontekstu

Ponownie uporządkuj wyniki, usuń duplikaty i dostosuj ich liczbę do dostępnej puli tokenów. Więcej fragmentów ≠ lepsze odpowiedzi.

8. Tworzenie promptu na podstawie dostępnych dowodów

Instrukcje powinny wymagać odpowiedzi wyłącznie z podanych fragmentów tekstu oraz wskazywać, gdy brakuje dowodów.

9. Uzasadnienie z cytatami

Należy podać identyfikatory fragmentów lub stron, aby użytkownicy mogli to sprawdzić. Brak cytowania stanowi zagrożenie.

10. Proces gotowy do wdrożenia

Przyjmowanie danych → dzielenie na fragmenty → włączanie informacji → tworzenie indeksu → hybrydowe wyszukiwanie → filtrowanie → ponowna klasyfikacja → generowanie odpowiedzi → cytowanie źródeł → ocena.

11. Co zwykle się psuje

Nieodpowiednie dzielenie na fragmenty; słabe metadane; wyszukiwanie wyłącznie na podstawie wektorów; zbyt duży kontekst; brak zestawu do oceny; brak cytatów; brak informacji o uprawnieniach dostępu; potajemna zmiana modeli do włączania informacji; brak informacji o aktualności danych.

Zakończenie

RAG w produkcji to wyszukiwanie informacji z integracją punktu końcowego LLM – a nie odwrotnie. Inwestuj w dzielenie na fragmenty, hybrydowe wyszukiwanie, filtry, cytowanie źródeł oraz ocenę; model do rozmów jest jedynie ostatnim etapem.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki ACL-negative. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki ACL-negative. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki ACL-negative. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki ACL-negative. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki ACL-negative. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw „złotych” pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki o wyniku negatywnym ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw „złotych” pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki o wyniku negatywnym ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw „złotych” pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki o wyniku negatywnym ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw „złotych” pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki o wyniku negatywnym ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw „złotych” pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki o wyniku negatywnym ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmienią się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Zachowaj zestaw złotych pytań dla każdej domeny: wyszukiwania według dokładnego ID, pytania w formie parafrazy oraz przypadki negatywne ACL. Zautomatyzuj je w środowisku CI za każdym razem, gdy zmieniają się ustawienia dzielenia na fragmenty lub embeddingu.

Ocena powinna znajdować się w tym samym repozytorium co konfiguracja dzielenia na fragmenty: gdy ktoś „tylko lekko zmienia” parametry nakładania się, system powinien zawieść się, zanim użytkownicy to zauważą.

Hybrydowe wyszukiwanie wciąż wymaga dobrych analizatorów oraz list synonimów dla żargonu specjalistycznego; same embeddingi nie pomogą w przypadku błędnie wpisanego kodu polityki.

Zdokumentuj specyfikację pola ACL na jednej stronie, aby każde nowe zadanie importu generowało te same dane, których oczekuje filtr wyświetlania.

Ocena powinna znajdować się w tym samym repozytorium co konfiguracja dzielenia na fragmenty: gdy ktoś „tylko lekko zmienia” parametry nakładania się, system powinien zawieść się, zanim użytkownicy to zauważą.