19

Production-Ready LLM Sistemleri İnşa Etmek: Flowwise’dan LangChain v0.3, RAG ve Neo4j’ye Tam Rehber

AI & LLM ENGINEERING / PRODUCTION GUIDE

Building Production-Grade AI Applications with LangChain & LLMs

Görsel prototiplemeden production mimarisine; Flowwise AI, LangChain LCEL, Chainlit, Neo4j, RAG, ChromaDB, Ollama ve Modelfile kullanarak modern kurumsal LLM sistemlerinin nasıl tasarlanacağını adım adım inceleyelim.

01 / VISUAL PROTOTYPING

Low-Code / No-Code Visual Prototyping ve LangChain Primitifleri

LLM tabanlı kurumsal uygulamalar geliştirirken yapılan en büyük hatalardan biri doğrudan Python koduna gömülerek mimari akışı ve düğümler arasındaki bağımlılıkları gözden kaçırmaktır.

Production-grade bir yapay zeka sistemi inşa etmenin ilk adımı, sistem bileşenlerini, veri akış hattını ve ajan kararlarını hızlıca doğrulamaktır. Bu aşama bir Proof of Concept (PoC) olarak düşünülebilir.

Engineering Principle
Önce mimariyi görselleştir, sonra kodu üretime taşı. Görsel PoC, gereksiz kodlama maliyetini ve mimari hataları erkenden yakalamanın en hızlı yollarından biridir.

1.1 Containerize LLM Orkestrasyonu ve Flowwise AI

Production mimarilerinde sistem izolasyonu ve bağımlılık yönetimi kritik önem taşır. Configuration drift riskini azaltmak için Flowwise AI gibi araçları doğrudan host makinede çalıştırmak yerine Docker Container içerisinde izole etmek daha güvenlidir.

Docker Compose ile Isolation & Persistence

docker-compose.yml
version: '3.8'

services:
  flowwise:
    image: flowwiseai/flowwise:1.6.6
    container_name: flowwise_orchestrator
    restart: always

    ports:
      - "3000:3000"

    environment:
      - PORT=3000
      - DATABASE_PATH=/root/.flowwise
      - APIKEY_PATH=/root/.flowwise
      - SECRETKEY_PATH=/root/.flowwise
      - LOG_LEVEL=debug

    volumes:
      - ./flowwise_data:/root/.flowwise
01 / PORT

Environment & Port Mapping

Flowwise container içerisinde 3000 portunda çalışırken host seviyesinde farklı bir porta map edilebilir.

02 / STORAGE

Volume Persistence

/root/.flowwise dizininin host makineye bağlanması, container yeniden başlatılsa bile flow ve yetkilendirme verilerinin korunmasını sağlar.

03 / DEBUG

Debug Logging

LOG_LEVEL=debug, zincir çağrıları sırasında LLM'e giden prompt ve dönen payload'ları ayrıntılı incelemeye yardımcı olur.

04 / ISOLATION

Container Boundary

Bağımlılıkların ve runtime state'in izole edilmesi production deployment sürecini daha kontrollü hale getirir.

1.2 LangChain Temel Primitifleri

LangChain ekosistemi LLM etrafında soyutlanmış modüler Nodes / Runnables yapısından oluşur. Görsel arayüzdeki her düğüm, Python veya TypeScript SDK tarafında karşılığı bulunan bir bileşene denk gelir.

ChatPromptTemplate
System + User
Chat Model
GPT / Claude / LLM
Output Parser
Raw / Structured

Prompt Engineering: ChatPromptTemplate

Modern LLM uygulamalarında mesajları mantıksal rollere ayırmak için ChatPromptTemplate kullanılır.

SYSTEM

System Message

Modelin kimliğini, sınırlarını, görevini, üslubunu ve güvenlik davranışlarını belirler.

HUMAN

Human Message

Kullanıcıdan gelen dinamik girdiyi veya RAG context bilgisini temsil eder.

AI

AI Message

Modelin geçmiş konuşmalarda verdiği yanıtların temsilidir.

RUNTIME

Dynamic Variables

{variable_name} biçimindeki değişkenler chain çalışırken runtime sırasında enjekte edilir.

1.3 Prompt Chaining & Query Rewriting

Kullanıcının ham girdisi bazen RAG sistemine veya ana LLM'e gönderilemeyecek kadar bozuk, eksik ya da belirsiz olabilir. Bu durumda Sequential Chaining yaklaşımı uygulanabilir.

User Query
Query Refiner LLM
Clean Prompt
Main LLM
Result

İlk zincir düşük temperature değerine sahip deterministik bir modelle sorguyu temizler. İkinci zincir ise bu çıktıyı business logic'in uygulanacağı ana modele aktarır.

RAG Impact
Query rewriting özellikle RAG sistemlerinde semantic retrieval precision değerini artırabilir. Arama motoruna gönderilen sorgu ne kadar iyi normalize edilirse ilgili context'in bulunma ihtimali de o kadar yükselir.

1.4 Agents ve Tool Calling

Statik chain'lerin aksine Agent yapıları dinamik karar verme yeteneğine sahiptir. Agent, kendisine verilen hedef doğrultusunda hangi Tool'un ne zaman ve hangi parametrelerle çağrılacağına karar verir.

User Request
Agent Decision Loop
Search Tool
Calculator
Observation
Final Output

Tool Calling neden gereklidir?

  1. Search Tools: Güncel haber, hava durumu veya canlı API verilerini almak için kullanılır.
  2. Calculator: Matematiksel hesapları deterministic biçimde gerçekleştirmek için kullanılır.
  3. Custom Code Tools: Python veya JavaScript ile özel business logic çalıştırılmasını sağlar.

Burada kritik detay tool tanımlarındaki description alanıdır. Agent, hangi tool'un hangi problemi çözebileceğine büyük ölçüde bu açıklamalar üzerinden karar verir.

1.5 Visual Flow → REST API

PoC olarak oluşturulan Flowwise chatflow production'da görsel arayüzde bırakılmamalı; dış sistemlerin tüketebileceği modüler bir REST API katmanına dönüştürülmelidir.

Özellikle multi-user sistemlerde sessionId yönetimi kritik önem taşır. Aksi durumda bir kullanıcının sohbet geçmişinin başka bir kullanıcıya sızması mümkün olabilir.

python / flowwise_api.py
import requests

FLOWWISE_API_URL = (
    "http://localhost:3000/api/v1/prediction/YOUR-CHATFLOW-ID"
)

def query_ai_pipeline(
    user_message: str,
    user_session_id: str
) -> dict:

    payload = {
        "question": user_message,
        "overrideConfig": {
            "sessionId": user_session_id,
            "returnOption": True
        }
    }

    headers = {
        "Content-Type": "application/json"
    }

    response = requests.post(
        FLOWWISE_API_URL,
        json=payload,
        headers=headers
    )

    if response.status_code == 200:
        return response.json()

    raise Exception(
        f"API Hatası [{response.status_code}]: "
        f"{response.text}"
    )

result = query_ai_pipeline(
    "Ankara'da bugün hava nasıl?",
    user_session_id="usr_123_sess_99"
)

print(result)

Bölüm 1 — Architecture Takeaways

  • Node bazlı düşünme ve bileşen bağımlılıklarını görselleştirdik.
  • ChatPromptTemplate ile mesaj rollerini ayırdık.
  • Query rewriting ile input kalitesini artırdık.
  • Agent ve Tool Calling ile LLM'in sınırlarını dış araçlarla genişlettik.
  • REST API ve sessionId ile Flowwise PoC'yi servis katmanına taşıdık.
02 / PRODUCTION PYTHON

Production-Grade Python Mimarisi: LCEL, Chainlit, Memory & Observability

Visual prototyping mimariyi anlamak için güçlü bir başlangıçtır. Ancak sistem production'a taşındığında tam kontrol, performans, state yönetimi, güvenlik ve observability gereksinimleri nedeniyle kod tabanlı mimariye geçiş gerekir.

2.1 LangChain v0.3 ve LCEL

LangChain Expression Language (LCEL), bileşenleri Runnable nesneleri olarak birleştiren deklaratif bir mimaridir. Asenkron çalıştırma, streaming ve batch işlemleri bu yaklaşımın doğal parçalarıdır.

Prompt
|
Model
|
Parser
String
lcel_chain.py
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    (
        "system",
        "Sen kıdemli bir yazılım mimarısın. "
        "Soruları teknik detaylarıyla yanıtla."
    ),
    ("user", "{question}")
])

model = ChatAnthropic(
    model="claude-3-5-sonnet-20240620",
    temperature=0.2,
    max_tokens=2048
)

parser = StrOutputParser()

chain = prompt | model | parser

# async response
# response = await chain.ainvoke({
#     "question": "LCEL'in avantajları nelerdir?"
# })

Bu declarative yapı sayesinde Prompt → Model → Parser hattı daha okunabilir hale gelir. Ayrıca zincirin herhangi bir noktasına middleware veya interceptor eklemek kolaylaşır.

2.2 Memory ve Context Window Optimizasyonu

LLM'in ağırlıkları dışında kalıcı bir sohbet state'i bulunmaz. Conversation memory, geçmiş mesajların modele yeniden taşınmasıyla simüle edilir. Ancak konuşma büyüdükçe context window ve token maliyetleri kritik hale gelir.

User Message
Memory Strategy
Buffer
/
Window
/
Summary
LLM Context
Memory Çalışma Mantığı Avantaj Dezavantaj
Buffer Tüm geçmişi ham haliyle tutar. Kısa sohbetlerde basit ve güçlüdür. Token maliyeti sürekli büyür.
Buffer Window Son K mesajı tutar. Context boyutunu sınırlar. Eski bilgiler kaybolabilir.
Summary Buffer Eski konuşmaları özetler, son mesajları ham tutar. Context ve token kullanımını optimize eder. Özetleme için ek LLM çağrısı gerekir.

2.3 Graph Tabanlı Memory: Neo4j

KV veya düz metin tabanlı memory sistemleri kullanıcılar, kavramlar ve olaylar arasındaki ilişkileri takip etmekte sınırlıdır. Knowledge Graph yaklaşımında bu bilgiler node ve relationship olarak saklanır.

User: Volkan
→ HAS_ROLE →
Developer
Python
neo4j_memory.py
from langchain_community.chat_message_histories \
    import Neo4jChatMessageHistory

def get_neo4j_memory(session_id: str):
    return Neo4jChatMessageHistory(
        session_id=session_id,
        url="bolt://localhost:7687",
        username="neo4j",
        password="your_password"
    )

memory = get_neo4j_memory(
    "usr_volkan_sess_01"
)

memory.add_user_message(
    "Ben Volkan, Python geliştiricisiyim."
)

memory.add_ai_message(
    "Merhaba Volkan! Python projelerinde "
    "nasıl yardımcı olabilirim?"
)

2.4 Chainlit UI ve Lifecycle Management

Production LLM UI katmanında hızlı yanıt, asynchronous streaming, session management ve dosya yükleme gibi özellikler gerekir. Chainlit bu ihtiyaçları Python tabanlı bir UI katmanı olarak karşılar.

@cl.on_chat_start

Session Initialization

Chain, memory ve kullanıcıya özel konfigürasyonların hazırlandığı aşamadır.

@cl.on_message

Message Handler

Kullanıcı her mesaj gönderdiğinde asenkron olarak tetiklenir.

@cl.on_stop

Stop Generation

Kullanıcının yanıt üretimini durdurduğu durumda devreye girer.

@cl.on_chat_resume

Session Resume

Kesilmiş veya eski bir oturuma authentication ve persistence ile geri dönmeyi sağlar.

chainlit_app.py
import chainlit as cl
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

@cl.on_chat_start
async def on_chat_start():
    prompt = ChatPromptTemplate.from_messages([
        ("system", "Sen yardımcı bir AI asistanısın."),
        ("user", "{question}")
    ])

    model = ChatAnthropic(
        model="claude-3-5-sonnet-20240620",
        streaming=True
    )

    chain = prompt | model | StrOutputParser()

    cl.user_session.set("chain", chain)

    await cl.Message(
        content="Sisteme hoş geldiniz!"
    ).send()

@cl.on_message
async def on_message(message: cl.Message):
    chain = cl.user_session.get("chain")

    msg = cl.Message(content="")
    await msg.send()

    async for chunk in chain.astream({
        "question": message.content
    }):
        await msg.stream_token(chunk)

    await msg.update()

2.5 Authentication & PostgreSQL Data Layer

Production ortamında uygulamanın yetkisiz erişime kapatılması ve sohbet verilerinin kalıcı bir ilişkisel veritabanında tutulması gerekir.

authentication.py
import chainlit as cl

@cl.password_auth_callback
def auth_callback(
    username: str,
    password: str
):
    # Production'da password hash kontrolü yapılmalıdır.
    if username == "admin" and password == "secure_password_123":
        return cl.User(
            identifier=username,
            metadata={
                "role": "admin",
                "provider": "credentials"
            }
        )

    return None
postgres_data_layer.py
from chainlit.data.sql_alchemy \
    import SQLAlchemyDataLayer
import chainlit as cl

DATABASE_URL = (
    "postgresql+asyncpg://"
    "postgres:admin_password@"
    "localhost:5432/chainlit_db"
)

@cl.data_layer
def setup_data_layer():
    return SQLAlchemyDataLayer(
        conninfo=DATABASE_URL
    )
USERS

User Profiles

Kullanıcı kimlik ve profil bilgilerinin tutulduğu katman.

THREADS

Sessions

Sohbet ve oturum başlıklarını temsil eder.

STEPS

LLM / Tool Steps

LLM çağrıları, tool çalışmaları ve ara adımlar burada izlenebilir.

FEEDBACKS

User Feedback

Kullanıcıların olumlu veya olumsuz değerlendirmelerini saklar.

2.6 Observability & Telemetry

Klasik APM sistemleri LLM uygulamalarındaki token kullanımı, model latency'si ve chain içindeki ara adımlar gibi AI-spesifik metrikleri tek başına yeterince açıklayamaz.

User Message
Query Translation
120ms / 45 tokens
Vector Search
85ms
Final Response
850ms / 310 tokens
telemetry.py
import chainlit as cl

@cl.step(
    type="tool",
    name="Translator Step"
)
async def translate_to_english(
    text: str
) -> str:
    translated = f"[Translated]: {text}"
    return translated
Observability
Tek bir API anahtarı ile LLM input/output içerikleri, token maliyetleri ve kullanıcı feedback'leri merkezi telemetry katmanına aktarılabilir.
03 / KNOWLEDGE LAYER

RAG: Retrieval-Augmented Generation, Embedding & Vector Databases

LLM'lerin en büyük teknik kısıtlarından biri yalnızca eğitildikleri bilgilerle sınırlı olmaları ve bilmedikleri konularda ikna edici fakat yanlış yanıtlar üretebilmeleridir.

RAG, modelin parametrik hafızasına güvenmek yerine sorgu sırasında harici bilgi deposundan ilgili parçaları bulup bunları modelin context'ine ekleyen mimaridir.

RAG Mental Model
RAG, modeli yeniden eğitmeden modele yeni bilgi kullandırmanın en esnek yöntemlerinden biridir. Modelin ağırlıklarını değiştirmez; inference sırasında doğru context'i sağlar.

3.1 RAG Pipeline

PDF / TXT
Chunking
Embedding
Vector DB

User Query
Query Embedding
Semantic Search
Top-K Context
LLM
01 / INDEXING

Offline / Batch

Dokümanlar okunur, chunk'lara ayrılır, embedding'e çevrilir ve Vector DB'ye kaydedilir.

02 / RETRIEVAL

Runtime Search

Kullanıcı sorgusu vektörleştirilir ve en alakalı Top-K parçalar semantic similarity ile bulunur.

03 / GENERATION

Context + LLM

Bulunan context ile kullanıcının sorusu system prompt içerisinde birleştirilerek LLM'e gönderilir.

04 / GROUNDING

Controlled Answers

Modelin yalnızca sağlanan context üzerinden cevap vermesi hallucination riskini azaltır.

3.2 Chunking Strategy

Büyük dokümanı tek seferde modele göndermek hem token maliyetini artırır hem de retrieval kalitesini düşürebilir. Bu nedenle dokümanlar anlamlı parçalara bölünür.

chunking.py
from langchain_text_splitters import \
    RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len,
    is_separator_regex=False,
    separators=[
        "\n\n",
        "\n",
        " ",
        ""
    ]
)
CHUNK_SIZE

Parça Boyutu

Çok küçük değerler context'i bölebilir; çok büyük değerler retrieval precision'ı düşürebilir.

OVERLAP

Context Continuity

Parçalar arasında ortak metin bırakarak cümle veya paragraf sınırlarında oluşabilecek anlam kaybı azaltılır.

3.3 Embedding ve Vector Space

Embedding, metinsel ifadeyi çok boyutlu bir vektöre dönüştürür. Anlamsal olarak benzer ifadeler vektör uzayında birbirlerine yakın konumlanır.

"Köpek"
"Kaniş"
"Veritabanı"

Kosinüs Benzerliği

Similarity
İki vektör arasındaki açının kosinüsü hesaplanarak anlamsal yakınlık ölçülebilir. Değer 1'e yaklaştıkça yönler daha benzer, 0'a yaklaştıkça daha ilgisiz kabul edilir.

3.4 ChromaDB ve SHA-256 Deduplication

Aynı dokümanın tekrar tekrar vector database'e eklenmesi hem storage büyümesine hem de retrieval sırasında aynı bilginin birden fazla kez dönmesine neden olabilir.

vector_store.py
import hashlib
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain_core.documents import Document

embedding_model = OllamaEmbeddings(
    model="bge-m3:latest",
    base_url="http://localhost:11434"
)

vector_store = Chroma(
    collection_name="enterprise_knowledge",
    embedding_function=embedding_model,
    persist_directory="./chroma_db_storage"
)

def add_documents_with_deduplication(
    documents: list[Document]
):
    new_docs = []
    new_ids = []

    existing_ids = set(
        vector_store.get()["ids"]
    )

    for doc in documents:
        content_hash = hashlib.sha256(
            doc.page_content.encode("utf-8")
        ).hexdigest()

        if content_hash not in existing_ids:
            new_docs.append(doc)
            new_ids.append(content_hash)
            existing_ids.add(content_hash)

    if new_docs:
        vector_store.add_documents(
            documents=new_docs,
            ids=new_ids
        )
        print(
            f"✅ {len(new_docs)} yeni benzersiz "
            "parça eklendi."
        )
    else:
        print(
            "ℹ️ Tüm dokümanlar zaten mevcut."
        )

3.5 Chainlit ile End-to-End RAG

rag_app.py
import chainlit as cl
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

embedding_function = OllamaEmbeddings(
    model="bge-m3:latest",
    base_url="http://localhost:11434"
)

vector_store = Chroma(
    collection_name="pdf_rag_app",
    embedding_function=embedding_function,
    persist_directory="./pdf_chroma_db"
)

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20240620",
    temperature=0.1
)

@cl.step(
    type="retriever",
    name="Vector DB Search"
)
async def retrieve_context(query: str):
    docs = vector_store.similarity_search(
        query,
        k=3
    )

    context_text = "\n\n---\n\n".join(
        d.page_content for d in docs
    )

    cl.user_session.set(
        "retrieved_docs",
        docs
    )

    return context_text

@cl.on_chat_start
async def on_start():
    files = None

    while files is None:
        files = await cl.AskFileMessage(
            content="PDF yükleyin:",
            accept=["application/pdf"],
            max_size_mb=20,
            timeout=180
        ).send()

    file = files[0]

    msg = cl.Message(
        content=f"📄 `{file.name}` işleniyor..."
    )

    await msg.send()

    loader = PyPDFLoader(file.path)
    raw_docs = loader.load()

    splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200
    )

    chunks = splitter.split_documents(
        raw_docs
    )

    vector_store.add_documents(chunks)

    msg.content = (
        f"✅ `{file.name}` başarıyla indekslendi "
        f"({len(chunks)} parça)."
    )

    await msg.update()

Strict Grounding Prompt

grounded_prompt.py
prompt_template = ChatPromptTemplate.from_messages([
    (
        "system",
        """
        Sen kurumsal bir doküman asistanısın.

        Aşağıda verilen BAĞLAM bilgisini kullanarak
        kullanıcının sorusunu yanıtla.

        Eğer verilen bağlamda cevap YOKSA,
        kesinlikle bilgi uydurma.

        Şu yanıtı ver:
        'Verilen dokümanda bu konuyla ilgili
        yeterli bilgi bulunmamaktadır.'

        BAĞLAM:
        {context}
        """
    ),
    ("user", "{question}")
])

chain = (
    prompt_template
    | llm
    | StrOutputParser()
)

Bölüm 3 — RAG Architecture Takeaways

  • Indexing → Retrieval → Generation hattını oluşturduk.
  • Recursive Chunking ile dokümanları anlamlı parçalara ayırdık.
  • Embedding ve semantic similarity ile ilgili context'i bulduk.
  • SHA-256 ile duplicate kayıtları engelledik.
  • ChromaDB ve Chainlit ile canlı RAG uygulaması kurduk.
  • Strict Grounding prompt ile modelin context dışına çıkmasını sınırladık.
04 / LOCAL AI

Veri Gizliliği, Local LLM Orkestrasyonu, Quantization & Ollama

Kurumsal AI sistemlerinde hassas finansal bilgiler, müşteri verileri, kaynak kodları ve KVKK/GDPR kapsamındaki içeriklerin üçüncü taraf cloud endpoint'lerine gönderilmesi her zaman kabul edilebilir değildir.

Bu nedenle bazı kullanım senaryolarında Zero Data Leakage prensibiyle çalışan local inference mimarisi daha uygun hale gelir.

Local AI Principle
Veri kurum içinde kalır → model kurum içinde çalışır → inference endpoint'i kurum içinde tutulur.

4.1 Open-Weights Model Ekosistemi

Modern açık ağırlıklı model ekosisteminde Llama, Mistral, Gemma ve farklı üreticilerin modelleri bulunmaktadır. Bu modeller local inference altyapılarında çalıştırılabilir.

Open-Weight Model
Quantization
Inference Engine
Local GPU / LPU

4.2 Quantization Nedir?

Model ağırlıkları yüksek hassasiyetli veri tiplerinden daha küçük veri tiplerine dönüştürülerek bellek kullanımı azaltılabilir.

FP16
16-bit
INT8
8-bit
INT4
4-bit
Format Hassasiyet Bellek Kullanım
FP16 En yüksek Yüksek GPU / yüksek kalite inference
Q8_0 Çok yüksek Daha düşük Kalite odaklı quantized inference
Q4_K_M Pratikte yüksek Çok daha düşük Tüketici GPU / laptop local inference

4.3 GPU vs CPU vs LPU

GPU

Parallel Matrix Compute

Model ağırlıklarının VRAM'e yüklenmesiyle yüksek token/saniye değerlerine ulaşabilen standart inference donanımıdır.

CPU + RAM

Fallback Compute

VRAM yetersiz olduğunda model sistem RAM'i üzerinden çalışabilir. Ancak memory bandwidth darboğazı inference hızını düşürür.

LPU

Language Processing

Metin üretim iş yüklerine özel tasarlanmış accelerator mimarileri çok düşük latency ve yüksek token throughput hedefler.

KEY METRIC

Tokens / Second

Local inference performansını değerlendirirken latency yanında token/saniye önemli bir ölçüttür.

4.4 Ollama ile Local LLM Orkestrasyonu

Ollama, karmaşık C++ veya llama.cpp kurulum detaylarıyla uğraşmadan local makinede LLM'leri çalıştırmayı ve REST API üzerinden erişmeyi kolaylaştırır.

LangChain App
HTTP / JSON →
Ollama :11434
Local GPU / VRAM

Ollama varsayılan olarak 11434 portu üzerinden REST API yayınlar. Bu API CLI, Docker veya Python uygulamaları tarafından kullanılabilir.

Docker ile GPU Destekli Ollama

docker-compose.yml
version: '3.8'

services:
  ollama_engine:
    image: ollama/ollama:latest
    container_name: local_ollama_server
    restart: always

    ports:
      - "11434:11434"

    volumes:
      - ./ollama_storage:/root/.ollama

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Ollama CLI Temel Komutları

terminal
# Model indir
ollama pull llama3.1:8b

# Kurulu modelleri listele
ollama list

# Interaktif sohbet
ollama run llama3.1:8b

# Aktif modeller
ollama ps
05 / MODEL CONFIGURATION

Fine-Tuning Alternatifi: Modelfile ile Model Konfigürasyonu

Bir modelin davranışını, rolünü veya context window'unu değiştirmek için her zaman sıfırdan fine-tuning yapmak gerekmez. Ollama'nın Modelfile yaklaşımı, var olan bir modeli deklaratif biçimde yeni bir model varyantına dönüştürmeye izin verir.

Mental Model
Modelfile yaklaşımını bir çeşit Dockerfile for LLM behavior gibi düşünebilirsin: FROM ile model seçilir, PARAMETER ile çalışma davranışı değiştirilir ve SYSTEM ile rol/sınırlar tanımlanır.

5.1 Modelfile Yapısı

Modelfile
# Base Model
FROM llama3.1:8b

# Hyperparameters
PARAMETER temperature 0.2
PARAMETER top_p 0.9
PARAMETER num_ctx 8192

# System Prompt
SYSTEM """
Sen 'CyberSec Assistant' adında
kurumsal bir siber güvenlik uzmanısın.

Sana sorulan sorulara yalnızca:
* siber güvenlik
* ağ güvenliği
* güvenli kodlama
çerçevesinde yanıt ver.

Konu dışı sorulara:
'Bu konu siber güvenlik kapsamım dışındadır.'
yanıtını ver.

Yanıtlarını Türkçe üret.
"""

5.2 Critical Parameters

Parameter Ne yapar? Teknik Asistan İçin
num_ctx Modelin tek seferde işleyebileceği context kapasitesini belirler. Uzun doküman ve conversation history için artırılabilir.
temperature Çıktının rastgelelik derecesini kontrol eder. Kod ve teknik görevlerde düşük değerler tercih edilir.
top_p Kelime seçiminde dikkate alınan olasılık havuzunu sınırlar. Daha kontrollü generation sağlar.

Context Window

Uzun dokümanlar veya geniş conversation history ile çalışan sistemlerde context window kritik hale gelir. num_ctx değerinin artırılması modelin tek seferde daha fazla token görmesini sağlar; ancak bu durum bellek kullanımını da artırır.

2K Context
8K Context
16K Context

5.3 Özel Modeli Build Etme

terminal
ollama create cybersec-llama3 -f ./Modelfile

Bu işlem sonrasında cybersec-llama3 adıyla özel bir model varyantı oluşturulur. Böylece temel modelin ağırlıklarını yeniden eğitmeden role, context boyutuna ve generation parametrelerine önceden belirlenmiş davranışlar kazandırılır.

5.4 LangChain ile Local Model Integration

local_llm.py
from langchain_community.chat_models import ChatOllama
from langchain_community.embeddings import OllamaEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Local Chat Model
local_llm = ChatOllama(
    base_url="http://localhost:11434",
    model="cybersec-llama3",
    temperature=0.1,
    num_ctx=8192
)

# Local Embedding Model
local_embeddings = OllamaEmbeddings(
    base_url="http://localhost:11434",
    model="bge-m3:latest"
)

# Prompt
prompt = ChatPromptTemplate.from_messages([
    (
        "system",
        "Sana verilen sorguları dikkatle analiz et."
    ),
    ("user", "{input}")
])

# LCEL Chain
cyber_chain = (
    prompt
    | local_llm
    | StrOutputParser()
)

async def main():
    query = (
        "SQL Injection saldırılarına karşı "
        "Python FastAPI'de nasıl önlem alınır?"
    )

    print(
        "🤖 Yerel LLM Yanıtı Üretiliyor..."
    )

    async for chunk in cyber_chain.astream({
        "input": query
    }):
        print(
            chunk,
            end="",
            flush=True
        )
Zero Data Leakage Architecture
Bu mimaride prompt → LangChain → Ollama → Local Model hattı kurum içerisinde tutulabilir. Özellikle hassas kurumsal verilerle çalışan sistemlerde bu yaklaşım önemli bir güvenlik avantajıdır.
06 / FULL ARCHITECTURE

Serinin Tam Mimarisi

Buraya kadar konsept aşamasından production-grade, local ve gözlemlenebilir AI mimarisine kadar bütün temel katmanları ele aldık.

Flowwise
LangChain / LCEL
Chainlit
RAG
ChromaDB
Ollama
Local LLM
01

Flowwise AI

Node bağımlılıklarını ve LLM pipeline'larını görsel olarak doğrulamak için PoC katmanı.

02

LangChain / LCEL

Visual PoC'yi production Python chain'lerine dönüştüren declarative orchestration katmanı.

03

Chainlit

Streaming, session management, authentication ve kullanıcı deneyimi için UI katmanı.

04

Neo4j / Memory

Conversation state ve kullanıcılar arasındaki anlamsal ilişkileri yönetmek için gelişmiş memory katmanı.

05

RAG / ChromaDB

Kurumsal dokümanları embedding ve semantic retrieval ile LLM context'ine bağlayan bilgi katmanı.

06

Ollama / Local LLM

Hassas verilerin kurum içinde tutulmasını sağlayan local inference ve orchestration katmanı.

Production Checklist

  • Architecture: Önce node ve pipeline bağımlılıklarını görselleştir.
  • Orchestration: LCEL ile Prompt → Model → Parser zincirlerini deklaratif oluştur.
  • Memory: Context window ve token maliyetine göre Buffer, Window, Summary veya Graph memory seç.
  • Knowledge: Şirket verilerini RAG üzerinden modele getir.
  • Retrieval: Chunking, embedding, semantic similarity ve Top-K seçimlerini doğru tasarla.
  • Deduplication: SHA-256 gibi deterministic ID stratejileriyle duplicate embedding'leri engelle.
  • Security: Authentication, session isolation ve database persistence mekanizmalarını production'a dahil et.
  • Observability: Token, latency, tool execution ve model adımlarını telemetry sistemi üzerinden izle.
  • Privacy: Hassas kurumsal veriler için local inference ve Ollama gibi çözümleri değerlendir.
  • Model Behavior: Fine-tuning yapmadan önce Modelfile + System Prompt + generation parameter yaklaşımını değerlendir.
Final Architecture Principle
Modern bir AI uygulaması yalnızca bir LLM çağrısından ibaret değildir. Production-grade sistem; orchestration + memory + retrieval + security + observability + inference infrastructure katmanlarının birlikte tasarlanmasıyla ortaya çıkar.
AI & LLM Engineering — Production Architecture Guide

Yorum bırakın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir