>>29>В моем мире локально на своем компе поднимать ллм будет только лютый гик судя по всему ты + учитывая какие методы предпочитаешь я ваще вахуе, либо чел который хочет приватных uncesored сессий.Или нищкнка. Не анон, такой план: это просто потестить. А вот в соседей комнате у женщины RTX 2060, она будет пока на работах/учебах - я там запущу. И у меня идея научить объяснять его в KiKad электронные схемы мне для учебы. Я бы мог просто учиться, но мне очень нужно не просто учиться, так как не самый высокий уровень языка буду выравнивать вот такими хитростями. На обычный ИИ агент я тоже подпишусь, Claudie умеет c KiCad работать там по одной либе, но токен мамоном станет.
А все, я вернулся к unsloath, у них API. Гоняет модель охуенно и пиздец умная для такого железа. OCR так же есть и другой вижн.
Код:
from openai import OpenAI
import telebot
import requests
import traceback
import subprocess
import time
BASE_URL = "http://localhost:8888"
API_KEY = "ВАШ_API_КЛЮЧ" # sk-unsloth-...
BOT_TOKEN = "ВАШ_ТОКЕН_БОТА" # от @BotFather
MODEL_PATH = "unsloth/Qwen3.5-4B-GGUF"
GGUF_VARIANT = "Q4_K_S"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
# ─── Утилиты ───────────────────────────────────────────────────────────────────
def check_connection():
try:
r = requests.get(f"{BASE_URL}/api/health", timeout=5)
return r.status_code == 200
except Exception:
return False
def get_status():
try:
r = requests.get(f"{BASE_URL}/api/inference/status", headers=HEADERS, timeout=5)
return r.json()
except Exception as e:
print(f"❌ Не удалось получить статус: {e}")
return None
def load_model():
print("⏳ Загружаем модель...")
try:
r = requests.post(
f"{BASE_URL}/api/inference/load",
headers=HEADERS,
json={"model_path": MODEL_PATH, "gguf_variant": GGUF_VARIANT},
timeout=300
)
if r.status_code == 200:
data = r.json()
print(f"✅ Модель загружена: {data.get('display_name', data.get('model'))}")
return True
else:
print(f"❌ Ошибка загрузки: {r.status_code} - {r.text[:300]}")
return False
except Exception as e:
print(f"❌ Исключение при загрузке модели: {e}")
return False
def start_unsloth():
print("🚀 Запускаем Unsloth...")
try:
subprocess.Popen(
["unsloth", "run", "--model", f"{MODEL_PATH}:{GGUF_VARIANT}"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
except FileNotFoundError:
print("❌ Команда 'unsloth' не найдена. Проверь PATH или укажи полный путь.")
return False
print("⏳ Ждём запуска Unsloth...")
for i in range(30):
time.sleep(2)
if check_connection():
print("✅ Unsloth запущен!")
return True
print(f" ожидание... ({(i+1)*2}с)")
print("❌ Unsloth не запустился за 60 секунд")
return False
# ─── Запуск ────────────────────────────────────────────────────────────────────
print("🔌 Проверяем соединение с Unsloth...")
if not check_connection():
print("⚠️ Unsloth не запущен, пробуем запустить...")
if not start_unsloth():
raise SystemExit()
else:
print("✅ Unsloth уже запущен")
status = get_status()
if status and status.get("active_model"):
model_name = status["active_model"]
ctx = status.get("context_length")
gguf_variant = status.get("gguf_variant", "")
print(f"✅ Модель уже загружена: {model_name} | GGUF: {gguf_variant} | Контекст: {ctx}")
else:
if not load_model():
raise SystemExit()
# ─── Бот ───────────────────────────────────────────────────────────────────────
client = OpenAI(base_url=f"{BASE_URL}/v1", api_key=API_KEY)
bot = telebot.TeleBot(BOT_TOKEN)
@bot.message_handler(func=lambda message: True)
def echo_all(message):
user_text = message.text.strip() if message.text else ""
username = message.from_user.username or message.from_user.first_name
print(f"📨 [{username}]: {user_text[:80]}")
if not user_text:
bot.reply_to(message, "⚠️ Пустое сообщение.")
print("⚠️ Пустое сообщение — пропущено")
return
bot.send_chat_action(message.chat.id, "typing")
try:
full_response = ""
last_typing = time.time()
stream = client.chat.completions.create(
model="default",
messages=[{"role": "user", "content": user_text}],
stream=True,
)
for chunk in stream:
if time.time() - last_typing > 4:
bot.send_chat_action(message.chat.id, "typing")
last_typing = time.time()
if chunk.choices and chunk.choices[0].delta.content:
full_response += chunk.choices[0].delta.content
if full_response:
print(f"🤖 Ответ [{username}]: {full_response[:80]}...")
bot.reply_to(message, full_response)
else:
print("⚠️ Модель вернула пустой ответ")
bot.reply_to(message, "⚠️ Модель не дала ответа.")
except Exception as e:
err = str(e)
print(f"❌ Ошибка: {err}")
traceback.print_exc()
if "No model loaded" in err:
bot.reply_to(message, "❌ Модель выгружена. Перезапусти бота.")
elif "401" in err:
bot.reply_to(message, "❌ Неверный API ключ.")
elif "429" in err:
pass
else:
bot.reply_to(message, f"❌ Ошибка: {err[:200]}")
print("🚀 Бот запущен!")
bot.infinity_polling()