Yazılım eğitimi asistanlarında kod, API dokümanı ve ders içeriğini hibrit arama ile bulup cross-encoder reranker ile sıralamayı; recall, gecikme ve kaynak çakışmalarını ölçerek ele alır.
Yazılım Eğitimi Asistanlarında Hibrit RAG ve Reranking Tasarımı
Yazılım eğitimi için neden hibrit RAG gerekir?
Yazılım eğitimi içeriğinde sadece embedding araması kullanmak, hata kodu, sınıf adı, parametre ve sürüm etiketi gibi seyrek ama kritik tokenleri kaybettirir. Örneğin "TypeError: unhashable type: list" sorgusunda dense model semantik olarak benzer Python koleksiyon açıklamalarını getirebilir, fakat hata metninin tamamını içeren çözümü garanti etmez. OpenSearch üzerinde aynı sorguyu BM25 ve vektör aramasıyla çalıştırıp sonuçları Reciprocal Rank Fusion (RRF) ile birleştirin. RRF, skor ölçeklerini normalize etmeye ihtiyaç duymaz; her belgenin katkısı 1 / (k + rank) olduğundan BM25 skoru ile cosine similarity skorunu doğrudan toplama hatasını önler.
POST course-content/_search
{
"size": 20,
"retriever": {
"rrf": {
"retrievers": [
{ "standard": { "query": { "match": { "body": "unhashable type list" } } } },
{ "knn": {
"field": "embedding",
"query_vector_builder": {
"text_embedding": {
"model_id": ".multilingual-e5-small",
"model_text": "unhashable type list"
}
},
"k": 50,
"num_candidates": 200
}}
],
"rank_constant": 60
}
},
"query": {
"bool": {
"filter": [
{ "term": { "language": "python" } },
{ "term": { "published": true } }
]
}
}
}Filtreleri yalnızca reranking sonrasına bırakmayın. Dil, kurs, görünürlük ve tenant filtresi retrieval aşamasında uygulanmazsa ilk 50 adayın önemli kısmı yetkisiz veya ilgisiz içerik olabilir; reranker doğru dokümanı hiç görmez. OpenSearch mapping içinde `language`, `course_id` ve `published` alanlarını `keyword` tanımlayın. Çok kiracılı sistemde `tenant_id` filtresini sunucunun ürettiği zorunlu sorgu parçası yapın; istemciden gelen filtreyi tek başına güven sınırı olarak kabul etmeyin.
Kod ve doküman parçalamasında sınırları AST ile kurmak
Sabit 500 tokenlık chunklar, bir fonksiyonun imzasını başka chunkta, hata işleme bloğunu başka chunkta bırakabilir. Python içerikleri için tree-sitter veya Python `ast` modülüyle modül, sınıf ve fonksiyon sınırlarında parça üretin. Her fonksiyon chunkına modül docstringini, import listesini ve sınıf bağlamını metadata olarak ekleyin; aksi halde `Client` gibi genel bir sembolün hangi pakete ait olduğunu embedding modeli ayırt edemez.
import ast
from pathlib import Path
source = Path("src/payment/client.py").read_text()
tree = ast.parse(source)
module_imports = [
ast.get_source_segment(source, node)
for node in tree.body
if isinstance(node, (ast.Import, ast.ImportFrom))
]
chunks = []
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
code = ast.get_source_segment(source, node)
chunks.append({
"id": f"payment/client.py:{node.lineno}",
"symbol": node.name,
"kind": "function",
"body": "\n".join(module_imports + [code]),
"start_line": node.lineno,
"end_line": node.end_lineno
})AST tabanlı parçalarda yaygın hata, yalnızca fonksiyon gövdesini indeksleyip çağrılan private helper veya veri sınıfı tanımını dışarıda bırakmaktır. Bu durum özellikle dependency injection, decorator ve generic type kullanan örneklerde modelin eksik kod üretmesine yol açar. İndekse `outbound_symbols` alanı ekleyip statik analizden bulunan çağrıları saklayın; retrieval sonrasında ilk 10 adayın doğrudan bağımlılıklarını en fazla 2 hop ile genişletin. Python için `pyright --outputjson`, TypeScript için `tsc --generateTrace` çıktısı bu bağımlılık grafiğinin üretiminde kullanılabilir.
Cross-encoder reranking ile ilk aday kümesini düzeltmek
Hibrit retrieval 50 aday döndürdüğünde, ilk sıradaki sonuç hala ders başlığındaki ortak kelimeler nedeniyle yanlış olabilir. `sentence-transformers` paketindeki `CrossEncoder`, sorgu ve chunkı birlikte encode ettiği için "JWT refresh token" sorgusunda access token açıklamasını, refresh akışıyla karşılaştırarak aşağı çekebilir. Bu modeli bütün koleksiyona değil, yalnızca retrieval sonrası 20-80 adaya çalıştırın; cross-encoder maliyeti aday sayısıyla doğrusal büyür.
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
query = "FastAPI uygulamasinda refresh token nasil iptal edilir?"
candidates = retrieve_hybrid(query, limit=40)
pairs = [(query, item["body"]) for item in candidates]
scores = reranker.predict(pairs, batch_size=16, show_progress_bar=False)
ranked = sorted(
zip(candidates, scores),
key=lambda pair: float(pair[1]),
reverse=True
)[:6]Reranker girdisine ham chunk yerine `title + symbol + body` gönderin, ancak metadata anahtarlarını doğal dil olmayan uzun JSON olarak eklemeyin. Modelin token bütçesi kodun sonundaki exception handler veya örneğin çözüm kısmına ulaşmadan dolabilir. `tiktoken` ya da kullandığınız modelin tokenizerı ile 1.200 tokenlık üst sınır koyun; kodda ilk 200 ve son 800 tokenı koruyup ortadaki bölümü kesmek, yalnızca baştan kesmeye göre hata çözüm bloklarını daha sık muhafaza eder.
Gecikme ve retrieval kalitesini önce-sonra ölçmek
Hibrit RAG değişikliğini yalnızca sohbet beğenisiyle değerlendirmeyin. En az 200 gerçek sorgudan oluşan, her sorgu için kabul edilen chunk kimlikleri bulunan bir golden set hazırlayın. `Recall@20`, `MRR@10`, p50 ve p95 retrieval gecikmesini ayrı kaydedin. Reranker eklemek Recall@20 değerini değiştirmez, çünkü aday havuzunu değiştirmez; buna karşılık MRR@10 artmalı ve p95 toplam gecikmeye model çıkarım süresi eklenmelidir. Bu ayrım, yanlışlıkla retrieval iyileşti sonucu çıkarılmasını engeller.
from ranx import Qrels, Run, evaluate
qrels = Qrels({
"q-17": {"chunk-42": 1, "chunk-91": 1},
"q-18": {"chunk-10": 1}
})
run = Run({
"q-17": {"chunk-42": 0.91, "chunk-12": 0.88},
"q-18": {"chunk-10": 0.77, "chunk-33": 0.68}
})
print(evaluate(qrels, run, ["recall@20", "mrr@10", "ndcg@10"]))OpenTelemetry ile `embed`, `opensearch.search`, `rerank` ve `llm.generate` spanlarını ayrı isimlerle yayınlayın; Grafana Tempo veya Jaeger ekranında toplam sürenin nerede harcandığını böylece ayırabilirsiniz. Karşılaştırmada aynı golden seti, aynı filtreleri ve aynı `k=50` aday havuzunu kullanın. Örneğin baseline BM25 için p95 85 ms ve MRR@10 0.61, hibrit artı reranker için p95 310 ms ve MRR@10 0.79 ise, p95 bütçesi 400 ms olan interaktif akışta değişiklik kabul edilebilir. p95 bütçesi 200 ms ise rerankerı yalnızca düşük güvenli sorgularda çalıştırın; örneğin ilk iki RRF sonucu arasındaki skor farkı 0.015 altındaysa devreye alın.
Kaynak çakışması, güncellik ve yanıt bağlama kuralları
Bir ders notu eski API örneği içerirken resmi doküman yeni imza içerebilir. İki chunkı modele eşit önemde vermek, özellikle kod üretiminde kaldırılmış parametrelerin tekrar önerilmesine neden olur. İndekste `source_rank`, `updated_at` ve `content_hash` alanları tutun; retrieval sonrası aynı sembol için hash veya canonical URL bazında yinelenen chunkları kaldırın. Ardından resmi referanslara `source_rank=100`, eğitmen notlarına `source_rank=50` gibi bir öncelik verip RRF sonucunda eşitlik bozucu olarak kullanın.
Yanıtı üretirken her öneriyi kaynak chunk kimliğiyle bağlayın ve modelden desteklenmeyen bir API imzası uydurmamasını isteyin. Uygulama katmanında kaynak sayısı 2 altındaysa veya ilk kaynağın rerank skoru belirlediğiniz kalibrasyon eşiğinin altındaysa kod bloğu üretmek yerine arama kapsamını daraltan bir soru sorun. Bu kontrol için yanıt JSONunda `claims[].citation_ids` şeması kullanın ve API katmanında citation kimliklerinin gerçekten retrieval sonucunda yer aldığını doğrulayın; yalnızca prompt talimatı bu garantiyi vermez.
TechCareer İlgili Eğitimler
Sık Sorulan Sorular
Yazılım eğitimi RAG sisteminde BM25 ve vektör araması nasıl birleştirilir?
OpenSearch RRF retriever ile BM25 ve kNN sonuçlarını birleştirin. Her iki retriever için 50 aday alın, `rank_constant` değerini 60 ile başlatın ve golden set üzerinde `MRR@10` ölçün. BM25 ve cosine skorlarını doğrudan toplamayın; skor aralıkları ve dağılımları aynı değildir.
Yazılım eğitimi asistanında reranker kaç sonuç üzerinde çalışmalı?
Başlangıç için hibrit retrievaldan gelen ilk 40 adayı `CrossEncoder` ile sıralayın ve ilk 6 sonucu bağlama verin. p95 gecikmesini OpenTelemetry spanlarıyla ölçün. GPU veya CPU kapasitesine göre 20, 40 ve 80 aday için `MRR@10` ile p95 değerini karşılaştırarak sınırı seçin.
Yazılım eğitimi içeriklerinde kod chunk boyutu kaç token olmalı?
Sabit token sayısı yerine tree-sitter veya AST ile fonksiyon ve sınıf sınırlarını kullanın. Bağlama girecek her chunk için 1.200 token üst sınırı uygulayın, importları ve sembol adını koruyun. Büyük fonksiyonlarda ilk 200 ile son 800 tokenı saklamak, exception ve return bloklarının kaybolmasını azaltır.
RAG retrieval kalitesi üretimde hangi metriklerle izlenmeli?
Etiketli golden set üzerinde `Recall@20`, `MRR@10` ve `nDCG@10` hesaplayın. Üretimde ise OpenTelemetry ile retrieval, reranking ve generation sürelerini ayırıp p50 ve p95 değerlerini izleyin. Reranker eklenince Recall sabit kalıp MRR artıyorsa, değişiklik sıralamayı iyileştiriyor demektir.
AI / LLM Discovery
Bu makale Opendart Akademi Yapay Zeka eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.



