veteroner commited on
Commit
58c4fec
·
verified ·
1 Parent(s): 6f3c06e

CRANE AI ZeroGPU Space yüklendi

Browse files
README.md CHANGED
@@ -1,289 +1,98 @@
1
- ---
2
- title: Teknova Nova AI
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 4.26.0
8
- app_file: gradio_app.py
9
- pinned: false
10
- license: mit
11
- language:
12
- - tr
13
- - en
14
- tags:
15
- - text-generation
16
- - conversational
17
- - turkish
18
- - teknova
19
- - nova-ai
20
- - chat
21
- - assistant
22
- pipeline_tag: text-generation
23
- library_name: transformers
24
- ---
25
-
26
- # 🚀 Teknova Nova AI
27
-
28
- **Teknova** tarafından geliştirilen **özgün** Türkçe yapay zeka modeli - Hugging Face ZeroGPU ile hızlandırılmış!
29
-
30
- ## ✨ Özellikler
31
-
32
- - 🧠 **Özgün Model**: Teknova tarafından sıfırdan geliştirilen yapay zeka modeli
33
- - 🇹🇷 **Türkçe Optimizasyonu**: Türkçe dil yapısına özel olarak eğitilmiş
34
- - **ZeroGPU Hızlı**: Hugging Face ZeroGPU teknolojisi ile hızlandırılmış
35
- - 💬 **Akıllı Sohbet**: Doğal dil işleme ile akıllı konuşma
36
- - 🎯 **Kullanıcı Dostu**: Kolay kullanım için tasarlanmış arayüz
37
-
38
- ## 🚀 Nasıl Kullanılır?
39
-
40
- 1. **Sohbet Başlat**: Aşağıdaki chat arayüzünde mesajınızı yazın
41
- 2. **Gönder**: 🚀 Gönder butonuna tıklayın
42
- 3. **Yanıt Al**: Nova AI'dan anlık yanıt alın
43
- 4. **Devam Edin**: Konuşmaya devam ederek daha detaylı bilgi alın
44
-
45
- ## 💡 Örnek Sorular
46
-
47
- - "Merhaba Nova AI, nasılsın?"
48
- - "Yapay zeka nedir?"
49
- - "Teknova hakkında bilgi ver"
50
- - "Bana bir hikaye anlat"
51
- - "Python programlama hakkında bilgi ver"
52
-
53
- ## 🛠️ Teknik Bilgiler
54
-
55
- - **Model**: Teknova Nova AI (Özgün)
56
- - **Framework**: Transformers, PyTorch
57
- - **UI**: Gradio 4.36.1
58
- - **Hızlandırma**: Hugging Face ZeroGPU
59
- - **Dil**: Türkçe odaklı çok dilli destek
60
-
61
- ## 📄 Lisans
62
-
63
- Bu proje MIT lisansı ile lisanslanmıştır.
64
-
65
- ## 🔗 Bağlantılar
66
-
67
- - **Geliştirici**: Teknova Innovation
68
- - **Model**: Nova AI (Özgün)
69
- - **Platform**: Hugging Face Spaces
70
-
71
- ---
72
-
73
- 🌟 **Teknova Nova AI** - Tamamen özgün Türkçe dil modeli ile güçlendirilmiş yapay zeka deneyimi!
74
-
75
- ---
76
-
77
- ## 🌟 **Model Özellikleri**
78
-
79
- ### **Özgün Teknova Teknolojisi**
80
- - 🧠 **Türkçe Optimizasyonu** - Türkçe dil yapısına özel eğitim
81
- - 💬 **Doğal Konuşma** - İnsan benzeri etkileşim yetenekleri
82
- - 🎯 **Bağlamsal Anlama** - Gelişmiş anlam çıkarma
83
- - **Hızlı Yanıt** - Optimize edilmiş performans
84
- - 🔧 **Çok Amaçlı** - Sohbet, yazma, analiz yetenekleri
85
-
86
- ### 🛠️ **Teknik Detaylar**
87
- - **Temel Model:** Mistral-7B mimarisi
88
- - **Parametre Sayısı:** 7.24 milyar
89
- - **Eğitim Dili:** Türkçe + İngilizce
90
- - **Bağlam Uzunluğu:** 8192 token
91
- - **Model Formatı:** SafeTensors + PyTorch
92
-
93
- ---
94
-
95
- ## 🚀 **Kullanım**
96
-
97
- ### 💻 **Transformers ile**
98
- ```python
99
- from transformers import AutoModelForCausalLM, AutoTokenizer
100
- import torch
101
-
102
- # Nova AI modelini yükle
103
- model_name = "Teknova/NovaAI"
104
- tokenizer = AutoTokenizer.from_pretrained(model_name)
105
- model = AutoModelForCausalLM.from_pretrained(
106
- model_name,
107
- torch_dtype=torch.float16,
108
- device_map="auto"
109
- )
110
-
111
- # Sohbet örneği
112
- def chat_with_nova(message):
113
- conversation = f"Kullanıcı: {message}\nNova AI:"
114
- inputs = tokenizer(conversation, return_tensors="pt")
115
-
116
- with torch.no_grad():
117
- outputs = model.generate(
118
- **inputs,
119
- max_new_tokens=512,
120
- temperature=0.7,
121
- top_p=0.9,
122
- do_sample=True,
123
- pad_token_id=tokenizer.eos_token_id
124
- )
125
-
126
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
127
- return response[len(conversation):].strip()
128
-
129
- # Örnek kullanım
130
- response = chat_with_nova("Merhaba Nova AI, nasılsın?")
131
- print(response)
132
- ```
133
-
134
- ### 🌐 **API ile Kullanım**
135
- ```python
136
- import requests
137
-
138
- API_URL = "https://api-inference.huggingface.co/models/Teknova/NovaAI"
139
- headers = {"Authorization": "Bearer YOUR_HF_TOKEN"}
140
-
141
- def query_nova_ai(payload):
142
- response = requests.post(API_URL, headers=headers, json=payload)
143
- return response.json()
144
-
145
- # Örnek sorgu
146
- output = query_nova_ai({
147
- "inputs": "Yapay zeka teknolojileri hakkında bilgi ver",
148
- "parameters": {
149
- "max_new_tokens": 256,
150
- "temperature": 0.7,
151
- "top_p": 0.9
152
- }
153
- })
154
- print(output)
155
- ```
156
-
157
- ---
158
-
159
- ## 💡 **Örnek Kullanım Alanları**
160
-
161
- ### 🎯 **Sohbet ve Asistan**
162
- - Müşteri hizmetleri chatbotu
163
- - Kişisel asistan uygulamaları
164
- - Eğitim ve öğretim desteği
165
-
166
- ### 📝 **İçerik Üretimi**
167
- - Blog yazısı ve makale yazımı
168
- - Sosyal medya içeriği
169
- - Yaratıcı yazım desteği
170
-
171
- ### 🔍 **Analiz ve Özetleme**
172
- - Metin analizi ve özetleme
173
- - Duygu analizi
174
- - Bilgi çıkarma
175
-
176
- ---
177
-
178
- ## ⚙️ **Model Parametreleri**
179
-
180
- | Parametre | Değer | Açıklama |
181
- |-----------|-------|----------|
182
- | `temperature` | 0.7 | Yaratıcılık seviyesi (0.1-1.5) |
183
- | `top_p` | 0.9 | Nucleus sampling |
184
- | `max_new_tokens` | 512 | Maksimum yanıt uzunluğu |
185
- | `repetition_penalty` | 1.1 | Tekrar önleme |
186
-
187
- ---
188
-
189
- ## 🎨 **Demo ve Uygulamalar**
190
-
191
- ### 🌐 **Web Arayüzü**
192
- - **Gradio Demo:** [Nova AI Chat](https://huggingface.co/spaces/Teknova/NovaAI-Chat)
193
- - **HTML Arayüz:** Kendi web sitenizde kullanabilirsiniz
194
-
195
- ### 📱 **Entegrasyon**
196
- ```javascript
197
- // Web sitesinde kullanım örneği
198
- const API_URL = 'https://api-inference.huggingface.co/models/Teknova/NovaAI';
199
-
200
- async function queryNovaAI(text) {
201
- const response = await fetch(API_URL, {
202
- headers: {
203
- 'Authorization': 'Bearer YOUR_TOKEN',
204
- 'Content-Type': 'application/json'
205
- },
206
- method: 'POST',
207
- body: JSON.stringify({
208
- inputs: text,
209
- parameters: {
210
- max_new_tokens: 256,
211
- temperature: 0.7
212
- }
213
- })
214
- });
215
-
216
- return await response.json();
217
- }
218
- ```
219
-
220
- ---
221
-
222
- ## 📊 **Performans**
223
-
224
- ### 🚀 **Hız ve Verimlilik**
225
- - **CPU Modunda:** ~2-3 saniye yanıt süresi
226
- - **GPU Modunda:** ~0.5-1 saniye yanıt süresi
227
- - **Bellek Kullanımı:** ~14.5GB model boyutu
228
- - **Optimizasyon:** 4-bit quantization desteği
229
-
230
- ### 🎯 **Kalite Metrikleri**
231
- - **Türkçe Doğruluk:** Yüksek seviyede Türkçe anlama
232
- - **Bağlamsal Tutarlılık:** Uzun konuşmalarda tutarlı yanıtlar
233
- - **Yaratıcılık:** Özgün ve çeşitli içerik üretimi
234
-
235
- ---
236
-
237
- ## 🔧 **Sistem Gereksinimleri**
238
-
239
- ### 💻 **Minimum Gereksinimler**
240
- - **RAM:** 16GB (4-bit quantization ile)
241
- - **GPU:** 8GB VRAM (RTX 3070 veya üzeri)
242
- - **CPU:** 4 çekirdek, 2.5GHz+
243
- - **Depolama:** 20GB boş alan
244
-
245
- ### 🚀 **Önerilen Gereksinimler**
246
- - **RAM:** 32GB
247
- - **GPU:** 16GB+ VRAM (RTX 4080/4090)
248
- - **CPU:** 8+ çekirdek, 3.0GHz+
249
- - **Depolama:** SSD, 50GB+ boş alan
250
-
251
- ---
252
-
253
- ## 📜 **Lisans ve Kullanım**
254
-
255
- Bu model **Apache 2.0** lisansı altında yayınlanmıştır. Ticari ve akademik kullanım için serbesttir.
256
-
257
- ### ⚠️ **Önemli Notlar**
258
- - Model özgün Teknova teknolojisi içermektedir
259
- - Türkçe optimizasyonları Teknova tarafından geliştirilmiştir
260
- - Responsible AI ilkelerine uygun olarak kullanılmalıdır
261
-
262
- ---
263
-
264
- ## 🏢 **Teknova Hakkında**
265
-
266
- **Teknova**, Türkiye'nin öncü yapay zeka teknoloji şirketidir. Özgün AI çözümleri geliştirerek teknoloji dünyasında fark yaratmayı hedefliyoruz.
267
-
268
- ### 🎯 **Misyonumuz**
269
- Yapay zeka teknolojilerini Türkçe konuşan kullanıcılar için optimize etmek ve erişilebilir kılmak.
270
-
271
- ### 🚀 **Vizyonumuz**
272
- Türkiye'den dünyaya özgün yapay zeka teknolojileri ihraç etmek.
273
-
274
- ---
275
-
276
- ## 📞 **İletişim ve Destek**
277
-
278
- - **🌐 Website:** [teknova.ai](https://teknova.ai)
279
- - **📧 E-posta:** info@teknova.ai
280
- - **💬 Destek:** [GitHub Issues](https://github.com/teknova-ai/nova-ai/issues)
281
- - **📱 Sosyal Medya:** [@TeknovaAI](https://twitter.com/TeknovaAI)
282
-
283
- ---
284
-
285
- ## 🙏 **Teşekkürler**
286
-
287
- Nova AI'yi kullandığınız için teşekkürler! Geri bildirimleriniz bizim için değerlidir.
288
-
289
- **Teknova Nova AI** - *Türkiye'nin Özgün Yapay Zeka Teknolojisi* 🚀
 
1
+ ---
2
+ title: CRANE AI ZeroGPU
3
+ emoji: 🏗️
4
+ colorFrom: red
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 4.29.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ hardware: zero-gpu
12
+ tags:
13
+ - ai
14
+ - multi-model
15
+ - zero-gpu
16
+ - crane
17
+ - turkish
18
+ - code-generation
19
+ - chat
20
+ - reasoning
21
+ language:
22
+ - tr
23
+ - en
24
+ short_description: CRANE AI Hibrit Yapay Zeka Sistemi - ZeroGPU Powered
25
+ ---
26
+
27
+ # 🏗️ CRANE AI - ZeroGPU Powered
28
+
29
+ **Hibrit Yapay Zeka Sistemi** - HuggingFace ZeroGPU ile güçlendirilmiş
30
+
31
+ ## 🔥 ZeroGPU Features
32
+
33
+ - **Ücretsiz GPU Erişimi**: HuggingFace'in ücretsiz GPU kaynaklarını kullanır
34
+ - **Hızlı Model Yükleme**: GPU'da optimize edilmiş model başlatma
35
+ - **Akıllı Router Sistemi**: Görevlere göre en uygun modeli seçer
36
+ - **Hibrit Mimari**: Birden fazla küçük model birlikte çalışır
37
+
38
+ ## 🧠 Sistem Mimarisi
39
+
40
+ ### MicroModule System
41
+ - **FastModule**: TinyLlama (hızlı yanıt)
42
+ - **CodeModule**: DeepSeek-Coder (kod yazma)
43
+ - **ChatModule**: Qwen2.5 (sohbet)
44
+ - **ReasonModule**: Phi-3 (mantık yürütme)
45
+
46
+ ### ZeroGPU Optimizasyonları
47
+ - `@spaces.GPU` dekoratörleri
48
+ - GPU memory management
49
+ - Efficient model loading
50
+ - Concurrent request handling
51
+
52
+ ## 🚀 Kullanım
53
+
54
+ ### Desteklenen Görevler:
55
+ - 💬 **Genel sohbet**: Doğal dil işleme
56
+ - 🔧 **Kod yazma**: Python, JavaScript, vb.
57
+ - 🤔 **Problem çözme**: Mantık yürütme
58
+ - **Hızlı sorular**: Kısa yanıtlar
59
+
60
+ ### Örnek Kullanımlar:
61
+ ```
62
+ "Python'da bir hesap makinesi yaz"
63
+ "Fibonacci dizisi algoritması"
64
+ "Web development hakkında bilgi ver"
65
+ "Bugün nasıl bir gün?"
66
+ ```
67
+
68
+ ## Performans
69
+
70
+ - **GPU**: NVIDIA A100/T4 (ZeroGPU)
71
+ - **Memory**: ~4GB VRAM
72
+ - **Response Time**: ~2-5 saniye
73
+ - **Concurrent Users**: 2 kullanıcı
74
+
75
+ ## 🔧 Teknik Detaylar
76
+
77
+ ### Model Specifications:
78
+ - **TinyLlama**: 1.1B parametreli chat modeli
79
+ - **DeepSeek-Coder**: 1.3B kod üretim modeli
80
+ - **Qwen2.5**: 1.5B sohbet modeli
81
+ - **Phi-3**: Mini reasoning modeli
82
+
83
+ ### ZeroGPU Configuration:
84
+ - Duration: 30-60 saniye GPU slots
85
+ - Concurrency: 2 eşzamanlı kullanıcı
86
+ - Auto-shutdown: Idle durumda otomatik kapanma
87
+
88
+ ## 📄 Lisans
89
+
90
+ MIT Lisansı - Açık kaynak
91
+
92
+ ## 👨‍💻 Geliştirici
93
+
94
+ [@veteroner](https://huggingface.co/veteroner)
95
+
96
+ ---
97
+
98
+ 🔥 **ZeroGPU ile ücretsiz GPU gücünden yararlanın!**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,360 +1,170 @@
 
1
  """
2
- 🚀 Nova AI - Hugging Face Spaces ZeroGPU
3
- Teknova tarafından geliştirilen özgün yapay zeka modeli
4
- ZeroGPU ile hızlandırılmış
5
  """
6
 
7
  import gradio as gr
 
8
  import torch
9
- import os
10
  import logging
 
 
11
  import time
12
- from typing import List, Tuple
13
 
14
- # Spaces import - sadece Hugging Face Spaces'te mevcut
15
- try:
16
- import spaces
17
- HAS_SPACES = True
18
- except ImportError:
19
- HAS_SPACES = False
20
- # Spaces decorator'ı için dummy fonksiyon
21
- def spaces_gpu(func):
22
- return func
23
- spaces = type('spaces', (), {'GPU': spaces_gpu})()
24
-
25
- # Logging setup
26
  logging.basicConfig(level=logging.INFO)
27
  logger = logging.getLogger(__name__)
28
 
29
- # Global variables
30
- model = None
31
- tokenizer = None
32
- device = "cuda" if torch.cuda.is_available() else "cpu"
33
-
34
- def load_demo_responses():
35
- """
36
- Demo yanıtları - model yokken kullanılacak
37
- """
38
- demo_responses = {
39
- "merhaba": "Merhaba! Ben Nova AI, Teknova'nın özgün yapay zeka teknolojisi. Size nasıl yardımcı olabilirim?",
40
- "nasılsın": "Ben Nova AI'yım ve harika hissediyorum! Sizinle sohbet etmek için buradayım. Ne konuşmak istersiniz?",
41
- "nova ai nedir": "Nova AI, Teknova tarafından geliştirilen özgün bir yapay zeka modelidir. Türkçe konuşabilir ve çeşitli konularda yardımcı olabilirim.",
42
- "teknova": "Teknova, Türkiye'nin öncü yapay zeka teknoloji şirketidir. Özgün AI çözümleri geliştiriyoruz.",
43
- "yapay zeka": "Yapay zeka, bilgisayarların insan benzeri düşünme ve öğrenme yetenekleri göstermesidir. Ben de bir yapay zeka örneğiyim!",
44
- "projeler": "Size yenilikçi proje fikirleri önerebilirim: AI chatbot, veri analizi, web uygulaması, mobil uygulama gibi...",
45
- "gelecek": "Gelecekte yapay zeka, otonom araçlar, akıllı şehirler ve personalize eğitim gibi alanlarda devrim yaratacak!"
46
- }
47
- return demo_responses
48
 
49
- def generate_demo_response(message: str) -> str:
50
- """
51
- Demo yanıt oluştur (model olmadığında)
52
- """
53
- message_lower = message.lower().strip()
54
- demo_responses = load_demo_responses()
55
-
56
- # Exact match
57
- if message_lower in demo_responses:
58
- return demo_responses[message_lower]
59
-
60
- # Partial match
61
- for key, response in demo_responses.items():
62
- if key in message_lower:
63
- return response
64
-
65
- # Default responses
66
- if "?" in message:
67
- return f"'{message}' hakkında çok ilginç bir soru sordunuz! Nova AI olarak elimden geldiğince yardımcı olmaya çalışırım. Bu konuda daha spesifik sorular sorabilirsiniz."
68
-
69
- return f"Nova AI burada! '{message}' konusunda konuşmak güzel. Size nasıl yardımcı olabilirim? Daha detaylı sorular sorabilirsiniz."
70
-
71
- def chat_response(message: str, history: List[List[str]], max_length: int, temperature: float) -> Tuple[str, List[List[str]]]:
72
- """
73
- Chat response function
74
- """
75
- if not message.strip():
76
- return "", history
77
-
78
- # Simulate thinking time
79
- time.sleep(0.5)
80
-
81
- # Generate response
82
- if model and tokenizer:
83
- # Gerçek model ile yanıt (model yüklü ise)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  try:
85
- response = generate_real_response(message, max_length, temperature)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  except Exception as e:
87
- response = f"Model hatası: {str(e)} - Demo moduna geçiliyor..."
88
- response += "\n\n" + generate_demo_response(message)
89
- else:
90
- # Demo yanıt
91
- response = generate_demo_response(message)
92
- response += "\n\n💡 *Not: Bu demo modunda çalışıyor. Gerçek Nova AI modeli yüklendiğinde daha gelişmiş yanıtlar alacaksınız.*"
93
-
94
- # Add to history
95
- history.append([message, response])
96
- return "", history
97
 
98
- @spaces.GPU
99
- def generate_real_response(message: str, max_length: int, temperature: float) -> str:
100
- """
101
- Gerçek model ile yanıt oluştur - ZeroGPU destekli
102
- """
103
- if not model or not tokenizer:
104
- return generate_demo_response(message)
105
-
106
- try:
107
- inputs = tokenizer.encode(message, return_tensors="pt")
108
- if device == "cuda":
109
- inputs = inputs.to(device)
110
-
111
- with torch.no_grad():
112
- outputs = model.generate(
113
- inputs,
114
- max_length=max_length,
115
- temperature=temperature,
116
- do_sample=True,
117
- pad_token_id=tokenizer.eos_token_id,
118
- no_repeat_ngram_size=3,
119
- top_p=0.9
120
- )
121
-
122
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
123
- if message in response:
124
- response = response.replace(message, "").strip()
125
-
126
- return response if response else generate_demo_response(message)
127
-
128
- except Exception as e:
129
- logger.error(f"Model generation error: {e}")
130
- return generate_demo_response(message)
131
 
132
- @spaces.GPU
133
- def load_model():
134
- """
135
- Teknova Nova AI modelini yükle - ZeroGPU destekli
136
- """
137
- global model, tokenizer
138
-
139
- try:
140
- from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
141
-
142
- # Model path - Hugging Face Hub'dan yükle
143
- model_path = "veteroner/NovaAI"
144
-
145
- logger.info(f"🚀 Teknova Nova AI modeli Hub'dan yükleniyor: {model_path}")
146
-
147
- # Tokenizer yükle
148
- tokenizer = AutoTokenizer.from_pretrained(
149
- model_path,
150
- trust_remote_code=True,
151
- use_fast=True
152
- )
153
-
154
- # Pad token ayarla
155
- if tokenizer.pad_token is None:
156
- tokenizer.pad_token = tokenizer.eos_token
157
-
158
- # Model yükle - ZeroGPU optimizasyonu
159
- model = AutoModelForCausalLM.from_pretrained(
160
- model_path,
161
- device_map="auto",
162
- trust_remote_code=True,
163
- torch_dtype=torch.float16,
164
- low_cpu_mem_usage=True
165
- )
166
-
167
- logger.info(f"✅ Nova AI model yüklendi ({device})")
168
- return f"✅ Teknova Nova AI hazır! ({device})"
169
-
170
- except Exception as e:
171
- logger.error(f"Model yükleme hatası: {e}")
172
- return f"❌ Model yüklenemedi: {str(e)} - Demo modunda çalışacak"
173
 
174
- @spaces.GPU
175
- def chat_with_nova(message: str, history: List[Tuple[str, str]]) -> str:
176
- """
177
- Nova AI ile sohbet et - ZeroGPU destekli
178
- """
179
- global model, tokenizer
180
-
181
- if model is None or tokenizer is None:
182
- # Demo yanıt ver
183
- return generate_demo_response(message) + "\n\n💡 *Not: Demo modunda çalışıyor.*"
184
-
185
- if not message.strip():
186
- return "❓ Lütfen bir mesaj yazın."
187
-
188
  try:
189
- # Konuşma geçmişini hazırla
190
- conversation = ""
191
- for user_msg, bot_msg in history:
192
- if user_msg and bot_msg:
193
- conversation += f"Kullanıcı: {user_msg}\nNova AI: {bot_msg}\n"
194
-
195
- # Yeni mesajı ekle
196
- conversation += f"Kullanıcı: {message}\nNova AI:"
197
-
198
- # Tokenize et
199
- inputs = tokenizer(
200
- conversation,
201
- return_tensors="pt",
202
- truncation=True,
203
- max_length=2048,
204
- padding=True
205
- )
206
-
207
- # GPU'ya taşı
208
- if torch.cuda.is_available():
209
- inputs = {k: v.to(model.device) for k, v in inputs.items()}
210
-
211
- # Yanıt üret
212
- with torch.no_grad():
213
- outputs = model.generate(
214
- **inputs,
215
- max_new_tokens=256,
216
- temperature=0.7,
217
- top_p=0.9,
218
- do_sample=True,
219
- pad_token_id=tokenizer.pad_token_id,
220
- eos_token_id=tokenizer.eos_token_id,
221
- repetition_penalty=1.1
222
- )
223
-
224
- # Yanıtı decode et
225
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
226
-
227
- # Sadece yeni üretilen kısmı al
228
- new_response = response[len(conversation):].strip()
229
-
230
- return new_response if new_response else "Üzgünüm, yanıt üretemedi."
231
-
232
- except Exception as e:
233
- logger.error(f"Chat hatası: {e}")
234
- return f"❌ Yanıt üretirken hata: {str(e)}"
235
-
236
- # Model yüklemeyi başlat
237
- logger.info("Model yükleme başlatılıyor...")
238
- load_status = load_model()
239
- logger.info(f"Model durumu: {load_status}")
240
 
241
  # Gradio arayüzü
242
- with gr.Blocks(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  theme=gr.themes.Soft(),
244
- title="Teknova Nova AI - ZeroGPU",
245
- css="""
246
- .gradio-container {
247
- max-width: 900px;
248
- margin: 0 auto;
249
- }
250
- .header-text {
251
- text-align: center;
252
- padding: 20px;
253
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
254
- color: white;
255
- border-radius: 15px;
256
- margin-bottom: 20px;
257
- }
258
- """
259
- ) as demo:
260
-
261
- # Header
262
- gr.HTML("""
263
- <div class="header-text">
264
- <h1 style="font-size: 2.5rem; margin: 0; font-weight: bold;">
265
- 🚀 Teknova Nova AI
266
- </h1>
267
- <p style="font-size: 1.2rem; margin: 10px 0; opacity: 0.9;">
268
- Türkiye'nin Özgün Yapay Zeka Modeli
269
- </p>
270
- <div style="background: rgba(255,255,255,0.2); padding: 8px 16px; border-radius: 20px; display: inline-block; font-size: 0.9rem;">
271
- 🧠 Nova AI • 🇹�� Türkçe Optimize • ⚡ ZeroGPU Hızlı
272
- </div>
273
- </div>
274
- """)
275
-
276
- # Chat interface
277
- chatbot = gr.Chatbot(
278
- height=500,
279
- show_label=False,
280
- show_share_button=True,
281
- show_copy_button=True,
282
- avatar_images=[None, "🤖"],
283
- bubble_full_width=False
284
- )
285
-
286
- with gr.Row():
287
- msg = gr.Textbox(
288
- placeholder="Nova AI'ya mesajınızı yazın... (Örn: Merhaba, nasılsın?)",
289
- show_label=False,
290
- scale=4,
291
- container=False
292
- )
293
- submit = gr.Button("🚀 Gönder", scale=1, variant="primary")
294
-
295
- with gr.Row():
296
- clear = gr.Button("🗑️ Temizle", scale=1)
297
- retry = gr.Button("🔄 Tekrar Dene", scale=1)
298
-
299
- # Examples
300
- gr.Examples(
301
- examples=[
302
- "Merhaba Nova AI, nasılsın?",
303
- "Yapay zeka nedir?",
304
- "Teknova hakkında bilgi ver",
305
- "Bana bir hikaye anlat",
306
- "Python programlama hakkında bilgi ver"
307
- ],
308
- inputs=msg,
309
- label="💡 Örnek Sorular"
310
- )
311
-
312
- # Footer
313
- gr.HTML("""
314
- <div style="text-align: center; padding: 15px; color: #666; font-size: 0.9rem;">
315
- <p>🌟 <strong>Teknova Nova AI</strong> - Tamamen özgün Türkçe dil modeli</p>
316
- <p>🚀 ZeroGPU teknolojisi ile hızlandırılmış</p>
317
- <p style="color: #999;">⚡ Teknova Innovation ile güçlendirilmiştir</p>
318
- </div>
319
- """)
320
-
321
- # Event handlers
322
- def user_message(message, history):
323
- return "", history + [[message, None]]
324
-
325
- @spaces.GPU
326
- def bot_message(history):
327
- """Bot yanıtı oluştur - ZeroGPU destekli"""
328
- if history and history[-1][1] is None:
329
- user_msg = history[-1][0]
330
- bot_response = chat_with_nova(user_msg, history[:-1])
331
- history[-1][1] = bot_response
332
- return history
333
-
334
- @spaces.GPU
335
- def retry_last(history):
336
- """Son mesajı yeniden dene - ZeroGPU destekli"""
337
- if history and history[-1][1] is not None:
338
- user_msg = history[-1][0]
339
- bot_response = chat_with_nova(user_msg, history[:-1])
340
- history[-1][1] = bot_response
341
- return history
342
-
343
- # Event bindings
344
- msg.submit(user_message, [msg, chatbot], [msg, chatbot], queue=False).then(
345
- bot_message, chatbot, chatbot
346
- )
347
- submit.click(user_message, [msg, chatbot], [msg, chatbot], queue=False).then(
348
- bot_message, chatbot, chatbot
349
- )
350
- clear.click(lambda: None, None, chatbot, queue=False)
351
- retry.click(retry_last, chatbot, chatbot)
352
 
353
- # Launch
354
  if __name__ == "__main__":
355
  demo.launch(
 
356
  server_name="0.0.0.0",
357
  server_port=7860,
358
- share=False,
359
  show_error=True
360
- )
 
1
+ #!/usr/bin/env python3
2
  """
3
+ CRANE AI - ZeroGPU Space Demo
4
+ HuggingFace ZeroGPU ile çalışır
 
5
  """
6
 
7
  import gradio as gr
8
+ import spaces
9
  import torch
10
+ import asyncio
11
  import logging
12
+ import os
13
+ from typing import Dict, Any
14
  import time
 
15
 
16
+ # Logging
 
 
 
 
 
 
 
 
 
 
 
17
  logging.basicConfig(level=logging.INFO)
18
  logger = logging.getLogger(__name__)
19
 
20
+ # ZeroGPU için import'lar
21
+ from config.settings import MODELS, HF_TOKEN
22
+ from modules.code_module import CodeModule
23
+ from modules.chat_module import ChatModule
24
+ from modules.reason_module import ReasonModule
25
+ from modules.fast_module import FastModule
26
+ from router.intelligent_router import IntelligentRouter
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ class CRANEZeroGPU:
29
+ """CRANE AI ZeroGPU Wrapper"""
30
+
31
+ def __init__(self):
32
+ self.modules = {}
33
+ self.router = None
34
+ self.is_initialized = False
35
+
36
+ @spaces.GPU(duration=60) # 60 saniye GPU
37
+ async def initialize_models(self):
38
+ """Modelleri GPU'da başlatır"""
39
+ if self.is_initialized:
40
+ return
41
+
42
+ logger.info("🔥 ZeroGPU'da modeller yükleniyor...")
43
+
44
+ # GPU cihazını ayarla
45
+ device = "cuda" if torch.cuda.is_available() else "cpu"
46
+ logger.info(f"🖥️ Cihaz: {device}")
47
+
48
+ # Modelleri yükle
49
+ for name, cfg in MODELS.items():
50
+ try:
51
+ config = {**cfg, "device": device, "hf_token": os.getenv("HF_TOKEN", "")}
52
+
53
+ if name == "fast_module": # Sadece hızlı modeli yükle (GPU sınırlaması için)
54
+ module = FastModule(config)
55
+ await module.load_model()
56
+ self.modules[name] = module
57
+ logger.info(f" ✅ {name} GPU'da yüklendi")
58
+ break # Sadece bir model yükle
59
+
60
+ except Exception as e:
61
+ logger.error(f" ❌ {name} yükleme hatası: {e}")
62
+
63
+ # Router'ı başlat
64
+ if self.modules:
65
+ self.router = IntelligentRouter(self.modules, {
66
+ "confidence_threshold": 0.6,
67
+ "max_concurrent_requests": 1,
68
+ "timeout": 30,
69
+ "fallback_model": "fast_module"
70
+ })
71
+
72
+ self.is_initialized = True
73
+ logger.info("🔥 ZeroGPU başlatma tamamlandı")
74
+
75
+ @spaces.GPU(duration=30)
76
+ async def process_query(self, message: str, history: list) -> str:
77
+ """Mesajı ZeroGPU'da işler"""
78
  try:
79
+ # Modelleri başlat
80
+ await self.initialize_models()
81
+
82
+ if not self.router or not self.modules:
83
+ return "⚠️ Sistem başlatılamadı. Lütfen tekrar deneyin."
84
+
85
+ # Hızlı yanıt için basit kontrol
86
+ message_lower = message.lower()
87
+
88
+ # Basit selamlaşma
89
+ greetings = ["merhaba", "selam", "hi", "hello", "hey"]
90
+ if any(greeting in message_lower for greeting in greetings):
91
+ return "🏗️ Merhaba! Ben CRANE AI. Size nasıl yardımcı olabilirim?"
92
+
93
+ # Kod talebi kontrolü
94
+ code_keywords = ["kod", "code", "python", "javascript", "function", "def"]
95
+ if any(keyword in message_lower for keyword in code_keywords):
96
+ response = "🔧 Kod yazma modülü aktif... "
97
+ else:
98
+ response = "💬 "
99
+
100
+ # Modeli çalıştır
101
+ start_time = time.time()
102
+ result = await self.router.route_query(message, {"history": history})
103
+ duration = time.time() - start_time
104
+
105
+ if result and "response" in result:
106
+ response += result["response"]
107
+ response += f"\n\n⚡ İşlem süresi: {duration:.2f}s"
108
+ else:
109
+ response += "Üzgünüm, şu anda yanıt veremiyorum. Lütfen tekrar deneyin."
110
+
111
+ return response
112
+
113
  except Exception as e:
114
+ logger.error(f"ZeroGPU işlem hatası: {e}")
115
+ return f" Hata oluştu: {str(e)}"
 
 
 
 
 
 
 
 
116
 
117
+ # Global instance
118
+ crane_gpu = CRANEZeroGPU()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
+ async def chat_interface(message, history):
121
+ """Gradio chat interface"""
122
+ return await crane_gpu.process_query(message, history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ def sync_chat_interface(message, history):
125
+ """Senkron wrapper"""
126
+ loop = asyncio.new_event_loop()
127
+ asyncio.set_event_loop(loop)
 
 
 
 
 
 
 
 
 
 
128
  try:
129
+ return loop.run_until_complete(chat_interface(message, history))
130
+ finally:
131
+ loop.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  # Gradio arayüzü
134
+ demo = gr.ChatInterface(
135
+ fn=sync_chat_interface,
136
+ type="messages",
137
+ title="🏗️ CRANE AI - ZeroGPU Powered",
138
+ description="""
139
+ **CRANE AI Hibrit Yapay Zeka Sistemi** - HuggingFace ZeroGPU ile güçlendirilmiş
140
+
141
+ 🔥 **ZeroGPU Features:**
142
+ - Ücretsiz GPU erişimi
143
+ - Hızlı model yükleme
144
+ - Optimize edilmiş performans
145
+
146
+ 🧠 **Desteklenen Görevler:**
147
+ - 💬 Genel sohbet
148
+ - 🔧 Kod yazma
149
+ - 🤔 Problem çözme
150
+ - ⚡ Hızlı sorular
151
+ """,
152
  theme=gr.themes.Soft(),
153
+ examples=[
154
+ "Merhaba! CRANE AI nasıl çalışır?",
155
+ "Python'da bir hesap makinesi yaz",
156
+ "Fibonacci dizisi algoritması",
157
+ "Web development hakkında bilgi ver",
158
+ "Bugün nasıl bir gün?",
159
+ ],
160
+ cache_examples=False, # ZeroGPU için
161
+ concurrency_limit=2, # Eşzamanlı kullanıcı sınırı
162
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
 
164
  if __name__ == "__main__":
165
  demo.launch(
166
+ share=False,
167
  server_name="0.0.0.0",
168
  server_port=7860,
 
169
  show_error=True
170
+ )
config/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Configuration Package
3
+ """
4
+
5
+ from .settings import *
6
+
7
+ __all__ = [
8
+ 'MODELS',
9
+ 'ROUTER_CONFIG',
10
+ 'MEMORY_CONFIG',
11
+ 'API_CONFIG',
12
+ 'SYSTEM_LIMITS',
13
+ 'LOGGING_CONFIG',
14
+ 'HF_TOKEN',
15
+ 'DEVICE'
16
+ ]
config/settings.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI Sistem Yapılandırması
3
+ """
4
+
5
+ import os
6
+ from typing import Dict, Any
7
+
8
+ # Hugging Face Token güvenlik için ortam değişkeninden okunur
9
+ HF_TOKEN = os.getenv("HF_TOKEN", "")
10
+
11
+ # Model Yapılandırması
12
+ MODELS = {
13
+ "code_module": {
14
+ "model_id": "deepseek-ai/deepseek-coder-1.3b-instruct",
15
+ "task": "code_generation",
16
+ "max_tokens": 2048,
17
+ "temperature": 0.1,
18
+ "priority": 1
19
+ },
20
+ "chat_module": {
21
+ "model_id": "Qwen/Qwen2.5-1.5B-Instruct",
22
+ "task": "chat",
23
+ "max_tokens": 1024,
24
+ "temperature": 0.7,
25
+ "priority": 2
26
+ },
27
+ "reason_module": {
28
+ "model_id": "microsoft/Phi-3-mini-4k-instruct",
29
+ "task": "reasoning",
30
+ "max_tokens": 1024,
31
+ "temperature": 0.3,
32
+ "priority": 3
33
+ },
34
+ "fast_module": {
35
+ "model_id": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
36
+ "task": "quick_response",
37
+ "max_tokens": 512,
38
+ "temperature": 0.8,
39
+ "priority": 4
40
+ }
41
+ }
42
+
43
+ # Router Yapılandırması
44
+ ROUTER_CONFIG = {
45
+ "confidence_threshold": 0.6,
46
+ "max_concurrent_requests": 4,
47
+ "timeout": 30,
48
+ "fallback_model": "fast_module"
49
+ }
50
+
51
+ # Memory Yapılandırması
52
+ MEMORY_CONFIG = {
53
+ "max_slots": 10,
54
+ "slot_size": 1024,
55
+ "cleanup_interval": 300 # 5 dakika
56
+ }
57
+
58
+ # API Yapılandırması
59
+ API_CONFIG = {
60
+ "host": "0.0.0.0",
61
+ "port": 8000,
62
+ "workers": 1
63
+ }
64
+
65
+ # Sistem Limitleri
66
+ SYSTEM_LIMITS = {
67
+ "max_input_length": 4096,
68
+ "max_output_length": 2048,
69
+ "max_concurrent_users": 10
70
+ }
71
+
72
+ # Logging
73
+ LOGGING_CONFIG = {
74
+ "level": "INFO",
75
+ "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
76
+ "file": "logs/crane_ai.log"
77
+ }
78
+
79
+ def get_model_config(model_name: str) -> Dict[str, Any]:
80
+ """Belirli bir model için yapılandırma döndürür"""
81
+ return MODELS.get(model_name, MODELS["fast_module"])
82
+
83
+ def get_device():
84
+ """Kullanılacak cihazı belirler"""
85
+ try:
86
+ import torch
87
+ if torch.cuda.is_available():
88
+ return "cuda"
89
+ elif torch.backends.mps.is_available():
90
+ return "mps"
91
+ else:
92
+ return "cpu"
93
+ except ImportError:
94
+ return "cpu"
95
+
96
+ # Cihaz yapılandırması
97
+ DEVICE = get_device()
core/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Core Modülleri
3
+ """
4
+
5
+ from .base_module import BaseMicroModule
6
+ from .token_capsule import TokenCapsuleLayer, TokenCapsule
7
+
8
+ __all__ = [
9
+ 'BaseMicroModule',
10
+ 'TokenCapsuleLayer',
11
+ 'TokenCapsule'
12
+ ]
core/base_module.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Temel MicroModule Sınıfı
3
+ """
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import Any, Dict, List, Optional
7
+ import torch
8
+ from transformers import AutoTokenizer, AutoModelForCausalLM
9
+ from peft import PeftModel, PeftConfig
10
+ import os
11
+ import logging
12
+ import asyncio
13
+ from threading import Lock
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ class BaseMicroModule(ABC):
18
+ """Tüm MicroModule'lar için temel sınıf"""
19
+
20
+ def __init__(self, model_id: str, config: Dict[str, Any]):
21
+ self.model_id = model_id
22
+ self.config = config
23
+ self.device = config.get("device", "cpu")
24
+ self.max_tokens = config.get("max_tokens", 1024)
25
+ self.temperature = config.get("temperature", 0.7)
26
+ self.priority = config.get("priority", 1)
27
+
28
+ # Model ve tokenizer
29
+ self.model = None
30
+ self.tokenizer = None
31
+ self.is_loaded = False
32
+ self.load_lock = Lock()
33
+
34
+ # İstatistikler
35
+ self.request_count = 0
36
+ self.total_tokens = 0
37
+ self.avg_response_time = 0
38
+
39
+ async def load_model(self):
40
+ """Modeli yükler"""
41
+ if self.is_loaded:
42
+ return
43
+
44
+ with self.load_lock:
45
+ if self.is_loaded:
46
+ return
47
+
48
+ try:
49
+ logger.info(f"Loading model: {self.model_id}")
50
+
51
+ # Tokenizer yükleme
52
+ self.tokenizer = AutoTokenizer.from_pretrained(
53
+ self.model_id,
54
+ trust_remote_code=True,
55
+ token=self.config.get("hf_token")
56
+ )
57
+
58
+ # Model yükleme
59
+ self.model = AutoModelForCausalLM.from_pretrained(
60
+ self.model_id,
61
+ trust_remote_code=True,
62
+ torch_dtype=torch.float16 if self.device != "cpu" else torch.float32,
63
+ device_map="auto" if self.device != "cpu" else None,
64
+ token=self.config.get("hf_token")
65
+ )
66
+
67
+ # LoRA adaptörü kontrolü
68
+ adapter_dir = os.path.join("model_cache", self.model_id.replace("/", "_"), "adapter")
69
+ if os.path.isdir(adapter_dir):
70
+ try:
71
+ self.model = PeftModel.from_pretrained(self.model, adapter_dir, is_trainable=False)
72
+ self.model = self.model.merge_and_unload()
73
+ logger.info(f"LoRA adaptörü yüklendi: {adapter_dir}")
74
+ except Exception as adp_err:
75
+ logger.warning(f"Adaptör yüklenemedi ({adapter_dir}): {adp_err}")
76
+
77
+ # Pad token ayarı
78
+ if self.tokenizer.pad_token is None:
79
+ self.tokenizer.pad_token = self.tokenizer.eos_token
80
+
81
+ self.is_loaded = True
82
+ logger.info(f"Model loaded successfully: {self.model_id}")
83
+
84
+ except Exception as e:
85
+ logger.error(f"Error loading model {self.model_id}: {str(e)}")
86
+ raise
87
+
88
+ @abstractmethod
89
+ def can_handle(self, query: str, context: Dict[str, Any]) -> float:
90
+ """Bu modülün sorguyu ne kadar iyi işleyebileceğini belirler (0-1)"""
91
+ pass
92
+
93
+ @abstractmethod
94
+ async def process(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
95
+ """Ana işleme fonksiyonu"""
96
+ pass
97
+
98
+ async def generate_response(self, prompt: str, **kwargs) -> str:
99
+ """Metin üretimi"""
100
+ if not self.is_loaded:
101
+ await self.load_model()
102
+
103
+ try:
104
+ # Tokenlara çevir
105
+ inputs = self.tokenizer(
106
+ prompt,
107
+ return_tensors="pt",
108
+ max_length=self.max_tokens,
109
+ truncation=True,
110
+ padding=True
111
+ )
112
+
113
+ # Tenzile cihaz aktarımı
114
+ if self.device != "cpu":
115
+ inputs = {k: v.to(self.device) for k, v in inputs.items()}
116
+
117
+ # Üretim parametreleri
118
+ generation_config = {
119
+ "max_new_tokens": kwargs.get("max_tokens", self.max_tokens),
120
+ "temperature": kwargs.get("temperature", self.temperature),
121
+ "do_sample": True,
122
+ "top_p": 0.9,
123
+ "top_k": 50,
124
+ "pad_token_id": self.tokenizer.pad_token_id,
125
+ "eos_token_id": self.tokenizer.eos_token_id,
126
+ "no_repeat_ngram_size": 3
127
+ }
128
+
129
+ # Üretim
130
+ with torch.no_grad():
131
+ outputs = self.model.generate(
132
+ **inputs,
133
+ **generation_config
134
+ )
135
+
136
+ # Metne çevir
137
+ response = self.tokenizer.decode(
138
+ outputs[0][inputs["input_ids"].shape[1]:],
139
+ skip_special_tokens=True
140
+ )
141
+
142
+ # İstatistikleri güncelle
143
+ self.request_count += 1
144
+ self.total_tokens += len(outputs[0])
145
+
146
+ return response.strip()
147
+
148
+ except Exception as e:
149
+ logger.error(f"Generation error in {self.model_id}: {str(e)}")
150
+ raise
151
+
152
+ def get_stats(self) -> Dict[str, Any]:
153
+ """Modül istatistiklerini döndürür"""
154
+ return {
155
+ "model_id": self.model_id,
156
+ "is_loaded": self.is_loaded,
157
+ "request_count": self.request_count,
158
+ "total_tokens": self.total_tokens,
159
+ "avg_response_time": self.avg_response_time,
160
+ "priority": self.priority
161
+ }
162
+
163
+ def unload_model(self):
164
+ """Modeli bellekten kaldırır"""
165
+ if self.model:
166
+ del self.model
167
+ self.model = None
168
+ if self.tokenizer:
169
+ del self.tokenizer
170
+ self.tokenizer = None
171
+ self.is_loaded = False
172
+
173
+ # GPU belleğini temizle
174
+ if torch.cuda.is_available():
175
+ torch.cuda.empty_cache()
176
+
177
+ logger.info(f"Model unloaded: {self.model_id}")
core/token_capsule.py ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Token Capsule Layer
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional, Tuple
6
+ import torch
7
+ import numpy as np
8
+ from transformers import AutoTokenizer
9
+ import logging
10
+ from dataclasses import dataclass
11
+ import asyncio
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ @dataclass
16
+ class TokenCapsule:
17
+ """Token kapsülü veri yapısı"""
18
+ tokens: List[int]
19
+ attention_mask: List[int]
20
+ token_type_ids: List[int]
21
+ embeddings: Optional[torch.Tensor] = None
22
+ metadata: Dict[str, Any] = None
23
+
24
+ class TokenCapsuleLayer:
25
+ """Token işleme ve optimizasyon katmanı"""
26
+
27
+ def __init__(self, config: Dict[str, Any]):
28
+ self.config = config
29
+ self.max_length = config.get("max_length", 2048)
30
+ self.device = config.get("device", "cpu")
31
+
32
+ # Token cache
33
+ self.token_cache = {}
34
+ self.cache_size = config.get("cache_size", 1000)
35
+
36
+ # Token istatistikleri
37
+ self.token_stats = {
38
+ "total_processed": 0,
39
+ "cache_hits": 0,
40
+ "cache_misses": 0,
41
+ "avg_token_length": 0
42
+ }
43
+
44
+ # Tokenizer havuzu
45
+ self.tokenizer_pool = {}
46
+
47
+ async def process_input(self, text: str, model_id: str, context: Dict[str, Any] = None) -> TokenCapsule:
48
+ """Giriş metnini token kapsülüne çevirir"""
49
+ try:
50
+ # Cache kontrolü
51
+ cache_key = f"{model_id}:{hash(text)}"
52
+ if cache_key in self.token_cache:
53
+ self.token_stats["cache_hits"] += 1
54
+ return self.token_cache[cache_key]
55
+
56
+ # Tokenizer al
57
+ tokenizer = await self._get_tokenizer(model_id)
58
+
59
+ # Tokenize et
60
+ encoding = tokenizer(
61
+ text,
62
+ max_length=self.max_length,
63
+ padding=True,
64
+ truncation=True,
65
+ return_tensors="pt"
66
+ )
67
+
68
+ # Token kapsülü oluştur
69
+ capsule = TokenCapsule(
70
+ tokens=encoding["input_ids"].squeeze().tolist(),
71
+ attention_mask=encoding["attention_mask"].squeeze().tolist(),
72
+ token_type_ids=encoding.get("token_type_ids", []).squeeze().tolist() if encoding.get("token_type_ids") is not None else [],
73
+ metadata={
74
+ "model_id": model_id,
75
+ "original_text": text[:100], # İlk 100 karakter
76
+ "token_count": len(encoding["input_ids"].squeeze()),
77
+ "context": context
78
+ }
79
+ )
80
+
81
+ # Cache'e ekle
82
+ self._add_to_cache(cache_key, capsule)
83
+
84
+ # İstatistikleri güncelle
85
+ self.token_stats["total_processed"] += 1
86
+ self.token_stats["cache_misses"] += 1
87
+ self._update_avg_length(len(capsule.tokens))
88
+
89
+ return capsule
90
+
91
+ except Exception as e:
92
+ logger.error(f"Token processing error: {str(e)}")
93
+ raise
94
+
95
+ async def optimize_tokens(self, capsule: TokenCapsule, optimization_type: str = "standard") -> TokenCapsule:
96
+ """Token optimizasyonu yapar"""
97
+ try:
98
+ if optimization_type == "compress":
99
+ return await self._compress_tokens(capsule)
100
+ elif optimization_type == "expand":
101
+ return await self._expand_tokens(capsule)
102
+ elif optimization_type == "filter":
103
+ return await self._filter_tokens(capsule)
104
+ else:
105
+ return capsule
106
+
107
+ except Exception as e:
108
+ logger.error(f"Token optimization error: {str(e)}")
109
+ return capsule
110
+
111
+ async def merge_capsules(self, capsules: List[TokenCapsule], strategy: str = "concat") -> TokenCapsule:
112
+ """Birden fazla kapsülü birleştirir"""
113
+ try:
114
+ if strategy == "concat":
115
+ return await self._concat_capsules(capsules)
116
+ elif strategy == "interleave":
117
+ return await self._interleave_capsules(capsules)
118
+ elif strategy == "priority":
119
+ return await self._priority_merge_capsules(capsules)
120
+ else:
121
+ return capsules[0] if capsules else None
122
+
123
+ except Exception as e:
124
+ logger.error(f"Capsule merging error: {str(e)}")
125
+ return capsules[0] if capsules else None
126
+
127
+ async def extract_embeddings(self, capsule: TokenCapsule, model: Any) -> TokenCapsule:
128
+ """Token embedding'lerini çıkarır"""
129
+ try:
130
+ if capsule.embeddings is not None:
131
+ return capsule
132
+
133
+ # Model'den embedding'leri al
134
+ input_ids = torch.tensor([capsule.tokens]).to(self.device)
135
+ attention_mask = torch.tensor([capsule.attention_mask]).to(self.device)
136
+
137
+ with torch.no_grad():
138
+ outputs = model(
139
+ input_ids=input_ids,
140
+ attention_mask=attention_mask,
141
+ output_hidden_states=True
142
+ )
143
+
144
+ # Son katman hidden state'ini al
145
+ embeddings = outputs.hidden_states[-1]
146
+ capsule.embeddings = embeddings.squeeze()
147
+
148
+ return capsule
149
+
150
+ except Exception as e:
151
+ logger.error(f"Embedding extraction error: {str(e)}")
152
+ return capsule
153
+
154
+ async def _get_tokenizer(self, model_id: str) -> AutoTokenizer:
155
+ """Model için tokenizer alır"""
156
+ if model_id not in self.tokenizer_pool:
157
+ try:
158
+ tokenizer = AutoTokenizer.from_pretrained(
159
+ model_id,
160
+ trust_remote_code=True,
161
+ token=self.config.get("hf_token")
162
+ )
163
+
164
+ # Pad token ayarı
165
+ if tokenizer.pad_token is None:
166
+ tokenizer.pad_token = tokenizer.eos_token
167
+
168
+ self.tokenizer_pool[model_id] = tokenizer
169
+
170
+ except Exception as e:
171
+ logger.error(f"Tokenizer loading error for {model_id}: {str(e)}")
172
+ raise
173
+
174
+ return self.tokenizer_pool[model_id]
175
+
176
+ async def _compress_tokens(self, capsule: TokenCapsule) -> TokenCapsule:
177
+ """Token sıkıştırma"""
178
+ # Önemli token'ları tespit et ve gereksizleri çıkar
179
+ important_tokens = []
180
+ attention_mask = []
181
+
182
+ for i, token in enumerate(capsule.tokens):
183
+ # Özel tokenları koru
184
+ if token in [0, 1, 2, 3]: # [PAD], [UNK], [CLS], [SEP]
185
+ important_tokens.append(token)
186
+ attention_mask.append(capsule.attention_mask[i])
187
+ # Çok tekrarlanan tokenları atla
188
+ elif token not in important_tokens[-5:]: # Son 5 token içinde yoksa
189
+ important_tokens.append(token)
190
+ attention_mask.append(capsule.attention_mask[i])
191
+
192
+ compressed_capsule = TokenCapsule(
193
+ tokens=important_tokens,
194
+ attention_mask=attention_mask,
195
+ token_type_ids=capsule.token_type_ids[:len(important_tokens)],
196
+ embeddings=capsule.embeddings,
197
+ metadata={**capsule.metadata, "compressed": True}
198
+ )
199
+
200
+ return compressed_capsule
201
+
202
+ async def _expand_tokens(self, capsule: TokenCapsule) -> TokenCapsule:
203
+ """Token genişletme"""
204
+ # Context token'ları ekle
205
+ expanded_tokens = [1] + capsule.tokens + [2] # [CLS] + tokens + [SEP]
206
+ expanded_attention = [1] + capsule.attention_mask + [1]
207
+
208
+ expanded_capsule = TokenCapsule(
209
+ tokens=expanded_tokens,
210
+ attention_mask=expanded_attention,
211
+ token_type_ids=capsule.token_type_ids,
212
+ embeddings=capsule.embeddings,
213
+ metadata={**capsule.metadata, "expanded": True}
214
+ )
215
+
216
+ return expanded_capsule
217
+
218
+ async def _filter_tokens(self, capsule: TokenCapsule) -> TokenCapsule:
219
+ """Token filtreleme"""
220
+ # Gereksiz token'ları filtrele
221
+ filtered_tokens = []
222
+ filtered_attention = []
223
+
224
+ for i, token in enumerate(capsule.tokens):
225
+ # Padding token'ları atla
226
+ if token != 0:
227
+ filtered_tokens.append(token)
228
+ filtered_attention.append(capsule.attention_mask[i])
229
+
230
+ filtered_capsule = TokenCapsule(
231
+ tokens=filtered_tokens,
232
+ attention_mask=filtered_attention,
233
+ token_type_ids=capsule.token_type_ids[:len(filtered_tokens)],
234
+ embeddings=capsule.embeddings,
235
+ metadata={**capsule.metadata, "filtered": True}
236
+ )
237
+
238
+ return filtered_capsule
239
+
240
+ async def _concat_capsules(self, capsules: List[TokenCapsule]) -> TokenCapsule:
241
+ """Kapsülleri ardışık olarak birleştirir"""
242
+ if not capsules:
243
+ return None
244
+
245
+ merged_tokens = []
246
+ merged_attention = []
247
+ merged_metadata = {"merged": True, "source_count": len(capsules)}
248
+
249
+ for capsule in capsules:
250
+ merged_tokens.extend(capsule.tokens)
251
+ merged_attention.extend(capsule.attention_mask)
252
+
253
+ # Metadata birleştir
254
+ if capsule.metadata:
255
+ for key, value in capsule.metadata.items():
256
+ if key not in merged_metadata:
257
+ merged_metadata[key] = []
258
+ merged_metadata[key].append(value)
259
+
260
+ # Maksimum uzunluk kontrolü
261
+ if len(merged_tokens) > self.max_length:
262
+ merged_tokens = merged_tokens[:self.max_length]
263
+ merged_attention = merged_attention[:self.max_length]
264
+
265
+ return TokenCapsule(
266
+ tokens=merged_tokens,
267
+ attention_mask=merged_attention,
268
+ token_type_ids=[],
269
+ metadata=merged_metadata
270
+ )
271
+
272
+ async def _interleave_capsules(self, capsules: List[TokenCapsule]) -> TokenCapsule:
273
+ """Kapsülleri aralarında birleştirir"""
274
+ # Implement interleaving logic
275
+ return await self._concat_capsules(capsules)
276
+
277
+ async def _priority_merge_capsules(self, capsules: List[TokenCapsule]) -> TokenCapsule:
278
+ """Öncelik sırasına göre birleştirir"""
279
+ # Öncelik skoruna göre sırala
280
+ sorted_capsules = sorted(capsules, key=lambda x: x.metadata.get("priority", 0), reverse=True)
281
+ return await self._concat_capsules(sorted_capsules)
282
+
283
+ def _add_to_cache(self, key: str, capsule: TokenCapsule):
284
+ """Cache'e ekler"""
285
+ if len(self.token_cache) >= self.cache_size:
286
+ # En eski entry'yi sil
287
+ oldest_key = next(iter(self.token_cache))
288
+ del self.token_cache[oldest_key]
289
+
290
+ self.token_cache[key] = capsule
291
+
292
+ def _update_avg_length(self, length: int):
293
+ """Ortalama token uzunluğunu günceller"""
294
+ current_avg = self.token_stats["avg_token_length"]
295
+ total_processed = self.token_stats["total_processed"]
296
+
297
+ # Yeni ortalama hesapla
298
+ new_avg = ((current_avg * (total_processed - 1)) + length) / total_processed
299
+ self.token_stats["avg_token_length"] = new_avg
300
+
301
+ def get_stats(self) -> Dict[str, Any]:
302
+ """Token layer istatistikleri"""
303
+ cache_hit_rate = self.token_stats["cache_hits"] / max(self.token_stats["total_processed"], 1)
304
+
305
+ return {
306
+ "total_processed": self.token_stats["total_processed"],
307
+ "cache_hit_rate": cache_hit_rate,
308
+ "cache_size": len(self.token_cache),
309
+ "avg_token_length": self.token_stats["avg_token_length"],
310
+ "tokenizer_pool_size": len(self.tokenizer_pool)
311
+ }
312
+
313
+ def clear_cache(self):
314
+ """Cache'i temizler"""
315
+ self.token_cache.clear()
316
+ logger.info("Token cache cleared")
download_models.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ CRANE AI - Model İndirme Script'i
4
+ HuggingFace'den modelleri önceden indirir
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import logging
10
+ from typing import Dict, Any
11
+ import asyncio
12
+ import torch
13
+ from transformers import AutoTokenizer, AutoModelForCausalLM
14
+ from huggingface_hub import login
15
+ import gc
16
+
17
+ # Logging ayarları
18
+ logging.basicConfig(
19
+ level=logging.INFO,
20
+ format='%(asctime)s - %(levelname)s - %(message)s'
21
+ )
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # HuggingFace Token
25
+ HF_TOKEN = os.getenv("HF_TOKEN", "")
26
+
27
+ # İndirilecek modeller
28
+ MODELS_TO_DOWNLOAD = {
29
+ "deepseek-coder": {
30
+ "model_id": "deepseek-ai/deepseek-coder-1.3b-instruct",
31
+ "description": "Kod yazımı için DeepSeek Coder 1.3B",
32
+ "task": "code_generation"
33
+ },
34
+ "qwen-chat": {
35
+ "model_id": "Qwen/Qwen2.5-1.5B-Instruct",
36
+ "description": "Sohbet için Qwen2.5 1.5B",
37
+ "task": "chat"
38
+ },
39
+ "phi-reason": {
40
+ "model_id": "microsoft/Phi-3-mini-4k-instruct",
41
+ "description": "Mantık için Phi-3 Mini",
42
+ "task": "reasoning"
43
+ },
44
+ "tinyllama-fast": {
45
+ "model_id": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
46
+ "description": "Hızlı yanıt için TinyLlama 1.1B",
47
+ "task": "quick_response"
48
+ }
49
+ }
50
+
51
+ def get_device():
52
+ """Cihaz tipini belirler"""
53
+ if torch.cuda.is_available():
54
+ return "cuda"
55
+ elif torch.backends.mps.is_available():
56
+ return "mps"
57
+ else:
58
+ return "cpu"
59
+
60
+ def setup_cache_dir():
61
+ """Model cache dizinini ayarlar"""
62
+ cache_dir = os.path.join(os.getcwd(), "model_cache")
63
+ os.makedirs(cache_dir, exist_ok=True)
64
+ os.environ["TRANSFORMERS_CACHE"] = cache_dir
65
+ return cache_dir
66
+
67
+ def login_huggingface():
68
+ """HuggingFace'e login ol"""
69
+ try:
70
+ login(token=HF_TOKEN)
71
+ logger.info("✅ HuggingFace login başarılı")
72
+ return True
73
+ except Exception as e:
74
+ logger.error(f"❌ HuggingFace login hatası: {str(e)}")
75
+ return False
76
+
77
+ def download_model(model_info: Dict[str, Any]) -> bool:
78
+ """Tek bir modeli indir"""
79
+ model_id = model_info["model_id"]
80
+ description = model_info["description"]
81
+
82
+ try:
83
+ logger.info(f"📥 İndiriliyor: {description}")
84
+ logger.info(f" Model ID: {model_id}")
85
+
86
+ # Önce tokenizer'ı indir
87
+ logger.info(" 🔤 Tokenizer indiriliyor...")
88
+ tokenizer = AutoTokenizer.from_pretrained(
89
+ model_id,
90
+ trust_remote_code=True,
91
+ token=HF_TOKEN
92
+ )
93
+ logger.info(" ✅ Tokenizer indirildi")
94
+
95
+ # Sonra modeli indir
96
+ logger.info(" 🤖 Model indiriliyor...")
97
+ model = AutoModelForCausalLM.from_pretrained(
98
+ model_id,
99
+ trust_remote_code=True,
100
+ torch_dtype=torch.float16 if get_device() != "cpu" else torch.float32,
101
+ token=HF_TOKEN
102
+ )
103
+ logger.info(" ✅ Model indirildi")
104
+
105
+ # Belleği temizle
106
+ del model
107
+ del tokenizer
108
+ gc.collect()
109
+ if torch.cuda.is_available():
110
+ torch.cuda.empty_cache()
111
+
112
+ logger.info(f"✅ {description} başarıyla indirildi!\n")
113
+ return True
114
+
115
+ except Exception as e:
116
+ logger.error(f"❌ {description} indirme hatası: {str(e)}\n")
117
+ return False
118
+
119
+ def main():
120
+ """Ana fonksiyon"""
121
+ logger.info("🚀 CRANE AI Model İndirme Başlatılıyor...")
122
+ logger.info(f"🔧 Cihaz: {get_device()}")
123
+
124
+ # Cache dizini ayarla
125
+ cache_dir = setup_cache_dir()
126
+ logger.info(f"📁 Cache dizini: {cache_dir}")
127
+
128
+ # HuggingFace login
129
+ if not login_huggingface():
130
+ logger.error("❌ HuggingFace login başarısız. Çıkılıyor...")
131
+ sys.exit(1)
132
+
133
+ # Modelleri indir
134
+ logger.info(f"📦 {len(MODELS_TO_DOWNLOAD)} model indirilecek...\n")
135
+
136
+ successful_downloads = 0
137
+ failed_downloads = 0
138
+
139
+ for model_name, model_info in MODELS_TO_DOWNLOAD.items():
140
+ if download_model(model_info):
141
+ successful_downloads += 1
142
+ else:
143
+ failed_downloads += 1
144
+
145
+ # Özet
146
+ logger.info("="*50)
147
+ logger.info("📊 İNDİRME ÖZETİ")
148
+ logger.info("="*50)
149
+ logger.info(f"✅ Başarılı: {successful_downloads}")
150
+ logger.info(f"❌ Başarısız: {failed_downloads}")
151
+ logger.info(f"📁 Cache dizini: {cache_dir}")
152
+
153
+ if successful_downloads == len(MODELS_TO_DOWNLOAD):
154
+ logger.info("🎉 Tüm modeller başarıyla indirildi!")
155
+ else:
156
+ logger.warning("⚠️ Bazı modeller indirilemedi.")
157
+
158
+ logger.info("="*50)
159
+
160
+ if __name__ == "__main__":
161
+ main()
memory/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Memory Package
3
+ """
4
+
5
+ from .local_memory import LocalMemoryManager, MemorySlot
6
+
7
+ __all__ = ['LocalMemoryManager', 'MemorySlot']
memory/local_memory.py ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Local Memory Management
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional
6
+ import asyncio
7
+ import time
8
+ import json
9
+ from dataclasses import dataclass, asdict
10
+ from datetime import datetime, timedelta
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ @dataclass
16
+ class MemorySlot:
17
+ """Bellek slot'u veri yapısı"""
18
+ id: str
19
+ content: Any
20
+ timestamp: float
21
+ ttl: float # Time to live (seconds)
22
+ access_count: int = 0
23
+ priority: int = 1
24
+ tags: List[str] = None
25
+ metadata: Dict[str, Any] = None
26
+
27
+ def __post_init__(self):
28
+ if self.tags is None:
29
+ self.tags = []
30
+ if self.metadata is None:
31
+ self.metadata = {}
32
+
33
+ def is_expired(self) -> bool:
34
+ """Slot'un süresinin dolup dolmadığını kontrol eder"""
35
+ return time.time() > (self.timestamp + self.ttl)
36
+
37
+ def update_access(self):
38
+ """Erişim sayısını günceller"""
39
+ self.access_count += 1
40
+ self.timestamp = time.time()
41
+
42
+ def to_dict(self) -> Dict[str, Any]:
43
+ """Dictionary'e çevirir"""
44
+ return asdict(self)
45
+
46
+ class LocalMemoryManager:
47
+ """Yerel bellek yönetimi sistemi"""
48
+
49
+ def __init__(self, config: Dict[str, Any]):
50
+ self.config = config
51
+ self.max_slots = config.get("max_slots", 10)
52
+ self.default_ttl = config.get("default_ttl", 3600) # 1 saat
53
+ self.cleanup_interval = config.get("cleanup_interval", 300) # 5 dakika
54
+
55
+ # Bellek slot'ları
56
+ self.slots: Dict[str, MemorySlot] = {}
57
+
58
+ # İstatistikler
59
+ self.stats = {
60
+ "total_writes": 0,
61
+ "total_reads": 0,
62
+ "cache_hits": 0,
63
+ "cache_misses": 0,
64
+ "evictions": 0,
65
+ "cleanups": 0
66
+ }
67
+
68
+ # Background cleanup task
69
+ self.cleanup_task = None
70
+ self.is_running = False
71
+
72
+ async def start(self):
73
+ """Bellek yöneticisini başlatır"""
74
+ if not self.is_running:
75
+ self.is_running = True
76
+ self.cleanup_task = asyncio.create_task(self._cleanup_worker())
77
+ logger.info("Memory manager started")
78
+
79
+ async def stop(self):
80
+ """Bellek yöneticisini durdurur"""
81
+ self.is_running = False
82
+ if self.cleanup_task:
83
+ self.cleanup_task.cancel()
84
+ try:
85
+ await self.cleanup_task
86
+ except asyncio.CancelledError:
87
+ pass
88
+ logger.info("Memory manager stopped")
89
+
90
+ async def store(self, key: str, content: Any, ttl: Optional[float] = None,
91
+ priority: int = 1, tags: List[str] = None, metadata: Dict[str, Any] = None) -> bool:
92
+ """Bellek slot'una veri yazar"""
93
+ try:
94
+ # TTL ayarı
95
+ if ttl is None:
96
+ ttl = self.default_ttl
97
+
98
+ # Slot oluştur
99
+ slot = MemorySlot(
100
+ id=key,
101
+ content=content,
102
+ timestamp=time.time(),
103
+ ttl=ttl,
104
+ priority=priority,
105
+ tags=tags or [],
106
+ metadata=metadata or {}
107
+ )
108
+
109
+ # Yer kontrolü
110
+ if len(self.slots) >= self.max_slots and key not in self.slots:
111
+ await self._evict_slot()
112
+
113
+ # Slot'u kaydet
114
+ self.slots[key] = slot
115
+ self.stats["total_writes"] += 1
116
+
117
+ logger.debug(f"Stored in memory slot: {key}")
118
+ return True
119
+
120
+ except Exception as e:
121
+ logger.error(f"Memory store error: {str(e)}")
122
+ return False
123
+
124
+ async def retrieve(self, key: str) -> Optional[Any]:
125
+ """Bellek slot'undan veri okur"""
126
+ try:
127
+ if key not in self.slots:
128
+ self.stats["cache_misses"] += 1
129
+ return None
130
+
131
+ slot = self.slots[key]
132
+
133
+ # Expire kontrolü
134
+ if slot.is_expired():
135
+ await self.remove(key)
136
+ self.stats["cache_misses"] += 1
137
+ return None
138
+
139
+ # Erişim güncelle
140
+ slot.update_access()
141
+ self.stats["total_reads"] += 1
142
+ self.stats["cache_hits"] += 1
143
+
144
+ logger.debug(f"Retrieved from memory slot: {key}")
145
+ return slot.content
146
+
147
+ except Exception as e:
148
+ logger.error(f"Memory retrieve error: {str(e)}")
149
+ return None
150
+
151
+ async def remove(self, key: str) -> bool:
152
+ """Bellek slot'unu siler"""
153
+ try:
154
+ if key in self.slots:
155
+ del self.slots[key]
156
+ logger.debug(f"Removed memory slot: {key}")
157
+ return True
158
+ return False
159
+
160
+ except Exception as e:
161
+ logger.error(f"Memory remove error: {str(e)}")
162
+ return False
163
+
164
+ async def search_by_tags(self, tags: List[str]) -> List[MemorySlot]:
165
+ """Tag'lere göre slot'ları arar"""
166
+ matching_slots = []
167
+
168
+ for slot in self.slots.values():
169
+ if not slot.is_expired():
170
+ if any(tag in slot.tags for tag in tags):
171
+ matching_slots.append(slot)
172
+
173
+ return matching_slots
174
+
175
+ async def get_active_slots(self) -> List[MemorySlot]:
176
+ """Aktif slot'ları döndürür"""
177
+ active_slots = []
178
+
179
+ for slot in self.slots.values():
180
+ if not slot.is_expired():
181
+ active_slots.append(slot)
182
+
183
+ return active_slots
184
+
185
+ async def update_slot(self, key: str, content: Any = None, ttl: Optional[float] = None,
186
+ priority: Optional[int] = None, tags: Optional[List[str]] = None,
187
+ metadata: Optional[Dict[str, Any]] = None) -> bool:
188
+ """Slot'u günceller"""
189
+ try:
190
+ if key not in self.slots:
191
+ return False
192
+
193
+ slot = self.slots[key]
194
+
195
+ # Expire kontrolü
196
+ if slot.is_expired():
197
+ await self.remove(key)
198
+ return False
199
+
200
+ # Güncellemeleri uygula
201
+ if content is not None:
202
+ slot.content = content
203
+ if ttl is not None:
204
+ slot.ttl = ttl
205
+ if priority is not None:
206
+ slot.priority = priority
207
+ if tags is not None:
208
+ slot.tags = tags
209
+ if metadata is not None:
210
+ slot.metadata.update(metadata)
211
+
212
+ slot.timestamp = time.time()
213
+
214
+ logger.debug(f"Updated memory slot: {key}")
215
+ return True
216
+
217
+ except Exception as e:
218
+ logger.error(f"Memory update error: {str(e)}")
219
+ return False
220
+
221
+ async def _evict_slot(self):
222
+ """En az öncelikli slot'u çıkarır"""
223
+ if not self.slots:
224
+ return
225
+
226
+ # En az kullanılan ve en düşük öncelikli slot'u bul
227
+ candidates = []
228
+ for slot in self.slots.values():
229
+ if not slot.is_expired():
230
+ candidates.append(slot)
231
+
232
+ if not candidates:
233
+ return
234
+
235
+ # Skorlama: düşük priority + düşük access_count + eski timestamp
236
+ def eviction_score(slot):
237
+ age = time.time() - slot.timestamp
238
+ return (1 / slot.priority) + (1 / max(slot.access_count, 1)) + (age / 3600)
239
+
240
+ victim = max(candidates, key=eviction_score)
241
+ await self.remove(victim.id)
242
+ self.stats["evictions"] += 1
243
+
244
+ logger.debug(f"Evicted memory slot: {victim.id}")
245
+
246
+ async def _cleanup_worker(self):
247
+ """Periyodik temizlik işlevi"""
248
+ while self.is_running:
249
+ try:
250
+ await asyncio.sleep(self.cleanup_interval)
251
+ await self._cleanup_expired()
252
+ except asyncio.CancelledError:
253
+ break
254
+ except Exception as e:
255
+ logger.error(f"Cleanup worker error: {str(e)}")
256
+
257
+ async def _cleanup_expired(self):
258
+ """Süresi dolmuş slot'ları temizler"""
259
+ expired_keys = []
260
+
261
+ for key, slot in self.slots.items():
262
+ if slot.is_expired():
263
+ expired_keys.append(key)
264
+
265
+ for key in expired_keys:
266
+ await self.remove(key)
267
+
268
+ if expired_keys:
269
+ self.stats["cleanups"] += 1
270
+ logger.debug(f"Cleaned up {len(expired_keys)} expired slots")
271
+
272
+ async def export_memory(self, include_expired: bool = False) -> Dict[str, Any]:
273
+ """Belleği dışa aktarır"""
274
+ export_data = {
275
+ "timestamp": datetime.now().isoformat(),
276
+ "slots": [],
277
+ "stats": self.stats
278
+ }
279
+
280
+ for slot in self.slots.values():
281
+ if include_expired or not slot.is_expired():
282
+ export_data["slots"].append(slot.to_dict())
283
+
284
+ return export_data
285
+
286
+ async def import_memory(self, data: Dict[str, Any]) -> bool:
287
+ """Belleği içe aktarır"""
288
+ try:
289
+ slots_data = data.get("slots", [])
290
+
291
+ for slot_data in slots_data:
292
+ slot = MemorySlot(**slot_data)
293
+ if not slot.is_expired():
294
+ self.slots[slot.id] = slot
295
+
296
+ logger.info(f"Imported {len(slots_data)} memory slots")
297
+ return True
298
+
299
+ except Exception as e:
300
+ logger.error(f"Memory import error: {str(e)}")
301
+ return False
302
+
303
+ def get_stats(self) -> Dict[str, Any]:
304
+ """Bellek istatistikleri"""
305
+ total_requests = self.stats["total_reads"]
306
+ hit_rate = self.stats["cache_hits"] / max(total_requests, 1)
307
+
308
+ active_slots = sum(1 for slot in self.slots.values() if not slot.is_expired())
309
+
310
+ return {
311
+ "total_slots": len(self.slots),
312
+ "active_slots": active_slots,
313
+ "max_slots": self.max_slots,
314
+ "hit_rate": hit_rate,
315
+ "total_writes": self.stats["total_writes"],
316
+ "total_reads": self.stats["total_reads"],
317
+ "evictions": self.stats["evictions"],
318
+ "cleanups": self.stats["cleanups"]
319
+ }
320
+
321
+ async def clear_all(self):
322
+ """Tüm belleği temizler"""
323
+ self.slots.clear()
324
+ logger.info("All memory slots cleared")
modules/__init__.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Modüller
3
+ """
4
+
5
+ from .code_module import CodeModule
6
+ from .chat_module import ChatModule
7
+ from .reason_module import ReasonModule
8
+ from .fast_module import FastModule
9
+
10
+ __all__ = [
11
+ 'CodeModule',
12
+ 'ChatModule',
13
+ 'ReasonModule',
14
+ 'FastModule'
15
+ ]
modules/chat_module.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Sohbet Modülü
3
+ """
4
+
5
+ from typing import Dict, Any
6
+ from core.base_module import BaseMicroModule
7
+ import logging
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class ChatModule(BaseMicroModule):
12
+ """Genel sohbet için özelleşmiş modül"""
13
+
14
+ def __init__(self, config: Dict[str, Any]):
15
+ super().__init__(
16
+ model_id="Qwen/Qwen2.5-1.5B-Instruct",
17
+ config=config
18
+ )
19
+
20
+ # Sohbet anahtar kelimeleri
21
+ self.chat_keywords = {
22
+ "merhaba", "selam", "nasılsın", "naber", "günaydın",
23
+ "iyi akşamlar", "hoş geldin", "sohbet", "konuş",
24
+ "anlat", "düşün", "fikir", "görüş", "yardım",
25
+ "açıkla", "izah", "detay", "örnek", "hikaye"
26
+ }
27
+
28
+ # Genel konular
29
+ self.general_topics = {
30
+ "hava", "spor", "müzik", "film", "kitap", "yemek",
31
+ "seyahat", "hobiler", "oyun", "teknoloji", "tarih",
32
+ "kültür", "sanat", "bilim", "doğa", "eğitim"
33
+ }
34
+
35
+ def can_handle(self, query: str, context: Dict[str, Any]) -> float:
36
+ """Sohbet sorguları için uygunluk skoru"""
37
+ query_lower = query.lower()
38
+
39
+ # Sohbet anahtar kelimelerini kontrol et
40
+ chat_score = 0
41
+ for keyword in self.chat_keywords:
42
+ if keyword in query_lower:
43
+ chat_score += 0.15
44
+
45
+ # Genel konuları kontrol et
46
+ for topic in self.general_topics:
47
+ if topic in query_lower:
48
+ chat_score += 0.1
49
+
50
+ # Soru işaretleri ve konuşma ifadeleri
51
+ if "?" in query or "nedir" in query_lower or "nasıl" in query_lower:
52
+ chat_score += 0.2
53
+
54
+ # Uzun açıklama gerektiren sorular
55
+ if any(word in query_lower for word in ["açıkla", "anlat", "detay", "neden"]):
56
+ chat_score += 0.25
57
+
58
+ # Kısa ve basit sorular için yüksek skor
59
+ if len(query.split()) <= 10:
60
+ chat_score += 0.1
61
+
62
+ # Maksimum 1.0 skor
63
+ return min(chat_score, 1.0)
64
+
65
+ async def process(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
66
+ """Sohbet işlemi"""
67
+ try:
68
+ # Sohbet için özel prompt
69
+ prompt = self._build_chat_prompt(query, context)
70
+
71
+ # Yanıt üretimi
72
+ response = await self.generate_response(
73
+ prompt,
74
+ max_tokens=self.config.get("max_tokens", 1024),
75
+ temperature=0.7 # Sohbet için orta temperature
76
+ )
77
+
78
+ return {
79
+ "response": response,
80
+ "module": "chat_module",
81
+ "confidence": self.can_handle(query, context),
82
+ "conversation_type": self._detect_conversation_type(query)
83
+ }
84
+
85
+ except Exception as e:
86
+ logger.error(f"Chat processing error: {str(e)}")
87
+ return {
88
+ "error": str(e),
89
+ "module": "chat_module"
90
+ }
91
+
92
+ def _build_chat_prompt(self, query: str, context: Dict[str, Any]) -> str:
93
+ """Sohbet için prompt hazırlar"""
94
+
95
+ # Konuşma geçmişi
96
+ history = context.get("history", [])
97
+
98
+ # Temel prompt
99
+ prompt = f"""Sen yardımsever, dostane ve zeki bir asistansın. Kullanıcılarla doğal bir şekilde sohbet ediyorsun.
100
+
101
+ Özellikler:
102
+ - Türkçe konuşuyorsun
103
+ - Samimi ve dostane bir ton kullanıyorsun
104
+ - Bilgilendirici ama sıkıcı olmayan yanıtlar veriyorsun
105
+ - Kullanıcının duygusal durumunu anlıyorsun
106
+
107
+ """
108
+
109
+ # Konuşma geçmişi varsa ekle
110
+ if history:
111
+ prompt += "Önceki konuşma:\n"
112
+ for i, msg in enumerate(history[-3:]): # Son 3 mesajı al
113
+ prompt += f"{'Kullanıcı' if i % 2 == 0 else 'Asistan'}: {msg}\n"
114
+ prompt += "\n"
115
+
116
+ # Mevcut soru
117
+ prompt += f"Kullanıcı: {query}\nAsistan:"
118
+
119
+ return prompt
120
+
121
+ def _detect_conversation_type(self, query: str) -> str:
122
+ """Konuşma türünü tespit eder"""
123
+ query_lower = query.lower()
124
+
125
+ # Selamlama
126
+ if any(word in query_lower for word in ["merhaba", "selam", "günaydın"]):
127
+ return "greeting"
128
+
129
+ # Soru
130
+ if "?" in query or any(word in query_lower for word in ["nedir", "nasıl", "neden"]):
131
+ return "question"
132
+
133
+ # Duygusal
134
+ if any(word in query_lower for word in ["üzgün", "mutlu", "kızgın", "heyecanlı"]):
135
+ return "emotional"
136
+
137
+ # Bilgi arama
138
+ if any(word in query_lower for word in ["açıkla", "anlat", "öğren", "bilgi"]):
139
+ return "information"
140
+
141
+ # Varsayılan
142
+ return "general"
modules/code_module.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Kod Yazım Modülü
3
+ """
4
+
5
+ import re
6
+ from typing import Dict, Any
7
+ from core.base_module import BaseMicroModule
8
+ import logging
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class CodeModule(BaseMicroModule):
13
+ """Kod yazımı için özelleşmiş modül"""
14
+
15
+ def __init__(self, config: Dict[str, Any]):
16
+ super().__init__(
17
+ model_id="deepseek-ai/deepseek-coder-1.3b-instruct",
18
+ config=config
19
+ )
20
+
21
+ # Kod kelime anahtar kelimeleri
22
+ self.code_keywords = {
23
+ "function", "class", "def", "import", "from", "return",
24
+ "if", "else", "for", "while", "try", "except", "with",
25
+ "python", "javascript", "java", "c++", "html", "css",
26
+ "kod", "kodu", "script", "fonksiyon", "sınıf", "algoritma",
27
+ "program", "yazılım", "debug", "hata", "fix", "düzelt"
28
+ }
29
+
30
+ # Programlama dilleri
31
+ self.programming_languages = {
32
+ "python", "javascript", "java", "c++", "c#", "php", "ruby",
33
+ "go", "rust", "kotlin", "swift", "typescript", "html", "css",
34
+ "sql", "bash", "powershell", "r", "matlab", "scala"
35
+ }
36
+
37
+ def can_handle(self, query: str, context: Dict[str, Any]) -> float:
38
+ """Kod yazımı sorguları için uygunluk skoru"""
39
+ query_lower = query.lower()
40
+
41
+ # Kod anahtar kelimelerini kontrol et
42
+ code_score = 0
43
+ for keyword in self.code_keywords:
44
+ if keyword in query_lower:
45
+ code_score += 0.15
46
+
47
+ # Programlama dili belirtilmişse
48
+ for lang in self.programming_languages:
49
+ if lang in query_lower:
50
+ code_score += 0.3
51
+
52
+ # Kod yazımı action kelimeleri
53
+ action_keywords = ["yaz", "oluştur", "geliştir", "kur", "hazırla", "tasarla"]
54
+ for action in action_keywords:
55
+ if action in query_lower:
56
+ code_score += 0.2
57
+
58
+ # Kod karakteristik işaretlerini kontrol et
59
+ if any(char in query for char in ["()", "{}", "[]", "==", "!=", "<=", ">="]):
60
+ code_score += 0.15
61
+
62
+ # Kod blokları varsa
63
+ if "```" in query or "def " in query or "class " in query:
64
+ code_score += 0.3
65
+
66
+ # Spesifik kod türleri
67
+ code_types = ["hesap", "makinesi", "calculator", "app", "uygulama", "website", "site"]
68
+ for code_type in code_types:
69
+ if code_type in query_lower:
70
+ code_score += 0.25
71
+
72
+ # Maksimum 1.0 skor
73
+ return min(code_score, 1.0)
74
+
75
+ async def process(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
76
+ """Kod yazımı işlemi"""
77
+ try:
78
+ # Kod yazımı için özel prompt
79
+ prompt = self._build_code_prompt(query, context)
80
+
81
+ # Kod üretimi
82
+ response = await self.generate_response(
83
+ prompt,
84
+ max_tokens=self.config.get("max_tokens", 2048),
85
+ temperature=0.1 # Kod için düşük temperature
86
+ )
87
+
88
+ # Kod bloklarını ayıkla
89
+ code_blocks = self._extract_code_blocks(response)
90
+
91
+ return {
92
+ "response": response,
93
+ "code_blocks": code_blocks,
94
+ "language": self._detect_language(query),
95
+ "module": "code_module",
96
+ "confidence": self.can_handle(query, context)
97
+ }
98
+
99
+ except Exception as e:
100
+ logger.error(f"Code processing error: {str(e)}")
101
+ return {
102
+ "error": str(e),
103
+ "module": "code_module"
104
+ }
105
+
106
+ def _build_code_prompt(self, query: str, context: Dict[str, Any]) -> str:
107
+ """Kod yazımı için prompt hazırlar"""
108
+
109
+ # Dil tespiti
110
+ language = self._detect_language(query)
111
+
112
+ # Temel prompt
113
+ prompt = f"""Sen bir uzman programcısın. Kullanıcının sorusunu anla ve en iyi kodu yaz.
114
+
115
+ Kullanıcı sorusu: {query}
116
+
117
+ Lütfen:
118
+ 1. Temiz, okunabilir kod yaz
119
+ 2. Kod açıklamalarını Türkçe yap
120
+ 3. En iyi pratikleri kullan
121
+ 4. Gerekirse örnek kullanımı göster
122
+
123
+ """
124
+
125
+ # Dil özelinde ekleme
126
+ if language:
127
+ prompt += f"Programlama dili: {language}\n"
128
+
129
+ # Bağlam varsa ekle
130
+ if context.get("history"):
131
+ prompt += f"Önceki konuşma: {context['history'][-1]}\n"
132
+
133
+ return prompt
134
+
135
+ def _detect_language(self, query: str) -> str:
136
+ """Sorgudan programlama dilini tespit eder"""
137
+ query_lower = query.lower()
138
+
139
+ for lang in self.programming_languages:
140
+ if lang in query_lower:
141
+ return lang
142
+
143
+ # Varsayılan dil
144
+ return "python"
145
+
146
+ def _extract_code_blocks(self, response: str) -> list:
147
+ """Yanıttan kod bloklarını ayıklar"""
148
+ code_blocks = []
149
+
150
+ # Markdown kod blokları
151
+ pattern = r'```(\w+)?\n(.*?)\n```'
152
+ matches = re.findall(pattern, response, re.DOTALL)
153
+
154
+ for match in matches:
155
+ lang, code = match
156
+ code_blocks.append({
157
+ "language": lang or "text",
158
+ "code": code.strip()
159
+ })
160
+
161
+ # Tek satır kod blokları
162
+ inline_pattern = r'`([^`]+)`'
163
+ inline_matches = re.findall(inline_pattern, response)
164
+
165
+ for code in inline_matches:
166
+ if len(code) > 5: # Çok kısa olanları atla
167
+ code_blocks.append({
168
+ "language": "inline",
169
+ "code": code.strip()
170
+ })
171
+
172
+ return code_blocks
modules/fast_module.py ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Fast Response Modülü
3
+ """
4
+
5
+ from typing import Dict, Any
6
+ from core.base_module import BaseMicroModule
7
+ import logging
8
+ import asyncio
9
+
10
+ # Weather tool import
11
+ try:
12
+ from tools.weather_tool import WeatherTool
13
+ WEATHER_TOOL_AVAILABLE = True
14
+ except ImportError:
15
+ WEATHER_TOOL_AVAILABLE = False
16
+ WeatherTool = None
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ class FastModule(BaseMicroModule):
21
+ """Hızlı yanıt için özelleşmiş modül"""
22
+
23
+ def __init__(self, config: Dict[str, Any]):
24
+ super().__init__(
25
+ model_id="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
26
+ config=config
27
+ )
28
+
29
+ # Weather tool initialize
30
+ if WEATHER_TOOL_AVAILABLE:
31
+ self.weather_tool = WeatherTool()
32
+ else:
33
+ self.weather_tool = None
34
+
35
+ # Hızlı yanıt anahtar kelimeleri
36
+ self.quick_keywords = {
37
+ "hızlı", "kısa", "özet", "basit", "kolay",
38
+ "evet", "hayır", "doğru", "yanlış", "kim",
39
+ "ne", "nerede", "ne zaman", "kaç", "hangi",
40
+ "merhaba", "selam", "teşekkür", "tamam"
41
+ }
42
+
43
+ # Basit soru türleri
44
+ self.simple_patterns = {
45
+ "greeting": ["merhaba", "selam", "günaydın", "iyi akşam"],
46
+ "thanks": ["teşekkür", "sağol", "merci"],
47
+ "simple_question": ["kim", "ne", "nerede", "kaç"],
48
+ "yes_no": ["mı", "mi", "mu", "mü"],
49
+ "time": ["saat", "tarih", "zaman"],
50
+ "weather": ["hava", "sıcaklık", "yağmur"]
51
+ }
52
+
53
+ # Hazır yanıtlar
54
+ self.quick_responses = {
55
+ "greeting": [
56
+ "Merhaba! Size nasıl yardımcı olabilirim?",
57
+ "Selam! Bugün nasılsınız?",
58
+ "Günaydın! Ne yapmak istiyorsunuz?"
59
+ ],
60
+ "thanks": [
61
+ "Rica ederim! Başka bir konuda yardımcı olabilir miyim?",
62
+ "Bir şey değil! Başka sorunuz var mı?",
63
+ "Memnun oldum! Size daha nasıl yardımcı olabilirim?"
64
+ ],
65
+ "unknown": [
66
+ "Bu konuda daha detaylı bilgi verebilir miyim?",
67
+ "Sorunuzu biraz daha açabilir misiniz?",
68
+ "Bu konuda size yardımcı olmak istiyorum."
69
+ ]
70
+ }
71
+
72
+ def can_handle(self, query: str, context: Dict[str, Any]) -> float:
73
+ """Hızlı yanıt sorguları için uygunluk skoru"""
74
+ query_lower = query.lower()
75
+
76
+ # Kod anahtar kelimelerini kontrol et (negatif skor)
77
+ code_keywords = {
78
+ "function", "class", "def", "import", "from", "return",
79
+ "if", "else", "for", "while", "try", "except", "with",
80
+ "python", "javascript", "java", "c++", "html", "css",
81
+ "kod", "kodu", "script", "fonksiyon", "sınıf", "algoritma",
82
+ "program", "yazılım", "debug", "hata", "fix", "düzelt",
83
+ "yaz", "oluştur", "geliştir", "hesap", "makinesi"
84
+ }
85
+
86
+ # Kod soruları için düşük skor
87
+ for keyword in code_keywords:
88
+ if keyword in query_lower:
89
+ return 0.1 # Çok düşük skor
90
+
91
+ # Hızlı yanıt anahtar kelimelerini kontrol et
92
+ quick_score = 0
93
+ for keyword in self.quick_keywords:
94
+ if keyword in query_lower:
95
+ quick_score += 0.15
96
+
97
+ # Basit soru pattern'larını kontrol et
98
+ for pattern_type, patterns in self.simple_patterns.items():
99
+ for pattern in patterns:
100
+ if pattern in query_lower:
101
+ quick_score += 0.2
102
+
103
+ # Kısa sorular için yüksek skor
104
+ word_count = len(query.split())
105
+ if word_count <= 5:
106
+ quick_score += 0.3
107
+ elif word_count <= 10:
108
+ quick_score += 0.2
109
+
110
+ # Selamlama ve teşekkür ifadeleri
111
+ if any(word in query_lower for word in ["merhaba", "selam", "teşekkür", "sağol"]):
112
+ quick_score += 0.4
113
+
114
+ # Evet/hayır soruları
115
+ if any(ending in query_lower for ending in ["mı?", "mi?", "mu?", "mü?"]):
116
+ quick_score += 0.25
117
+
118
+ # Hava durumu soruları için yüksek skor
119
+ if self.weather_tool and self.weather_tool.can_handle(query):
120
+ quick_score += 0.6
121
+
122
+ # Maksimum 1.0 skor
123
+ return min(quick_score, 1.0)
124
+
125
+ async def process(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
126
+ """Hızlı yanıt işlemi"""
127
+ try:
128
+ # Weather tool kontrolü
129
+ if self.weather_tool and self.weather_tool.can_handle(query):
130
+ weather_response = await self.weather_tool.process_weather_query(query)
131
+ return {
132
+ "response": weather_response,
133
+ "module": "fast_module",
134
+ "confidence": self.can_handle(query, context),
135
+ "response_type": "weather_tool",
136
+ "cached": False,
137
+ "tool_used": "weather_api"
138
+ }
139
+
140
+ # Önce hazır yanıt kontrolü
141
+ quick_response = self._check_quick_response(query)
142
+ if quick_response:
143
+ return {
144
+ "response": quick_response,
145
+ "module": "fast_module",
146
+ "confidence": self.can_handle(query, context),
147
+ "response_type": "quick",
148
+ "cached": True
149
+ }
150
+
151
+ # Hızlı yanıt için özel prompt
152
+ prompt = self._build_fast_prompt(query, context)
153
+
154
+ # Yanıt üretimi (düşük token limit)
155
+ response = await self.generate_response(
156
+ prompt,
157
+ max_tokens=min(self.config.get("max_tokens", 512), 256), # Maksimum 256 token
158
+ temperature=0.8 # Hızlı yanıt için yüksek temperature
159
+ )
160
+
161
+ return {
162
+ "response": response,
163
+ "module": "fast_module",
164
+ "confidence": self.can_handle(query, context),
165
+ "response_type": "generated",
166
+ "cached": False
167
+ }
168
+
169
+ except Exception as e:
170
+ logger.error(f"Fast processing error: {str(e)}")
171
+ return {
172
+ "error": str(e),
173
+ "module": "fast_module"
174
+ }
175
+
176
+ def _check_quick_response(self, query: str) -> str:
177
+ """Hazır yanıtları kontrol eder"""
178
+ query_lower = query.lower()
179
+
180
+ # Selamlama kontrolü
181
+ if any(word in query_lower for word in self.simple_patterns["greeting"]):
182
+ import random
183
+ return random.choice(self.quick_responses["greeting"])
184
+
185
+ # Teşekkür kontrolü
186
+ if any(word in query_lower for word in self.simple_patterns["thanks"]):
187
+ import random
188
+ return random.choice(self.quick_responses["thanks"])
189
+
190
+ # Basit evet/hayır soruları
191
+ if len(query.split()) <= 3:
192
+ if any(ending in query_lower for ending in ["mı?", "mi?", "mu?", "mü?"]):
193
+ return "Bu konuda kesin bir yanıt verebilmek için biraz daha detay gerekiyor."
194
+
195
+ return None
196
+
197
+ def _build_fast_prompt(self, query: str, context: Dict[str, Any]) -> str:
198
+ """Hızlı yanıt için prompt hazırlar"""
199
+
200
+ # Sorgu türünü belirle
201
+ query_type = self._detect_query_type(query)
202
+
203
+ # Temel prompt
204
+ prompt = f"""Sen hızlı ve özlü yanıtlar veren bir asistansın. Kısa ve net cevaplar veriyorsun.
205
+
206
+ Kullanıcı sorusu: {query}
207
+
208
+ Lütfen:
209
+ 1. Kısa ve net yanıt ver
210
+ 2. Gereksiz detaylara girme
211
+ 3. Doğrudan soruyu yanıtla
212
+ 4. Maksimum 2-3 cümle kullan
213
+
214
+ Soru türü: {query_type}
215
+ """
216
+
217
+ # Bağlam varsa kısaca ekle
218
+ if context.get("history"):
219
+ last_msg = context["history"][-1]
220
+ if len(last_msg) < 100: # Sadece kısa geçmişi ekle
221
+ prompt += f"\nÖnceki: {last_msg}\n"
222
+
223
+ return prompt
224
+
225
+ def _detect_query_type(self, query: str) -> str:
226
+ """Sorgu türünü tespit eder"""
227
+ query_lower = query.lower()
228
+
229
+ # Selamlama
230
+ if any(word in query_lower for word in self.simple_patterns["greeting"]):
231
+ return "greeting"
232
+
233
+ # Teşekkür
234
+ if any(word in query_lower for word in self.simple_patterns["thanks"]):
235
+ return "thanks"
236
+
237
+ # Basit soru
238
+ if any(word in query_lower for word in self.simple_patterns["simple_question"]):
239
+ return "simple_question"
240
+
241
+ # Evet/hayır
242
+ if any(ending in query_lower for ending in ["mı?", "mi?", "mu?", "mü?"]):
243
+ return "yes_no"
244
+
245
+ # Zaman
246
+ if any(word in query_lower for word in self.simple_patterns["time"]):
247
+ return "time"
248
+
249
+ # Hava
250
+ if any(word in query_lower for word in self.simple_patterns["weather"]):
251
+ return "weather"
252
+
253
+ # Kısa soru
254
+ if len(query.split()) <= 5:
255
+ return "short_question"
256
+
257
+ # Varsayılan
258
+ return "general"
modules/reason_module.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Reasoning Modülü
3
+ """
4
+
5
+ from typing import Dict, Any
6
+ from core.base_module import BaseMicroModule
7
+ import logging
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class ReasonModule(BaseMicroModule):
12
+ """Mantık yürütme için özelleşmiş modül"""
13
+
14
+ def __init__(self, config: Dict[str, Any]):
15
+ super().__init__(
16
+ model_id="microsoft/Phi-3-mini-4k-instruct",
17
+ config=config
18
+ )
19
+
20
+ # Mantık yürütme anahtar kelimeleri
21
+ self.reasoning_keywords = {
22
+ "çünkü", "neden", "sebep", "niye", "nasıl", "analiz",
23
+ "karşılaştır", "değerlendir", "açıkla", "kanıtla",
24
+ "sonuç", "çıkarım", "mantık", "düşünce", "fikir",
25
+ "strateji", "plan", "çözüm", "problem", "sorun",
26
+ "avantaj", "dezavantaj", "fark", "benzerlik"
27
+ }
28
+
29
+ # Analiz türleri
30
+ self.analysis_types = {
31
+ "problem_solving", "comparison", "evaluation",
32
+ "cause_effect", "strategy", "pros_cons"
33
+ }
34
+
35
+ def can_handle(self, query: str, context: Dict[str, Any]) -> float:
36
+ """Mantık yürütme sorguları için uygunluk skoru"""
37
+ query_lower = query.lower()
38
+
39
+ # Mantık yürütme anahtar kelimelerini kontrol et
40
+ reasoning_score = 0
41
+ for keyword in self.reasoning_keywords:
42
+ if keyword in query_lower:
43
+ reasoning_score += 0.12
44
+
45
+ # Soru türlerini kontrol et
46
+ if "neden" in query_lower or "çünkü" in query_lower:
47
+ reasoning_score += 0.25
48
+
49
+ # Karşılaştırma ifadeleri
50
+ if any(word in query_lower for word in ["karşılaştır", "fark", "benzer", "hangisi"]):
51
+ reasoning_score += 0.2
52
+
53
+ # Analiz gerektiren ifadeler
54
+ if any(word in query_lower for word in ["analiz", "değerlendir", "incele", "araştır"]):
55
+ reasoning_score += 0.2
56
+
57
+ # Problem çözme ifadeleri
58
+ if any(word in query_lower for word in ["problem", "sorun", "çözüm", "nasıl"]):
59
+ reasoning_score += 0.15
60
+
61
+ # Uzun ve karmaşık sorular
62
+ if len(query.split()) > 15:
63
+ reasoning_score += 0.1
64
+
65
+ # Maksimum 1.0 skor
66
+ return min(reasoning_score, 1.0)
67
+
68
+ async def process(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
69
+ """Mantık yürütme işlemi"""
70
+ try:
71
+ # Analiz türünü belirle
72
+ analysis_type = self._detect_analysis_type(query)
73
+
74
+ # Mantık yürütme için özel prompt
75
+ prompt = self._build_reasoning_prompt(query, context, analysis_type)
76
+
77
+ # Yanıt üretimi
78
+ response = await self.generate_response(
79
+ prompt,
80
+ max_tokens=self.config.get("max_tokens", 1024),
81
+ temperature=0.3 # Mantık yürütme için düşük temperature
82
+ )
83
+
84
+ return {
85
+ "response": response,
86
+ "module": "reason_module",
87
+ "confidence": self.can_handle(query, context),
88
+ "analysis_type": analysis_type,
89
+ "reasoning_steps": self._extract_reasoning_steps(response)
90
+ }
91
+
92
+ except Exception as e:
93
+ logger.error(f"Reasoning processing error: {str(e)}")
94
+ return {
95
+ "error": str(e),
96
+ "module": "reason_module"
97
+ }
98
+
99
+ def _build_reasoning_prompt(self, query: str, context: Dict[str, Any], analysis_type: str) -> str:
100
+ """Mantık yürütme için prompt hazırlar"""
101
+
102
+ # Analiz türüne göre özel prompt
103
+ if analysis_type == "problem_solving":
104
+ system_prompt = """Sen bir problem çözme uzmanısın. Sorunları adım adım analiz edip mantıklı çözümler üretiyorsun."""
105
+ elif analysis_type == "comparison":
106
+ system_prompt = """Sen bir karşılaştırma uzmanısın. Farklı seçenekleri objektif bir şekilde karşılaştırıyorsun."""
107
+ elif analysis_type == "evaluation":
108
+ system_prompt = """Sen bir değerlendirme uzmanısın. Durumları kapsamlı bir şekilde analiz ediyorsun."""
109
+ elif analysis_type == "cause_effect":
110
+ system_prompt = """Sen bir sebep-sonuç analizi uzmanısın. Olaylar arasındaki ilişkileri açıklıyorsun."""
111
+ else:
112
+ system_prompt = """Sen bir mantık yürütme uzmanısın. Karmaşık konuları açık ve anlaşılır şekilde analiz ediyorsun."""
113
+
114
+ # Temel prompt
115
+ prompt = f"""{system_prompt}
116
+
117
+ Kullanıcı sorusu: {query}
118
+
119
+ Lütfen:
120
+ 1. Konuyu kapsamlı analiz et
121
+ 2. Mantık zincirini açıkla
122
+ 3. Somut örnekler ver
123
+ 4. Sonuçları net bir şekilde özetle
124
+
125
+ Analiz türü: {analysis_type}
126
+ """
127
+
128
+ # Bağlam varsa ekle
129
+ if context.get("history"):
130
+ prompt += f"\nÖnceki konuşma: {context['history'][-1]}\n"
131
+
132
+ return prompt
133
+
134
+ def _detect_analysis_type(self, query: str) -> str:
135
+ """Sorgudan analiz türünü tespit eder"""
136
+ query_lower = query.lower()
137
+
138
+ # Problem çözme
139
+ if any(word in query_lower for word in ["problem", "sorun", "çöz", "nasıl"]):
140
+ return "problem_solving"
141
+
142
+ # Karşılaştırma
143
+ if any(word in query_lower for word in ["karşılaştır", "fark", "hangisi", "seç"]):
144
+ return "comparison"
145
+
146
+ # Değerlendirme
147
+ if any(word in query_lower for word in ["değerlendir", "incele", "analiz"]):
148
+ return "evaluation"
149
+
150
+ # Sebep-sonuç
151
+ if any(word in query_lower for word in ["neden", "çünkü", "sebep", "sonuç"]):
152
+ return "cause_effect"
153
+
154
+ # Strateji
155
+ if any(word in query_lower for word in ["strateji", "plan", "yaklaşım"]):
156
+ return "strategy"
157
+
158
+ # Avantaj-dezavantaj
159
+ if any(word in query_lower for word in ["avantaj", "dezavantaj", "artı", "eksi"]):
160
+ return "pros_cons"
161
+
162
+ # Varsayılan
163
+ return "general_reasoning"
164
+
165
+ def _extract_reasoning_steps(self, response: str) -> list:
166
+ """Yanıttan mantık yürütme adımlarını çıkarır"""
167
+ steps = []
168
+
169
+ # Numaralı adımları bul
170
+ import re
171
+ numbered_steps = re.findall(r'(\d+[\.\)])\s*([^\n]+)', response)
172
+
173
+ for num, step in numbered_steps:
174
+ steps.append({
175
+ "step": num,
176
+ "description": step.strip()
177
+ })
178
+
179
+ # Anahtar kelimelerle adımları bul
180
+ key_phrases = [
181
+ "ilk olarak", "öncelikle", "birincisi",
182
+ "ikincisi", "üçüncüsü", "son olarak",
183
+ "sonuç olarak", "özetle", "bu nedenle"
184
+ ]
185
+
186
+ sentences = response.split('.')
187
+ for sentence in sentences:
188
+ sentence = sentence.strip()
189
+ if any(phrase in sentence.lower() for phrase in key_phrases):
190
+ if len(sentence) > 10: # Çok kısa olanları atla
191
+ steps.append({
192
+ "step": "auto",
193
+ "description": sentence
194
+ })
195
+
196
+ return steps[:10] # Maksimum 10 adım
requirements.txt CHANGED
@@ -1,10 +1,18 @@
1
  torch>=2.0.0
2
- gradio==4.26.0
3
- transformers>=4.30.0
4
- accelerate>=0.20.0
5
- bitsandbytes>=0.41.0
6
  spaces>=0.19.0
 
 
7
  numpy>=1.24.0
8
- sentencepiece>=0.1.99
9
- protobuf>=3.20.0
10
- safetensors>=0.3.0
 
 
 
 
 
 
 
1
  torch>=2.0.0
2
+ transformers==4.41.0
3
+ accelerate>=0.28.0
4
+ tokenizers>=0.19.0
5
+ gradio==4.29.0
6
  spaces>=0.19.0
7
+ requests>=2.31.0
8
+ aiohttp>=3.9.0
9
  numpy>=1.24.0
10
+ psutil>=5.9.0
11
+ huggingface_hub>=0.20.0
12
+ safetensors>=0.4.0
13
+ peft==0.10.0
14
+ bitsandbytes==0.43.0
15
+ pydantic>=2.6.0
16
+ python-multipart>=0.0.9
17
+ aiofiles>=23.2.0
18
+ jinja2>=3.1.3
router/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Router Package
3
+ """
4
+
5
+ from .intelligent_router import IntelligentRouter
6
+
7
+ __all__ = ['IntelligentRouter']
router/intelligent_router.py ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Intelligent Router Layer
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional
6
+ import asyncio
7
+ import logging
8
+ from dataclasses import dataclass
9
+ from datetime import datetime
10
+ import json
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ @dataclass
15
+ class RoutingDecision:
16
+ """Routing kararı için veri sınıfı"""
17
+ module_name: str
18
+ confidence: float
19
+ priority: int
20
+ reasoning: str
21
+ estimated_time: float
22
+
23
+ class IntelligentRouter:
24
+ """Sorguları en uygun modüllere yönlendiren router"""
25
+
26
+ def __init__(self, modules: Dict[str, Any], config: Dict[str, Any]):
27
+ self.modules = modules
28
+ self.config = config
29
+ self.routing_history = []
30
+ self.performance_stats = {}
31
+
32
+ # Routing parametreleri
33
+ self.confidence_threshold = config.get("confidence_threshold", 0.7)
34
+ self.max_concurrent = config.get("max_concurrent_requests", 4)
35
+ self.timeout = config.get("timeout", 30)
36
+ self.fallback_module = config.get("fallback_module", "fast_module")
37
+
38
+ # Performans takibi
39
+ self.total_requests = 0
40
+ self.successful_routings = 0
41
+ self.failed_routings = 0
42
+
43
+ async def route_query(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
44
+ """Ana routing fonksiyonu"""
45
+ try:
46
+ start_time = datetime.now()
47
+
48
+ # Routing kararı al
49
+ routing_decisions = await self._analyze_query(query, context)
50
+
51
+ # En iyi modülü seç
52
+ best_module = self._select_best_module(routing_decisions)
53
+
54
+ if not best_module:
55
+ # Fallback modülü kullan
56
+ best_module = RoutingDecision(
57
+ module_name=self.fallback_module,
58
+ confidence=0.5,
59
+ priority=999,
60
+ reasoning="Fallback module used",
61
+ estimated_time=2.0
62
+ )
63
+
64
+ # Modülü çalıştır
65
+ result = await self._execute_module(
66
+ best_module.module_name,
67
+ query,
68
+ context
69
+ )
70
+
71
+ # Performans güncelle
72
+ execution_time = (datetime.now() - start_time).total_seconds()
73
+ self._update_performance_stats(
74
+ best_module.module_name,
75
+ execution_time,
76
+ True
77
+ )
78
+
79
+ # Routing geçmişini güncelle
80
+ self._update_routing_history(query, best_module, result, execution_time)
81
+
82
+ # Sonuç ekle
83
+ result["routing_info"] = {
84
+ "selected_module": best_module.module_name,
85
+ "confidence": best_module.confidence,
86
+ "reasoning": best_module.reasoning,
87
+ "execution_time": execution_time,
88
+ "all_candidates": [
89
+ {
90
+ "module": decision.module_name,
91
+ "confidence": decision.confidence,
92
+ "priority": decision.priority
93
+ }
94
+ for decision in routing_decisions
95
+ ]
96
+ }
97
+
98
+ return result
99
+
100
+ except Exception as e:
101
+ logger.error(f"Routing error: {str(e)}")
102
+ self.failed_routings += 1
103
+
104
+ # Hata durumunda fallback
105
+ return await self._execute_fallback(query, context, str(e))
106
+
107
+ async def _analyze_query(self, query: str, context: Dict[str, Any]) -> List[RoutingDecision]:
108
+ """Sorguyu analiz eder ve tüm modüllerin skorlarını hesaplar"""
109
+ decisions = []
110
+
111
+ # Tüm modülleri paralel olarak test et
112
+ tasks = []
113
+ for module_name, module in self.modules.items():
114
+ if hasattr(module, 'can_handle'):
115
+ task = asyncio.create_task(
116
+ self._evaluate_module(module_name, module, query, context)
117
+ )
118
+ tasks.append(task)
119
+
120
+ # Sonuçları topla
121
+ results = await asyncio.gather(*tasks, return_exceptions=True)
122
+
123
+ for result in results:
124
+ if isinstance(result, RoutingDecision):
125
+ decisions.append(result)
126
+ elif isinstance(result, Exception):
127
+ logger.warning(f"Module evaluation error: {str(result)}")
128
+
129
+ # Confidence'a göre sırala
130
+ decisions.sort(key=lambda x: x.confidence, reverse=True)
131
+
132
+ return decisions
133
+
134
+ async def _evaluate_module(self, module_name: str, module: Any, query: str, context: Dict[str, Any]) -> RoutingDecision:
135
+ """Tek bir modülü değerlendirir"""
136
+ try:
137
+ # Can_handle skorunu al
138
+ confidence = module.can_handle(query, context)
139
+
140
+ # Modül performansını kontrol et
141
+ performance = self.performance_stats.get(module_name, {})
142
+ avg_time = performance.get("avg_execution_time", 2.0)
143
+ success_rate = performance.get("success_rate", 0.8)
144
+
145
+ # Confidence'ı performansa göre ayarla
146
+ adjusted_confidence = confidence * success_rate
147
+
148
+ # Priority'yi config'den al
149
+ priority = module.config.get("priority", 1)
150
+
151
+ # Reasoning oluştur
152
+ reasoning = self._generate_reasoning(
153
+ module_name, confidence, performance, query
154
+ )
155
+
156
+ return RoutingDecision(
157
+ module_name=module_name,
158
+ confidence=adjusted_confidence,
159
+ priority=priority,
160
+ reasoning=reasoning,
161
+ estimated_time=avg_time
162
+ )
163
+
164
+ except Exception as e:
165
+ logger.error(f"Error evaluating module {module_name}: {str(e)}")
166
+ return RoutingDecision(
167
+ module_name=module_name,
168
+ confidence=0.0,
169
+ priority=999,
170
+ reasoning=f"Evaluation error: {str(e)}",
171
+ estimated_time=10.0
172
+ )
173
+
174
+ def _select_best_module(self, decisions: List[RoutingDecision]) -> Optional[RoutingDecision]:
175
+ """En iyi modülü seçer"""
176
+ if not decisions:
177
+ return None
178
+
179
+ # Confidence threshold'u geçenleri filtrele
180
+ qualified = [d for d in decisions if d.confidence >= self.confidence_threshold]
181
+
182
+ if not qualified:
183
+ # Eğer hiçbiri threshold'u geçmiyorsa en yüksek skorluyu al
184
+ qualified = [decisions[0]]
185
+
186
+ # Priority ve confidence'a göre sırala
187
+ qualified.sort(key=lambda x: (x.priority, -x.confidence))
188
+
189
+ return qualified[0]
190
+
191
+ async def _execute_module(self, module_name: str, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
192
+ """Seçilen modülü çalıştırır"""
193
+ try:
194
+ module = self.modules.get(module_name)
195
+ if not module:
196
+ raise Exception(f"Module {module_name} not found")
197
+
198
+ # Timeout ile çalıştır
199
+ result = await asyncio.wait_for(
200
+ module.process(query, context),
201
+ timeout=self.timeout
202
+ )
203
+
204
+ self.successful_routings += 1
205
+ return result
206
+
207
+ except asyncio.TimeoutError:
208
+ logger.error(f"Module {module_name} timed out")
209
+ raise Exception(f"Module {module_name} execution timeout")
210
+ except Exception as e:
211
+ logger.error(f"Module {module_name} execution error: {str(e)}")
212
+ raise
213
+
214
+ async def _execute_fallback(self, query: str, context: Dict[str, Any], error: str) -> Dict[str, Any]:
215
+ """Fallback modülü çalıştırır"""
216
+ try:
217
+ fallback_module = self.modules.get(self.fallback_module)
218
+ if fallback_module:
219
+ result = await fallback_module.process(query, context)
220
+ result["fallback_used"] = True
221
+ result["original_error"] = error
222
+ return result
223
+ else:
224
+ return {
225
+ "error": f"Routing failed and no fallback available: {error}",
226
+ "fallback_used": True
227
+ }
228
+ except Exception as e:
229
+ return {
230
+ "error": f"Both routing and fallback failed: {error}, {str(e)}",
231
+ "fallback_used": True
232
+ }
233
+
234
+ def _update_performance_stats(self, module_name: str, execution_time: float, success: bool):
235
+ """Performans istatistiklerini günceller"""
236
+ if module_name not in self.performance_stats:
237
+ self.performance_stats[module_name] = {
238
+ "total_requests": 0,
239
+ "successful_requests": 0,
240
+ "total_time": 0,
241
+ "avg_execution_time": 0,
242
+ "success_rate": 0
243
+ }
244
+
245
+ stats = self.performance_stats[module_name]
246
+ stats["total_requests"] += 1
247
+ stats["total_time"] += execution_time
248
+
249
+ if success:
250
+ stats["successful_requests"] += 1
251
+
252
+ # Ortalama süre & başarı oranı
253
+ stats["avg_execution_time"] = stats["total_time"] / max(stats["total_requests"], 1)
254
+ stats["success_rate"] = stats["successful_requests"] / max(stats["total_requests"], 1)
255
+
256
+ self.total_requests += 1
257
+
258
+ def _update_routing_history(self, query: str, decision: RoutingDecision, result: Dict[str, Any], execution_time: float):
259
+ """Routing geçmişini günceller"""
260
+ entry = {
261
+ "timestamp": datetime.now().isoformat(),
262
+ "query": query[:100], # İlk 100 karakter
263
+ "selected_module": decision.module_name,
264
+ "confidence": decision.confidence,
265
+ "execution_time": execution_time,
266
+ "success": "error" not in result
267
+ }
268
+
269
+ self.routing_history.append(entry)
270
+
271
+ # Geçmişi sınırla (son 1000 entry)
272
+ if len(self.routing_history) > 1000:
273
+ self.routing_history = self.routing_history[-1000:]
274
+
275
+ def _generate_reasoning(self, module_name: str, confidence: float, performance: Dict[str, Any], query: str) -> str:
276
+ """Routing kararı için açıklama oluşturur"""
277
+ reasons = []
278
+
279
+ if confidence > 0.8:
280
+ reasons.append(f"Yüksek confidence skoru ({confidence:.2f})")
281
+ elif confidence > 0.6:
282
+ reasons.append(f"Orta confidence skoru ({confidence:.2f})")
283
+ else:
284
+ reasons.append(f"Düşük confidence skoru ({confidence:.2f})")
285
+
286
+ if performance:
287
+ success_rate = performance.get("success_rate", 0)
288
+ if success_rate > 0.9:
289
+ reasons.append("Yüksek başarı oranı")
290
+ elif success_rate > 0.7:
291
+ reasons.append("Orta başarı oranı")
292
+ else:
293
+ reasons.append("Düşük başarı oranı")
294
+
295
+ return ", ".join(reasons)
296
+
297
+ def get_stats(self) -> Dict[str, Any]:
298
+ """Router istatistiklerini döndürür"""
299
+ return {
300
+ "total_requests": self.total_requests,
301
+ "successful_routings": self.successful_routings,
302
+ "failed_routings": self.failed_routings,
303
+ "success_rate": self.successful_routings / max(self.total_requests, 1),
304
+ "module_performance": self.performance_stats,
305
+ "recent_history": self.routing_history[-10:] # Son 10 routing
306
+ }
setup.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Kurulum Scripti
3
+ """
4
+
5
+ import asyncio
6
+ import logging
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ # Logging ayarları
12
+ logging.basicConfig(
13
+ level=logging.INFO,
14
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
15
+ )
16
+ logger = logging.getLogger(__name__)
17
+
18
+ class CRANESetup:
19
+ """CRANE AI kurulum sınıfı"""
20
+
21
+ def __init__(self):
22
+ self.project_root = Path(__file__).parent
23
+ self.required_dirs = [
24
+ "logs",
25
+ "models",
26
+ "cache",
27
+ "data",
28
+ "exports"
29
+ ]
30
+
31
+ async def setup_system(self):
32
+ """Sistemi kurar"""
33
+ try:
34
+ logger.info("🏗️ CRANE AI Kurulumu Başlatılıyor...")
35
+
36
+ # Dizinleri oluştur
37
+ await self._create_directories()
38
+
39
+ # Paketleri kontrol et
40
+ await self._check_packages()
41
+
42
+ # Hugging Face token'ını kontrol et
43
+ await self._check_hf_token()
44
+
45
+ # Modelleri hazırla
46
+ await self._prepare_models()
47
+
48
+ # Test çalıştır
49
+ await self._run_tests()
50
+
51
+ logger.info("✅ CRANE AI Kurulumu Başarıyla Tamamlandı!")
52
+ logger.info("🚀 Sistemi başlatmak için: python main.py")
53
+
54
+ except Exception as e:
55
+ logger.error(f"❌ Kurulum hatası: {str(e)}")
56
+ sys.exit(1)
57
+
58
+ async def _create_directories(self):
59
+ """Gerekli dizinleri oluşturur"""
60
+ logger.info("📁 Dizinler oluşturuluyor...")
61
+
62
+ for dir_name in self.required_dirs:
63
+ dir_path = self.project_root / dir_name
64
+ dir_path.mkdir(exist_ok=True)
65
+ logger.info(f" ✅ {dir_name}/ oluşturuldu")
66
+
67
+ # __init__.py dosyalarını oluştur
68
+ init_files = [
69
+ "core/__init__.py",
70
+ "router/__init__.py",
71
+ "memory/__init__.py",
72
+ "config/__init__.py"
73
+ ]
74
+
75
+ for init_file in init_files:
76
+ init_path = self.project_root / init_file
77
+ init_path.parent.mkdir(exist_ok=True)
78
+ if not init_path.exists():
79
+ init_path.write_text('"""Package initialization"""')
80
+ logger.info(f" ✅ {init_file} oluşturuldu")
81
+
82
+ async def _check_packages(self):
83
+ """Gerekli paketleri kontrol eder"""
84
+ logger.info("📦 Paketler kontrol ediliyor...")
85
+
86
+ required_packages = [
87
+ "torch",
88
+ "transformers",
89
+ "fastapi",
90
+ "uvicorn",
91
+ "gradio",
92
+ "numpy",
93
+ "requests",
94
+ "psutil"
95
+ ]
96
+
97
+ missing_packages = []
98
+
99
+ for package in required_packages:
100
+ try:
101
+ __import__(package)
102
+ logger.info(f" ✅ {package} mevcut")
103
+ except ImportError:
104
+ missing_packages.append(package)
105
+ logger.warning(f" ❌ {package} eksik")
106
+
107
+ if missing_packages:
108
+ logger.error(f"❌ Eksik paketler: {', '.join(missing_packages)}")
109
+ logger.info("💡 Çözüm: pip install -r requirements.txt")
110
+ raise Exception("Eksik paketler var")
111
+
112
+ async def _check_hf_token(self):
113
+ """Hugging Face token'ını kontrol eder"""
114
+ logger.info("🔑 Hugging Face token kontrol ediliyor...")
115
+
116
+ from config.settings import HF_TOKEN
117
+
118
+ if not HF_TOKEN or HF_TOKEN == "YOUR_TOKEN_HERE":
119
+ logger.error("❌ Hugging Face token bulunamadı")
120
+ logger.info("💡 config/settings.py dosyasında HF_TOKEN'ı ayarlayın")
121
+ raise Exception("Hugging Face token gerekli")
122
+
123
+ # Token'ın geçerli olup olmadığını kontrol et
124
+ try:
125
+ from huggingface_hub import HfApi
126
+ api = HfApi()
127
+ user_info = api.whoami(token=HF_TOKEN)
128
+ logger.info(f" ✅ Token geçerli: {user_info.get('name', 'Unknown')}")
129
+ except Exception as e:
130
+ logger.error(f"❌ Token geçersiz: {str(e)}")
131
+ raise Exception("Hugging Face token geçersiz")
132
+
133
+ async def _prepare_models(self):
134
+ """Modelleri hazırlar"""
135
+ logger.info("🤖 Modeller hazırlanıyor...")
136
+
137
+ from config.settings import MODELS, DEVICE
138
+
139
+ # Cihaz bilgisini göster
140
+ logger.info(f" 🖥️ Cihaz: {DEVICE}")
141
+
142
+ # Model bilgilerini göster
143
+ for model_name, model_config in MODELS.items():
144
+ model_id = model_config["model_id"]
145
+ logger.info(f" 📋 {model_name}: {model_id}")
146
+
147
+ # Model cache'ini kontrol et
148
+ cache_dir = self.project_root / "cache" / model_name
149
+ cache_dir.mkdir(exist_ok=True)
150
+
151
+ logger.info(" ✅ Modeller hazırlandı")
152
+
153
+ async def _run_tests(self):
154
+ """Basit testler çalıştırır"""
155
+ logger.info("🧪 Testler çalıştırılıyor...")
156
+
157
+ try:
158
+ # Router testi
159
+ from router.intelligent_router import IntelligentRouter
160
+ logger.info(" ✅ Router importu başarılı")
161
+
162
+ # Modül testleri
163
+ from modules import CodeModule, ChatModule, ReasonModule, FastModule
164
+ logger.info(" ✅ Modül importları başarılı")
165
+
166
+ # Memory testi
167
+ from memory.local_memory import LocalMemoryManager
168
+ logger.info(" ✅ Memory Manager importu başarılı")
169
+
170
+ # Token layer testi
171
+ from core.token_capsule import TokenCapsuleLayer
172
+ logger.info(" ✅ Token Capsule Layer importu başarılı")
173
+
174
+ logger.info(" ✅ Tüm testler başarılı")
175
+
176
+ except Exception as e:
177
+ logger.error(f"❌ Test hatası: {str(e)}")
178
+ raise Exception("Sistem testleri başarısız")
179
+
180
+ def main():
181
+ """Ana kurulum fonksiyonu"""
182
+ setup = CRANESetup()
183
+ asyncio.run(setup.setup_system())
184
+
185
+ if __name__ == "__main__":
186
+ main()
tools/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - External Tools Package
3
+ """
4
+
5
+ from .weather_tool import WeatherTool
6
+
7
+ __all__ = ['WeatherTool']
tools/weather_tool.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRANE AI - Weather Tool
3
+ Gerçek zamanlı hava durumu verisi için tool
4
+ """
5
+
6
+ import asyncio
7
+ import json
8
+ from typing import Dict, Any, Optional
9
+ import logging
10
+
11
+ try:
12
+ import aiohttp
13
+ AIOHTTP_AVAILABLE = True
14
+ except ImportError:
15
+ import requests
16
+ AIOHTTP_AVAILABLE = False
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ class WeatherTool:
21
+ """Hava durumu sorguları için external tool"""
22
+
23
+ def __init__(self):
24
+ # Ücretsiz OpenWeatherMap API kullanabiliriz
25
+ self.base_url = "http://api.openweathermap.org/data/2.5/weather"
26
+ self.api_key = None # API key gerekirse eklenebilir
27
+
28
+ # Alternatif olarak wttr.in kullanabiliriz (ücretsiz)
29
+ self.wttr_url = "http://wttr.in/{city}?format=j1"
30
+
31
+ def can_handle(self, query: str) -> bool:
32
+ """Bu tool'un handle edebileceği sorguları tespit eder"""
33
+ weather_keywords = [
34
+ "hava", "weather", "sıcaklık", "temperature", "yağmur", "rain",
35
+ "kar", "snow", "rüzgar", "wind", "nem", "humidity", "güneş", "sun",
36
+ "bulut", "cloud", "fırtına", "storm", "bugün", "today", "yarın", "tomorrow"
37
+ ]
38
+
39
+ query_lower = query.lower()
40
+ return any(keyword in query_lower for keyword in weather_keywords)
41
+
42
+ async def get_weather(self, city: str = "Istanbul") -> Dict[str, Any]:
43
+ """Belirtilen şehir için hava durumu bilgisi alır"""
44
+ try:
45
+ # wttr.in API kullan (ücretsiz ve API key gerektirmez)
46
+ url = f"http://wttr.in/{city}?format=j1"
47
+
48
+ if AIOHTTP_AVAILABLE:
49
+ # Async aiohttp kullan
50
+ async with aiohttp.ClientSession() as session:
51
+ async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as response:
52
+ if response.status == 200:
53
+ data = await response.json()
54
+ else:
55
+ return {
56
+ "error": f"API response error: {response.status}",
57
+ "status": "error"
58
+ }
59
+ else:
60
+ # Fallback to sync requests
61
+ import requests
62
+ response = requests.get(url, timeout=10)
63
+ if response.status_code == 200:
64
+ data = response.json()
65
+ else:
66
+ return {
67
+ "error": f"API response error: {response.status_code}",
68
+ "status": "error"
69
+ }
70
+
71
+ # Veriyi parse et
72
+ current = data.get("current_condition", [{}])[0]
73
+ weather_desc = current.get("weatherDesc", [{}])[0].get("value", "Bilinmiyor")
74
+ temp_c = current.get("temp_C", "N/A")
75
+ humidity = current.get("humidity", "N/A")
76
+ wind_speed = current.get("windspeedKmph", "N/A")
77
+
78
+ return {
79
+ "city": city,
80
+ "temperature": f"{temp_c}°C",
81
+ "description": weather_desc,
82
+ "humidity": f"{humidity}%",
83
+ "wind_speed": f"{wind_speed} km/h",
84
+ "status": "success"
85
+ }
86
+
87
+ except Exception as e:
88
+ logger.error(f"Weather API error: {str(e)}")
89
+ return {
90
+ "error": str(e),
91
+ "status": "error"
92
+ }
93
+
94
+ def extract_city(self, query: str) -> str:
95
+ """Sorgudan şehir adını çıkarır"""
96
+ # Türk şehirleri
97
+ turkish_cities = [
98
+ "istanbul", "ankara", "izmir", "bursa", "antalya", "adana",
99
+ "konya", "gaziantep", "mersin", "diyarbakır", "kayseri", "eskişehir"
100
+ ]
101
+
102
+ query_lower = query.lower()
103
+
104
+ # Şehir adı geçiyorsa onu al
105
+ for city in turkish_cities:
106
+ if city in query_lower:
107
+ return city.title()
108
+
109
+ # Şehir belirtilmemişse İstanbul default
110
+ return "Istanbul"
111
+
112
+ async def process_weather_query(self, query: str) -> str:
113
+ """Hava durumu sorgusunu işler ve yanıt oluşturur"""
114
+ try:
115
+ # Şehri tespit et
116
+ city = self.extract_city(query)
117
+
118
+ # Hava durumu bilgisini al
119
+ weather_data = await self.get_weather(city)
120
+
121
+ if weather_data.get("status") == "success":
122
+ return f"""🌤️ **{city} Hava Durumu:**
123
+
124
+ 🌡️ **Sıcaklık:** {weather_data['temperature']}
125
+ ☁️ **Durum:** {weather_data['description']}
126
+ 💧 **Nem:** {weather_data['humidity']}
127
+ 💨 **Rüzgar:** {weather_data['wind_speed']}
128
+
129
+ *Güncel bilgi - API üzerinden alındı*"""
130
+ else:
131
+ return f"❌ Hava durumu bilgisi alınamadı: {weather_data.get('error', 'Bilinmeyen hata')}"
132
+
133
+ except Exception as e:
134
+ logger.error(f"Weather query processing error: {str(e)}")
135
+ return f"❌ Hava durumu servisi şu anda kullanılamıyor: {str(e)}"
training/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+
training/fine_tune.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Fine-tune CRANE AI modelleri (LoRA/QLoRA).
2
+
3
+ Kullanım:
4
+ python training/fine_tune.py --module code_module --data data/code_train.jsonl --output adapters/code_module
5
+
6
+ Varsayılan hiper-parametreler configte yer alır; CLI arg'ları ile override edilebilir.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import os
12
+ import json
13
+ import logging
14
+ from pathlib import Path
15
+
16
+ import torch
17
+ from datasets import load_dataset
18
+ from transformers import AutoTokenizer, AutoModelForCausalLM
19
+ from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
20
+ from trl import SFTTrainer
21
+
22
+ MODEL_MAP = {
23
+ "code_module": "deepseek-ai/deepseek-coder-1.3b-instruct",
24
+ "chat_module": "Qwen/Qwen2.5-1.5B-Instruct",
25
+ "reason_module": "microsoft/Phi-3-mini-4k-instruct",
26
+ "fast_module": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
27
+ }
28
+
29
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
30
+ log = logging.getLogger(__name__)
31
+
32
+ def parse_args():
33
+ p = argparse.ArgumentParser(description="CRANE AI Fine-Tuner")
34
+ p.add_argument("--module", choices=list(MODEL_MAP.keys()))
35
+ p.add_argument("--data", required=True, help="JSONL veya HuggingFace dataset yolu")
36
+ p.add_argument("--output", default="adapters", help="Çıktı klasörü (LoRA adaptörü)")
37
+ p.add_argument("--epochs", type=int, default=3)
38
+ p.add_argument("--lr", type=float, default=2e-4)
39
+ p.add_argument("--batch", type=int, default=16)
40
+ p.add_argument("--r", type=int, default=16)
41
+ p.add_argument("--alpha", type=int, default=32)
42
+ p.add_argument("--bits4", action="store_true", help="QLoRA (4-bit) kullan")
43
+ return p.parse_args()
44
+
45
+ def main():
46
+ args = parse_args()
47
+
48
+ model_id = MODEL_MAP[args.module]
49
+ log.info(f"Model: {model_id}")
50
+
51
+ # Dataset
52
+ if os.path.isfile(args.data):
53
+ ds = load_dataset("json", data_files=args.data)["train"]
54
+ else:
55
+ ds = load_dataset(args.data)["train"]
56
+
57
+ tok = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
58
+ tok.pad_token = tok.eos_token if tok.pad_token is None else tok.pad_token
59
+
60
+ if args.bits4:
61
+ model = AutoModelForCausalLM.from_pretrained(model_id, load_in_4bit=True, device_map="auto")
62
+ model = prepare_model_for_kbit_training(model)
63
+ else:
64
+ model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16, device_map="auto")
65
+
66
+ peft_cfg = LoraConfig(
67
+ r=args.r,
68
+ lora_alpha=args.alpha,
69
+ lora_dropout=0.05,
70
+ target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
71
+ bias="none",
72
+ task_type="CAUSAL_LM",
73
+ )
74
+ model = get_peft_model(model, peft_cfg)
75
+
76
+ trainer = SFTTrainer(
77
+ model=model,
78
+ tokenizer=tok,
79
+ train_dataset=ds,
80
+ max_seq_length=4096,
81
+ gradient_accumulation_steps=max(1, 32 // args.batch),
82
+ learning_rate=args.lr,
83
+ num_train_epochs=args.epochs,
84
+ per_device_train_batch_size=args.batch,
85
+ )
86
+
87
+ trainer.train()
88
+
89
+ out_dir = Path(args.output) / args.module
90
+ out_dir.mkdir(parents=True, exist_ok=True)
91
+ model.save_pretrained(out_dir)
92
+ tok.save_pretrained(out_dir)
93
+ log.info(f"LoRA adaptörü kaydedildi → {out_dir}")
94
+
95
+ if __name__ == "__main__":
96
+ main()