Spaces:
Sleeping
Sleeping
| import os | |
| import logging | |
| import time | |
| import threading | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| import requests | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| def heartbeat(): | |
| while True: | |
| try: | |
| requests.get("http://127.0.0.1:11434/api/tags", timeout=5) | |
| except: | |
| pass | |
| time.sleep(10) | |
| threading.Thread(target=heartbeat, daemon=True).start() | |
| app = FastAPI() | |
| OLLAMA_URL = os.getenv("OLLAMA_HOST", "http://localhost:11434") | |
| queue_lock = threading.Lock() | |
| active = 0 | |
| MAX = 2 | |
| class ChatRequest(BaseModel): | |
| model: str = "hf.co/mradermacher/gemma-3-4b-persian-v0-abliterated-GGUF:Q4_K_M" | |
| messages: list | |
| temperature: float = 0.7 | |
| stream: bool = False | |
| options: dict = {} | |
| # ═══ کلمات کلیدی گسترده برای تشخیص کد ═══ | |
| CODE_KEYWORDS = [ | |
| # ─── برنامهنویسی عمومی ─── | |
| "کد", "code", "کدنویسی", "برنامهنویسی", "برنامه نویسی", "programming", | |
| "سورس", "source", "اسکریپت", "script", "اسکریپتینگ", | |
| "فانکشن", "function", "تابع", "متد", "method", "کلاس", "class", | |
| "آبجکت", "object", "اینترفیس", "interface", "ماژول", "module", | |
| "پکیج", "package", "لایبرری", "library", "فریمورک", "framework", | |
| # ─── زبانهای برنامهنویسی ─── | |
| "python", "پایتون", "جاوااسکریپت", "javascript", "js", "تایپاسکریپت", "typescript", "ts", | |
| "جاوا", "java", "سیشارپ", "csharp", "c#", "سیپلاسپلاس", "cpp", "c++", "سی", "c", | |
| "گو", "go", "روبی", "ruby", "پیاچپی", "php", "لاراول", "laravel", | |
| "سوئیفت", "swift", "کاتلین", "kotlin", "rust", "راست", | |
| "اسکالا", "scala", "پرل", "perl", "lua", "لوآ", | |
| "آر", "r", "متلب", "matlab", "فرترن", "fortran", | |
| "کوبول", "cobol", "پاسکال", "pascal", "دلفی", "delphi", | |
| "اشمی", "bash", "شل", "shell", "پاورشل", "powershell", | |
| "اچتیامال", "html", "سیاساس", "css", "اسکیوال", "sql", | |
| "اچتیامال", "xml", "جیسون", "json", "یمل", "yaml", | |
| "مارکداون", "markdown", "لتکس", "latex", "رجکس", "regex", "ریجکس", | |
| # ─── دیتابیس ─── | |
| "دیتابیس", "database", "دیتا بیس", "بانک اطلاعاتی", | |
| "mysql", "ماریا", "mariadb", "پستگرس", "postgresql", "پستگرسکیوال", | |
| "مونگو", "mongodb", "ردیس", "redis", "کاساندرا", "cassandra", | |
| "الاستیک", "elasticsearch", "داینامو", "dynamodb", "فایربیس", "firebase", | |
| "اسکیوالایت", "sqlite", "اوراکل", "oracle", "مایکروسافت اسکیوال", "mssql", | |
| "جدول", "table", "کوئری", "query", "کوری", "سلکت", "select", "اینزرت", "insert", | |
| "آپدیت", "update", "دیلیت", "delete", "جوین", "join", "ایندکس", "index", | |
| # ─── شبکه و امنیت ─── | |
| "اسکن", "scan", "پورت", "port", "اسکن پورت", "port scan", "پورت اسکن", | |
| "نفوذ", "penetration", "تست نفوذ", "pentest", "هایکینگ", "hacking", | |
| "کالی", "kali", "متاسپلویت", "metasploit", "بورپ", "burp", | |
| "انمپ", "nmap", "مپ", "map", "زمپ", "zmap", "ماسکِن", "masscan", | |
| "نیسوس", "nessus", "اوپنوس", "openvas", "نکستوس", "nexpose", | |
| "وایرشارک", "wireshark", "tcpdump", "تنکپ", "tshark", | |
| "پروکسی", "proxy", "vpn", "ویپیان", "تور", "tor", | |
| "فایروال", "firewall", "iptables", "یوف dubois", "ufw", | |
| "دیاناس", "dns", "dhcp", "دیاچسیپی", "آیپی", "ip", "آدرس آیپی", | |
| "مک", "mac", "آدرس مک", "روتر", "router", "سوئیچ", "switch", | |
| "لود بالانسر", "load balancer", "سیدیان", "cdn", | |
| "اساساچ", "ssh", "تلنت", "telnet", "افتیپی", "ftp", "اسافتیپی", "sftp", | |
| "اسامتیپی", "smtp", "پاپ۳", "pop3", "آیامایپی", "imap", | |
| "http", "https", "اساسال", "ssl", "تیالاس", "tls", "سرتیفیکیت", | |
| "دومین", "domain", "سابدامین", "subdomain", "هاست", "host", | |
| "پینگ", "ping", "تریسروت", "traceroute", "nslookup", "دیگ", "dig", | |
| "netcat", "انسی", "nc", "socat", "سوکت", "socket", | |
| # ─── وب و API ─── | |
| "api", "ایپیآی", "رست", "rest", "گرافکیوال", "graphql", "grpc", | |
| "soap", "وبسرویس", "webservice", "میکروسرویس", "microservice", | |
| "کرال", "crawl", "اسکرپ", "scrape", "وباسکرپینگ", "web scraping", | |
| "سلنیوم", "selenium", "پلیرایت", "playwright", "پاپتیر", "puppeteer", | |
| "بیوتیفولسoup", "beautifulsoup", "اسکرپی", "scrapy", | |
| "فستapi", "fastapi", "فلسک", "flask", "جانگو", "django", "تورنادو", "tornado", | |
| "اکسپرس", "express", "نست", "nest", "نکست", "next", "نکستجیاس", "nextjs", | |
| "ریکت", "react", "ویو", "vue", "انگولار", "angular", "اسویالت", "svelte", | |
| "بوتاسترپ", "bootstrap", "تیلویند", "tailwind", "متریال", "material", | |
| # ─── سیستمعامل و داکر ─── | |
| "لینوکس", "linux", "اوبونتو", "ubuntu", "دبیان", "debian", "سنتاواس", "centos", | |
| "ردهت", "redhat", "فدورا", "fedora", "آرچ", "arch", "مانجارو", "manjaro", | |
| "ویندوز", "windows", "مک", "mac", "مکاواس", "macos", | |
| "داکر", "docker", "کانتینر", "container", "کوبرنتیز", "kubernetes", "k8s", | |
| "هلم", "helm", "jenkins", "جنکینز", "ci/cd", "سیآی/سیدی", | |
| "ansible", "انسیبل", "ترافورم", "terraform", "پاکر", "packer", | |
| "وگرانت", "vagrant", "پروتیوس", "prometheus", "گرافانا", "grafana", | |
| # ─── گیت و ورژن کنترل ─── | |
| "گیت", "git", "گیتهاب", "github", "گیتلب", "gitlab", "بیتباکت", "bitbucket", | |
| "کامیت", "commit", "پوش", "push", "پول", "pull", "مرج", "merge", "برنچ", "branch", | |
| "تگ", "tag", "ریبیس", "rebase", "چریپیک", "cherry-pick", "استش", "stash", | |
| "کلون", "clone", "فورک", "fork", "پولریکوئست", "pull request", "pr", | |
| # ─── کلود و سرور ─── | |
| "aws", "ایدیبلیواس", "آمازون", "azure", "آژور", "gcp", "جیسیپی", "گوگل کلود", | |
| "ec2", "اس۳", "s3", "rds", "لامبدا", "lambda", "کلودفرانت", "cloudfront", | |
| "ورسل", "vercel", "نتلیفای", "netlify", "هروکو", "heroku", | |
| "دیجیتال اوشن", "digitalocean", "لینود", "linode", "ولچر", "vultr", | |
| "انجیناکس", "nginx", "آپاچی", "apache", "تامکت", "tomcat", | |
| # ─── هوش مصنوعی و دیتا ─── | |
| "هوش مصنوعی", "ai", "ماشین لرنینگ", "machine learning", "ml", | |
| "دیپ لرنینگ", "deep learning", "شبکه عصبی", "neural network", | |
| "تنسورفلو", "tensorflow", "کراس", "keras", "پایتورچ", "pytorch", | |
| "سایکیتلرن", "scikit-learn", "پانداس", "pandas", "نمپای", "numpy", | |
| "matplotlib", "سیبورن", "seaborn", "پلاتلی", "plotly", | |
| "jupyter", "ژوپیتر", "کولب", "colab", "آناکوندا", "anaconda", | |
| "opencv", "اچپیال", "hugging face", "ترنسفورمرز", "transformers", | |
| "llm", "مدل زبانی", "chatgpt", "جیپیتی", "gpt", "bert", "الما", | |
| "پرامپت", "prompt", "پرامپت انجینرینگ", "prompt engineering", | |
| "آراَگ", "rag", "embedding", "امبدینگ", "وکتور", "vector", | |
| # ─── الگوریتم و ساختمان داده ─── | |
| "الگوریتم", "algorithm", "ساختمان داده", "data structure", | |
| "لیست", "list", "آرایه", "array", "دیکشنری", "dictionary", "dict", "هشمپ", "hashmap", | |
| "تاپل", "tuple", "ست", "set", "استک", "stack", "کیو", "queue", "دک", "deque", | |
| "لیست پیوندی", "linked list", "درخت", "tree", "باینری", "binary", | |
| "گراف", "graph", "هیپ", "heap", "تری", "trie", "بلوم فیلتر", "bloom filter", | |
| "سورت", "sort", "مرتبسازی", "سرچ", "search", "جستجو", | |
| "بینری سرچ", "binary search", "دیافاس", "dfs", "بیافاس", "bfs", | |
| "دایناسیک", "dynamic programming", "dp", "گرِدی", "greedy", | |
| "بکترکینگ", "backtracking", "دیواید اند کانکر", "divide and conquer", | |
| "ریکرژن", "recursion", "تکرار", "iteration", "مموایزیشن", "memoization", | |
| # ─── تست و دیباگ ─── | |
| "تست", "test", "یونیت تست", "unit test", "اینتگرشن تست", "integration test", | |
| "e2e", "اند تو اند", "تست خودکار", "automation test", | |
| "دیباگ", "debug", "دیباگر", "debugger", "لاگ", "log", "لاگینگ", "logging", | |
| "پروفایلینگ", "profiling", "بهینهسازی", "optimization", "پرفورمنس", "performance", | |
| "ریفکتور", "refactor", "کلین کد", "clean code", "دیزاین پترن", "design pattern", | |
| "سالید", "solid", "dry", "kiss", "yagni", | |
| # ─── موبایل ─── | |
| "اندروید", "android", "آیاواس", "ios", "فلاتر", "flutter", "دارت", "dart", | |
| "ریکت نیتیو", "react native", "کوردوا", "cordova", "آیونیک", "ionic", | |
| "سوئیفت", "swift", "کاتلین", "kotlin", "جتپک کامپوز", "jetpack compose", | |
| # ─── بلاکچین ─── | |
| "بلاکچین", "blockchain", "بیتکوین", "bitcoin", "اتریوم", "ethereum", | |
| "قرارداد هوشمند", "smart contract", "سولیدیتی", "solidity", | |
| "وب۳", "web3", "دیفای", "defi", "انافتی", "nft", | |
| "ماینینگ", "mining", "استیکینگ", "staking", "ولت", "wallet", | |
| # ─── سختافزار و IoT ─── | |
| "آردوینو", "arduino", "رسپبری", "raspberry", "اسپ۳۲", "esp32", | |
| "اینترنت اشیاء", "iot", "سنسور", "sensor", "میکروکنترلر", "microcontroller", | |
| "gpio", "جیپیآیاو", "pwm", "آی۲سی", "i2c", "اسپیآی", "spi", "یوارت", "uart", | |
| # ─── فرمتها و ابزارها ─── | |
| "csv", "اکسل", "excel", "pdf", "ورد", "word", "json", "xml", "yaml", | |
| "docker-compose", "dockerfile", "makefile", "cmake", "gradle", "maven", | |
| "npm", "ینپیام", "pip", "کندا", "conda", "venv", "virtualenv", | |
| "requirements", "package.json", "cargo", "composer", | |
| # ─── کلمات فارسی مرتبط ─── | |
| "بنویس", "بساز", "بده", "نمایش بده", "چاپ کن", "اجرا کن", "run", | |
| "نمونه", "مثال", "example", "sample", "تمپلیت", "template", "boilerplate", | |
| "چطوری", "چگونه", "how to", "آموزش", "tutorial", "راهنما", "guide", | |
| "مشکل", "خطا", "error", "باگ", "bug", "issue", "ایشو", | |
| "راهحل", "solution", "fix", "فیکس", "پچ", "patch", | |
| ] | |
| def is_code_request(messages: list) -> bool: | |
| """تشخیص درخواست کد از پیام آخر کاربر""" | |
| if not messages: | |
| return False | |
| text = messages[-1].get("content", "").lower() | |
| return any(k in text for k in CODE_KEYWORDS) | |
| def root(): | |
| return {"ok": True, "queue": {"active": active, "max": MAX}} | |
| def tags(): | |
| try: | |
| return requests.get(f"{OLLAMA_URL}/api/tags", timeout=10).json() | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def health(): | |
| try: | |
| r = requests.get(f"{OLLAMA_URL}/api/tags", timeout=5) | |
| return {"ok": r.status_code == 200} | |
| except: | |
| return {"ok": False} | |
| def wait_turn(timeout=60): | |
| global active | |
| start = time.time() | |
| while True: | |
| with queue_lock: | |
| if active < MAX: | |
| active += 1 | |
| return | |
| if time.time() - start > timeout: | |
| raise HTTPException(status_code=503, detail="سرور شلوغه. دوباره تلاش کنید") | |
| time.sleep(0.5) | |
| def release(): | |
| global active | |
| with queue_lock: | |
| active = max(0, active - 1) | |
| def chat(req: ChatRequest): | |
| wait_turn() | |
| start = time.time() | |
| try: | |
| body = req.dict() | |
| body["keep_alive"] = -1 | |
| if "options" not in body or not body["options"]: | |
| body["options"] = {} | |
| # ═══ تشخیص خودکار حالت ═══ | |
| code_mode = is_code_request(body.get("messages", [])) | |
| # حالت چت — کوتاه و سریع | |
| body["options"]["num_predict"] = 400 | |
| body["options"]["num_ctx"] = 2048 # context کمتر | |
| body["options"]["num_thread"] = 2 | |
| timeout = 75 # ۱ دقیقه | |
| logger.info("Mode: CHAT (fast response)") | |
| logger.info(f"Chat: model={body['model']}, predict={body['options']['num_predict']}, ctx={body['options']['num_ctx']}") | |
| r = requests.post( | |
| f"{OLLAMA_URL}/api/chat", | |
| json=body, | |
| timeout=timeout | |
| ) | |
| elapsed = time.time() - start | |
| logger.info(f"Done in {elapsed:.1f}s (mode={'CODE' if code_mode else 'CHAT'})") | |
| return r.json() | |
| except requests.exceptions.Timeout: | |
| logger.error("Timeout!") | |
| raise HTTPException(status_code=504, detail="timeout") | |
| except Exception as e: | |
| logger.error(f"Error: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| finally: | |
| release() | |
| async def startup(): | |
| logger.info("Proxy started with auto mode detection") | |
| async def shutdown(): | |
| logger.info("Proxy stopped") |