fp
fp
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
if not exist ".venv\Scripts\pythonw.exe" (
|
||||||
|
echo [INFO] Sanal ortam bulunamadi. Ilk kurulum baslatiliyor...
|
||||||
|
call "%~dp0kurulum.bat"
|
||||||
|
if not %errorlevel%==0 (
|
||||||
|
echo [HATA] Kurulum basarisiz. Program baslatilamadi.
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
call ".venv\Scripts\activate.bat"
|
||||||
|
start "AI Asistan" /B ".venv\Scripts\pythonw.exe" "%~dp0main.pyw"
|
||||||
|
exit /b 0
|
||||||
Binary file not shown.
+63
@@ -0,0 +1,63 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
echo [1/4] Python kontrol ediliyor...
|
||||||
|
set "PY_CMD="
|
||||||
|
|
||||||
|
where python >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
python -c "import sys; raise SystemExit(0 if sys.version_info.major==3 else 1)" >nul 2>nul
|
||||||
|
if %errorlevel%==0 set "PY_CMD=python"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not defined PY_CMD (
|
||||||
|
where py >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
py -3.13 -c "import sys" >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
set "PY_CMD=py -3.13"
|
||||||
|
) else (
|
||||||
|
py -3 -c "import sys" >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
set "PY_CMD=py -3"
|
||||||
|
) else (
|
||||||
|
py -c "import sys" >nul 2>nul
|
||||||
|
if %errorlevel%==0 set "PY_CMD=py"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not defined PY_CMD (
|
||||||
|
echo [HATA] Uygun Python 3 bulunamadi.
|
||||||
|
echo [HATA] Python 3.13 kurup tekrar deneyin: https://www.python.org/downloads/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [2/4] Sanal ortam olusturuluyor...
|
||||||
|
if not exist ".venv\Scripts\python.exe" (
|
||||||
|
%PY_CMD% -m venv .venv
|
||||||
|
if not %errorlevel%==0 (
|
||||||
|
echo [HATA] .venv olusturulamadi.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [3/4] pip guncelleniyor...
|
||||||
|
call ".venv\Scripts\activate.bat"
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
if not %errorlevel%==0 (
|
||||||
|
echo [HATA] pip guncellenemedi.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [4/4] Paketler kuruluyor...
|
||||||
|
pip install -r requirements.txt
|
||||||
|
if not %errorlevel%==0 (
|
||||||
|
echo [HATA] Paket kurulumu basarisiz.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [OK] Kurulum tamamlandi.
|
||||||
|
exit /b 0
|
||||||
@@ -0,0 +1,368 @@
|
|||||||
|
import pyperclip
|
||||||
|
from pynput import keyboard
|
||||||
|
import pyautogui
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import requests
|
||||||
|
import queue
|
||||||
|
|
||||||
|
|
||||||
|
# --- AYARLAR ---
|
||||||
|
OLLAMA_URL = "http://localhost:11434/api/generate"
|
||||||
|
MODEL_ADI = "gemini-3-flash-preview:latest" # Ana model (F8)
|
||||||
|
TEXT_MODEL_CANDIDATES = [
|
||||||
|
MODEL_ADI,
|
||||||
|
"gemini-3-flash-preview:cloud",
|
||||||
|
]
|
||||||
|
|
||||||
|
KISAYOL_METIN = keyboard.Key.f8 # Metin secimi icin kisayol
|
||||||
|
|
||||||
|
|
||||||
|
# Global değişkenler
|
||||||
|
root = None
|
||||||
|
gui_queue = queue.Queue()
|
||||||
|
kisayol_basildi = False
|
||||||
|
|
||||||
|
|
||||||
|
# --- MENÜ SEÇENEKLERİ VE PROMPT'LAR ---
|
||||||
|
ISLEMLER = {
|
||||||
|
"📝 Gramer Düzelt": "Bu metni Türkçe yazım ve dil bilgisi kurallarına göre düzelt, resmi ve akıcı olsun. Sadece sonucu ver.",
|
||||||
|
"🇬🇧 İngilizceye Çevir": "Bu metni İngilizceye çevir. Sadece çeviriyi ver.",
|
||||||
|
"🇹🇷 Türkçeye Çevir": "Bu metni Türkçeye çevir. Sadece çeviriyi ver.",
|
||||||
|
"📑 Özetle (Madde Madde)": "Bu metni analiz et ve en önemli noktaları madde madde özetle.",
|
||||||
|
"💼 Daha Resmi Yap": "Bu metni kurumsal bir e-posta diline çevir, çok resmi olsun.",
|
||||||
|
"🐍 Python Koduna Çevir": "Bu metindeki isteği yerine getiren bir Python kodu yaz. Sadece kodu ver.",
|
||||||
|
"📧 Cevap Yaz (Mail)": "Bu gelen bir e-posta, buna kibar ve profesyonel bir cevap metni taslağı yaz.",
|
||||||
|
"🎮 PS5 Oyun Skor + Acımasız Yorum": (
|
||||||
|
"Seçili metni bir PS5 oyunu adı olarak ele al. Aşağıdaki formatta Türkçe cevap ver:\n"
|
||||||
|
"1) Oyun: <ad>\n"
|
||||||
|
"2) Topluluk Beğeni Skorları:\n"
|
||||||
|
"- Metacritic User Score: <değer veya 'bilgi yok'>\n"
|
||||||
|
"- OpenCritic / benzer eleştirmen ortalaması: <değer veya 'bilgi yok'>\n"
|
||||||
|
"- Oyuncu yorumu ortalaması (PS Store vb.): <değer veya 'bilgi yok'>\n"
|
||||||
|
"3) Hüküm: sadece 'IYI' veya 'KOTU'\n"
|
||||||
|
"4) Acımasız Yorum: 2-4 cümle, net ve sert.\n"
|
||||||
|
"Kurallar: Kesin bilmediğin puanı uydurma, onun yerine 'bilgi yok' yaz. "
|
||||||
|
"Yorumu skorlarla tutarlı kur."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_available_text_model():
|
||||||
|
"""Metin işlemede kullanılabilir modeli seçer."""
|
||||||
|
preferred_models = []
|
||||||
|
for model in TEXT_MODEL_CANDIDATES:
|
||||||
|
if model and model not in preferred_models:
|
||||||
|
preferred_models.append(model)
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get("http://localhost:11434/api/tags", timeout=5)
|
||||||
|
if response.status_code != 200:
|
||||||
|
return MODEL_ADI
|
||||||
|
|
||||||
|
models = response.json().get("models", [])
|
||||||
|
installed_lower = {m.get("name", "").lower(): m.get("name", "") for m in models}
|
||||||
|
|
||||||
|
for candidate in preferred_models:
|
||||||
|
candidate_lower = candidate.lower()
|
||||||
|
if candidate_lower in installed_lower:
|
||||||
|
return installed_lower[candidate_lower]
|
||||||
|
|
||||||
|
candidate_base = candidate_lower.split(":")[0]
|
||||||
|
for installed_name_lower, installed_name in installed_lower.items():
|
||||||
|
if installed_name_lower.startswith(candidate_base + ":"):
|
||||||
|
return installed_name
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return MODEL_ADI
|
||||||
|
|
||||||
|
|
||||||
|
def ollama_cevap_al(prompt):
|
||||||
|
"""Ollama API'den cevap al."""
|
||||||
|
try:
|
||||||
|
aktif_model = get_available_text_model()
|
||||||
|
payload = {
|
||||||
|
"model": aktif_model,
|
||||||
|
"prompt": prompt,
|
||||||
|
"stream": False,
|
||||||
|
"options": {
|
||||||
|
"temperature": 0.7,
|
||||||
|
"top_p": 0.9,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(OLLAMA_URL, json=payload, timeout=60)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
result = response.json()
|
||||||
|
return result.get("response", "").strip()
|
||||||
|
|
||||||
|
err_msg = (
|
||||||
|
f"Ollama API Hatası: {response.status_code}\n"
|
||||||
|
f"Model: {aktif_model}\n"
|
||||||
|
f"Cevap: {response.text}"
|
||||||
|
)
|
||||||
|
print(f"❌ {err_msg}")
|
||||||
|
gui_queue.put((messagebox.showerror, ("API Hatası", err_msg)))
|
||||||
|
return None
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
err_msg = (
|
||||||
|
"Ollama'ya bağlanılamadı.\n"
|
||||||
|
"Programın çalıştığından emin olun!\n"
|
||||||
|
"(http://localhost:11434)"
|
||||||
|
)
|
||||||
|
print(f"❌ {err_msg}")
|
||||||
|
gui_queue.put((messagebox.showerror, ("Bağlantı Hatası", err_msg)))
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
err_msg = f"Beklenmeyen Hata: {e}"
|
||||||
|
print(f"❌ {err_msg}")
|
||||||
|
gui_queue.put((messagebox.showerror, ("Hata", err_msg)))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def strip_code_fence(text):
|
||||||
|
if not text:
|
||||||
|
return text
|
||||||
|
cleaned = text.strip()
|
||||||
|
if cleaned.startswith("```"):
|
||||||
|
lines = cleaned.splitlines()
|
||||||
|
lines = lines[1:] if lines else []
|
||||||
|
while lines and lines[-1].strip() == "```":
|
||||||
|
lines = lines[:-1]
|
||||||
|
cleaned = "\n".join(lines).strip()
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
|
||||||
|
def secili_metni_kopyala(max_deneme=4):
|
||||||
|
sentinel = f"__AI_ASISTAN__{time.time_ns()}__"
|
||||||
|
try:
|
||||||
|
pyperclip.copy(sentinel)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for _ in range(max_deneme):
|
||||||
|
pyautogui.hotkey("ctrl", "c")
|
||||||
|
time.sleep(0.2)
|
||||||
|
metin = pyperclip.paste()
|
||||||
|
if metin and metin.strip() and metin != sentinel:
|
||||||
|
return metin
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def pencere_modunda_gosterilsin_mi(komut_adi):
|
||||||
|
return "PS5 Oyun Skor" in komut_adi
|
||||||
|
|
||||||
|
|
||||||
|
def sonuc_penceresi_goster(baslik, icerik):
|
||||||
|
pencere = tk.Toplevel(root)
|
||||||
|
pencere.title(baslik)
|
||||||
|
pencere.geometry("780x520")
|
||||||
|
pencere.minsize(520, 320)
|
||||||
|
pencere.attributes("-topmost", True)
|
||||||
|
|
||||||
|
frame = tk.Frame(pencere, bg="#1f1f1f")
|
||||||
|
frame.pack(fill="both", expand=True, padx=10, pady=10)
|
||||||
|
|
||||||
|
text_alani = tk.Text(
|
||||||
|
frame,
|
||||||
|
wrap="word",
|
||||||
|
bg="#2b2b2b",
|
||||||
|
fg="white",
|
||||||
|
insertbackground="white",
|
||||||
|
font=("Segoe UI", 10),
|
||||||
|
padx=10,
|
||||||
|
pady=10,
|
||||||
|
)
|
||||||
|
kaydirma = tk.Scrollbar(frame, command=text_alani.yview)
|
||||||
|
text_alani.configure(yscrollcommand=kaydirma.set)
|
||||||
|
|
||||||
|
text_alani.pack(side="left", fill="both", expand=True)
|
||||||
|
kaydirma.pack(side="right", fill="y")
|
||||||
|
|
||||||
|
text_alani.insert("1.0", icerik)
|
||||||
|
text_alani.config(state="disabled")
|
||||||
|
|
||||||
|
alt_frame = tk.Frame(pencere, bg="#1f1f1f")
|
||||||
|
alt_frame.pack(fill="x", padx=10, pady=(0, 10))
|
||||||
|
|
||||||
|
def panoya_kopyala():
|
||||||
|
pyperclip.copy(icerik)
|
||||||
|
|
||||||
|
tk.Button(
|
||||||
|
alt_frame,
|
||||||
|
text="Panoya Kopyala",
|
||||||
|
command=panoya_kopyala,
|
||||||
|
bg="#3d3d3d",
|
||||||
|
fg="white",
|
||||||
|
activebackground="#4d4d4d",
|
||||||
|
activeforeground="white",
|
||||||
|
relief="flat",
|
||||||
|
padx=12,
|
||||||
|
pady=6,
|
||||||
|
).pack(side="left")
|
||||||
|
|
||||||
|
tk.Button(
|
||||||
|
alt_frame,
|
||||||
|
text="Kapat",
|
||||||
|
command=pencere.destroy,
|
||||||
|
bg="#3d3d3d",
|
||||||
|
fg="white",
|
||||||
|
activebackground="#4d4d4d",
|
||||||
|
activeforeground="white",
|
||||||
|
relief="flat",
|
||||||
|
padx=12,
|
||||||
|
pady=6,
|
||||||
|
).pack(side="right")
|
||||||
|
|
||||||
|
pencere.focus_force()
|
||||||
|
pencere.lift()
|
||||||
|
|
||||||
|
|
||||||
|
def islemi_yap(komut_adi, secili_metin):
|
||||||
|
prompt_emri = ISLEMLER[komut_adi]
|
||||||
|
full_prompt = f"{prompt_emri}:\n\n'{secili_metin}'"
|
||||||
|
|
||||||
|
print(f"🤖 İşlem: {komut_adi}")
|
||||||
|
print("⏳ Ollama ile işleniyor...")
|
||||||
|
|
||||||
|
sonuc = ollama_cevap_al(full_prompt)
|
||||||
|
if not sonuc:
|
||||||
|
print("❌ Sonuç alınamadı.")
|
||||||
|
return
|
||||||
|
|
||||||
|
sonuc = strip_code_fence(sonuc)
|
||||||
|
if sonuc.startswith("'") and sonuc.endswith("'"):
|
||||||
|
sonuc = sonuc[1:-1]
|
||||||
|
|
||||||
|
if pencere_modunda_gosterilsin_mi(komut_adi):
|
||||||
|
gui_queue.put((sonuc_penceresi_goster, (komut_adi, sonuc)))
|
||||||
|
print("✅ Sonuç ayrı pencerede gösterildi.")
|
||||||
|
return
|
||||||
|
|
||||||
|
time.sleep(0.2)
|
||||||
|
pyperclip.copy(sonuc)
|
||||||
|
time.sleep(0.1)
|
||||||
|
pyautogui.hotkey("ctrl", "v")
|
||||||
|
print("✅ İşlem tamamlandı!")
|
||||||
|
|
||||||
|
|
||||||
|
def process_queue():
|
||||||
|
"""Kuyruktaki GUI işlemlerini ana thread'de çalıştırır."""
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
task = gui_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
break
|
||||||
|
func, args = task
|
||||||
|
func(*args)
|
||||||
|
finally:
|
||||||
|
if root:
|
||||||
|
root.after(100, process_queue)
|
||||||
|
|
||||||
|
|
||||||
|
def menu_goster():
|
||||||
|
"""Metni kopyalar ve menüyü gösterir (ana thread)."""
|
||||||
|
secili_metin = secili_metni_kopyala()
|
||||||
|
if not secili_metin.strip():
|
||||||
|
gui_queue.put(
|
||||||
|
(
|
||||||
|
messagebox.showwarning,
|
||||||
|
(
|
||||||
|
"Secim Bulunamadi",
|
||||||
|
"Lutfen once metin secin, sonra F8 ile menuyu acin.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
menu = tk.Menu(
|
||||||
|
root,
|
||||||
|
tearoff=0,
|
||||||
|
bg="#2b2b2b",
|
||||||
|
fg="white",
|
||||||
|
activebackground="#4a4a4a",
|
||||||
|
activeforeground="white",
|
||||||
|
font=("Segoe UI", 10),
|
||||||
|
)
|
||||||
|
|
||||||
|
def komut_olustur(k_adi, s_metin):
|
||||||
|
def komut_calistir():
|
||||||
|
threading.Thread(
|
||||||
|
target=islemi_yap, args=(k_adi, s_metin), daemon=True
|
||||||
|
).start()
|
||||||
|
|
||||||
|
return komut_calistir
|
||||||
|
|
||||||
|
for baslik in ISLEMLER.keys():
|
||||||
|
menu.add_command(label=baslik, command=komut_olustur(baslik, secili_metin))
|
||||||
|
|
||||||
|
menu.add_separator()
|
||||||
|
menu.add_command(label="❌ İptal", command=lambda: None)
|
||||||
|
|
||||||
|
try:
|
||||||
|
x, y = pyautogui.position()
|
||||||
|
menu.tk_popup(x, y)
|
||||||
|
finally:
|
||||||
|
menu.grab_release()
|
||||||
|
|
||||||
|
|
||||||
|
def on_press(key):
|
||||||
|
global kisayol_basildi
|
||||||
|
try:
|
||||||
|
if key == KISAYOL_METIN and not kisayol_basildi:
|
||||||
|
kisayol_basildi = True
|
||||||
|
gui_queue.put((menu_goster, ()))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def on_release(key):
|
||||||
|
global kisayol_basildi
|
||||||
|
try:
|
||||||
|
if key == KISAYOL_METIN:
|
||||||
|
kisayol_basildi = False
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("🤖 AI Asistan - Metin İşleme")
|
||||||
|
print("=" * 60)
|
||||||
|
aktif_text_model = get_available_text_model()
|
||||||
|
print(f"📦 Metin İşleme (F8): {aktif_text_model}")
|
||||||
|
print()
|
||||||
|
print("🔧 Kullanım:")
|
||||||
|
print(" F8 - Metin sec ve AI islemleri yap")
|
||||||
|
print()
|
||||||
|
print("⚠️ Programı kapatmak için bu pencereyi kapatın veya Ctrl+C yapın.")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
test_response = requests.get("http://localhost:11434/api/tags", timeout=5)
|
||||||
|
if test_response.status_code == 200:
|
||||||
|
print("✅ Ollama bağlantısı başarılı!")
|
||||||
|
else:
|
||||||
|
print("⚠️ Ollama'ya bağlanılamadı, servisi kontrol edin!")
|
||||||
|
except Exception:
|
||||||
|
print("⚠️ Ollama çalışmıyor olabilir! 'ollama serve' ile başlatın.")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
|
||||||
|
listener.start()
|
||||||
|
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw()
|
||||||
|
root.after(100, process_queue)
|
||||||
|
|
||||||
|
try:
|
||||||
|
root.mainloop()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Kapatılıyor...")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
requests
|
||||||
|
pyperclip
|
||||||
|
pynput
|
||||||
|
pyautogui
|
||||||
|
sympy
|
||||||
|
Pillow
|
||||||
|
PyMuPDF
|
||||||
Reference in New Issue
Block a user