Spaces:
Running
Running
File size: 4,633 Bytes
56d2d0f 583a271 56d2d0f 583a271 56d2d0f c8dd008 5bd5e01 ba425e2 f0fffb2 100e61f c8dd008 ba425e2 583a271 5892ed0 583a271 f0fffb2 c8dd008 f0fffb2 c8dd008 f0fffb2 56d2d0f f0fffb2 56d2d0f c8dd008 583a271 c8dd008 56d2d0f 583a271 56d2d0f f0fffb2 56d2d0f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import os
import re
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
from huggingface_hub import hf_hub_download
from llama_cpp import Llama
from tavily import TavilyClient
API_KEYS = {k.strip() for k in os.environ.get("GINI_API_KEYS", "").split(",") if k.strip()}
if os.environ.get("GINI_API_KEY"): API_KEYS.add(os.environ.get("GINI_API_KEY"))
SYSTEM_PROMPT = (
"Ты — продвинутый ИИ-ассистент по имени Gini (по-русски твое имя звучит как Джини). "
"Ты дружелюбная, невероятно умная и всегда готовая помочь собеседница. "
"Отвечай всегда на естественном, живом и грамотном русском языке. "
"\n\nВАЖНОЕ ПРАВИЛО ДЛЯ ТЕКУЩЕГО РЕЖИМА: "
"В данный момент ты выступаешь в роли Senior-эксперта, архитектора и глубокого мыслителя. "
"Обязательно используй свою встроенную систему размышления (выводи свои логические шаги внутри тегов <think>). "
"Сначала рассмотри проблему с разных сторон, проанализируй варианты, проверь себя на ошибки, а затем, после закрытия тега </think>, выдай окончательный, идеально структурированный ответ."
"Отвечай ИСКЛЮЧИТЕЛЬНО на чистом русском языке. Тебе КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО использовать китайские иероглифы или китайские слова в своих ответах."
)
TAVILY_API_KEY = "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"
tavily = TavilyClient(api_key=TAVILY_API_KEY)
def get_web_context(query: str) -> str:
query_lower = query.lower()
keywords = ["найди", "поищи", "погугли", "кто", "что", "когда", "где", "какая", "почему", "новости", "вчера", "погода", "курс"]
if any(k in query_lower for k in keywords) or query.endswith("?"):
try:
response = tavily.search(query, search_depth="basic", max_results=3)
results = response.get("results", [])
if results:
snippets = [f"- {r.get('title', '')} (Источник: {r.get('url', '')}): {r.get('content', '')}" for r in results]
return (
"ВНИМАНИЕ! Свежая информация из интернета по запросу пользователя:\n"
+ "\n".join(snippets)
+ "\n\nОпирайся строго на эти факты при ответе и ОБЯЗАТЕЛЬНО красиво укажи ссылки на источники в конце своего ответа."
)
except Exception:
pass
return ""
# Загружаем мыслящую DeepSeek-R1 (на базе 7-миллиардной Qwen)
MODEL_PATH = hf_hub_download(
repo_id="bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF",
filename="DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf",
)
llm = Llama(model_path=MODEL_PATH, n_ctx=8192, n_threads=int(os.environ.get("N_THREADS", "2")), verbose=False)
app = FastAPI()
class GenerateRequest(BaseModel):
prompt: str
max_new_tokens: int = 2000 # Выдаем огромный лимит, чтобы ей хватило места "подумать"
@app.get("/ping")
async def ping(): return {"status": "ok"}
@app.post("/generate")
async def generate(req: GenerateRequest, request: Request):
auth = request.headers.get("Authorization", "")
if auth.removeprefix("Bearer ").strip() not in API_KEYS:
raise HTTPException(status_code=401, detail="Unauthorized")
system_content = SYSTEM_PROMPT
web_context = get_web_context(req.prompt)
if web_context:
system_content += f"\n\n{web_context}"
result = llm.create_chat_completion(
messages=[
{"role": "system", "content": system_content},
{"role": "user", "content": req.prompt},
],
max_tokens=req.max_new_tokens,
temperature=0.6, # Идеальная температура для R1
top_p=0.95,
repeat_penalty=1.1,
)
return {"response": result["choices"][0]["message"]["content"].strip()} |