Rid3 commited on
Commit
0e057d9
·
verified ·
1 Parent(s): be0d60b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -70
app.py CHANGED
@@ -4,9 +4,11 @@ from fastapi import FastAPI, HTTPException
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from pydantic import BaseModel
6
  from llama_cpp import Llama
 
7
 
8
- app = FastAPI(title="My Local Brains API")
9
 
 
10
  app.add_middleware(
11
  CORSMiddleware,
12
  allow_origins=["*"],
@@ -15,106 +17,87 @@ app.add_middleware(
15
  allow_headers=["*"],
16
  )
17
 
18
- # Папка, где будут лежать ваши .gguf файлы
19
- MODELS_DIR = "./models"
20
- os.makedirs(MODELS_DIR, exist_ok=True)
21
-
22
  current_llm = None
23
- current_model_name = ""
24
 
25
- def get_local_models():
26
- """Возвращает список всех .gguf файлов в папке models"""
27
- return [f for f in os.listdir(MODELS_DIR) if f.endswith('.gguf')]
 
 
 
 
28
 
29
- def load_model(model_filename: str):
30
- global current_llm, current_model_name
 
31
 
32
- model_path = os.path.join(MODELS_DIR, model_filename)
33
 
34
- if not os.path.exists(model_path):
35
- raise HTTPException(status_code=404, detail=f"Модель {model_filename} не найдена в папке {MODELS_DIR}")
36
-
37
- if current_model_name == model_filename and current_llm is not None:
38
- return # Модель уже загружена
39
 
40
- print(f"--- Загрузка мозга: {model_filename} ---")
41
-
42
- # Освобождаем память от предыдущей модели
43
  if current_llm is not None:
44
  del current_llm
45
  gc.collect()
46
 
47
  try:
 
 
 
 
48
  current_llm = Llama(
49
  model_path=model_path,
50
- n_ctx=4096, # Размер контекста (можно увеличить до 8192, если хватает памяти)
51
  n_threads=os.cpu_count() or 4,
52
- n_gpu_layers=-1, # -1 означает выгрузку всех возможных слоев на видеокарту (GPU)
53
  verbose=False
54
  )
55
- current_model_name = model_filename
56
- print(f"✅ Мозг '{model_filename}' успешно подключен!")
57
  except Exception as e:
58
- print(f"❌ Ошибка загрузки {model_filename}: {e}")
59
- raise HTTPException(status_code=500, detail=str(e))
60
-
61
- class ChatRequest(BaseModel):
62
- prompt: str
63
- model: str = "" # Имя файла, например: "my_brain_v1.gguf". Если пусто, возьмет первую доступную.
64
- system_prompt: str = "Ты полезный, умный ИИ-ассистент."
65
- max_tokens: int = 512
66
- temperature: float = 0.7
67
-
68
- @app.get("/models")
69
- async def list_models():
70
- """Посмотреть все доступные модели"""
71
- return {
72
- "available_models": get_local_models(),
73
- "current_loaded_model": current_model_name
74
- }
75
 
76
  @app.post("/chat")
77
  async def chat(request: ChatRequest):
78
- global current_model_name
79
-
80
- # Определяем, какую модель грузить
81
- target_model = request.model
82
- if not target_model:
83
- models = get_local_models()
84
- if not models:
85
- raise HTTPException(status_code=404, detail="В папке ./models нет ни одного .gguf файла!")
86
- target_model = models[0] # Берем первую попавшуюся
87
-
88
- # Загружаем, если еще не загружена
89
- if target_model != current_model_name:
90
- load_model(target_model)
91
 
92
  try:
93
- # Универсальный шаблон промпта (System + User).
94
- # Если вы используете модели формата Llama-3 или ChatML, шаблон можно поменять.
95
- prompt = f"System: {request.system_prompt}\nUser: {request.prompt}\nAssistant:"
96
 
97
  output = current_llm.create_completion(
98
- prompt=prompt,
99
  max_tokens=request.max_tokens,
100
  temperature=request.temperature,
101
- stop=["User:", "System:", "<|endoftext|>", "<|im_end|>"]
102
  )
103
 
104
- response_text = output["choices"][0]["text"].strip()
105
  return {
106
- "response": response_text,
107
- "model_used": current_model_name
108
  }
109
-
110
  except Exception as e:
111
- print(f"Ошибка при генерации: {e}")
112
- raise HTTPException(status_code=500, detail="Ошибка генерации ответа")
113
 
114
- @app.get("/")
115
  async def health():
 
116
  return {
117
- "status": "online",
118
- "active_brain": current_model_name,
119
- "instruction": f"Положите ваши .gguf файлы в папку {os.path.abspath(MODELS_DIR)}"
120
- }
 
 
 
 
 
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from pydantic import BaseModel
6
  from llama_cpp import Llama
7
+ from huggingface_hub import hf_hub_download
8
 
9
+ app = FastAPI(title="Xtime GGUF Remote API")
10
 
11
+ # Настройка CORS для удаленного подключения
12
  app.add_middleware(
13
  CORSMiddleware,
14
  allow_origins=["*"],
 
17
  allow_headers=["*"],
18
  )
19
 
20
+ # Глобальные переменные для хранения текущей модели в памяти
 
 
 
21
  current_llm = None
22
+ current_model_id = "" # format: repo_id/filename
23
 
24
+ class ChatRequest(BaseModel):
25
+ repo_id: str # Ссылка на репозиторий апр. "bartowski/Llama-3.2-3B-Instruct-GGUF")
26
+ filename: str # Имя файла (напр. "Llama-3.2-3B-Instruct-Q4_K_M.gguf")
27
+ prompt: str # Текст пользователя
28
+ system_prompt: str = "You are a helpful assistant."
29
+ max_tokens: int = 512
30
+ temperature: float = 0.7
31
 
32
+ def load_model_if_new(repo_id: str, filename: str):
33
+ """Загружает модель, если она еще не в памяти или если пришла новая ссылка"""
34
+ global current_llm, current_model_id
35
 
36
+ new_model_id = f"{repo_id}/{filename}"
37
 
38
+ # Если модель уже загружена, просто выходим
39
+ if current_llm is not None and current_model_id == new_model_id:
40
+ return
 
 
41
 
42
+ print(f"--- Загрузка новой модели: {new_model_id} ---")
43
+
44
+ # Очистка памяти перед загрузкой новой модели
45
  if current_llm is not None:
46
  del current_llm
47
  gc.collect()
48
 
49
  try:
50
+ # Скачивание файла с Hugging Face (использует кэш, если файл уже есть)
51
+ model_path = hf_hub_download(repo_id=repo_id, filename=filename)
52
+
53
+ # Инициализация Llama
54
  current_llm = Llama(
55
  model_path=model_path,
56
+ n_ctx=2048,
57
  n_threads=os.cpu_count() or 4,
58
+ n_gpu_layers=0, # Установите > 0, если у вас есть GPU
59
  verbose=False
60
  )
61
+ current_model_id = new_model_id
62
+ print(f"✅ Модель {filename} успешно загружена и готова")
63
  except Exception as e:
64
+ print(f"❌ Ошибка при загрузке модели: {e}")
65
+ raise HTTPException(status_code=500, detail=f"Failed to load model: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  @app.post("/chat")
68
  async def chat(request: ChatRequest):
69
+ """Эндпоинт для чата, который сам переключает модели"""
70
+ # 1. Проверяем/загружаем модель
71
+ load_model_if_new(request.repo_id, request.filename)
 
 
 
 
 
 
 
 
 
 
72
 
73
  try:
74
+ # 2. Генерация ответа (базовый формат, подходящий для большинства моделей)
75
+ formatted_prompt = f"System: {request.system_prompt}\nUser: {request.prompt}\nAssistant:"
 
76
 
77
  output = current_llm.create_completion(
78
+ prompt=formatted_prompt,
79
  max_tokens=request.max_tokens,
80
  temperature=request.temperature,
81
+ stop=["User:", "System:", "</s>", "<|endoftext|>"]
82
  )
83
 
 
84
  return {
85
+ "response": output["choices"][0]["text"].strip(),
86
+ "model_id": current_model_id
87
  }
 
88
  except Exception as e:
89
+ print(f"Ошибка генерации: {e}")
90
+ raise HTTPException(status_code=500, detail="Generation error")
91
 
92
+ @app.get("/health")
93
  async def health():
94
+ """Проверка состояния сервера"""
95
  return {
96
+ "status": "online",
97
+ "current_model": current_model_id if current_model_id else "None"
98
+ }
99
+
100
+ if __name__ == "__main__":
101
+ import uvicorn
102
+ # Запуск на порту 7860 (стандарт для HF Spaces)
103
+ uvicorn.run(app, host="0.0.0.0", port=7860)