Download app.py from GoshawkVortexAI/Goshawk_LexiAI: direct link, hf CLI and curl.
- Browser
- Download file 2.83 kB
-
https://huggingface.co/spaces/GoshawkVortexAI/Goshawk_LexiAI/resolve/main/app.py
- Command line
-
hf download hf://spaces/GoshawkVortexAI/Goshawk_LexiAI/app.py
-
curl -L -o app.py https://huggingface.co/spaces/GoshawkVortexAI/Goshawk_LexiAI/resolve/main/app.py
2.83 kB
| """LexiAI – Space sunucusu (tek dosya). | |
| Ana dizindeki LoRA adapter'ını Qwen2.5-7B-Instruct üzerine yükler, | |
| index.html'i "/" adresinde yayınlar, yorumu "/comment" adresinden akıtır. | |
| Token gerekmez. GPU'lu Space gerekir (en az ~24 GB VRAM, ya da 4-bit için QUANT=4).""" | |
| import os, json, threading | |
| import torch, uvicorn | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import FileResponse, StreamingResponse, JSONResponse | |
| from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer, BitsAndBytesConfig | |
| from peft import PeftModel | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| BASE = "Qwen/Qwen2.5-7B-Instruct" | |
| SYSTEM = ("Sen Türk hukuku konusunda yardımcı bir asistansın. Bir sınıflandırıcının sonucunu ve belge metnini alırsın. " | |
| "Türkçe, en fazla 120 kelimeyle yorumla: 1) Belge ne ve sınıflandırma makul mü, " | |
| "2) Dikkat edilmesi gereken noktalar/riskler, 3) Önerilen sonraki adım. Kısa maddeler kullan. " | |
| "Kesin hukuki tavsiye verme.") | |
| tok = AutoTokenizer.from_pretrained(HERE if os.path.exists(os.path.join(HERE, "tokenizer.json")) else BASE) | |
| kw = dict(device_map="auto") | |
| if os.environ.get("QUANT") == "4": | |
| kw["quantization_config"] = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16) | |
| else: | |
| kw["torch_dtype"] = torch.bfloat16 | |
| model = AutoModelForCausalLM.from_pretrained(BASE, **kw) | |
| if os.path.exists(os.path.join(HERE, "adapter_config.json")): | |
| model = PeftModel.from_pretrained(model, HERE) | |
| model.eval() | |
| lock = threading.Lock() | |
| app = FastAPI() | |
| def home(): | |
| return FileResponse(os.path.join(HERE, "index.html")) | |
| def health(): | |
| return {"ok": True} | |
| async def comment(req: Request): | |
| try: | |
| d = await req.json() | |
| except Exception: | |
| return JSONResponse({"error": "Geçersiz istek"}, status_code=400) | |
| info = str(d.get("info", ""))[:1000] | |
| text = str(d.get("text", ""))[:3000] | |
| msgs = [{"role": "system", "content": SYSTEM}, | |
| {"role": "user", "content": info + "\n\nBelge metni:\n" + text}] | |
| ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device) | |
| streamer = TextIteratorStreamer(tok, skip_prompt=True, skip_special_tokens=True) | |
| def work(): | |
| with lock, torch.inference_mode(): | |
| model.generate(input_ids=ids, attention_mask=torch.ones_like(ids), streamer=streamer, | |
| max_new_tokens=350, do_sample=True, temperature=0.3, top_p=0.9) | |
| threading.Thread(target=work, daemon=True).start() | |
| return StreamingResponse((t for t in streamer), media_type="text/plain; charset=utf-8") | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", 7860))) | |