Türk çiftçileri, tarım teknikerleri ve tarımsal girişimciler için geliştirilmiş; hibe programları ve zirai mücadele konularında Türkçe / İngilizce inline alıntılarla yanıt veren, offline-first RAG chatbotu.
Nasıl Çalışır · Hızlı Başlangıç · Yapılandırma · API · Bilgi Tabanı
Canlı demo, Render'ın ücretsiz katmanında Gemini cloud modunda çalışmaktadır. Uzun bir hareketsizlik döneminin ardından gelen ilk istek, instance uyanırken yaklaşık bir dakika sürebilir.
- Neden Var
- Özellikler
- Nasıl Çalışır
- Mimari
- Proje Yapısı
- Hızlı Başlangıç
- Çıkarım Arka Uçları
- Yapılandırma
- API
- Bilgi Tabanı
- Testler
- Dağıtım
- Önemli Tasarım Kararları
- Kısıtlamalar
- Lisans
Her yıl binlerce çiftçi; IPARD III hibe başvurusu, TKDK destekleri, mazot-gübre ödemeleri, zirai mücadele takvimi ve TARSİM sigortası gibi konuları on farklı bakanlık sayfasından, eski tebliğlerden ve dağınık PDF dosyalarından bulmak zorunda kalıyor — üstelik büyük bölümü teknik dille yazılmış.
Bu proje, tüm bu belge kümesini bir retrieval-augmented generation (RAG) chatbotuna dönüştürür: Türkçe veya İngilizce sorulan bir soruya, yalnızca yüklenen kaynak belgelerden yararlanarak, her bilginin hangi belgeden ve hangi sayfadan geldiğini gösteren tıklanabilir inline alıntılarla yanıt verir. Yerel çalıştırıldığında internet bağlantısı gerektirmez ve hiçbir veriyi üçüncü tarafla paylaşmaz; web bağlantısı olarak dağıtıldığında ise çiftçiler doğrudan URL'yi açarak kullanabilir.
| 🌍 İki Dilli | Türkçe veya İngilizce sorun; yanıt sorduğunuz dilde gelir (TR/EN toggle) |
| 📎 Inline Alıntılar | Her bilgi, kaynağın tam sayfasına veya PDF bölümüne bağlanan numaralı bir chip ile işaretlenir |
| 🔒 Varsayılan Offline | Embedding ve sohbet çıkarımı, Microsoft Foundry Local (Ollama yedek) ile cihaz üzerinde çalışır — veri dışarı çıkmaz |
| ☁️ İsteğe Bağlı Cloud | İki ortam değişkenini değiştirerek Gemini üzerinde çalıştırın ve asistanı herkese açık bağlantı olarak paylaşın |
| 🧠 Konuşma Belleği | "Peki seracılık için şart nedir?" gibi takip soruları önceki konuşma turlarına göre çözümlenir |
| 🔀 Topic Router | Gelen soru (Hibe / Zirai Mücadele / Sulama / Sigorta / Organik / Kapsam Dışı) kategorilerine otomatik sınıflandırılır; ilgili belge grubu seçilir |
| 🈯 Çeviri Köprüsü | İngilizce sorular yalnızca retrieval için Türkçeye çevrilir; böylece retrieval kalitesi embedder'ın çok dilli kabiliyetine bağlı kalmaz |
| 🚫 Tahmin Yapmayı Reddeder | Benzerlik eşiğinin altındaki parçalar gürültü olarak atılır; kapsam dışı sorulara dürüstçe "Bu konuda bilgim yok" yanıtı döner |
| 🎨 Özel Arayüz | El yapımı, mobil uyumlu sohbet arayüzü — geçmiş kenar çubuğu, konu filtreleri, öneri chip'leri, kaynak pill'leri, çerez onayı modalı |
| 📊 Sorgu Günlüğü | Rate-limit dahil her soru ayrı bir SQLite veritabanına kalıcı olarak kaydedilir; token korumalı admin endpoint üzerinden okunabilir |
| 🛡️ Güvenli Uç Noktalar | IP başına kayan pencere rate limiting, sınırlı istek gövdeleri, sabit zamanlı admin token kontrolü, ayrışık 429 / 503 hata semantiği |
| ✅ Test Edilmiş | Loader, chunker, embedder, store, generator, query log ve HTTP katmanını kapsayan pytest test paketi |
-
Yükleme (Ingestion) — Kaynak belgeler (
.md,.txt,.pdf) kaynak adı/URL metadata'sıyla birlikte yüklenir, paragraf boyutlu parçalara (~200–500 kelime) bölünür, embed edilir ve yerel SQLite veritabanında saklanır. -
Sınıflandırma (Topic Routing) — Gelen soru önce bir LLM çağrısıyla
A–Gkategorilerinden birine atanır; ilgili belge koleksiyonu seçilir. -
Geri Çağırma (Retrieval) — Soru embed edilerek depolanan tüm parçalarla kosinüs benzerliği üzerinden puanlanır; minimum eşiğin üzerindeki ilk K eşleşme tutulur, geri kalanı gürültü olarak atılır.
-
Çeviri Köprüsü — Belgeler Türkçe olduğundan, İngilizce sorular yalnızca retrieval için Türkçeye çevrilir. Modelin yanıtladığı, orijinal sorudur (ve orijinal dildir).
-
Konuşma Belleği — Mevcut sohbetin son birkaç turu prompt'a eklenir; böylece takip soruları az önce tartışılanla ilişkilendirilir. Retrieval'ın kendisi yalnızca güncel soruya karşı çalışır; geçmiş yalnızca yanıtlama çağrısını besler.
-
Üretim (Generation) — Soru, geri çağrılan parçalar ve son geçmiş, yapılandırılmış chat modeline gönderilir; model sorunun orijinal dilinde yanıt verir ve alıntıları inline olarak
[n]biçiminde işaretler. -
Render — Ham yanıt,
segmentslistesine (değişen metin ve alıntı işaretleyicileri) ve tekilleştirilmiş birsourceslistesine ayrıştırılır; frontend bunları tıklanabilir chip'ler ve kaynak pill satırı olarak gösterir.
flowchart TD
subgraph ingest["Yükleme — scripts/ingest.py (offline, her deploy'da bir kez çalışır)"]
D["belgeler/<br/>md · txt · pdf"] --> L["loader.py<br/>metin + kaynak metadata"]
L --> C["chunker.py<br/>~200-500 kelimelik parçalar"]
C --> E1["embedder.py"]
E1 --> DB[("knowledge.db<br/>parçalar + embedding'ler")]
end
subgraph serve["İstek Yolu — server.py"]
U["Kullanıcı sorusu<br/>TR / EN"] --> TR["topic_router.py<br/>A-G kategori tespiti"]
TR --> T["generator.translate_query_for_retrieval<br/>(yalnızca İngilizce soru için)"]
T --> E2["embedder.py"]
E2 --> R["retriever.get_top_chunks<br/>top-K + benzerlik eşiği"]
DB --> R
R --> G["generator.answer_query<br/>soru + parçalar + geçmiş"]
G --> S["segments + sources JSON"]
S --> UI["static/ sohbet arayüzü<br/>alıntı chip'leri + kaynak pill'leri"]
U -.-> QL[("queries.db<br/>kalıcı sorgu günlüğü")]
end
subgraph backends["Değiştirilebilir Arka Uçlar — rag/config.py"]
F["foundry<br/>Microsoft Foundry Local"]
O["ollama<br/>yerel yedek"]
GM["gemini<br/>cloud deploy"]
end
E1 -.-> backends
E2 -.-> backends
G -.-> backends
.
├── rag/ # RAG pipeline — burada web framework import'u yok
│ ├── config.py # Tüm ayarlanabilir sabitler, env-var ile geçersiz kılınabilir
│ ├── loader.py # belgeler/ → metin + bölüm başına kaynak adı/URL
│ ├── chunker.py # Paragraf tabanlı parçalama (~200-500 kelime)
│ ├── embedder.py # Foundry / Ollama / Gemini
│ ├── store.py # SQLite CRUD — chunks + embedding'ler
│ ├── retriever.py # Kosinüs benzerliği + eşik filtresi
│ ├── topic_router.py # A-G kategori sınıflandırması
│ └── generator.py # Sistem promptları + çeviri köprüsü + LLM çağrısı
│
├── scripts/
│ └── ingest.py # Tek seferlik belge yükleme script'i
│
├── server.py # FastAPI uygulama + rate limiting + admin endpoint
│
├── static/ # El yapımı sohbet arayüzü
│ ├── index.html
│ ├── style.css # Glassmorphism dark tema
│ └── app.js # Sohbet mantığı + animasyonlar + alıntı render
│
├── belgeler/ # Tarımsal kaynak belgeler
│ ├── hibe/
│ │ ├── ipard3_rehberi.md
│ │ └── kkydp_kilavuzu.md
│ ├── zirai_mucadele/
│ │ ├── domates_entegre_mucadele.md
│ │ └── bugday_mucadele.md
│ ├── sulama/
│ │ └── tarimsal_sulama_rehberi.md
│ └── sigorta/
│ └── tarsim_kilavuzu.md
│
├── tests/ # pytest test paketi
├── requirements.txt
├── .env.example
└── README.md
- Python 3.12+
- Offline mod için: Microsoft Foundry Local veya Ollama
- Cloud mod için: Google AI Studio'dan Gemini API key → aistudio.google.com/apikey
# 1. Depoyu klonlayın
git clone https://github.com/KULLANICI_ADI/AgroBot_Tarim_Asistani.git
cd AgroBot_Tarim_Asistani
# 2. Sanal ortam oluşturun ve bağımlılıkları yükleyin
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# 3. Ortam değişkenlerini yapılandırın
cp .env.example .env
# .env dosyasını düzenleyin (aşağıdaki Yapılandırma bölümüne bakın)
# 4. Belgeleri yükleyin (ilk kurulumda ve belgeler değiştiğinde çalıştırın)
python scripts/ingest.py
# 5. Sunucuyu başlatın
uvicorn server:app --reloadTarayıcınızda http://localhost:8000 adresini açın.
| Arka Uç | Açıklama | Ne Zaman Kullanılır |
|---|---|---|
foundry |
Microsoft Foundry Local | Tam offline, veri gizliliği öncelikli |
ollama |
Ollama (yerel yedek) | Foundry kurulu değilse |
gemini |
Google Gemini API | Üretim / herkese açık demo |
Arka ucu BACKEND ortam değişkeniyle değiştirin.
.env.example dosyasını .env olarak kopyalayın ve doldurun:
# Arka uç seçimi: foundry | ollama | gemini
BACKEND=gemini
# Gemini (cloud mod için)
GEMINI_API_KEY=your_key_here
GEMINI_CHAT_MODEL=gemini-1.5-flash
GEMINI_EMBED_MODEL=models/embedding-001
# Ollama (offline mod için)
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_CHAT_MODEL=llama3.1:8b
OLLAMA_EMBED_MODEL=nomic-embed-text
# RAG ayarları
TOP_K=5
SIMILARITY_THRESHOLD=0.35
MAX_HISTORY_TURNS=4
# Güvenlik
ADMIN_TOKEN=gizli-token-buraya
# Rate limiting
RATE_LIMIT_PER_MINUTE=20Sohbet uç noktası.
İstek gövdesi:
{
"question": "IPARD III seracılık hibesi için şartlar neler?",
"history": [
{"role": "user", "content": "Merhaba"},
{"role": "assistant", "content": "Merhaba! Size nasıl yardımcı olabilirim?"}
],
"language": "tr"
}Yanıt:
{
"answer": "IPARD III programı kapsamında sera yapımı...",
"segments": [
{"type": "text", "content": "IPARD III programı kapsamında sera yapımı"},
{"type": "citation", "index": 1},
{"type": "text", "content": " desteklenmektedir."}
],
"sources": [
{
"index": 1,
"title": "IPARD III Program Rehberi",
"section": "Tedbir 4.1",
"page": "38-42"
}
],
"category": "A",
"language_detected": "tr"
}curl -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8000/admin/queriesbelgeler/ dizini aşağıdaki kategorilere ayrılmıştır:
| Kategori | İçerik | Örnek Kaynaklar |
|---|---|---|
hibe/ |
IPARD III, KKYDP, Bakanlık tebliğleri | TKDK rehberleri, destekleme tebliğleri |
zirai_mucadele/ |
Hastalık, zararlı, yabancı ot talimatları | Bakanlık entegre mücadele kılavuzları |
sulama/ |
Sulama sistemleri, toprak analizi | DSİ / Bakanlık sulama rehberleri |
sigorta/ |
TARSİM ürün ve risk teminatları | TARSİM kılavuzları |
organik/ |
Sertifikasyon, izinli maddeler | Organik tarım yönetmelikleri |
Yeni bir belge eklemek için:
# belgeler/ilgili_kategori/ dizinine kopyalayın
cp yeni_belge.pdf belgeler/hibe/
# Yeniden yükleyin
python scripts/ingest.pypytest tests/ -vTest kapsamı: loader, chunker, embedder, store, retriever, topic_router, generator, query_log ve HTTP katmanı.
- Depoyu GitHub'a push'layın
- render.com üzerinde yeni bir Web Service oluşturun
- Aşağıdaki değerleri ayarlayın:
- Build Command:
pip install -r requirements.txt && python scripts/ingest.py - Start Command:
uvicorn server:app --host 0.0.0.0 --port $PORT
- Build Command:
- Ortam değişkenlerini Render dashboard'undan ekleyin (
BACKEND=gemini,GEMINI_API_KEY=...)
docker build -t agrobot .
docker run -p 8000:8000 --env-file .env agrobotNeden retrieval için çeviri köprüsü? Kaynak belgeler Türkçe'dir. Kullanıcılar İngilizce soru sorduğunda, soruyu önce retrieval için Türkçeye çevirmek, çapraz dilli embedding yeteneklerine güvenmekten daha güvenilir sonuç verir. Model her durumda orijinal dilde yanıt verir.
Neden topic router? Farklı kategorilerin belge kümeleri birbirinden ayrıdır. Tüm belgelerde arama yapmak yerine ilgili kümeyi seçmek hem precision'ı artırır hem de token maliyetini düşürür.
Neden SQLite, vektör veritabanı değil? Tek sunucu, tek süreç dağıtımları için SQLite + kosinüs benzerliği, Chroma veya Qdrant kurmaktan daha az karmaşıktır. Vektör boyutu <1536, satır sayısı <500K iken fark ihmal edilebilir düzeydedir.
Neden tahmin yapmıyor?
Tarımsal tavsiyeler — özellikle ilaç dozları ve hibe başvuru şartları —
halüsinasyona çok duyarlıdır. Asistan, benzerlik eşiğinin altındaki parçaları
gürültü olarak atar ve "Bu konuda elimdeki belgelerde bilgi bulunmuyor" der.
- Yüklü belgelerden alınmayan bilgileri yanıtlamaz (bu kasıtlı bir tasarım kararıdır)
- Gerçek zamanlı piyasa fiyatları, anlık hava durumu ve hukuki tavsiye kapsam dışıdır
- Yeni tebliğler ve belgeler eklendikçe
ingest.pyyeniden çalıştırılmalıdır - Canlı demo Render'ın ücretsiz katmanında çalıştığından uyku modundan uyanması zaman alabilir
Türk çiftçileri için sevgiyle yapıldı 🌾