Ana içeriğe atla

RAG ile Llama 4: Demo Projeyle Rehber

Basit bir web uygulaması oluşturmak için Llama 4 kullanarak bir geri getirim destekli üretim (RAG) hattı kurmayı öğrenin.
Güncel 3 Eki 2026  · 12 dk. oku

Yapay Zeka ile Keşfedin

ChatGPTClaudePerplexity

Llama 4 Scout, 10 milyon tokenlık devasa bir bağlam penceresine sahip olarak pazarlanıyor, ancak eğitimi maksimum 256 bin token giriş boyutuyla sınırlıydı. Bu da daha büyük girdilerde performansın düşebileceği anlamına geliyor. Bunu önlemek için geri getirim destekli üretim (RAG) hattıyla Llama 4 kullanabiliriz.

Bu eğitimde, LangChain ekosistemini kullanarak adım adım bir RAG hattı kurmayı ve kullanıcıların belgeler yükleyip onlar hakkında sorular sorabileceği bir web uygulaması oluşturmayı açıklayacağım.

Okurlarımızı yapay zekâdaki en son gelişmelerden haberdar etmek için haftanın önemli haberlerini derlediğimiz, ücretsiz Cuma bültenimiz The Median'ı gönderiyoruz. Abone olun; haftada sadece birkaç dakikada güncel kalın:

Neden Llama 4'ü RAG ile Kullanmalı?

Llama 4, 10 milyon tokenlık bir bağlam penceresiyle geliyor; yani 100 kitabı besleyip bunlar hakkında bağlamsal yanıtlar alabiliriz. Ancak bu etkileyici özelliğe rağmen, Llama 4'ü RAG ile eşleştirmek için güçlü nedenler var. İşte nedenleri:

1. Büyük girdilerde performans sınırlamaları

Llama 4 büyük bir bağlam penceresini desteklese de, eğitimi en fazla 256 bin tokenlık girişlerle sınırlıydı. Girdiler bu eşiğe yaklaştığında veya aştığında modelin performansı düşebilir. RAG, yalnızca en ilgili bilgileri getirerek bu sorunu hafifletir ve girdinin özlü ve odaklı kalmasını sağlar.

2. Verimlilik ve odak

RAG, bir vektör veritabanından yüksek düzeyde ilgili bilgilerin getirilmesini sağlar ve Llama 4'ün daha küçük, daha hedefli girdileri işlemesine imkân verir. Bu yaklaşım hem verimliliği hem de doğruluğu artırır.

3. Maliyet tasarrufu

Llama 4'ün tam bağlam penceresiyle devasa girdileri işlemek hesaplama açısından maliyetli olabilir. RAG kullanarak yalnızca en ilgili veriler getirilip işlenir; bu da hesaplama yükünü ve ilgili maliyetleri önemli ölçüde düşürür.

Llama 4 RAG Hattını Kurma

Bu eğitimde, bir .docx dosyasını yükleyip içeriği hakkında sorular sormanıza olanak tanıyan basit bir geri getirim destekli üretim hattını adım adım nasıl kuracağımı açıklayacağım.

1. Kurulum

Önce bir GroqCloud API anahtarı oluşturup bunu bir ortam değişkeni olarak kaydetmemiz gerekiyor. Ardından bağlamı yüklemek, bölmek, vektörleştirmek ve getirmek ile yanıt üretmek için gereken tüm Python paketlerini kuracağız.

%%capture
%pip install langchain
%pip install langchain-community 
%pip install langchainhub 
%pip install langchain-chroma 
%pip install langchain-groq
%pip install langchain-huggingface
%pip install unstructured[docx]

2. LLM ve gömme modelini başlatma

Groq API'sini kullanarak model nesnesini model adı ve API anahtarıyla kuracağız. Benzer şekilde, gömme modelini Hugging Face'ten indirip gömme modelimiz olarak yükleyeceğiz.

from langchain_groq import ChatGroq
from langchain_huggingface import HuggingFaceEmbeddings

llm = ChatGroq(model="meta-llama/llama-4-scout-17b-16e-instruct", api_key=groq_api_key)

embed_model = HuggingFaceEmbeddings(model_name="mixedbread-ai/mxbai-embed-large-v1")

3. Verileri yükleme ve bölme

.docx dosyasını kök klasörden yükleyip 1000 karakterlik parçalara böleceğiz.

from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Initialize the text splitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=100,
    separators=["\n\n", "\n"]
)

# Load the .docx files
loader = DirectoryLoader("./", glob="*.docx", use_multithreading=True)
documents = loader.load()

# Split the documents into chunks
chunks = text_splitter.split_documents(documents)

# Print the number of chunks
print(len(chunks))
29

4. Vektör deposunu kurma ve doldurma

Chroma vektör deposunu başlatın ve metin parçalarını vektör veritabanına sağlayın. Metin, depolanmadan önce gömmelere dönüştürülecektir. Sonrasında vektör depomuzun düzgün biçimde doldurulup doldurulmadığını test etmek için bir benzerlik araması çalıştıracağız.

from langchain_chroma import Chroma

vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embed_model,
    persist_directory="./Vectordb",
)

query = "What is this tutorial about?"
docs = vectorstore.similarity_search(query)
print(docs[0].page_content)
Learn how to Fine-tune Stable Diffusion XL with DreamBooth and LoRA on your personal images. 

Let's try another prompt:

Prompt:

5. RAG hattını oluşturma

Sonraki adımda, vektör depomuzu bir getiriciye dönüştürecek ve RAG hattı için bir istem şablonu oluşturacağız.

# Create retriever
retriever = vectorstore.as_retriever()

# Import PromptTemplate
from langchain_core.prompts import PromptTemplate

# Define a clearer, more professional prompt template
template = """You are an expert assistant tasked with answering questions based on the provided documents.
Use only the given context to generate your answer.
If the answer cannot be found in the context, clearly state that you do not know.
Be detailed and precise in your response, but avoid mentioning or referencing the context itself.

Context:
{context}

Question:
{question}

Answer:"""

# Create the PromptTemplate
rag_prompt = PromptTemplate.from_template(template)

Son olarak, RAG istemine hem bağlamı hem soruyu sağlayan RAG zincirini oluşturacağız; bunu Llama 4 modelinden geçirip temiz bir yanıt üreteceğiz.

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | rag_prompt
    | llm
    | StrOutputParser()
)

Şimdi RAG zincirine belgeyle ilgili bir soru soracağız.

from IPython.display import display, Markdown

response = rag_chain.invoke("What this tutorial about?")
Markdown(response)
This tutorial is about setting up and using the Janus project, specifically Janus Pro, a multimodal model that can understand images and generate images from text prompts, and building a local solution to use the model privately on a laptop GPU. It covers learning about the Janus Series, setting up the Janus project, building a Docker container to run the model locally, and testing its capabilities with various image and text prompts.

Gördüğünüz gibi, yanıt son derece doğru ve bağlama duyarlı. Yukarıdaki kodu çalıştırırken herhangi bir sorunla karşılaşırsanız, lütfen şu DataLab çalışma kitabına bakın: Llama 4 RAG hattı.

Llama 4 Docx Sohbet Uygulamasını Oluşturma

Bu bölümde, önceki RAG hattı kodunu Gradio paketini kullanarak işlevsel bir sohbet uygulamasına dönüştüreceğiz. Başlamak için, aşağıdaki pip komutuyla Gradio'yu kurmanız gerekir:

$ pip install gradio

Uygulama basit ve kullanıcı dostu olacak şekilde tasarlanmıştır; tek bir .docx dosyası, birden çok .docx dosyası veya .docx dosyaları içeren bir .zip arşivi yüklemeyi sağlar. Kullanıcılar, yüklenen tüm dosyaların içeriği hakkında sorular sorabilir; bu da bilgiyi hızlı ve verimli şekilde getirmeyi sağlar.

Uygulamanın özellikleri:

  • Belge yükleme: Uygulama, yüklenen dosyalardan belgeleri doğrudan çıkarır ve yükler.
  • Metin bölme: Belgeler, verimli işleme ve getirim için yönetilebilir parçalara bölünür.
  • Vektör deposu entegrasyonu: ChromaDB yerine, belge gömmelerini yönetmek için bellekiçi vektör deposu kullanılır.
  • RAG hattı: Belge getirimi ile bir dil modelini birleştirerek yüklenen içeriğe dayalı doğru yanıtlar sağlar.
  • Kullanıcı arayüzü: Kullanıcıların soru sorup sağlanan belgelere dayalı ayrıntılı yanıtlar aldığı bir sohbet arayüzü sunar.
  • Hata yönetimi: Desteklenmeyen dosya türleri ve yükleme sırasında yaşanan sorunlar için geri bildirim sağlar ve kullanıcı deneyimini iyileştirir.
  • Sıfırlama işlevi: Kullanıcılar uygulama durumunu sıfırlayarak yeni belge yüklemeleriyle sıfırdan başlayabilir.

Haydi hepsini bir araya getirelim:

main.py:

# ========== Standard Library ==========
import os
import tempfile
import zipfile
from typing import List, Optional, Tuple, Union
import collections


# ========== Third-Party Libraries ==========
import gradio as gr
from groq import Groq
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import DirectoryLoader, UnstructuredFileLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_groq import ChatGroq
from langchain_huggingface import HuggingFaceEmbeddings

# ========== Configs ==========
TITLE = """<h1 align="center">🗨️🦙 Llama 4 Docx Chatter</h1>"""
AVATAR_IMAGES = (
    None,
    "./logo.png",
)

# Acceptable file extensions
TEXT_EXTENSIONS = [".docx", ".zip"]

# ========== Models & Clients ==========
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
client = Groq(api_key=GROQ_API_KEY)
llm = ChatGroq(model="meta-llama/llama-4-scout-17b-16e-instruct", api_key=GROQ_API_KEY)
embed_model = HuggingFaceEmbeddings(model_name="mixedbread-ai/mxbai-embed-large-v1")

# ========== Core Components ==========
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=100,
    separators=["\n\n", "\n"],
)

rag_template = """You are an expert assistant tasked with answering questions based on the provided documents.
Use only the given context to generate your answer.
If the answer cannot be found in the context, clearly state that you do not know.
Be detailed and precise in your response, but avoid mentioning or referencing the context itself.
Context:
{context}
Question:
{question}
Answer:"""
rag_prompt = PromptTemplate.from_template(rag_template)


# ========== App State ==========
class AppState:
    vectorstore: Optional[InMemoryVectorStore] = None
    rag_chain = None


state = AppState()

# ========== Utility Functions ==========


def load_documents_from_files(files: List[str]) -> List:
    """Load documents from uploaded files directly without moving."""
    all_documents = []

    # Temporary directory if ZIP needs extraction
    with tempfile.TemporaryDirectory() as temp_dir:
        for file_path in files:
            ext = os.path.splitext(file_path)[1].lower()

            if ext == ".zip":
                # Extract ZIP inside temp_dir
                with zipfile.ZipFile(file_path, "r") as zip_ref:
                    zip_ref.extractall(temp_dir)

                # Load all docx from extracted zip
                loader = DirectoryLoader(
                    path=temp_dir,
                    glob="**/*.docx",
                    use_multithreading=True,
                )
                docs = loader.load()
                all_documents.extend(docs)

            elif ext == ".docx":
                # Load single docx directly
                loader = UnstructuredFileLoader(file_path)
                docs = loader.load()
                all_documents.extend(docs)

    return all_documents


def get_last_user_message(chatbot: List[Union[gr.ChatMessage, dict]]) -> Optional[str]:
    """Get last user prompt."""
    for message in reversed(chatbot):
        content = (
            message.get("content") if isinstance(message, dict) else message.content
        )
        if (
            message.get("role") if isinstance(message, dict) else message.role
        ) == "user":
            return content
    return None


# ========== Main Logic ==========




def upload_files(
    files: Optional[List[str]], chatbot: List[Union[gr.ChatMessage, dict]]
):
    """Handle file upload - .docx or .zip containing docx."""
    if not files:
        return chatbot

    file_summaries = []  # <-- Collect formatted file/folder info
    documents = []

    with tempfile.TemporaryDirectory() as temp_dir:
        for file_path in files:
            filename = os.path.basename(file_path)
            ext = os.path.splitext(file_path)[1].lower()

            if ext == ".zip":
                file_summaries.append(f"📦 **{filename}** (ZIP file) contains:")
                try:
                    with zipfile.ZipFile(file_path, "r") as zip_ref:
                        zip_ref.extractall(temp_dir)
                        zip_contents = zip_ref.namelist()

                        # Group files by folder
                        folder_map = collections.defaultdict(list)
                        for item in zip_contents:
                            if item.endswith("/"):
                                continue  # skip folder entries themselves
                            folder = os.path.dirname(item)
                            file_name = os.path.basename(item)
                            folder_map[folder].append(file_name)

                        # Format nicely
                        for folder, files_in_folder in folder_map.items():
                            if folder:
                                file_summaries.append(f"📂 {folder}/")
                            else:
                                file_summaries.append(f"📄 (root)")
                            for f in files_in_folder:
                                file_summaries.append(f"   - {f}")

                    # Load docx files extracted from ZIP
                    loader = DirectoryLoader(
                        path=temp_dir,
                        glob="**/*.docx",
                        use_multithreading=True,
                    )
                    docs = loader.load()
                    documents.extend(docs)

                except zipfile.BadZipFile:
                    chatbot.append(
                        gr.ChatMessage(
                            role="assistant",
                            content=f"❌ Failed to open ZIP file: {filename}",
                        )
                    )

            elif ext == ".docx":
                file_summaries.append(f"📄 **{filename}**")
                loader = UnstructuredFileLoader(file_path)
                docs = loader.load()
                documents.extend(docs)

            else:
                file_summaries.append(f"❌ Unsupported file type: {filename}")

    if not documents:
        chatbot.append(
            gr.ChatMessage(
                role="assistant", content="No valid .docx files found in upload."
            )
        )
        return chatbot

    # Split documents
    chunks = text_splitter.split_documents(documents)
    if not chunks:
        chatbot.append(
            gr.ChatMessage(
                role="assistant", content="Failed to split documents into chunks."
            )
        )
        return chatbot

    # Create Vectorstore
    state.vectorstore = InMemoryVectorStore.from_documents(
        documents=chunks,
        embedding=embed_model,
    )
    retriever = state.vectorstore.as_retriever()

    # Build RAG Chain
    state.rag_chain = (
        {"context": retriever, "question": RunnablePassthrough()}
        | rag_prompt
        | llm
        | StrOutputParser()
    )

    # Final display
    chatbot.append(
        gr.ChatMessage(
            role="assistant",
            content="**Uploaded Files:**\n"
            + "\n".join(file_summaries)
            + "\n\n✅ Ready to chat!",
        )
    )
    return chatbot


def user_message(
    text_prompt: str, chatbot: List[Union[gr.ChatMessage, dict]]
) -> Tuple[str, List[Union[gr.ChatMessage, dict]]]:
    """Add user's text input to conversation."""
    if text_prompt.strip():
        chatbot.append(gr.ChatMessage(role="user", content=text_prompt))
    return "", chatbot


def process_query(
    chatbot: List[Union[gr.ChatMessage, dict]],
) -> List[Union[gr.ChatMessage, dict]]:
    """Process user's query through RAG pipeline."""
    prompt = get_last_user_message(chatbot)
    if not prompt:
        chatbot.append(
            gr.ChatMessage(role="assistant", content="Please type a question first.")
        )
        return chatbot

    if state.rag_chain is None:
        chatbot.append(
            gr.ChatMessage(role="assistant", content="Please upload documents first.")
        )
        return chatbot

    chatbot.append(gr.ChatMessage(role="assistant", content="Thinking..."))

    try:
        response = state.rag_chain.invoke(prompt)
        chatbot[-1].content = response
    except Exception as e:
        chatbot[-1].content = f"Error: {str(e)}"

    return chatbot


def reset_app(
    chatbot: List[Union[gr.ChatMessage, dict]],
) -> List[Union[gr.ChatMessage, dict]]:
    """Reset application state."""
    state.vectorstore = None
    state.rag_chain = None
    return [
        gr.ChatMessage(
            role="assistant", content="App reset! Upload new documents to start."
        )
    ]


# ========== UI Layout ==========

with gr.Blocks(theme=gr.themes.Soft()) as demo:
    gr.HTML(TITLE)
    chatbot = gr.Chatbot(
        label="Llama 4 RAG",
        type="messages",
        bubble_full_width=False,
        avatar_images=AVATAR_IMAGES,
        scale=2,
        height=350,
    )

    with gr.Row(equal_height=True):
        text_prompt = gr.Textbox(
            placeholder="Ask a question...", show_label=False, autofocus=True, scale=28
        )
        send_button = gr.Button(
            value="Send",
            variant="primary",
            scale=1,
            min_width=80,
        )
        upload_button = gr.UploadButton(
            label="Upload",
            file_count="multiple",
            file_types=TEXT_EXTENSIONS,
            scale=1,
            min_width=80,
        )
        reset_button = gr.Button(
            value="Reset",
            variant="stop",
            scale=1,
            min_width=80,
        )

    send_button.click(
        fn=user_message,
        inputs=[text_prompt, chatbot],
        outputs=[text_prompt, chatbot],
        queue=False,
    ).then(fn=process_query, inputs=[chatbot], outputs=[chatbot])

    text_prompt.submit(
        fn=user_message,
        inputs=[text_prompt, chatbot],
        outputs=[text_prompt, chatbot],
        queue=False,
    ).then(fn=process_query, inputs=[chatbot], outputs=[chatbot])

    upload_button.upload(
        fn=upload_files, inputs=[upload_button, chatbot], outputs=[chatbot], queue=False
    )
    reset_button.click(fn=reset_app, inputs=[chatbot], outputs=[chatbot], queue=False)

demo.queue().launch()

Llama 4 Docx Sohbet Uygulamasını Test Etme

Şimdi web uygulamasını çalıştırıp işlevlerini test edeceğiz. Uygulamayı başlatmak için terminalde aşağıdaki komutu çalıştırın:

$ python main.py 

Web sunucusu çalışmaya başladıktan sonra, web arayüzüne erişmek için şu URL'ye gidin veya tarayıcınıza kopyalayıp yapıştırın: http://127.0.0.1:7860

Sohbet arayüzümüz şöyle görünüyor:

llama 4 rag gradio arayüzü

.docx dosyaları içeren bir .zip dosyası yükleyeceğiz ve bunu yaparken zip dosyasının içindeki tüm klasör ve dosyaları göreceksiniz.

llama 4 rag gradio arayüz testi

Sonraki adımda, belgeler hakkında spesifik sorular sorabiliriz:

llama 4 rag gradio arayüz testi

Ayrıca birkaç saniye içinde yeni bir dosya yükleyip onun hakkında sohbet etmek için “Reset” düğmesine basabilirsiniz.

llama 4 rag gradio arayüz testi

Yerelde test ettikten sonra, web uygulamasını Hugging Face Space üzerinde ücretsiz olarak kolayca dağıtabilirsiniz. Dağıtılan uygulamanın bağlantısı: kingabzpro/Llama-4-RAG 

llama 4 rag gradio arayüz testi

Kaynak: kingabzpro/Llama-4-RAG 

Kod kaynağı, not defteri ve yapılandırma dosyaları kingabzpro/Llama-4-RAG deposunda bulunabilir. 

Sonuç

Uzun bağlam pencereli modellerin ortaya çıkmasına rağmen RAG asla modası geçmeyecek. RAG, harici kaynaklardan bilgi getirmede verimli ve maliyet-etkin bir yöntem olarak kalır ve modellere ek bağlam sağlar.

Ayrıca, RAG sistemlerini çalıştırmak, modele doğrudan kapsamlı bağlam beslemeye kıyasla doğası gereği daha ekonomiktir; bu da önemli hesaplama kaynakları gerektirir. Bu nedenle RAG, birçok kullanım senaryosu için pratik ve ölçeklenebilir bir çözümdür.

Llama 4 hakkında daha fazla bilgi edinmek için şu kaynaklara göz atın:


Abid Ali Awan's photo
Author
Abid Ali Awan
LinkedIn
Twitter

Sertifikalı bir veri bilimcisi olarak, yenilikçi makine öğrenimi uygulamaları oluşturmak için en son teknolojileri kullanmaya büyük ilgi duyuyorum. Konuşma tanıma, veri analizi ve raporlama, MLOps, konuşma yapay zekası ve NLP alanlarında güçlü bir geçmişe sahip olarak, gerçek bir etki yaratabilecek akıllı sistemler geliştirme becerilerimi geliştirdim. Teknik uzmanlığımın yanı sıra, karmaşık kavramları açık ve özlü bir dille ifade etme yeteneğine sahip, becerikli bir iletişimciyim. Sonuç olarak, veri bilimi konusunda aranan bir blog yazarı oldum ve giderek büyüyen veri profesyonelleri topluluğuyla görüşlerimi ve deneyimlerimi paylaşıyorum. Şu anda, içerik oluşturma ve düzenlemeye odaklanıyorum. Büyük dil modelleriyle çalışarak, hem işletmelerin hem de bireylerin verilerinden en iyi şekilde yararlanmalarına yardımcı olabilecek güçlü ve ilgi çekici içerikler geliştiriyorum.

Konular
Yapay Zeka
Büyük Dil Modelleri

Bu kurslarla yapay zekâyı öğrenin!

Kurs

Llama 3 ile Çalışmak

2 sa
15.7K
Llama LLM'yi yerel olarak çalıştırmak ve yığınınıza entegre etmek için en son teknikleri keşfedin.
Ayrıntıları GörüntüleRight Arrow
Kursa Başla
Devamını GörRight Arrow
İlgili

blog

Hızlı Sevkiyat İçin Pratik Vibe Kodlama Teknoloji Yığını

Ön uç, arka uç, veritabanları, kimlik doğrulama, depolama, e-posta, test, dağıtım ve izleme için en iyi araçları keşfedin.
Abid Ali Awan's photo

Abid Ali Awan

14 dk.

blog

2026’da En Popüler 40 Yazılım Mühendisi Mülakat Sorusu

Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Dario Radečić's photo

Dario Radečić

15 dk.

Eğitim

.gitignore Nasıl Kullanılır: Örneklerle Pratik Bir Giriş

Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Kurtis Pykes 's photo

Kurtis Pykes

8 dk.

Eğitim

Python'da Listeyi String'e Nasıl Dönüştürürsünüz

Bu hızlı eğitimde, Python'da bir listeyi string'e nasıl dönüştüreceğinizi öğrenin.
Adel Nehme's photo

Adel Nehme

Devamını GörDevamını Gör