Spaces:
Running
Running
| import os | |
| from fastapi import FastAPI, HTTPException, Header | |
| from pydantic import BaseModel | |
| from huggingface_hub import hf_hub_download | |
| from llama_cpp import Llama | |
| # --- Авторизация --- | |
| # Свой ключ для код-модели; если не задан — берём общий GINI_API_KEY | |
| API_KEY = os.environ.get("GINI_CODE_API_KEY") or os.environ.get("GINI_API_KEY", "") | |
| # --- Модель: Qwen2.5-Coder (специализирована на коде) --- | |
| # Вариант по умолчанию — 7B (умнее). Для скорости см. блок ниже. | |
| REPO_ID = "bartowski/Qwen2.5-Coder-7B-Instruct-GGUF" | |
| FILENAME = "Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf" | |
| # Быстрее, но проще — раскомментируй эти две строки и закомментируй две сверху: | |
| # REPO_ID = "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF" | |
| # FILENAME = "Qwen2.5-Coder-3B-Instruct-Q4_K_M.gguf" | |
| SYSTEM_PROMPT = ( | |
| "Ты — Gini-Coder, помощник-программист. " | |
| "Отвечай кратко и по делу, выдавай рабочий код. " | |
| "Оборачивай код в markdown-блоки с указанием языка. " | |
| "Пояснения добавляй только там, где они реально нужны." | |
| ) | |
| MODEL_PATH = hf_hub_download(repo_id=REPO_ID, filename=FILENAME) | |
| llm = Llama( | |
| model_path=MODEL_PATH, | |
| n_ctx=4096, # больше контекста под длинный код | |
| n_threads=int(os.environ.get("N_THREADS", "2")), | |
| verbose=False, | |
| ) | |
| app = FastAPI() | |
| class GenerateRequest(BaseModel): | |
| prompt: str | |
| max_new_tokens: int = 512 # код обычно длиннее обычного ответа | |
| def ping(): | |
| return {"status": "ok"} | |
| def generate(req: GenerateRequest, authorization: str = Header(default="")): | |
| token = authorization.removeprefix("Bearer ").strip() | |
| if not API_KEY or token != API_KEY: | |
| raise HTTPException(status_code=401, detail="Unauthorized") | |
| out = llm.create_chat_completion( | |
| messages=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": req.prompt}, | |
| ], | |
| max_tokens=req.max_new_tokens, | |
| temperature=0.2, # низкая — код должен быть точным, не «фантазийным» | |
| top_p=0.9, | |
| repeat_penalty=1.05, | |
| ) | |
| answer = out["choices"][0]["message"]["content"].strip() | |
| return {"response": answer} |