Kod Kaynaklarından RAG Nasıl Yapılır?

Cahit Barkin Ozer
30 min readDec 5, 2024

--

Continue.dev, Cursor, Tabby, Cody ve Qodo’daki kod dosya ve repolarından RAG yapmaya dair güncel yöntemleri derledim.

Tüm proje reponuz LLM’e sığmayacaktır (veya doğruluğu olumsuz etkileyecektir) yukarıdaki görseldeki gibi. Bu yüzden kod’larınız ile RAG yapmaya ihtiyacınız var.

Indexing kod repolarının embedding model ile vektörlere çeviriliip kaydedilmesi kastedilirken kod rag ile repo’nun içinde bahsedilen kod parçasının bu index’lenen vektörler arasında vektör veritabanında aratılması ile de yapılabilir veya açık olan scriptler arasından en alakalı parçaların toplanıp getirilmesi ile gerçek zamanlı da gerçekleştirilebilir.

Özet

Özetlersek Continue.dev, Cursor, Tabby, Cody ve Qodo (Codium)’un Kod RAG yapılarını araştırdım. İnsanlar tarafından kapalı kaynaklı Cursor en iyisi olarak görülüyor, Continue.dev ve Tabby açık kaynaklı Cursor olmaya çalışıyor ancak Continue.dev daha çok beğeniliyor.

YZ asistanının sohbet kısmına @Codebase koyup tüm repo bağlamında RAG veya @File ile dosya bağlamında RAG yapabiliyorsunuz. Kullanılan taglerin isimleri bile hep aynı o denli lideri takip etme durumları söz konusu. Cursor 15–20 saniye, onu takip eden araçlar 20–30 saniyede cevap veriyorlarmış (TPS birimi verilmemişti yorum maalesef).

Hepsi tree-sitter diye koddan ağaç oluşturan bir aracı kullanıyorlar, çoğu programlama dil destekleniyor ve kendi sorgu dili var (Cursor tree-sitter ile koddan graph oluşturuyormuş). Projelerdeki sınıf ve fonksiyon referansları soyut sözdizim ağacı AST analizine dayalı basit bir yığın tabanlı yöntemle belirlenip metaveriler olarak saklanıyor. Bu bilgiler vektör veritabanından alınan gömme vektörleriyle birleştirip dil modeline daha zengin bir bağlam sağlanıyor. Erişim aşamasında da vektör araması tek başına başarılı değil BM25, reranking, Hyde ile desteklenince kullanışlı hale geliyormuş.

Gömme modeli seçiminde bu tablo adreslenmiş: https://huggingface.co/spaces/mteb/leaderboard

Codium bir paylaşımında CST kullandığını ancak yetersiz kaldığını söylüyor. Codium LLM’leri kullanarak kodlara yorum satırı eklediklerini sonra bu yorumları gömmeye çevirerek kodu bilgi tabanı olarak kullandıklarını söylüyorlar. RAG’in ikincil kısmı olan erişim kısmında reranking yaptıklarını söylüyorlar (önce en alakalı repolar sonra en alakalı sınıflar gibi). Codium adını Qodo yapmış ve Repo agent’a odaklanmaya karar vermis gibi gözüküyor.

Sourcegraph şirketinin amacı devasa repoları veritabanı şekilinde kullanıma açabilmekmiş (100.000+ repo). Sourcegraph’ın Cody ürünü var ve büyük repolarda embedding kullanmak maaliyetli olduğu için şimdilik vazgeçmişler ve yazılım tabanlı bir yaklaşıma odaklanmışlar.

CodeRagBench diye bir benchmark da buldum.

Hadi şimdi derinlemesine bakalım bulduklarıma.

1. Cursor

Cursor’un Kod RAG ile ilgili “@codebase” özelliği vardır. [1]

“@CodeBase”

Cursor Chat, @Codebase aracılığıyla kullanılacak en önemli kod parçalarını bulana kadar aşağıdaki adımları izler.[1]

  • Toplama: Önemli dosyalar/kod parçaları için kod tabanını tarama.[1]
  • Yeniden sıralama: Bağlam öğelerini sorguya göre yeniden sıralama.[1]
  • Mantık yürütme: Bağlamı kullanma planı üzerinde düşünme.[1]
  • Üretme: Yanıt üretme.[1]

Cursor’ın Chat CodeBase’i üç şekilde etkileşime girer:

  1. Varsayılan Kod Tabanı Sohbeti: Kod tabanı dizine eklenmemişse, Cursor Chat ilgili kodu bulmak için arama sorgularını kullanır. Daha iyi doğruluk için, gömme tabanlı bir arama önerilir.[1]
  2. Gömme Araması: Kod tabanı dizine eklendiğinde, Cursor Chat doğru yanıtlar oluşturmak için gömmeleri kullanır. Ctrl + Enter’a basmak, konuşmaya dahil edilecek ilgili kod parçacıkları için dizinlenmiş kod tabanını tarar.[1]
  3. Gelişmiş Kod Tabanı Araması: @Codebase’i kullanmak, kod tabanında daha ayrıntılı ve kesin bir arama yapılmasını sağlar.[1]

Daha iyi sonuçlar için dizinleme (indeksleme) ve gömme tabanlı arama teşvik edilmektedir.[1]

Daha iyi ve daha doğru kod tabanı yanıtları için @codebase veya Ctrl + Enter kullanarak kod tabanınızı dizinleyebilirsiniz. Perde arkasında, Cursor kod tabanınızdaki her dosya için gömmeleri hesaplar ve bunları kod tabanı yanıtlarınızın doğruluğunu artırmak için kullanır. Kod tabanı dizininiz en son kod tabanı değişikliklerinizle otomatik olarak senkronize olur. Varsayılan olarak, Cursor kod tabanınızdaki tüm dosyaları dizinler.[1]

2. Continue.dev

Continue.dev’in ayrıca bir “@Codebase” etiketi de vardır.[2]

Continue.dev kod tabanınızı dizinler, böylece daha sonra çalışma alanınız boyunca en alakalı bağlamı otomatik olarak çekebilir. Bu, gömmelere dayalı erişim ve anahtar sözcük aramasının bir kombinasyonu yoluyla yapılır. Varsayılan olarak, tüm gömmeler transformers.js kullanılarak lokal olarak hesaplanır ve ~/.continue/index’te lokal olarak depolanır. [2]

Uyarı: Şu anda, transformers.js JetBrains IDE’lerinde kullanılamaz. Ancak, buradaki listeden farklı bir gömme modeli seçebilirsiniz: [https://docs.continue.dev/customize/model-types/embeddings]. [2]

Şu anda, kod tabanına erişme özelliği “CodeBase” ve “Folder” bağlam sağlayıcıları ile mevcuttur. Bunları girdi kutusuna @Codebase veya @Folder yazarak ve ardından bir soru sorarak kullanabilirsiniz. Girdi kutusunun içerikleri, ilgili dosyaları belirlemek için kod tabanının (veya klasörün) geri kalanındaki gömmelerle karşılaştırılacaktır. Repoya dayalı bir soru sorabilir veya kod üretebilirsiniz. Ayrıca belirli bir klasörü sormak için “@Folder” etiketini de kullanabilirsiniz.[2]

Dikkat: Kod tabanı ve Klasör özellikleri, LLM’in kod tabanınızdaki her dosyayı görmesini veya yeniden düzenleme yapmasını istediğiniz durumlarda yardımcı olamaz; örneğin aşağıdaki sorular bu özellik için uygun değildir: “X fonksiyonunun çağrıldığı her yeri bul”, “Kod tabanını incele ve herhangi bir yazım hatası bul”, “X fonksiyonuna yeni bir parametre ekle ve kullanımları güncelle”. Bu senaryolar için bir repo agent tercih edilebilir.[2]

Kod tabanı bağlam sağlayıcısının davranışını konfigüre etmenize izin veren birkaç seçenek vardır. Bunlar config.json’da ayarlanabilir ve kod tabanı, belgeler ve klasör bağlam sağlayıcıları için aynıdır:

  • nRetrieve: Vektör veritabanından başlangıçta alınacak sonuç sayısı (varsayılan: 25) [2]
  • nFinal: Yeniden sıralamadan sonra kullanılacak nihai sonuç sayısı (varsayılan: 5) [2]
  • useReranking: nRetrieve sonuçlarının ilk seçimine izin verecek olan yeniden sıralamanın kullanılıp kullanılmayacağı, ardından en iyi nFinal sonuçlarını seçmek için bir LLM’nin kullanılıp kullanılmayacağı (varsayılan: True) [2]

Repo Haritası (Repository Map)

Claude 3, Llama 3.1/3.2, Gemini 1.5 ve GPT-4o ailelerindeki modeller, kod tabanı alımı sırasında otomatik olarak bir repo haritası [https://docs.continue.dev/customize/context-providers#repository-map] kullanırlar; bu da modelin kod tabanınızın yapısını anlamasına ve soruları yanıtlamak için kullanmasına olanak tanır. Repo Haritası Bağlam Sağlayıcısı, dosyaların bir listesini ve bu dosyalardaki en üst düzey sınıfların, fonksiyonların ve metodların çağrı imzalarını sağlar. Bu, modelin belirli bir kod parçasının kod tabanının geri kalanıyla nasıl ilişkili olduğunu daha iyi anlamasına yardımcı olur. Şu anda, repo haritası yalnızca kod tabanındaki dosya yollarını içerir. [2]

Tüm bağlam sağlayıcılarının listesini burada bulabilirsiniz: [https://docs.continue.dev/customize/context-providers#repository-map]

Continue’nun Özel Kod Rag Önerisi

Continue.dev, @Codebase ile birlikte hazır gelirken, vektör veritabanınızı kurmak ve özel bir erişim destekli üretim (RAG: Retrieval Augmented Generation) sistemi oluşturmak isteyebilirsiniz. Bu, lokal olarak mevcut olmayan koda erişmenize, kodu tüm kullanıcılar arasında tek seferde dizinlemenize veya özel mantık eklemenize olanak tanır. Bu kılavuzda, bunu oluşturmak için gereken adımlarda size yol göstereceğiz. [3]

Adım 1: Bir gömme modeli seçin

Gömme modeli seçerken kod ile eğitilmiş yüksek başarılı bir model seçmelisiniz. Bunun için şu adrese bakabilirsiniz: [https://huggingface.co/spaces/mteb/leaderboard]

Adım 2: Bir vektör veritabanı seçin

Çoğu vektör veritabanı büyük kod tabanlarını performanslı bir şekilde işleyebildiğinden, kurulum ve deneme kolaylığı açısından birini seçmenizi öneririz. LanceDB bunun için iyi bir seçimdir çünkü hem Python hem de Node.js için kütüphanelerle bellek içerisinde basitçe çalışabilir. Bu, projenin başında altyapı kurmak yerine kod yazmaya odaklanabileceğiniz anlamına gelir. Zaten bir vektör veritabanı seçtiyseniz, LanceDB yerine bunu kullanmanızda hiçbir problem olmayacaktır. [3]

Adım 3: “Parçalara ayırma” (chunking) stratejisini seçin

Çoğu gömme modeli aynı anda yalnızca sınırlı miktarda metni işleyebilir. Bunu aşmak için kodumuzu daha küçük parçalara “parçalarız” (chunking). [3]

Gömme modeli seçerken bağlam uzunluğu önemlidir. Örneğin voyage-code-2'yi kullanırsanız, çoğu dosyanın sığması için yeterli olan 16.000 tokenli maksimum bağlam uzunluğuna sahiptir. Bu, başlangıçta, limiti aşan dosyaların aştığı yerden sonrasını almama gibi daha saf bir stratejiyle idare edebileceğiniz anlamına gelir. En kolaydan en kapsamlıya doğru, kullanabileceğiniz 3 parçalama stratejisi şunlardır:

  1. Bağlam uzunluğunu aştığında dosyayı kesin: Bu şekilde, dosya başına her zaman 1 parçanız olacaktır. [3]
  2. Dosyayı sabit uzunlukta parçalara bölün: Dosyanın en üstünden başlayarak, mevcut parçanıza sınıra ulaşana kadar satırlar ekleyin, ardından diğer parçayı başlatın. [3]
  3. Tekrarlayan, soyut sözdizimi ağacı (AST: abstract syntax tree) tabanlı bir strateji kullanın: Bu en kesin, ancak en karmaşık olanıdır. Çoğu durumda, (1) veya (2)’yi kullanarak yüksek kaliteli sonuçlar elde edebilirsiniz, ancak denemek isterseniz Continue.dev chunker [https://github.com/continuedev/continue/blob/main/core/indexing/chunk/code.ts] veya LlamaIndex’te [https://docs.llamaindex.ai/en/stable/api_reference/node_parsers/code/] bir referans örnek bulabilirsiniz. [3]

Bu kılavuzda her zamanki gibi, minimum çaba ile maksimum getiriyi elde edeceğiniz yöntem ile başlamanızı öneriyoruz. [3]

Adım 4: Bir dizinleme betiği (indexing script) oluşturun

Kodunuzu geri alınabilir bir formatta vektör veritabanına ekleyeceğimiz dizinleme üç adımda gerçekleşir:

  1. Parçalama. [3]
  2. Gömmelerin oluşturulması. [3]
  3. Vektör veritabanına ekleme. [3]

LanceDB ile, belgelerinde gösterildiği gibi 2. ve 3. adımları aynı anda yapabiliriz: [https://lancedb.github.io/lancedb/basic/#using-the-embedding-api]. Örneğin Voyage AI kullanıyorsanız, şu şekilde yapılandırılır: [3]

from lancedb.pydantic import LanceModel, Vector
from lancedb.embeddings import get_registry

db = lancedb.connect("/tmp/db")
func = get_registry().get("openai").create(
name="voyage-code-2",
base_url="https://api.voyageai.com/v1/",
api_key=os.environ["VOYAGE_API_KEY"],
)

class CodeChunks(LanceModel):
filename: str
text: str = func.SourceField()
# 1536, `voyage-code-2` modelinin gömme boyutudur.
vector: Vector(1536) = func.VectorField()

table = db.create_table("code_chunks", schema=CodeChunks, mode="overwrite")
table.add([
{"text": "print('hello world!')", filename: "hello.py"},
{"text": "print('goodbye world!')", filename: "goodbye.py"}
])

query = "greetings"
actual = table.search(query).limit(1).to_pydantic(CodeChunks)[0]
print(actual.text)

Uyarı: Birden fazla reponun indeksini oluşturuyorsanız, bunları ayrı “tablolarda” (LanceDB tarafından kullanılan terminoloji) veya “koleksiyonlarda” (bazı diğer vektör veritabanları tarafından kullanılan terminoloji ile) depolamak en iyisidir. Bir “repo” alanı ekleme ve ardından buna göre filtreleme alternatifi daha az performanslıdır. [3]

Hangi veritabanını veya modeli seçerseniz seçin, betiğiniz dizinlemek istediğiniz tüm dosyalar üzerinde yineleme yapmalı, bunları parçalara ayırmalı, her parça için gömeler oluşturmalı ve ardından tüm parçaları vektör veritabanınıza eklemelidir. [3]

Adım 5: Dizin oluşturma betiğinizi çalıştırın

Uyarı: Mükemmel bir üretim sürümünde, bir dosya değiştiğinde, o dosya ve başka hiçbir şey otomatik olarak yeniden dizine eklenmesin diye “otomatik, artımlı dizinleme” oluşturmak istersiniz. Bunun mükemmel şekilde güncel gömmeler oluşturma ve daha düşük maliyet avantajları vardır. Bununla birlikte, bunu denemeden önce işlem hattını oluşturmanızı ve test etmenizi şiddetle öneririz. Kod tabanınız sıklıkla tamamen yeniden yazılmıyorsa, dizinin tamamen yenilenmesi yeterli ve makul derecede ucuz olacaktır. [3]

Bu noktada, dizinleme betiğinizi yazdınız ve vektör veritabanınızdan sorgular yapabileceğinizi test ettiniz. Şimdi, dizinleme betiğini ne zaman çalıştıracağınıza dair bir plan isteyeceksiniz. Başlangıçta, muhtemelen elle çalıştırmalısınız. Özel RAG’nizin değer sağladığından ve uzun vadede hazır olduğundan emin olduğunuzda, onu periyodik olarak çalıştırmak için bir cron job ayarlayabilirsiniz. Kod tabanları kısa zaman dilimlerinde büyük ölçüde değişmediğinden, günde bir kereden fazla yeniden dizinleme yapmayacaksınızdır. Haftada veya ayda bir kez muhtemelen yeterli olacaktır. [3]

Adım 6: Sunucunuzu kurun

Continue.dev uzantısının özel RAG sisteminize erişebilmesi için bir sunucu kurmanız gerekir. Bu sunucu, uzantıdan bir sorgu almak, vektör veritabanını sorgulamak ve sonuçları Continue tarafından beklenen biçimde döndürmekten sorumludur. Aşağıda Continue.dev’in “HTTP” bağlam sağlayıcısından gelen istekleri işleyebilen FastAPI kullanan bir örnek uygulaması. [3]

"""
Bu, "http" bağlam sağlayıcısıyla kullanılabilen bir sunucunun örneğidir.
"""

from fastapi import FastAPI
from pydantic import BaseModel


class ContextProviderInput(BaseModel):
query: str
fullInput: str


app = FastAPI()


@app.post("/retrieve")
async def create_item(item: ContextProviderInput):
results = [] # TODO: Vektör veritabanınızı burada sorgulayın.

# Continue.dev tarafından beklenen "bağlam öğesi" biçimini oluşturun
context_items = []
for result in results:
context_items.append({
"name": result.filename,
"description": result.filename,
"content": result.text,
})

return context_items

Sunucunuzu kurduktan sonra, config.json dosyasındaki contextProviders dizisine “HTTP” bağlam sağlayıcısını ekleyerek kullanmaya devam etmeyi yapılandırabilirsiniz: [3]

{
"name": "http",
"params": {
"url": "https://myserver.com/retrieve",
"title": "http",
"description": "Custom HTTP Context Provider",
"displayTitle": "My Custom Context"
}
}

Adım 7 (Bonus): Yeniden sıralamayı (reranking) ayarlayın

Sonuçlarınızın kalitesini artırmak istiyorsanız, harika bir ilk adım yeniden sıralama eklemektir. Bu, vektör veritabanından daha büyük bir başlangıç ​​sonuç havuzunu almayı ve ardından bunları en alakalıdan en az alakalıya doğru sıralamak için bir yeniden sıralama modeli kullanmayı içerir. Bu işe yarar çünkü yeniden sıralama modeli, en iyi sonuçların küçük kümesinde biraz daha pahalı bir hesaplama yapabilir ve böylece veritabanındaki tüm girdileri aramak zorunda olan benzerlik aramasından daha doğru bir sıralama sağlayabilir. [3]

Örneğin her sorgu için toplam 10 sonuç döndürmek istiyorsanız, o zaman şunları yapmalısınız:

  1. Benzerlik araması kullanarak vektör veritabanından ~50 sonuç alın. [3]
  2. Bu 50 sonucun tamamını, her biri için alaka puanları almak üzere sorguyla birlikte yeniden sıralama API’sine gönderin. [3]
  3. Sonuçları alaka puanına göre sıralayın ve ilk 10'u döndürün. [3]

Ayrıca continue.dev’e özel bağlam sağlayıcınızı da ekleyebilirsiniz: [https://docs.continue.dev/customize/tutorials/build-your-own-context-provider]

3. Qodo (Eski Adıyla Codium)

Bu bölümde, Qodo’nun (eski adıyla Codium) sınırlı bağlam pencereleri ve büyük, karmaşık kod tabanları olan LLM’ler arasındaki boşluğu kapatmak ve kod kalitesini ve bütünlüğünü ön planda tutan üretken bir AI kodlama platformu oluşturmak için RAG’a nasıl yaklaştığını paylaşacağım. [4]
RAG kabaca iki bölüme ayrılabilir: bilgi tabanını (bizim durumumuzda kod tabanını) dizinleme ve erişme.

Sürekli değişen bir üretim kod tabanı için RAG ile dizinleme tek seferlik veya periyodik bir iş değildir. Sürekli olarak yeni bir dizini korumak için sağlam bir işlem hattına ihtiyaç vardır. [4]

Aşağıdaki diyagram, dosyaların parçalara ayrılmak üzere uygun ayırıcıya yönlendirildiği, parçaların doğal dil açıklamalarıyla geliştirildiği ve her parça için vektör gömmelerinin vektör veritabanına kaydedilmeden önce oluşturulduğu erişim işlem hattımızı göstermektedir. [4]

Parçalara Ayırma (Chunking)

Parçalama, doğal dil metni için nispeten basittir, paragraflar (ve cümleler) anlamsal olarak anlamlı bölümler oluşturmak için belirgin sınır noktaları sağlar. Ancak, saf parçalama yöntemleri, kodun anlamlı bölümlerini doğru bir şekilde belirlemede zorluk çeker ve bu da sınır tanımlama ve alakasız veya eksik bilgilerin eklenmesiyle ilgili sorunlara yol açar. Bir LLM’e geçersiz veya eksik kod bölümleri sağlamanın, yardımcı olmaktan ziyade performansı olumsuz etkileyebileceğini ve halüsinasyonları artırabileceğini gördük.[4]

Sweep AI ekibi, geçen yıl kod parçalama stratejilerini ayrıntılı olarak açıklayan harika bir blog yazısı [https://docs.sweep.dev/blogs/chunking-2m-files] yayınladı. Tutarlı bölümler oluşturmak için somut bir sözdizimi ağacı (CST) ayrıştırıcısı kullanma yöntemlerini açık kaynaklı hale getirdiler ve algoritmaları o zamandan beri LlamaIndex tarafından benimsendi. [4]

Saf Parçaya Ayırmanın Zorlukları:

  • Basit parçalama yöntemleri genellikle anlamlı kod parçaları oluşturmada başarısız olur ve bu da eksik veya alakasız parçalara yol açar. [4]
  • Dil modellerine sağlanan eksik kod, performansı düşürür ve halüsinasyonları artırır. [4]

Sweep AI’ın Yaklaşımı:

  • Sweep AI, daha iyi parçalama için Somut Sözdizimi Ağacı (CST: Concrete Syntax Tree) ayrıştırıcısı kullanan bir yöntem geliştirdi. [4]
  • Etkili olmasına rağmen, tam bağlamı yakalama (örneğin, eksik içe aktarmalar veya sınıf tanımları), büyük yapıları işleme ve kurumsal ölçekli kod tabanlarındaki zorlukları ele alma konusunda zorluk çekti. [4]

Geliştirilmiş Parçalama Stratejileri:

  • Dile Özel Statik Analiz: Kod düğümlerinin yinelemeli bölünmesi, parçaların yapısal sınırlara saygı göstermesini ve ilgili öğeleri bir arada tutmasını sağlar (örneğin, aynı parçadaki “if else” ifadeleri). [4]
  • Bağlam Koruma: İçe aktarma (import) ve sınıf tanımları gibi kritik bağlam, yöntemlerin veya yapıların tam olarak anlaşılmasını sağlamak için parçalarda tutulur. [4]
  • Esnek Parça Boyutları: Parçalar küçük tutulur (örneğin, ~500 karakter) ancak gerekli bağlamı içerecek kadar da esnektir. Daha büyük sınıflar, her biri temel bağlamı içeren daha küçük birimlere bölünür. [4]

Dosya Türüne Özel Stratejiler:

  • Dosya türlerine göre farklı stratejiler uygulanır (örneğin, OpenAPI/Swagger özellikleri satırlar yerine uç noktalara göre parçalara ayrılır ve böylece her parçanın eksiksiz uç nokta ayrıntılarını içermesi sağlanır). [4]

Bu stratejiler, AI modelleri için kod parçalandırmayı optimize ederek bütünlüğü, bağlamsal bütünlüğü ve anlamsal uygunluğu garanti eder. [4]

Doğal Dil Açıklamalarıyla Gömmeleri Geliştirme

Kod gömmeleri genellikle kodun anlamsal anlamını yakalamaz, özellikle de doğal dil sorguları için. Her kod parçası için doğal dil açıklamaları oluşturmak için LLM’leri kullanırız. Bu açıklamalar daha sonra kodun yanına yerleştirilerek doğal dil sorguları için ilgili koda erişme yeteneğimizi artırır. [4]

Örneğin, AI platformları genelinde bitirme nedenlerini standartlaştıran “map_finish_reason” fonksiyonu şu şekilde tanımlanmaktadır:

Çeşitli AI platformlarından bitiş nedenlerini standartlaştıran ve platforma özgü nedenleri ‘dur’, ‘uzunluk’ ve ‘içerik_filtresi’ gibi yaygın terimlere eşleyen Python fonksiyonu.”[4]

Bu tür açıklamaları kodla eşleştirerek, gömmeler kod semantiği ile doğal dil sorguları arasındaki boşluğu kapatmada daha iyi hale gelir ve kod anlamını etkili bir şekilde yakalamada sıklıkla başarısız olan standart kod gömmelerinin sınırlamalarını ele alır. Bu yaklaşım, doğal dil istemleriyle kod tabanlarını sorgulamayı kolaylaştırır.[4]

Gelişmiş Alma ve Sıralama

Basit vektör benzerliği araması, özellikle milyonlarca dizinlenmiş parçaya sahip büyük, çeşitli kod tabanlarında, genellikle alakasız veya bağlam dışı kod parçaları getirir. İki aşamalı bir alma süreci uyguladık. İlk olarak, vektör repomuzdan ilk erişim işlemini gerçekleştiririz. Ardından, sonuçları belirli görev veya sorguya olan alakalarına göre filtrelemek ve sıralamak için bir LLM kullanırız.[4]

Bir geliştirici “API oran sınırlamasının nasıl ele alınacağını” sorgularsa, sistemimiz önce API çağrıları ve hata işlemeyle ilgili birkaç kod parçacığı alabilir. LLM daha sonra bu parçacıkları sorgu bağlamında analiz ederek, özellikle oran sınırlama mantığıyla ilgilenenleri daha üst sıralara yerleştirir ve alakasız sonuçları atar.[4]

Kurumsal Repolar için RAG’ı Ölçeklendirme

Repoların sayısı binlere ulaştığında, her sorgu için tüm repolarda arama yapıldığında arama gürültülü ve verimsiz hale gelir. Tek tek kod parçalarına dalmadan önce arama alanını daraltmak için repo düzeyinde filtreleme stratejileri geliştiriyoruz. Bu, bir kuruluşun en iyi uygulamalarla uyumlu ve iyi organize edilmiş kod içeren belirli repoları belirlemesine olanak tanıyan “altın repolar” kavramını içerir. Belirli bir mikro hizmet mimarisi modeliyle ilgili bir sorgu için, sistemimiz öncelikle meta verilere ve üst düzey içerik analizine dayanarak ilgili bilgileri içerme olasılığı en yüksek ilk 5–10 repoyu belirleyebilir. Daha sonra bu repolar içinde ayrıntılı kod araması gerçekleştirerek gürültüyü önemli ölçüde azaltır ve alaka düzeyini iyileştirir.[4]

RAG Karşılaştırması ve Değerlendirmesi

Standartlaştırılmış ölçütlerin eksikliği nedeniyle RAG sistemlerinin kod performansını değerlendirmek zordur. Kurumsal müşterilerimizden gelen gerçek dünya kullanım verileriyle otomatik ölçümleri birleştiren çok yönlü bir değerlendirme yaklaşımı geliştirdik. Alakalılık puanlaması (geliştiricilerin alınan kod parçacıklarını ne sıklıkla kullandıkları), doğruluk ölçümleri (kod tamamlama görevleri için) ve verimlilik ölçümlerinin (yanıt süresi, kaynak kullanımı) bir kombinasyonunu kullanıyoruz. Ayrıca geri bildirim ve gerçek dünya performans verilerini toplamak için kurumsal müşterilerimizle yakın bir şekilde iş birliği yapıyoruz.[4]

4. Açık Kaynaklı Projeler

LanceDB’nin Koddan RAG Makalesi

Sankalp Shubham harika bir Code RAG eğitimi paylaşmıştır, bu kısımda onu inceleyceğiz. [5] [6]

Demo:

Sankalp yukarıdaki videodakileri yapan CodeQA adlı bir proje yapmıştır. Cursor’ın @codebase özelliği gibi, CodeQA de kod tabanı genelindeki sorgularınıza ilgili kod parçacıkları, dosya adları ve referanslarla yanıt verebilir. Java, Python, Rust ve Javascript’i destekler ve diğer dillere kolayca genişletilebilir. [5]

Projesinin adresi: [https://github.com/sankalp1999/code_qa?ref=blog.lancedb.com]

Projesinin iki önemli kısmı vardır: Kod tabanının dizinlenmesi ve erişim hattı. İlk kısımda, tree-sitter projesinin yardımıyla kod tabanı dizinleme ve LanceDB yardımıyla gömme araması (embedding search) hakkındadır. [5]

Kod Tabanı Dizinleme
Kod Bağlamı Erişimi

Hedef Tanımı

Amaç, aşağıdaki yetenekleri sağlayarak kullanıcının kod tabanını anlamasına ve doğru kod üretmesine yardımcı olacak bir uygulama oluşturmaktır:

  1. Kullanıcı “@codebase” anahtar kelimesini belirttiğinde, bir kod tabanına ilişkin doğal dil sorularını doğru ve ilgili bilgilerle yanıtlayın. [5]
  2. Bağlamsal kod parçacıkları sağlayın ve aşağıdakiler de dahil olmak üzere kod kullanım modellerini analiz edin:
  • Belirli sınıflar ve yöntemler nasıl kullanılır [5]
  • Sınıf oluşturucuları ve uygulamaları hakkında ayrıntılar [5]

3. Kod referanslarını takip edin ve kullanın:

  • Kod öğelerinin kod tabanında nerede kullanıldığını belirleyin [5]
  • Tüm yanıtlar için kaynak referansları sağlayın [5]

4. Toplanan bağlamı, kod oluşturma ve önerilerde yardımcı olmak için kullanın. [5]

Sorular basit (tek atım (one shot) ) ile karmaşık (çok atım (few shot)) arasında değişebilir. Tek atımlı sorular tek bir kaynaktan alınan bilgiler kullanılarak cevaplanabilirken, çok atımlı sorular LLM’nin eksiksiz bir cevap sağlamak için birden fazla kaynaktan bilgi toplayıp sentezlemesini gerektirir. [5]

Örnekler:

  • “Bu git reposu ne hakkında?” [5]
  • “Belirli bir yöntem nasıl çalışır?” → Burada yöntemin tam adını belirtmeyebilirsiniz. [5]
  • “Hangi yöntemler xyz şeylerini yapar?” → Sorgunuzdan ilgili yöntem/sınıf adlarını tanımlaması gerekir. [5]
  • Daha karmaşık olabilirler, örneğin “EncoderClass ve DecoderClass arasındaki bağlantı nedir?” → Sistemin birden fazla kaynaktan bağlam toplayarak yanıt vermesi gerekir (çok atımlı soru yanıtlama). [5]

Neden LLM’leri doğrudan kullanamıyorum?

Bazı LLM’ler daha geniş bağlam pencerelerini destekler ancak bu modeller ve kullanım şekli maliyetlidir, cevapların işlenmesi daha uzun sürer ve alacağınız cevapların doğruluğu azalabilir. [5]

Parçalara Ayırma

Gömme modelleri yalnızca belirli bir uzunluğa kadar metni işleyebilir (dizi uzunluğu olarak adlandırılır ve genellikle 1024 ila 8192 token arasındadır). Bu nedenle, bir blog yazısı gibi uzun bir metin parçamız olduğunda, onu daha küçük, anlamlı parçalara bölmemiz gerekir. Bu, benzer içerikleri daha doğru bir şekilde eşleştirmemize ve anlamı bozulmadan tutmamıza yardımcı olur. [5]

Metni şu şekilde yönetilebilir parçalara ayırıyoruz:

  • Gömme modelinin işleyebileceği kadar küçük mü? [5]
  • Yine de, kendi başlarına okunduğunda mantıklı mı? [5]
  • Yararlı olmak için yeterli bağlamı koruyun. [5]

Bu bölmeyi yapmanın birkaç yolu vardır:

  • Sabit boyutlu parçalama (eşit boyutlu parçalara bölme) [5]
  • İçeriğe uyum sağlayan akıllı ayırıcılar kullanın (RecursiveCharacterTextSplitter gibi) [5]

Unutulmaması gereken önemli bir şey, farklı içerik türlerinin farklı bölme yaklaşımlarına ihtiyaç duymasıdır. Bir blog yazısı, biraz kod ve teknik dokümantasyonun hepsinin kendi yapısı vardır ve gömme modellerimizden iyi sonuçlar almak için bu yapıyı korumamız gerekir. Kod‘a özel parçalama stratejilerini tartışmaya doğru ilerledikçe, kod yapısını korumanın daha da önemli hale geldiği bu parçalama ve gömme anlayışı çok önemlidir. [5]

Kod Tabanını Parçalama

Sözdizimi Düzeyinde Parçalama

Kodların benzersiz parçalama zorlukları vardır:

  • Hiyerarşik yapılar nasıl ele alınır? [5]
  • Dile özgü yapılar (yapıcılar, sınıf) nasıl çıkarılır? [5]
  • Dilden bağımsız nasıl yapılır? Farklı dillerin farklı sözdizimleri vardır. [5]

İşte sözdizimi düzeyinde bölümlemenin devreye girdiği yer burasıdır. [5]

  • Kodu soyut sözdizimi ağacı (AST) gösterimine ayrıştırabiliriz [5]
  • AST’yi dolaşın ve fonksiyon bildirimleri, sınıf tanımları, tüm sınıf kodu veya oluşturucu çağrıları gibi ilgili alt ağaçları veya düğümleri parçalar halinde çıkarın. Tek bir değişkene kadar değişen ayrıntı düzeylerinden çıkarmayı sağlar [5]
  • Ayrıca bazı uygulamalarla kod tabanı genelinde referanslar elde etmek de mümkündür [5]
  • AST’yi kullanarak, kod içindeki hiyerarşik yapıyı ve ilişkileri yakalamak mümkündür [5]

AST Nasıl Oluşturulur?

Python’un yerleşik ast kütüphanesi güçlü de olsa da yalnızca Python koduyla sınırlıdır. Daha dil bağımsız bir çözüme ihtiyaç vardı. Cevap “tree-sitter”dır. YC destekli şirketler, Cursor (kod grafikleri oluşturma yaklaşımları büyük ölçüde tree-sitter’ın yeteneklerine dayanır), YZ destekli terminal tabanlı bir programcı olan Aider.chat, AST işlemeleri için tree-sitter kullanır (bu konuda mükemmel bir yazıları vardır: [https://aider.chat/docs/repomap.html?ref=blog.lancedb.com]). [5]

Tree-Sitter Nedir?

Tree-sitter bir ayrıştırıcı üreteci aracı ve artımlı bir ayrıştırma kütüphanesidir. Bir kaynak dosyası için somut bir sözdizimi ağacı oluşturabilir ve kaynak dosyası düzenlendikçe sözdizimi ağacını etkili bir şekilde güncelleyebilir. Tree-sitter şunları hedefler:

  • Herhangi bir programlama dilini ayrıştıracak kadar genel.
  • Her tuş vuruşunda ayrıştıracak kadar hızlı.
  • Sözdizimi hatalarıyla bile yararlı sonuçlar sağlayacak kadar sağlam.
  • Saf bir C çalışma zamanı kitaplığıyla bağımlılıktan uzak.

Temel özellik, artımlı ayrıştırmadır → kod değiştikçe sözdizim ağacının verimli bir şekilde güncellenmesi, bu da sözdizimi vurgulama ve otomatik girintileme gibi IDE özellikleri için mükemmel hale getirir. Bir arkadaşımın önerisiyle kod editörü altyapısını araştırırken, genellikle AST kütüphaneleri + LSP (Language Server Protocol: Dil Sunucusu Protokolü) kullandıklarını fark ettim. LSIF dizinleri (LSP’nin bilgi formatı) kod gömme için bir alternatif olsa da çoklu dil desteğinin karmaşıklığı nedeniyle bunları es geçtim. [5]

Tree-sitter açıklama videosu:

Tree-sitter ile sözdizimine dalmak

Başlamanın en basit yolu tree_sitter_languages ​​modülüdür. Desteklenen tüm programlama dilleri için önceden oluşturulmuş ayrıştırıcılarla birlikte gelir. [5]

Tree-sitter deneme alanında da oynamayı deneyebilirsiniz:[https://tree-sitter.github.io/tree-sitter/playground?ref=blog.lancedb.com]

pip install tree-sitter-languages

Tree-sitter örneğini burada bulabilirsiniz: [https://github.com/sankalp1999/code_qa/tree/main/tutorial]

Tree-sitter sorgularını buradan kontrol edebilirsiniz: [https://tree-sitter.github.io/tree-sitter/using-parsers?ref=blog.lancedb.com#pattern-matching-with-queries]

Kod tabanı genelinde referanslar

Bir kod tabanında fonksiyon ve sınıf referanslarını belirlemek için kullanılan bir yöntemi açıklayalım. Bu bilgiler, bir dil modeli (LLM) için sağlanan bağlamı zenginleştirmek amacıyla kullanılmaktadır. Yöntem, kodun hiyerarşik yapısını işleyen bir yığın tabanlı ağaç dolaşımı yaklaşımı ile kodun soyut sözdizim ağacını (AST) analiz etmeyi içerir. Karmaşık etiketleme veya sorgu tabanlı sistemlere güvenmek yerine, daha basit bir yaklaşım benimsenmiştir: Eğer koddaki bir isim, bilinen bir sınıf adıyla eşleşiyorsa ve çevresindeki kodun yapısı (AST’deki ebeveyn düğüm türü) bu sınıfın kullanıldığını gösteriyorsa (örneğin, bir nesne oluşturma ya da tip açıklaması olarak), bu bir sınıf referansı olarak kaydedilir. Benzer şekilde, bir fonksiyon veya metot adı eşleştiğinde ve AST bunun çağrıldığını gösterdiğinde, bu bir metot referansı olarak kaydedilir. Bu referanslar, kod tabanının belirli “parçalarına” (örneğin, dosyalar, fonksiyonlar veya diğer mantıksal birimler) bağlanan meta veriler olarak saklanır. Daha sonra, bir vektör veritabanından (VectorDB) gömme vektörleri (kodun sayısal temsilleri) alınırken, bu meta veriler de bağlama dahil edilir. Bu zenginleştirilmiş bilgiler, LLM’in kod tabanıyla ilgili sorgularda daha doğru ve alakalı yanıtlar üretme yeteneğini geliştirir. [5]

Kod Bağlamına Erişim

Kod Bağlamına Erişim

Daha önce gömmelerle çalıştıysanız, gömme aramasının o kadar etkili olmadığını ve HyDE, hibrit vektör araması ve yeniden sıralama gibi alma hattında bazı ek adımların izlenmesi gerektiğini bilirsiniz. [6]

Gömme öğelerde dikkat edilmesi gerekenler:

  • Benchmark: [https://huggingface.co/spaces/mteb/leaderboard?ref=blog.lancedb.com] adresine gidin ve gömme puanlarını, dizi uzunluğunu ve desteklenen dilleri kontrol edin. [6]
  • Gecikme: API tabanlı gömmeler, yalnızca ağ gidiş-dönüşlerinin eklediği gecikme nedeniyle yerel gömmelerdendaha yavaş olabilir. Bu nedenle hız istiyorsanız ve hesaplamanız varsa, yerel gömmeleri kullanmak daha iyi olabilir. [6]
  • Maliyet: Ücretsiz veya sadece deneme yapmak istiyorsanız, açık kaynaklı cümle dönüştürücülerine gidin. bge-en-v1.5 veya nomic-embed-v1 ihtiyacınız olan tek şeydir. Aksi takdirde, çoğu kapalı kaynaklı gömme yalnızca ucuzdur. [6]
  • Kullanım Durumu: Kod gömüyorsanız, kullandığınız gömmelerin ön eğitim verilerinde koda sahip olması gerekir. Puanlarınızı önemli ölçüde iyileştirmek için ince ayarlı gömümleri kullanabilirsiniz. LlamaIndex, tüm Hugging Face gömümlerini ince ayarlamak için yüksek seviyeli bir API’ye sahiptir. Jina yakın zamanda ince ayar API’sini duyurdu ancak ben henüz denemedim. [6]
  • Gizlilik: Gizlilik için açık kaynaklı modellerinizi çalıştırmayı tercih edin. [6]

Sourcegraph blog yazısı şöyle diyor:

“Gömmeler bağlamı almak için yararlı olsa da önemli zorluklar ortaya çıkardı: Kodu OpenAI gibi üçüncü taraf API’lerine göndermek gizlilik endişeleri yarattı, gömmeleri sürdürmek ve güncellemek yöneticiler için operasyonel karmaşıklık getirdi ve 100.000'den fazla repoya sahip büyük kod tabanlarına ölçeklendirme vektör veritabanı aramalarını kaynak yoğun hale getirdi. Bu sınırlamalar, çoklu repo bağlam özelliklerini etkili bir şekilde uygulama yeteneklerini engelledi.” [https://sourcegraph.com/blog/how-cody-understands-your-codebase?ref=blog.lancedb.com] [6]

Sourcegraph, Cody kod asistanı üzerinde çalışır ve Sourcegraph, büyük kod tabanlarını dizinlemeye odaklanır. Sourcegraph, mimarilerinde gömmeleri kullanmaktan uzaklaştı. [6]

Bir vektör veritabanını değerlendirirken aşağıdakilere dikkat edin:

  • İhtiyacınız olan tüm entegrasyonlar için destek örneğin LLM’ler, farklı şirketler, [6]
  • Geri Çağırma ve Gecikme [6]
  • Maliyet [6]
  • Tanıdıklık/Kullanım Kolaylığı [6]
  • Açık kaynak/kapalı kaynak [6]

Kod tabanını gömme ve tabloları oluşturma kodu create_tables.py’de bulunabilir. İki ayrı tablo tutuyorum bunlardan biri yöntemler için, diğeri sınıflar ve README dosyaları gibi çeşitli öğeler için. Her şeyi ayrı tutmak, ayrı meta verileri ve ayrı vektör aramalarını sorgulamama olanak tanır; en yakın sınıfı al, en yakın yöntemleri al. İşte LanceDB uygulaması: [https://github.com/sankalp1999/code_qa/blob/main/create_tables.py?ref=blog.lancedb.com] [6]

Erişim

Tablolar hazır olduğunda, vectorDB’ye sorgular verebiliriz ve o da kaba kuvvet araması (kosinüs benzerliği/nokta ürünü) kullanarak en benzer belgeleri çıktı olarak verecektir. Bu sonuçlar alakalı olacak ancak düşündüğünüz kadar doğru olmayacak. Gömme araması, öyle olmayana kadar sihir gibi geliyor. Diğer bazı projelerdeki deneyimime göre, sonuçlar alakalı ancak genellikle gürültülü ve ayrıca sıralama sıklıkla yanlış olabiliyor. Bazı eksiklikleri göstermek için aşağıya bir Twitter dizisi ekliyorum: [https://x.com/eugeneyan/status/1767403777139917133?ref=blog.lancedb.com] [6]

Gömme Aramasını İyileştirme

BM25

Yapılacak ilk şey genellikle anlamsal aramayı BM25 gibi anahtar kelime tabanlı bir aramayla birleştirmektir. Bunlar birçok vectorDB tarafından zaten hazır şekilde desteklenmektedir. “Semantweet” projemin erişiminde, hazır haliyle hibrit aramayı (anlamsal arama + bm25) destekleyen LanceDB’yi kullandım, tantivy kullanarak tam metin tabanlı bir dizin oluşturmak için sadece biraz ek kod yazmam gerekti. [6]

Farklı yöntemlerin sonuçları nasıl etkileyebileceğini gösteren lancedb sitesinde bazı kıyaslamalar bulunmaktadır: [https://lancedb.github.io/lancedb/hybrid_search/eval/?ref=blog.lancedb.com]. [6]

Recall, ilgili belgelerin kaç tanesine eriştiğimizdir yani belge sayısıdır. Erişim performansını ölçmek için kullanılır. [6]

Meta Verileri Kullanarak Filtreleme

Anlamsal aramayı geliştirmek için bir diğer etkili yaklaşım meta veri filtreleme kullanmaktır. Verileriniz tarihler, anahtar sözcükler veya ölçümler gibi nitelikler içeriyorsa, anlamsal bir arama yapmadan önce sonuçları önceden filtrelemek için SQL kullanabilirsiniz. Bu iki adımlı süreç arama kalitesini ve performansını önemli ölçüde iyileştirebilir. Gömmelerin gizli alanda bağımsız noktalar olarak var olduğunu unutmamak önemlidir, bu nedenle bu ön filtreleme adımı ilgili arama alanını daraltmaya yardımcı olur. [6]

Yeniden Sıralama

Vektör aramasından sonra yeniden sıralayıcılar (re-rankers) kullanmak, sonuçları önemli ölçüde iyileştirmenin kolay bir yoludur. Kısaca, yeniden sıralayıcılar sorgu tokenleri ile gömme arama sonuçlarındaki tokenler arasında çapraz dikkat (cross-attention) uygular. [6]

Bunların yüksek seviyede nasıl çalıştığını anlamaya çalışalım. CodeQA v2'de, Cohere Re-ranker 3'e (CodeQA v1'de kullandığım) yakın performansla kıyaslamalara dayalı en iyi performans gösteren yerel yeniden sıralama modeli olduğu için answerdotai/answerai-colbert-small-v1'i kullanıyorum: [https://blog.lancedb.com/hybrid-search-and-reranking-report/] [6]

Çapraz kodlama (yeniden sıralama) ve çift kodlama (arama tabanlı gömmeler) (Cross-encoding (re-ranking) vs bi-encoding (embeddings based search))

Her iki GPT-3 / BERT tipi model de iki tarzda çalıştırılabilir → çapraz kodlayıcı ve çift kodlayıcı. Aynı şekilde eğitilmeleri (veya ince ayarlanmaları) gerekir. Bir çapraz kodlayıcı, sorguyu her belgeyle birleştirir ve alaka puanlarını hesaplar. Birleştirilmiş sorgu+belge çiftlerinin her biri, birkaç dikkat ve mlp katmanından geçerek önceden eğitilmiş modelden (BERT gibi) geçirilir. Öz-dikkat mekanizması, sorgu ile belge arasındaki etkileşimi yakalamaya yardımcı olur (sorgunun tüm gömmeleri belgeyle etkileşime girer) [6]

Bağlamsallaştırılmış gömmeler elde etmek için çıktıyı gizli bir katmandan (genellikle sonuncusu) alırız. Bu gömmeler, sabit boyutlu bir gösterim elde etmek için bir araya getirilir. Bunlar daha sonra doğrusal bir katmandan ve ardından softmax/sigmoid’den geçirilerek lojit → alaka puanları → [0,5, 0,6, 0,8, 0,1, …] [6] elde edilir.

D tane dokümanımız ve Q tane sorgumuz olduğunu varsayalım. 1 sorgu için alaka skorunu hesaplamak amacıyla modelden D adet (sorgu+doküman) geçişi yapmamız gerekecek. Q sorgu için ise D * Q geçişi yapılacaktır çünkü ****her bir D ve Q birleşimi benzersizdir. [6]

Bir bi-encoder yaklaşımı (veya embedding arama yaklaşımı), dokümanları ve sorguları ayrı ayrı kodlar ve ardından nokta çarpımı hesaplar. Diyelim ki D tane dokümanınız ve Q tane sorgunuz var. [6]

D embeddinglerini önceden hesaplayın. Bu embedding’i tekrar hesaplamak yerine yeniden kullanabiliriz. Şimdi, her sorgu için D ve Q’nun nokta çarpımını hesaplayın. Nokta çarpımı O(1) işlem olarak düşünülebilir. [6]

  • D dokümanlarını kodlama maliyeti → D.
  • Q sorgularını kodlama maliyeti → Q.
  • Toplam maliyet, D + Q olur.
  • Bu yaklaşım, cross-encoder yaklaşımından çok daha hızlıdır. [6]

Cross-encoder yaklaşımında, sorgudaki her bir token dokümanlarla etkileşime girer ve her doküman için bir alaka skoru atar. Bu nedenle, bi-encoder’lara kıyasla daha doğrudur, ancak yavaştır çünkü her bir çiftin (her bir Q+D kombinasyonu benzersiz olduğu için) ayrı ayrı işlenmesi gereklidir ve embedding’ler önceden hesaplanamaz. Bu nedenle, hızlı geri çağırma (retrieval) için bir bi-encoder yaklaşımına bağlı kalabiliriz (embedding’leri oluşturma, sorguyu kodlama, dokümanları kodlama ve bir vektör veritabanında saklama, benzerliği hesaplama). Daha sonra, sonuçları iyileştirmek için ilk K sonucu almak amacıyla reranker’lar (cross-encoder’lar) kullanılabilir. [6]

HyDE: Varsayımsal Belge Gömmeleri (HyDE: Hypothetical Document Embeddings)

HyDE nedir?

Semantik arama dediğimizde varsayılan olarak Dense Retrieval’ı kastederiz. Ve Dense Retrieval’ın bazı zayıflıkları vardır. Yeni veya az kaynaklı konularda, dillerde, kodlarda anlam eşlemesi yaparken yetersiz kalabilmektedir.

Language Technologies Institute ve Carnegie Mellon Üniversitesi işbirliği ile 20 Dec 2022 yılında yayımlanan “Precise Zero-Shot Dense Retrieval without Relevance Labels” [https://arxiv.org/pdf/2212.10496] makalesinde yazarlar bu soruna HyDE (short for Hypothetical Document Embeddings) çözümü sunmaktadırlar.

HyDE çözümünde önce LLM soruyu alır ve potansiyel bir cevap tahmin eder, buna sahte doküman denir. Bu doküman vektöre çevirilerek gerçek cevap aranır. İkinci adımda ise, LLM’in çıktısında hatalar varsa bile sistem bu hataları filtreler ve böylece vektör veritabanındaki gerçek yüksek kaliteli dokümanlara odaklanılır.

HyDE başarılı mı?

HyDE herhangi bir eğitim verisine ihtiyaç duymadan çalışır. Önceden binlerce sorgu ve cevap örneğini etiketlemenize gerek yoktur. HyDE birçok görevi (arama, gerçek kontrolü veya soru cevaplama gibi) halledebilir ve hatta farklı dillerde bile iyi çalışır. HyDE, hiçbir şeyle başlamayan bir sistem için etkileyici olan, çok sayıda veri üzerinde eğitilmiş sistemlere benzer şekilde performans gösterir. HyDE özellikle arama sistemi yeniyken, çok data yokken arama kalitesini arttırmak amacıyla performans ve maaliyetten ödün verilerek tercih edilir.

Peki biz neden Kod ile RAG yaparken HyDE kullanıyoruz?

Kullanıcının sorgusu doğal dil ile (İngilizce veya Türkçe) ve daha az koddan oluşacaktır. Ancak bizim gömmelerimiz çoğunlukla koddan oluşur. Şimdi gizli alanı (latent space) düşünürsek, kod, doğal dile göre koda anlamsal olarak daha yakın olacaktır.[6]

HYDE Sistem İstemi:

HYDE_SYSTEM_PROMPT = '''
Sen uzman bir yazılım mühendisisin.
Görevin verilen sorguyu yanıtlayan kodu tahmin etmek.

Talimatlar:
1. Sorguyu dikkatlice analiz et.
2. Çözümü adım adım düşün.
3. Sorguyu ele alan özlü, deyimsel bir kodu oluştur.
4. Yanıtına belirli metot adları, sınıf adları ve temel kavramlar ekle.
5. Uygunsa, verilen görev için modern kütüphaneler veya en iyi uygulamaları öner.
6. Sağlanan bağlama göre dili tahmin edebilirsin.

Çıktı biçimi:
- Yalnızca iyileştirilmiş sorguyu veya tahmin edilen kod parçacığını sağlay.
- Kodun dışında herhangi bir açıklayıcı metin ekleme.
- Yanıtın daha fazla işleme veya yürütme için doğrudan kullanılabilir olduğundan emin ol.'''

Halüsinasyonlu sorgu, tablolarımızdan ilk 5 sonucu alarak ilk vektör aramasını gerçekleştirir. Bu sonuçlar ikinci bir HyDE sorgusu için bir bağlam görevi görür. İlk sorguda, programlama dili bilinmez ancak getirilen bağlamın yardımıyla dil daha iyi öğrenilir. İkinci HyDE sorgusu ise daha fazla bağlamın farkındadır ve sorguyu ilgili koda özgü ayrıntılarla genişletir. [6]

HYDE_V2_SYSTEM_PROMPT = '''
Siz uzman bir yazılım mühendisisin.
Görevin, sağlanan bağlamı kullanarak orijinal sorguyu geliştirmek: {query}: {temp_context}.

Talimatlar:
1. Sorguyu ve bağlamı iyice analiz et.
2. Sorguyu ilgili koda özgü ayrıntılarla genişlet:
- Kodla ilgili sorgular için: Kesin yöntem adlarını, sınıf adlarını ve temel kavramları ekle.
- Genel sorgular için: README.md veya konfigürasyon dosyaları gibi önemli dosyalara başvur.
- Yönteme özgü sorgular için: Olası uygulama ayrıntılarını tahmin et ve modern, ilgili kitaplıkları öner.
3. Sorguyu yanıtlamak için en alakalı olan bağlamdan anahtar sözcükleri dahil et.
4. İlgili olabilecek herhangi bir önemli terminoloji veya en iyi uygulamayı ekle.
5. Geliştirilmiş sorgunun daha açıklayıcı ve hedefli olurken odaklanmış ve özlü kalmasını sağla.
6. Sağlanan bağlama göre dili tahmin edebilirsin.

Çıktı biçimi: Yalnızca geliştirilmiş sorguyu sağla. Herhangi bir açıklayıcı metin veya ek yorum ekleme.'''

LLM’in hem kod hem de doğal dil anlayışından yararlanarak, ilgili kod terminolojisini ve doğal dil açıklamalarını içeren genişletilmiş, bağlamsal olarak daha bilinçli bir sorgu oluşturulur. Bu iki adımlı süreç, kullanıcının doğal dil sorgusu ile kod tabanının teknik içeriği arasındaki anlamsal boşluğu kapatmaya yardımcı olur. [6]

İkinci sorgu kullanılarak bir vektör araması gerçekleştirilir ve en iyi K sonuçları answerdotai/answerai-colbert-small-v1 kullanılarak yeniden sıralanır ve ardından ilgili meta veriler getirilir: [https://huggingface.co/answerdotai/answerai-colbert-small-v1] [6]

Referansların meta verilerden alındığını ve LLM için bağlam olarak beslenecek kodla birleştirildiğini unutmayın. [6]

hyde_query = openai_hyde(query)

method_docs = method_table.search(hyde_query).limit(5).to_pandas()
class_docs = class_table.search(hyde_query).limit(5).to_pandas()

temp_context = '\n'.join(method_docs['code'] + '\n'.join(class_docs['source_code']) )

hyde_query_v2 = openai_hyde_v2(query, temp_context)

logging.info("-query_v2-")
logging.info(hyde_query_v2)

method_search = method_table.search(hyde_query_v2)
class_search = class_table.search(hyde_query_v2)

if rerank: # Kullanıcı arayüzünden yeniden sıralama seçilirse
method_search = method_search.rerank(reranker)
class_search = class_search.rerank(reranker)

method_docs = method_search.limit(5).to_list()
class_docs = class_search.limit(5).to_list()

top_3_methods = method_docs[:3]
methods_combined = "\n\n".join(f"File: {doc['file_path']}\nCode:\n{doc['code']}" for doc in top_3_methods)

top_3_classes = class_docs[:3]
classes_combined = "\n\n".join(f"File: {doc['file_path']}\nClass Info:\n{doc['source_code']} References: \n{doc['references']} \n END OF ROW {i}" for i, doc in enumerate(top_3_classes))

Burada RAG’ı tamamladık. Kullanıcı @codebase’den bahsederse, yalnızca gömmeler alınır, aksi takdirde mevcut bağlam kullanılır. LLM bağlam konusunda emin değilse, kullanıcıya @codebase’den bahsetmesini söyler (sistem istemi nedeniyle). [6]

 rerank = True if rerank in [True, 'true', 'True', '1'] else False

if '@codebase' in query:
query = query.replace('@codebase', '').strip()
context = generate_context(query, rerank)
app.logger.info("Generated context for query with @codebase.")
app.redis_client.set(f"user:{user_id}:chat_context", context)
else:
context = app.redis_client.get(f"user:{user_id}:chat_context")
if context is None:
context = ""
else:
context = context.decode()

# Şimdi, gerekirse sohbet yanıtı sırasında yeniden sıralamayı uygulayın
response = openai_chat(query, context[:12000]) # Gerektiği gibi ayarlayın

Olası İyileştirmeler

Gecikme

Özellikle gecikme bölümünde çok sayıda iyileştirme mümkündür. Şu anda, @codebase ile ve yeniden sıralama olmadan yapılan sorgular yaklaşık 10–20 saniye, yeniden sıralama etkinleştirildiğinde 20–30 saniye aralığında (ki bu yavaştır) sürüyor. Savunmam için, Cursor da genellikle 15–20 saniye civarında cevap veriyor. [6]

  • Gecikmeyi azaltmanın en kolay yolu, Groq veya Cerebras gibi yüksek verimli çıkarım sağlayıcılarından Llama3.1 70B gibi bir LLM kullanmaktır. Bu, gecikmeyi en az 10 saniye azaltmalıdır (gpt4o-mini ile HyDE çağrılarını hızlandırın). [6]
  • Ağ gecikmesini ele almak için lokal gömmeler kullanmayı deneyin [6]
  • Gecikme darboğazımız HyDE sorgularıdır. Bunları bire indirmek veya ortadan kaldırmak mümkün müdür? Belki de repo haritasında Bm25 tabanlı anahtar kelime aramalarının bir kombinasyonunu uygulamak en azından 1 HyDE sorgusunu azaltmaya yardımcı olabilir: [https://aider.chat/docs/repomap.html?ref=blog.lancedb.com] [6]

Doğruluk

Kolayca elde edilebilecek bir şey

  • Daha iyi gömmeler denemek veya ince ayarlı gömmeleri kullanmaktır. [6]
  • Değerlendirmeleri uygulamak ve geri bildirim döngüsünün yardımıyla doğruluğu optimize etmektir. [6]

Cody by Sourcegraph

Bir kullanıcı Cody’ye Kod Asistanına (bir sohbet mesajı veya bir komut aracılığıyla) sorgu gönderdiğinde, gerçekleşen ilk şey Cody’nin bir istem derlemesidir. Cody kullanıcının girdisini alır ve onu LLM’den en iyi yanıtı almak için tasarlanmış bir istem haline getirir. İstem üç bölüme ayrılabilir: Sistem istemi olan ön ek, istem kullanıcı girdisi ve Cody’nin bulup LLM’in ilgili bir yanıt sağlamasına yardımcı olmak için aldığı ek bilgi olan bağlam (örneğin: “ “[Contents of sourcegraph/sourcegraph/internal/search/zoekt/query.go]”).[7]

Kullanıcının IDE’si ile Sourcegraph’ta remote repo’lu kod arasında çeşitli bağlam kaynakları mevcuttur. Cody’nin her bir özelliği için, hem doğruluk hem de hız açısından en uygun yaklaşımı göz önünde bulundurmamız gerekir. Sohbet ve komutlar için Cody’nin geniş bir bağlama erişimi olmalıdır. İdeal bir durumda, bu, bir kullanıcının soru sormak isteyebileceği bir kod tabanının tüm yüzey alanını kapsayan bağlam anlamına gelir. [7]

Sourcegraph’ın Kod Zekası Platformu tam da burada devreye giriyor. Sourcegraph’ın temel platformu, kodu anlayan bir motor olarak işlev görüyor. Müşterilerimizin tek bir kod barındırıcısında (Bitbucket veya GitLab gibi) ~100 repodan, bir dizi kod barındırıcısında yaşayan 100.000+ repoya kadar uzanan kod tabanları bulunmaktadır. Tüm bu durumlarda Sourcegraph tüm bu kodu dizinliyor ve anlıyor. [7]

Bu platformu, ürünümüz Code Search [https://sourcegraph.com/code-search] aracılığıyla arama deneyimlerini güçlendirmek için kullanıyoruz. Code Search, geliştiricilerin tek bir yerde geniş kod tabanlarında arama yapmasına ve gezinmesine yardımcı olmak için yüksek performanslı bir arama motoru kullanır. [7]

Şimdi, Cody’yi desteklemek için aynı temel platformu kullanıyoruz ve platformdan Cody’nin LLM’sine kod tabanınızı anlamak için bağlam olarak bilgi aktarabiliyoruz. [7]

Bir kullanıcı Cody’yi çağırdığında, bağlamı çekmek istediği repoları seçebilir (bu gönderi itibarıyla, kullanıcılar bir seferde en fazla 10 repo seçebilir). Cody, Sourcegraph örneğiyle iletişim kuracak ve seçilen repolar üzerinde bir arama çalıştıracaktır. [7]

Arama isteği kullanıcı sorgusunu önceden işler, metni gömmelere böler ve herhangi bir yabancı bilgi içermeyen standart bir gösterimle kalmamız için bir dizi temizleme adımı uygular. Daha sonra bu token listesi Sourcegraph arama motoru tarafından işlenir, bu da kullanıcı tarafından seçilen repoları tarar ve dosya parçacıklarını (bir parçacık, genel dosyanın bir alt kümesidir) arama sorgusuyla alakalarına göre sıralar. [7]

İlgililiği hesaplamak için Cody, BM25 sıralama işlevinin uyarlanmış bir biçimini, eldeki belirli göreve göre öğrenilen ve ayarlanan diğer sinyallerle birlikte kullanır. Bu aşamada doğru bağlamı sıralamak, kullanıcıların Cody’den ilgili yanıtlar alması için sürecin kritik bir parçasıdır, bu nedenle bu sıralamaya yaklaşımımızı sürekli olarak ayarlıyoruz. Parçacıklar sıralandıktan sonra, en ilgili olanlar istem bağlamında kullanılmak üzere Cody istemcisine geri gönderilir. [7]

Sourcegraph araması tarafından döndürülen dosya parçacıklarının yanı sıra Cody, yerel bağlama (kullanıcının IDE’sinde açık olan proje) da erişebilir. Cody, uzaktan alınan bağlama eklemek için IDE’deki açık dosyalardan parçacıkları çeker. [7]

Cody daha sonra her bağlam sağlayıcısı tarafından sağlanan tüm parçacıkların alakalılığına bakar ve genel bir sıralama oluşturur. Cody bu genel sıralamadan, döndürülen ilk N parçacığı alır (N, her parçacığın uzunluğunun bir fonksiyonudur) ve bunları oluşturduğu istemin ‘bağlamına’ paketler. Bu bağlam, önek ve kullanıcı girdisiyle birlikte, Cody’nin daha sonra LLM’ye göndereceği tam istemi tamamlar. LLM daha sonra kullanıcıya geri dönmek üzere bir yanıt oluştururken aldığı bağlamın tam metnini okuyacak ve değerlendirecektir. [7]

Otomatik Tamamlama (Autocomplete)

Hem satır içi hem de çok satırlı otomatik tamamlama, farklı bağlam alma yöntemleri kullanır. Otomatik tamamlamanın en yararlı olması için son derece hızlı olması gerektiğinden (kullanıcılar yazarken yardımcı bir şekilde araya girerek), Cody, kurumsal bir Sourcegraph örneğinde uzaktan aramalar çalıştırmak yerine, otomatik tamamlama için yerel bağlamı aramayı önceliklendiren algoritmalar kullanır. Otomatik tamamlama ayrıca, kod tamamlama görevleri ve düşük gecikme için ayarlanmış seçenekleri tercih ederek farklı LLM’ler kullanır. [7]

Bir kullanıcı yazı yazarken, Cody, kullanıcının gerçekleştirdiği eylemlerin amacını sürekli olarak değerlendirmektedir. Tree-Sitter adlı bir ayrıştırma (parsing) kütüphanesi kullanarak, Cody, aktif iş akışına en uygun tamamlama deneyiminin türünü hızlı bir şekilde belirleyebilir. Örneğin, bir fonksiyonun imzasından içini yazma, kod yorumu yazma veya bir metot çağrısı uygulama gibi. Bu belirlenen amaç, Cody’nin mevcut göreve en iyi şekilde uyacak bağlamı anlamasına yardımcı olur. [7]

Amaç sınıflandırıldıktan sonra, Cody, aktif dosyanın içeriği, açık diğer sekmeler, yakın zamanda kapatılan sekmeler ve daha fazlasını içeren çeşitli yerel bağlam kaynaklarına başvurur. Cody, bu bağlam akışlarından, tamamlamayı yönlendirmek için faydalı referans örnekleri olan benzer veya ilgili kod bölümlerini belirler. Sohbet için bağlam seçimi gibi, Cody en alakalı kod parçalarını bir istem haline getirir ve bunu tamamlama için optimize edilmiş LLM’e gönderir. LLM’den gelen yanıt daha sonra ayrıştırılır ve kullanıcının imlecinin önünde bir ‘ghost text’ (hayalet metin) olarak gösterilir. [7]

Elbette, bu, tamamlama sürecinin aşırı derecede basitleştirilmiş bir özetidir. Bu alan, sürekli olarak araştırma ve geliştirme ile zenginleşen bir konudur. Daha fazla bilgi edinmekle ilgileniyorsanız, şunlara göz atmanızı öneririz: [https://sourcegraph.com/blog/the-lifecycle-of-a-code-ai-completion]. [7]

Peki, gömmelere ne oldu?

Embeddings, ürünümüzü beta olarak piyasaya sürdüğümüzden beri Cody’nin veri alma altyapısının temelini oluşturuyordu. Ancak artık Cody Enterprise genel olarak kullanıma sunulduğuna göre, (şimdilik) embeddings’i geride bırakıyoruz. Peki, neden böyle bir değişikliğe gittik? [7]

Öncelikle, arka plan bilgisi olarak, gömmeleri yüksek seviyede anlamak önemlidir. Kısaca, gömeler, yüksek boyutlu verilerin yoğun bir vektör temsili anlamına gelir. Daha önce, token’ları (kaynak kodu) bir vektöre dönüştürmek için OpenAI’nin gömme modeli olan text-embedding-ada-002'yi kullanıyorduk. Ardından, bağlam için bir vektör tabanlı veri alma sistemi çalıştırabiliyorduk. Bir kullanıcı Cody’ye bir sorgu gönderdiğinde, bu sorgu bir vektöre dönüştürülüyor ve bu vektör, kullanıcının kod tabanını temsil eden vektörlerle karşılaştırılıyordu. Bu karşılaştırma sonucunda, bağlam olarak kullanılacak dosyalar ve kod parçacıkları elde ediliyordu. [7]

Embeddings bağlamı almak için işe yarasa da, bizim açımızdan bazı dezavantajları vardı. Embeddings, tüm kodunuzu vektör uzayında temsil etmeyi gerektiriyor ve bunu yapmak için kaynak kodunu OpenAI API’sine göndermek zorundayız. Daha sonra bu vektörlerin depolanması, korunması ve güncellenmesi gerekiyor. Bu durum üç nedenle ideal değildi:

  1. Kodunuzun işlenmek üzere bir üçüncü tarafa (OpenAI) gönderilmesi gerekiyor ve herkes kodunun bu şekilde paylaşılmasını istemeyebilir. [7]
  2. Gömme oluşturma ve güncel tutma süreci, Sourcegraph yöneticilerinin yönetmek zorunda olduğu bir karmaşıklık ekliyor. [7]
  3. Bir kod tabanının boyutu arttıkça, buna bağlı olarak vektör veritabanı da büyüyor ve 100.000'den fazla repoya sahip kod tabanlarında vektör veritabanı aramaları karmaşık ve kaynak yoğun hale geliyor. Bu karmaşıklık, yeni çoklu repo bağlamı özelliğimizi geliştirme yeteneğimizi sınırlıyordu. [7]

Cody’nin, piyasadaki herhangi bir kodlama asistanından daha iyi bir bağlam sunmasını sağlama taahhüdümüz, bu sorunlara bir çözüm bulmamızı zorunlu kıldı. Önceki bölümlerde açıklandığı gibi, bağlam alma işlemleri için embeddings’in yerine Sourcegraph’ın lokal platformunu kullanmayı başardık. Bu yeni çözüm, kodun bir embedding işlemcisine gönderilmesini gerektirmiyor, ek bir yapılandırma gerektirmiyor ve devasa kod tabanlarına ölçeklenebiliyor. [7]

Bu değişiklikten kaynaklanan iyileştirmelerden dolayı heyecanlı olsak da, gelecekte bağlamı daha da geliştirmek için gömmeleri bir şekilde kullanma fırsatlarının olabileceğine inanıyoruz. Bu, bizim için aktif bir araştırma alanı olmaya devam ediyor ve gelecekte bu konuda daha fazla şey paylaşmayı sabırsızlıkla bekliyoruz. [7]

Tabby

Tabby ayrıca Code RAG yapan açık kaynaklı bir kod yardımcısıdır. Tabby Github reposunu kontrol edin: [https://github.com/TabbyML/tabby]

Özel bir sorgu kullanarak Treesitter ile daha derin entegrasyonla RAG’ı geliştirin. Bu, Tabby’nin kod dizinine LSP benzeri bir anlayış getirecektir. Tabby ayrıca varsayılan olarak etkinleştirilmiş erişim destekli kod tamamlama desteğiyle bir v0.3.0 sürümüne gelir. Repo düzeyinde erişim ile geliştirilen Tabby, kod tabanınızda daha akıllı hale gelir ve reponuzdaki başka bir dosyadan ilgili bir işleve/kod örneğine hızla başvurur. [8]

LLM Destekli Kod Tamamlama için Repo Bağlamı

“Kendi kendine yeten” kodlama görevleri için önceden eğitilmiş Dil Modelleri (LLM’ler) kullanmak iyi sonuç verir, ancak bunları büyük ve karmaşık repolar içinde kullanmak, LLM’lerin bağımlılıkları, API’leri ve mevcut soyutlamaları anlamalarına yardımcı olmak için repo bağlamının sağlanmasını gerektirir.[8]

Temel Zorluklar

  1. Bağımlılıkları Anlamak: LLM’lerin, mevcut kod tabanı yapılarına uyan doğru kod tamamlamaları üretmek için repoya özgü bağlama ihtiyaçları vardır.[8]
  2. Bağlam Penceresi Sınırlamaları: Token sınırlamaları ve gecikme sorunları nedeniyle tüm reponun girdi olarak sağlanması pratik değildir.[8]

Yaklaşım

  1. Seçici Bağlam Dahil Etme:
  • Tüm dosyalar yerine ilgili parçacıkları (örneğin, yöntem bildirimleri veya API kullanımı) ekleyin. Örnek: Yalnızca CompletionState::new metodunu içeren dosyanın önekinin eklenmesi, doğru tamamlama oluşturulmasına izin verdi.[8]

2. Araçlarla Otomasyon:

  • Ağaç bekçisi: Ters bir token dizini oluşturmak için koddan yapılandırılmış sembolleri (örneğin, yöntemler, türler) çıkarır. Tür tanımları gibi sorgular, özlü, dil bağımsız parçacıkları derlemek için kullanılır.[8]
  • Parçacıklar, tamamlama istekleri sırasında ilgili bağlam için BM25 araması kullanılarak gömmeleştirilir, dizine eklenir ve alınır.[8]

3. Optimize Edilmiş Kod Parçacığı Biçimlendirmesi: İlgili kod parçacıkları, anlamsal bütünlüğü koruyarak ve anlayışı kolaylaştırarak tamamlama isteğine yorum olarak dahil edilir.[8]

Alma Arttırılmış Kod Tamamlama ile İlgili Geliştirmeler

  • Bu özellik, geliştirilmiş kod önerileri için ilgili repo parçacıklarını alır ve entegre eder. LLM’lerin mevcut soyutlamaları ve API’leri daha iyi kullanmasını sağlar.[8]

Yol Haritası

  1. Parça Dizinleme: Farklı programlama dilleri için ilgili parçaların seçimini iyileştirin.[8]
  2. İnce Ayarlı Alma Algoritmaları: Daha alakalı parçacıkları önceliklendirmek için LLM dikkat ağırlıklarından yararlanın.[8]

Özetlenen yaklaşım, karmaşık repolar için LLM destekli kod tamamlamada önemli iyileştirmeler olduğunu ve daha fazla iyileştirme ve verimlilik iyileştirmeleri için planlar olduğunu göstermektedir.[8]

Kod RAG Karşılaştırması

Son olarak, bu Kod RAG Benchmark makalesini inceleyebilirsiniz: [https://code-rag-bench.github.io/]

Bu çalışma, yalnızca dil modellerinin parametrik bilgisine güvenmek yerine, kütüphane belgeleri, eğitimler ve diğer programlamayla ilgili materyaller gibi harici kaynaklar sağlayarak kod üretimini iyileştirmek için geri alma ile güçlendirilmiş kod üretiminin (RACG) potansiyelini vurgulamaktadır. Bazı önceki çabalara rağmen, RACG çeşitli görevler ve geri alma kaynakları arasında yeterince araştırılmamıştır. Bunu ele almak için yazarlar, üç kategori kod üretimi görevini kapsayan bir kıyaslama olan CodeRAG-Bench’i tanıtmaktadır: genel programlama, açık alan sorunları ve repo düzeyindeki zorluklar. Ayrıca beş tür geri alma kaynağını bir araya getiriyorlar: rekabet çözümleri, çevrimiçi eğitimler, kütüphane belgeleri, StackOverflow gönderileri ve GitHub repoları. [9]

Temel bulgular şunlardır:

  • Yüksek kalitede alınan bağlamlar kod üretimini geliştirebilir. [9]
  • Ancak, mevcut alma modellerinin ilgili bilgileri almak için yardıma ihtiyacı var ve kod oluşturma modelleri, kısa bağlam uzunlukları ve yetersiz erişim destekli üretim (RAG) yetenekleri gibi kısıtlamalar nedeniyle sınırlı iyileştirmeler gösteriyor. [9]

Çalışmanın amacı, daha iyi kod odaklı RAG sistemlerinin geliştirilmesini teşvik etmek ve CodeRAG-Bench’i RACG araştırmalarını ilerletmek için değerli bir sınama ortamı (testbed) olarak konumlandırmaktır. [9]

Kaynak

[1] Cursor, (2024), Codebase:

[https://docs.cursor.com/chat/codebase]

[2] Continue.dev, (2024), CodeBase:

[https://docs.continue.dev/customize/deep-dives/codebase]

[3] Continue.dev, (2024), Custom Code RAG:

[https://docs.continue.dev/customize/tutorials/custom-code-rag]

[4] Tal Sheffer, (July 10, 2024), RAG for a Codebase with 10k Repos:

[https://www.qodo.ai/blog/rag-for-large-scale-code-repos/]

[5] Sankalp Shubham, (Nov 6, 2024), An attempt to build cursor’s @codebase feature — RAG on codebases — part 1/2:

[https://blog.lancedb.com/rag-codebase-1/]

[6] Sankalp Shubham, (Nov 7, 2024), An attempt to build cursor’s @codebase feature — RAG on codebases — part 2/2:

[https://blog.lancedb.com/building-rag-on-codebases-part-2/]

[7] Alex Isken, Corey Hill, (February 16, 2024), How Cody understands your codebase:

[https://sourcegraph.com/blog/how-cody-understands-your-codebase?ref=blog.lancedb.com]

[8] Meng Zhang, (October 16, 2023), Repository context for LLM assisted code completion:

[https://tabby.tabbyml.com/blog/2023/10/16/repository-context-for-code-completion/]

[9] Wang, Asai, Yu, Xu, Xie, Neubig, Freid, (20 Jun 2024), CodeRAG-Bench: Can Retrieval Augment Code Generation?

[https://code-rag-bench.github.io/]

--

--

Cahit Barkin Ozer
Cahit Barkin Ozer

Written by Cahit Barkin Ozer

Üretken YZ başta olmak üzere teknoloji alanındaki yenilikleri öğrenip sizlerle paylaşıyorum. Youtube Kanalım: https://www.youtube.com/@cbarkinozer

No responses yet